The rest of it is down to the fact that we’re using the language that was developed for RtCW singleplayer, which it worked fine on. I had wished to re-write it to be a more useful language for what we wished to do, but at the time this wasn’t seen as being a very time-efficient thing, as there wasn’t likely to be much scripting involved. Unfortunately, as things went on, the nature of the project changed, but we had no time to change the language, and re-writing the script might not have been fun, so we were stuck with what we had.
as for scripting
it makes my head hurt
but i want more
i think ppl hate it because they try cut and paste to learn (eeeekkkk!!! goldrush tank resurection script has just taken me a wk to get my head round)
even now that i understand scripting cut and paste usually takes longer than starting from scratch
namechanges when following somebody elses script help to understand what is calling what and when (everybody describes things diferently)
its just anoying finding that one entity in the map with the wrong values after days of wondering why the script wont work :bash:
Agree, and thats why it would be great to have a compile switch for Q3BSP that outputs a file with all the scriptnames and entitynames that is using anything related to the .script file.
Or perhaps someone good at programming could do a simple program that looks through the .bsp/.map file making the .script stuff printed to a txt file.
EDIT: Maybe I should’ve posted this on a thread by itself so it’s easier to find
Here’s a little explanation of accum implementation, and the operations supported. I’m pretty sure accum is implemented as an array though i could be wrong. Anyway it makes a lot of sense to me to treat it as an array so that’s how I’m explaining it. I use the word function to refer to a routine or target or whatever you call it. The following makes a lot of sense if you know some basic C or C++, but it should be pretty clear even if you don’t. Please those who know this stuff better, correct any mistakes.
Every function(EDIT: actually every entity, thanks SCDS_reyaIP) has an 8 integer local array called accum implicitly declared for it. When you say ‘accum 0’ or ‘accum 1’ you are simply referring to the first and second elements of the accum array for that function. Thus the accum variable “namesâ€? are simply the indexes into the accum array and that’s why they have to be integers from 0 to 7. You have 8 total elements in your accum array(shown in pic), all of which are 32 bit integers. You also have a globalaccum array which functions the same way but can be accessed and modified from any function. Here are the operations that you can do on the array elements
The (global) part is optional, depending if you’re talking about the global array or local function arrays. All examples refer to above picture.
Arithmetic operations
baccum <n> inc <m>[/b]
-Increment element n by m, or decrease by m if m is a negative number.
Example: In picture accum[4] holds the value 8. So accum 4 inc 5, adds 5 to 8 and stores the sum back in accum[4]. So now accum[4] holds the value 13.
baccum <n> set <m>[/b]
-Set the value for element n to m
Example: accum 0 set 10 would clear out the 4 and place 10 as the value for element 0
baccum <n> random <m>[/b]
-Set the value of element n to a random integer from 0 to m. I’m not sure if m is included or excluded but I assume it would be excluded (if the internal implementation is something like rand() % m). Somebody correct me.
Example: same as set but with a random integer.
Bitwise operations
baccum <n> bitset <m>[/b]
-Sets bit m of element n to 1. m can vary from 0 to 31(since we have 32 bit integers)
Example: accum 1 bitset 3. Sets the fourth bit of element 1 to 1. The new binary value would look like:000…001110 which is equal to 14. So element 1 now holds the value 14. These are usually used in conjunction with the bitwise control statements(see below) to check if a bit is 0 or 1. It basically gives you a total of 32*8 = 256 Boolean variables which can be used to check any true/false conditions. For example you could use the first bit of some element to store the state of the tank(damaged or not) and the second bit of the same element to check if the bridge is build or not and so on for any condition with only two possible states.
baccum <n> bitreset <m>[/b]
-Sets bit m of element n to 0. m can vary from 0 to 31.
Example: accum 5 bitreset 5. Sets the sixth bit of element 5 to 0. The new binary value would look like:000…001101 which is equal to 13. So element 5 now holds the value 13.
Control Statements
baccum <n> abort_if_less_than <m>
(global)accum <n> abort_if_greater_than <m>
(global)accum <n> abort_if_not_equal <m>
(global)accum <n> abort_if_equal <m>
(global)accum <n> abort_if_bitset <m>
(global)accum <n> abort_if_not_bitset <m> [/b]
-Exit current function and return(?) control to calling function if the condition is met. If the condition is false then the current functions continues execution.
Example: accum 6 abort_if_equal 10 would be a true condition and the function would exit immediately.
Example: accum 3 abort_if_bitset 0 . Checks if the first bit of the third element is 1. Since the bit is 1 the condition is met and the function exits.
baccum <n> trigger_if_equal <m> <s> <t>[/b]
-Checks if the value of element n is equal to m. If so it calls subfunction t in function s.
Example: accum 7 trigger_if_equal 2 game_manager some_fuction
First it compares the value of element 7 to 2. Since they’re equal it calls function some_function which is declared inside the game_manager function.
Other(synchronization?) baccum <n> wait_while_equal <m> [/b]. This is pure speculation since I’ve never seen this used anywhere. Somebody please correct me. I’m assuming it pauses execution of the current function until element n is NOT equal to m. Another thread has to change the value of element n to something different from m for the execution to continue(basically the equivalent of a while(accum[n ] ==m); ).
#define G_MAX_SCRIPT_ACCUM_BUFFERS 8
...
struct gentity_s {
entityState_t s; // communicated by server to clients
...
// entity scripting system
char *scriptName;
int numScriptEvents;
g_script_event_t *scriptEvents; // contains a list of actions to perform for each event type
g_script_status_t scriptStatus; // current status of scripting
// the accumulation buffer
int scriptAccumBuffer[G_MAX_SCRIPT_ACCUM_BUFFERS];
...
From RTCW, but it is reasonable to assume ET is much the same.
The important part of accum system being an array, is that the array is stored in the entity with the corresponding scriptname key. (except global, which is global, of course :P)
If you know assembler accum blah and abort_if_blah are very natural.
BTW imho accum is used in controlling and regulating techniques and stands there for the electric device accumulator. Simulating analog selfregulating closed Circles on the Comp lead them call the accumulator simply accum.
This is a very important note and one which can cause alot of problems if not understood correctly. Any pause in a function will stop all previous functions from working again. The stack will not return.
This is the best way to run several functions at once but in different routines.
Update to the LDR, a scripting section. Any feedback or contributions are welcome. If you want to add sections to this LDR then please let me know. (Any contributions will need to be re-formatted to look the same as the existing LDR, but you will have the final say if you dont like the re-format)
Ive been doing nothing but reading for 3 days. This might sound like a stupid question, but has anyone ever run across a full PDF tutorial on mapping? All I remember my good buddy Meso saying, (he was the lead guy for the RA3 Map Project), read, read, read, read!!
Of course, doing is the next half of the battle. Us mapping newbies love to get ahead of ourselves. hehe.
Thanks to everyone for all the great support so far. It’s nice to see a community like this. I’m very glad to have taken my interest to the next level.
My guess would be the fear of source code. Especially
with the lack of syntax checkers and debuggers though
the game itself does a decent job in my very recent,
very casual experience (I played with g_scriptdebug today…
it’s cool).
Of course, as a programmer of 20+ years,
I’m used to debugging code.
A lot of map makers aren’t.
I wish more map makers would use the flexibility
it provides… especially Splash Damage.
We recently had a request from our users to remove
the ammo and health racks from our (ND80’s) LMS
server.
Although this was fairly easy to do for battery, fueldump and
goldrush because SD had used the scriptname tag for each
of the racks (and the clipping planes and triggers surrounding
them), I found no easy way to do this for the other three maps.
Obviously, SD only used the scriptname on the
entities/targets/whatevers on the things they needed
to add in one mode and remove in others.
But if they had given all those things scripts in all
the maps, then I could have written:
xyz
{
spawn
{
remove
}
}
functions for all the items we didn’t want.
I don’t know if there is a performance hit for including
a scriptname. And I’m sure some map makers are adament
that their maps be run the way they were originally designed.
But if more map makers used scripting, it would give
server administrators more flexibility when running
their maps.
Some sample’s of modifications that I’ve made
(other than the above) at the risk of pissing some of the
authors of the maps (though they shouldn’t be too pissed
since I distributed them as seperate .pk3s):
Drakir’s Flughafen didn’t end until somebody won. When
he changed the name to Fliegerhorst, he made the Allies
the default winner. A lot of our players thought that ruined
the game play. So I hacked the script to set wm_setwinner
to -1 at the beginning (z_ss_fliegerhorst.pk3). We thought
he had it right the first time.
I most recently did just the same to Mizar’s remake
of Drakir’s md_bridge as well (ss_md_bridge_fix.pk3).
[Note: both these patches only run/ran on our campaign servers –
you obviously wouldn’t want to use them on stopwatch servers.]
The Stargate SG-1 Beta (a work in progress) has a front
gate that requires dyno and then can be rebuilt in one second.
That seemed ridiculous so I changed it to grenade only
(ss_SG_1945_changewall.pk3) and it is a lot more
fun.
Finally, I recently made a patch (ss_mml_helmsdeep_fp_flagfix.pk3)
for Gerbil’s Helm’s deep that I thought fixed the flag but now I’m not sure.
Gerbil actually has a question there for someone concerning my
“fix” and a bug on oasis concerning capturable/permanent spawn
points.]
Anyway… I find it very useful and wish it was used
more. It provides more more flexibility it seems than
embedding information in the .bsp.
Of course, I am no ET mapper. The truth is, I wrote an entire program to create the last map I made
rather than take the time to do it myself by hand.
[It’s actually cool to see all the tools available now that
do automatic terrain generation and what not given my
experience with bmp2map and another java application
I wrote (currently offline) that minimizes triangles on
a terrain given a grid of elevation data.]
Anyhoo, that’s my two pennies as a coder/scripter (as
opposed to a mapper)… they fear the source. I, for one,
would be happy as a coder to help a mapper out. Given
the necessary tags, playing with source can be fun and
gives the potential to expore possibilities.
In conclusion (whew, bet you’re glad that’s over) I hope
more map makers use the power and flexibility that
scripting provides, even if they themselves don’t
necessarily see the need for it (who’d a thunk
the LMS’ers would want life hard? :)).
I see your point, note taken. In order to make a item/model/brush scriptable it needs to be an entity. And we dont have too much of them to use in a map, there is a limit to how many entitys you can have in a map.