1 //********************************************************************************************
2 //*
3 //* This file is part of Egoboo.
4 //*
5 //* Egoboo is free software: you can redistribute it and/or modify it
6 //* under the terms of the GNU General Public License as published by
7 //* the Free Software Foundation, either version 3 of the License, or
8 //* (at your option) any later version.
9 //*
10 //* Egoboo is distributed in the hope that it will be useful, but
11 //* WITHOUT ANY WARRANTY; without even the implied warranty of
12 //* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 //* General Public License for more details.
14 //*
15 //* You should have received a copy of the GNU General Public License
16 //* along with Egoboo. If not, see <http://www.gnu.org/licenses/>.
17 //*
18 //********************************************************************************************
19
20 /// @file script.c
21 /// @brief Implements the game's scripting language.
22 /// @details
23
24 #include "script.h"
25 #include "script_compile.h"
26 #include "script_functions.h"
27
28 #include "mad.h"
29
30 #include "log.h"
31 #include "camera.h"
32 #include "game.h"
33 #include "network.h"
34
35 #include "egoboo_vfs.h"
36 #include "egoboo_setup.h"
37 #include "egoboo_strutil.h"
38 #include "egoboo_math.h"
39
40 #include "profile.inl"
41 #include "char.inl"
42
43 #include <assert.h>
44
45 //--------------------------------------------------------------------------------------------
46 //--------------------------------------------------------------------------------------------
47
48 static const char * script_error_classname = "UNKNOWN";
49 static PRO_REF script_error_model = ( PRO_REF )MAX_PROFILE;
50 static const char * script_error_name = "UNKNOWN";
51 static REF_T script_error_index = ( Uint16 )( ~0 );
52
53 static bool_t scr_increment_exe( ai_state_t * pself );
54 static bool_t scr_set_exe( ai_state_t * pself, size_t offset );
55
56 // static Uint8 run_function_obsolete( script_state_t * pstate, ai_state_t * pself );
57 static Uint8 scr_run_function( script_state_t * pstate, ai_state_t * pself );
58 static void scr_set_operand( script_state_t * pstate, Uint8 variable );
59 static void scr_run_operand( script_state_t * pstate, ai_state_t * pself );
60
61 static bool_t scr_run_operation( script_state_t * pstate, ai_state_t * pself );
62 static bool_t scr_run_function_call( script_state_t * pstate, ai_state_t * pself );
63
64 PROFILE_DECLARE( script_function )
65
66 static int _script_function_calls[SCRIPT_FUNCTIONS_COUNT];
67 static double _script_function_times[SCRIPT_FUNCTIONS_COUNT];
68
69 static bool_t _scripting_system_initialized = bfalse;
70
71 //--------------------------------------------------------------------------------------------
72 //--------------------------------------------------------------------------------------------
scripting_system_begin()73 void scripting_system_begin()
74 {
75 if ( !_scripting_system_initialized )
76 {
77 int cnt;
78
79 PROFILE_INIT( script_function );
80
81 for ( cnt = 0; cnt < SCRIPT_FUNCTIONS_COUNT; cnt++ )
82 {
83 _script_function_calls[cnt] = 0;
84 _script_function_times[cnt] = 0.0F;
85 }
86
87 _scripting_system_initialized = btrue;
88 }
89 }
90
91 //--------------------------------------------------------------------------------------------
scripting_system_end()92 void scripting_system_end()
93 {
94 if ( _scripting_system_initialized )
95 {
96 PROFILE_FREE( script_function );
97
98 #if (DEBUG_SCRIPT_LEVEL > 1 ) && defined(DEBUG_PROFILE) && defined(_DEBUG)
99 {
100 FILE * ftmp = fopen( vfs_resolveWriteFilename( "/debug/script_function_timing.txt" ), "a+" );
101
102 if ( NULL != ftmp )
103 {
104 int cnt;
105
106 for ( cnt = 0; cnt < SCRIPT_FUNCTIONS_COUNT; cnt++ )
107 {
108 if ( _script_function_calls[cnt] > 0 )
109 {
110 fprintf( ftmp, "function == %d\tname == \"%s\"\tcalls == %d\ttime == %lf\n",
111 cnt, script_function_names[cnt], _script_function_calls[cnt], _script_function_times[cnt] );
112 }
113 }
114
115 fflush( ftmp );
116 fclose( ftmp );
117 }
118 }
119 #endif
120
121 _scripting_system_initialized = bfalse;
122 }
123 }
124
125 //--------------------------------------------------------------------------------------------
126 //--------------------------------------------------------------------------------------------
scr_run_chr_script(const CHR_REF character)127 void scr_run_chr_script( const CHR_REF character )
128 {
129 /// @details ZZ@> This function lets one character do AI stuff
130
131 script_state_t my_state;
132 chr_t * pchr;
133 ai_state_t * pself;
134
135 // make sure that this module is initialized
136 scripting_system_begin();
137
138 if ( !INGAME_CHR( character ) ) return;
139 pchr = ChrList.lst + character;
140 pself = &( pchr->ai );
141
142 // has the time for this character to die come and gone?
143 if ( pself->poof_time >= 0 && pself->poof_time <= ( Sint32 )update_wld ) return;
144
145 // grab the "changed" value from the last time the script was run
146 if ( pself->changed )
147 {
148 SET_BIT( pself->alert, ALERTIF_CHANGED );
149 pself->changed = bfalse;
150 }
151
152 PROFILE_BEGIN_STRUCT( pself );
153
154 // debug a certain script
155 // debug_scripts = ( 385 == pself->index && 76 == pchr->profile_ref );
156
157 // target_old is set to the target every time the script is run
158 pself->target_old = pself->target;
159
160 // Make life easier
161 script_error_classname = "UNKNOWN";
162 script_error_model = pchr->profile_ref;
163 script_error_index = ( Uint16 )( ~0 );
164 script_error_name = "UNKNOWN";
165 if ( script_error_model < MAX_PROFILE )
166 {
167 CAP_REF icap = pro_get_icap( script_error_model );
168
169 script_error_classname = CapStack.lst[ icap ].classname;
170
171 script_error_index = ProList.lst[script_error_model].iai;
172 if ( script_error_index < MAX_AI )
173 {
174 script_error_name = AisStorage.ary[script_error_index].szName;
175 }
176 }
177
178 if ( debug_scripts )
179 {
180 FILE * scr_file = ( NULL == debug_script_file ) ? stdout : debug_script_file;
181
182 fprintf( scr_file, "\n\n--------\n%d - %s\n", script_error_index, script_error_name );
183 fprintf( scr_file, "%d - %s\n", REF_TO_INT( script_error_model ), script_error_classname );
184
185 // who are we related to?
186 fprintf( scr_file, "\tindex == %d\n", REF_TO_INT( pself->index ) );
187 fprintf( scr_file, "\ttarget == %d\n", REF_TO_INT( pself->target ) );
188 fprintf( scr_file, "\towner == %d\n", REF_TO_INT( pself->owner ) );
189 fprintf( scr_file, "\tchild == %d\n", REF_TO_INT( pself->child ) );
190
191 // some local storage
192 fprintf( scr_file, "\talert == %x\n", pself->alert );
193 fprintf( scr_file, "\tstate == %d\n", pself->state );
194 fprintf( scr_file, "\tcontent == %d\n", pself->content );
195 fprintf( scr_file, "\ttimer == %d\n", pself->timer );
196 fprintf( scr_file, "\tupdate_wld == %d\n", update_wld );
197
198 // ai memory from the last event
199 fprintf( scr_file, "\tbumplast == %d\n", REF_TO_INT( pself->bumplast ) );
200 fprintf( scr_file, "\tattacklast == %d\n", REF_TO_INT( pself->attacklast ) );
201 fprintf( scr_file, "\thitlast == %d\n", REF_TO_INT( pself->hitlast ) );
202 fprintf( scr_file, "\tdirectionlast == %d\n", pself->directionlast );
203 fprintf( scr_file, "\tdamagetypelast == %d\n", pself->damagetypelast );
204 fprintf( scr_file, "\tlastitemused == %d\n", REF_TO_INT( pself->lastitemused ) );
205 fprintf( scr_file, "\ttarget_old == %d\n", REF_TO_INT( pself->target_old ) );
206
207 // message handling
208 fprintf( scr_file, "\torder == %d\n", pself->order_value );
209 fprintf( scr_file, "\tcounter == %d\n", pself->order_counter );
210
211 // waypoints
212 fprintf( scr_file, "\twp_tail == %d\n", pself->wp_lst.tail );
213 fprintf( scr_file, "\twp_head == %d\n\n", pself->wp_lst.head );
214 }
215
216 // Clear the button latches
217 if ( !VALID_PLA( pchr->is_which_player ) )
218 {
219 RESET_BIT_FIELD( pchr->latch.b );
220 }
221
222 // Reset the target if it can't be seen
223 if (( pself->target != pself->index ) && !chr_can_see_object( character, pself->target ) )
224 {
225 pself->target = pself->index;
226 }
227
228 // reset the script state
229 memset( &my_state, 0, sizeof( my_state ) );
230
231 // reset the ai
232 pself->terminate = bfalse;
233 pself->indent = 0;
234 pself->exe_stt = AisStorage.ary[pself->type].iStartPosition;
235 pself->exe_end = AisStorage.ary[pself->type].iEndPosition;
236
237 // Run the AI Script
238 scr_set_exe( pself, pself->exe_stt );
239 while ( !pself->terminate && pself->exe_pos < pself->exe_end )
240 {
241 // This is used by the Else function
242 // it only keeps track of functions
243 pself->indent_last = pself->indent;
244 pself->indent = GET_DATA_BITS( pself->opcode );
245
246 // Was it a function
247 if ( HAS_SOME_BITS( pself->opcode, FUNCTION_BIT ) )
248 {
249 if ( !scr_run_function_call( &my_state, pself ) )
250 {
251 break;
252 }
253 }
254 else
255 {
256 if ( !scr_run_operation( &my_state, pself ) )
257 {
258 break;
259 }
260 }
261 }
262
263 // Set latches
264 if ( !VALID_PLA( pchr->is_which_player ) )
265 {
266 float latch2;
267
268 ai_state_ensure_wp( pself );
269
270 if ( pchr->ismount && INGAME_CHR( pchr->holdingwhich[SLOT_LEFT] ) )
271 {
272 // Mount
273 pchr->latch.x = ChrList.lst[pchr->holdingwhich[SLOT_LEFT]].latch.x;
274 pchr->latch.y = ChrList.lst[pchr->holdingwhich[SLOT_LEFT]].latch.y;
275 }
276 else if ( pself->wp_valid )
277 {
278 // Normal AI
279 pchr->latch.x = ( pself->wp[kX] - pchr->pos.x ) / ( GRID_ISIZE << 2 );
280 pchr->latch.y = ( pself->wp[kY] - pchr->pos.y ) / ( GRID_ISIZE << 2 );
281 }
282 else
283 {
284 // AI, but no valid waypoints
285 pchr->latch.x = 0;
286 pchr->latch.y = 0;
287 }
288
289 latch2 = pchr->latch.x * pchr->latch.x + pchr->latch.y * pchr->latch.y;
290 if ( latch2 > 1.0f )
291 {
292 float scale = 1.0f / SQRT( latch2 );
293 pchr->latch.x *= scale;
294 pchr->latch.y *= scale;
295 }
296 }
297
298 // Clear alerts for next time around
299 RESET_BIT_FIELD( pself->alert );
300
301 PROFILE_END2_STRUCT( pself );
302 }
303
304 //--------------------------------------------------------------------------------------------
scr_run_function_call(script_state_t * pstate,ai_state_t * pself)305 bool_t scr_run_function_call( script_state_t * pstate, ai_state_t * pself )
306 {
307 Uint8 functionreturn;
308
309 // check for valid pointers
310 if ( NULL == pstate || NULL == pself ) return bfalse;
311
312 // check for valid execution pointer
313 if ( pself->exe_pos < pself->exe_stt || pself->exe_pos >= pself->exe_end ) return bfalse;
314
315 // Run the function
316 functionreturn = scr_run_function( pstate, pself );
317
318 // move the execution pointer to the jump code
319 scr_increment_exe( pself );
320 if ( functionreturn )
321 {
322 // move the execution pointer to the next opcode
323 scr_increment_exe( pself );
324 }
325 else
326 {
327 // use the jump code to jump to the right location
328 size_t new_index = pself->opcode;
329
330 // make sure the value is valid
331 EGOBOO_ASSERT( new_index < AISMAXCOMPILESIZE && new_index >= pself->exe_stt && new_index <= pself->exe_end );
332
333 // actually do the jump
334 scr_set_exe( pself, new_index );
335 }
336
337 return btrue;
338 }
339
340 //--------------------------------------------------------------------------------------------
scr_run_operation(script_state_t * pstate,ai_state_t * pself)341 bool_t scr_run_operation( script_state_t * pstate, ai_state_t * pself )
342 {
343 const char * variable;
344 Uint32 var_value, operand_count, i;
345
346 // check for valid pointers
347 if ( NULL == pstate || NULL == pself ) return bfalse;
348
349 // check for valid execution pointer
350 if ( pself->exe_pos < pself->exe_stt || pself->exe_pos >= pself->exe_end ) return bfalse;
351
352 var_value = pself->opcode & VALUE_BITS;
353
354 // debug stuff
355 variable = "UNKNOWN";
356 if ( debug_scripts )
357 {
358 FILE * scr_file = ( NULL == debug_script_file ) ? stdout : debug_script_file;
359
360 for ( i = 0; i < pself->indent; i++ ) { fprintf( scr_file, " " ); }
361
362 for ( i = 0; i < MAX_OPCODE; i++ )
363 {
364 if ( 'V' == OpList.ary[i].cType && var_value == OpList.ary[i].iValue )
365 {
366 variable = OpList.ary[i].cName;
367 break;
368 };
369 }
370
371 fprintf( scr_file, "%s = ", variable );
372 }
373
374 // Get the number of operands
375 scr_increment_exe( pself );
376 operand_count = pself->opcode;
377
378 // Now run the operation
379 pstate->operationsum = 0;
380 for ( i = 0; i < operand_count && pself->exe_pos < pself->exe_end; i++ )
381 {
382 scr_increment_exe( pself );
383 scr_run_operand( pstate, pself );
384 }
385 if ( debug_scripts )
386 {
387 FILE * scr_file = ( NULL == debug_script_file ) ? stdout : debug_script_file;
388 fprintf( scr_file, " == %d \n", pstate->operationsum );
389 }
390
391 // Save the results in the register that called the arithmetic
392 scr_set_operand( pstate, var_value );
393
394 // go to the next opcode
395 scr_increment_exe( pself );
396
397 return btrue;
398 }
399
400 //--------------------------------------------------------------------------------------------
scr_run_function(script_state_t * pstate,ai_state_t * pself)401 Uint8 scr_run_function( script_state_t * pstate, ai_state_t * pself )
402 {
403 /// @details BB@> This is about half-way to what is needed for Lua integration
404
405 // Mask out the indentation
406 Uint32 valuecode = pself->opcode & VALUE_BITS;
407
408 // Assume that the function will pass, as most do
409 Uint8 returncode = btrue;
410 if ( MAX_OPCODE == valuecode )
411 {
412 log_message( "SCRIPT ERROR: scr_run_function() - model == %d, class name == \"%s\" - Unknown opcode found!\n", REF_TO_INT( script_error_model ), script_error_classname );
413 return bfalse;
414 }
415
416 // debug stuff
417 if ( debug_scripts )
418 {
419 Uint32 i;
420 FILE * scr_file = ( NULL == debug_script_file ) ? stdout : debug_script_file;
421
422 for ( i = 0; i < pself->indent; i++ ) { fprintf( scr_file, " " ); }
423
424 for ( i = 0; i < MAX_OPCODE; i++ )
425 {
426 if ( 'F' == OpList.ary[i].cType && valuecode == OpList.ary[i].iValue )
427 {
428 fprintf( scr_file, "%s\n", OpList.ary[i].cName );
429 break;
430 };
431 }
432 }
433
434 if ( valuecode > SCRIPT_FUNCTIONS_COUNT )
435 {
436 }
437 else
438 {
439 PROFILE_RESET( script_function );
440
441 PROFILE_BEGIN( script_function )
442 {
443 // Figure out which function to run
444 switch ( valuecode )
445 {
446 case FIFSPAWNED: returncode = scr_Spawned( pstate, pself ); break;
447 case FIFTIMEOUT: returncode = scr_TimeOut( pstate, pself ); break;
448 case FIFATWAYPOINT: returncode = scr_AtWaypoint( pstate, pself ); break;
449 case FIFATLASTWAYPOINT: returncode = scr_AtLastWaypoint( pstate, pself ); break;
450 case FIFATTACKED: returncode = scr_Attacked( pstate, pself ); break;
451 case FIFBUMPED: returncode = scr_Bumped( pstate, pself ); break;
452 case FIFORDERED: returncode = scr_Ordered( pstate, pself ); break;
453 case FIFCALLEDFORHELP: returncode = scr_CalledForHelp( pstate, pself ); break;
454 case FSETCONTENT: returncode = scr_set_Content( pstate, pself ); break;
455 case FIFKILLED: returncode = scr_Killed( pstate, pself ); break;
456 case FIFTARGETKILLED: returncode = scr_TargetKilled( pstate, pself ); break;
457 case FCLEARWAYPOINTS: returncode = scr_ClearWaypoints( pstate, pself ); break;
458 case FADDWAYPOINT: returncode = scr_AddWaypoint( pstate, pself ); break;
459 case FFINDPATH: returncode = scr_FindPath( pstate, pself ); break;
460 case FCOMPASS: returncode = scr_Compass( pstate, pself ); break;
461 case FGETTARGETARMORPRICE: returncode = scr_get_TargetArmorPrice( pstate, pself ); break;
462 case FSETTIME: returncode = scr_set_Time( pstate, pself ); break;
463 case FGETCONTENT: returncode = scr_get_Content( pstate, pself ); break;
464 case FJOINTARGETTEAM: returncode = scr_JoinTargetTeam( pstate, pself ); break;
465 case FSETTARGETTONEARBYENEMY: returncode = scr_set_TargetToNearbyEnemy( pstate, pself ); break;
466 case FSETTARGETTOTARGETLEFTHAND: returncode = scr_set_TargetToTargetLeftHand( pstate, pself ); break;
467 case FSETTARGETTOTARGETRIGHTHAND: returncode = scr_set_TargetToTargetRightHand( pstate, pself ); break;
468 case FSETTARGETTOWHOEVERATTACKED: returncode = scr_set_TargetToWhoeverAttacked( pstate, pself ); break;
469 case FSETTARGETTOWHOEVERBUMPED: returncode = scr_set_TargetToWhoeverBumped( pstate, pself ); break;
470 case FSETTARGETTOWHOEVERCALLEDFORHELP: returncode = scr_set_TargetToWhoeverCalledForHelp( pstate, pself ); break;
471 case FSETTARGETTOOLDTARGET: returncode = scr_set_TargetToOldTarget( pstate, pself ); break;
472 case FSETTURNMODETOVELOCITY: returncode = scr_set_TurnModeToVelocity( pstate, pself ); break;
473 case FSETTURNMODETOWATCH: returncode = scr_set_TurnModeToWatch( pstate, pself ); break;
474 case FSETTURNMODETOSPIN: returncode = scr_set_TurnModeToSpin( pstate, pself ); break;
475 case FSETBUMPHEIGHT: returncode = scr_set_BumpHeight( pstate, pself ); break;
476 case FIFTARGETHASID: returncode = scr_TargetHasID( pstate, pself ); break;
477 case FIFTARGETHASITEMID: returncode = scr_TargetHasItemID( pstate, pself ); break;
478 case FIFTARGETHOLDINGITEMID: returncode = scr_TargetHoldingItemID( pstate, pself ); break;
479 case FIFTARGETHASSKILLID: returncode = scr_TargetHasSkillID( pstate, pself ); break;
480 case FELSE: returncode = scr_Else( pstate, pself ); break;
481 case FRUN: returncode = scr_Run( pstate, pself ); break;
482 case FWALK: returncode = scr_Walk( pstate, pself ); break;
483 case FSNEAK: returncode = scr_Sneak( pstate, pself ); break;
484 case FDOACTION: returncode = scr_DoAction( pstate, pself ); break;
485 case FKEEPACTION: returncode = scr_KeepAction( pstate, pself ); break;
486 case FISSUEORDER: returncode = scr_IssueOrder( pstate, pself ); break;
487 case FDROPWEAPONS: returncode = scr_DropWeapons( pstate, pself ); break;
488 case FTARGETDOACTION: returncode = scr_TargetDoAction( pstate, pself ); break;
489 case FOPENPASSAGE: returncode = scr_OpenPassage( pstate, pself ); break;
490 case FCLOSEPASSAGE: returncode = scr_ClosePassage( pstate, pself ); break;
491 case FIFPASSAGEOPEN: returncode = scr_PassageOpen( pstate, pself ); break;
492 case FGOPOOF: returncode = scr_GoPoof( pstate, pself ); break;
493 case FCOSTTARGETITEMID: returncode = scr_CostTargetItemID( pstate, pself ); break;
494 case FDOACTIONOVERRIDE: returncode = scr_DoActionOverride( pstate, pself ); break;
495 case FIFHEALED: returncode = scr_Healed( pstate, pself ); break;
496 case FSENDMESSAGE: returncode = scr_SendPlayerMessage( pstate, pself ); break;
497 case FCALLFORHELP: returncode = scr_CallForHelp( pstate, pself ); break;
498 case FADDIDSZ: returncode = scr_AddIDSZ( pstate, pself ); break;
499 case FSETSTATE: returncode = scr_set_State( pstate, pself ); break;
500 case FGETSTATE: returncode = scr_get_State( pstate, pself ); break;
501 case FIFSTATEIS: returncode = scr_StateIs( pstate, pself ); break;
502 case FIFTARGETCANOPENSTUFF: returncode = scr_TargetCanOpenStuff( pstate, pself ); break;
503 case FIFGRABBED: returncode = scr_Grabbed( pstate, pself ); break;
504 case FIFDROPPED: returncode = scr_Dropped( pstate, pself ); break;
505 case FSETTARGETTOWHOEVERISHOLDING: returncode = scr_set_TargetToWhoeverIsHolding( pstate, pself ); break;
506 case FDAMAGETARGET: returncode = scr_DamageTarget( pstate, pself ); break;
507 case FIFXISLESSTHANY: returncode = scr_XIsLessThanY( pstate, pself ); break;
508 case FSETWEATHERTIME: returncode = scr_set_WeatherTime( pstate, pself ); break;
509 case FGETBUMPHEIGHT: returncode = scr_get_BumpHeight( pstate, pself ); break;
510 case FIFREAFFIRMED: returncode = scr_Reaffirmed( pstate, pself ); break;
511 case FUNKEEPACTION: returncode = scr_UnkeepAction( pstate, pself ); break;
512 case FIFTARGETISONOTHERTEAM: returncode = scr_TargetIsOnOtherTeam( pstate, pself ); break;
513 case FIFTARGETISONHATEDTEAM: returncode = scr_TargetIsOnHatedTeam( pstate, pself ); break;
514 case FPRESSLATCHBUTTON: returncode = scr_PressLatchButton( pstate, pself ); break;
515 case FSETTARGETTOTARGETOFLEADER: returncode = scr_set_TargetToTargetOfLeader( pstate, pself ); break;
516 case FIFLEADERKILLED: returncode = scr_LeaderKilled( pstate, pself ); break;
517 case FBECOMELEADER: returncode = scr_BecomeLeader( pstate, pself ); break;
518 case FCHANGETARGETARMOR: returncode = scr_ChangeTargetArmor( pstate, pself ); break;
519 case FGIVEMONEYTOTARGET: returncode = scr_GiveMoneyToTarget( pstate, pself ); break;
520 case FDROPKEYS: returncode = scr_DropKeys( pstate, pself ); break;
521 case FIFLEADERISALIVE: returncode = scr_LeaderIsAlive( pstate, pself ); break;
522 case FIFTARGETISOLDTARGET: returncode = scr_TargetIsOldTarget( pstate, pself ); break;
523 case FSETTARGETTOLEADER: returncode = scr_set_TargetToLeader( pstate, pself ); break;
524 case FSPAWNCHARACTER: returncode = scr_SpawnCharacter( pstate, pself ); break;
525 case FRESPAWNCHARACTER: returncode = scr_RespawnCharacter( pstate, pself ); break;
526 case FCHANGETILE: returncode = scr_ChangeTile( pstate, pself ); break;
527 case FIFUSED: returncode = scr_Used( pstate, pself ); break;
528 case FDROPMONEY: returncode = scr_DropMoney( pstate, pself ); break;
529 case FSETOLDTARGET: returncode = scr_set_OldTarget( pstate, pself ); break;
530 case FDETACHFROMHOLDER: returncode = scr_DetachFromHolder( pstate, pself ); break;
531 case FIFTARGETHASVULNERABILITYID: returncode = scr_TargetHasVulnerabilityID( pstate, pself ); break;
532 case FCLEANUP: returncode = scr_CleanUp( pstate, pself ); break;
533 case FIFCLEANEDUP: returncode = scr_CleanedUp( pstate, pself ); break;
534 case FIFSITTING: returncode = scr_Sitting( pstate, pself ); break;
535 case FIFTARGETISHURT: returncode = scr_TargetIsHurt( pstate, pself ); break;
536 case FIFTARGETISAPLAYER: returncode = scr_TargetIsAPlayer( pstate, pself ); break;
537 case FPLAYSOUND: returncode = scr_PlaySound( pstate, pself ); break;
538 case FSPAWNPARTICLE: returncode = scr_SpawnParticle( pstate, pself ); break;
539 case FIFTARGETISALIVE: returncode = scr_TargetIsAlive( pstate, pself ); break;
540 case FSTOP: returncode = scr_Stop( pstate, pself ); break;
541 case FDISAFFIRMCHARACTER: returncode = scr_DisaffirmCharacter( pstate, pself ); break;
542 case FREAFFIRMCHARACTER: returncode = scr_ReaffirmCharacter( pstate, pself ); break;
543 case FIFTARGETISSELF: returncode = scr_TargetIsSelf( pstate, pself ); break;
544 case FIFTARGETISMALE: returncode = scr_TargetIsMale( pstate, pself ); break;
545 case FIFTARGETISFEMALE: returncode = scr_TargetIsFemale( pstate, pself ); break;
546 case FSETTARGETTOSELF: returncode = scr_set_TargetToSelf( pstate, pself ); break;
547 case FSETTARGETTORIDER: returncode = scr_set_TargetToRider( pstate, pself ); break;
548 case FGETATTACKTURN: returncode = scr_get_AttackTurn( pstate, pself ); break;
549 case FGETDAMAGETYPE: returncode = scr_get_DamageType( pstate, pself ); break;
550 case FBECOMESPELL: returncode = scr_BecomeSpell( pstate, pself ); break;
551 case FBECOMESPELLBOOK: returncode = scr_BecomeSpellbook( pstate, pself ); break;
552 case FIFSCOREDAHIT: returncode = scr_ScoredAHit( pstate, pself ); break;
553 case FIFDISAFFIRMED: returncode = scr_Disaffirmed( pstate, pself ); break;
554 case FTRANSLATEORDER: returncode = scr_TranslateOrder( pstate, pself ); break;
555 case FSETTARGETTOWHOEVERWASHIT: returncode = scr_set_TargetToWhoeverWasHit( pstate, pself ); break;
556 case FSETTARGETTOWIDEENEMY: returncode = scr_set_TargetToWideEnemy( pstate, pself ); break;
557 case FIFCHANGED: returncode = scr_Changed( pstate, pself ); break;
558 case FIFINWATER: returncode = scr_InWater( pstate, pself ); break;
559 case FIFBORED: returncode = scr_Bored( pstate, pself ); break;
560 case FIFTOOMUCHBAGGAGE: returncode = scr_TooMuchBaggage( pstate, pself ); break;
561 case FIFGROGGED: returncode = scr_Grogged( pstate, pself ); break;
562 case FIFDAZED: returncode = scr_Dazed( pstate, pself ); break;
563 case FIFTARGETHASSPECIALID: returncode = scr_TargetHasSpecialID( pstate, pself ); break;
564 case FPRESSTARGETLATCHBUTTON: returncode = scr_PressTargetLatchButton( pstate, pself ); break;
565 case FIFINVISIBLE: returncode = scr_Invisible( pstate, pself ); break;
566 case FIFARMORIS: returncode = scr_ArmorIs( pstate, pself ); break;
567 case FGETTARGETGROGTIME: returncode = scr_get_TargetGrogTime( pstate, pself ); break;
568 case FGETTARGETDAZETIME: returncode = scr_get_TargetDazeTime( pstate, pself ); break;
569 case FSETDAMAGETYPE: returncode = scr_set_DamageType( pstate, pself ); break;
570 case FSETWATERLEVEL: returncode = scr_set_WaterLevel( pstate, pself ); break;
571 case FENCHANTTARGET: returncode = scr_EnchantTarget( pstate, pself ); break;
572 case FENCHANTCHILD: returncode = scr_EnchantChild( pstate, pself ); break;
573 case FTELEPORTTARGET: returncode = scr_TeleportTarget( pstate, pself ); break;
574 case FGIVEEXPERIENCETOTARGET: returncode = scr_GiveExperienceToTarget( pstate, pself ); break;
575 case FINCREASEAMMO: returncode = scr_IncreaseAmmo( pstate, pself ); break;
576 case FUNKURSETARGET: returncode = scr_UnkurseTarget( pstate, pself ); break;
577 case FGIVEEXPERIENCETOTARGETTEAM: returncode = scr_GiveExperienceToTargetTeam( pstate, pself ); break;
578 case FIFUNARMED: returncode = scr_Unarmed( pstate, pself ); break;
579 case FRESTOCKTARGETAMMOIDALL: returncode = scr_RestockTargetAmmoIDAll( pstate, pself ); break;
580 case FRESTOCKTARGETAMMOIDFIRST: returncode = scr_RestockTargetAmmoIDFirst( pstate, pself ); break;
581 case FFLASHTARGET: returncode = scr_FlashTarget( pstate, pself ); break;
582 case FSETREDSHIFT: returncode = scr_set_RedShift( pstate, pself ); break;
583 case FSETGREENSHIFT: returncode = scr_set_GreenShift( pstate, pself ); break;
584 case FSETBLUESHIFT: returncode = scr_set_BlueShift( pstate, pself ); break;
585 case FSETLIGHT: returncode = scr_set_Light( pstate, pself ); break;
586 case FSETALPHA: returncode = scr_set_Alpha( pstate, pself ); break;
587 case FIFHITFROMBEHIND: returncode = scr_HitFromBehind( pstate, pself ); break;
588 case FIFHITFROMFRONT: returncode = scr_HitFromFront( pstate, pself ); break;
589 case FIFHITFROMLEFT: returncode = scr_HitFromLeft( pstate, pself ); break;
590 case FIFHITFROMRIGHT: returncode = scr_HitFromRight( pstate, pself ); break;
591 case FIFTARGETISONSAMETEAM: returncode = scr_TargetIsOnSameTeam( pstate, pself ); break;
592 case FKILLTARGET: returncode = scr_KillTarget( pstate, pself ); break;
593 case FUNDOENCHANT: returncode = scr_UndoEnchant( pstate, pself ); break;
594 case FGETWATERLEVEL: returncode = scr_get_WaterLevel( pstate, pself ); break;
595 case FCOSTTARGETMANA: returncode = scr_CostTargetMana( pstate, pself ); break;
596 case FIFTARGETHASANYID: returncode = scr_TargetHasAnyID( pstate, pself ); break;
597 case FSETBUMPSIZE: returncode = scr_set_BumpSize( pstate, pself ); break;
598 case FIFNOTDROPPED: returncode = scr_NotDropped( pstate, pself ); break;
599 case FIFYISLESSTHANX: returncode = scr_YIsLessThanX( pstate, pself ); break;
600 case FSETFLYHEIGHT: returncode = scr_set_FlyHeight( pstate, pself ); break;
601 case FIFBLOCKED: returncode = scr_Blocked( pstate, pself ); break;
602 case FIFTARGETISDEFENDING: returncode = scr_TargetIsDefending( pstate, pself ); break;
603 case FIFTARGETISATTACKING: returncode = scr_TargetIsAttacking( pstate, pself ); break;
604 case FIFSTATEIS0: returncode = scr_StateIs0( pstate, pself ); break;
605 case FIFSTATEIS1: returncode = scr_StateIs1( pstate, pself ); break;
606 case FIFSTATEIS2: returncode = scr_StateIs2( pstate, pself ); break;
607 case FIFSTATEIS3: returncode = scr_StateIs3( pstate, pself ); break;
608 case FIFSTATEIS4: returncode = scr_StateIs4( pstate, pself ); break;
609 case FIFSTATEIS5: returncode = scr_StateIs5( pstate, pself ); break;
610 case FIFSTATEIS6: returncode = scr_StateIs6( pstate, pself ); break;
611 case FIFSTATEIS7: returncode = scr_StateIs7( pstate, pself ); break;
612 case FIFCONTENTIS: returncode = scr_ContentIs( pstate, pself ); break;
613 case FSETTURNMODETOWATCHTARGET: returncode = scr_set_TurnModeToWatchTarget( pstate, pself ); break;
614 case FIFSTATEISNOT: returncode = scr_StateIsNot( pstate, pself ); break;
615 case FIFXISEQUALTOY: returncode = scr_XIsEqualToY( pstate, pself ); break;
616 case FDEBUGMESSAGE: returncode = scr_DebugMessage( pstate, pself ); break;
617 case FBLACKTARGET: returncode = scr_BlackTarget( pstate, pself ); break;
618 case FSENDMESSAGENEAR: returncode = scr_SendMessageNear( pstate, pself ); break;
619 case FIFHITGROUND: returncode = scr_HitGround( pstate, pself ); break;
620 case FIFNAMEISKNOWN: returncode = scr_NameIsKnown( pstate, pself ); break;
621 case FIFUSAGEISKNOWN: returncode = scr_UsageIsKnown( pstate, pself ); break;
622 case FIFHOLDINGITEMID: returncode = scr_HoldingItemID( pstate, pself ); break;
623 case FIFHOLDINGRANGEDWEAPON: returncode = scr_HoldingRangedWeapon( pstate, pself ); break;
624 case FIFHOLDINGMELEEWEAPON: returncode = scr_HoldingMeleeWeapon( pstate, pself ); break;
625 case FIFHOLDINGSHIELD: returncode = scr_HoldingShield( pstate, pself ); break;
626 case FIFKURSED: returncode = scr_Kursed( pstate, pself ); break;
627 case FIFTARGETISKURSED: returncode = scr_TargetIsKursed( pstate, pself ); break;
628 case FIFTARGETISDRESSEDUP: returncode = scr_TargetIsDressedUp( pstate, pself ); break;
629 case FIFOVERWATER: returncode = scr_OverWater( pstate, pself ); break;
630 case FIFTHROWN: returncode = scr_Thrown( pstate, pself ); break;
631 case FMAKENAMEKNOWN: returncode = scr_MakeNameKnown( pstate, pself ); break;
632 case FMAKEUSAGEKNOWN: returncode = scr_MakeUsageKnown( pstate, pself ); break;
633 case FSTOPTARGETMOVEMENT: returncode = scr_StopTargetMovement( pstate, pself ); break;
634 case FSETXY: returncode = scr_set_XY( pstate, pself ); break;
635 case FGETXY: returncode = scr_get_XY( pstate, pself ); break;
636 case FADDXY: returncode = scr_AddXY( pstate, pself ); break;
637 case FMAKEAMMOKNOWN: returncode = scr_MakeAmmoKnown( pstate, pself ); break;
638 case FSPAWNATTACHEDPARTICLE: returncode = scr_SpawnAttachedParticle( pstate, pself ); break;
639 case FSPAWNEXACTPARTICLE: returncode = scr_SpawnExactParticle( pstate, pself ); break;
640 case FACCELERATETARGET: returncode = scr_AccelerateTarget( pstate, pself ); break;
641 case FIFDISTANCEISMORETHANTURN: returncode = scr_distanceIsMoreThanTurn( pstate, pself ); break;
642 case FIFCRUSHED: returncode = scr_Crushed( pstate, pself ); break;
643 case FMAKECRUSHVALID: returncode = scr_MakeCrushValid( pstate, pself ); break;
644 case FSETTARGETTOLOWESTTARGET: returncode = scr_set_TargetToLowestTarget( pstate, pself ); break;
645 case FIFNOTPUTAWAY: returncode = scr_NotPutAway( pstate, pself ); break;
646 case FIFTAKENOUT: returncode = scr_TakenOut( pstate, pself ); break;
647 case FIFAMMOOUT: returncode = scr_AmmoOut( pstate, pself ); break;
648 case FPLAYSOUNDLOOPED: returncode = scr_PlaySoundLooped( pstate, pself ); break;
649 case FSTOPSOUND: returncode = scr_StopSound( pstate, pself ); break;
650 case FHEALSELF: returncode = scr_HealSelf( pstate, pself ); break;
651 case FEQUIP: returncode = scr_Equip( pstate, pself ); break;
652 case FIFTARGETHASITEMIDEQUIPPED: returncode = scr_TargetHasItemIDEquipped( pstate, pself ); break;
653 case FSETOWNERTOTARGET: returncode = scr_set_OwnerToTarget( pstate, pself ); break;
654 case FSETTARGETTOOWNER: returncode = scr_set_TargetToOwner( pstate, pself ); break;
655 case FSETFRAME: returncode = scr_set_Frame( pstate, pself ); break;
656 case FBREAKPASSAGE: returncode = scr_BreakPassage( pstate, pself ); break;
657 case FSETRELOADTIME: returncode = scr_set_ReloadTime( pstate, pself ); break;
658 case FSETTARGETTOWIDEBLAHID: returncode = scr_set_TargetToWideBlahID( pstate, pself ); break;
659 case FPOOFTARGET: returncode = scr_PoofTarget( pstate, pself ); break;
660 case FCHILDDOACTIONOVERRIDE: returncode = scr_ChildDoActionOverride( pstate, pself ); break;
661 case FSPAWNPOOF: returncode = scr_SpawnPoof( pstate, pself ); break;
662 case FSETSPEEDPERCENT: returncode = scr_set_SpeedPercent( pstate, pself ); break;
663 case FSETCHILDSTATE: returncode = scr_set_ChildState( pstate, pself ); break;
664 case FSPAWNATTACHEDSIZEDPARTICLE: returncode = scr_SpawnAttachedSizedParticle( pstate, pself ); break;
665 case FCHANGEARMOR: returncode = scr_ChangeArmor( pstate, pself ); break;
666 case FSHOWTIMER: returncode = scr_ShowTimer( pstate, pself ); break;
667 case FIFFACINGTARGET: returncode = scr_FacingTarget( pstate, pself ); break;
668 case FPLAYSOUNDVOLUME: returncode = scr_PlaySoundVolume( pstate, pself ); break;
669 case FSPAWNATTACHEDFACEDPARTICLE: returncode = scr_SpawnAttachedFacedParticle( pstate, pself ); break;
670 case FIFSTATEISODD: returncode = scr_StateIsOdd( pstate, pself ); break;
671 case FSETTARGETTODISTANTENEMY: returncode = scr_set_TargetToDistantEnemy( pstate, pself ); break;
672 case FTELEPORT: returncode = scr_Teleport( pstate, pself ); break;
673 case FGIVESTRENGTHTOTARGET: returncode = scr_GiveStrengthToTarget( pstate, pself ); break;
674 case FGIVEWISDOMTOTARGET: returncode = scr_GiveWisdomToTarget( pstate, pself ); break;
675 case FGIVEINTELLIGENCETOTARGET: returncode = scr_GiveIntelligenceToTarget( pstate, pself ); break;
676 case FGIVEDEXTERITYTOTARGET: returncode = scr_GiveDexterityToTarget( pstate, pself ); break;
677 case FGIVELIFETOTARGET: returncode = scr_GiveLifeToTarget( pstate, pself ); break;
678 case FGIVEMANATOTARGET: returncode = scr_GiveManaToTarget( pstate, pself ); break;
679 case FSHOWMAP: returncode = scr_ShowMap( pstate, pself ); break;
680 case FSHOWYOUAREHERE: returncode = scr_ShowYouAreHere( pstate, pself ); break;
681 case FSHOWBLIPXY: returncode = scr_ShowBlipXY( pstate, pself ); break;
682 case FHEALTARGET: returncode = scr_HealTarget( pstate, pself ); break;
683 case FPUMPTARGET: returncode = scr_PumpTarget( pstate, pself ); break;
684 case FCOSTAMMO: returncode = scr_CostAmmo( pstate, pself ); break;
685 case FMAKESIMILARNAMESKNOWN: returncode = scr_MakeSimilarNamesKnown( pstate, pself ); break;
686 case FSPAWNATTACHEDHOLDERPARTICLE: returncode = scr_SpawnAttachedHolderParticle( pstate, pself ); break;
687 case FSETTARGETRELOADTIME: returncode = scr_set_TargetReloadTime( pstate, pself ); break;
688 case FSETFOGLEVEL: returncode = scr_set_FogLevel( pstate, pself ); break;
689 case FGETFOGLEVEL: returncode = scr_get_FogLevel( pstate, pself ); break;
690 case FSETFOGTAD: returncode = scr_set_FogTAD( pstate, pself ); break;
691 case FSETFOGBOTTOMLEVEL: returncode = scr_set_FogBottomLevel( pstate, pself ); break;
692 case FGETFOGBOTTOMLEVEL: returncode = scr_get_FogBottomLevel( pstate, pself ); break;
693 case FCORRECTACTIONFORHAND: returncode = scr_CorrectActionForHand( pstate, pself ); break;
694 case FIFTARGETISMOUNTED: returncode = scr_TargetIsMounted( pstate, pself ); break;
695 case FSPARKLEICON: returncode = scr_SparkleIcon( pstate, pself ); break;
696 case FUNSPARKLEICON: returncode = scr_UnsparkleIcon( pstate, pself ); break;
697 case FGETTILEXY: returncode = scr_get_TileXY( pstate, pself ); break;
698 case FSETTILEXY: returncode = scr_set_TileXY( pstate, pself ); break;
699 case FSETSHADOWSIZE: returncode = scr_set_ShadowSize( pstate, pself ); break;
700 case FORDERTARGET: returncode = scr_OrderTarget( pstate, pself ); break;
701 case FSETTARGETTOWHOEVERISINPASSAGE: returncode = scr_set_TargetToWhoeverIsInPassage( pstate, pself ); break;
702 case FIFCHARACTERWASABOOK: returncode = scr_CharacterWasABook( pstate, pself ); break;
703 case FSETENCHANTBOOSTVALUES: returncode = scr_set_EnchantBoostValues( pstate, pself ); break;
704 case FSPAWNCHARACTERXYZ: returncode = scr_SpawnCharacterXYZ( pstate, pself ); break;
705 case FSPAWNEXACTCHARACTERXYZ: returncode = scr_SpawnExactCharacterXYZ( pstate, pself ); break;
706 case FCHANGETARGETCLASS: returncode = scr_ChangeTargetClass( pstate, pself ); break;
707 case FPLAYFULLSOUND: returncode = scr_PlayFullSound( pstate, pself ); break;
708 case FSPAWNEXACTCHASEPARTICLE: returncode = scr_SpawnExactChaseParticle( pstate, pself ); break;
709 case FCREATEORDER: returncode = scr_CreateOrder( pstate, pself ); break;
710 case FORDERSPECIALID: returncode = scr_OrderSpecialID( pstate, pself ); break;
711 case FUNKURSETARGETINVENTORY: returncode = scr_UnkurseTargetInventory( pstate, pself ); break;
712 case FIFTARGETISSNEAKING: returncode = scr_TargetIsSneaking( pstate, pself ); break;
713 case FDROPITEMS: returncode = scr_DropItems( pstate, pself ); break;
714 case FRESPAWNTARGET: returncode = scr_RespawnTarget( pstate, pself ); break;
715 case FTARGETDOACTIONSETFRAME: returncode = scr_TargetDoActionSetFrame( pstate, pself ); break;
716 case FIFTARGETCANSEEINVISIBLE: returncode = scr_TargetCanSeeInvisible( pstate, pself ); break;
717 case FSETTARGETTONEARESTBLAHID: returncode = scr_set_TargetToNearestBlahID( pstate, pself ); break;
718 case FSETTARGETTONEARESTENEMY: returncode = scr_set_TargetToNearestEnemy( pstate, pself ); break;
719 case FSETTARGETTONEARESTFRIEND: returncode = scr_set_TargetToNearestFriend( pstate, pself ); break;
720 case FSETTARGETTONEARESTLIFEFORM: returncode = scr_set_TargetToNearestLifeform( pstate, pself ); break;
721 case FFLASHPASSAGE: returncode = scr_FlashPassage( pstate, pself ); break;
722 case FFINDTILEINPASSAGE: returncode = scr_FindTileInPassage( pstate, pself ); break;
723 case FIFHELDINLEFTHAND: returncode = scr_HeldInLeftHand( pstate, pself ); break;
724 case FNOTANITEM: returncode = scr_NotAnItem( pstate, pself ); break;
725 case FSETCHILDAMMO: returncode = scr_set_ChildAmmo( pstate, pself ); break;
726 case FIFHITVULNERABLE: returncode = scr_HitVulnerable( pstate, pself ); break;
727 case FIFTARGETISFLYING: returncode = scr_TargetIsFlying( pstate, pself ); break;
728 case FIDENTIFYTARGET: returncode = scr_IdentifyTarget( pstate, pself ); break;
729 case FBEATMODULE: returncode = scr_BeatModule( pstate, pself ); break;
730 case FENDMODULE: returncode = scr_EndModule( pstate, pself ); break;
731 case FDISABLEEXPORT: returncode = scr_DisableExport( pstate, pself ); break;
732 case FENABLEEXPORT: returncode = scr_EnableExport( pstate, pself ); break;
733 case FGETTARGETSTATE: returncode = scr_get_TargetState( pstate, pself ); break;
734 case FIFEQUIPPED: returncode = scr_Equipped( pstate, pself ); break;
735 case FDROPTARGETMONEY: returncode = scr_DropTargetMoney( pstate, pself ); break;
736 case FGETTARGETCONTENT: returncode = scr_get_TargetContent( pstate, pself ); break;
737 case FDROPTARGETKEYS: returncode = scr_DropTargetKeys( pstate, pself ); break;
738 case FJOINTEAM: returncode = scr_JoinTeam( pstate, pself ); break;
739 case FTARGETJOINTEAM: returncode = scr_TargetJoinTeam( pstate, pself ); break;
740 case FCLEARMUSICPASSAGE: returncode = scr_ClearMusicPassage( pstate, pself ); break;
741 case FCLEARENDMESSAGE: returncode = scr_ClearEndMessage( pstate, pself ); break;
742 case FADDENDMESSAGE: returncode = scr_AddEndMessage( pstate, pself ); break;
743 case FPLAYMUSIC: returncode = scr_PlayMusic( pstate, pself ); break;
744 case FSETMUSICPASSAGE: returncode = scr_set_MusicPassage( pstate, pself ); break;
745 case FMAKECRUSHINVALID: returncode = scr_MakeCrushInvalid( pstate, pself ); break;
746 case FSTOPMUSIC: returncode = scr_StopMusic( pstate, pself ); break;
747 case FFLASHVARIABLE: returncode = scr_FlashVariable( pstate, pself ); break;
748 case FACCELERATEUP: returncode = scr_AccelerateUp( pstate, pself ); break;
749 case FFLASHVARIABLEHEIGHT: returncode = scr_FlashVariableHeight( pstate, pself ); break;
750 case FSETDAMAGETIME: returncode = scr_set_DamageTime( pstate, pself ); break;
751 case FIFSTATEIS8: returncode = scr_StateIs8( pstate, pself ); break;
752 case FIFSTATEIS9: returncode = scr_StateIs9( pstate, pself ); break;
753 case FIFSTATEIS10: returncode = scr_StateIs10( pstate, pself ); break;
754 case FIFSTATEIS11: returncode = scr_StateIs11( pstate, pself ); break;
755 case FIFSTATEIS12: returncode = scr_StateIs12( pstate, pself ); break;
756 case FIFSTATEIS13: returncode = scr_StateIs13( pstate, pself ); break;
757 case FIFSTATEIS14: returncode = scr_StateIs14( pstate, pself ); break;
758 case FIFSTATEIS15: returncode = scr_StateIs15( pstate, pself ); break;
759 case FIFTARGETISAMOUNT: returncode = scr_TargetIsAMount( pstate, pself ); break;
760 case FIFTARGETISAPLATFORM: returncode = scr_TargetIsAPlatform( pstate, pself ); break;
761 case FADDSTAT: returncode = scr_AddStat( pstate, pself ); break;
762 case FDISENCHANTTARGET: returncode = scr_DisenchantTarget( pstate, pself ); break;
763 case FDISENCHANTALL: returncode = scr_DisenchantAll( pstate, pself ); break;
764 case FSETVOLUMENEARESTTEAMMATE: returncode = scr_set_VolumeNearestTeammate( pstate, pself ); break;
765 case FADDSHOPPASSAGE: returncode = scr_AddShopPassage( pstate, pself ); break;
766 case FTARGETPAYFORARMOR: returncode = scr_TargetPayForArmor( pstate, pself ); break;
767 case FJOINEVILTEAM: returncode = scr_JoinEvilTeam( pstate, pself ); break;
768 case FJOINNULLTEAM: returncode = scr_JoinNullTeam( pstate, pself ); break;
769 case FJOINGOODTEAM: returncode = scr_JoinGoodTeam( pstate, pself ); break;
770 case FPITSKILL: returncode = scr_PitsKill( pstate, pself ); break;
771 case FSETTARGETTOPASSAGEID: returncode = scr_set_TargetToPassageID( pstate, pself ); break;
772 case FMAKENAMEUNKNOWN: returncode = scr_MakeNameUnknown( pstate, pself ); break;
773 case FSPAWNEXACTPARTICLEENDSPAWN: returncode = scr_SpawnExactParticleEndSpawn( pstate, pself ); break;
774 case FSPAWNPOOFSPEEDSPACINGDAMAGE: returncode = scr_SpawnPoofSpeedSpacingDamage( pstate, pself ); break;
775 case FGIVEEXPERIENCETOGOODTEAM: returncode = scr_GiveExperienceToGoodTeam( pstate, pself ); break;
776 case FDONOTHING: returncode = scr_DoNothing( pstate, pself ); break;
777 case FGROGTARGET: returncode = scr_GrogTarget( pstate, pself ); break;
778 case FDAZETARGET: returncode = scr_DazeTarget( pstate, pself ); break;
779 case FENABLERESPAWN: returncode = scr_EnableRespawn( pstate, pself ); break;
780 case FDISABLERESPAWN: returncode = scr_DisableRespawn( pstate, pself ); break;
781 case FDISPELTARGETENCHANTID: returncode = scr_DispelTargetEnchantID( pstate, pself ); break;
782 case FIFHOLDERBLOCKED: returncode = scr_HolderBlocked( pstate, pself ); break;
783 // case FGETSKILLLEVEL: returncode = scr_get_SkillLevel( pstate, pself ); break;
784 case FIFTARGETHASNOTFULLMANA: returncode = scr_TargetHasNotFullMana( pstate, pself ); break;
785 case FENABLELISTENSKILL: returncode = scr_EnableListenSkill( pstate, pself ); break;
786 case FSETTARGETTOLASTITEMUSED: returncode = scr_set_TargetToLastItemUsed( pstate, pself ); break;
787 case FFOLLOWLINK: returncode = scr_FollowLink( pstate, pself ); break;
788 case FIFOPERATORISLINUX: returncode = scr_OperatorIsLinux( pstate, pself ); break;
789 case FIFTARGETISAWEAPON: returncode = scr_TargetIsAWeapon( pstate, pself ); break;
790 case FIFSOMEONEISSTEALING: returncode = scr_SomeoneIsStealing( pstate, pself ); break;
791 case FIFTARGETISASPELL: returncode = scr_TargetIsASpell( pstate, pself ); break;
792 case FIFBACKSTABBED: returncode = scr_Backstabbed( pstate, pself ); break;
793 case FGETTARGETDAMAGETYPE: returncode = scr_get_TargetDamageType( pstate, pself ); break;
794 case FADDQUEST: returncode = scr_AddQuest( pstate, pself ); break;
795 case FBEATQUESTALLPLAYERS: returncode = scr_BeatQuestAllPlayers( pstate, pself ); break;
796 case FIFTARGETHASQUEST: returncode = scr_TargetHasQuest( pstate, pself ); break;
797 case FSETQUESTLEVEL: returncode = scr_set_QuestLevel( pstate, pself ); break;
798 case FADDQUESTALLPLAYERS: returncode = scr_AddQuestAllPlayers( pstate, pself ); break;
799 case FADDBLIPALLENEMIES: returncode = scr_AddBlipAllEnemies( pstate, pself ); break;
800 case FPITSFALL: returncode = scr_PitsFall( pstate, pself ); break;
801 case FIFTARGETISOWNER: returncode = scr_TargetIsOwner( pstate, pself ); break;
802 case FEND: returncode = scr_End( pstate, pself ); break;
803
804 case FSETSPEECH: returncode = scr_set_Speech( pstate, pself ); break;
805 case FSETMOVESPEECH: returncode = scr_set_MoveSpeech( pstate, pself ); break;
806 case FSETSECONDMOVESPEECH: returncode = scr_set_SecondMoveSpeech( pstate, pself ); break;
807 case FSETATTACKSPEECH: returncode = scr_set_AttackSpeech( pstate, pself ); break;
808 case FSETASSISTSPEECH: returncode = scr_set_AssistSpeech( pstate, pself ); break;
809 case FSETTERRAINSPEECH: returncode = scr_set_TerrainSpeech( pstate, pself ); break;
810 case FSETSELECTSPEECH: returncode = scr_set_SelectSpeech( pstate, pself ); break;
811
812 case FTAKEPICTURE: returncode = scr_TakePicture( pstate, pself ); break;
813 case FIFOPERATORISMACINTOSH: returncode = scr_OperatorIsMacintosh( pstate, pself ); break;
814 case FIFMODULEHASIDSZ: returncode = scr_ModuleHasIDSZ( pstate, pself ); break;
815 case FMORPHTOTARGET: returncode = scr_MorphToTarget( pstate, pself ); break;
816 case FGIVEMANAFLOWTOTARGET: returncode = scr_GiveManaFlowToTarget( pstate, pself ); break;
817 case FGIVEMANARETURNTOTARGET:returncode = scr_GiveManaReturnToTarget( pstate, pself ); break;
818 case FSETMONEY: returncode = scr_set_Money( pstate, pself ); break;
819 case FIFTARGETCANSEEKURSES: returncode = scr_TargetCanSeeKurses( pstate, pself ); break;
820 case FSPAWNATTACHEDCHARACTER:returncode = scr_SpawnAttachedCharacter( pstate, pself ); break;
821 case FKURSETARGET: returncode = scr_KurseTarget( pstate, pself ); break;
822 case FSETCHILDCONTENT: returncode = scr_set_ChildContent( pstate, pself ); break;
823 case FSETTARGETTOCHILD: returncode = scr_set_TargetToChild( pstate, pself ); break;
824 case FSETDAMAGETHRESHOLD: returncode = scr_set_DamageThreshold( pstate, pself ); break;
825 case FACCELERATETARGETUP: returncode = scr_AccelerateTargetUp( pstate, pself ); break;
826 case FSETTARGETAMMO: returncode = scr_set_TargetAmmo( pstate, pself ); break;
827 case FENABLEINVICTUS: returncode = scr_EnableInvictus( pstate, pself ); break;
828 case FDISABLEINVICTUS: returncode = scr_DisableInvictus( pstate, pself ); break;
829 case FTARGETDAMAGESELF: returncode = scr_TargetDamageSelf( pstate, pself ); break;
830 case FSETTARGETSIZE: returncode = scr_SetTargetSize( pstate, pself ); break;
831 case FIFTARGETISFACINGSELF: returncode = scr_TargetIsFacingSelf( pstate, pself ); break;
832 case FDRAWBILLBOARD: returncode = scr_DrawBillboard( pstate, pself ); break;
833 case FSETTARGETTOFIRSTBLAHINPASSAGE: returncode = scr_set_TargetToBlahInPassage( pstate, pself ); break;
834
835 case FIFLEVELUP: returncode = scr_LevelUp( pstate, pself ); break;
836 case FGIVESKILLTOTARGET: returncode = scr_GiveSkillToTarget( pstate, pself ); break;
837
838 // if none of the above, skip the line and log an error
839 default:
840 log_message( "SCRIPT ERROR: scr_run_function() - ai script %d - unhandled script function %d\n", pself->type, valuecode );
841 returncode = bfalse;
842 break;
843 }
844
845 }
846 PROFILE_END2( script_function );
847
848 _script_function_calls[valuecode] += 1;
849 _script_function_times[valuecode] += clktime_script_function;
850 }
851
852 return returncode;
853 }
854
855 //--------------------------------------------------------------------------------------------
scr_set_operand(script_state_t * pstate,Uint8 variable)856 void scr_set_operand( script_state_t * pstate, Uint8 variable )
857 {
858 /// @details ZZ@> This function sets one of the tmp* values for scripted AI
859 switch ( variable )
860 {
861 case VARTMPX:
862 pstate->x = pstate->operationsum;
863 break;
864
865 case VARTMPY:
866 pstate->y = pstate->operationsum;
867 break;
868
869 case VARTMPDISTANCE:
870 pstate->distance = pstate->operationsum;
871 break;
872
873 case VARTMPTURN:
874 pstate->turn = pstate->operationsum;
875 break;
876
877 case VARTMPARGUMENT:
878 pstate->argument = pstate->operationsum;
879 break;
880
881 default:
882 log_warning( "scr_set_operand() - cannot assign a number to index %d", variable );
883 break;
884 }
885 }
886
887 //--------------------------------------------------------------------------------------------
scr_run_operand(script_state_t * pstate,ai_state_t * pself)888 void scr_run_operand( script_state_t * pstate, ai_state_t * pself )
889 {
890 /// @details ZZ@> This function does the scripted arithmetic in OPERATOR, OPERAND pairs
891
892 const char * varname, * op;
893
894 STRING buffer = EMPTY_CSTR;
895 Uint8 variable;
896 Uint8 operation;
897
898 Uint32 iTmp;
899
900 chr_t * pchr = NULL, * ptarget = NULL, * powner = NULL;
901
902 if ( !DEFINED_CHR( pself->index ) ) return;
903 pchr = ChrList.lst + pself->index;
904
905 if ( DEFINED_CHR( pself->target ) )
906 {
907 ptarget = ChrList.lst + pself->target;
908 }
909
910 if ( DEFINED_CHR( pself->owner ) )
911 {
912 powner = ChrList.lst + pself->owner;
913 }
914
915 // get the operator
916 iTmp = 0;
917 varname = buffer;
918 operation = GET_DATA_BITS( pself->opcode );
919 if ( HAS_SOME_BITS( pself->opcode, FUNCTION_BIT ) )
920 {
921 // Get the working opcode from a constant, constants are all but high 5 bits
922 iTmp = pself->opcode & VALUE_BITS;
923 if ( debug_scripts ) snprintf( buffer, SDL_arraysize( buffer ), "%d", iTmp );
924 }
925 else
926 {
927 // Get the variable opcode from a register
928 variable = pself->opcode & VALUE_BITS;
929
930 switch ( variable )
931 {
932 case VARTMPX:
933 varname = "TMPX";
934 iTmp = pstate->x;
935 break;
936
937 case VARTMPY:
938 varname = "TMPY";
939 iTmp = pstate->y;
940 break;
941
942 case VARTMPDISTANCE:
943 varname = "TMPDISTANCE";
944 iTmp = pstate->distance;
945 break;
946
947 case VARTMPTURN:
948 varname = "TMPTURN";
949 iTmp = pstate->turn;
950 break;
951
952 case VARTMPARGUMENT:
953 varname = "TMPARGUMENT";
954 iTmp = pstate->argument;
955 break;
956
957 case VARRAND:
958 varname = "RAND";
959 iTmp = RANDIE;
960 break;
961
962 case VARSELFX:
963 varname = "SELFX";
964 iTmp = pchr->pos.x;
965 break;
966
967 case VARSELFY:
968 varname = "SELFY";
969 iTmp = pchr->pos.y;
970 break;
971
972 case VARSELFTURN:
973 varname = "SELFTURN";
974 iTmp = pchr->ori.facing_z;
975 break;
976
977 case VARSELFCOUNTER:
978 varname = "SELFCOUNTER";
979 iTmp = pself->order_counter;
980 break;
981
982 case VARSELFORDER:
983 varname = "SELFORDER";
984 iTmp = pself->order_value;
985 break;
986
987 case VARSELFMORALE:
988 varname = "SELFMORALE";
989 iTmp = TeamStack.lst[pchr->baseteam].morale;
990 break;
991
992 case VARSELFLIFE:
993 varname = "SELFLIFE";
994 iTmp = pchr->life;
995 break;
996
997 case VARTARGETX:
998 varname = "TARGETX";
999 iTmp = ( NULL == ptarget ) ? 0 : ptarget->pos.x;
1000 break;
1001
1002 case VARTARGETY:
1003 varname = "TARGETY";
1004 iTmp = ( NULL == ptarget ) ? 0 : ptarget->pos.y;
1005 break;
1006
1007 case VARTARGETDISTANCE:
1008 varname = "TARGETDISTANCE";
1009 if ( NULL == ptarget )
1010 {
1011 iTmp = 0x7FFFFFFF;
1012 }
1013 else
1014 {
1015 iTmp = ABS( ptarget->pos.x - pchr->pos.x ) + ABS( ptarget->pos.y - pchr->pos.y );
1016 }
1017 break;
1018
1019 case VARTARGETTURN:
1020 varname = "TARGETTURN";
1021 iTmp = ( NULL == ptarget ) ? 0 : ptarget->ori.facing_z;
1022 break;
1023
1024 case VARLEADERX:
1025 varname = "LEADERX";
1026 iTmp = pchr->pos.x;
1027 if ( TeamStack.lst[pchr->team].leader != NOLEADER )
1028 iTmp = team_get_pleader( pchr->team )->pos.x;
1029
1030 break;
1031
1032 case VARLEADERY:
1033 varname = "LEADERY";
1034 iTmp = pchr->pos.y;
1035 if ( TeamStack.lst[pchr->team].leader != NOLEADER )
1036 iTmp = team_get_pleader( pchr->team )->pos.y;
1037
1038 break;
1039
1040 case VARLEADERDISTANCE:
1041 {
1042 chr_t * pleader;
1043 varname = "LEADERDISTANCE";
1044
1045 pleader = team_get_pleader( pchr->team );
1046
1047 if ( NULL == pleader )
1048 {
1049 iTmp = 0x7FFFFFFF;
1050 }
1051 else
1052 {
1053 iTmp = ABS( pleader->pos.x - pchr->pos.x ) + ABS( pleader->pos.y - pchr->pos.y );
1054 }
1055 }
1056 break;
1057
1058 case VARLEADERTURN:
1059 varname = "LEADERTURN";
1060 iTmp = pchr->ori.facing_z;
1061 if ( TeamStack.lst[pchr->team].leader != NOLEADER )
1062 iTmp = team_get_pleader( pchr->team )->ori.facing_z;
1063
1064 break;
1065
1066 case VARGOTOX:
1067 varname = "GOTOX";
1068
1069 ai_state_ensure_wp( pself );
1070
1071 if ( !pself->wp_valid )
1072 {
1073 iTmp = pchr->pos.x;
1074 }
1075 else
1076 {
1077 iTmp = pself->wp[kX];
1078 }
1079 break;
1080
1081 case VARGOTOY:
1082 varname = "GOTOY";
1083
1084 ai_state_ensure_wp( pself );
1085
1086 if ( !pself->wp_valid )
1087 {
1088 iTmp = pchr->pos.y;
1089 }
1090 else
1091 {
1092 iTmp = pself->wp[kY];
1093 }
1094 break;
1095
1096 case VARGOTODISTANCE:
1097 varname = "GOTODISTANCE";
1098
1099 ai_state_ensure_wp( pself );
1100
1101 if ( !pself->wp_valid )
1102 {
1103 iTmp = 0x7FFFFFFF;
1104 }
1105 else
1106 {
1107 iTmp = ABS( pself->wp[kX] - pchr->pos.x ) +
1108 ABS( pself->wp[kY] - pchr->pos.y );
1109 }
1110 break;
1111
1112 case VARTARGETTURNTO:
1113 varname = "TARGETTURNTO";
1114 if ( NULL == ptarget )
1115 {
1116 iTmp = 0;
1117 }
1118 else
1119 {
1120 iTmp = vec_to_facing( ptarget->pos.x - pchr->pos.x , ptarget->pos.y - pchr->pos.y );
1121 iTmp = CLIP_TO_16BITS( iTmp );
1122 }
1123 break;
1124
1125 case VARPASSAGE:
1126 varname = "PASSAGE";
1127 iTmp = pself->passage;
1128 break;
1129
1130 case VARWEIGHT:
1131 varname = "WEIGHT";
1132 iTmp = pchr->holdingweight;
1133 break;
1134
1135 case VARSELFALTITUDE:
1136 varname = "SELFALTITUDE";
1137 iTmp = pchr->pos.z - pchr->enviro.floor_level;
1138 break;
1139
1140 case VARSELFID:
1141 varname = "SELFID";
1142 iTmp = chr_get_idsz( pself->index, IDSZ_TYPE );
1143 break;
1144
1145 case VARSELFHATEID:
1146 varname = "SELFHATEID";
1147 iTmp = chr_get_idsz( pself->index, IDSZ_HATE );
1148 break;
1149
1150 case VARSELFMANA:
1151 varname = "SELFMANA";
1152 iTmp = pchr->mana;
1153 if ( pchr->canchannel ) iTmp += pchr->life;
1154
1155 break;
1156
1157 case VARTARGETSTR:
1158 varname = "TARGETSTR";
1159 iTmp = ( NULL == ptarget ) ? 0 : ptarget->strength;
1160 break;
1161
1162 case VARTARGETWIS:
1163 varname = "TARGETWIS";
1164 iTmp = ( NULL == ptarget ) ? 0 : ptarget->wisdom;
1165 break;
1166
1167 case VARTARGETINT:
1168 varname = "TARGETINT";
1169 iTmp = ( NULL == ptarget ) ? 0 : ptarget->intelligence;
1170 break;
1171
1172 case VARTARGETDEX:
1173 varname = "TARGETDEX";
1174 iTmp = ( NULL == ptarget ) ? 0 : ptarget->dexterity;
1175 break;
1176
1177 case VARTARGETLIFE:
1178 varname = "TARGETLIFE";
1179 iTmp = ( NULL == ptarget ) ? 0 : ptarget->life;
1180 break;
1181
1182 case VARTARGETMANA:
1183 varname = "TARGETMANA";
1184 if ( NULL == ptarget )
1185 {
1186 iTmp = 0;
1187 }
1188 else
1189 {
1190 iTmp = ptarget->mana;
1191 if ( ptarget->canchannel ) iTmp += ptarget->life;
1192 }
1193
1194 break;
1195
1196 case VARTARGETLEVEL:
1197 varname = "TARGETLEVEL";
1198 iTmp = ( NULL == ptarget ) ? 0 : ptarget->experiencelevel;
1199 break;
1200
1201 case VARTARGETSPEEDX:
1202 varname = "TARGETSPEEDX";
1203 iTmp = ( NULL == ptarget ) ? 0 : ABS( ptarget->vel.x );
1204 break;
1205
1206 case VARTARGETSPEEDY:
1207 varname = "TARGETSPEEDY";
1208 iTmp = ( NULL == ptarget ) ? 0 : ABS( ptarget->vel.y );
1209 break;
1210
1211 case VARTARGETSPEEDZ:
1212 varname = "TARGETSPEEDZ";
1213 iTmp = ( NULL == ptarget ) ? 0 : ABS( ptarget->vel.z );
1214 break;
1215
1216 case VARSELFSPAWNX:
1217 varname = "SELFSPAWNX";
1218 iTmp = pchr->pos_stt.x;
1219 break;
1220
1221 case VARSELFSPAWNY:
1222 varname = "SELFSPAWNY";
1223 iTmp = pchr->pos_stt.y;
1224 break;
1225
1226 case VARSELFSTATE:
1227 varname = "SELFSTATE";
1228 iTmp = pself->state;
1229 break;
1230
1231 case VARSELFCONTENT:
1232 varname = "SELFCONTENT";
1233 iTmp = pself->content;
1234 break;
1235
1236 case VARSELFSTR:
1237 varname = "SELFSTR";
1238 iTmp = pchr->strength;
1239 break;
1240
1241 case VARSELFWIS:
1242 varname = "SELFWIS";
1243 iTmp = pchr->wisdom;
1244 break;
1245
1246 case VARSELFINT:
1247 varname = "SELFINT";
1248 iTmp = pchr->intelligence;
1249 break;
1250
1251 case VARSELFDEX:
1252 varname = "SELFDEX";
1253 iTmp = pchr->dexterity;
1254 break;
1255
1256 case VARSELFMANAFLOW:
1257 varname = "SELFMANAFLOW";
1258 iTmp = pchr->manaflow;
1259 break;
1260
1261 case VARTARGETMANAFLOW:
1262 varname = "TARGETMANAFLOW";
1263 iTmp = ( NULL == ptarget ) ? 0 : ptarget->manaflow;
1264 break;
1265
1266 case VARSELFATTACHED:
1267 varname = "SELFATTACHED";
1268 iTmp = number_of_attached_particles( pself->index );
1269 break;
1270
1271 case VARSWINGTURN:
1272 varname = "SWINGTURN";
1273 iTmp = PCamera->swing << 2;
1274 break;
1275
1276 case VARXYDISTANCE:
1277 varname = "XYDISTANCE";
1278 iTmp = SQRT( pstate->x * pstate->x + pstate->y * pstate->y );
1279 break;
1280
1281 case VARSELFZ:
1282 varname = "SELFZ";
1283 iTmp = pchr->pos.z;
1284 break;
1285
1286 case VARTARGETALTITUDE:
1287 varname = "TARGETALTITUDE";
1288 iTmp = ( NULL == ptarget ) ? 0 : ptarget->pos.z - ptarget->enviro.floor_level;
1289 break;
1290
1291 case VARTARGETZ:
1292 varname = "TARGETZ";
1293 iTmp = ( NULL == ptarget ) ? 0 : ptarget->pos.z;
1294 break;
1295
1296 case VARSELFINDEX:
1297 varname = "SELFINDEX";
1298 iTmp = REF_TO_INT( pself->index );
1299 break;
1300
1301 case VAROWNERX:
1302 varname = "OWNERX";
1303 iTmp = ( NULL == powner ) ? 0 : powner->pos.x;
1304 break;
1305
1306 case VAROWNERY:
1307 varname = "OWNERY";
1308 iTmp = ( NULL == powner ) ? 0 : powner->pos.y;
1309 break;
1310
1311 case VAROWNERTURN:
1312 varname = "OWNERTURN";
1313 iTmp = ( NULL == powner ) ? 0 : powner->ori.facing_z;
1314 break;
1315
1316 case VAROWNERDISTANCE:
1317 varname = "OWNERDISTANCE";
1318 if ( NULL == powner )
1319 {
1320 iTmp = 0x7FFFFFFF;
1321 }
1322 else
1323 {
1324 iTmp = ABS( powner->pos.x - pchr->pos.x ) + ABS( powner->pos.y - pchr->pos.y );
1325 }
1326 break;
1327
1328 case VAROWNERTURNTO:
1329 varname = "OWNERTURNTO";
1330 if ( NULL == powner )
1331 {
1332 iTmp = 0;
1333 }
1334 else
1335 {
1336 iTmp = vec_to_facing( powner->pos.x - pchr->pos.x , powner->pos.y - pchr->pos.y );
1337 iTmp = CLIP_TO_16BITS( iTmp );
1338 }
1339 break;
1340
1341 case VARXYTURNTO:
1342 varname = "XYTURNTO";
1343 iTmp = vec_to_facing( pstate->x - pchr->pos.x , pstate->y - pchr->pos.y );
1344 iTmp = CLIP_TO_16BITS( iTmp );
1345 break;
1346
1347 case VARSELFMONEY:
1348 varname = "SELFMONEY";
1349 iTmp = pchr->money;
1350 break;
1351
1352 case VARSELFACCEL:
1353 varname = "SELFACCEL";
1354 iTmp = ( pchr->maxaccel_reset * 100.0f );
1355 break;
1356
1357 case VARTARGETEXP:
1358 varname = "TARGETEXP";
1359 iTmp = ( NULL == ptarget ) ? 0 : ptarget->experience;
1360 break;
1361
1362 case VARSELFAMMO:
1363 varname = "SELFAMMO";
1364 iTmp = pchr->ammo;
1365 break;
1366
1367 case VARTARGETAMMO:
1368 varname = "TARGETAMMO";
1369 iTmp = ( NULL == ptarget ) ? 0 : ptarget->ammo;
1370 break;
1371
1372 case VARTARGETMONEY:
1373 varname = "TARGETMONEY";
1374 iTmp = ( NULL == ptarget ) ? 0 : ptarget->money;
1375 break;
1376
1377 case VARTARGETTURNAWAY:
1378 varname = "TARGETTURNAWAY";
1379 if ( NULL == ptarget )
1380 {
1381 iTmp = 0;
1382 }
1383 else
1384 {
1385 iTmp = vec_to_facing( ptarget->pos.x - pchr->pos.x , ptarget->pos.y - pchr->pos.y );
1386 iTmp = CLIP_TO_16BITS( iTmp );
1387 }
1388 break;
1389
1390 case VARSELFLEVEL:
1391 varname = "SELFLEVEL";
1392 iTmp = pchr->experiencelevel;
1393 break;
1394
1395 case VARTARGETRELOADTIME:
1396 varname = "TARGETRELOADTIME";
1397 iTmp = ( NULL == ptarget ) ? 0 : ptarget->reload_timer;
1398 break;
1399
1400 case VARSPAWNDISTANCE:
1401 varname = "SPAWNDISTANCE";
1402 iTmp = ABS( pchr->pos_stt.x - pchr->pos.x ) + ABS( pchr->pos_stt.y - pchr->pos.y );
1403 break;
1404
1405 case VARTARGETMAXLIFE:
1406 varname = "TARGETMAXLIFE";
1407 iTmp = ( NULL == ptarget ) ? 0 : ptarget->lifemax;
1408 break;
1409
1410 case VARTARGETTEAM:
1411 varname = "TARGETTEAM";
1412 iTmp = ( NULL == ptarget ) ? 0 : ptarget->team;
1413 //iTmp = REF_TO_INT( chr_get_iteam( pself->target ) );
1414 break;
1415
1416 case VARTARGETARMOR:
1417 varname = "TARGETARMOR";
1418 iTmp = ( NULL == ptarget ) ? 0 : ptarget->skin;
1419 break;
1420
1421 case VARDIFFICULTY:
1422 varname = "DIFFICULTY";
1423 iTmp = cfg.difficulty;
1424 break;
1425
1426 case VARTIMEHOURS:
1427 varname = "TIMEHOURS";
1428 iTmp = getCurrentTime()->tm_hour;
1429 break;
1430
1431 case VARTIMEMINUTES:
1432 varname = "TIMEMINUTES";
1433 iTmp = getCurrentTime()->tm_min;
1434 break;
1435
1436 case VARTIMESECONDS:
1437 varname = "TIMESECONDS";
1438 iTmp = getCurrentTime()->tm_sec;
1439 break;
1440
1441 case VARDATEMONTH:
1442 varname = "DATEMONTH";
1443 iTmp = getCurrentTime()->tm_mon + 1;
1444 break;
1445
1446 case VARDATEDAY:
1447 varname = "DATEDAY";
1448 iTmp = getCurrentTime()->tm_mday;
1449 break;
1450
1451 default:
1452 log_message( "SCRIPT ERROR: scr_run_operand() - model == %d, class name == \"%s\" - Unknown variable found!\n", REF_TO_INT( script_error_model ), script_error_classname );
1453 break;
1454 }
1455 }
1456
1457 // Now do the math
1458 op = "UNKNOWN";
1459 switch ( operation )
1460 {
1461 case OPADD:
1462 op = "ADD";
1463 pstate->operationsum += iTmp;
1464 break;
1465
1466 case OPSUB:
1467 op = "SUB";
1468 pstate->operationsum -= iTmp;
1469 break;
1470
1471 case OPAND:
1472 op = "AND";
1473 pstate->operationsum &= iTmp;
1474 break;
1475
1476 case OPSHR:
1477 op = "SHR";
1478 pstate->operationsum >>= iTmp;
1479 break;
1480
1481 case OPSHL:
1482 op = "SHL";
1483 pstate->operationsum <<= iTmp;
1484 break;
1485
1486 case OPMUL:
1487 op = "MUL";
1488 pstate->operationsum *= iTmp;
1489 break;
1490
1491 case OPDIV:
1492 op = "DIV";
1493 if ( iTmp != 0 )
1494 {
1495 pstate->operationsum = (( float )pstate->operationsum ) / iTmp;
1496 }
1497 else
1498 {
1499 log_message( "SCRIPT ERROR: scr_run_operand() - model == %d, class name == \"%s\" - Cannot divide by zero!\n", REF_TO_INT( script_error_model ), script_error_classname );
1500 }
1501 break;
1502
1503 case OPMOD:
1504 op = "MOD";
1505 if ( iTmp != 0 )
1506 {
1507 pstate->operationsum %= iTmp;
1508 }
1509 else
1510 {
1511 log_message( "SCRIPT ERROR: scr_run_operand() - model == %d, class name == \"%s\" - Cannot modulo by zero!\n", REF_TO_INT( script_error_model ), script_error_classname );
1512 }
1513 break;
1514
1515 default:
1516 log_message( "SCRIPT ERROR: scr_run_operand() - model == %d, class name == \"%s\" - unknown op\n", REF_TO_INT( script_error_model ), script_error_classname );
1517 break;
1518 }
1519
1520 if ( debug_scripts )
1521 {
1522 FILE * scr_file = ( NULL == debug_script_file ) ? stdout : debug_script_file;
1523 fprintf( scr_file, "%s %s(%d) ", op, varname, iTmp );
1524 }
1525 }
1526
scr_increment_exe(ai_state_t * pself)1527 bool_t scr_increment_exe( ai_state_t * pself )
1528 {
1529 if ( NULL == pself ) return bfalse;
1530 if ( pself->exe_pos < pself->exe_stt || pself->exe_pos >= pself->exe_end ) return bfalse;
1531
1532 pself->exe_pos++;
1533 pself->opcode = AisCompiled_buffer[pself->exe_pos];
1534
1535 return btrue;
1536 }
1537
1538 //--------------------------------------------------------------------------------------------
scr_set_exe(ai_state_t * pself,size_t offset)1539 bool_t scr_set_exe( ai_state_t * pself, size_t offset )
1540 {
1541 if ( NULL == pself ) return bfalse;
1542 if ( offset < pself->exe_stt || offset >= pself->exe_end ) return bfalse;
1543
1544 pself->exe_pos = offset;
1545 pself->opcode = AisCompiled_buffer[pself->exe_pos];
1546
1547 return btrue;
1548 }
1549
1550 //--------------------------------------------------------------------------------------------
1551 //--------------------------------------------------------------------------------------------
waypoint_list_peek(waypoint_list_t * plst,waypoint_t wp)1552 bool_t waypoint_list_peek( waypoint_list_t * plst, waypoint_t wp )
1553 {
1554 int index;
1555
1556 // is the list valid?
1557 if ( NULL == plst || plst->tail >= MAXWAY ) return bfalse;
1558
1559 // is the list is empty?
1560 if ( 0 == plst->head ) return bfalse;
1561
1562 if ( plst->tail > plst->head )
1563 {
1564 // fix the tail
1565 plst->tail = plst->head;
1566
1567 // we have passed the last waypoint
1568 // just tell them the previous waypoint
1569 index = plst->tail - 1;
1570 }
1571 else if ( plst->tail == plst->head )
1572 {
1573 // we have passed the last waypoint
1574 // just tell them the previous waypoint
1575 index = plst->tail - 1;
1576 }
1577 else
1578 {
1579 // tell them the current waypoint
1580 index = plst->tail;
1581 }
1582
1583 wp[kX] = plst->pos[index][kX];
1584 wp[kY] = plst->pos[index][kY];
1585 wp[kZ] = plst->pos[index][kZ];
1586
1587 return btrue;
1588 }
1589
1590 //--------------------------------------------------------------------------------------------
waypoint_list_push(waypoint_list_t * plst,int x,int y)1591 bool_t waypoint_list_push( waypoint_list_t * plst, int x, int y )
1592 {
1593 /// @details BB@> Add a waypoint to the waypoint list
1594
1595 if ( NULL == plst ) return bfalse;
1596
1597 // add the value
1598 plst->pos[plst->head][kX] = x;
1599 plst->pos[plst->head][kY] = y;
1600 plst->pos[plst->head][kZ] = 0;
1601
1602 // do not let the list overflow
1603 plst->head++;
1604 if ( plst->head >= MAXWAY ) plst->head = MAXWAY - 1;
1605
1606 return btrue;
1607 }
1608
1609 //--------------------------------------------------------------------------------------------
waypoint_list_reset(waypoint_list_t * plst)1610 bool_t waypoint_list_reset( waypoint_list_t * plst )
1611 {
1612 /// @details BB@> reset the waypoint list to the beginning
1613
1614 if ( NULL == plst ) return bfalse;
1615
1616 plst->tail = 0;
1617
1618 return btrue;
1619 }
1620
1621 //--------------------------------------------------------------------------------------------
waypoint_list_clear(waypoint_list_t * plst)1622 bool_t waypoint_list_clear( waypoint_list_t * plst )
1623 {
1624 /// @details BB@> Clear out all waypoints
1625
1626 if ( NULL == plst ) return bfalse;
1627
1628 plst->tail = 0;
1629 plst->head = 0;
1630
1631 return btrue;
1632 }
1633
1634 //--------------------------------------------------------------------------------------------
waypoint_list_empty(waypoint_list_t * plst)1635 bool_t waypoint_list_empty( waypoint_list_t * plst )
1636 {
1637 if ( NULL == plst ) return btrue;
1638
1639 return 0 == plst->head;
1640 }
1641
1642 //--------------------------------------------------------------------------------------------
waypoint_list_finished(waypoint_list_t * plst)1643 bool_t waypoint_list_finished( waypoint_list_t * plst )
1644 {
1645 if ( NULL == plst || 0 == plst->head ) return btrue;
1646
1647 return plst->tail == plst->head;
1648 }
1649
1650 //--------------------------------------------------------------------------------------------
waypoint_list_advance(waypoint_list_t * plst)1651 bool_t waypoint_list_advance( waypoint_list_t * plst )
1652 {
1653 bool_t retval;
1654
1655 if ( NULL == plst ) return bfalse;
1656
1657 retval = bfalse;
1658 if ( plst->tail > plst->head )
1659 {
1660 // fix the tail
1661 plst->tail = plst->head;
1662 }
1663 else if ( plst->tail < plst->head )
1664 {
1665 // advance the tail
1666 plst->tail++;
1667 retval = btrue;
1668 }
1669
1670 // clamp the tail to valid values
1671 if ( plst->tail >= MAXWAY ) plst->tail = MAXWAY - 1;
1672
1673 return retval;
1674 }
1675
1676 //--------------------------------------------------------------------------------------------
ai_state_get_wp(ai_state_t * pself)1677 bool_t ai_state_get_wp( ai_state_t * pself )
1678 {
1679 // try to load up the top waypoint
1680
1681 if ( NULL == pself || !INGAME_CHR( pself->index ) ) return bfalse;
1682
1683 pself->wp_valid = waypoint_list_peek( &( pself->wp_lst ), pself->wp );
1684
1685 return btrue;
1686 }
1687
1688 //--------------------------------------------------------------------------------------------
ai_state_ensure_wp(ai_state_t * pself)1689 bool_t ai_state_ensure_wp( ai_state_t * pself )
1690 {
1691 // is the current waypoint is not valid, try to load up the top waypoint
1692
1693 if ( NULL == pself || !INGAME_CHR( pself->index ) ) return bfalse;
1694
1695 if ( pself->wp_valid ) return btrue;
1696
1697 return ai_state_get_wp( pself );
1698 }
1699
1700 //--------------------------------------------------------------------------------------------
1701 //--------------------------------------------------------------------------------------------
set_alerts(const CHR_REF character)1702 void set_alerts( const CHR_REF character )
1703 {
1704 /// @details ZZ@> This function polls some alert conditions
1705
1706 chr_t * pchr;
1707 ai_state_t * pai;
1708 bool_t at_waypoint;
1709
1710 // invalid characters do not think
1711 if ( !INGAME_CHR( character ) ) return;
1712 pchr = ChrList.lst + character;
1713 pai = chr_get_pai( character );
1714
1715 if ( waypoint_list_empty( &( pai->wp_lst ) ) ) return;
1716
1717 // let's let mounts get alert updates...
1718 // imagine a mount, like a racecar, that needs to make sure that it follows X
1719 // waypoints around a track or something
1720
1721 // mounts do not get alerts
1722 // if ( INGAME_CHR(pchr->attachedto) ) return;
1723
1724 // is the current waypoint is not valid, try to load up the top waypoint
1725 ai_state_ensure_wp( pai );
1726
1727 at_waypoint = bfalse;
1728 if ( pai->wp_valid )
1729 {
1730 at_waypoint = ( ABS( pchr->pos.x - pai->wp[kX] ) < WAYTHRESH ) &&
1731 ( ABS( pchr->pos.y - pai->wp[kY] ) < WAYTHRESH );
1732 }
1733
1734 if ( at_waypoint )
1735 {
1736 SET_BIT( pai->alert, ALERTIF_ATWAYPOINT );
1737
1738 if ( waypoint_list_finished( &( pai->wp_lst ) ) )
1739 {
1740 // we are now at the last waypoint
1741 // if the object can be alerted to last waypoint, do it
1742 // this test needs to be done because the ALERTIF_ATLASTWAYPOINT
1743 // doubles for "at last waypoint" and "not put away"
1744 if ( !chr_get_pcap( character )->isequipment )
1745 {
1746 SET_BIT( pai->alert, ALERTIF_ATLASTWAYPOINT );
1747 }
1748
1749 // !!!!restart the waypoint list, do not clear them!!!!
1750 waypoint_list_reset( &( pai->wp_lst ) );
1751
1752 // load the top waypoint
1753 ai_state_get_wp( pai );
1754 }
1755 else if ( waypoint_list_advance( &( pai->wp_lst ) ) )
1756 {
1757 // load the top waypoint
1758 ai_state_get_wp( pai );
1759 }
1760 }
1761 }
1762
1763 //--------------------------------------------------------------------------------------------
issue_order(const CHR_REF character,Uint32 value)1764 void issue_order( const CHR_REF character, Uint32 value )
1765 {
1766 /// @details ZZ@> This function issues an value for help to all teammates
1767
1768 CHR_REF cnt;
1769 int counter;
1770
1771 for ( cnt = 0, counter = 0; cnt < MAX_CHR; cnt++ )
1772 {
1773 if ( !INGAME_CHR( cnt ) ) continue;
1774
1775 if ( chr_get_iteam( cnt ) == chr_get_iteam( character ) )
1776 {
1777 ai_add_order( chr_get_pai( cnt ), value, counter );
1778 counter++;
1779 }
1780 }
1781 }
1782
1783 //--------------------------------------------------------------------------------------------
issue_special_order(Uint32 value,IDSZ idsz)1784 void issue_special_order( Uint32 value, IDSZ idsz )
1785 {
1786 /// @details ZZ@> This function issues an order to all characters with the a matching special IDSZ
1787
1788 CHR_REF cnt;
1789 int counter;
1790
1791 for ( cnt = 0, counter = 0; cnt < MAX_CHR; cnt++ )
1792 {
1793 cap_t * pcap;
1794
1795 if ( !INGAME_CHR( cnt ) ) continue;
1796
1797 pcap = chr_get_pcap( cnt );
1798 if ( NULL == pcap ) continue;
1799
1800 if ( idsz == pcap->idsz[IDSZ_SPECIAL] )
1801 {
1802 ai_add_order( chr_get_pai( cnt ), value, counter );
1803 counter++;
1804 }
1805 }
1806 }
1807
1808 //--------------------------------------------------------------------------------------------
1809 //--------------------------------------------------------------------------------------------
ai_state_free(ai_state_t * pself)1810 bool_t ai_state_free( ai_state_t * pself )
1811 {
1812 if ( NULL == pself ) return bfalse;
1813
1814 // free any allocated data
1815 PROFILE_FREE_STRUCT( pself );
1816
1817 return btrue;
1818 };
1819
1820 //--------------------------------------------------------------------------------------------
ai_state_reconstruct(ai_state_t * pself)1821 ai_state_t * ai_state_reconstruct( ai_state_t * pself )
1822 {
1823 if ( NULL == pself ) return pself;
1824
1825 // deallocate any existing data
1826 ai_state_free( pself );
1827
1828 // set everything to safe values
1829 memset( pself, 0, sizeof( *pself ) );
1830
1831 pself->index = ( CHR_REF )MAX_CHR;
1832 pself->target = ( CHR_REF )MAX_CHR;
1833 pself->owner = ( CHR_REF )MAX_CHR;
1834 pself->child = ( CHR_REF )MAX_CHR;
1835 pself->target_old = ( CHR_REF )MAX_CHR;
1836 pself->poof_time = -1;
1837
1838 pself->bumplast = ( CHR_REF )MAX_CHR;
1839 pself->attacklast = ( CHR_REF )MAX_CHR;
1840 pself->hitlast = ( CHR_REF )MAX_CHR;
1841
1842 return pself;
1843 }
1844
1845 //--------------------------------------------------------------------------------------------
ai_state_ctor(ai_state_t * pself)1846 ai_state_t * ai_state_ctor( ai_state_t * pself )
1847 {
1848 if ( NULL == ai_state_reconstruct( pself ) ) return NULL;
1849
1850 PROFILE_INIT_STRUCT( ai, pself );
1851
1852 return pself;
1853 }
1854
1855 //--------------------------------------------------------------------------------------------
ai_state_dtor(ai_state_t * pself)1856 ai_state_t * ai_state_dtor( ai_state_t * pself )
1857 {
1858 if ( NULL == pself ) return pself;
1859
1860 // initialize the object
1861 ai_state_reconstruct( pself );
1862
1863 return pself;
1864 }
1865
1866