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_functions.c
21 /// @brief implementation of the internal egoscript functions
22 /// @details These are the c-functions that are called to implement the egoscript commsnds
23 /// At some pont, the non-trivial commands in this file will be broken out to discrete functions
24 /// and wrapped by some external language (like Lua) using something like SWIG, and a cross compiler written.
25 /// The current code is about 3/4 of the way toward this goal.
26 /// The functions below will then be replaced with stub calls to the "real" functions.
27 
28 #include "script_functions.h"
29 
30 #include "profile.inl"
31 #include "enchant.inl"
32 #include "char.inl"
33 #include "particle.inl"
34 #include "mad.h"
35 #include "mesh.inl"
36 
37 #include "link.h"
38 #include "camera.h"
39 #include "passage.h"
40 #include "graphic.h"
41 #include "input.h"
42 #include "network.h"
43 #include "game.h"
44 #include "log.h"
45 
46 #include "spawn_file.h"
47 #include "quest.h"
48 
49 #include "egoboo_math.h"
50 #include "egoboo_strutil.h"
51 #include "egoboo_setup.h"
52 #include "egoboo_math.inl"
53 
54 //--------------------------------------------------------------------------------------------
55 //--------------------------------------------------------------------------------------------
56 // turn off this annoying warning
57 #if defined _MSC_VER
58 #    pragma warning(disable : 4189) // local variable is initialized but not referenced
59 #endif
60 
61 #define SCRIPT_FUNCTION_BEGIN() \
62     chr_t * pchr; \
63     pro_t * ppro; \
64     Uint8 returncode = btrue; \
65     if( NULL == pstate || NULL == pself || !ALLOCATED_CHR(pself->index) ) return bfalse; \
66     pchr = ChrList.lst + pself->index; \
67     if( !LOADED_PRO(pchr->profile_ref) ) return bfalse; \
68     ppro = ProList.lst + pchr->profile_ref;
69 
70 #define SCRIPT_FUNCTION_END() \
71     return returncode;
72 
73 #define FUNCTION_BEGIN() \
74     Uint8 returncode = btrue; \
75     if( !ALLOCATED_PCHR( pchr ) ) return bfalse;
76 
77 #define FUNCTION_END() \
78     return returncode;
79 
80 #define SET_TARGET_0(ITARGET)         pself->target = ITARGET;
81 #define SET_TARGET_1(ITARGET,PTARGET) if( NULL != PTARGET ) { PTARGET = INGAME_CHR(ITARGET) ? ChrList.lst + ITARGET : NULL; }
82 #define SET_TARGET(ITARGET,PTARGET)   SET_TARGET_0( ITARGET ); SET_TARGET_1(ITARGET,PTARGET)
83 
84 #define SCRIPT_REQUIRE_TARGET(PTARGET) \
85     if( !INGAME_CHR(pself->target) ) return bfalse; \
86     PTARGET = ChrList.lst + pself->target;
87 
88 //--------------------------------------------------------------------------------------------
89 //--------------------------------------------------------------------------------------------
90 
91 /// @defgroup _bitwise_functions_ Bitwise Scripting Functions
92 /// @details These functions may be necessary to export the bitwise functions for handling alerts to
93 ///  scripting languages where there is no support for bitwise operators (Lua, tcl, ...)
94 
95 //--------------------------------------------------------------------------------------------
96 
97 /// @ingroup _bitwise_functions_
scr_set_AlertBit(script_state_t * pstate,ai_state_t * pself)98 Uint8 scr_set_AlertBit( script_state_t * pstate, ai_state_t * pself )
99 {
100     /// @details BB@> Sets the bit in the 32-bit integer self.alert indexed by pstate->argument
101 
102     SCRIPT_FUNCTION_BEGIN();
103 
104     returncode = bfalse;
105     if ( pstate->argument >= 0 && pstate->argument < 32 )
106     {
107         SET_BIT( pself->alert, 1 << pstate->argument );
108         returncode = btrue;
109     }
110 
111     SCRIPT_FUNCTION_END();
112 }
113 
114 //--------------------------------------------------------------------------------------------
115 
116 /// @ingroup _bitwise_functions_
scr_ClearAlertBit(script_state_t * pstate,ai_state_t * pself)117 Uint8 scr_ClearAlertBit( script_state_t * pstate, ai_state_t * pself )
118 {
119     /// @details BB@> Clears the bit in the 32-bit integer self.alert indexed by pstate->argument
120 
121     SCRIPT_FUNCTION_BEGIN();
122 
123     returncode = bfalse;
124     if ( pstate->argument >= 0 && pstate->argument < 32 )
125     {
126         UNSET_BIT( pself->alert, 1 << pstate->argument );
127         returncode = btrue;
128     }
129 
130     SCRIPT_FUNCTION_END();
131 }
132 
133 //--------------------------------------------------------------------------------------------
134 
135 /// @ingroup _bitwise_functions_
scr_TestAlertBit(script_state_t * pstate,ai_state_t * pself)136 Uint8 scr_TestAlertBit( script_state_t * pstate, ai_state_t * pself )
137 {
138     /// @details BB@> Tests to see if the the bit in the 32-bit integer self.alert indexed by pstate->argument is non-zero
139 
140     SCRIPT_FUNCTION_BEGIN();
141 
142     returncode = bfalse;
143     if ( pstate->argument >= 0 && pstate->argument < 32 )
144     {
145         returncode = HAS_SOME_BITS( pself->alert,  1 << pstate->argument );
146     }
147 
148     SCRIPT_FUNCTION_END();
149 }
150 
151 //--------------------------------------------------------------------------------------------
152 
153 /// @ingroup _bitwise_functions_
scr_set_Alert(script_state_t * pstate,ai_state_t * pself)154 Uint8 scr_set_Alert( script_state_t * pstate, ai_state_t * pself )
155 {
156     /// @details BB@> Sets one or more bits of the self.alert variable given by the bitmask in tmpargument
157 
158     SCRIPT_FUNCTION_BEGIN();
159 
160     SET_BIT( pself->alert, pstate->argument );
161 
162     SCRIPT_FUNCTION_END();
163 }
164 
165 //--------------------------------------------------------------------------------------------
166 
167 /// @ingroup _bitwise_functions_
scr_ClearAlert(script_state_t * pstate,ai_state_t * pself)168 Uint8 scr_ClearAlert( script_state_t * pstate, ai_state_t * pself )
169 {
170     /// @details BB@> Clears one or more bits of the self.alert variable given by the bitmask in tmpargument
171 
172     SCRIPT_FUNCTION_BEGIN();
173 
174     UNSET_BIT( pself->alert, pstate->argument );
175 
176     SCRIPT_FUNCTION_END();
177 }
178 
179 //--------------------------------------------------------------------------------------------
180 
181 /// @ingroup _bitwise_functions_
scr_TestAlert(script_state_t * pstate,ai_state_t * pself)182 Uint8 scr_TestAlert( script_state_t * pstate, ai_state_t * pself )
183 {
184     /// @details BB@> Tests one or more bits of the self.alert variable given by the bitmask in tmpargument
185 
186     SCRIPT_FUNCTION_BEGIN();
187 
188     returncode = HAS_SOME_BITS( pself->alert, pstate->argument );
189 
190     SCRIPT_FUNCTION_END();
191 }
192 
193 //--------------------------------------------------------------------------------------------
194 
195 /// @ingroup _bitwise_functions_
scr_set_Bit(script_state_t * pstate,ai_state_t * pself)196 Uint8 scr_set_Bit( script_state_t * pstate, ai_state_t * pself )
197 {
198     /// @details BB@> Sets the bit in the 32-bit tmpx variable with the offset given in tmpy
199 
200     SCRIPT_FUNCTION_BEGIN();
201 
202     returncode = bfalse;
203     if ( pstate->y >= 0 && pstate->y < 32 )
204     {
205         SET_BIT( pstate->x, 1 << pstate->y );
206         returncode = btrue;
207     }
208 
209     SCRIPT_FUNCTION_END();
210 }
211 
212 //--------------------------------------------------------------------------------------------
213 
214 /// @ingroup _bitwise_functions_
scr_ClearBit(script_state_t * pstate,ai_state_t * pself)215 Uint8 scr_ClearBit( script_state_t * pstate, ai_state_t * pself )
216 {
217     /// @details BB@> Clears the bit in the 32-bit tmpx variable with the offset given in tmpy
218 
219     SCRIPT_FUNCTION_BEGIN();
220 
221     returncode = bfalse;
222     if ( pstate->y >= 0 && pstate->y < 32 )
223     {
224         UNSET_BIT( pstate->x, 1 << pstate->y );
225         returncode = btrue;
226     }
227 
228     SCRIPT_FUNCTION_END();
229 }
230 
231 //--------------------------------------------------------------------------------------------
232 
233 /// @ingroup _bitwise_functions_
scr_TestBit(script_state_t * pstate,ai_state_t * pself)234 Uint8 scr_TestBit( script_state_t * pstate, ai_state_t * pself )
235 {
236     /// @details BB@> Tests the bit in the 32-bit tmpx variable with the offset given in tmpy
237 
238     SCRIPT_FUNCTION_BEGIN();
239 
240     returncode = bfalse;
241     if ( pstate->y >= 0 && pstate->y < 32 )
242     {
243         returncode = HAS_SOME_BITS( pstate->x, 1 << pstate->y );
244     }
245 
246     SCRIPT_FUNCTION_END();
247 }
248 
249 //--------------------------------------------------------------------------------------------
250 
251 /// @ingroup _bitwise_functions_
scr_set_Bits(script_state_t * pstate,ai_state_t * pself)252 Uint8 scr_set_Bits( script_state_t * pstate, ai_state_t * pself )
253 {
254     /// @details BB@> Adds the bits in the 32-bit tmpx based on the bitmask in tmpy
255 
256     SCRIPT_FUNCTION_BEGIN();
257 
258     SET_BIT( pstate->x, pstate->y );
259 
260     SCRIPT_FUNCTION_END();
261 }
262 
263 //--------------------------------------------------------------------------------------------
264 
265 /// @ingroup _bitwise_functions_
scr_ClearBits(script_state_t * pstate,ai_state_t * pself)266 Uint8 scr_ClearBits( script_state_t * pstate, ai_state_t * pself )
267 {
268     /// @details BB@> Clears the bits in the 32-bit tmpx based on the bitmask in tmpy
269 
270     SCRIPT_FUNCTION_BEGIN();
271 
272     UNSET_BIT( pstate->x, pstate->y );
273 
274     SCRIPT_FUNCTION_END();
275 }
276 
277 //--------------------------------------------------------------------------------------------
278 
279 /// @ingroup _bitwise_functions_
scr_TestBits(script_state_t * pstate,ai_state_t * pself)280 Uint8 scr_TestBits( script_state_t * pstate, ai_state_t * pself )
281 {
282     /// @details BB@> Tests the bits in the 32-bit tmpx based on the bitmask in tmpy
283 
284     SCRIPT_FUNCTION_BEGIN();
285 
286     returncode = HAS_SOME_BITS( pstate->x, pstate->y );
287 
288     SCRIPT_FUNCTION_END();
289 }
290 
291 //--------------------------------------------------------------------------------------------
292 //--------------------------------------------------------------------------------------------
scr_Spawned(script_state_t * pstate,ai_state_t * pself)293 Uint8 scr_Spawned( script_state_t * pstate, ai_state_t * pself )
294 {
295     // IfSpawned()
296     /// @details ZZ@> This function proceeds if the character was spawned this update
297 
298     SCRIPT_FUNCTION_BEGIN();
299 
300     // Proceed only if it's a new character
301     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_SPAWNED );
302 
303     SCRIPT_FUNCTION_END();
304 }
305 
306 //--------------------------------------------------------------------------------------------
scr_TimeOut(script_state_t * pstate,ai_state_t * pself)307 Uint8 scr_TimeOut( script_state_t * pstate, ai_state_t * pself )
308 {
309     // IfTimeOut()
310     /// @details ZZ@> This function proceeds if the character's aitime is 0.  Use
311     /// in conjunction with set_Time
312 
313     SCRIPT_FUNCTION_BEGIN();
314 
315     // Proceed only if time alert is set
316     returncode = ( update_wld > pself->timer );
317 
318     SCRIPT_FUNCTION_END();
319 }
320 
321 //--------------------------------------------------------------------------------------------
scr_AtWaypoint(script_state_t * pstate,ai_state_t * pself)322 Uint8 scr_AtWaypoint( script_state_t * pstate, ai_state_t * pself )
323 {
324     // IfAtWaypoint()
325     /// @details ZZ@> This function proceeds if the character reached its waypoint this
326     /// update
327 
328     SCRIPT_FUNCTION_BEGIN();
329 
330     // Proceed only if the character reached a waypoint
331     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_ATWAYPOINT );
332 
333     SCRIPT_FUNCTION_END();
334 }
335 
336 //--------------------------------------------------------------------------------------------
scr_AtLastWaypoint(script_state_t * pstate,ai_state_t * pself)337 Uint8 scr_AtLastWaypoint( script_state_t * pstate, ai_state_t * pself )
338 {
339     // IfAtLastWaypoint()
340     /// @details ZZ@> This function proceeds if the character reached its last waypoint this
341     /// update
342 
343     SCRIPT_FUNCTION_BEGIN();
344 
345     // Proceed only if the character reached its last waypoint
346     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_ATLASTWAYPOINT );
347 
348     SCRIPT_FUNCTION_END();
349 }
350 
351 //--------------------------------------------------------------------------------------------
scr_Attacked(script_state_t * pstate,ai_state_t * pself)352 Uint8 scr_Attacked( script_state_t * pstate, ai_state_t * pself )
353 {
354     // IfAttacked()
355     /// @details ZZ@> This function proceeds if the character ( an item ) was put in its
356     /// owner's pocket this update
357 
358     SCRIPT_FUNCTION_BEGIN();
359 
360     // Proceed only if the character was damaged
361     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_ATTACKED );
362 
363     SCRIPT_FUNCTION_END();
364 }
365 
366 //--------------------------------------------------------------------------------------------
scr_Bumped(script_state_t * pstate,ai_state_t * pself)367 Uint8 scr_Bumped( script_state_t * pstate, ai_state_t * pself )
368 {
369     // IfBumped()
370     /// @details ZZ@> This function proceeds if the character was bumped by another character
371     /// this update
372 
373     SCRIPT_FUNCTION_BEGIN();
374 
375     // Proceed only if the character was bumped
376     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_BUMPED );
377 
378     SCRIPT_FUNCTION_END();
379 }
380 
381 //--------------------------------------------------------------------------------------------
scr_Ordered(script_state_t * pstate,ai_state_t * pself)382 Uint8 scr_Ordered( script_state_t * pstate, ai_state_t * pself )
383 {
384     // IfOrdered()
385     /// @details ZZ@> This function proceeds if the character got an order from another
386     /// character on its team this update
387 
388     SCRIPT_FUNCTION_BEGIN();
389 
390     // Proceed only if the character was ordered
391     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_ORDERED );
392 
393     SCRIPT_FUNCTION_END();
394 }
395 
396 //--------------------------------------------------------------------------------------------
scr_CalledForHelp(script_state_t * pstate,ai_state_t * pself)397 Uint8 scr_CalledForHelp( script_state_t * pstate, ai_state_t * pself )
398 {
399     // IfCalledForHelp()
400     /// @details ZZ@> This function proceeds if one of the character's teammates was nearly
401     /// killed this update
402 
403     SCRIPT_FUNCTION_BEGIN();
404 
405     // Proceed only if the character was called for help
406     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_CALLEDFORHELP );
407 
408     SCRIPT_FUNCTION_END();
409 }
410 
411 //--------------------------------------------------------------------------------------------
scr_set_Content(script_state_t * pstate,ai_state_t * pself)412 Uint8 scr_set_Content( script_state_t * pstate, ai_state_t * pself )
413 {
414     // SetContent( tmpargument )
415     /// @details ZZ@> This function sets the content variable.  Used in conjunction with
416     /// GetContent.  Content is preserved from update to update
417 
418     SCRIPT_FUNCTION_BEGIN();
419 
420     // Set the content
421     pself->content = pstate->argument;
422 
423     SCRIPT_FUNCTION_END();
424 }
425 
426 //--------------------------------------------------------------------------------------------
scr_Killed(script_state_t * pstate,ai_state_t * pself)427 Uint8 scr_Killed( script_state_t * pstate, ai_state_t * pself )
428 {
429     // IfKilled()
430     /// @details ZZ@> This function proceeds if the character was killed this update
431 
432     SCRIPT_FUNCTION_BEGIN();
433 
434     // Proceed only if the character's been killed
435     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_KILLED );
436 
437     SCRIPT_FUNCTION_END();
438 }
439 
440 //--------------------------------------------------------------------------------------------
scr_TargetKilled(script_state_t * pstate,ai_state_t * pself)441 Uint8 scr_TargetKilled( script_state_t * pstate, ai_state_t * pself )
442 {
443     // IfTargetKilled()
444     /// @details ZZ@> This function proceeds if the character's target from last update was
445     /// killed during this update
446 
447     chr_t * pself_target;
448 
449     SCRIPT_FUNCTION_BEGIN();
450 
451     SCRIPT_REQUIRE_TARGET( pself_target );
452 
453     // Proceed only if the character's target has just died or is already dead
454     returncode = ( HAS_SOME_BITS( pself->alert, ALERTIF_TARGETKILLED ) || !pself_target->alive );
455 
456     SCRIPT_FUNCTION_END();
457 }
458 
459 //--------------------------------------------------------------------------------------------
scr_ClearWaypoints(script_state_t * pstate,ai_state_t * pself)460 Uint8 scr_ClearWaypoints( script_state_t * pstate, ai_state_t * pself )
461 {
462     // ClearWaypoints()
463     /// @details ZZ@> This function is used to move a character around.  Do this before
464     /// AddWaypoint
465 
466     SCRIPT_FUNCTION_BEGIN();
467 
468     returncode = waypoint_list_clear( &( pself->wp_lst ) );
469 
470     SCRIPT_FUNCTION_END();
471 }
472 
473 //--------------------------------------------------------------------------------------------
scr_AddWaypoint(script_state_t * pstate,ai_state_t * pself)474 Uint8 scr_AddWaypoint( script_state_t * pstate, ai_state_t * pself )
475 {
476     // AddWaypoint( tmpx = "x position", tmpy = "y position" )
477     /// @details ZZ@> This function tells the character where to move next
478 
479 #if defined(_DEBUG) && defined(DEBUG_WAYPOINTS)
480     fvec2_t pos;
481     fvec3_t nrm;
482     float   pressure;
483 
484     SCRIPT_FUNCTION_BEGIN();
485 
486     // init the vector with the desired position
487     pos.x = pstate->x;
488     pos.y = pstate->y;
489 
490     // is this a safe position?
491     returncode = bfalse;
492 
493     if ( 255 == chr_get_pcap( pself->index )->weight || !mesh_hit_wall( PMesh, pos.v, pchr->bump.size, pchr->stoppedby, nrm.v, &pressure, NULL ) )
494     {
495         // yes it is safe. add it.
496         returncode = waypoint_list_push( &( pself->wp_lst ), pstate->x, pstate->y );
497     }
498     else
499     {
500         cap_t * pcap;
501         // no it is not safe. what to do? nothing, or add the current position?
502         //returncode = waypoint_list_push( &(pself->wp_lst), pchr->pos.x, pchr->pos.y );
503 
504         pcap = chr_get_pcap( GET_REF_PCHR( pchr ) );
505 
506         if ( NULL != pcap )
507         {
508             log_warning( "scr_AddWaypoint() - failed to add a waypoint because object was \"inside\" a wall.\n"
509                          "\tcharacter %d (\"%s\", \"%s\")\n"
510                          "\tWaypoint index %d\n"
511                          "\tWaypoint location (in tiles) <%f,%f>\n"
512                          "\tWall normal <%1.4f,%1.4f>\n"
513                          "\tPressure %f\n",
514                          GET_REF_PCHR( pchr ), pchr->Name, pcap->name,
515                          pself->wp_lst.head,
516                          pos.x / GRID_FSIZE, pos.y / GRID_FSIZE,
517                          nrm.x, nrm.y,
518                          SQRT( pressure ) / GRID_FSIZE );
519         }
520     }
521 #else
522     SCRIPT_FUNCTION_BEGIN();
523     returncode = waypoint_list_push( &( pself->wp_lst ), pstate->x, pstate->y );
524 #endif
525 
526     if ( returncode )
527     {
528         // make sure we update the waypoint, since the list changed
529         ai_state_get_wp( pself );
530     }
531 
532     SCRIPT_FUNCTION_END();
533 }
534 
535 //--------------------------------------------------------------------------------------------
scr_FindPath(script_state_t * pstate,ai_state_t * pself)536 Uint8 scr_FindPath( script_state_t * pstate, ai_state_t * pself )
537 {
538     // FindPath
539     /// @details ZF@> This modifies the eay the character moves relative to its target. There is no pth finding at this time.
540     /// @todo scr_FindPath doesn't really work yet
541 
542     SCRIPT_FUNCTION_BEGIN();
543 
544     // Yep this is it
545     if ( INGAME_CHR( pself->target ) && pself->target != pself->index )
546     {
547         float fx, fy;
548 
549         chr_t * pself_target = ChrList.lst + pself->target;
550 
551         if ( pstate->distance != MOVE_FOLLOW )
552         {
553             fx = pself_target->pos.x;
554             fy = pself_target->pos.y;
555         }
556         else
557         {
558             fx = generate_randmask( -512, 1023 ) + pself_target->pos.x;
559             fy = generate_randmask( -512, 1023 ) + pself_target->pos.y;
560         }
561 
562         pstate->turn = vec_to_facing( fx - pchr->pos.x , fy - pchr->pos.y );
563 
564         if ( pstate->distance == MOVE_RETREAT )
565         {
566             // flip around to the other direction and add in some randomness
567             pstate->turn += ATK_BEHIND + generate_randmask( -8192, 16383 );
568         }
569         pstate->turn = CLIP_TO_16BITS( pstate->turn );
570 
571         if ( pstate->distance == MOVE_CHARGE || pstate->distance == MOVE_RETREAT )
572         {
573             reset_character_accel( pself->index ); // Force 100% speed
574         }
575 
576         // Then add the waypoint
577         returncode = waypoint_list_push( &( pself->wp_lst ), fx, fy );
578 
579         if ( returncode )
580         {
581             // return the new position
582             pstate->x = fx;
583             pstate->y = fy;
584 
585             if ( returncode )
586             {
587                 // make sure we update the waypoint, since the list changed
588                 ai_state_get_wp( pself );
589             }
590         }
591     }
592 
593     SCRIPT_FUNCTION_END();
594 }
595 
596 //--------------------------------------------------------------------------------------------
scr_Compass(script_state_t * pstate,ai_state_t * pself)597 Uint8 scr_Compass( script_state_t * pstate, ai_state_t * pself )
598 {
599     // Compass( tmpturn = "rotation", tmpdistance = "radius" )
600     /// @details ZZ@> This function modifies tmpx and tmpy, depending on the setting of
601     /// tmpdistance and tmpturn.  It acts like one of those Compass thing
602     /// with the two little needle legs
603 
604     TURN_T turn;
605 
606     SCRIPT_FUNCTION_BEGIN();
607 
608     turn = TO_TURN( pstate->turn );
609 
610     pstate->x -= turntocos[ turn ] * pstate->distance;
611     pstate->y -= turntosin[ turn ] * pstate->distance;
612 
613     SCRIPT_FUNCTION_END();
614 }
615 
616 //--------------------------------------------------------------------------------------------
scr_get_TargetArmorPrice(script_state_t * pstate,ai_state_t * pself)617 Uint8 scr_get_TargetArmorPrice( script_state_t * pstate, ai_state_t * pself )
618 {
619     // tmpx = GetTargetArmorPrice( tmpargument = "skin" )
620     /// @details ZZ@> This function returns the cost of the desired skin upgrade, setting
621     /// tmpx to the price
622 
623     Uint16 sTmp = 0;
624     cap_t * pcap;
625 
626     SCRIPT_FUNCTION_BEGIN();
627 
628     pcap = chr_get_pcap( pself->target );
629 
630     returncode = bfalse;
631     if ( NULL != pcap )
632     {
633         sTmp = pstate->argument % MAX_SKIN;
634 
635         pstate->x = pcap->skincost[sTmp];
636         returncode = btrue;
637     }
638 
639     SCRIPT_FUNCTION_END();
640 }
641 
642 //--------------------------------------------------------------------------------------------
scr_set_Time(script_state_t * pstate,ai_state_t * pself)643 Uint8 scr_set_Time( script_state_t * pstate, ai_state_t * pself )
644 {
645     // SetTime( tmpargument = "time" )
646     /// @details ZZ@> This function sets the character's ai timer.  50 clicks per second.
647     /// Used in conjunction with IfTimeOut
648 
649     SCRIPT_FUNCTION_BEGIN();
650 
651     if ( pstate->argument > -1 )
652     {
653         pself->timer = update_wld + pstate->argument;
654     }
655 
656     SCRIPT_FUNCTION_END();
657 }
658 
659 //--------------------------------------------------------------------------------------------
scr_get_Content(script_state_t * pstate,ai_state_t * pself)660 Uint8 scr_get_Content( script_state_t * pstate, ai_state_t * pself )
661 {
662     // tmpargument = GetContent()
663     /// @details ZZ@> This function sets tmpargument to the character's content variable.
664     /// Used in conjunction with set_Content, or as a NOP to space out an Else
665 
666     SCRIPT_FUNCTION_BEGIN();
667 
668     // Get the content
669     pstate->argument = pself->content;
670 
671     SCRIPT_FUNCTION_END();
672 }
673 
674 //--------------------------------------------------------------------------------------------
scr_JoinTargetTeam(script_state_t * pstate,ai_state_t * pself)675 Uint8 scr_JoinTargetTeam( script_state_t * pstate, ai_state_t * pself )
676 {
677     // JoinTargetTeam()
678     /// @details ZZ@> This function lets a character join a different team.  Used
679     /// mostly for pets
680 
681     chr_t * pself_target;
682 
683     SCRIPT_FUNCTION_BEGIN();
684 
685     SCRIPT_REQUIRE_TARGET( pself_target );
686 
687     returncode = bfalse;
688     if ( INGAME_CHR( pself->target ) )
689     {
690         switch_team( pself->index, pself_target->team );
691         returncode = btrue;
692     }
693 
694     SCRIPT_FUNCTION_END();
695 }
696 
697 //--------------------------------------------------------------------------------------------
scr_set_TargetToNearbyEnemy(script_state_t * pstate,ai_state_t * pself)698 Uint8 scr_set_TargetToNearbyEnemy( script_state_t * pstate, ai_state_t * pself )
699 {
700     // SetTargetToNearbyEnemy()
701     /// @details ZZ@> This function sets the target to a nearby enemy, failing if there are none
702 
703     CHR_REF ichr;
704 
705     SCRIPT_FUNCTION_BEGIN();
706 
707     ichr = chr_find_target( pchr, NEARBY, IDSZ_NONE, TARGET_ENEMIES );
708 
709     if ( INGAME_CHR( ichr ) )
710     {
711         SET_TARGET_0( ichr );
712     }
713     else
714     {
715         returncode = bfalse;
716     }
717 
718     SCRIPT_FUNCTION_END();
719 }
720 
721 //--------------------------------------------------------------------------------------------
scr_set_TargetToTargetLeftHand(script_state_t * pstate,ai_state_t * pself)722 Uint8 scr_set_TargetToTargetLeftHand( script_state_t * pstate, ai_state_t * pself )
723 {
724     // SetTargetToTargetLeftHand()
725     /// @details ZZ@> This function sets the target to the item in the target's left hand,
726     /// failing if the target has no left hand item
727 
728     CHR_REF ichr;
729     chr_t * pself_target;
730 
731     SCRIPT_FUNCTION_BEGIN();
732 
733     SCRIPT_REQUIRE_TARGET( pself_target );
734 
735     ichr = pself_target->holdingwhich[SLOT_LEFT];
736     returncode = bfalse;
737     if ( INGAME_CHR( ichr ) )
738     {
739         SET_TARGET( ichr, pself_target );
740         returncode = btrue;
741     }
742 
743     SCRIPT_FUNCTION_END();
744 }
745 
746 //--------------------------------------------------------------------------------------------
scr_set_TargetToTargetRightHand(script_state_t * pstate,ai_state_t * pself)747 Uint8 scr_set_TargetToTargetRightHand( script_state_t * pstate, ai_state_t * pself )
748 {
749     // SetTargetToTargetRightHand()
750     /// @details ZZ@> This function sets the target to the item in the target's right hand,
751     /// failing if the target has no right hand item
752 
753     CHR_REF ichr;
754     chr_t * pself_target;
755 
756     SCRIPT_FUNCTION_BEGIN();
757 
758     SCRIPT_REQUIRE_TARGET( pself_target );
759 
760     ichr = pself_target->holdingwhich[SLOT_RIGHT];
761     returncode = bfalse;
762     if ( INGAME_CHR( ichr ) )
763     {
764         SET_TARGET( ichr, pself_target );
765         returncode = btrue;
766     }
767 
768     SCRIPT_FUNCTION_END();
769 }
770 
771 //--------------------------------------------------------------------------------------------
scr_set_TargetToWhoeverAttacked(script_state_t * pstate,ai_state_t * pself)772 Uint8 scr_set_TargetToWhoeverAttacked( script_state_t * pstate, ai_state_t * pself )
773 {
774     // SetTargetToWhoeverAttacked()
775     /// @details ZZ@> This function sets the target to whoever attacked the character last, failing for damage tiles
776 
777     SCRIPT_FUNCTION_BEGIN();
778 
779     if ( INGAME_CHR( pself->attacklast ) )
780     {
781         SET_TARGET_0( pself->attacklast );
782     }
783     else
784     {
785         returncode = bfalse;
786     }
787 
788     SCRIPT_FUNCTION_END();
789 }
790 
791 //--------------------------------------------------------------------------------------------
scr_set_TargetToWhoeverBumped(script_state_t * pstate,ai_state_t * pself)792 Uint8 scr_set_TargetToWhoeverBumped( script_state_t * pstate, ai_state_t * pself )
793 {
794     // SetTargetToWhoeverBumped()
795     /// @details ZZ@> This function sets the target to whoever bumped the character last. It never fails
796 
797     SCRIPT_FUNCTION_BEGIN();
798 
799     if ( INGAME_CHR( pself->bumplast ) )
800     {
801         SET_TARGET_0( pself->bumplast );
802     }
803     else
804     {
805         returncode = bfalse;
806     }
807 
808     SCRIPT_FUNCTION_END();
809 }
810 
811 //--------------------------------------------------------------------------------------------
scr_set_TargetToWhoeverCalledForHelp(script_state_t * pstate,ai_state_t * pself)812 Uint8 scr_set_TargetToWhoeverCalledForHelp( script_state_t * pstate, ai_state_t * pself )
813 {
814     // SetTargetToWhoeverCalledForHelp()
815     /// @details ZZ@> This function sets the target to whoever called for help last.
816 
817     SCRIPT_FUNCTION_BEGIN();
818 
819     if ( VALID_TEAM_RANGE( pchr->team ) )
820     {
821         CHR_REF isissy = TeamStack.lst[pchr->team].sissy;
822 
823         if ( INGAME_CHR( isissy ) )
824         {
825             SET_TARGET_0( isissy );
826         }
827         else
828         {
829             returncode = bfalse;
830         }
831     }
832     else
833     {
834         returncode = bfalse;
835     }
836 
837     SCRIPT_FUNCTION_END();
838 }
839 
840 //--------------------------------------------------------------------------------------------
scr_set_TargetToOldTarget(script_state_t * pstate,ai_state_t * pself)841 Uint8 scr_set_TargetToOldTarget( script_state_t * pstate, ai_state_t * pself )
842 {
843     // SetTargetToOldTarget()
844     /// @details ZZ@> This function sets the target to the target from last update, used to
845     /// undo other set_Target functions
846 
847     SCRIPT_FUNCTION_BEGIN();
848 
849     if ( INGAME_CHR( pself->target_old ) )
850     {
851         SET_TARGET_0( pself->target_old );
852     }
853     else
854     {
855         returncode = bfalse;
856     }
857 
858     SCRIPT_FUNCTION_END();
859 }
860 
861 //--------------------------------------------------------------------------------------------
scr_set_TurnModeToVelocity(script_state_t * pstate,ai_state_t * pself)862 Uint8 scr_set_TurnModeToVelocity( script_state_t * pstate, ai_state_t * pself )
863 {
864     // SetTurnModeToVelocity()
865     /// @details ZZ@> This function sets the character's movement mode to the default
866 
867     SCRIPT_FUNCTION_BEGIN();
868 
869     pchr->turnmode = TURNMODE_VELOCITY;
870 
871     SCRIPT_FUNCTION_END();
872 }
873 
874 //--------------------------------------------------------------------------------------------
scr_set_TurnModeToWatch(script_state_t * pstate,ai_state_t * pself)875 Uint8 scr_set_TurnModeToWatch( script_state_t * pstate, ai_state_t * pself )
876 {
877     // SetTurnModeToWatch()
878     /// @details ZZ@> This function makes the character look at its next waypoint, usually
879     /// used with close waypoints or the Stop function
880 
881     SCRIPT_FUNCTION_BEGIN();
882 
883     pchr->turnmode = TURNMODE_WATCH;
884 
885     SCRIPT_FUNCTION_END();
886 }
887 
888 //--------------------------------------------------------------------------------------------
scr_set_TurnModeToSpin(script_state_t * pstate,ai_state_t * pself)889 Uint8 scr_set_TurnModeToSpin( script_state_t * pstate, ai_state_t * pself )
890 {
891     // SetTurnModeToSpin()
892     /// @details ZZ@> This function makes the character spin around in a circle, usually
893     /// used for magical items and such
894 
895     SCRIPT_FUNCTION_BEGIN();
896 
897     pchr->turnmode = TURNMODE_SPIN;
898 
899     SCRIPT_FUNCTION_END();
900 }
901 
902 //--------------------------------------------------------------------------------------------
scr_set_BumpHeight(script_state_t * pstate,ai_state_t * pself)903 Uint8 scr_set_BumpHeight( script_state_t * pstate, ai_state_t * pself )
904 {
905     // SetBumpHeight( tmpargument = "height" )
906     /// @details ZZ@> This function makes the character taller or shorter, usually used when
907     /// the character dies
908 
909     SCRIPT_FUNCTION_BEGIN();
910 
911     chr_set_height( pchr, pstate->argument );
912 
913     SCRIPT_FUNCTION_END();
914 }
915 
916 //--------------------------------------------------------------------------------------------
scr_TargetHasID(script_state_t * pstate,ai_state_t * pself)917 Uint8 scr_TargetHasID( script_state_t * pstate, ai_state_t * pself )
918 {
919     // IfTargetHasID( tmpargument = "idsz" )
920     /// @details ZZ@> This function proceeds if the target has either a parent or type IDSZ
921     /// matching tmpargument.
922 
923     SCRIPT_FUNCTION_BEGIN();
924 
925     returncode = chr_is_type_idsz( pself->target, pstate->argument );
926 
927     SCRIPT_FUNCTION_END();
928 }
929 
930 //--------------------------------------------------------------------------------------------
scr_TargetHasItemID(script_state_t * pstate,ai_state_t * pself)931 Uint8 scr_TargetHasItemID( script_state_t * pstate, ai_state_t * pself )
932 {
933     // IfTargetHasItemID( tmpargument = "idsz" )
934     /// @details ZZ@> This function proceeds if the target has a matching item in his/her
935     /// pockets or hands.
936 
937     CHR_REF item;
938 
939     SCRIPT_FUNCTION_BEGIN();
940 
941     item = chr_has_item_idsz( pself->target, ( IDSZ ) pstate->argument, bfalse, NULL );
942 
943     returncode = INGAME_CHR( item );
944 
945     SCRIPT_FUNCTION_END();
946 }
947 
948 //--------------------------------------------------------------------------------------------
scr_TargetHoldingItemID(script_state_t * pstate,ai_state_t * pself)949 Uint8 scr_TargetHoldingItemID( script_state_t * pstate, ai_state_t * pself )
950 {
951     // IfTargetHoldingItemID( tmpargument = "idsz" )
952     /// @details ZZ@> This function proceeds if the target has a matching item in his/her
953     /// hands.  It also sets tmpargument to the proper latch button to press
954     /// to use that item
955 
956     CHR_REF item;
957 
958     SCRIPT_FUNCTION_BEGIN();
959 
960     item = chr_holding_idsz( pself->target, pstate->argument );
961 
962     returncode = INGAME_CHR( item );
963 
964     SCRIPT_FUNCTION_END();
965 }
966 
967 //--------------------------------------------------------------------------------------------
scr_TargetHasSkillID(script_state_t * pstate,ai_state_t * pself)968 Uint8 scr_TargetHasSkillID( script_state_t * pstate, ai_state_t * pself )
969 {
970     // IfTargetHasSkillID( tmpargument = "skill idsz" )
971     /// @details ZZ@> This function proceeds if ID matches tmpargument
972 
973     chr_t *pself_target;
974 
975     SCRIPT_FUNCTION_BEGIN();
976 
977     SCRIPT_REQUIRE_TARGET( pself_target );
978 
979     returncode = ( 0 != chr_get_skill( pself_target, ( IDSZ )pstate->argument ) );
980 
981     SCRIPT_FUNCTION_END();
982 }
983 
984 //--------------------------------------------------------------------------------------------
scr_Else(script_state_t * pstate,ai_state_t * pself)985 Uint8 scr_Else( script_state_t * pstate, ai_state_t * pself )
986 {
987     // Else
988     /// @details ZZ@> This function fails if the last function was more indented
989 
990     SCRIPT_FUNCTION_BEGIN();
991 
992     returncode = ( pself->indent >= pself->indent_last );
993 
994     SCRIPT_FUNCTION_END();
995 }
996 
997 //--------------------------------------------------------------------------------------------
scr_Run(script_state_t * pstate,ai_state_t * pself)998 Uint8 scr_Run( script_state_t * pstate, ai_state_t * pself )
999 {
1000     // Run()
1001     /// @details ZZ@> This function sets the character's maximum acceleration to its
1002     /// actual maximum
1003 
1004     SCRIPT_FUNCTION_BEGIN();
1005 
1006     reset_character_accel( pself->index );
1007 
1008     SCRIPT_FUNCTION_END();
1009 }
1010 
1011 //--------------------------------------------------------------------------------------------
scr_Walk(script_state_t * pstate,ai_state_t * pself)1012 Uint8 scr_Walk( script_state_t * pstate, ai_state_t * pself )
1013 {
1014     // Walk()
1015     /// @details ZZ@> This function sets the character's maximum acceleration to 66%
1016     /// of its actual maximum
1017 
1018     SCRIPT_FUNCTION_BEGIN();
1019 
1020     reset_character_accel( pself->index );
1021 
1022     pchr->maxaccel      = pchr->maxaccel_reset * 0.66f;
1023     pchr->movement_bits = CHR_MOVEMENT_BITS_WALK;
1024 
1025     SCRIPT_FUNCTION_END();
1026 }
1027 
1028 //--------------------------------------------------------------------------------------------
scr_Sneak(script_state_t * pstate,ai_state_t * pself)1029 Uint8 scr_Sneak( script_state_t * pstate, ai_state_t * pself )
1030 {
1031     // Sneak()
1032     /// @details ZZ@> This function sets the character's maximum acceleration to 33%
1033     /// of its actual maximum
1034 
1035     SCRIPT_FUNCTION_BEGIN();
1036 
1037     reset_character_accel( pself->index );
1038 
1039     pchr->maxaccel      = pchr->maxaccel_reset * 0.33f;
1040     pchr->movement_bits = CHR_MOVEMENT_BITS_SNEAK | CHR_MOVEMENT_BITS_STOP;
1041 
1042     SCRIPT_FUNCTION_END();
1043 }
1044 
1045 //--------------------------------------------------------------------------------------------
scr_DoAction(script_state_t * pstate,ai_state_t * pself)1046 Uint8 scr_DoAction( script_state_t * pstate, ai_state_t * pself )
1047 {
1048     // DoAction( tmpargument = "action" )
1049     /// @details ZZ@> This function makes the character do a given action if it isn't doing
1050     /// anything better.  Fails if the action is invalid or if the character is doing
1051     /// something else already
1052 
1053     int action;
1054 
1055     SCRIPT_FUNCTION_BEGIN();
1056 
1057     action = mad_get_action_ref( pchr->inst.imad, pstate->argument );
1058 
1059     returncode = bfalse;
1060     if ( rv_success == chr_start_anim( pchr, action, bfalse, bfalse ) )
1061     {
1062         returncode = btrue;
1063     }
1064 
1065     SCRIPT_FUNCTION_END();
1066 }
1067 
1068 //--------------------------------------------------------------------------------------------
scr_KeepAction(script_state_t * pstate,ai_state_t * pself)1069 Uint8 scr_KeepAction( script_state_t * pstate, ai_state_t * pself )
1070 {
1071     // KeepAction()
1072     /// @details ZZ@> This function makes the character's animation stop on its last frame
1073     /// and stay there.  Usually used for dropped items
1074 
1075     SCRIPT_FUNCTION_BEGIN();
1076 
1077     chr_instance_set_action_keep( &( pchr->inst ), btrue );
1078 
1079     SCRIPT_FUNCTION_END();
1080 }
1081 
1082 //--------------------------------------------------------------------------------------------
scr_IssueOrder(script_state_t * pstate,ai_state_t * pself)1083 Uint8 scr_IssueOrder( script_state_t * pstate, ai_state_t * pself )
1084 {
1085     // IssueOrder( tmpargument = "order"  )
1086     /// @details ZZ@> This function tells all of the character's teammates to do something,
1087     /// though each teammate needs to interpret the order using IfOrdered in
1088     /// its own script.
1089 
1090     SCRIPT_FUNCTION_BEGIN();
1091 
1092     issue_order( pself->index, pstate->argument );
1093 
1094     SCRIPT_FUNCTION_END();
1095 }
1096 
1097 //--------------------------------------------------------------------------------------------
scr_DropWeapons(script_state_t * pstate,ai_state_t * pself)1098 Uint8 scr_DropWeapons( script_state_t * pstate, ai_state_t * pself )
1099 {
1100     // DropWeapons()
1101     /// @details ZZ@> This function drops the character's in-hand items.  It will also
1102     /// buck the rider if the character is a mount
1103 
1104     CHR_REF ichr;
1105 
1106     SCRIPT_FUNCTION_BEGIN();
1107 
1108     // This funtion drops the character's in hand items/riders
1109     ichr = pchr->holdingwhich[SLOT_LEFT];
1110     if ( INGAME_CHR( ichr ) )
1111     {
1112         detach_character_from_mount( ichr, btrue, btrue );
1113         if ( pchr->ismount )
1114         {
1115             fvec3_t tmp_pos;
1116 
1117             ChrList.lst[ichr].vel.z    = DISMOUNTZVEL;
1118             ChrList.lst[ichr].jump_timer = JUMPDELAY;
1119 
1120             tmp_pos = chr_get_pos( ChrList.lst + ichr );
1121             tmp_pos.z += DISMOUNTZVEL;
1122             chr_set_pos( ChrList.lst + ichr, tmp_pos.v );
1123         }
1124     }
1125 
1126     ichr = pchr->holdingwhich[SLOT_RIGHT];
1127     if ( INGAME_CHR( ichr ) )
1128     {
1129         detach_character_from_mount( ichr, btrue, btrue );
1130         if ( pchr->ismount )
1131         {
1132             fvec3_t tmp_pos;
1133 
1134             ChrList.lst[ichr].vel.z    = DISMOUNTZVEL;
1135             ChrList.lst[ichr].jump_timer = JUMPDELAY;
1136 
1137             tmp_pos = chr_get_pos( ChrList.lst + ichr );
1138             tmp_pos.z += DISMOUNTZVEL;
1139             chr_set_pos( ChrList.lst + ichr, tmp_pos.v );
1140         }
1141     }
1142 
1143     SCRIPT_FUNCTION_END();
1144 }
1145 
1146 //--------------------------------------------------------------------------------------------
scr_TargetDoAction(script_state_t * pstate,ai_state_t * pself)1147 Uint8 scr_TargetDoAction( script_state_t * pstate, ai_state_t * pself )
1148 {
1149     // TargetDoAction( tmpargument = "action" )
1150     /// @details ZZ@> The function makes the target start a new action, if it is valid for the model
1151     /// It will fail if the action is invalid or if the target is doing
1152     /// something else already
1153 
1154     SCRIPT_FUNCTION_BEGIN();
1155 
1156     returncode = bfalse;
1157     if ( INGAME_CHR( pself->target ) )
1158     {
1159         chr_t * pself_target = ChrList.lst + pself->target;
1160 
1161         if ( pself_target->alive )
1162         {
1163             int action = mad_get_action_ref( pself_target->inst.imad, pstate->argument );
1164 
1165             if ( rv_success == chr_start_anim( pself_target, action, bfalse, bfalse ) )
1166             {
1167                 returncode = btrue;
1168             }
1169         }
1170     }
1171 
1172     SCRIPT_FUNCTION_END();
1173 }
1174 
1175 //--------------------------------------------------------------------------------------------
scr_OpenPassage(script_state_t * pstate,ai_state_t * pself)1176 Uint8 scr_OpenPassage( script_state_t * pstate, ai_state_t * pself )
1177 {
1178     // OpenPassage( tmpargument = "passage" )
1179 
1180     /// @details ZZ@> This function opens the passage specified by tmpargument, failing if the
1181     /// passage was already open.
1182     /// Passage areas are defined in passage.txt and set in spawn.txt for the given character
1183 
1184     SCRIPT_FUNCTION_BEGIN();
1185 
1186     returncode = open_passage(( PASS_REF )pstate->argument );
1187 
1188     SCRIPT_FUNCTION_END();
1189 }
1190 
1191 //--------------------------------------------------------------------------------------------
scr_ClosePassage(script_state_t * pstate,ai_state_t * pself)1192 Uint8 scr_ClosePassage( script_state_t * pstate, ai_state_t * pself )
1193 {
1194     // ClosePassage( tmpargument = "passage" )
1195     /// @details ZZ@> This function closes the passage specified by tmpargument, proceeding
1196     /// if the passage isn't blocked.  Crushable characters within the passage
1197     /// are crushed.
1198 
1199     SCRIPT_FUNCTION_BEGIN();
1200 
1201     returncode = close_passage(( PASS_REF )pstate->argument );
1202 
1203     SCRIPT_FUNCTION_END();
1204 }
1205 
1206 //--------------------------------------------------------------------------------------------
scr_PassageOpen(script_state_t * pstate,ai_state_t * pself)1207 Uint8 scr_PassageOpen( script_state_t * pstate, ai_state_t * pself )
1208 {
1209     // IfPassageOpen( tmpargument = "passage" )
1210     /// @details ZZ@> This function proceeds if the given passage is valid and open to movement
1211     /// Used mostly by door characters to tell them when to run their open animation.
1212 
1213     SCRIPT_FUNCTION_BEGIN();
1214 
1215     returncode = bfalse;
1216     if ( pstate->argument >= 0 && pstate->argument < MAX_PASS )
1217     {
1218         PASS_REF ipass = ( PASS_REF )pstate->argument;
1219 
1220         returncode = PassageStack.lst[ipass].open;
1221     }
1222 
1223     SCRIPT_FUNCTION_END();
1224 }
1225 
1226 //--------------------------------------------------------------------------------------------
scr_GoPoof(script_state_t * pstate,ai_state_t * pself)1227 Uint8 scr_GoPoof( script_state_t * pstate, ai_state_t * pself )
1228 {
1229     // GoPoof()
1230     /// @details ZZ@> This function flags the character to be removed from the game entirely.
1231     /// This doesn't work on players
1232 
1233     SCRIPT_FUNCTION_BEGIN();
1234 
1235     returncode = bfalse;
1236     if ( !VALID_PLA( pchr->is_which_player ) )
1237     {
1238         returncode = btrue;
1239         pself->poof_time = update_wld;
1240     }
1241 
1242     SCRIPT_FUNCTION_END();
1243 }
1244 
1245 //--------------------------------------------------------------------------------------------
scr_CostTargetItemID(script_state_t * pstate,ai_state_t * pself)1246 Uint8 scr_CostTargetItemID( script_state_t * pstate, ai_state_t * pself )
1247 {
1248     // CostTargetItemID( tmpargument = "idsz" )
1249     /// @details ZZ@> This function proceeds if the target has a matching item, and poofs
1250     /// that item.
1251     /// For one use keys and such
1252 
1253     CHR_REF item, pack_last, ichr;
1254 
1255     SCRIPT_FUNCTION_BEGIN();
1256 
1257     ichr = pself->target;
1258     item = chr_has_item_idsz( ichr, ( IDSZ ) pstate->argument, bfalse, &pack_last );
1259 
1260     returncode = bfalse;
1261     if ( INGAME_CHR( item ) )
1262     {
1263         returncode = btrue;
1264 
1265         if ( ChrList.lst[item].ammo > 1 )
1266         {
1267             // Cost one ammo
1268             ChrList.lst[item].ammo--;
1269         }
1270         else
1271         {
1272             // Poof the item
1273             if ( INGAME_CHR( pack_last ) && ChrList.lst[item].pack.is_packed )
1274             {
1275                 // Remove from the pack
1276                 ChrList.lst[pack_last].pack.next = ChrList.lst[item].pack.next;
1277                 ChrList.lst[ichr].pack.count--;
1278 
1279                 ChrList.lst[item].pack.was_packed = ChrList.lst[item].pack.is_packed;
1280                 ChrList.lst[item].pack.is_packed  = bfalse;
1281                 ChrList.lst[item].pack.next       = ( CHR_REF )MAX_CHR;
1282             }
1283             else if ( INGAME_CHR( pack_last ) && !ChrList.lst[item].pack.is_packed )
1284             {
1285                 // this is corrupt data == trouble
1286                 // treat it as the normal case. if it causes errors, we'll fix them later
1287                 ChrList.lst[pack_last].pack.next = ChrList.lst[item].pack.next;
1288                 ChrList.lst[ichr].pack.count--;
1289 
1290                 ChrList.lst[item].pack.was_packed = ChrList.lst[item].pack.is_packed;
1291                 ChrList.lst[item].pack.is_packed  = bfalse;
1292                 ChrList.lst[item].pack.next       = ( CHR_REF )MAX_CHR;
1293             }
1294             else
1295             {
1296                 // Drop from hand
1297                 detach_character_from_mount( item, btrue, bfalse );
1298             }
1299 
1300             // get rid of the character, no matter what
1301             chr_request_terminate( item );
1302         }
1303     }
1304 
1305     SCRIPT_FUNCTION_END();
1306 }
1307 
1308 //--------------------------------------------------------------------------------------------
scr_DoActionOverride(script_state_t * pstate,ai_state_t * pself)1309 Uint8 scr_DoActionOverride( script_state_t * pstate, ai_state_t * pself )
1310 {
1311     // DoActionOverride( tmpargument = "action" )
1312     /// @details ZZ@> This function makes the character do a given action no matter what
1313     /// It will fail if the action is invalid
1314 
1315     int action;
1316 
1317     SCRIPT_FUNCTION_BEGIN();
1318 
1319     action = mad_get_action_ref( pchr->inst.imad, pstate->argument );
1320 
1321     returncode = bfalse;
1322     if ( rv_success == chr_start_anim( pchr, action, bfalse, btrue ) )
1323     {
1324         returncode = btrue;
1325     }
1326 
1327     SCRIPT_FUNCTION_END();
1328 }
1329 
1330 //--------------------------------------------------------------------------------------------
scr_Healed(script_state_t * pstate,ai_state_t * pself)1331 Uint8 scr_Healed( script_state_t * pstate, ai_state_t * pself )
1332 {
1333     // IfHealed()
1334     /// @details ZZ@> This function proceeds if the character was healed by a healing particle
1335 
1336     SCRIPT_FUNCTION_BEGIN();
1337 
1338     // Proceed only if the character was healed
1339     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_HEALED );
1340 
1341     SCRIPT_FUNCTION_END();
1342 }
1343 
1344 //--------------------------------------------------------------------------------------------
scr_SendPlayerMessage(script_state_t * pstate,ai_state_t * pself)1345 Uint8 scr_SendPlayerMessage( script_state_t * pstate, ai_state_t * pself )
1346 {
1347     // SendPlayerMessage( tmpargument = "message number" )
1348     /// @details ZZ@> This function sends a message to the players
1349 
1350     SCRIPT_FUNCTION_BEGIN();
1351 
1352     returncode = _display_message( pself->index, pchr->profile_ref, pstate->argument, pstate );
1353 
1354     SCRIPT_FUNCTION_END();
1355 }
1356 
1357 //--------------------------------------------------------------------------------------------
scr_CallForHelp(script_state_t * pstate,ai_state_t * pself)1358 Uint8 scr_CallForHelp( script_state_t * pstate, ai_state_t * pself )
1359 {
1360     // CallForHelp()
1361     /// @details ZZ@> This function calls all of the character's teammates for help.  The
1362     /// teammates must use IfCalledForHelp in their scripts
1363 
1364     SCRIPT_FUNCTION_BEGIN();
1365 
1366     call_for_help( pself->index );
1367 
1368     SCRIPT_FUNCTION_END();
1369 }
1370 
1371 //--------------------------------------------------------------------------------------------
scr_AddIDSZ(script_state_t * pstate,ai_state_t * pself)1372 Uint8 scr_AddIDSZ( script_state_t * pstate, ai_state_t * pself )
1373 {
1374     // AddIDSZ( tmpargument = "idsz" )
1375     /// @details ZZ@> This function slaps an expansion IDSZ onto the menu.txt file.
1376     /// Used to show completion of special quests for a given module
1377 
1378     SCRIPT_FUNCTION_BEGIN();
1379 
1380     module_add_idsz_vfs( pickedmodule_name, pstate->argument, 0, NULL );
1381 
1382     SCRIPT_FUNCTION_END();
1383 }
1384 
1385 //--------------------------------------------------------------------------------------------
scr_set_State(script_state_t * pstate,ai_state_t * pself)1386 Uint8 scr_set_State( script_state_t * pstate, ai_state_t * pself )
1387 {
1388     // SetState( tmpargument = "state" )
1389     /// @details ZZ@> This function sets the character's state.
1390     /// VERY IMPORTANT. State is preserved from update to update
1391 
1392     SCRIPT_FUNCTION_BEGIN();
1393 
1394     // set the state - this function updates the is_hidden
1395     chr_set_ai_state( pchr, pstate->argument );
1396 
1397     SCRIPT_FUNCTION_END();
1398 }
1399 
1400 //--------------------------------------------------------------------------------------------
scr_get_State(script_state_t * pstate,ai_state_t * pself)1401 Uint8 scr_get_State( script_state_t * pstate, ai_state_t * pself )
1402 {
1403     // tmpargument = GetState()
1404     /// @details ZZ@> This function reads the character's state variable
1405 
1406     SCRIPT_FUNCTION_BEGIN();
1407 
1408     pstate->argument = pself->state;
1409 
1410     SCRIPT_FUNCTION_END();
1411 }
1412 
1413 //--------------------------------------------------------------------------------------------
scr_StateIs(script_state_t * pstate,ai_state_t * pself)1414 Uint8 scr_StateIs( script_state_t * pstate, ai_state_t * pself )
1415 {
1416     // IfStateIs( tmpargument = "state" )
1417     /// @details ZZ@> This function proceeds if the character's state equals tmpargument
1418 
1419     SCRIPT_FUNCTION_BEGIN();
1420 
1421     returncode = ( pstate->argument == pself->state );
1422 
1423     SCRIPT_FUNCTION_END();
1424 }
1425 
1426 //--------------------------------------------------------------------------------------------
scr_TargetCanOpenStuff(script_state_t * pstate,ai_state_t * pself)1427 Uint8 scr_TargetCanOpenStuff( script_state_t * pstate, ai_state_t * pself )
1428 {
1429     // IfTargetCanOpenStuff()
1430     /// @details ZZ@> This function proceeds if the target can open stuff ( set in data.txt )
1431     /// Used by chests and buttons and such so only "smart" creatures can operate
1432     /// them
1433 
1434     chr_t * pself_target;
1435 
1436     SCRIPT_FUNCTION_BEGIN();
1437     returncode = bfalse;
1438 
1439     SCRIPT_REQUIRE_TARGET( pself_target );
1440 
1441     if ( pself_target->ismount )
1442     {
1443         CHR_REF iheld = pself_target->holdingwhich[SLOT_LEFT];
1444 
1445         if ( DEFINED_CHR( iheld ) )
1446         {
1447             // can the rider open the
1448             returncode = ChrList.lst[iheld].openstuff;
1449         }
1450     }
1451 
1452     if ( !returncode )
1453     {
1454         // if a rider can't openstuff, can the target openstuff?
1455         returncode = pself_target->openstuff;
1456     }
1457 
1458     SCRIPT_FUNCTION_END();
1459 }
1460 
1461 //--------------------------------------------------------------------------------------------
scr_Grabbed(script_state_t * pstate,ai_state_t * pself)1462 Uint8 scr_Grabbed( script_state_t * pstate, ai_state_t * pself )
1463 {
1464     // IfGrabbed()
1465     /// @details ZZ@> This function proceeds if the character was grabbed (picked up) this update.
1466     /// Used mostly by item characters
1467 
1468     SCRIPT_FUNCTION_BEGIN();
1469 
1470     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_GRABBED );
1471 
1472     SCRIPT_FUNCTION_END();
1473 }
1474 
1475 //--------------------------------------------------------------------------------------------
scr_Dropped(script_state_t * pstate,ai_state_t * pself)1476 Uint8 scr_Dropped( script_state_t * pstate, ai_state_t * pself )
1477 {
1478     // IfDropped()
1479     /// @details ZZ@> This function proceeds if the character was dropped this update.
1480     /// Used mostly by item characters
1481 
1482     SCRIPT_FUNCTION_BEGIN();
1483 
1484     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_DROPPED );
1485 
1486     SCRIPT_FUNCTION_END();
1487 }
1488 
1489 //--------------------------------------------------------------------------------------------
scr_set_TargetToWhoeverIsHolding(script_state_t * pstate,ai_state_t * pself)1490 Uint8 scr_set_TargetToWhoeverIsHolding( script_state_t * pstate, ai_state_t * pself )
1491 {
1492     // SetTargetToWhoeverIsHolding()
1493     /// @details ZZ@> This function sets the target to the character's holder or mount,
1494     /// failing if the character has no mount or holder
1495 
1496     SCRIPT_FUNCTION_BEGIN();
1497 
1498     if ( INGAME_CHR( pchr->attachedto ) )
1499     {
1500         SET_TARGET_0( pchr->attachedto );
1501     }
1502     else
1503     {
1504         returncode = bfalse;
1505     }
1506 
1507     SCRIPT_FUNCTION_END();
1508 }
1509 
1510 //--------------------------------------------------------------------------------------------
scr_DamageTarget(script_state_t * pstate,ai_state_t * pself)1511 Uint8 scr_DamageTarget( script_state_t * pstate, ai_state_t * pself )
1512 {
1513     // DamageTarget( tmpargument = "damage" )
1514     /// @details ZZ@> This function applies little bit of love to the character's target.
1515     /// The amount is set in tmpargument
1516 
1517     IPair tmp_damage;
1518 
1519     SCRIPT_FUNCTION_BEGIN();
1520 
1521     tmp_damage.base = pstate->argument;
1522     tmp_damage.rand = 1;
1523 
1524     damage_character( pself->target, ATK_FRONT, tmp_damage, pchr->damagetarget_damagetype, pchr->team, pself->index, DAMFX_NBLOC, btrue );
1525 
1526     SCRIPT_FUNCTION_END();
1527 }
1528 
1529 //--------------------------------------------------------------------------------------------
scr_XIsLessThanY(script_state_t * pstate,ai_state_t * pself)1530 Uint8 scr_XIsLessThanY( script_state_t * pstate, ai_state_t * pself )
1531 {
1532     // IfXIsLessThanY( tmpx, tmpy )
1533     /// @details ZZ@> This function proceeds if tmpx is less than tmpy.
1534 
1535     SCRIPT_FUNCTION_BEGIN();
1536 
1537     returncode = ( pstate->x < pstate->y );
1538 
1539     SCRIPT_FUNCTION_END();
1540 }
1541 
1542 //--------------------------------------------------------------------------------------------
scr_set_WeatherTime(script_state_t * pstate,ai_state_t * pself)1543 Uint8 scr_set_WeatherTime( script_state_t * pstate, ai_state_t * pself )
1544 {
1545     // SetWeatherTime( tmpargument = "time" )
1546     /// @details ZZ@> This function can be used to slow down or speed up or stop rain and
1547     /// other weather effects
1548 
1549     SCRIPT_FUNCTION_BEGIN();
1550 
1551     // Set the weather timer
1552     weather.timer_reset = pstate->argument;
1553     weather.time = pstate->argument;
1554 
1555     SCRIPT_FUNCTION_END();
1556 }
1557 
1558 //--------------------------------------------------------------------------------------------
scr_get_BumpHeight(script_state_t * pstate,ai_state_t * pself)1559 Uint8 scr_get_BumpHeight( script_state_t * pstate, ai_state_t * pself )
1560 {
1561     // tmpargument = GetBumpHeight()
1562     /// @details ZZ@> This function sets tmpargument to the character's height
1563 
1564     SCRIPT_FUNCTION_BEGIN();
1565 
1566     pstate->argument = pchr->bump.height;
1567 
1568     SCRIPT_FUNCTION_END();
1569 }
1570 
1571 //--------------------------------------------------------------------------------------------
scr_Reaffirmed(script_state_t * pstate,ai_state_t * pself)1572 Uint8 scr_Reaffirmed( script_state_t * pstate, ai_state_t * pself )
1573 {
1574     // IfReaffirmed()
1575     /// @details ZZ@> This function proceeds if the character was damaged by its reaffirm
1576     /// damage type.  Used to relight the torch.
1577 
1578     SCRIPT_FUNCTION_BEGIN();
1579 
1580     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_REAFFIRMED );
1581 
1582     SCRIPT_FUNCTION_END();
1583 }
1584 
1585 //--------------------------------------------------------------------------------------------
scr_UnkeepAction(script_state_t * pstate,ai_state_t * pself)1586 Uint8 scr_UnkeepAction( script_state_t * pstate, ai_state_t * pself )
1587 {
1588     // UnkeepAction()
1589     /// @details ZZ@> This function is the opposite of KeepAction. It makes the current animation resume.
1590 
1591     SCRIPT_FUNCTION_BEGIN();
1592 
1593     chr_instance_set_action_keep( &( pchr->inst ), bfalse );
1594 
1595     SCRIPT_FUNCTION_END();
1596 }
1597 
1598 //--------------------------------------------------------------------------------------------
scr_TargetIsOnOtherTeam(script_state_t * pstate,ai_state_t * pself)1599 Uint8 scr_TargetIsOnOtherTeam( script_state_t * pstate, ai_state_t * pself )
1600 {
1601     // IfTargetIsOnOtherTeam()
1602     /// @details ZZ@> This function proceeds if the target is on another team
1603 
1604     chr_t * pself_target;
1605 
1606     SCRIPT_FUNCTION_BEGIN();
1607 
1608     SCRIPT_REQUIRE_TARGET( pself_target );
1609 
1610     returncode = ( pself_target->alive && chr_get_iteam( pself->target ) != pchr->team );
1611 
1612     SCRIPT_FUNCTION_END();
1613 }
1614 
1615 //--------------------------------------------------------------------------------------------
scr_TargetIsOnHatedTeam(script_state_t * pstate,ai_state_t * pself)1616 Uint8 scr_TargetIsOnHatedTeam( script_state_t * pstate, ai_state_t * pself )
1617 {
1618     // IfTargetIsOnHatedTeam()
1619     /// @details ZZ@> This function proceeds if the target is on an enemy team
1620 
1621     chr_t * pself_target;
1622 
1623     SCRIPT_FUNCTION_BEGIN();
1624 
1625     SCRIPT_REQUIRE_TARGET( pself_target );
1626 
1627     returncode = ( pself_target->alive && team_hates_team( pchr->team, chr_get_iteam( pself->target ) ) && !pself_target->invictus );
1628 
1629     SCRIPT_FUNCTION_END();
1630 }
1631 
1632 //--------------------------------------------------------------------------------------------
scr_PressLatchButton(script_state_t * pstate,ai_state_t * pself)1633 Uint8 scr_PressLatchButton( script_state_t * pstate, ai_state_t * pself )
1634 {
1635     // PressLatchButton( tmpargument = "latch bits" )
1636     /// @details ZZ@> This function sets the character latch buttons
1637 
1638     SCRIPT_FUNCTION_BEGIN();
1639 
1640     pchr->latch.b = pchr->latch.b | pstate->argument;
1641 
1642     SCRIPT_FUNCTION_END();
1643 }
1644 
1645 //--------------------------------------------------------------------------------------------
scr_set_TargetToTargetOfLeader(script_state_t * pstate,ai_state_t * pself)1646 Uint8 scr_set_TargetToTargetOfLeader( script_state_t * pstate, ai_state_t * pself )
1647 {
1648     // SetTargetToTargetOfLeader()
1649     /// @details ZZ@> This function sets the character's target to the target of its leader,
1650     /// or it fails with no change if the leader is dead
1651 
1652     SCRIPT_FUNCTION_BEGIN();
1653 
1654     if ( VALID_TEAM_RANGE( pchr->team ) )
1655     {
1656         CHR_REF ileader = TeamStack.lst[pchr->team].leader;
1657 
1658         if ( NOLEADER != ileader && INGAME_CHR( ileader ) )
1659         {
1660             CHR_REF itarget = ChrList.lst[ileader].ai.target;
1661 
1662             if ( INGAME_CHR( itarget ) )
1663             {
1664                 SET_TARGET_0( itarget );
1665             }
1666             else
1667             {
1668                 returncode = bfalse;
1669             }
1670         }
1671         else
1672         {
1673             returncode = bfalse;
1674         }
1675     }
1676     else
1677     {
1678         returncode = bfalse;
1679     }
1680 
1681     SCRIPT_FUNCTION_END();
1682 }
1683 
1684 //--------------------------------------------------------------------------------------------
scr_LeaderKilled(script_state_t * pstate,ai_state_t * pself)1685 Uint8 scr_LeaderKilled( script_state_t * pstate, ai_state_t * pself )
1686 {
1687     // IfLeaderKilled()
1688     /// @details ZZ@> This function proceeds if the team's leader died this update
1689 
1690     SCRIPT_FUNCTION_BEGIN();
1691 
1692     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_LEADERKILLED );
1693 
1694     SCRIPT_FUNCTION_END();
1695 }
1696 
1697 //--------------------------------------------------------------------------------------------
scr_BecomeLeader(script_state_t * pstate,ai_state_t * pself)1698 Uint8 scr_BecomeLeader( script_state_t * pstate, ai_state_t * pself )
1699 {
1700     // BecomeLeader()
1701     /// @details ZZ@> This function makes the character the leader of the team
1702 
1703     SCRIPT_FUNCTION_BEGIN();
1704 
1705     TeamStack.lst[pchr->team].leader = pself->index;
1706 
1707     SCRIPT_FUNCTION_END();
1708 }
1709 
1710 //--------------------------------------------------------------------------------------------
scr_ChangeTargetArmor(script_state_t * pstate,ai_state_t * pself)1711 Uint8 scr_ChangeTargetArmor( script_state_t * pstate, ai_state_t * pself )
1712 {
1713     // ChangeTargetArmor( tmpargument = "armor" )
1714 
1715     /// @details ZZ@> This function sets the target's armor type and returns the old type
1716     /// as tmpargument and the new type as tmpx
1717 
1718     int iTmp;
1719     chr_t * pself_target;
1720 
1721     SCRIPT_FUNCTION_BEGIN();
1722 
1723     SCRIPT_REQUIRE_TARGET( pself_target );
1724 
1725     iTmp = pself_target->skin;
1726     pstate->x = change_armor( pself->target, pstate->argument );
1727 
1728     pstate->argument = iTmp;  // The character's old armor
1729 
1730     SCRIPT_FUNCTION_END();
1731 }
1732 
1733 //--------------------------------------------------------------------------------------------
scr_GiveMoneyToTarget(script_state_t * pstate,ai_state_t * pself)1734 Uint8 scr_GiveMoneyToTarget( script_state_t * pstate, ai_state_t * pself )
1735 {
1736     // GiveMoneyToTarget( tmpargument = "money" )
1737     /// @details ZZ@> This function increases the target's money, while decreasing the
1738     /// character's own money.  tmpargument is set to the amount transferred
1739 
1740     int tTmp;
1741     int iTmp;
1742     chr_t * pself_target;
1743 
1744     SCRIPT_FUNCTION_BEGIN();
1745 
1746     SCRIPT_REQUIRE_TARGET( pself_target );
1747 
1748     iTmp = pchr->money;
1749     tTmp = pself_target->money;
1750     iTmp -= pstate->argument;
1751     tTmp += pstate->argument;
1752     if ( iTmp < 0 ) { tTmp += iTmp;  pstate->argument += iTmp;  iTmp = 0; }
1753     if ( tTmp < 0 ) { iTmp += tTmp;  pstate->argument += tTmp;  tTmp = 0; }
1754     if ( iTmp > MAXMONEY ) { iTmp = MAXMONEY; }
1755     if ( tTmp > MAXMONEY ) { tTmp = MAXMONEY; }
1756 
1757     pchr->money = iTmp;
1758     pself_target->money = tTmp;
1759 
1760     SCRIPT_FUNCTION_END();
1761 }
1762 
1763 //--------------------------------------------------------------------------------------------
scr_DropKeys(script_state_t * pstate,ai_state_t * pself)1764 Uint8 scr_DropKeys( script_state_t * pstate, ai_state_t * pself )
1765 {
1766     // DropKeys()
1767     /// @details ZZ@> This function drops all of the keys in the character's inventory.
1768     /// This does NOT drop keys in the character's hands.
1769 
1770     SCRIPT_FUNCTION_BEGIN();
1771 
1772     drop_keys( pself->index );
1773 
1774     SCRIPT_FUNCTION_END();
1775 }
1776 
1777 //--------------------------------------------------------------------------------------------
scr_LeaderIsAlive(script_state_t * pstate,ai_state_t * pself)1778 Uint8 scr_LeaderIsAlive( script_state_t * pstate, ai_state_t * pself )
1779 {
1780     // IfLeaderIsAlive()
1781     /// @details ZZ@> This function proceeds if the team has a leader
1782 
1783     SCRIPT_FUNCTION_BEGIN();
1784 
1785     returncode = ( TeamStack.lst[pchr->team].leader != NOLEADER );
1786 
1787     SCRIPT_FUNCTION_END();
1788 }
1789 
1790 //--------------------------------------------------------------------------------------------
scr_TargetIsOldTarget(script_state_t * pstate,ai_state_t * pself)1791 Uint8 scr_TargetIsOldTarget( script_state_t * pstate, ai_state_t * pself )
1792 {
1793     // IfTargetIsOldTarget()
1794     /// @details ZZ@> This function proceeds if the target is the same as it was last update
1795 
1796     SCRIPT_FUNCTION_BEGIN();
1797 
1798     returncode = ( pself->target == pself->target_old );
1799 
1800     SCRIPT_FUNCTION_END();
1801 }
1802 
1803 //--------------------------------------------------------------------------------------------
scr_set_TargetToLeader(script_state_t * pstate,ai_state_t * pself)1804 Uint8 scr_set_TargetToLeader( script_state_t * pstate, ai_state_t * pself )
1805 {
1806     // SetTargetToLeader()
1807     /// @details ZZ@> This function sets the target to the leader, proceeding if their is
1808     /// a valid leader for the character's team
1809 
1810     SCRIPT_FUNCTION_BEGIN();
1811 
1812     returncode = bfalse;
1813     if ( VALID_TEAM_RANGE( pchr->team ) )
1814     {
1815         CHR_REF ileader = TeamStack.lst[pchr->team].leader;
1816 
1817         if ( NOLEADER != ileader && INGAME_CHR( ileader ) )
1818         {
1819             SET_TARGET_0( ileader );
1820             returncode = btrue;
1821         }
1822     }
1823 
1824     SCRIPT_FUNCTION_END();
1825 }
1826 
1827 //--------------------------------------------------------------------------------------------
scr_SpawnCharacter(script_state_t * pstate,ai_state_t * pself)1828 Uint8 scr_SpawnCharacter( script_state_t * pstate, ai_state_t * pself )
1829 {
1830     // SpawnCharacter( tmpx = "x", tmpy = "y", tmpturn = "turn", tmpdistance = "speed" )
1831 
1832     /// @details ZZ@> This function spawns a character of the same type as the spawner.
1833     /// This function spawns a character, failing if x,y is invalid
1834     /// This is horribly complicated to use, so see ANIMATE.OBJ for an example
1835     /// tmpx and tmpy give the coodinates, tmpturn gives the new character's
1836     /// direction, and tmpdistance gives the new character's initial velocity
1837 
1838     CHR_REF ichr;
1839     int tTmp;
1840     fvec3_t   pos;
1841 
1842     SCRIPT_FUNCTION_BEGIN();
1843 
1844     pos.x = pstate->x;
1845     pos.y = pstate->y;
1846     pos.z = 0;
1847 
1848     ichr = spawn_one_character( pos, pchr->profile_ref, pchr->team, 0, CLIP_TO_16BITS( pstate->turn ), NULL, ( CHR_REF )MAX_CHR );
1849     returncode = DEFINED_CHR( ichr );
1850 
1851     if ( !returncode )
1852     {
1853         if ( ichr > PMod->importamount * MAXIMPORTPERPLAYER )
1854         {
1855             log_warning( "Object %s failed to spawn a copy of itself\n", pchr->obj_base._name );
1856         }
1857     }
1858     else
1859     {
1860         chr_t * pchild = ChrList.lst + ichr;
1861 
1862         // was the child spawned in a "safe" spot?
1863         if ( !chr_get_safe( pchild, NULL ) )
1864         {
1865             chr_request_terminate( ichr );
1866             ichr = ( CHR_REF )MAX_CHR;
1867         }
1868         else
1869         {
1870             pself->child = ichr;
1871 
1872             tTmp = TO_TURN( pchr->ori.facing_z + ATK_BEHIND );
1873 
1874             pchild->vel.x += turntocos[ tTmp ] * pstate->distance;
1875             pchild->vel.y += turntosin[ tTmp ] * pstate->distance;
1876 
1877             pchild->iskursed = pchr->iskursed;  /// @details BB@> inherit this from your spawner
1878             pchild->ai.passage = pself->passage;
1879             pchild->ai.owner   = pself->owner;
1880 
1881             pchild->dismount_timer  = PHYS_DISMOUNT_TIME;
1882             pchild->dismount_object = pself->index;
1883         }
1884     }
1885 
1886     SCRIPT_FUNCTION_END();
1887 }
1888 
1889 //--------------------------------------------------------------------------------------------
scr_RespawnCharacter(script_state_t * pstate,ai_state_t * pself)1890 Uint8 scr_RespawnCharacter( script_state_t * pstate, ai_state_t * pself )
1891 {
1892     // RespawnCharacter()
1893     /// @details ZZ@> This function respawns the character at its starting location.
1894     /// Often used with the Clean functions
1895 
1896     SCRIPT_FUNCTION_BEGIN();
1897 
1898     respawn_character( pself->index );
1899 
1900     SCRIPT_FUNCTION_END();
1901 }
1902 
1903 //--------------------------------------------------------------------------------------------
scr_ChangeTile(script_state_t * pstate,ai_state_t * pself)1904 Uint8 scr_ChangeTile( script_state_t * pstate, ai_state_t * pself )
1905 {
1906     // ChangeTile( tmpargument = "tile type")
1907     /// @details ZZ@> This function changes the tile under the character to the new tile type,
1908     /// which is highly module dependent
1909 
1910     SCRIPT_FUNCTION_BEGIN();
1911 
1912     returncode = mesh_set_texture( PMesh, pchr->onwhichgrid, pstate->argument );
1913 
1914     SCRIPT_FUNCTION_END();
1915 }
1916 
1917 //--------------------------------------------------------------------------------------------
scr_Used(script_state_t * pstate,ai_state_t * pself)1918 Uint8 scr_Used( script_state_t * pstate, ai_state_t * pself )
1919 {
1920     // IfUsed()
1921     /// @details ZZ@> This function proceeds if the character was used by its holder or rider.
1922     /// Character's cannot be used if their reload time is greater than 0
1923 
1924     SCRIPT_FUNCTION_BEGIN();
1925 
1926     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_USED );
1927 
1928     SCRIPT_FUNCTION_END();
1929 }
1930 
1931 //--------------------------------------------------------------------------------------------
scr_DropMoney(script_state_t * pstate,ai_state_t * pself)1932 Uint8 scr_DropMoney( script_state_t * pstate, ai_state_t * pself )
1933 {
1934     // DropMoney( tmpargument = "money" )
1935     /// @details ZZ@> This function drops a certain amount of money, if the character has that
1936     /// much
1937 
1938     SCRIPT_FUNCTION_BEGIN();
1939 
1940     drop_money( pself->index, pstate->argument );
1941 
1942     SCRIPT_FUNCTION_END();
1943 }
1944 
1945 //--------------------------------------------------------------------------------------------
scr_set_OldTarget(script_state_t * pstate,ai_state_t * pself)1946 Uint8 scr_set_OldTarget( script_state_t * pstate, ai_state_t * pself )
1947 {
1948     // SetOldTarget()
1949     /// @details ZZ@> This function sets the old target to the current target.  To allow
1950     /// greater manipulations of the target
1951 
1952     SCRIPT_FUNCTION_BEGIN();
1953 
1954     pself->target_old = pself->target;
1955 
1956     SCRIPT_FUNCTION_END();
1957 }
1958 
1959 //--------------------------------------------------------------------------------------------
scr_DetachFromHolder(script_state_t * pstate,ai_state_t * pself)1960 Uint8 scr_DetachFromHolder( script_state_t * pstate, ai_state_t * pself )
1961 {
1962     // DetachFromHolder()
1963     /// @details ZZ@> This function drops the character or makes it get off its mount
1964     /// Can be used to make slippery weapons, or to make certain characters
1965     /// incapable of wielding certain weapons. "A troll can't grab a torch"
1966 
1967     SCRIPT_FUNCTION_BEGIN();
1968 
1969     if ( INGAME_CHR( pchr->attachedto ) )
1970     {
1971         detach_character_from_mount( pself->index, btrue, btrue );
1972     }
1973     else
1974     {
1975         returncode = bfalse;
1976     }
1977 
1978     SCRIPT_FUNCTION_END();
1979 }
1980 
1981 //--------------------------------------------------------------------------------------------
scr_TargetHasVulnerabilityID(script_state_t * pstate,ai_state_t * pself)1982 Uint8 scr_TargetHasVulnerabilityID( script_state_t * pstate, ai_state_t * pself )
1983 {
1984     // IfTargetHasVulnerabilityID( tmpargument = "vulnerability idsz" )
1985     /// @details ZZ@> This function proceeds if the target is vulnerable to the given IDSZ.
1986 
1987     cap_t * pcap;
1988 
1989     SCRIPT_FUNCTION_BEGIN();
1990 
1991     returncode = bfalse;
1992 
1993     pcap = chr_get_pcap( pself->target );
1994     if ( NULL != pcap )
1995     {
1996         returncode = ( pcap->idsz[IDSZ_VULNERABILITY] == ( IDSZ ) pstate->argument );
1997     }
1998 
1999     SCRIPT_FUNCTION_END();
2000 }
2001 
2002 //--------------------------------------------------------------------------------------------
scr_CleanUp(script_state_t * pstate,ai_state_t * pself)2003 Uint8 scr_CleanUp( script_state_t * pstate, ai_state_t * pself )
2004 {
2005     // CleanUp()
2006     /// @details ZZ@> This function tells all the dead characters on the team to clean
2007     /// themselves up.  Usually done by the boss creature every second or so
2008 
2009     SCRIPT_FUNCTION_BEGIN();
2010 
2011     issue_clean( pself->index );
2012 
2013     SCRIPT_FUNCTION_END();
2014 }
2015 
2016 //--------------------------------------------------------------------------------------------
scr_CleanedUp(script_state_t * pstate,ai_state_t * pself)2017 Uint8 scr_CleanedUp( script_state_t * pstate, ai_state_t * pself )
2018 {
2019     // IfCleanedUp()
2020     /// @details ZZ@> This function proceeds if the character is dead and if the boss told it
2021     /// to clean itself up
2022 
2023     SCRIPT_FUNCTION_BEGIN();
2024 
2025     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_CLEANEDUP );
2026 
2027     SCRIPT_FUNCTION_END();
2028 }
2029 
2030 //--------------------------------------------------------------------------------------------
scr_Sitting(script_state_t * pstate,ai_state_t * pself)2031 Uint8 scr_Sitting( script_state_t * pstate, ai_state_t * pself )
2032 {
2033     // IfSitting()
2034     /// @details ZZ@> This function proceeds if the character is riding a mount
2035 
2036     SCRIPT_FUNCTION_BEGIN();
2037 
2038     returncode = INGAME_CHR( pchr->attachedto );
2039 
2040     SCRIPT_FUNCTION_END();
2041 }
2042 
2043 //--------------------------------------------------------------------------------------------
scr_TargetIsHurt(script_state_t * pstate,ai_state_t * pself)2044 Uint8 scr_TargetIsHurt( script_state_t * pstate, ai_state_t * pself )
2045 {
2046     // IfTargetIsHurt()
2047     /// @details ZZ@> This function passes only if the target is hurt and alive
2048 
2049     chr_t * pself_target;
2050 
2051     SCRIPT_FUNCTION_BEGIN();
2052 
2053     SCRIPT_REQUIRE_TARGET( pself_target );
2054 
2055     if ( !pself_target->alive || pself_target->life > pself_target->lifemax - HURTDAMAGE )
2056         returncode = bfalse;
2057 
2058     SCRIPT_FUNCTION_END();
2059 }
2060 
2061 //--------------------------------------------------------------------------------------------
scr_TargetIsAPlayer(script_state_t * pstate,ai_state_t * pself)2062 Uint8 scr_TargetIsAPlayer( script_state_t * pstate, ai_state_t * pself )
2063 {
2064     // IfTargetIsAPlayer()
2065     /// @details ZZ@> This function proceeds if the target is controlled by a human ( may not be local )
2066 
2067     chr_t * pself_target;
2068 
2069     SCRIPT_FUNCTION_BEGIN();
2070 
2071     SCRIPT_REQUIRE_TARGET( pself_target );
2072 
2073     returncode = VALID_PLA( pself_target->is_which_player );
2074 
2075     SCRIPT_FUNCTION_END();
2076 }
2077 
2078 //--------------------------------------------------------------------------------------------
scr_PlaySound(script_state_t * pstate,ai_state_t * pself)2079 Uint8 scr_PlaySound( script_state_t * pstate, ai_state_t * pself )
2080 {
2081     // PlaySound( tmpargument = "sound" )
2082     /// @details ZZ@> This function plays one of the character's sounds.
2083     /// The sound fades out depending on its distance from the viewer
2084 
2085     SCRIPT_FUNCTION_BEGIN();
2086 
2087     if ( pchr->pos_old.z > PITNOSOUND && VALID_SND( pstate->argument ) )
2088     {
2089         sound_play_chunk( pchr->pos_old, chr_get_chunk_ptr( pchr, pstate->argument ) );
2090     }
2091 
2092     SCRIPT_FUNCTION_END();
2093 }
2094 
2095 //--------------------------------------------------------------------------------------------
scr_SpawnParticle(script_state_t * pstate,ai_state_t * pself)2096 Uint8 scr_SpawnParticle( script_state_t * pstate, ai_state_t * pself )
2097 {
2098     // SpawnParticle(tmpargument = "particle", tmpdistance = "character vertex", tmpx = "offset x", tmpy = "offset y" )
2099     /// @details ZZ@> This function spawns a particle, offset from the character's location
2100 
2101     PRT_REF iprt;
2102     CHR_REF ichr;
2103 
2104     SCRIPT_FUNCTION_BEGIN();
2105 
2106     ichr = pself->index;
2107     if ( INGAME_CHR( pchr->attachedto ) )
2108     {
2109         ichr = pchr->attachedto;
2110     }
2111 
2112     iprt = spawn_one_particle( pchr->pos, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, pself->index, pstate->distance, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
2113 
2114     returncode = DEFINED_PRT( iprt );
2115     if ( returncode )
2116     {
2117         fvec3_t tmp_pos;
2118         prt_t * pprt = PrtList.lst + iprt;
2119 
2120         // attach the particle
2121         place_particle_at_vertex( pprt, pself->index, pstate->distance );
2122         pprt->attachedto_ref = ( CHR_REF )MAX_CHR;
2123 
2124         tmp_pos = prt_get_pos( pprt );
2125 
2126         // Correct X, Y, Z spacing
2127         tmp_pos.z += PipStack.lst[pprt->pip_ref].spacing_vrt_pair.base;
2128 
2129         // Don't spawn in walls
2130         tmp_pos.x += pstate->x;
2131         if ( EMPTY_BIT_FIELD != prt_test_wall( pprt, tmp_pos.v, NULL ) )
2132         {
2133             tmp_pos.x = pprt->pos.x;
2134 
2135             tmp_pos.y += pstate->y;
2136             if ( EMPTY_BIT_FIELD != prt_test_wall( pprt, tmp_pos.v, NULL ) )
2137             {
2138                 tmp_pos.y = pprt->pos.y;
2139             }
2140         }
2141 
2142         prt_set_pos( pprt, tmp_pos.v );
2143     }
2144 
2145     SCRIPT_FUNCTION_END();
2146 }
2147 
2148 //--------------------------------------------------------------------------------------------
scr_TargetIsAlive(script_state_t * pstate,ai_state_t * pself)2149 Uint8 scr_TargetIsAlive( script_state_t * pstate, ai_state_t * pself )
2150 {
2151     // IfTargetIsAlive()
2152     /// @details ZZ@> This function proceeds if the target is alive
2153 
2154     chr_t * pself_target;
2155 
2156     SCRIPT_FUNCTION_BEGIN();
2157 
2158     SCRIPT_REQUIRE_TARGET( pself_target );
2159 
2160     returncode = pself_target->alive;
2161 
2162     SCRIPT_FUNCTION_END();
2163 }
2164 
2165 //--------------------------------------------------------------------------------------------
scr_Stop(script_state_t * pstate,ai_state_t * pself)2166 Uint8 scr_Stop( script_state_t * pstate, ai_state_t * pself )
2167 {
2168     // Stop()
2169     /// @details ZZ@> This function sets the character's maximum acceleration to 0.  Used
2170     /// along with Walk and Run and Sneak
2171 
2172     SCRIPT_FUNCTION_BEGIN();
2173 
2174     pchr->maxaccel      = 0;
2175     pchr->movement_bits = CHR_MOVEMENT_BITS_STOP;
2176 
2177     SCRIPT_FUNCTION_END();
2178 }
2179 
2180 //--------------------------------------------------------------------------------------------
scr_DisaffirmCharacter(script_state_t * pstate,ai_state_t * pself)2181 Uint8 scr_DisaffirmCharacter( script_state_t * pstate, ai_state_t * pself )
2182 {
2183     // DisaffirmCharacter()
2184     /// @details ZZ@> This function removes all the attached particles from a character
2185     /// ( stuck arrows, flames, etc )
2186 
2187     SCRIPT_FUNCTION_BEGIN();
2188 
2189     disaffirm_attached_particles( pself->index );
2190 
2191     SCRIPT_FUNCTION_END();
2192 }
2193 
2194 //--------------------------------------------------------------------------------------------
scr_ReaffirmCharacter(script_state_t * pstate,ai_state_t * pself)2195 Uint8 scr_ReaffirmCharacter( script_state_t * pstate, ai_state_t * pself )
2196 {
2197     // ReaffirmCharacter()
2198     /// @details ZZ@> This function makes sure it has all of its reaffirmation particles
2199     /// attached to it. Used to make the torch light again
2200 
2201     SCRIPT_FUNCTION_BEGIN();
2202 
2203     reaffirm_attached_particles( pself->index );
2204 
2205     SCRIPT_FUNCTION_END();
2206 }
2207 
2208 //--------------------------------------------------------------------------------------------
scr_TargetIsSelf(script_state_t * pstate,ai_state_t * pself)2209 Uint8 scr_TargetIsSelf( script_state_t * pstate, ai_state_t * pself )
2210 {
2211     // IfTargetIsSelf()
2212     /// @details ZZ@> This function proceeds if the character is targeting itself
2213 
2214     SCRIPT_FUNCTION_BEGIN();
2215 
2216     returncode = ( pself->target == pself->index );
2217 
2218     SCRIPT_FUNCTION_END();
2219 }
2220 
2221 //--------------------------------------------------------------------------------------------
scr_TargetIsMale(script_state_t * pstate,ai_state_t * pself)2222 Uint8 scr_TargetIsMale( script_state_t * pstate, ai_state_t * pself )
2223 {
2224     // IfTargetIsMale()
2225     /// @details ZZ@> This function proceeds only if the target is male
2226 
2227     chr_t * pself_target;
2228 
2229     SCRIPT_FUNCTION_BEGIN();
2230 
2231     SCRIPT_REQUIRE_TARGET( pself_target );
2232 
2233     returncode = ( pself_target->gender == GENDER_MALE );
2234 
2235     SCRIPT_FUNCTION_END();
2236 }
2237 
2238 //--------------------------------------------------------------------------------------------
scr_TargetIsFemale(script_state_t * pstate,ai_state_t * pself)2239 Uint8 scr_TargetIsFemale( script_state_t * pstate, ai_state_t * pself )
2240 {
2241     // IfTargetIsFemale()
2242     /// @details ZZ@> This function proceeds if the target is female
2243 
2244     chr_t * pself_target;
2245 
2246     SCRIPT_FUNCTION_BEGIN();
2247 
2248     SCRIPT_REQUIRE_TARGET( pself_target );
2249 
2250     returncode = ( pself_target->gender == GENDER_FEMALE );
2251 
2252     SCRIPT_FUNCTION_END();
2253 }
2254 
2255 //--------------------------------------------------------------------------------------------
scr_set_TargetToSelf(script_state_t * pstate,ai_state_t * pself)2256 Uint8 scr_set_TargetToSelf( script_state_t * pstate, ai_state_t * pself )
2257 {
2258     // SetTargetToSelf()
2259     /// @details ZZ@> This function sets the target to the character itself
2260 
2261     SCRIPT_FUNCTION_BEGIN();
2262 
2263     SET_TARGET_0( pself->index );
2264 
2265     SCRIPT_FUNCTION_END();
2266 }
2267 
2268 //--------------------------------------------------------------------------------------------
scr_set_TargetToRider(script_state_t * pstate,ai_state_t * pself)2269 Uint8 scr_set_TargetToRider( script_state_t * pstate, ai_state_t * pself )
2270 {
2271     // SetTargetToRider()
2272     /// @details ZZ@> This function sets the target to whoever is riding the character (left/only grip),
2273     /// failing if there is no rider
2274 
2275     SCRIPT_FUNCTION_BEGIN();
2276 
2277     if ( INGAME_CHR( pchr->holdingwhich[SLOT_LEFT] ) )
2278     {
2279         SET_TARGET_0( pchr->holdingwhich[SLOT_LEFT] );
2280     }
2281     else
2282     {
2283         returncode = bfalse;
2284     }
2285 
2286     SCRIPT_FUNCTION_END();
2287 }
2288 
2289 //--------------------------------------------------------------------------------------------
scr_get_AttackTurn(script_state_t * pstate,ai_state_t * pself)2290 Uint8 scr_get_AttackTurn( script_state_t * pstate, ai_state_t * pself )
2291 {
2292     // tmpturn = GetAttackTurn()
2293     /// @details ZZ@> This function sets tmpturn to the direction from which the last attack
2294     /// came. Not particularly useful in most cases, but it could be.
2295 
2296     SCRIPT_FUNCTION_BEGIN();
2297 
2298     pstate->turn = pself->directionlast;
2299 
2300     SCRIPT_FUNCTION_END();
2301 }
2302 
2303 //--------------------------------------------------------------------------------------------
scr_get_DamageType(script_state_t * pstate,ai_state_t * pself)2304 Uint8 scr_get_DamageType( script_state_t * pstate, ai_state_t * pself )
2305 {
2306     // tmpargument = GetDamageType()
2307     /// @details ZZ@> This function sets tmpargument to the damage type of the last attack that
2308     /// hit the character
2309 
2310     SCRIPT_FUNCTION_BEGIN();
2311 
2312     pstate->argument = pself->damagetypelast;
2313 
2314     SCRIPT_FUNCTION_END();
2315 }
2316 
2317 //--------------------------------------------------------------------------------------------
scr_BecomeSpell(script_state_t * pstate,ai_state_t * pself)2318 Uint8 scr_BecomeSpell( script_state_t * pstate, ai_state_t * pself )
2319 {
2320     // BecomeSpell()
2321     /// @details ZZ@> This function turns a spellbook character into a spell based on its
2322     /// content.
2323     /// TOO COMPLICATED TO EXPLAIN.  SHOULDN'T EVER BE NEEDED BY YOU.
2324 
2325     int iskin;
2326     cap_t * pcap;
2327 
2328     SCRIPT_FUNCTION_BEGIN();
2329 
2330     // get the spellbook's skin
2331     iskin = pchr->skin;
2332 
2333     // change the spellbook to a spell effect
2334     change_character( pself->index, ( PRO_REF )pself->content, 0, ENC_LEAVE_NONE );
2335 
2336     // set the spell effect parameters
2337     pself->content = 0;
2338     chr_set_ai_state( pchr, 0 );
2339 
2340     // have to do this every time pself->state is modified
2341     chr_update_hide( pchr );
2342 
2343     // set the book icon of the spell effect if it is not already set
2344     pcap = chr_get_pcap( pself->index );
2345     if ( NULL != pcap )
2346     {
2347         pcap->spelleffect_type = iskin;
2348     }
2349 
2350     SCRIPT_FUNCTION_END();
2351 }
2352 
2353 //--------------------------------------------------------------------------------------------
scr_BecomeSpellbook(script_state_t * pstate,ai_state_t * pself)2354 Uint8 scr_BecomeSpellbook( script_state_t * pstate, ai_state_t * pself )
2355 {
2356     // BecomeSpellbook()
2357     //
2358     /// @details ZZ@> This function turns a spell character into a spellbook and sets the content accordingly.
2359     /// TOO COMPLICATED TO EXPLAIN. Just copy the spells that already exist, and don't change
2360     /// them too much
2361 
2362     PRO_REF  old_profile;
2363     mad_t * pmad;
2364     int iskin;
2365 
2366     SCRIPT_FUNCTION_BEGIN();
2367 
2368     // Figure out what this spellbook looks like
2369     iskin = 0;
2370     if ( NULL != chr_get_pcap( pself->index ) ) iskin = chr_get_pcap( pself->index )->spelleffect_type;
2371 
2372     // convert the spell effect to a spellbook
2373     old_profile = pchr->profile_ref;
2374     change_character( pself->index, ( PRO_REF )SPELLBOOK, iskin, ENC_LEAVE_NONE );
2375 
2376     // Reset the spellbook state so it doesn't burn up
2377     chr_set_ai_state( pchr, 0 );
2378     pself->content = REF_TO_INT( old_profile );
2379 
2380     // set the spellbook animations
2381     pmad = chr_get_pmad( pself->index );
2382 
2383     if ( NULL != pmad )
2384     {
2385         // Do dropped animation
2386         int tmp_action = mad_get_action_ref( pchr->inst.imad, ACTION_JB );
2387 
2388         if ( rv_success == chr_start_anim( pchr, tmp_action, bfalse, btrue ) )
2389         {
2390             returncode = btrue;
2391         }
2392     }
2393 
2394     // have to do this every time pself->state is modified
2395     chr_update_hide( pchr );
2396 
2397     SCRIPT_FUNCTION_END();
2398 }
2399 
2400 //--------------------------------------------------------------------------------------------
scr_ScoredAHit(script_state_t * pstate,ai_state_t * pself)2401 Uint8 scr_ScoredAHit( script_state_t * pstate, ai_state_t * pself )
2402 {
2403     // IfScoredAHit()
2404     /// @details ZZ@> This function proceeds if the character damaged another character this
2405     /// update. If it's a held character it also sets the target to whoever was hit
2406 
2407     SCRIPT_FUNCTION_BEGIN();
2408 
2409     // Proceed only if the character scored a hit
2410 //    if ( !INGAME_CHR( pchr->attachedto ) || ChrList.lst[pchr->attachedto].ismount )
2411 //    {
2412     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_SCOREDAHIT );
2413 //    }
2414 
2415     // Proceed only if the holder scored a hit with the character
2416     /*    else if ( ChrList.lst[pchr->attachedto].ai.lastitemused == pself->index )
2417         {
2418             returncode = HAS_SOME_BITS( ChrList.lst[pchr->attachedto].ai.alert, ALERTIF_SCOREDAHIT );
2419         }
2420         else returncode = bfalse;*/
2421 
2422     SCRIPT_FUNCTION_END();
2423 }
2424 
2425 //--------------------------------------------------------------------------------------------
scr_Disaffirmed(script_state_t * pstate,ai_state_t * pself)2426 Uint8 scr_Disaffirmed( script_state_t * pstate, ai_state_t * pself )
2427 {
2428     // IfDisaffirmed()
2429     /// @details ZZ@> This function proceeds if the character was disaffirmed.
2430     /// This doesn't seem useful anymore.
2431 
2432     SCRIPT_FUNCTION_BEGIN();
2433 
2434     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_DISAFFIRMED );
2435 
2436     SCRIPT_FUNCTION_END();
2437 }
2438 
2439 //--------------------------------------------------------------------------------------------
scr_TranslateOrder(script_state_t * pstate,ai_state_t * pself)2440 Uint8 scr_TranslateOrder( script_state_t * pstate, ai_state_t * pself )
2441 {
2442     // tmpx,tmpy,tmpargument = TranslateOrder()
2443     /// @details ZZ@> This function translates a packed order into understandable values.
2444     /// See CreateOrder for more.  This function sets tmpx, tmpy, tmpargument,
2445     /// and sets the target ( if valid )
2446 
2447     CHR_REF ichr;
2448 
2449     SCRIPT_FUNCTION_BEGIN();
2450 
2451     ichr = CLIP_TO_16BITS( pself->order_value >> 24 );
2452 
2453     if ( INGAME_CHR( ichr ) )
2454     {
2455         SET_TARGET_0( ichr );
2456 
2457         pstate->x        = (( pself->order_value >> 14 ) & 0x03FF ) << 6;
2458         pstate->y        = (( pself->order_value >>  4 ) & 0x03FF ) << 6;
2459         pstate->argument = (( pself->order_value >>  0 ) & 0x000F );
2460     }
2461     else
2462     {
2463         returncode = bfalse;
2464     }
2465 
2466     SCRIPT_FUNCTION_END();
2467 }
2468 
2469 //--------------------------------------------------------------------------------------------
scr_set_TargetToWhoeverWasHit(script_state_t * pstate,ai_state_t * pself)2470 Uint8 scr_set_TargetToWhoeverWasHit( script_state_t * pstate, ai_state_t * pself )
2471 {
2472     // SetTargetToWhoeverWasHit()
2473     /// @details ZZ@> This function sets the target to whoever was hit by the character last
2474 
2475     SCRIPT_FUNCTION_BEGIN();
2476 
2477     if ( INGAME_CHR( pself->hitlast ) )
2478     {
2479         SET_TARGET_0( pself->hitlast );
2480     }
2481     else
2482     {
2483         returncode = bfalse;
2484     }
2485 
2486     SCRIPT_FUNCTION_END();
2487 }
2488 
2489 //--------------------------------------------------------------------------------------------
scr_set_TargetToWideEnemy(script_state_t * pstate,ai_state_t * pself)2490 Uint8 scr_set_TargetToWideEnemy( script_state_t * pstate, ai_state_t * pself )
2491 {
2492     // SetTargetToWideEnemy()
2493     /// @details ZZ@> This function sets the target to an enemy in the vicinity around the
2494     /// character, failing if there are none
2495 
2496     CHR_REF ichr;
2497     SCRIPT_FUNCTION_BEGIN();
2498 
2499     ichr = chr_find_target( pchr, WIDE, IDSZ_NONE, TARGET_ENEMIES );
2500 
2501     if ( INGAME_CHR( ichr ) )
2502     {
2503         SET_TARGET_0( ichr );
2504     }
2505     else
2506     {
2507         returncode = bfalse;
2508     }
2509 
2510     SCRIPT_FUNCTION_END();
2511 }
2512 
2513 //--------------------------------------------------------------------------------------------
scr_Changed(script_state_t * pstate,ai_state_t * pself)2514 Uint8 scr_Changed( script_state_t * pstate, ai_state_t * pself )
2515 {
2516     // IfChanged()
2517     /// @details ZZ@> This function proceeds if the character was polymorphed.
2518     /// Needed for morph spells and such
2519 
2520     SCRIPT_FUNCTION_BEGIN();
2521 
2522     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_CHANGED );
2523 
2524     SCRIPT_FUNCTION_END();
2525 }
2526 
2527 //--------------------------------------------------------------------------------------------
scr_InWater(script_state_t * pstate,ai_state_t * pself)2528 Uint8 scr_InWater( script_state_t * pstate, ai_state_t * pself )
2529 {
2530     // IfInWater()
2531     /// @details ZZ@> This function proceeds if the character has just entered into some water
2532     /// this update ( and the water is really water, not fog or another effect )
2533 
2534     SCRIPT_FUNCTION_BEGIN();
2535 
2536     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_INWATER );
2537 
2538     SCRIPT_FUNCTION_END();
2539 }
2540 
2541 //--------------------------------------------------------------------------------------------
scr_Bored(script_state_t * pstate,ai_state_t * pself)2542 Uint8 scr_Bored( script_state_t * pstate, ai_state_t * pself )
2543 {
2544     // IfBored()
2545     /// @details ZZ@> This function proceeds if the character has been standing idle too long
2546 
2547     SCRIPT_FUNCTION_BEGIN();
2548 
2549     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_BORED );
2550 
2551     SCRIPT_FUNCTION_END();
2552 }
2553 
2554 //--------------------------------------------------------------------------------------------
scr_TooMuchBaggage(script_state_t * pstate,ai_state_t * pself)2555 Uint8 scr_TooMuchBaggage( script_state_t * pstate, ai_state_t * pself )
2556 {
2557     // IfTooMuchBaggage()
2558     /// @details ZZ@> This function proceeds if the character tries to put an item in his/her
2559     /// pockets, but the character already has 6 items in the inventory.
2560     /// Used to tell the players what's going on.
2561 
2562     SCRIPT_FUNCTION_BEGIN();
2563 
2564     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_TOOMUCHBAGGAGE );
2565 
2566     SCRIPT_FUNCTION_END();
2567 }
2568 
2569 //--------------------------------------------------------------------------------------------
scr_Grogged(script_state_t * pstate,ai_state_t * pself)2570 Uint8 scr_Grogged( script_state_t * pstate, ai_state_t * pself )
2571 {
2572     // IfGrogged()
2573     /// @details ZZ@> This function proceeds if the character has been grogged ( a type of
2574     /// confusion ) this update
2575 
2576     SCRIPT_FUNCTION_BEGIN();
2577 
2578     returncode = ChrList.lst[pself->index].grog_timer > 0 && HAS_SOME_BITS( pself->alert, ALERTIF_CONFUSED );
2579 
2580     SCRIPT_FUNCTION_END();
2581 }
2582 
2583 //--------------------------------------------------------------------------------------------
scr_Dazed(script_state_t * pstate,ai_state_t * pself)2584 Uint8 scr_Dazed( script_state_t * pstate, ai_state_t * pself )
2585 {
2586     // IfDazed()
2587     /// @details ZZ@> This function proceeds if the character has been dazed ( a type of
2588     /// confusion ) this update
2589 
2590     SCRIPT_FUNCTION_BEGIN();
2591 
2592     returncode = ChrList.lst[pself->index].daze_timer > 0 && HAS_SOME_BITS( pself->alert, ALERTIF_CONFUSED );
2593 
2594     SCRIPT_FUNCTION_END();
2595 }
2596 
2597 //--------------------------------------------------------------------------------------------
scr_TargetHasSpecialID(script_state_t * pstate,ai_state_t * pself)2598 Uint8 scr_TargetHasSpecialID( script_state_t * pstate, ai_state_t * pself )
2599 {
2600     // IfTargetHasSpecialID( tmpargument = "special idsz" )
2601     /// @details ZZ@> This function proceeds if the character has a special IDSZ ( in data.txt )
2602 
2603     cap_t * pcap;
2604 
2605     SCRIPT_FUNCTION_BEGIN();
2606 
2607     returncode = bfalse;
2608 
2609     pcap = chr_get_pcap( pself->target );
2610     if ( NULL != pcap )
2611     {
2612         returncode = ( pcap->idsz[IDSZ_SPECIAL] == ( IDSZ ) pstate->argument );
2613     }
2614 
2615     SCRIPT_FUNCTION_END();
2616 }
2617 
2618 //--------------------------------------------------------------------------------------------
scr_PressTargetLatchButton(script_state_t * pstate,ai_state_t * pself)2619 Uint8 scr_PressTargetLatchButton( script_state_t * pstate, ai_state_t * pself )
2620 {
2621     // PressTargetLatchButton( tmpargument = "latch bits" )
2622     /// @details ZZ@> This function mimics joystick button presses for the target.
2623     /// For making items force their own usage and such
2624 
2625     chr_t * pself_target;
2626 
2627     SCRIPT_FUNCTION_BEGIN();
2628 
2629     SCRIPT_REQUIRE_TARGET( pself_target );
2630 
2631     SET_BIT( pself_target->latch.b, pstate->argument );
2632 
2633     SCRIPT_FUNCTION_END();
2634 }
2635 
2636 //--------------------------------------------------------------------------------------------
scr_Invisible(script_state_t * pstate,ai_state_t * pself)2637 Uint8 scr_Invisible( script_state_t * pstate, ai_state_t * pself )
2638 {
2639     // IfInvisible()
2640     /// @details ZZ@> This function proceeds if the character is invisible
2641 
2642     SCRIPT_FUNCTION_BEGIN();
2643 
2644     returncode = pchr->inst.alpha <= INVISIBLE;
2645 
2646     SCRIPT_FUNCTION_END();
2647 }
2648 
2649 //--------------------------------------------------------------------------------------------
scr_ArmorIs(script_state_t * pstate,ai_state_t * pself)2650 Uint8 scr_ArmorIs( script_state_t * pstate, ai_state_t * pself )
2651 {
2652     // IfArmorIs( tmpargument = "skin" )
2653     /// @details ZZ@> This function proceeds if the character's skin type equals tmpargument
2654 
2655     int tTmp;
2656 
2657     SCRIPT_FUNCTION_BEGIN();
2658 
2659     tTmp = pchr->skin;
2660     returncode = ( tTmp == pstate->argument );
2661 
2662     SCRIPT_FUNCTION_END();
2663 }
2664 
2665 //--------------------------------------------------------------------------------------------
scr_get_TargetGrogTime(script_state_t * pstate,ai_state_t * pself)2666 Uint8 scr_get_TargetGrogTime( script_state_t * pstate, ai_state_t * pself )
2667 {
2668     // tmpargument = GetTargetGrogTime()
2669     /// @details ZZ@> This function sets tmpargument to the number of updates before the
2670     /// character is ungrogged, proceeding if the number is greater than 0
2671 
2672     chr_t * pself_target;
2673 
2674     SCRIPT_FUNCTION_BEGIN();
2675 
2676     SCRIPT_REQUIRE_TARGET( pself_target );
2677 
2678     pstate->argument = pself_target->grog_timer;
2679 
2680     returncode = ( 0 != pstate->argument );
2681 
2682     SCRIPT_FUNCTION_END();
2683 }
2684 
2685 //--------------------------------------------------------------------------------------------
scr_get_TargetDazeTime(script_state_t * pstate,ai_state_t * pself)2686 Uint8 scr_get_TargetDazeTime( script_state_t * pstate, ai_state_t * pself )
2687 {
2688     // tmpargument = GetTargetDazeTime()
2689     /// @details ZZ@> This function sets tmpargument to the number of updates before the
2690     /// character is undazed, proceeding if the number is greater than 0
2691 
2692     chr_t * pself_target;
2693 
2694     SCRIPT_FUNCTION_BEGIN();
2695 
2696     SCRIPT_REQUIRE_TARGET( pself_target );
2697 
2698     pstate->argument = pself_target->daze_timer;
2699 
2700     returncode = ( 0 != pstate->argument );
2701 
2702     SCRIPT_FUNCTION_END();
2703 }
2704 
2705 //--------------------------------------------------------------------------------------------
scr_set_DamageType(script_state_t * pstate,ai_state_t * pself)2706 Uint8 scr_set_DamageType( script_state_t * pstate, ai_state_t * pself )
2707 {
2708     // SetDamageType( tmpargument = "damage type" )
2709     /// @details ZZ@> This function lets a weapon change the type of damage it inflicts
2710 
2711     SCRIPT_FUNCTION_BEGIN();
2712 
2713     pchr->damagetarget_damagetype = pstate->argument % DAMAGE_COUNT;
2714 
2715     SCRIPT_FUNCTION_END();
2716 }
2717 
2718 //--------------------------------------------------------------------------------------------
scr_set_WaterLevel(script_state_t * pstate,ai_state_t * pself)2719 Uint8 scr_set_WaterLevel( script_state_t * pstate, ai_state_t * pself )
2720 {
2721     // SetWaterLevel( tmpargument = "level" )
2722     /// @details ZZ@> This function raises or lowers the water in the module
2723 
2724     int iTmp;
2725     float fTmp;
2726 
2727     SCRIPT_FUNCTION_BEGIN();
2728 
2729     fTmp = ( pstate->argument / 10.0f ) - water.douse_level;
2730     water.surface_level += fTmp;
2731     water.douse_level += fTmp;
2732 
2733     for ( iTmp = 0; iTmp < MAXWATERLAYER; iTmp++ )
2734     {
2735         water.layer[iTmp].z += fTmp;
2736     }
2737 
2738     SCRIPT_FUNCTION_END();
2739 }
2740 
2741 //--------------------------------------------------------------------------------------------
scr_EnchantTarget(script_state_t * pstate,ai_state_t * pself)2742 Uint8 scr_EnchantTarget( script_state_t * pstate, ai_state_t * pself )
2743 {
2744     // EnchantTarget()
2745     /// @details ZZ@> This function enchants the target with the enchantment given
2746     /// in enchant.txt. Make sure you use set_OwnerToTarget before doing this.
2747 
2748     ENC_REF iTmp;
2749 
2750     SCRIPT_FUNCTION_BEGIN();
2751 
2752     iTmp = spawn_one_enchant( pself->owner, pself->target, pself->index, ( ENC_REF )MAX_ENC, ( PRO_REF )MAX_PROFILE );
2753     returncode = DEFINED_ENC( iTmp );
2754 
2755     SCRIPT_FUNCTION_END();
2756 }
2757 
2758 //--------------------------------------------------------------------------------------------
scr_EnchantChild(script_state_t * pstate,ai_state_t * pself)2759 Uint8 scr_EnchantChild( script_state_t * pstate, ai_state_t * pself )
2760 {
2761     // EnchantChild()
2762     /// @details ZZ@> This function can be used with SpawnCharacter to enchant the
2763     /// newly spawned character with the enchantment
2764     /// given in enchant.txt. Make sure you use set_OwnerToTarget before doing this.
2765 
2766     ENC_REF iTmp;
2767 
2768     SCRIPT_FUNCTION_BEGIN();
2769 
2770     iTmp = spawn_one_enchant( pself->owner, pself->child, pself->index, ( ENC_REF )MAX_ENC, ( PRO_REF )MAX_PROFILE );
2771     returncode = DEFINED_ENC( iTmp );
2772 
2773     SCRIPT_FUNCTION_END();
2774 }
2775 
2776 //--------------------------------------------------------------------------------------------
scr_TeleportTarget(script_state_t * pstate,ai_state_t * pself)2777 Uint8 scr_TeleportTarget( script_state_t * pstate, ai_state_t * pself )
2778 {
2779     // TeleportTarget( tmpx = "x", tmpy = "y" )
2780     /// @details ZZ@> This function teleports the target to the X, Y location, failing if the
2781     /// location is off the map or blocked
2782 
2783     SCRIPT_FUNCTION_BEGIN();
2784 
2785     returncode = chr_teleport( pself->target, pstate->x, pstate->y, pstate->distance, pstate->turn );
2786 
2787     SCRIPT_FUNCTION_END();
2788 }
2789 
2790 //--------------------------------------------------------------------------------------------
scr_GiveExperienceToTarget(script_state_t * pstate,ai_state_t * pself)2791 Uint8 scr_GiveExperienceToTarget( script_state_t * pstate, ai_state_t * pself )
2792 {
2793     // GiveExperienceToTarget( tmpargument = "amount", tmpdistance = "type" )
2794     /// @details ZZ@> This function gives the target some experience, xptype from distance,
2795     /// amount from argument.
2796 
2797     SCRIPT_FUNCTION_BEGIN();
2798 
2799     give_experience( pself->target, pstate->argument, ( xp_type )pstate->distance, bfalse );
2800 
2801     SCRIPT_FUNCTION_END();
2802 }
2803 
2804 //--------------------------------------------------------------------------------------------
scr_IncreaseAmmo(script_state_t * pstate,ai_state_t * pself)2805 Uint8 scr_IncreaseAmmo( script_state_t * pstate, ai_state_t * pself )
2806 {
2807     // IncreaseAmmo()
2808     /// @details ZZ@> This function increases the character's ammo by 1
2809 
2810     SCRIPT_FUNCTION_BEGIN();
2811     if ( pchr->ammo < pchr->ammomax )
2812     {
2813         pchr->ammo++;
2814     }
2815 
2816     SCRIPT_FUNCTION_END();
2817 }
2818 
2819 //--------------------------------------------------------------------------------------------
scr_UnkurseTarget(script_state_t * pstate,ai_state_t * pself)2820 Uint8 scr_UnkurseTarget( script_state_t * pstate, ai_state_t * pself )
2821 {
2822     // UnkurseTarget()
2823     /// @details ZZ@> This function unkurses the target
2824 
2825     chr_t * pself_target;
2826 
2827     SCRIPT_FUNCTION_BEGIN();
2828 
2829     SCRIPT_REQUIRE_TARGET( pself_target );
2830 
2831     pself_target->iskursed = bfalse;
2832 
2833     SCRIPT_FUNCTION_END();
2834 }
2835 
2836 //--------------------------------------------------------------------------------------------
scr_GiveExperienceToTargetTeam(script_state_t * pstate,ai_state_t * pself)2837 Uint8 scr_GiveExperienceToTargetTeam( script_state_t * pstate, ai_state_t * pself )
2838 {
2839     // GiveExperienceToTargetTeam( tmpargument = "amount", tmpdistance = "type" )
2840     /// @details ZZ@> This function gives experience to everyone on the target's team
2841 
2842     SCRIPT_FUNCTION_BEGIN();
2843 
2844     give_team_experience( chr_get_iteam( pself->target ), pstate->argument, pstate->distance );
2845 
2846     SCRIPT_FUNCTION_END();
2847 }
2848 
2849 //--------------------------------------------------------------------------------------------
scr_Unarmed(script_state_t * pstate,ai_state_t * pself)2850 Uint8 scr_Unarmed( script_state_t * pstate, ai_state_t * pself )
2851 {
2852     // IfUnarmed()
2853     /// @details ZZ@> This function proceeds if the character is holding no items in hand.
2854 
2855     SCRIPT_FUNCTION_BEGIN();
2856 
2857     returncode = ( !INGAME_CHR( pchr->holdingwhich[SLOT_LEFT] ) && !INGAME_CHR( pchr->holdingwhich[SLOT_RIGHT] ) );
2858 
2859     SCRIPT_FUNCTION_END();
2860 }
2861 
2862 //--------------------------------------------------------------------------------------------
scr_RestockTargetAmmoIDAll(script_state_t * pstate,ai_state_t * pself)2863 Uint8 scr_RestockTargetAmmoIDAll( script_state_t * pstate, ai_state_t * pself )
2864 {
2865     // RestockTargetAmmoIDAll( tmpargument = "idsz" )
2866     /// @details ZZ@> This function restocks the ammo of every item the character is holding,
2867     /// if the item matches the ID given ( parent or child type )
2868 
2869     CHR_REF ichr;
2870     int iTmp;
2871     chr_t * pself_target;
2872 
2873     SCRIPT_FUNCTION_BEGIN();
2874 
2875     SCRIPT_REQUIRE_TARGET( pself_target );
2876 
2877     iTmp = 0;  // Amount of ammo given
2878 
2879     ichr = pself_target->holdingwhich[SLOT_LEFT];
2880     iTmp += restock_ammo( ichr, pstate->argument );
2881 
2882     ichr = pself_target->holdingwhich[SLOT_RIGHT];
2883     iTmp += restock_ammo( ichr, pstate->argument );
2884 
2885     PACK_BEGIN_LOOP( ipacked, pself_target->pack.next )
2886     {
2887         iTmp += restock_ammo( ipacked, pstate->argument );
2888     }
2889     PACK_END_LOOP( ipacked );
2890 
2891     pstate->argument = iTmp;
2892     returncode = ( iTmp != 0 );
2893 
2894     SCRIPT_FUNCTION_END();
2895 }
2896 
2897 //--------------------------------------------------------------------------------------------
scr_RestockTargetAmmoIDFirst(script_state_t * pstate,ai_state_t * pself)2898 Uint8 scr_RestockTargetAmmoIDFirst( script_state_t * pstate, ai_state_t * pself )
2899 {
2900     // RestockTargetAmmoIDFirst( tmpargument = "idsz" )
2901     /// @details ZZ@> This function restocks the ammo of the first item the character is holding,
2902     /// if the item matches the ID given ( parent or child type )
2903 
2904     int     iTmp;
2905     chr_t * pself_target;
2906 
2907     SCRIPT_FUNCTION_BEGIN();
2908 
2909     SCRIPT_REQUIRE_TARGET( pself_target );
2910 
2911     iTmp = 0;  // Amount of ammo given
2912 
2913     if ( 0 == iTmp )
2914     {
2915         PACK_BEGIN_LOOP( ipacked, pself_target->holdingwhich[SLOT_LEFT] )
2916         {
2917             iTmp += restock_ammo( ipacked, pstate->argument );
2918             if ( 0 != iTmp ) break;
2919         }
2920         PACK_END_LOOP( ipacked )
2921     }
2922 
2923     if ( 0 == iTmp )
2924     {
2925         PACK_BEGIN_LOOP( ipacked, pself_target->holdingwhich[SLOT_RIGHT] )
2926         {
2927             iTmp += restock_ammo( ipacked, pstate->argument );
2928             if ( 0 != iTmp ) break;
2929         }
2930         PACK_END_LOOP( ipacked )
2931     }
2932 
2933     pstate->argument = iTmp;
2934     returncode = ( iTmp != 0 );
2935 
2936     SCRIPT_FUNCTION_END();
2937 }
2938 
2939 //--------------------------------------------------------------------------------------------
scr_FlashTarget(script_state_t * pstate,ai_state_t * pself)2940 Uint8 scr_FlashTarget( script_state_t * pstate, ai_state_t * pself )
2941 {
2942     // FlashTarget()
2943     /// @details ZZ@> This function makes the target flash
2944 
2945     SCRIPT_FUNCTION_BEGIN();
2946 
2947     flash_character( pself->target, 255 );
2948 
2949     SCRIPT_FUNCTION_END();
2950 }
2951 
2952 //--------------------------------------------------------------------------------------------
scr_set_RedShift(script_state_t * pstate,ai_state_t * pself)2953 Uint8 scr_set_RedShift( script_state_t * pstate, ai_state_t * pself )
2954 {
2955     // SetRedShift( tmpargument = "red darkening" )
2956     /// @details ZZ@> This function sets the character's red shift ( 0 - 3 ), higher values
2957     /// making the character less red and darker
2958 
2959     SCRIPT_FUNCTION_BEGIN();
2960 
2961     chr_set_redshift( pchr, pstate->argument );
2962 
2963     SCRIPT_FUNCTION_END();
2964 }
2965 
2966 //--------------------------------------------------------------------------------------------
scr_set_GreenShift(script_state_t * pstate,ai_state_t * pself)2967 Uint8 scr_set_GreenShift( script_state_t * pstate, ai_state_t * pself )
2968 {
2969     // SetGreenShift( tmpargument = "green darkening" )
2970     /// @details ZZ@> This function sets the character's green shift ( 0 - 3 ), higher values
2971     /// making the character less red and darker
2972 
2973     SCRIPT_FUNCTION_BEGIN();
2974 
2975     chr_set_grnshift( pchr, pstate->argument );
2976 
2977     SCRIPT_FUNCTION_END();
2978 }
2979 
2980 //--------------------------------------------------------------------------------------------
scr_set_BlueShift(script_state_t * pstate,ai_state_t * pself)2981 Uint8 scr_set_BlueShift( script_state_t * pstate, ai_state_t * pself )
2982 {
2983     // SetBlueShift( tmpargument = "blue darkening" )
2984     /// @details ZZ@> This function sets the character's blue shift ( 0 - 3 ), higher values
2985     /// making the character less red and darker
2986 
2987     SCRIPT_FUNCTION_BEGIN();
2988 
2989     chr_set_grnshift( pchr, pstate->argument );
2990 
2991     SCRIPT_FUNCTION_END();
2992 }
2993 
2994 //--------------------------------------------------------------------------------------------
scr_set_Light(script_state_t * pstate,ai_state_t * pself)2995 Uint8 scr_set_Light( script_state_t * pstate, ai_state_t * pself )
2996 {
2997     // SetLight( tmpargument = "lighness" )
2998     /// @details ZZ@> This function alters the character's transparency ( 0 - 254 )
2999     /// 255 = no transparency
3000 
3001     SCRIPT_FUNCTION_BEGIN();
3002 
3003     chr_set_light( pchr, pstate->argument );
3004 
3005     SCRIPT_FUNCTION_END();
3006 }
3007 
3008 //--------------------------------------------------------------------------------------------
scr_set_Alpha(script_state_t * pstate,ai_state_t * pself)3009 Uint8 scr_set_Alpha( script_state_t * pstate, ai_state_t * pself )
3010 {
3011     // SetAlpha( tmpargument = "alpha" )
3012     /// @details ZZ@> This function alters the character's transparency ( 0 - 255 )
3013     /// 255 = no transparency
3014 
3015     SCRIPT_FUNCTION_BEGIN();
3016 
3017     chr_set_alpha( pchr, pstate->argument );
3018 
3019     SCRIPT_FUNCTION_END();
3020 }
3021 
3022 //--------------------------------------------------------------------------------------------
scr_HitFromBehind(script_state_t * pstate,ai_state_t * pself)3023 Uint8 scr_HitFromBehind( script_state_t * pstate, ai_state_t * pself )
3024 {
3025     // IfHitFromBehind()
3026     /// @details ZZ@> This function proceeds if the last attack to the character came from behind
3027 
3028     SCRIPT_FUNCTION_BEGIN();
3029 
3030     returncode = bfalse;
3031     if ( pself->directionlast >= ATK_BEHIND - 8192 && pself->directionlast < ATK_BEHIND + 8192 )
3032         returncode = btrue;
3033 
3034     SCRIPT_FUNCTION_END();
3035 }
3036 
3037 //--------------------------------------------------------------------------------------------
scr_HitFromFront(script_state_t * pstate,ai_state_t * pself)3038 Uint8 scr_HitFromFront( script_state_t * pstate, ai_state_t * pself )
3039 {
3040     // IfHitFromFront()
3041     /// @details ZZ@> This function proceeds if the last attack to the character came
3042     /// from the front
3043 
3044     SCRIPT_FUNCTION_BEGIN();
3045 
3046     returncode = bfalse;
3047     if ( pself->directionlast >= ATK_LEFT + 8192 || pself->directionlast < ATK_FRONT + 8192 )
3048         returncode = btrue;
3049 
3050     SCRIPT_FUNCTION_END();
3051 }
3052 
3053 //--------------------------------------------------------------------------------------------
scr_HitFromLeft(script_state_t * pstate,ai_state_t * pself)3054 Uint8 scr_HitFromLeft( script_state_t * pstate, ai_state_t * pself )
3055 {
3056     // IfHitFromLeft()
3057     /// @details ZZ@> This function proceeds if the last attack to the character came
3058     /// from the left
3059 
3060     SCRIPT_FUNCTION_BEGIN();
3061 
3062     returncode = bfalse;
3063     if ( pself->directionlast >= ATK_LEFT - 8192 && pself->directionlast < ATK_LEFT + 8192 )
3064         returncode = btrue;
3065 
3066     SCRIPT_FUNCTION_END();
3067 }
3068 
3069 //--------------------------------------------------------------------------------------------
scr_HitFromRight(script_state_t * pstate,ai_state_t * pself)3070 Uint8 scr_HitFromRight( script_state_t * pstate, ai_state_t * pself )
3071 {
3072     // IfHitFromRight()
3073     /// @details ZZ@> This function proceeds if the last attack to the character came
3074     /// from the right
3075 
3076     SCRIPT_FUNCTION_BEGIN();
3077 
3078     returncode = bfalse;
3079     if ( pself->directionlast >= ATK_RIGHT - 8192 && pself->directionlast < ATK_RIGHT + 8192 )
3080         returncode = btrue;
3081 
3082     SCRIPT_FUNCTION_END();
3083 }
3084 
3085 //--------------------------------------------------------------------------------------------
scr_TargetIsOnSameTeam(script_state_t * pstate,ai_state_t * pself)3086 Uint8 scr_TargetIsOnSameTeam( script_state_t * pstate, ai_state_t * pself )
3087 {
3088     // IfTargetIsOnSameTeam()
3089     /// @details ZZ@> This function proceeds if the target is on the character's team
3090 
3091     SCRIPT_FUNCTION_BEGIN();
3092 
3093     returncode = bfalse;
3094     if ( chr_get_iteam( pself->target ) == pchr->team )
3095         returncode = btrue;
3096 
3097     SCRIPT_FUNCTION_END();
3098 }
3099 
3100 //--------------------------------------------------------------------------------------------
scr_KillTarget(script_state_t * pstate,ai_state_t * pself)3101 Uint8 scr_KillTarget( script_state_t * pstate, ai_state_t * pself )
3102 {
3103     // KillTarget()
3104     /// @details ZZ@> This function kills the target
3105 
3106     CHR_REF ichr;
3107 
3108     SCRIPT_FUNCTION_BEGIN();
3109 
3110     ichr = pself->index;
3111 
3112     //Weapons don't kill people, people kill people...
3113     if ( INGAME_CHR( pchr->attachedto ) && !ChrList.lst[pchr->attachedto].ismount )
3114     {
3115         ichr = pchr->attachedto;
3116     }
3117 
3118     kill_character( pself->target, ichr, bfalse );
3119 
3120     SCRIPT_FUNCTION_END();
3121 }
3122 
3123 //--------------------------------------------------------------------------------------------
scr_UndoEnchant(script_state_t * pstate,ai_state_t * pself)3124 Uint8 scr_UndoEnchant( script_state_t * pstate, ai_state_t * pself )
3125 {
3126     // UndoEnchant()
3127     /// @details ZZ@> This function removes the last enchantment spawned by the character,
3128     /// proceeding if an enchantment was removed
3129 
3130     SCRIPT_FUNCTION_BEGIN();
3131 
3132     if ( INGAME_ENC( pchr->undoenchant ) )
3133     {
3134         returncode = remove_enchant( pchr->undoenchant, NULL );
3135     }
3136     else
3137     {
3138         pchr->undoenchant = MAX_ENC;
3139         returncode = bfalse;
3140     }
3141 
3142     SCRIPT_FUNCTION_END();
3143 }
3144 
3145 //--------------------------------------------------------------------------------------------
scr_get_WaterLevel(script_state_t * pstate,ai_state_t * pself)3146 Uint8 scr_get_WaterLevel( script_state_t * pstate, ai_state_t * pself )
3147 {
3148     // tmpargument = GetWaterLevel()
3149     /// @details ZZ@> This function sets tmpargument to the current douse level for the water * 10.
3150     /// A waterlevel in wawalight of 85 would set tmpargument to 850
3151 
3152     SCRIPT_FUNCTION_BEGIN();
3153 
3154     pstate->argument = water.douse_level * 10;
3155 
3156     SCRIPT_FUNCTION_END();
3157 }
3158 
3159 //--------------------------------------------------------------------------------------------
scr_CostTargetMana(script_state_t * pstate,ai_state_t * pself)3160 Uint8 scr_CostTargetMana( script_state_t * pstate, ai_state_t * pself )
3161 {
3162     // CostTargetMana( tmpargument = "amount" )
3163     /// @details ZZ@> This function costs the target a specific amount of mana, proceeding
3164     /// if the target was able to pay the price.  The amounts are 8.8-bit fixed point
3165 
3166     SCRIPT_FUNCTION_BEGIN();
3167 
3168     returncode = cost_mana( pself->target, pstate->argument, pself->index );
3169 
3170     SCRIPT_FUNCTION_END();
3171 }
3172 
3173 //--------------------------------------------------------------------------------------------
scr_TargetHasAnyID(script_state_t * pstate,ai_state_t * pself)3174 Uint8 scr_TargetHasAnyID( script_state_t * pstate, ai_state_t * pself )
3175 {
3176     // IfTargetHasAnyID( tmpargument = "idsz" )
3177     /// @details ZZ@> This function proceeds if the target has any IDSZ that matches the given one
3178 
3179     SCRIPT_FUNCTION_BEGIN();
3180 
3181     returncode = chr_has_idsz( pself->target, pstate->argument );
3182 
3183     SCRIPT_FUNCTION_END();
3184 }
3185 
3186 //--------------------------------------------------------------------------------------------
scr_set_BumpSize(script_state_t * pstate,ai_state_t * pself)3187 Uint8 scr_set_BumpSize( script_state_t * pstate, ai_state_t * pself )
3188 {
3189     // SetBumpSize( tmpargument = "size" )
3190     /// @details ZZ@> This function sets the how wide the character is
3191 
3192     SCRIPT_FUNCTION_BEGIN();
3193 
3194     chr_set_width( pchr, pstate->argument );
3195 
3196     SCRIPT_FUNCTION_END();
3197 }
3198 
3199 //--------------------------------------------------------------------------------------------
scr_NotDropped(script_state_t * pstate,ai_state_t * pself)3200 Uint8 scr_NotDropped( script_state_t * pstate, ai_state_t * pself )
3201 {
3202     // IfNotDropped()
3203     /// @details ZZ@> This function proceeds if the character is kursed and another character
3204     /// was holding it and tried to drop it
3205 
3206     SCRIPT_FUNCTION_BEGIN();
3207 
3208     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_NOTDROPPED );
3209 
3210     SCRIPT_FUNCTION_END();
3211 }
3212 
3213 //--------------------------------------------------------------------------------------------
scr_YIsLessThanX(script_state_t * pstate,ai_state_t * pself)3214 Uint8 scr_YIsLessThanX( script_state_t * pstate, ai_state_t * pself )
3215 {
3216     // IfYIsLessThanX()
3217     /// @details ZZ@> This function proceeds if tmpy is less than tmpx
3218 
3219     SCRIPT_FUNCTION_BEGIN();
3220 
3221     returncode = ( pstate->y < pstate->x );
3222 
3223     SCRIPT_FUNCTION_END();
3224 }
3225 
3226 //--------------------------------------------------------------------------------------------
scr_set_FlyHeight(script_state_t * pstate,ai_state_t * pself)3227 Uint8 scr_set_FlyHeight( script_state_t * pstate, ai_state_t * pself )
3228 {
3229     // SetFlyHeight( tmpargument = "height" )
3230     /// @details ZZ@> This function makes the character fly ( or fall to ground if 0 )
3231 
3232     SCRIPT_FUNCTION_BEGIN();
3233 
3234     pchr->flyheight = pstate->argument;
3235 
3236     SCRIPT_FUNCTION_END();
3237 }
3238 
3239 //--------------------------------------------------------------------------------------------
scr_Blocked(script_state_t * pstate,ai_state_t * pself)3240 Uint8 scr_Blocked( script_state_t * pstate, ai_state_t * pself )
3241 {
3242     // IfBlocked()
3243     /// @details ZZ@> This function proceeds if the character blocked the attack of another
3244     /// character this update
3245 
3246     SCRIPT_FUNCTION_BEGIN();
3247 
3248     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_BLOCKED );
3249 
3250     SCRIPT_FUNCTION_END();
3251 }
3252 
3253 //--------------------------------------------------------------------------------------------
scr_TargetIsDefending(script_state_t * pstate,ai_state_t * pself)3254 Uint8 scr_TargetIsDefending( script_state_t * pstate, ai_state_t * pself )
3255 {
3256     // IfTargetIsDefending()
3257     /// @details ZZ@> This function proceeds if the target is holding up a shield or similar
3258     /// defense
3259 
3260     chr_t * pself_target;
3261 
3262     SCRIPT_FUNCTION_BEGIN();
3263 
3264     SCRIPT_REQUIRE_TARGET( pself_target );
3265 
3266     returncode = ACTION_IS_TYPE( pself_target->inst.action_which, P );
3267 
3268     SCRIPT_FUNCTION_END();
3269 }
3270 
3271 //--------------------------------------------------------------------------------------------
scr_TargetIsAttacking(script_state_t * pstate,ai_state_t * pself)3272 Uint8 scr_TargetIsAttacking( script_state_t * pstate, ai_state_t * pself )
3273 {
3274     // IfTargetIsAttacking()
3275     /// @details ZZ@> This function proceeds if the target is doing an attack action
3276 
3277     chr_t * pself_target;
3278 
3279     SCRIPT_FUNCTION_BEGIN();
3280 
3281     SCRIPT_REQUIRE_TARGET( pself_target );
3282 
3283     returncode = character_is_attacking( pself_target );
3284 
3285     SCRIPT_FUNCTION_END();
3286 }
3287 
3288 //--------------------------------------------------------------------------------------------
scr_StateIs0(script_state_t * pstate,ai_state_t * pself)3289 Uint8 scr_StateIs0( script_state_t * pstate, ai_state_t * pself )
3290 {
3291     SCRIPT_FUNCTION_BEGIN();
3292 
3293     returncode = ( 0 == pself->state );
3294 
3295     SCRIPT_FUNCTION_END();
3296 }
3297 
3298 //--------------------------------------------------------------------------------------------
scr_StateIs1(script_state_t * pstate,ai_state_t * pself)3299 Uint8 scr_StateIs1( script_state_t * pstate, ai_state_t * pself )
3300 {
3301     SCRIPT_FUNCTION_BEGIN();
3302 
3303     returncode = ( 1 == pself->state );
3304 
3305     SCRIPT_FUNCTION_END();
3306 }
3307 
3308 //--------------------------------------------------------------------------------------------
scr_StateIs2(script_state_t * pstate,ai_state_t * pself)3309 Uint8 scr_StateIs2( script_state_t * pstate, ai_state_t * pself )
3310 {
3311     SCRIPT_FUNCTION_BEGIN();
3312 
3313     returncode = ( 2 == pself->state );
3314 
3315     SCRIPT_FUNCTION_END();
3316 }
3317 
3318 //--------------------------------------------------------------------------------------------
scr_StateIs3(script_state_t * pstate,ai_state_t * pself)3319 Uint8 scr_StateIs3( script_state_t * pstate, ai_state_t * pself )
3320 {
3321     SCRIPT_FUNCTION_BEGIN();
3322 
3323     returncode = ( 3 == pself->state );
3324 
3325     SCRIPT_FUNCTION_END();
3326 }
3327 
3328 //--------------------------------------------------------------------------------------------
scr_StateIs4(script_state_t * pstate,ai_state_t * pself)3329 Uint8 scr_StateIs4( script_state_t * pstate, ai_state_t * pself )
3330 {
3331     SCRIPT_FUNCTION_BEGIN();
3332 
3333     returncode = ( 4 == pself->state );
3334 
3335     SCRIPT_FUNCTION_END();
3336 }
3337 
3338 //--------------------------------------------------------------------------------------------
scr_StateIs5(script_state_t * pstate,ai_state_t * pself)3339 Uint8 scr_StateIs5( script_state_t * pstate, ai_state_t * pself )
3340 {
3341     SCRIPT_FUNCTION_BEGIN();
3342 
3343     returncode = ( 5 == pself->state );
3344 
3345     SCRIPT_FUNCTION_END();
3346 }
3347 
3348 //--------------------------------------------------------------------------------------------
scr_StateIs6(script_state_t * pstate,ai_state_t * pself)3349 Uint8 scr_StateIs6( script_state_t * pstate, ai_state_t * pself )
3350 {
3351     SCRIPT_FUNCTION_BEGIN();
3352 
3353     returncode = ( 6 == pself->state );
3354 
3355     SCRIPT_FUNCTION_END();
3356 }
3357 
3358 //--------------------------------------------------------------------------------------------
scr_StateIs7(script_state_t * pstate,ai_state_t * pself)3359 Uint8 scr_StateIs7( script_state_t * pstate, ai_state_t * pself )
3360 {
3361     SCRIPT_FUNCTION_BEGIN();
3362 
3363     returncode = ( 7 == pself->state );
3364 
3365     SCRIPT_FUNCTION_END();
3366 }
3367 
3368 //--------------------------------------------------------------------------------------------
scr_ContentIs(script_state_t * pstate,ai_state_t * pself)3369 Uint8 scr_ContentIs( script_state_t * pstate, ai_state_t * pself )
3370 {
3371     // IfContentIs( tmpargument = "test" )
3372     /// @details ZZ@> This function proceeds if the content matches tmpargument
3373 
3374     SCRIPT_FUNCTION_BEGIN();
3375 
3376     returncode = ( pstate->argument == pself->content );
3377 
3378     SCRIPT_FUNCTION_END();
3379 }
3380 
3381 //--------------------------------------------------------------------------------------------
scr_set_TurnModeToWatchTarget(script_state_t * pstate,ai_state_t * pself)3382 Uint8 scr_set_TurnModeToWatchTarget( script_state_t * pstate, ai_state_t * pself )
3383 {
3384     // SetTurnModeToWatchTarget()
3385     /// @details ZZ@> This function makes the character face its target, no matter what
3386     /// direction it is moving in.  Undo this with set_TurnModeToVelocity
3387 
3388     SCRIPT_FUNCTION_BEGIN();
3389 
3390     pchr->turnmode = TURNMODE_WATCHTARGET;
3391 
3392     SCRIPT_FUNCTION_END();
3393 }
3394 
3395 //--------------------------------------------------------------------------------------------
scr_StateIsNot(script_state_t * pstate,ai_state_t * pself)3396 Uint8 scr_StateIsNot( script_state_t * pstate, ai_state_t * pself )
3397 {
3398     // IfStateIsNot( tmpargument = "test" )
3399     /// @details ZZ@> This function proceeds if the character's state does not equal tmpargument
3400 
3401     SCRIPT_FUNCTION_BEGIN();
3402 
3403     returncode = ( pstate->argument != pself->state );
3404 
3405     SCRIPT_FUNCTION_END();
3406 }
3407 
3408 //--------------------------------------------------------------------------------------------
scr_XIsEqualToY(script_state_t * pstate,ai_state_t * pself)3409 Uint8 scr_XIsEqualToY( script_state_t * pstate, ai_state_t * pself )
3410 {
3411     // These functions proceed if tmpx and tmpy are the same
3412 
3413     SCRIPT_FUNCTION_BEGIN();
3414 
3415     returncode = ( pstate->x == pstate->y );
3416 
3417     SCRIPT_FUNCTION_END();
3418 }
3419 
3420 //--------------------------------------------------------------------------------------------
scr_DebugMessage(script_state_t * pstate,ai_state_t * pself)3421 Uint8 scr_DebugMessage( script_state_t * pstate, ai_state_t * pself )
3422 {
3423     // DebugMessage()
3424     /// @details ZZ@> This function spits out some useful numbers
3425 
3426     SCRIPT_FUNCTION_BEGIN();
3427 
3428     debug_printf( "aistate %d, aicontent %d, target %d", pself->state, pself->content, REF_TO_INT( pself->target ) );
3429     debug_printf( "tmpx %d, tmpy %d", pstate->x, pstate->y );
3430     debug_printf( "tmpdistance %d, tmpturn %d", pstate->distance, pstate->turn );
3431     debug_printf( "tmpargument %d, selfturn %d", pstate->argument, pchr->ori.facing_z );
3432 
3433     SCRIPT_FUNCTION_END();
3434 }
3435 
3436 //--------------------------------------------------------------------------------------------
scr_BlackTarget(script_state_t * pstate,ai_state_t * pself)3437 Uint8 scr_BlackTarget( script_state_t * pstate, ai_state_t * pself )
3438 {
3439     // BlackTarget()
3440     /// @details ZZ@>  The opposite of FlashTarget, causing the target to turn black
3441 
3442     SCRIPT_FUNCTION_BEGIN();
3443 
3444     flash_character( pself->target, 0 );
3445 
3446     SCRIPT_FUNCTION_END();
3447 }
3448 
3449 //--------------------------------------------------------------------------------------------
scr_SendMessageNear(script_state_t * pstate,ai_state_t * pself)3450 Uint8 scr_SendMessageNear( script_state_t * pstate, ai_state_t * pself )
3451 {
3452     // SendMessageNear( tmpargument = "message" )
3453     /// @details ZZ@> This function sends a message if the camera is in the nearby area
3454 
3455     int iTmp;
3456 
3457     SCRIPT_FUNCTION_BEGIN();
3458 
3459     iTmp = ABS( pchr->pos_old.x - PCamera->track_pos.x ) + ABS( pchr->pos_old.y - PCamera->track_pos.y );
3460     if ( iTmp < MSGDISTANCE )
3461     {
3462         returncode = _display_message( pself->index, pchr->profile_ref, pstate->argument, pstate );
3463     }
3464 
3465     SCRIPT_FUNCTION_END();
3466 }
3467 
3468 //--------------------------------------------------------------------------------------------
scr_HitGround(script_state_t * pstate,ai_state_t * pself)3469 Uint8 scr_HitGround( script_state_t * pstate, ai_state_t * pself )
3470 {
3471     // IfHitGround()
3472     /// @details ZZ@> This function proceeds if a character hit the ground this update.
3473     /// Used to determine when to play the sound for a dropped item
3474 
3475     SCRIPT_FUNCTION_BEGIN();
3476 
3477     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_HITGROUND );
3478 
3479     SCRIPT_FUNCTION_END();
3480 }
3481 
3482 //--------------------------------------------------------------------------------------------
scr_NameIsKnown(script_state_t * pstate,ai_state_t * pself)3483 Uint8 scr_NameIsKnown( script_state_t * pstate, ai_state_t * pself )
3484 {
3485     // IfNameIsKnown()
3486     /// @details ZZ@> This function proceeds if the character's name is known
3487 
3488     SCRIPT_FUNCTION_BEGIN();
3489 
3490     returncode = pchr->nameknown;
3491 
3492     SCRIPT_FUNCTION_END();
3493 }
3494 
3495 //--------------------------------------------------------------------------------------------
scr_UsageIsKnown(script_state_t * pstate,ai_state_t * pself)3496 Uint8 scr_UsageIsKnown( script_state_t * pstate, ai_state_t * pself )
3497 {
3498     // IfUsageIsKnown()
3499     /// @details ZZ@> This function proceeds if the character's usage is known
3500 
3501     cap_t * pcap;
3502 
3503     SCRIPT_FUNCTION_BEGIN();
3504 
3505     pcap = pro_get_pcap( pchr->profile_ref );
3506 
3507     returncode = bfalse;
3508     if ( NULL != pcap )
3509     {
3510         returncode = pcap->usageknown;
3511     }
3512 
3513     SCRIPT_FUNCTION_END();
3514 }
3515 
3516 //--------------------------------------------------------------------------------------------
scr_HoldingItemID(script_state_t * pstate,ai_state_t * pself)3517 Uint8 scr_HoldingItemID( script_state_t * pstate, ai_state_t * pself )
3518 {
3519     // IfHoldingItemID( tmpargument = "idsz" )
3520     /// @details ZZ@> This function proceeds if the character is holding a specified item
3521     /// in hand, setting tmpargument to the latch button to press to use it
3522 
3523     CHR_REF item;
3524 
3525     SCRIPT_FUNCTION_BEGIN();
3526 
3527     item = chr_holding_idsz( pself->index, pstate->argument );
3528 
3529     returncode = INGAME_CHR( item );
3530 
3531     SCRIPT_FUNCTION_END();
3532 }
3533 
3534 //--------------------------------------------------------------------------------------------
scr_HoldingRangedWeapon(script_state_t * pstate,ai_state_t * pself)3535 Uint8 scr_HoldingRangedWeapon( script_state_t * pstate, ai_state_t * pself )
3536 {
3537     // IfHoldingRangedWeapon()
3538     /// @details ZZ@> This function passes if the character is holding a ranged weapon, returning
3539     /// the latch to press to use it.  This also checks ammo/ammoknown.
3540 
3541     CHR_REF ichr;
3542 
3543     SCRIPT_FUNCTION_BEGIN();
3544 
3545     returncode = bfalse;
3546     pstate->argument = 0;
3547 
3548     // Check right hand
3549     ichr = pchr->holdingwhich[SLOT_RIGHT];
3550     if ( INGAME_CHR( ichr ) )
3551     {
3552         cap_t * pcap = chr_get_pcap( ichr );
3553 
3554         if ( NULL != pcap && pcap->isranged && ( 0 == ChrList.lst[ichr].ammomax || ( 0 != ChrList.lst[ichr].ammo && ChrList.lst[ichr].ammoknown ) ) )
3555         {
3556             if ( 0 == pstate->argument || ( update_wld & 1 ) )
3557             {
3558                 pstate->argument = LATCHBUTTON_RIGHT;
3559                 returncode = btrue;
3560             }
3561         }
3562     }
3563 
3564     if ( !returncode )
3565     {
3566         // Check left hand
3567         ichr = pchr->holdingwhich[SLOT_LEFT];
3568         if ( INGAME_CHR( ichr ) )
3569         {
3570             cap_t * pcap = chr_get_pcap( ichr );
3571 
3572             if ( NULL != pcap && pcap->isranged && ( 0 == ChrList.lst[ichr].ammomax || ( 0 != ChrList.lst[ichr].ammo && ChrList.lst[ichr].ammoknown ) ) )
3573             {
3574                 pstate->argument = LATCHBUTTON_LEFT;
3575                 returncode = btrue;
3576             }
3577         }
3578 
3579     }
3580 
3581     SCRIPT_FUNCTION_END();
3582 }
3583 
3584 //--------------------------------------------------------------------------------------------
scr_HoldingMeleeWeapon(script_state_t * pstate,ai_state_t * pself)3585 Uint8 scr_HoldingMeleeWeapon( script_state_t * pstate, ai_state_t * pself )
3586 {
3587     // IfHoldingMeleeWeapon()
3588     /// @details ZZ@> This function proceeds if the character is holding a specified item
3589     /// in hand, setting tmpargument to the latch button to press to use it
3590 
3591     CHR_REF ichr;
3592 
3593     SCRIPT_FUNCTION_BEGIN();
3594 
3595     returncode = bfalse;
3596     pstate->argument = 0;
3597 
3598     if ( !returncode )
3599     {
3600         // Check right hand
3601         ichr = pchr->holdingwhich[SLOT_RIGHT];
3602         if ( INGAME_CHR( ichr ) )
3603         {
3604             cap_t * pcap = chr_get_pcap( ichr );
3605 
3606             if ( NULL != pcap && !pcap->isranged && pcap->weaponaction != ACTION_PA )
3607             {
3608                 if ( 0 == pstate->argument || ( update_wld & 1 ) )
3609                 {
3610                     pstate->argument = LATCHBUTTON_RIGHT;
3611                     returncode = btrue;
3612                 }
3613             }
3614         }
3615     }
3616 
3617     if ( !returncode )
3618     {
3619         // Check left hand
3620         ichr = pchr->holdingwhich[SLOT_LEFT];
3621         if ( INGAME_CHR( ichr ) )
3622         {
3623             cap_t * pcap = chr_get_pcap( ichr );
3624 
3625             if ( NULL != pcap && !pcap->isranged && pcap->weaponaction != ACTION_PA )
3626             {
3627                 pstate->argument = LATCHBUTTON_LEFT;
3628                 returncode = btrue;
3629             }
3630         }
3631     }
3632 
3633     SCRIPT_FUNCTION_END();
3634 }
3635 
3636 //--------------------------------------------------------------------------------------------
scr_HoldingShield(script_state_t * pstate,ai_state_t * pself)3637 Uint8 scr_HoldingShield( script_state_t * pstate, ai_state_t * pself )
3638 {
3639     // IfHoldingShield()
3640     /// @details ZZ@> This function proceeds if the character is holding a specified item
3641     /// in hand, setting tmpargument to the latch button to press to use it. The button will need to be held down.
3642 
3643     CHR_REF ichr;
3644 
3645     SCRIPT_FUNCTION_BEGIN();
3646 
3647     returncode = bfalse;
3648     pstate->argument = 0;
3649 
3650     if ( !returncode )
3651     {
3652         // Check right hand
3653         ichr = pchr->holdingwhich[SLOT_RIGHT];
3654         if ( INGAME_CHR( ichr ) )
3655         {
3656             cap_t * pcap = chr_get_pcap( ichr );
3657 
3658             if ( NULL != pcap && pcap->weaponaction == ACTION_PA )
3659             {
3660                 pstate->argument = LATCHBUTTON_RIGHT;
3661                 returncode = btrue;
3662             }
3663         }
3664     }
3665 
3666     if ( !returncode )
3667     {
3668         // Check left hand
3669         ichr = pchr->holdingwhich[SLOT_LEFT];
3670         if ( INGAME_CHR( ichr ) )
3671         {
3672             cap_t * pcap = chr_get_pcap( ichr );
3673 
3674             if ( NULL != pcap && pcap->weaponaction == ACTION_PA )
3675             {
3676                 pstate->argument = LATCHBUTTON_LEFT;
3677                 returncode = btrue;
3678             }
3679         }
3680     }
3681 
3682     SCRIPT_FUNCTION_END();
3683 }
3684 
3685 //--------------------------------------------------------------------------------------------
scr_Kursed(script_state_t * pstate,ai_state_t * pself)3686 Uint8 scr_Kursed( script_state_t * pstate, ai_state_t * pself )
3687 {
3688     // IfKursed()
3689     /// @details ZZ@> This function proceeds if the character is kursed
3690 
3691     SCRIPT_FUNCTION_BEGIN();
3692 
3693     returncode = pchr->iskursed;
3694 
3695     SCRIPT_FUNCTION_END();
3696 }
3697 
3698 //--------------------------------------------------------------------------------------------
scr_TargetIsKursed(script_state_t * pstate,ai_state_t * pself)3699 Uint8 scr_TargetIsKursed( script_state_t * pstate, ai_state_t * pself )
3700 {
3701     // IfTargetIsKursed()
3702     /// @details ZZ@> This function proceeds if the target is kursed
3703 
3704     chr_t * pself_target;
3705 
3706     SCRIPT_FUNCTION_BEGIN();
3707 
3708     SCRIPT_REQUIRE_TARGET( pself_target );
3709 
3710     returncode = pself_target->iskursed;
3711 
3712     SCRIPT_FUNCTION_END();
3713 }
3714 
3715 //--------------------------------------------------------------------------------------------
scr_TargetIsDressedUp(script_state_t * pstate,ai_state_t * pself)3716 Uint8 scr_TargetIsDressedUp( script_state_t * pstate, ai_state_t * pself )
3717 {
3718     // IfTargetIsDressedUp()
3719     /// @details ZZ@> This function proceeds if the target is dressed in fancy clothes
3720 
3721     cap_t * pcap;
3722 
3723     SCRIPT_FUNCTION_BEGIN();
3724 
3725     pcap = pro_get_pcap( pchr->profile_ref );
3726 
3727     returncode = bfalse;
3728     if ( NULL != pcap )
3729     {
3730         returncode = HAS_SOME_BITS( pcap->skindressy, 1 << pchr->skin );
3731     }
3732 
3733     SCRIPT_FUNCTION_END();
3734 }
3735 
3736 //--------------------------------------------------------------------------------------------
scr_OverWater(script_state_t * pstate,ai_state_t * pself)3737 Uint8 scr_OverWater( script_state_t * pstate, ai_state_t * pself )
3738 {
3739     // IfOverWater()
3740     /// @details ZZ@> This function proceeds if the character is on a water tile
3741 
3742     SCRIPT_FUNCTION_BEGIN();
3743 
3744     returncode = chr_is_over_water( pchr );
3745 
3746     SCRIPT_FUNCTION_END();
3747 }
3748 
3749 //--------------------------------------------------------------------------------------------
scr_Thrown(script_state_t * pstate,ai_state_t * pself)3750 Uint8 scr_Thrown( script_state_t * pstate, ai_state_t * pself )
3751 {
3752     // IfThrown()
3753     /// @details ZZ@> This function proceeds if the character was thrown this update.
3754 
3755     SCRIPT_FUNCTION_BEGIN();
3756 
3757     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_THROWN );
3758 
3759     SCRIPT_FUNCTION_END();
3760 }
3761 
3762 //--------------------------------------------------------------------------------------------
scr_MakeNameKnown(script_state_t * pstate,ai_state_t * pself)3763 Uint8 scr_MakeNameKnown( script_state_t * pstate, ai_state_t * pself )
3764 {
3765     // MakeNameKnown()
3766     /// @details ZZ@> This function makes the name of the character known, for identifying
3767     /// weapons and spells and such
3768 
3769     SCRIPT_FUNCTION_BEGIN();
3770 
3771     pchr->nameknown = btrue;
3772     //           pchr->icon = btrue;
3773 
3774     SCRIPT_FUNCTION_END();
3775 }
3776 
3777 //--------------------------------------------------------------------------------------------
scr_MakeUsageKnown(script_state_t * pstate,ai_state_t * pself)3778 Uint8 scr_MakeUsageKnown( script_state_t * pstate, ai_state_t * pself )
3779 {
3780     // MakeUsageKnown()
3781     /// @details ZZ@> This function makes the usage known for this type of object
3782     /// For XP gains from using an unknown potion or such
3783 
3784     cap_t * pcap;
3785 
3786     SCRIPT_FUNCTION_BEGIN();
3787 
3788     pcap = pro_get_pcap( pchr->profile_ref );
3789 
3790     returncode = bfalse;
3791     if ( NULL != pcap )
3792     {
3793         pcap->usageknown = btrue;
3794         returncode       = btrue;
3795     }
3796 
3797     SCRIPT_FUNCTION_END();
3798 }
3799 
3800 //--------------------------------------------------------------------------------------------
scr_StopTargetMovement(script_state_t * pstate,ai_state_t * pself)3801 Uint8 scr_StopTargetMovement( script_state_t * pstate, ai_state_t * pself )
3802 {
3803     // StopTargetMovement()
3804     /// @details ZZ@> This function makes the target stop moving temporarily
3805     /// Sets the target's x and y velocities to 0, and
3806     /// sets the z velocity to 0 if the character is moving upwards.
3807     /// This is a special function for the IronBall object
3808 
3809     chr_t * pself_target;
3810 
3811     SCRIPT_FUNCTION_BEGIN();
3812 
3813     SCRIPT_REQUIRE_TARGET( pself_target );
3814 
3815     pself_target->vel.x = 0;
3816     pself_target->vel.y = 0;
3817     if ( pself_target->vel.z > 0 ) pself_target->vel.z = gravity;
3818 
3819     SCRIPT_FUNCTION_END();
3820 }
3821 
3822 //--------------------------------------------------------------------------------------------
scr_set_XY(script_state_t * pstate,ai_state_t * pself)3823 Uint8 scr_set_XY( script_state_t * pstate, ai_state_t * pself )
3824 {
3825     // SetXY( tmpargument = "index", tmpx = "x", tmpy = "y" )
3826     /// @details ZZ@> This function sets one of the 8 permanent storage variable slots
3827     /// ( each of which holds an x,y pair )
3828 
3829     SCRIPT_FUNCTION_BEGIN();
3830 
3831     pself->x[pstate->argument&STOR_AND] = pstate->x;
3832     pself->y[pstate->argument&STOR_AND] = pstate->y;
3833 
3834     SCRIPT_FUNCTION_END();
3835 }
3836 
3837 //--------------------------------------------------------------------------------------------
scr_get_XY(script_state_t * pstate,ai_state_t * pself)3838 Uint8 scr_get_XY( script_state_t * pstate, ai_state_t * pself )
3839 {
3840     // tmpx,tmpy = GetXY( tmpargument = "index" )
3841     /// @details ZZ@> This function reads one of the 8 permanent storage variable slots,
3842     /// setting tmpx and tmpy accordingly
3843 
3844     SCRIPT_FUNCTION_BEGIN();
3845 
3846     pstate->x = pself->x[pstate->argument&STOR_AND];
3847     pstate->y = pself->y[pstate->argument&STOR_AND];
3848 
3849     SCRIPT_FUNCTION_END();
3850 }
3851 
3852 //--------------------------------------------------------------------------------------------
scr_AddXY(script_state_t * pstate,ai_state_t * pself)3853 Uint8 scr_AddXY( script_state_t * pstate, ai_state_t * pself )
3854 {
3855     // AddXY( tmpargument = "index", tmpx = "x", tmpy = "y" )
3856     /// @details ZZ@> This function alters the contents of one of the 8 permanent storage
3857     /// slots
3858 
3859     SCRIPT_FUNCTION_BEGIN();
3860 
3861     pself->x[pstate->argument&STOR_AND] += pstate->x;
3862     pself->y[pstate->argument&STOR_AND] += pstate->y;
3863 
3864     SCRIPT_FUNCTION_END();
3865 }
3866 
3867 //--------------------------------------------------------------------------------------------
scr_MakeAmmoKnown(script_state_t * pstate,ai_state_t * pself)3868 Uint8 scr_MakeAmmoKnown( script_state_t * pstate, ai_state_t * pself )
3869 {
3870     // MakeAmmoKnown()
3871     /// @details ZZ@> This function makes the character's ammo known ( for items )
3872 
3873     SCRIPT_FUNCTION_BEGIN();
3874 
3875     pchr->ammoknown = btrue;
3876 
3877     SCRIPT_FUNCTION_END();
3878 }
3879 
3880 //--------------------------------------------------------------------------------------------
scr_SpawnAttachedParticle(script_state_t * pstate,ai_state_t * pself)3881 Uint8 scr_SpawnAttachedParticle( script_state_t * pstate, ai_state_t * pself )
3882 {
3883     // SpawnAttachedParticle( tmpargument = "particle", tmpdistance = "vertex" )
3884     /// @details ZZ@> This function spawns a particle attached to the character
3885 
3886     CHR_REF ichr, iholder;
3887     PRT_REF iprt;
3888 
3889     SCRIPT_FUNCTION_BEGIN();
3890 
3891     ichr    = pself->index;
3892     iholder = chr_get_lowest_attachment( ichr, btrue );
3893     if ( INGAME_CHR( iholder ) )
3894     {
3895         ichr = iholder;
3896     }
3897 
3898     iprt = spawn_one_particle( pchr->pos, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, pself->index, pstate->distance, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
3899     returncode = DEFINED_PRT( iprt );
3900 
3901     SCRIPT_FUNCTION_END();
3902 }
3903 
3904 //--------------------------------------------------------------------------------------------
scr_SpawnExactParticle(script_state_t * pstate,ai_state_t * pself)3905 Uint8 scr_SpawnExactParticle( script_state_t * pstate, ai_state_t * pself )
3906 {
3907     // SpawnExactParticle( tmpargument = "particle", tmpx = "x", tmpy = "y", tmpdistance = "z" )
3908     /// @details ZZ@> This function spawns a particle at a specific x, y, z position
3909 
3910     PRT_REF iprt;
3911     CHR_REF ichr;
3912 
3913     SCRIPT_FUNCTION_BEGIN();
3914 
3915     ichr = pself->index;
3916     if ( INGAME_CHR( pchr->attachedto ) )
3917     {
3918         ichr = pchr->attachedto;
3919     }
3920 
3921     {
3922         fvec3_t   vtmp = VECT3( pstate->x, pstate->y, pstate->distance );
3923         iprt = spawn_one_particle( vtmp, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, ( CHR_REF )MAX_CHR, 0, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
3924     }
3925 
3926     returncode = DEFINED_PRT( iprt );
3927 
3928     SCRIPT_FUNCTION_END();
3929 }
3930 
3931 //--------------------------------------------------------------------------------------------
scr_AccelerateTarget(script_state_t * pstate,ai_state_t * pself)3932 Uint8 scr_AccelerateTarget( script_state_t * pstate, ai_state_t * pself )
3933 {
3934     // AccelerateTarget( tmpx = "acc x", tmpy = "acc y" )
3935     /// @details ZZ@> This function changes the x and y speeds of the target
3936 
3937     chr_t * pself_target;
3938 
3939     SCRIPT_FUNCTION_BEGIN();
3940 
3941     SCRIPT_REQUIRE_TARGET( pself_target );
3942 
3943     pself_target->vel.x += pstate->x;
3944     pself_target->vel.y += pstate->y;
3945 
3946     SCRIPT_FUNCTION_END();
3947 }
3948 
3949 //--------------------------------------------------------------------------------------------
scr_distanceIsMoreThanTurn(script_state_t * pstate,ai_state_t * pself)3950 Uint8 scr_distanceIsMoreThanTurn( script_state_t * pstate, ai_state_t * pself )
3951 {
3952     // IfdistanceIsMoreThanTurn()
3953     /// @details ZZ@> This function proceeds tmpdistance is greater than tmpturn
3954 
3955     SCRIPT_FUNCTION_BEGIN();
3956 
3957     returncode = ( pstate->distance > pstate->turn );
3958 
3959     SCRIPT_FUNCTION_END();
3960 }
3961 
3962 //--------------------------------------------------------------------------------------------
scr_Crushed(script_state_t * pstate,ai_state_t * pself)3963 Uint8 scr_Crushed( script_state_t * pstate, ai_state_t * pself )
3964 {
3965     // IfCrushed()
3966     /// @details ZZ@> This function proceeds if the character was crushed in a passage this
3967     /// update.
3968 
3969     SCRIPT_FUNCTION_BEGIN();
3970 
3971     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_CRUSHED );
3972 
3973     SCRIPT_FUNCTION_END();
3974 }
3975 
3976 //--------------------------------------------------------------------------------------------
scr_MakeCrushValid(script_state_t * pstate,ai_state_t * pself)3977 Uint8 scr_MakeCrushValid( script_state_t * pstate, ai_state_t * pself )
3978 {
3979     // MakeCrushValid()
3980     /// @details ZZ@> This function makes a character able to be crushed by closing doors
3981     /// and such
3982 
3983     SCRIPT_FUNCTION_BEGIN();
3984 
3985     pchr->canbecrushed = btrue;
3986 
3987     SCRIPT_FUNCTION_END();
3988 }
3989 
3990 //--------------------------------------------------------------------------------------------
scr_set_TargetToLowestTarget(script_state_t * pstate,ai_state_t * pself)3991 Uint8 scr_set_TargetToLowestTarget( script_state_t * pstate, ai_state_t * pself )
3992 {
3993     // SetTargetToLowestTarget()
3994     /// @details ZZ@> This function sets the target to the absolute bottom character.
3995     /// The holder of the target, or the holder of the holder of the target, or
3996     /// the holder of the holder of ther holder of the target, etc.   This function never fails
3997 
3998     CHR_REF itarget;
3999 
4000     SCRIPT_FUNCTION_BEGIN();
4001 
4002     itarget = chr_get_lowest_attachment( pself->target, bfalse );
4003 
4004     if ( INGAME_CHR( itarget ) )
4005     {
4006         SET_TARGET_0( itarget );
4007     }
4008     else
4009     {
4010         returncode = bfalse;
4011     }
4012 
4013     SCRIPT_FUNCTION_END();
4014 }
4015 
4016 //--------------------------------------------------------------------------------------------
scr_NotPutAway(script_state_t * pstate,ai_state_t * pself)4017 Uint8 scr_NotPutAway( script_state_t * pstate, ai_state_t * pself )
4018 {
4019     // IfNotPutAway()
4020     /// @details ZZ@> This function proceeds if the character couldn't be put into another
4021     /// character's pockets for some reason.
4022     /// It might be kursed or too big or something
4023 
4024     SCRIPT_FUNCTION_BEGIN();
4025 
4026     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_NOTPUTAWAY );
4027 
4028     SCRIPT_FUNCTION_END();
4029 }
4030 
4031 //--------------------------------------------------------------------------------------------
scr_TakenOut(script_state_t * pstate,ai_state_t * pself)4032 Uint8 scr_TakenOut( script_state_t * pstate, ai_state_t * pself )
4033 {
4034     // IfTakenOut()
4035     /// @details ZZ@> This function proceeds if the character is equiped in another's inventory,
4036     /// and the holder tried to unequip it ( take it out of pack ), but the
4037     /// item was kursed and didn't cooperate
4038 
4039     SCRIPT_FUNCTION_BEGIN();
4040 
4041     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_TAKENOUT );
4042 
4043     SCRIPT_FUNCTION_END();
4044 }
4045 
4046 //--------------------------------------------------------------------------------------------
scr_AmmoOut(script_state_t * pstate,ai_state_t * pself)4047 Uint8 scr_AmmoOut( script_state_t * pstate, ai_state_t * pself )
4048 {
4049     // IfAmmoOut()
4050     /// @details ZZ@> This function proceeds if the character itself has no ammo left.
4051     /// This is for crossbows and such, not archers.
4052 
4053     SCRIPT_FUNCTION_BEGIN();
4054 
4055     returncode = ( 0 == pchr->ammo );
4056 
4057     SCRIPT_FUNCTION_END();
4058 }
4059 
4060 //--------------------------------------------------------------------------------------------
scr_PlaySoundLooped(script_state_t * pstate,ai_state_t * pself)4061 Uint8 scr_PlaySoundLooped( script_state_t * pstate, ai_state_t * pself )
4062 {
4063     // PlaySoundLooped( tmpargument = "sound", tmpdistance = "frequency" )
4064 
4065     /// @details ZZ@> This function starts playing a continuous sound
4066 
4067     Mix_Chunk * new_chunk;
4068 
4069     SCRIPT_FUNCTION_BEGIN();
4070 
4071     returncode = bfalse;
4072 
4073     new_chunk = chr_get_chunk_ptr( pchr, pstate->argument );
4074 
4075     if ( NULL == new_chunk )
4076     {
4077         looped_stop_object_sounds( pself->index );       // Stop existing sound loop (if any)
4078     }
4079     else
4080     {
4081         Mix_Chunk * playing_chunk = NULL;
4082 
4083         // check whatever might be playing on the channel now
4084         if ( INVALID_SOUND_CHANNEL != pchr->loopedsound_channel )
4085         {
4086             playing_chunk = Mix_GetChunk( pchr->loopedsound_channel );
4087         }
4088 
4089         if ( playing_chunk != new_chunk )
4090         {
4091             pchr->loopedsound_channel = sound_play_chunk_looped( pchr->pos_old, new_chunk, -1, pself->index, &renderlist );
4092         }
4093     }
4094 
4095     returncode = ( INVALID_SOUND_CHANNEL != pchr->loopedsound_channel );
4096 
4097     SCRIPT_FUNCTION_END();
4098 }
4099 
4100 //--------------------------------------------------------------------------------------------
scr_StopSound(script_state_t * pstate,ai_state_t * pself)4101 Uint8 scr_StopSound( script_state_t * pstate, ai_state_t * pself )
4102 {
4103     // StopSound( tmpargument = "sound" )
4104     /// @details ZZ@> This function stops the playing of a continuous sound!
4105 
4106     SCRIPT_FUNCTION_BEGIN();
4107 
4108     looped_stop_object_sounds( pself->index );
4109 
4110     SCRIPT_FUNCTION_END();
4111 }
4112 
4113 //--------------------------------------------------------------------------------------------
scr_HealSelf(script_state_t * pstate,ai_state_t * pself)4114 Uint8 scr_HealSelf( script_state_t * pstate, ai_state_t * pself )
4115 {
4116     // HealSelf()
4117     /// @details ZZ@> This function gives life back to the character.
4118     /// Values given as 8.8-bit fixed point
4119     /// This does NOT remove [HEAL] enchants ( poisons )
4120     /// This does not set the ALERTIF_HEALED alert
4121 
4122     SCRIPT_FUNCTION_BEGIN();
4123 
4124     heal_character( pself->index, pself->index, pstate->argument, btrue );
4125 
4126     SCRIPT_FUNCTION_END();
4127 }
4128 
4129 //--------------------------------------------------------------------------------------------
scr_Equip(script_state_t * pstate,ai_state_t * pself)4130 Uint8 scr_Equip( script_state_t * pstate, ai_state_t * pself )
4131 {
4132     // Equip()
4133     /// @details ZZ@> This function flags the character as being equipped.
4134     /// This is used by equipment items when they are placed in the inventory
4135 
4136     SCRIPT_FUNCTION_BEGIN();
4137 
4138     pchr->isequipped = btrue;
4139 
4140     SCRIPT_FUNCTION_END();
4141 }
4142 
4143 //--------------------------------------------------------------------------------------------
scr_TargetHasItemIDEquipped(script_state_t * pstate,ai_state_t * pself)4144 Uint8 scr_TargetHasItemIDEquipped( script_state_t * pstate, ai_state_t * pself )
4145 {
4146     // IfTargetHasItemIDEquipped( tmpargument = "item idsz" )
4147     /// @details ZZ@> This function proceeds if the target already wearing a matching item
4148 
4149     CHR_REF item;
4150 
4151     SCRIPT_FUNCTION_BEGIN();
4152 
4153     item = chr_has_inventory_idsz( pself->target, pstate->argument, btrue, NULL );
4154 
4155     returncode = INGAME_CHR( item );
4156 
4157     SCRIPT_FUNCTION_END();
4158 }
4159 
4160 //--------------------------------------------------------------------------------------------
scr_set_OwnerToTarget(script_state_t * pstate,ai_state_t * pself)4161 Uint8 scr_set_OwnerToTarget( script_state_t * pstate, ai_state_t * pself )
4162 {
4163     // SetOwnerToTarget()
4164     /// @details ZZ@> This function must be called before enchanting anything.
4165     /// The owner is the character that pays the sustain costs and such for the enchantment
4166 
4167     SCRIPT_FUNCTION_BEGIN();
4168 
4169     pself->owner = pself->target;
4170 
4171     SCRIPT_FUNCTION_END();
4172 }
4173 
4174 //--------------------------------------------------------------------------------------------
scr_set_TargetToOwner(script_state_t * pstate,ai_state_t * pself)4175 Uint8 scr_set_TargetToOwner( script_state_t * pstate, ai_state_t * pself )
4176 {
4177     // SetTargetToOwner()
4178     /// @details ZZ@> This function sets the target to whoever was previously declared as the
4179     /// owner.
4180 
4181     SCRIPT_FUNCTION_BEGIN();
4182 
4183     if ( INGAME_CHR( pself->owner ) )
4184     {
4185         SET_TARGET_0( pself->owner );
4186     }
4187     else
4188     {
4189         returncode = bfalse;
4190     }
4191 
4192     SCRIPT_FUNCTION_END();
4193 }
4194 
4195 //--------------------------------------------------------------------------------------------
scr_set_Frame(script_state_t * pstate,ai_state_t * pself)4196 Uint8 scr_set_Frame( script_state_t * pstate, ai_state_t * pself )
4197 {
4198     // SetFrame( tmpargument = "frame" )
4199     /// @details ZZ@> This function sets the current .MD2 frame for the character.  Values are * 4
4200 
4201     int    frame_along = 0;
4202     Uint16 ilip        = 0;
4203 
4204     SCRIPT_FUNCTION_BEGIN();
4205 
4206     ilip        = pstate->argument & 3;
4207     frame_along = pstate->argument >> 2;
4208     chr_set_frame( pself->index, ACTION_DA, frame_along, ilip );
4209 
4210     SCRIPT_FUNCTION_END();
4211 }
4212 
4213 //--------------------------------------------------------------------------------------------
scr_BreakPassage(script_state_t * pstate,ai_state_t * pself)4214 Uint8 scr_BreakPassage( script_state_t * pstate, ai_state_t * pself )
4215 {
4216     // BreakPassage( tmpargument = "passage", tmpturn = "tile type", tmpdistance = "number of frames", tmpx = "borken tile", tmpy = "tile fx bits" )
4217 
4218     /// @details ZZ@> This function makes the tiles fall away ( turns into damage terrain )
4219     /// This function causes the tiles of a passage to increment if stepped on.
4220     /// tmpx and tmpy are both set to the location of whoever broke the tile if
4221     /// the function passed.
4222 
4223     SCRIPT_FUNCTION_BEGIN();
4224 
4225     returncode = _break_passage( pstate->y, pstate->x, pstate->distance, pstate->turn, ( PASS_REF )pstate->argument, &( pstate->x ), &( pstate->y ) );
4226 
4227     SCRIPT_FUNCTION_END();
4228 }
4229 
4230 //--------------------------------------------------------------------------------------------
scr_set_ReloadTime(script_state_t * pstate,ai_state_t * pself)4231 Uint8 scr_set_ReloadTime( script_state_t * pstate, ai_state_t * pself )
4232 {
4233     // SetReloadTime( tmpargument = "time" )
4234     /// @details ZZ@> This function stops a character from being used for a while.  Used
4235     /// by weapons to slow down their attack rate.  50 clicks per second.
4236 
4237     SCRIPT_FUNCTION_BEGIN();
4238 
4239     if ( pstate->argument > 0 ) pchr->reload_timer = pstate->argument;
4240     else pchr->reload_timer = 0;
4241 
4242     SCRIPT_FUNCTION_END();
4243 }
4244 
4245 //--------------------------------------------------------------------------------------------
scr_set_TargetToWideBlahID(script_state_t * pstate,ai_state_t * pself)4246 Uint8 scr_set_TargetToWideBlahID( script_state_t * pstate, ai_state_t * pself )
4247 {
4248     // SetTargetToWideBlahID( tmpargument = "idsz", tmpdistance = "blah bits" )
4249     /// @details ZZ@> This function sets the target to a character that matches the description,
4250     /// and who is located in the general vicinity of the character
4251 
4252     CHR_REF ichr;
4253 
4254     SCRIPT_FUNCTION_BEGIN();
4255 
4256     // Try to find one
4257     ichr = chr_find_target( pchr, WIDE, pstate->argument, pstate->distance );
4258 
4259     if ( INGAME_CHR( ichr ) )
4260     {
4261         SET_TARGET_0( ichr );
4262         returncode = btrue;
4263     }
4264     else
4265     {
4266         returncode = bfalse;
4267     }
4268 
4269     SCRIPT_FUNCTION_END();
4270 }
4271 
4272 //--------------------------------------------------------------------------------------------
scr_PoofTarget(script_state_t * pstate,ai_state_t * pself)4273 Uint8 scr_PoofTarget( script_state_t * pstate, ai_state_t * pself )
4274 {
4275     // PoofTarget()
4276     /// @details ZZ@> This function removes the target from the game, failing if the
4277     /// target is a player
4278 
4279     chr_t * pself_target;
4280 
4281     SCRIPT_FUNCTION_BEGIN();
4282 
4283     SCRIPT_REQUIRE_TARGET( pself_target );
4284 
4285     returncode = bfalse;
4286     if ( INVALID_PLA( pself_target->is_which_player ) )             //Do not poof players
4287     {
4288         returncode = btrue;
4289         if ( pself->target == pself->index )
4290         {
4291             // Poof self later
4292             pself->poof_time = update_wld + 1;
4293         }
4294         else
4295         {
4296             // Poof others now
4297             pself_target->ai.poof_time = update_wld;
4298 
4299             SET_TARGET( pself->index, pself_target );
4300         }
4301     }
4302 
4303     SCRIPT_FUNCTION_END();
4304 }
4305 
4306 //--------------------------------------------------------------------------------------------
scr_ChildDoActionOverride(script_state_t * pstate,ai_state_t * pself)4307 Uint8 scr_ChildDoActionOverride( script_state_t * pstate, ai_state_t * pself )
4308 {
4309     // ChildDoActionOverride( tmpargument = action )
4310 
4311     /// @details ZZ@> This function lets a character set the action of the last character
4312     /// it spawned.  It also sets the current frame to the first frame of the
4313     /// action ( no interpolation from last frame ). If the cation is not valid for the model,
4314     /// the function will fail
4315 
4316     SCRIPT_FUNCTION_BEGIN();
4317 
4318     returncode = bfalse;
4319     if ( INGAME_CHR( pself->child ) )
4320     {
4321         int action;
4322 
4323         chr_t * pchild = ChrList.lst + pself->child;
4324 
4325         action = mad_get_action_ref( pchild->inst.imad, pstate->argument );
4326 
4327         if ( rv_success == chr_start_anim( pchild, action, bfalse, btrue ) )
4328         {
4329             returncode = btrue;
4330         }
4331     }
4332 
4333     SCRIPT_FUNCTION_END();
4334 }
4335 
4336 //--------------------------------------------------------------------------------------------
scr_SpawnPoof(script_state_t * pstate,ai_state_t * pself)4337 Uint8 scr_SpawnPoof( script_state_t * pstate, ai_state_t * pself )
4338 {
4339     // SpawnPoof
4340     /// @details ZZ@> This function makes a lovely little poof at the character's location.
4341     /// The poof form and particle types are set in data.txt
4342 
4343     SCRIPT_FUNCTION_BEGIN();
4344 
4345     spawn_poof( pself->index, pchr->profile_ref );
4346 
4347     SCRIPT_FUNCTION_END();
4348 }
4349 
4350 //--------------------------------------------------------------------------------------------
scr_set_SpeedPercent(script_state_t * pstate,ai_state_t * pself)4351 Uint8 scr_set_SpeedPercent( script_state_t * pstate, ai_state_t * pself )
4352 {
4353     // SetSpeedPercent( tmpargument = "percent" )
4354     /// @details ZZ@> This function acts like Run or Walk, except it allows the explicit
4355     /// setting of the speed
4356 
4357     float fvalue;
4358 
4359     SCRIPT_FUNCTION_BEGIN();
4360 
4361     reset_character_accel( pself->index );
4362 
4363     fvalue = pstate->argument / 100.0f;
4364     fvalue = MAX( 0.0f, fvalue );
4365 
4366     pchr->maxaccel = pchr->maxaccel_reset * fvalue;
4367 
4368     if ( pchr->maxaccel < 0.33f )
4369     {
4370         // only sneak
4371         pchr->movement_bits = CHR_MOVEMENT_BITS_SNEAK | CHR_MOVEMENT_BITS_STOP;
4372     }
4373     else
4374     {
4375         // everything but sneak
4376         pchr->movement_bits = ( unsigned )( ~CHR_MOVEMENT_BITS_SNEAK );
4377     }
4378 
4379     SCRIPT_FUNCTION_END();
4380 }
4381 
4382 //--------------------------------------------------------------------------------------------
scr_set_ChildState(script_state_t * pstate,ai_state_t * pself)4383 Uint8 scr_set_ChildState( script_state_t * pstate, ai_state_t * pself )
4384 {
4385     // SetChildState( tmpargument = "state" )
4386     /// @details ZZ@> This function lets a character set the state of the last character it
4387     /// spawned
4388 
4389     SCRIPT_FUNCTION_BEGIN();
4390 
4391     if ( VALID_CHR_RANGE( pself->child ) )
4392     {
4393         chr_set_ai_state( ChrList.lst + pself->child, pstate->argument );
4394     }
4395 
4396     SCRIPT_FUNCTION_END();
4397 }
4398 
4399 //--------------------------------------------------------------------------------------------
scr_SpawnAttachedSizedParticle(script_state_t * pstate,ai_state_t * pself)4400 Uint8 scr_SpawnAttachedSizedParticle( script_state_t * pstate, ai_state_t * pself )
4401 {
4402     // SpawnAttachedSizedParticle( tmpargument = "particle", tmpdistance = "vertex", tmpturn = "size" )
4403     /// @details ZZ@> This function spawns a particle of the specific size attached to the
4404     /// character. For spell charging effects
4405 
4406     PRT_REF iprt;
4407     CHR_REF ichr;
4408 
4409     SCRIPT_FUNCTION_BEGIN();
4410 
4411     ichr = pself->index;
4412     if ( INGAME_CHR( pchr->attachedto ) )
4413     {
4414         ichr = pchr->attachedto;
4415     }
4416 
4417     iprt = spawn_one_particle( pchr->pos, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, pself->index, pstate->distance, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
4418 
4419     returncode = DEFINED_PRT( iprt );
4420 
4421     if ( returncode )
4422     {
4423         returncode = prt_set_size( PrtList.lst + iprt, pstate->turn );
4424     }
4425 
4426     SCRIPT_FUNCTION_END();
4427 }
4428 
4429 //--------------------------------------------------------------------------------------------
scr_ChangeArmor(script_state_t * pstate,ai_state_t * pself)4430 Uint8 scr_ChangeArmor( script_state_t * pstate, ai_state_t * pself )
4431 {
4432     // ChangeArmor( tmpargument = "time" )
4433     /// @details ZZ@> This function changes the character's armor.
4434     /// Sets tmpargument as the old type and tmpx as the new type
4435 
4436     int iTmp;
4437 
4438     SCRIPT_FUNCTION_BEGIN();
4439 
4440     pstate->x = pstate->argument;
4441     iTmp = pchr->skin;
4442     pstate->x = change_armor( pself->index, pstate->argument );
4443     pstate->argument = iTmp;  // The character's old armor
4444 
4445     SCRIPT_FUNCTION_END();
4446 }
4447 
4448 //--------------------------------------------------------------------------------------------
scr_ShowTimer(script_state_t * pstate,ai_state_t * pself)4449 Uint8 scr_ShowTimer( script_state_t * pstate, ai_state_t * pself )
4450 {
4451     // ShowTimer( tmpargument = "time" )
4452     /// @details ZZ@> This function sets the value displayed by the module timer.
4453     /// For races and such.  50 clicks per second
4454 
4455     SCRIPT_FUNCTION_BEGIN();
4456 
4457     timeron = btrue;
4458     timervalue = pstate->argument;
4459 
4460     SCRIPT_FUNCTION_END();
4461 }
4462 
4463 //--------------------------------------------------------------------------------------------
scr_FacingTarget(script_state_t * pstate,ai_state_t * pself)4464 Uint8 scr_FacingTarget( script_state_t * pstate, ai_state_t * pself )
4465 {
4466     // IfFacingTarget()
4467     /// @details ZZ@> This function proceeds if the character is more or less facing its
4468     /// target
4469 
4470     FACING_T sTmp = 0;
4471     chr_t *  pself_target;
4472 
4473     SCRIPT_FUNCTION_BEGIN();
4474 
4475     SCRIPT_REQUIRE_TARGET( pself_target );
4476 
4477     sTmp = vec_to_facing( pself_target->pos.x - pchr->pos.x , pself_target->pos.y - pchr->pos.y );
4478     sTmp -= pchr->ori.facing_z;
4479     returncode = ( sTmp > 55535 || sTmp < 10000 );
4480 
4481     SCRIPT_FUNCTION_END();
4482 }
4483 
4484 //--------------------------------------------------------------------------------------------
scr_PlaySoundVolume(script_state_t * pstate,ai_state_t * pself)4485 Uint8 scr_PlaySoundVolume( script_state_t * pstate, ai_state_t * pself )
4486 {
4487     // PlaySoundVolume( argument = "sound", distance = "volume" )
4488     /// @details ZZ@> This function sets the volume of a sound and plays it
4489 
4490     SCRIPT_FUNCTION_BEGIN();
4491 
4492     if ( pstate->distance > 0 )
4493     {
4494         if ( VALID_SND( pstate->argument ) )
4495         {
4496             int channel;
4497             channel = sound_play_chunk( pchr->pos_old, chr_get_chunk_ptr( pchr, pstate->argument ) );
4498 
4499             if ( channel != INVALID_SOUND_CHANNEL )
4500             {
4501                 Mix_Volume( channel, ( 128*pstate->distance ) / 100 );
4502             }
4503         }
4504     }
4505 
4506     SCRIPT_FUNCTION_END();
4507 }
4508 
4509 //--------------------------------------------------------------------------------------------
scr_SpawnAttachedFacedParticle(script_state_t * pstate,ai_state_t * pself)4510 Uint8 scr_SpawnAttachedFacedParticle( script_state_t * pstate, ai_state_t * pself )
4511 {
4512     // SpawnAttachedFacedParticle(  tmpargument = "particle", tmpdistance = "vertex", tmpturn = "turn" )
4513 
4514     /// @details ZZ@> This function spawns a particle attached to the character, facing the
4515     /// same direction given by tmpturn
4516 
4517     PRT_REF iprt;
4518     CHR_REF ichr;
4519 
4520     SCRIPT_FUNCTION_BEGIN();
4521 
4522     ichr = pself->index;
4523     if ( INGAME_CHR( pchr->attachedto ) )
4524     {
4525         ichr = pchr->attachedto;
4526     }
4527 
4528     iprt = spawn_one_particle( pchr->pos, CLIP_TO_16BITS( pstate->turn ), pchr->profile_ref, pstate->argument, pself->index, pstate->distance, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
4529 
4530     returncode = DEFINED_PRT( iprt );
4531 
4532     SCRIPT_FUNCTION_END();
4533 }
4534 
4535 //--------------------------------------------------------------------------------------------
scr_StateIsOdd(script_state_t * pstate,ai_state_t * pself)4536 Uint8 scr_StateIsOdd( script_state_t * pstate, ai_state_t * pself )
4537 {
4538     // IfStateIsOdd()
4539     /// @details ZZ@> This function proceeds if the character's state is 1, 3, 5, 7, etc.
4540 
4541     SCRIPT_FUNCTION_BEGIN();
4542 
4543     returncode = ( pself->state & 1 );
4544 
4545     SCRIPT_FUNCTION_END();
4546 }
4547 
4548 //--------------------------------------------------------------------------------------------
scr_set_TargetToDistantEnemy(script_state_t * pstate,ai_state_t * pself)4549 Uint8 scr_set_TargetToDistantEnemy( script_state_t * pstate, ai_state_t * pself )
4550 {
4551     // SetTargetToDistantEnemy( tmpdistance = "distance" )
4552     /// @details ZZ@> This function finds a character within a certain distance of the
4553     /// character, failing if there are none
4554 
4555     CHR_REF ichr;
4556 
4557     SCRIPT_FUNCTION_BEGIN();
4558 
4559     ichr = chr_find_target( pchr, pstate->distance, IDSZ_NONE, TARGET_ENEMIES );
4560 
4561     if ( INGAME_CHR( ichr ) )
4562     {
4563         SET_TARGET_0( ichr );
4564     }
4565     else
4566     {
4567         returncode = bfalse;
4568     }
4569 
4570     SCRIPT_FUNCTION_END();
4571 }
4572 
4573 //--------------------------------------------------------------------------------------------
scr_Teleport(script_state_t * pstate,ai_state_t * pself)4574 Uint8 scr_Teleport( script_state_t * pstate, ai_state_t * pself )
4575 {
4576     // Teleport( tmpx = "x", tmpy = "y" )
4577     /// @details ZZ@> This function teleports the character to a new location, failing if
4578     /// the location is blocked or off the map
4579 
4580     SCRIPT_FUNCTION_BEGIN();
4581 
4582     returncode = chr_teleport( pself->index, pstate->x, pstate->y, pchr->pos.z, pchr->ori.facing_z );
4583 
4584     SCRIPT_FUNCTION_END();
4585 }
4586 
4587 //--------------------------------------------------------------------------------------------
scr_GiveStrengthToTarget(script_state_t * pstate,ai_state_t * pself)4588 Uint8 scr_GiveStrengthToTarget( script_state_t * pstate, ai_state_t * pself )
4589 {
4590     // GiveStrengthToTarget()
4591     // Permanently boost the target's strength
4592 
4593     int iTmp;
4594     chr_t * pself_target;
4595 
4596     SCRIPT_FUNCTION_BEGIN();
4597 
4598     SCRIPT_REQUIRE_TARGET( pself_target );
4599 
4600     if ( pself_target->alive )
4601     {
4602         iTmp = pstate->argument;
4603         getadd( 0, pself_target->strength, PERFECTSTAT, &iTmp );
4604         pself_target->strength += iTmp;
4605     }
4606 
4607     SCRIPT_FUNCTION_END();
4608 }
4609 
4610 //--------------------------------------------------------------------------------------------
scr_GiveWisdomToTarget(script_state_t * pstate,ai_state_t * pself)4611 Uint8 scr_GiveWisdomToTarget( script_state_t * pstate, ai_state_t * pself )
4612 {
4613     // GiveWisdomToTarget()
4614     // Permanently boost the target's wisdom
4615 
4616     int iTmp;
4617     chr_t * pself_target;
4618 
4619     SCRIPT_FUNCTION_BEGIN();
4620 
4621     SCRIPT_REQUIRE_TARGET( pself_target );
4622 
4623     if ( pself_target->alive )
4624     {
4625         iTmp = pstate->argument;
4626         getadd( 0, pself_target->wisdom, PERFECTSTAT, &iTmp );
4627         pself_target->wisdom += iTmp;
4628     }
4629 
4630     SCRIPT_FUNCTION_END();
4631 }
4632 
4633 //--------------------------------------------------------------------------------------------
scr_GiveIntelligenceToTarget(script_state_t * pstate,ai_state_t * pself)4634 Uint8 scr_GiveIntelligenceToTarget( script_state_t * pstate, ai_state_t * pself )
4635 {
4636     // GiveIntelligenceToTarget()
4637     // Permanently boost the target's intelligence
4638 
4639     int iTmp;
4640     chr_t * pself_target;
4641 
4642     SCRIPT_FUNCTION_BEGIN();
4643 
4644     SCRIPT_REQUIRE_TARGET( pself_target );
4645 
4646     if ( pself_target->alive )
4647     {
4648         iTmp = pstate->argument;
4649         getadd( 0, pself_target->intelligence, PERFECTSTAT, &iTmp );
4650         pself_target->intelligence += iTmp;
4651     }
4652 
4653     SCRIPT_FUNCTION_END();
4654 }
4655 
4656 //--------------------------------------------------------------------------------------------
scr_GiveDexterityToTarget(script_state_t * pstate,ai_state_t * pself)4657 Uint8 scr_GiveDexterityToTarget( script_state_t * pstate, ai_state_t * pself )
4658 {
4659     // GiveDexterityToTarget()
4660     // Permanently boost the target's dexterity
4661 
4662     int iTmp;
4663     chr_t * pself_target;
4664 
4665     SCRIPT_FUNCTION_BEGIN();
4666 
4667     SCRIPT_REQUIRE_TARGET( pself_target );
4668 
4669     if ( pself_target->alive )
4670     {
4671         iTmp = pstate->argument;
4672         getadd( 0, pself_target->dexterity, PERFECTSTAT, &iTmp );
4673         pself_target->dexterity += iTmp;
4674     }
4675 
4676     SCRIPT_FUNCTION_END();
4677 }
4678 
4679 //--------------------------------------------------------------------------------------------
scr_GiveLifeToTarget(script_state_t * pstate,ai_state_t * pself)4680 Uint8 scr_GiveLifeToTarget( script_state_t * pstate, ai_state_t * pself )
4681 {
4682     // GiveLifeToTarget()
4683     /// @details ZZ@> Permanently boost the target's life
4684 
4685     int iTmp;
4686     chr_t * pself_target;
4687 
4688     SCRIPT_FUNCTION_BEGIN();
4689 
4690     SCRIPT_REQUIRE_TARGET( pself_target );
4691 
4692     if ( pself_target->alive )
4693     {
4694         iTmp = pstate->argument;
4695         getadd( LOWSTAT, pself_target->lifemax, PERFECTBIG, &iTmp );
4696         pself_target->lifemax += iTmp;
4697         if ( iTmp < 0 )
4698         {
4699             getadd( 1, pself_target->life, PERFECTBIG, &iTmp );
4700         }
4701 
4702         pself_target->life += iTmp;
4703     }
4704 
4705     SCRIPT_FUNCTION_END();
4706 }
4707 
4708 //--------------------------------------------------------------------------------------------
scr_GiveManaToTarget(script_state_t * pstate,ai_state_t * pself)4709 Uint8 scr_GiveManaToTarget( script_state_t * pstate, ai_state_t * pself )
4710 {
4711     // GiveManaToTarget()
4712     /// @details ZZ@> Permanently boost the target's mana
4713 
4714     int iTmp;
4715     chr_t * pself_target;
4716 
4717     SCRIPT_FUNCTION_BEGIN();
4718 
4719     SCRIPT_REQUIRE_TARGET( pself_target );
4720 
4721     if ( pself_target->alive )
4722     {
4723         iTmp = pstate->argument;
4724         getadd( 0, pself_target->manamax, PERFECTBIG, &iTmp );
4725         pself_target->manamax += iTmp;
4726         if ( iTmp < 0 )
4727         {
4728             getadd( 0, pself_target->mana, PERFECTBIG, &iTmp );
4729         }
4730 
4731         pself_target->mana += iTmp;
4732     }
4733 
4734     SCRIPT_FUNCTION_END();
4735 }
4736 
4737 //--------------------------------------------------------------------------------------------
scr_ShowMap(script_state_t * pstate,ai_state_t * pself)4738 Uint8 scr_ShowMap( script_state_t * pstate, ai_state_t * pself )
4739 {
4740     // ShowMap()
4741     /// @details ZZ@> This function shows the module's map.
4742     /// Fails if map already visible
4743 
4744     SCRIPT_FUNCTION_BEGIN();
4745     if ( mapon )  returncode = bfalse;
4746 
4747     mapon = mapvalid;
4748 
4749     SCRIPT_FUNCTION_END();
4750 }
4751 
4752 //--------------------------------------------------------------------------------------------
scr_ShowYouAreHere(script_state_t * pstate,ai_state_t * pself)4753 Uint8 scr_ShowYouAreHere( script_state_t * pstate, ai_state_t * pself )
4754 {
4755     // ShowYouAreHere()
4756     /// @details ZZ@> This function shows the blinking white blip on the map that represents the
4757     /// camera location
4758 
4759     SCRIPT_FUNCTION_BEGIN();
4760 
4761     youarehereon = mapvalid;
4762 
4763     SCRIPT_FUNCTION_END();
4764 }
4765 
4766 //--------------------------------------------------------------------------------------------
scr_ShowBlipXY(script_state_t * pstate,ai_state_t * pself)4767 Uint8 scr_ShowBlipXY( script_state_t * pstate, ai_state_t * pself )
4768 {
4769     // ShowBlipXY( tmpx = "x", tmpy = "y", tmpargument = "color" )
4770 
4771     /// @details ZZ@> This function draws a blip on the map, and must be done each update
4772     SCRIPT_FUNCTION_BEGIN();
4773 
4774     // Add a blip
4775     if ( blip_count < MAXBLIP )
4776     {
4777         if ( pstate->x > 0 && pstate->x < PMesh->gmem.edge_x && pstate->y > 0 && pstate->y < PMesh->gmem.edge_y )
4778         {
4779             if ( pstate->argument < COLOR_MAX && pstate->argument >= 0 )
4780             {
4781                 blip_x[blip_count] = pstate->x;
4782                 blip_y[blip_count] = pstate->y;
4783                 blip_c[blip_count] = pstate->argument;
4784                 blip_count++;
4785             }
4786         }
4787     }
4788 
4789     SCRIPT_FUNCTION_END();
4790 }
4791 
4792 //--------------------------------------------------------------------------------------------
scr_HealTarget(script_state_t * pstate,ai_state_t * pself)4793 Uint8 scr_HealTarget( script_state_t * pstate, ai_state_t * pself )
4794 {
4795     // HealTarget( tmpargument = "amount" )
4796     /// @details ZZ@> This function gives some life back to the target.
4797     /// Values are 8.8-bit fixed point. Any enchantments that are removed by [HEAL], like poison, go away
4798 
4799     SCRIPT_FUNCTION_BEGIN();
4800 
4801     returncode = bfalse;
4802     if ( heal_character( pself->target, pself->index, pstate->argument, bfalse ) )
4803     {
4804         returncode = btrue;
4805         remove_all_enchants_with_idsz( pself->target, MAKE_IDSZ( 'H', 'E', 'A', 'L' ) );
4806     }
4807 
4808     SCRIPT_FUNCTION_END();
4809 }
4810 
4811 //--------------------------------------------------------------------------------------------
scr_PumpTarget(script_state_t * pstate,ai_state_t * pself)4812 Uint8 scr_PumpTarget( script_state_t * pstate, ai_state_t * pself )
4813 {
4814     // PumpTarget( tmpargument = "amount" )
4815     /// @details ZZ@> This function gives some mana back to the target.
4816     /// Values are 8.8-bit fixed point
4817 
4818     int iTmp;
4819     chr_t * pself_target;
4820 
4821     SCRIPT_FUNCTION_BEGIN();
4822 
4823     SCRIPT_REQUIRE_TARGET( pself_target );
4824 
4825     if ( pself_target->alive )
4826     {
4827         iTmp = pstate->argument;
4828         getadd( 0, pself_target->mana, pself_target->manamax, &iTmp );
4829         pself_target->mana += iTmp;
4830     }
4831 
4832     SCRIPT_FUNCTION_END();
4833 }
4834 
4835 //--------------------------------------------------------------------------------------------
scr_CostAmmo(script_state_t * pstate,ai_state_t * pself)4836 Uint8 scr_CostAmmo( script_state_t * pstate, ai_state_t * pself )
4837 {
4838     // CostAmmo()
4839     /// @details ZZ@> This function costs the character 1 point of ammo
4840 
4841     SCRIPT_FUNCTION_BEGIN();
4842     if ( pchr->ammo > 0 )
4843     {
4844         pchr->ammo--;
4845     }
4846 
4847     SCRIPT_FUNCTION_END();
4848 }
4849 
4850 //--------------------------------------------------------------------------------------------
scr_MakeSimilarNamesKnown(script_state_t * pstate,ai_state_t * pself)4851 Uint8 scr_MakeSimilarNamesKnown( script_state_t * pstate, ai_state_t * pself )
4852 {
4853     // MakeSimilarNamesKnown()
4854     /// @details ZZ@> This function makes the names of similar objects known.
4855     /// Checks all 6 IDSZ types to make sure they match.
4856 
4857     int tTmp;
4858     Uint16 sTmp = 0;
4859     cap_t * pcap_chr;
4860 
4861     SCRIPT_FUNCTION_BEGIN();
4862 
4863     pcap_chr = pro_get_pcap( pchr->profile_ref );
4864     if ( NULL == pcap_chr ) return bfalse;
4865 
4866     CHR_BEGIN_LOOP_ACTIVE( cnt, pchr_test )
4867     {
4868         cap_t * pcap_test;
4869 
4870         pcap_test = chr_get_pcap( cnt );
4871         if ( NULL == pcap_test ) continue;
4872 
4873         sTmp = btrue;
4874         for ( tTmp = 0; tTmp < IDSZ_COUNT; tTmp++ )
4875         {
4876             if ( pcap_chr->idsz[tTmp] != pcap_test->idsz[tTmp] )
4877             {
4878                 sTmp = bfalse;
4879             }
4880         }
4881 
4882         if ( sTmp )
4883         {
4884             pchr_test->nameknown = btrue;
4885         }
4886     }
4887     CHR_END_LOOP();
4888 
4889     SCRIPT_FUNCTION_END();
4890 }
4891 
4892 //--------------------------------------------------------------------------------------------
scr_SpawnAttachedHolderParticle(script_state_t * pstate,ai_state_t * pself)4893 Uint8 scr_SpawnAttachedHolderParticle( script_state_t * pstate, ai_state_t * pself )
4894 {
4895     // SpawnAttachedHolderParticle( tmpargument = "particle", tmpdistance = "vertex" )
4896 
4897     /// @details ZZ@> This function spawns a particle attached to the character's holder, or to the character if no holder
4898 
4899     PRT_REF iprt;
4900     CHR_REF ichr;
4901 
4902     SCRIPT_FUNCTION_BEGIN();
4903 
4904     ichr = pself->index;
4905     if ( INGAME_CHR( pchr->attachedto ) )
4906     {
4907         ichr = pchr->attachedto;
4908     }
4909 
4910     iprt = spawn_one_particle( pchr->pos, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, ichr, pstate->distance, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
4911 
4912     returncode = DEFINED_PRT( iprt );
4913 
4914     SCRIPT_FUNCTION_END();
4915 }
4916 
4917 //--------------------------------------------------------------------------------------------
scr_set_TargetReloadTime(script_state_t * pstate,ai_state_t * pself)4918 Uint8 scr_set_TargetReloadTime( script_state_t * pstate, ai_state_t * pself )
4919 {
4920     // SetTargetReloadTime( tmpargument = "time" )
4921 
4922     /// @details ZZ@> This function sets the target's reload time
4923     /// This function stops the target from attacking for a while.
4924 
4925     chr_t * pself_target;
4926 
4927     SCRIPT_FUNCTION_BEGIN();
4928 
4929     SCRIPT_REQUIRE_TARGET( pself_target );
4930 
4931     if ( pstate->argument > 0 )
4932     {
4933         pself_target->reload_timer = pstate->argument;
4934     }
4935     else
4936     {
4937         pself_target->reload_timer = 0;
4938     }
4939 
4940     SCRIPT_FUNCTION_END();
4941 }
4942 
4943 //--------------------------------------------------------------------------------------------
scr_set_FogLevel(script_state_t * pstate,ai_state_t * pself)4944 Uint8 scr_set_FogLevel( script_state_t * pstate, ai_state_t * pself )
4945 {
4946     // SetFogLevel( tmpargument = "level" )
4947     /// @details ZZ@> This function sets the level of the module's fog.
4948     /// Values are * 10
4949     /// !!BAD!! DOESN'T WORK !!BAD!!
4950 
4951     float fTmp;
4952 
4953     SCRIPT_FUNCTION_BEGIN();
4954 
4955     fTmp = ( pstate->argument / 10.0f ) - fog.top;
4956     fog.top += fTmp;
4957     fog.distance += fTmp;
4958     fog.on = cfg.fog_allowed;
4959     if ( fog.distance < 1.0f )  fog.on = bfalse;
4960 
4961     SCRIPT_FUNCTION_END();
4962 }
4963 
4964 //--------------------------------------------------------------------------------------------
scr_get_FogLevel(script_state_t * pstate,ai_state_t * pself)4965 Uint8 scr_get_FogLevel( script_state_t * pstate, ai_state_t * pself )
4966 {
4967     // tmpargument = GetFogLevel()
4968     /// @details ZZ@> This function sets tmpargument to the level of the module's fog.
4969     /// Values are * 10
4970 
4971     SCRIPT_FUNCTION_BEGIN();
4972 
4973     pstate->argument = fog.top * 10;
4974 
4975     SCRIPT_FUNCTION_END();
4976 }
4977 
4978 //--------------------------------------------------------------------------------------------
scr_set_FogTAD(script_state_t * pstate,ai_state_t * pself)4979 Uint8 scr_set_FogTAD( script_state_t * pstate, ai_state_t * pself )
4980 {
4981     /// @details ZZ@> This function sets the color of the module's fog.
4982     /// TAD stands for <turn, argument, distance> == <red, green, blue>.
4983     /// Makes sense, huh?
4984     /// !!BAD!! DOESN'T WORK !!BAD!!
4985 
4986     SCRIPT_FUNCTION_BEGIN();
4987 
4988     fog.red = pstate->turn;
4989     fog.grn = pstate->argument;
4990     fog.blu = pstate->distance;
4991 
4992     SCRIPT_FUNCTION_END();
4993 }
4994 
4995 //--------------------------------------------------------------------------------------------
scr_set_FogBottomLevel(script_state_t * pstate,ai_state_t * pself)4996 Uint8 scr_set_FogBottomLevel( script_state_t * pstate, ai_state_t * pself )
4997 {
4998     // SetFogBottomLevel( tmpargument = "level" )
4999 
5000     /// @details ZZ@> This function sets the level of the module's fog.
5001     /// Values are * 10
5002 
5003     float fTmp;
5004 
5005     SCRIPT_FUNCTION_BEGIN();
5006 
5007     fTmp = ( pstate->argument / 10.0f ) - fog.bottom;
5008     fog.bottom += fTmp;
5009     fog.distance -= fTmp;
5010     fog.on = cfg.fog_allowed;
5011     if ( fog.distance < 1.0f )  fog.on = bfalse;
5012 
5013     SCRIPT_FUNCTION_END();
5014 }
5015 
5016 //--------------------------------------------------------------------------------------------
scr_get_FogBottomLevel(script_state_t * pstate,ai_state_t * pself)5017 Uint8 scr_get_FogBottomLevel( script_state_t * pstate, ai_state_t * pself )
5018 {
5019     // tmpargument = GetFogBottomLevel()
5020 
5021     /// @details ZZ@> This function sets tmpargument to the level of the module's fog.
5022     /// Values are * 10
5023 
5024     SCRIPT_FUNCTION_BEGIN();
5025 
5026     pstate->argument = fog.bottom * 10;
5027 
5028     SCRIPT_FUNCTION_END();
5029 }
5030 
5031 //--------------------------------------------------------------------------------------------
scr_CorrectActionForHand(script_state_t * pstate,ai_state_t * pself)5032 Uint8 scr_CorrectActionForHand( script_state_t * pstate, ai_state_t * pself )
5033 {
5034     // CorrectActionForHand( tmpargument = "action" )
5035     /// @details ZZ@> This function changes tmpargument according to which hand the character
5036     /// is held in It turns ZA into ZA, ZB, ZC, or ZD.
5037     /// USAGE:  wizards casting spells
5038 
5039     SCRIPT_FUNCTION_BEGIN();
5040     if ( INGAME_CHR( pchr->attachedto ) )
5041     {
5042         if ( pchr->inwhich_slot == SLOT_LEFT )
5043         {
5044             // A or B
5045             pstate->argument = generate_randmask( pstate->argument, 1 );
5046         }
5047         else
5048         {
5049             // C or D
5050             pstate->argument = generate_randmask( pstate->argument + 2, 1 );
5051         }
5052     }
5053 
5054     SCRIPT_FUNCTION_END();
5055 }
5056 
5057 //--------------------------------------------------------------------------------------------
scr_TargetIsMounted(script_state_t * pstate,ai_state_t * pself)5058 Uint8 scr_TargetIsMounted( script_state_t * pstate, ai_state_t * pself )
5059 {
5060     // IfTargetIsMounted()
5061     /// @details ZZ@> This function proceeds if the target is riding a mount
5062 
5063     CHR_REF ichr;
5064     chr_t * pself_target;
5065 
5066     SCRIPT_FUNCTION_BEGIN();
5067 
5068     SCRIPT_REQUIRE_TARGET( pself_target );
5069 
5070     returncode = bfalse;
5071 
5072     ichr = pself_target->attachedto;
5073     if ( INGAME_CHR( ichr ) )
5074     {
5075         returncode = ChrList.lst[ichr].ismount;
5076     }
5077 
5078     SCRIPT_FUNCTION_END();
5079 }
5080 
5081 //--------------------------------------------------------------------------------------------
scr_SparkleIcon(script_state_t * pstate,ai_state_t * pself)5082 Uint8 scr_SparkleIcon( script_state_t * pstate, ai_state_t * pself )
5083 {
5084     // SparkleIcon( tmpargument = "color" )
5085     /// @details ZZ@> This function starts little sparklies going around the character's icon
5086 
5087     SCRIPT_FUNCTION_BEGIN();
5088     if ( pstate->argument < COLOR_MAX )
5089     {
5090         if ( pstate->argument < -1 || pstate->argument >= COLOR_MAX )
5091         {
5092             pchr->sparkle = NOSPARKLE;
5093         }
5094         else
5095         {
5096             pchr->sparkle = pstate->argument;
5097         }
5098     }
5099 
5100     SCRIPT_FUNCTION_END();
5101 }
5102 
5103 //--------------------------------------------------------------------------------------------
scr_UnsparkleIcon(script_state_t * pstate,ai_state_t * pself)5104 Uint8 scr_UnsparkleIcon( script_state_t * pstate, ai_state_t * pself )
5105 {
5106     // UnsparkleIcon()
5107     /// @details ZZ@> This function stops little sparklies going around the character's icon
5108 
5109     SCRIPT_FUNCTION_BEGIN();
5110 
5111     pchr->sparkle = NOSPARKLE;
5112 
5113     SCRIPT_FUNCTION_END();
5114 }
5115 
5116 //--------------------------------------------------------------------------------------------
scr_get_TileXY(script_state_t * pstate,ai_state_t * pself)5117 Uint8 scr_get_TileXY( script_state_t * pstate, ai_state_t * pself )
5118 {
5119     // tmpargument = GetTileXY( tmpx = "x", tmpy = "y" )
5120     /// @details ZZ@> This function sets tmpargument to the tile type at the specified
5121     /// coordinates
5122 
5123     Uint32 iTmp;
5124 
5125     SCRIPT_FUNCTION_BEGIN();
5126 
5127     returncode = bfalse;
5128     iTmp = mesh_get_grid( PMesh, pstate->x, pstate->y );
5129     if ( mesh_grid_is_valid( PMesh, iTmp ) )
5130     {
5131         returncode = btrue;
5132         pstate->argument = CLIP_TO_08BITS( PMesh->tmem.tile_list[iTmp].img );
5133     }
5134 
5135     SCRIPT_FUNCTION_END();
5136 }
5137 
5138 //--------------------------------------------------------------------------------------------
scr_set_TileXY(script_state_t * pstate,ai_state_t * pself)5139 Uint8 scr_set_TileXY( script_state_t * pstate, ai_state_t * pself )
5140 {
5141     // scr_set_TileXY( tmpargument = "tile type", tmpx = "x", tmpy = "y" )
5142     /// @details ZZ@> This function changes the tile type at the specified coordinates
5143 
5144     Uint32 iTmp;
5145 
5146     SCRIPT_FUNCTION_BEGIN();
5147 
5148     iTmp       = mesh_get_grid( PMesh, pstate->x, pstate->y );
5149     returncode = mesh_set_texture( PMesh, iTmp, pstate->argument );
5150 
5151     SCRIPT_FUNCTION_END();
5152 }
5153 
5154 //--------------------------------------------------------------------------------------------
scr_set_ShadowSize(script_state_t * pstate,ai_state_t * pself)5155 Uint8 scr_set_ShadowSize( script_state_t * pstate, ai_state_t * pself )
5156 {
5157     // SetShadowSize( tmpargument = "size" )
5158     /// @details ZZ@> This function makes the character's shadow bigger or smaller
5159 
5160     SCRIPT_FUNCTION_BEGIN();
5161 
5162     pchr->shadow_size     = pstate->argument * pchr->fat;
5163     pchr->shadow_size_save = pstate->argument;
5164 
5165     SCRIPT_FUNCTION_END();
5166 }
5167 
5168 //--------------------------------------------------------------------------------------------
scr_OrderTarget(script_state_t * pstate,ai_state_t * pself)5169 Uint8 scr_OrderTarget( script_state_t * pstate, ai_state_t * pself )
5170 {
5171     // OrderTarget( tmpargument = "order" )
5172     /// @details ZZ@> This function issues an order to the given target
5173     /// Be careful in using this, always checking IDSZ first
5174 
5175     chr_t * pself_target;
5176 
5177     SCRIPT_FUNCTION_BEGIN();
5178 
5179     SCRIPT_REQUIRE_TARGET( pself_target );
5180 
5181     if ( !INGAME_CHR( pself->target ) )
5182     {
5183         returncode = bfalse;
5184     }
5185     else
5186     {
5187         returncode = ai_add_order( &( pself_target->ai ), pstate->argument, 0 );
5188     }
5189 
5190     SCRIPT_FUNCTION_END();
5191 }
5192 
5193 //--------------------------------------------------------------------------------------------
scr_set_TargetToWhoeverIsInPassage(script_state_t * pstate,ai_state_t * pself)5194 Uint8 scr_set_TargetToWhoeverIsInPassage( script_state_t * pstate, ai_state_t * pself )
5195 {
5196     // SetTargetToWhoeverIsInPassage()
5197     /// @details ZZ@> This function sets the target to whoever is blocking the given passage
5198     /// This function lets passage rectangles be used as event triggers
5199 
5200     CHR_REF ichr;
5201 
5202     SCRIPT_FUNCTION_BEGIN();
5203 
5204     ichr = who_is_blocking_passage(( PASS_REF )pstate->argument, pself->index, IDSZ_NONE, TARGET_SELF | TARGET_FRIENDS | TARGET_ENEMIES, IDSZ_NONE );
5205 
5206     if ( INGAME_CHR( ichr ) )
5207     {
5208         SET_TARGET_0( ichr );
5209     }
5210     else
5211     {
5212         returncode = bfalse;
5213     }
5214 
5215     SCRIPT_FUNCTION_END();
5216 }
5217 
5218 //--------------------------------------------------------------------------------------------
scr_CharacterWasABook(script_state_t * pstate,ai_state_t * pself)5219 Uint8 scr_CharacterWasABook( script_state_t * pstate, ai_state_t * pself )
5220 {
5221     // IfCharacterWasABook()
5222     /// @details ZZ@> This function proceeds if the base model is the same as the current
5223     /// model or if the base model is SPELLBOOK
5224     /// USAGE: USED BY THE MORPH SPELL. Not much use elsewhere
5225 
5226     SCRIPT_FUNCTION_BEGIN();
5227 
5228     returncode = ( pchr->basemodel_ref == SPELLBOOK ||
5229                    pchr->basemodel_ref == pchr->profile_ref );
5230 
5231     SCRIPT_FUNCTION_END();
5232 }
5233 
5234 //--------------------------------------------------------------------------------------------
scr_set_EnchantBoostValues(script_state_t * pstate,ai_state_t * pself)5235 Uint8 scr_set_EnchantBoostValues( script_state_t * pstate, ai_state_t * pself )
5236 {
5237     // SetEnchantBoostValues( tmpargument = "owner mana regen", tmpdistance = "owner life regen", tmpx = "target mana regen", tmpy = "target life regen" )
5238     /// @details ZZ@> This function sets the mana and life drains for the last enchantment
5239     /// spawned by this character.
5240     /// Values are 8.8-bit fixed point
5241 
5242     ENC_REF iTmp;
5243 
5244     SCRIPT_FUNCTION_BEGIN();
5245 
5246     iTmp = pchr->undoenchant;
5247 
5248     returncode = bfalse;
5249     if ( INGAME_ENC( iTmp ) )
5250     {
5251         EncList.lst[iTmp].owner_mana = pstate->argument;
5252         EncList.lst[iTmp].owner_life = pstate->distance;
5253         EncList.lst[iTmp].target_mana = pstate->x;
5254         EncList.lst[iTmp].target_life = pstate->y;
5255 
5256         returncode = btrue;
5257     }
5258 
5259     SCRIPT_FUNCTION_END();
5260 }
5261 
5262 //--------------------------------------------------------------------------------------------
scr_SpawnCharacterXYZ(script_state_t * pstate,ai_state_t * pself)5263 Uint8 scr_SpawnCharacterXYZ( script_state_t * pstate, ai_state_t * pself )
5264 {
5265     // SpawnCharacterXYZ( tmpx = "x", tmpy = "y", tmpdistance = "z", tmpturn = "turn" )
5266     /// @details ZZ@> This function spawns a character of the same type at a specific location, failing if x,y,z is invalid
5267 
5268     fvec3_t   pos;
5269     CHR_REF ichr;
5270 
5271     SCRIPT_FUNCTION_BEGIN();
5272 
5273     pos.x = pstate->x;
5274     pos.y = pstate->y;
5275     pos.z = pstate->distance;
5276 
5277     ichr = spawn_one_character( pos, pchr->profile_ref, pchr->team, 0, CLIP_TO_16BITS( pstate->turn ), NULL, ( CHR_REF )MAX_CHR );
5278     returncode = DEFINED_CHR( ichr );
5279 
5280     if ( !returncode )
5281     {
5282         if ( ichr > PMod->importamount * MAXIMPORTPERPLAYER )
5283         {
5284             log_warning( "Object %s failed to spawn a copy of itself\n", pchr->obj_base._name );
5285         }
5286     }
5287     else
5288     {
5289         chr_t * pchild = ChrList.lst + ichr;
5290 
5291         // was the child spawned in a "safe" spot?
5292         if ( !chr_get_safe( pchild, NULL ) )
5293         {
5294             chr_request_terminate( ichr );
5295             ichr = ( CHR_REF )MAX_CHR;
5296         }
5297         else
5298         {
5299             pself->child = ichr;
5300 
5301             pchild->iskursed   = pchr->iskursed;  /// @details BB@> inherit this from your spawner
5302             pchild->ai.passage = pself->passage;
5303             pchild->ai.owner   = pself->owner;
5304 
5305             pchild->dismount_timer  = PHYS_DISMOUNT_TIME;
5306             pchild->dismount_object = pself->index;
5307         }
5308     }
5309 
5310     SCRIPT_FUNCTION_END();
5311 }
5312 
5313 //--------------------------------------------------------------------------------------------
scr_SpawnExactCharacterXYZ(script_state_t * pstate,ai_state_t * pself)5314 Uint8 scr_SpawnExactCharacterXYZ( script_state_t * pstate, ai_state_t * pself )
5315 {
5316     // SpawnCharacterXYZ( tmpargument = "slot", tmpx = "x", tmpy = "y", tmpdistance = "z", tmpturn = "turn" )
5317     /// @details ZZ@> This function spawns a character at a specific location, using a
5318     /// specific model type, failing if x,y,z is invalid
5319     /// DON'T USE THIS FOR EXPORTABLE ITEMS OR CHARACTERS,
5320     /// AS THE MODEL SLOTS MAY VARY FROM MODULE TO MODULE.
5321 
5322     fvec3_t   pos;
5323     CHR_REF ichr;
5324 
5325     SCRIPT_FUNCTION_BEGIN();
5326 
5327     pos.x = pstate->x;
5328     pos.y = pstate->y;
5329     pos.z = pstate->distance;
5330 
5331     ichr = spawn_one_character( pos, ( PRO_REF )pstate->argument, pchr->team, 0, CLIP_TO_16BITS( pstate->turn ), NULL, ( CHR_REF )MAX_CHR );
5332     returncode = DEFINED_CHR( ichr );
5333 
5334     if ( !returncode )
5335     {
5336         if ( ichr > PMod->importamount * MAXIMPORTPERPLAYER )
5337         {
5338             cap_t * pcap = pro_get_pcap( pchr->profile_ref );
5339 
5340             log_warning( "Object \"%s\"(\"%s\") failed to spawn profile index %d\n", pchr->obj_base._name, NULL == pcap ? "INVALID" : pcap->classname, pstate->argument );
5341         }
5342     }
5343     else
5344     {
5345         chr_t * pchild = ChrList.lst + ichr;
5346 
5347         // was the child spawned in a "safe" spot?
5348         if ( !chr_get_safe( pchild, NULL ) )
5349         {
5350             chr_request_terminate( ichr );
5351             ichr = ( CHR_REF )MAX_CHR;
5352         }
5353         else
5354         {
5355             pself->child = ichr;
5356 
5357             pchild->iskursed   = pchr->iskursed;  /// @details BB@> inherit this from your spawner
5358             pchild->ai.passage = pself->passage;
5359             pchild->ai.owner   = pself->owner;
5360 
5361             pchild->dismount_timer  = PHYS_DISMOUNT_TIME;
5362             pchild->dismount_object = pself->index;
5363         }
5364     }
5365 
5366     SCRIPT_FUNCTION_END();
5367 }
5368 
5369 //--------------------------------------------------------------------------------------------
scr_ChangeTargetClass(script_state_t * pstate,ai_state_t * pself)5370 Uint8 scr_ChangeTargetClass( script_state_t * pstate, ai_state_t * pself )
5371 {
5372     // ChangeTargetClass( tmpargument = "slot" )
5373 
5374     /// @details ZZ@> This function changes the target character's model slot.
5375     /// DON'T USE THIS FOR EXPORTABLE ITEMS OR CHARACTERS, AS THE MODEL SLOTS MAY VARY FROM
5376     /// MODULE TO MODULE.
5377     /// USAGE: This is intended as a way to incorporate more player classes into the game.
5378 
5379     SCRIPT_FUNCTION_BEGIN();
5380 
5381     change_character_full( pself->target, ( PRO_REF )pstate->argument, 0, ENC_LEAVE_ALL );
5382 
5383     SCRIPT_FUNCTION_END();
5384 }
5385 
5386 //--------------------------------------------------------------------------------------------
scr_PlayFullSound(script_state_t * pstate,ai_state_t * pself)5387 Uint8 scr_PlayFullSound( script_state_t * pstate, ai_state_t * pself )
5388 {
5389     // PlayFullSound( tmpargument = "sound", tmpdistance = "frequency" )
5390     /// @details ZZ@> This function plays one of the character's sounds .
5391     /// The sound will be heard at full volume by all players (Victory music)
5392 
5393     SCRIPT_FUNCTION_BEGIN();
5394 
5395     if ( VALID_SND( pstate->argument ) )
5396     {
5397         sound_play_chunk_full( chr_get_chunk_ptr( pchr, pstate->argument ) );
5398     }
5399 
5400     SCRIPT_FUNCTION_END();
5401 }
5402 
5403 //--------------------------------------------------------------------------------------------
scr_SpawnExactChaseParticle(script_state_t * pstate,ai_state_t * pself)5404 Uint8 scr_SpawnExactChaseParticle( script_state_t * pstate, ai_state_t * pself )
5405 {
5406     // SpawnExactChaseParticle( tmpargument = "particle", tmpx = "x", tmpy = "y", tmpdistance = "z" )
5407     /// @details ZZ@> This function spawns a particle at a specific x, y, z position,
5408     /// that will home in on the character's target
5409 
5410     PRT_REF iprt;
5411     CHR_REF ichr;
5412 
5413     SCRIPT_FUNCTION_BEGIN();
5414 
5415     ichr = pself->index;
5416     if ( INGAME_CHR( pchr->attachedto ) )
5417     {
5418         ichr = pchr->attachedto;
5419     }
5420 
5421     {
5422         fvec3_t   vtmp = VECT3( pstate->x, pstate->y, pstate->distance );
5423         iprt = spawn_one_particle( vtmp, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, ( CHR_REF )MAX_CHR, 0, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
5424     }
5425 
5426     returncode = DEFINED_PRT( iprt );
5427 
5428     if ( returncode )
5429     {
5430         PrtList.lst[iprt].target_ref = pself->target;
5431     }
5432 
5433     SCRIPT_FUNCTION_END();
5434 }
5435 
5436 //--------------------------------------------------------------------------------------------
scr_CreateOrder(script_state_t * pstate,ai_state_t * pself)5437 Uint8 scr_CreateOrder( script_state_t * pstate, ai_state_t * pself )
5438 {
5439     // tmpargument = CreateOrder( tmpx = "value1", tmpy = "value2", tmpargument = "order" )
5440 
5441     /// @details ZZ@> This function compresses tmpx, tmpy, tmpargument ( 0 - 15 ), and the
5442     /// character's target into tmpargument.  This new tmpargument can then
5443     /// be issued as an order to teammates.  TranslateOrder will undo the
5444     /// compression
5445 
5446     Uint16 sTmp = 0;
5447 
5448     SCRIPT_FUNCTION_BEGIN();
5449 
5450     sTmp = ( REF_TO_INT( pself->target ) & 0x00FF ) << 24;
5451     sTmp |= (( pstate->x >> 6 ) & 0x03FF ) << 14;
5452     sTmp |= (( pstate->y >> 6 ) & 0x03FF ) << 4;
5453     sTmp |= ( pstate->argument & 0x000F );
5454     pstate->argument = sTmp;
5455 
5456     SCRIPT_FUNCTION_END();
5457 }
5458 
5459 //--------------------------------------------------------------------------------------------
scr_OrderSpecialID(script_state_t * pstate,ai_state_t * pself)5460 Uint8 scr_OrderSpecialID( script_state_t * pstate, ai_state_t * pself )
5461 {
5462     // OrderSpecialID( tmpargument = "compressed order", tmpdistance = "idsz" )
5463     /// @details ZZ@> This function orders all characters with the given special IDSZ.
5464 
5465     SCRIPT_FUNCTION_BEGIN();
5466 
5467     issue_special_order( pstate->argument, pstate->distance );
5468 
5469     SCRIPT_FUNCTION_END();
5470 }
5471 
5472 //--------------------------------------------------------------------------------------------
scr_UnkurseTargetInventory(script_state_t * pstate,ai_state_t * pself)5473 Uint8 scr_UnkurseTargetInventory( script_state_t * pstate, ai_state_t * pself )
5474 {
5475     // UnkurseTargetInventory()
5476     /// @details ZZ@> This function unkurses all items held and in the pockets of the target
5477 
5478     CHR_REF ichr;
5479     chr_t * pself_target;
5480 
5481     SCRIPT_FUNCTION_BEGIN();
5482 
5483     SCRIPT_REQUIRE_TARGET( pself_target );
5484 
5485     ichr = pself_target->holdingwhich[SLOT_LEFT];
5486     if ( INGAME_CHR( ichr ) )
5487     {
5488         ChrList.lst[ichr].iskursed = bfalse;
5489     }
5490 
5491     ichr = pself_target->holdingwhich[SLOT_RIGHT];
5492     if ( INGAME_CHR( ichr ) )
5493     {
5494         ChrList.lst[ichr].iskursed = bfalse;
5495     }
5496 
5497     PACK_BEGIN_LOOP( ipacked, pself_target->pack.next )
5498     {
5499         if ( INGAME_CHR( ipacked ) )
5500         {
5501             ChrList.lst[ipacked].iskursed = bfalse;
5502         }
5503     }
5504     PACK_END_LOOP( ipacked );
5505 
5506     SCRIPT_FUNCTION_END();
5507 }
5508 
5509 //--------------------------------------------------------------------------------------------
scr_TargetIsSneaking(script_state_t * pstate,ai_state_t * pself)5510 Uint8 scr_TargetIsSneaking( script_state_t * pstate, ai_state_t * pself )
5511 {
5512     // IfTargetIsSneaking()
5513     /// @details ZZ@> This function proceeds if the target is doing ACTION_WA or ACTION_DA
5514 
5515     chr_t * pself_target;
5516 
5517     SCRIPT_FUNCTION_BEGIN();
5518 
5519     SCRIPT_REQUIRE_TARGET( pself_target );
5520 
5521     returncode = ( pself_target->inst.action_which == ACTION_DA || pself_target->inst.action_which == ACTION_WA );
5522 
5523     SCRIPT_FUNCTION_END();
5524 }
5525 
5526 //--------------------------------------------------------------------------------------------
scr_DropItems(script_state_t * pstate,ai_state_t * pself)5527 Uint8 scr_DropItems( script_state_t * pstate, ai_state_t * pself )
5528 {
5529     // DropItems()
5530     /// @details ZZ@> This function drops all of the items the character is holding
5531 
5532     SCRIPT_FUNCTION_BEGIN();
5533 
5534     drop_all_items( pself->index );
5535 
5536     SCRIPT_FUNCTION_END();
5537 }
5538 
5539 //--------------------------------------------------------------------------------------------
scr_RespawnTarget(script_state_t * pstate,ai_state_t * pself)5540 Uint8 scr_RespawnTarget( script_state_t * pstate, ai_state_t * pself )
5541 {
5542     // RespawnTarget()
5543     /// @details ZZ@> This function respawns the target at its current location
5544 
5545     chr_t * pself_target;
5546 
5547     SCRIPT_FUNCTION_BEGIN();
5548 
5549     SCRIPT_REQUIRE_TARGET( pself_target );
5550 
5551     respawn_character( pself->target );
5552 
5553     SCRIPT_FUNCTION_END();
5554 }
5555 
5556 //--------------------------------------------------------------------------------------------
scr_TargetDoActionSetFrame(script_state_t * pstate,ai_state_t * pself)5557 Uint8 scr_TargetDoActionSetFrame( script_state_t * pstate, ai_state_t * pself )
5558 {
5559     // TargetDoActionSetFrame( tmpargument = "action" )
5560     /// @details ZZ@> This function starts the target doing the given action, and also sets
5561     /// the starting frame to the first of the animation ( so there is no
5562     /// interpolation 'cause it looks awful in some circumstances )
5563     /// It will fail if the action is invalid
5564 
5565     SCRIPT_FUNCTION_BEGIN();
5566 
5567     returncode = bfalse;
5568     if ( INGAME_CHR( pself->target ) )
5569     {
5570         int action;
5571         chr_t * pself_target = ChrList.lst + pself->target;
5572 
5573         action = mad_get_action_ref( pself_target->inst.imad, pstate->argument );
5574 
5575         if ( rv_success == chr_start_anim( pself_target, action, bfalse, btrue ) )
5576         {
5577             // remove the interpolation
5578             chr_instance_remove_interpolation( &( pself_target->inst ) );
5579 
5580             returncode = btrue;
5581         }
5582     }
5583 
5584     SCRIPT_FUNCTION_END();
5585 }
5586 
5587 //--------------------------------------------------------------------------------------------
scr_TargetCanSeeInvisible(script_state_t * pstate,ai_state_t * pself)5588 Uint8 scr_TargetCanSeeInvisible( script_state_t * pstate, ai_state_t * pself )
5589 {
5590     // IfTargetCanSeeInvisible()
5591     /// @details ZZ@> This function proceeds if the target can see invisible
5592 
5593     chr_t * pself_target;
5594 
5595     SCRIPT_FUNCTION_BEGIN();
5596 
5597     SCRIPT_REQUIRE_TARGET( pself_target );
5598 
5599     returncode = pself_target->see_invisible_level;
5600 
5601     SCRIPT_FUNCTION_END();
5602 }
5603 
5604 //--------------------------------------------------------------------------------------------
scr_set_TargetToNearestBlahID(script_state_t * pstate,ai_state_t * pself)5605 Uint8 scr_set_TargetToNearestBlahID( script_state_t * pstate, ai_state_t * pself )
5606 {
5607     // SetTargetToNearestBlahID( tmpargument = "idsz", tmpdistance = "blah bits" )
5608 
5609     /// @details ZZ@> This function finds the NEAREST ( exact ) character that fits the given
5610     /// parameters, failing if it finds none
5611 
5612     CHR_REF ichr;
5613 
5614     SCRIPT_FUNCTION_BEGIN();
5615 
5616     // Try to find one
5617     ichr = chr_find_target( pchr, NEAREST, pstate->argument, pstate->distance );
5618 
5619     if ( INGAME_CHR( ichr ) )
5620     {
5621         SET_TARGET_0( ichr );
5622     }
5623     else
5624     {
5625         returncode = bfalse;
5626     }
5627 
5628     SCRIPT_FUNCTION_END();
5629 }
5630 
5631 //--------------------------------------------------------------------------------------------
scr_set_TargetToNearestEnemy(script_state_t * pstate,ai_state_t * pself)5632 Uint8 scr_set_TargetToNearestEnemy( script_state_t * pstate, ai_state_t * pself )
5633 {
5634     // SetTargetToNearestEnemy()
5635     /// @details ZZ@> This function finds the NEAREST ( exact ) enemy, failing if it finds none
5636 
5637     CHR_REF ichr;
5638 
5639     SCRIPT_FUNCTION_BEGIN();
5640 
5641     ichr = chr_find_target( pchr, NEAREST, IDSZ_NONE, TARGET_ENEMIES );
5642 
5643     if ( INGAME_CHR( ichr ) )
5644     {
5645         SET_TARGET_0( ichr );
5646     }
5647     else
5648     {
5649         returncode = bfalse;
5650     }
5651 
5652     SCRIPT_FUNCTION_END();
5653 }
5654 
5655 //--------------------------------------------------------------------------------------------
scr_set_TargetToNearestFriend(script_state_t * pstate,ai_state_t * pself)5656 Uint8 scr_set_TargetToNearestFriend( script_state_t * pstate, ai_state_t * pself )
5657 {
5658     // SetTargetToNearestFriend()
5659     /// @details ZZ@> This function finds the NEAREST ( exact ) friend, failing if it finds none
5660 
5661     CHR_REF ichr;
5662 
5663     SCRIPT_FUNCTION_BEGIN();
5664 
5665     ichr = chr_find_target( pchr, NEAREST, IDSZ_NONE, TARGET_FRIENDS );
5666 
5667     if ( INGAME_CHR( ichr ) )
5668     {
5669         SET_TARGET_0( ichr );
5670     }
5671     else
5672     {
5673         returncode = bfalse;
5674     }
5675 
5676     SCRIPT_FUNCTION_END();
5677 }
5678 
5679 //--------------------------------------------------------------------------------------------
scr_set_TargetToNearestLifeform(script_state_t * pstate,ai_state_t * pself)5680 Uint8 scr_set_TargetToNearestLifeform( script_state_t * pstate, ai_state_t * pself )
5681 {
5682     // SetTargetToNearestLifeform()
5683 
5684     /// @details ZZ@> This function finds the NEAREST ( exact ) friend or enemy, failing if it
5685     /// finds none
5686 
5687     CHR_REF ichr;
5688 
5689     SCRIPT_FUNCTION_BEGIN();
5690 
5691     ichr = chr_find_target( pchr, NEAREST, IDSZ_NONE, TARGET_ITEMS | TARGET_FRIENDS | TARGET_ENEMIES );
5692 
5693     if ( INGAME_CHR( ichr ) )
5694     {
5695         SET_TARGET_0( ichr );
5696     }
5697     else
5698     {
5699         returncode = bfalse;
5700     }
5701 
5702     SCRIPT_FUNCTION_END();
5703 }
5704 
5705 //--------------------------------------------------------------------------------------------
scr_FlashPassage(script_state_t * pstate,ai_state_t * pself)5706 Uint8 scr_FlashPassage( script_state_t * pstate, ai_state_t * pself )
5707 {
5708     // FlashPassage( tmpargument = "passage", tmpdistance = "color" )
5709 
5710     /// @details ZZ@> This function makes the given passage light or dark.
5711     /// Usage: For debug purposes
5712 
5713     SCRIPT_FUNCTION_BEGIN();
5714 
5715     flash_passage(( PASS_REF )pstate->argument, pstate->distance );
5716 
5717     SCRIPT_FUNCTION_END();
5718 }
5719 
5720 //--------------------------------------------------------------------------------------------
scr_FindTileInPassage(script_state_t * pstate,ai_state_t * pself)5721 Uint8 scr_FindTileInPassage( script_state_t * pstate, ai_state_t * pself )
5722 {
5723     // tmpx, tmpy = FindTileInPassage( tmpargument = "passage", tmpdistance = "tile type", tmpx, tmpy )
5724 
5725     /// @details ZZ@> This function finds all tiles of the specified type that lie within the
5726     /// given passage.  Call multiple times to find multiple tiles.  tmpx and
5727     /// tmpy will be set to the middle of the found tile if one is found, or
5728     /// both will be set to 0 if no tile is found.
5729     /// tmpx and tmpy are required and set on return
5730 
5731     SCRIPT_FUNCTION_BEGIN();
5732 
5733     returncode = _find_grid_in_passage( pstate->x, pstate->y, pstate->distance, ( PASS_REF )pstate->argument, &( pstate->x ), &( pstate->y ) );
5734 
5735     SCRIPT_FUNCTION_END();
5736 }
5737 
5738 //--------------------------------------------------------------------------------------------
scr_HeldInLeftHand(script_state_t * pstate,ai_state_t * pself)5739 Uint8 scr_HeldInLeftHand( script_state_t * pstate, ai_state_t * pself )
5740 {
5741     // IfHeldInLeftHand()
5742     /// @details ZZ@> This function passes if another character is holding the character in its
5743     /// left hand.
5744     /// Usage: Used mostly by enchants that target the item of the other hand
5745 
5746     CHR_REF ichr;
5747 
5748     SCRIPT_FUNCTION_BEGIN();
5749 
5750     returncode = bfalse;
5751     ichr = pchr->attachedto;
5752     if ( INGAME_CHR( ichr ) )
5753     {
5754         returncode = ( ChrList.lst[ichr].holdingwhich[SLOT_LEFT] == pself->index );
5755     }
5756 
5757     SCRIPT_FUNCTION_END();
5758 }
5759 
5760 //--------------------------------------------------------------------------------------------
scr_NotAnItem(script_state_t * pstate,ai_state_t * pself)5761 Uint8 scr_NotAnItem( script_state_t * pstate, ai_state_t * pself )
5762 {
5763     // NotAnItem()
5764     /// @details ZZ@> This function makes the character a non-item character.
5765     /// Usage: Used for spells that summon creatures
5766 
5767     SCRIPT_FUNCTION_BEGIN();
5768 
5769     pchr->isitem = bfalse;
5770 
5771     SCRIPT_FUNCTION_END();
5772 }
5773 
5774 //--------------------------------------------------------------------------------------------
scr_set_ChildAmmo(script_state_t * pstate,ai_state_t * pself)5775 Uint8 scr_set_ChildAmmo( script_state_t * pstate, ai_state_t * pself )
5776 {
5777     // SetChildAmmo( tmpargument = "none" )
5778     /// @details ZZ@> This function sets the ammo of the last character spawned by this character
5779 
5780     SCRIPT_FUNCTION_BEGIN();
5781 
5782     ChrList.lst[pself->child].ammo = pstate->argument;
5783 
5784     SCRIPT_FUNCTION_END();
5785 }
5786 
5787 //--------------------------------------------------------------------------------------------
scr_HitVulnerable(script_state_t * pstate,ai_state_t * pself)5788 Uint8 scr_HitVulnerable( script_state_t * pstate, ai_state_t * pself )
5789 {
5790     // IfHitVulnerable()
5791     /// @details ZZ@> This function proceeds if the character was hit by a weapon of its
5792     /// vulnerability IDSZ.
5793     /// For example, a werewolf gets hit by a [SILV] bullet.
5794 
5795     SCRIPT_FUNCTION_BEGIN();
5796 
5797     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_HITVULNERABLE );
5798 
5799     SCRIPT_FUNCTION_END();
5800 }
5801 
5802 //--------------------------------------------------------------------------------------------
scr_TargetIsFlying(script_state_t * pstate,ai_state_t * pself)5803 Uint8 scr_TargetIsFlying( script_state_t * pstate, ai_state_t * pself )
5804 {
5805     // IfTargetIsFlying()
5806     /// @details ZZ@> This function proceeds if the character target is flying
5807 
5808     chr_t * pself_target;
5809 
5810     SCRIPT_FUNCTION_BEGIN();
5811 
5812     SCRIPT_REQUIRE_TARGET( pself_target );
5813 
5814     returncode = ( pself_target->flyheight > 0 );
5815 
5816     SCRIPT_FUNCTION_END();
5817 }
5818 
5819 //--------------------------------------------------------------------------------------------
scr_IdentifyTarget(script_state_t * pstate,ai_state_t * pself)5820 Uint8 scr_IdentifyTarget( script_state_t * pstate, ai_state_t * pself )
5821 {
5822     // IdentifyTarget()
5823     /// @details ZZ@> This function reveals the target's name, ammo, and usage
5824     /// Proceeds if the target was unknown
5825 
5826     cap_t * pcap;
5827     CHR_REF ichr;
5828 
5829     SCRIPT_FUNCTION_BEGIN();
5830 
5831     returncode = bfalse;
5832     ichr = pself->target;
5833     if ( ChrList.lst[ichr].ammomax != 0 )  ChrList.lst[ichr].ammoknown = btrue;
5834     if ( 0 == strcmp( "Blah", ChrList.lst[ichr].Name ) )
5835     {
5836         returncode = !ChrList.lst[ichr].nameknown;
5837         ChrList.lst[ichr].nameknown = btrue;
5838     }
5839 
5840     pcap = chr_get_pcap( pself->target );
5841     if ( NULL != pcap )
5842     {
5843         pcap->usageknown = btrue;
5844     }
5845 
5846     SCRIPT_FUNCTION_END();
5847 }
5848 
5849 //--------------------------------------------------------------------------------------------
scr_BeatModule(script_state_t * pstate,ai_state_t * pself)5850 Uint8 scr_BeatModule( script_state_t * pstate, ai_state_t * pself )
5851 {
5852     // BeatModule()
5853     /// @details ZZ@> This function displays the Module Ended message
5854 
5855     SCRIPT_FUNCTION_BEGIN();
5856 
5857     PMod->beat = btrue;
5858 
5859     SCRIPT_FUNCTION_END();
5860 }
5861 
5862 //--------------------------------------------------------------------------------------------
scr_EndModule(script_state_t * pstate,ai_state_t * pself)5863 Uint8 scr_EndModule( script_state_t * pstate, ai_state_t * pself )
5864 {
5865     // EndModule()
5866     /// @details ZZ@> This function presses the Escape key
5867 
5868     SCRIPT_FUNCTION_BEGIN();
5869 
5870     // This tells the game to quit
5871     EProc->escape_requested = btrue;
5872 
5873     SCRIPT_FUNCTION_END();
5874 }
5875 
5876 //--------------------------------------------------------------------------------------------
scr_DisableExport(script_state_t * pstate,ai_state_t * pself)5877 Uint8 scr_DisableExport( script_state_t * pstate, ai_state_t * pself )
5878 {
5879     // DisableExport()
5880     /// @details ZZ@> This function turns export off
5881 
5882     SCRIPT_FUNCTION_BEGIN();
5883 
5884     PMod->exportvalid = bfalse;
5885 
5886     SCRIPT_FUNCTION_END();
5887 }
5888 
5889 //--------------------------------------------------------------------------------------------
scr_EnableExport(script_state_t * pstate,ai_state_t * pself)5890 Uint8 scr_EnableExport( script_state_t * pstate, ai_state_t * pself )
5891 {
5892     // EnableExport()
5893     /// @details ZZ@> This function turns export on
5894 
5895     SCRIPT_FUNCTION_BEGIN();
5896 
5897     PMod->exportvalid = btrue;
5898 
5899     SCRIPT_FUNCTION_END();
5900 }
5901 
5902 //--------------------------------------------------------------------------------------------
scr_get_TargetState(script_state_t * pstate,ai_state_t * pself)5903 Uint8 scr_get_TargetState( script_state_t * pstate, ai_state_t * pself )
5904 {
5905     // tmpargument = GetTargetState()
5906     /// @details ZZ@> This function sets tmpargument to the state of the target
5907 
5908     chr_t * pself_target;
5909 
5910     SCRIPT_FUNCTION_BEGIN();
5911 
5912     SCRIPT_REQUIRE_TARGET( pself_target );
5913 
5914     pstate->argument = pself_target->ai.state;
5915 
5916     SCRIPT_FUNCTION_END();
5917 }
5918 
5919 //--------------------------------------------------------------------------------------------
scr_Equipped(script_state_t * pstate,ai_state_t * pself)5920 Uint8 scr_Equipped( script_state_t * pstate, ai_state_t * pself )
5921 {
5922     // This proceeds if the character is equipped
5923 
5924     SCRIPT_FUNCTION_BEGIN();
5925 
5926     returncode = pchr->isequipped;
5927 
5928     SCRIPT_FUNCTION_END();
5929 }
5930 
5931 //--------------------------------------------------------------------------------------------
scr_DropTargetMoney(script_state_t * pstate,ai_state_t * pself)5932 Uint8 scr_DropTargetMoney( script_state_t * pstate, ai_state_t * pself )
5933 {
5934     // DropTargetMoney( tmpargument = "amount" )
5935     /// @details ZZ@> This function drops some of the target's money
5936 
5937     SCRIPT_FUNCTION_BEGIN();
5938 
5939     drop_money( pself->target, pstate->argument );
5940 
5941     SCRIPT_FUNCTION_END();
5942 }
5943 
5944 //--------------------------------------------------------------------------------------------
scr_get_TargetContent(script_state_t * pstate,ai_state_t * pself)5945 Uint8 scr_get_TargetContent( script_state_t * pstate, ai_state_t * pself )
5946 {
5947     // tmpargument = GetTargetContent()
5948     // This sets tmpargument to the current Target's content value
5949 
5950     chr_t * pself_target;
5951 
5952     SCRIPT_FUNCTION_BEGIN();
5953 
5954     SCRIPT_REQUIRE_TARGET( pself_target );
5955 
5956     pstate->argument = pself_target->ai.content;
5957 
5958     SCRIPT_FUNCTION_END();
5959 }
5960 
5961 //--------------------------------------------------------------------------------------------
scr_DropTargetKeys(script_state_t * pstate,ai_state_t * pself)5962 Uint8 scr_DropTargetKeys( script_state_t * pstate, ai_state_t * pself )
5963 {
5964     // DropTargetKeys()
5965     /// @details ZZ@> This function makes the Target drops keys in inventory (Not inhand)
5966 
5967     SCRIPT_FUNCTION_BEGIN();
5968 
5969     drop_keys( pself->target );
5970 
5971     SCRIPT_FUNCTION_END();
5972 }
5973 
5974 //--------------------------------------------------------------------------------------------
scr_JoinTeam(script_state_t * pstate,ai_state_t * pself)5975 Uint8 scr_JoinTeam( script_state_t * pstate, ai_state_t * pself )
5976 {
5977     // JoinTeam( tmpargument = "team" )
5978     /// @details ZZ@> This makes the character itself join a specified team (A = 0, B = 1, 23 = Z, etc.)
5979 
5980     SCRIPT_FUNCTION_BEGIN();
5981 
5982     switch_team( pself->index, ( TEAM_REF )pstate->argument );
5983 
5984     SCRIPT_FUNCTION_END();
5985 }
5986 
5987 //--------------------------------------------------------------------------------------------
scr_TargetJoinTeam(script_state_t * pstate,ai_state_t * pself)5988 Uint8 scr_TargetJoinTeam( script_state_t * pstate, ai_state_t * pself )
5989 {
5990     // TargetJoinTeam( tmpargument = "team" )
5991     /// @details ZZ@> This makes the Target join a Team specified in tmpargument (A = 0, 25 = Z, etc.)
5992 
5993     SCRIPT_FUNCTION_BEGIN();
5994 
5995     switch_team( pself->target, ( TEAM_REF )pstate->argument );
5996 
5997     SCRIPT_FUNCTION_END();
5998 }
5999 
6000 //--------------------------------------------------------------------------------------------
scr_ClearMusicPassage(script_state_t * pstate,ai_state_t * pself)6001 Uint8 scr_ClearMusicPassage( script_state_t * pstate, ai_state_t * pself )
6002 {
6003     // ClearMusicPassage( tmpargument = "passage" )
6004     /// @details ZZ@> This clears the music for a specified passage
6005 
6006     SCRIPT_FUNCTION_BEGIN();
6007 
6008     returncode = bfalse;
6009     if ( pstate->argument >= 0 && pstate->argument < MAX_PASS )
6010     {
6011         PASS_REF ipass = ( PASS_REF )pstate->argument;
6012 
6013         PassageStack.lst[ipass].music = NO_MUSIC;
6014     }
6015 
6016     SCRIPT_FUNCTION_END();
6017 }
6018 
6019 //--------------------------------------------------------------------------------------------
scr_ClearEndMessage(script_state_t * pstate,ai_state_t * pself)6020 Uint8 scr_ClearEndMessage( script_state_t * pstate, ai_state_t * pself )
6021 {
6022     // ClearEndMessage()
6023     /// @details ZZ@> This function empties the end-module text buffer
6024 
6025     SCRIPT_FUNCTION_BEGIN();
6026 
6027     endtext[0] = CSTR_END;
6028     endtext_carat = 0;
6029 
6030     SCRIPT_FUNCTION_END();
6031 }
6032 
6033 //--------------------------------------------------------------------------------------------
scr_AddEndMessage(script_state_t * pstate,ai_state_t * pself)6034 Uint8 scr_AddEndMessage( script_state_t * pstate, ai_state_t * pself )
6035 {
6036     // AddEndMessage( tmpargument = "message" )
6037     /// @details ZZ@> This function appends a message to the end-module text buffer
6038 
6039     SCRIPT_FUNCTION_BEGIN();
6040 
6041     returncode = _append_end_text( pchr,  pstate->argument, pstate );
6042 
6043     SCRIPT_FUNCTION_END();
6044 }
6045 
6046 //--------------------------------------------------------------------------------------------
scr_PlayMusic(script_state_t * pstate,ai_state_t * pself)6047 Uint8 scr_PlayMusic( script_state_t * pstate, ai_state_t * pself )
6048 {
6049     // PlayMusic( tmpargument = "song number", tmpdistance = "fade time (msec)" )
6050     /// @details ZZ@> This function begins playing a new track of music
6051 
6052     SCRIPT_FUNCTION_BEGIN();
6053 
6054     if ( snd.musicvalid && ( songplaying != pstate->argument ) )
6055     {
6056         sound_play_song( pstate->argument, pstate->distance, -1 );
6057     }
6058 
6059     SCRIPT_FUNCTION_END();
6060 }
6061 
6062 //--------------------------------------------------------------------------------------------
scr_set_MusicPassage(script_state_t * pstate,ai_state_t * pself)6063 Uint8 scr_set_MusicPassage( script_state_t * pstate, ai_state_t * pself )
6064 {
6065     // SetMusicPassage( tmpargument = "passage", tmpturn = "type", tmpdistance = "repetitions" )
6066 
6067     /// @details ZZ@> This function makes the given passage play music if a player enters it
6068     /// tmpargument is the passage to set and tmpdistance is the music track to play.
6069 
6070     SCRIPT_FUNCTION_BEGIN();
6071 
6072     returncode = bfalse;
6073     if ( pstate->argument >= 0 && pstate->argument < MAX_PASS )
6074     {
6075         PASS_REF ipass = ( PASS_REF )pstate->argument;
6076 
6077         PassageStack.lst[ipass].music = pstate->distance;
6078     }
6079 
6080     SCRIPT_FUNCTION_END();
6081 }
6082 
6083 //--------------------------------------------------------------------------------------------
scr_MakeCrushInvalid(script_state_t * pstate,ai_state_t * pself)6084 Uint8 scr_MakeCrushInvalid( script_state_t * pstate, ai_state_t * pself )
6085 {
6086     // MakeCrushInvalid()
6087     /// @details ZZ@> This function makes doors unable to close on this object
6088 
6089     SCRIPT_FUNCTION_BEGIN();
6090 
6091     pchr->canbecrushed = bfalse;
6092 
6093     SCRIPT_FUNCTION_END();
6094 }
6095 
6096 //--------------------------------------------------------------------------------------------
scr_StopMusic(script_state_t * pstate,ai_state_t * pself)6097 Uint8 scr_StopMusic( script_state_t * pstate, ai_state_t * pself )
6098 {
6099     // StopMusic()
6100     /// @details ZZ@> This function stops the interactive music
6101 
6102     SCRIPT_FUNCTION_BEGIN();
6103 
6104     sound_stop_song();
6105 
6106     SCRIPT_FUNCTION_END();
6107 }
6108 
6109 //--------------------------------------------------------------------------------------------
scr_FlashVariable(script_state_t * pstate,ai_state_t * pself)6110 Uint8 scr_FlashVariable( script_state_t * pstate, ai_state_t * pself )
6111 {
6112     // FlashVariable( tmpargument = "amount" )
6113 
6114     /// @details ZZ@> This function makes the character flash according to tmpargument
6115 
6116     SCRIPT_FUNCTION_BEGIN();
6117 
6118     flash_character( pself->index, pstate->argument );
6119 
6120     SCRIPT_FUNCTION_END();
6121 }
6122 
6123 //--------------------------------------------------------------------------------------------
scr_AccelerateUp(script_state_t * pstate,ai_state_t * pself)6124 Uint8 scr_AccelerateUp( script_state_t * pstate, ai_state_t * pself )
6125 {
6126     // AccelerateUp( tmpargument = "acc z" )
6127     /// @details ZZ@> This function makes the character accelerate up and down
6128 
6129     SCRIPT_FUNCTION_BEGIN();
6130 
6131     pchr->vel.z += pstate->argument / 100.0f;
6132 
6133     SCRIPT_FUNCTION_END();
6134 }
6135 
6136 //--------------------------------------------------------------------------------------------
scr_FlashVariableHeight(script_state_t * pstate,ai_state_t * pself)6137 Uint8 scr_FlashVariableHeight( script_state_t * pstate, ai_state_t * pself )
6138 {
6139     // FlashVariableHeight( tmpturn = "intensity bottom", tmpx = "bottom", tmpdistance = "intensity top", tmpy = "top" )
6140     /// @details ZZ@> This function makes the character flash, feet one color, head another.
6141 
6142     SCRIPT_FUNCTION_BEGIN();
6143 
6144     flash_character_height( pself->index, CLIP_TO_16BITS( pstate->turn ), pstate->x, pstate->distance, pstate->y );
6145 
6146     SCRIPT_FUNCTION_END();
6147 }
6148 
6149 //--------------------------------------------------------------------------------------------
scr_set_DamageTime(script_state_t * pstate,ai_state_t * pself)6150 Uint8 scr_set_DamageTime( script_state_t * pstate, ai_state_t * pself )
6151 {
6152     // SetDamageTime( tmpargument = "time" )
6153     /// @details ZZ@> This function makes the character invincible for a little while
6154 
6155     SCRIPT_FUNCTION_BEGIN();
6156 
6157     pchr->damage_timer = pstate->argument;
6158 
6159     SCRIPT_FUNCTION_END();
6160 }
6161 
6162 //--------------------------------------------------------------------------------------------
scr_StateIs8(script_state_t * pstate,ai_state_t * pself)6163 Uint8 scr_StateIs8( script_state_t * pstate, ai_state_t * pself )
6164 {
6165     SCRIPT_FUNCTION_BEGIN();
6166 
6167     returncode = ( 8 == pself->state );
6168 
6169     SCRIPT_FUNCTION_END();
6170 }
6171 
6172 //--------------------------------------------------------------------------------------------
scr_StateIs9(script_state_t * pstate,ai_state_t * pself)6173 Uint8 scr_StateIs9( script_state_t * pstate, ai_state_t * pself )
6174 {
6175     SCRIPT_FUNCTION_BEGIN();
6176 
6177     returncode = ( 9 == pself->state );
6178 
6179     SCRIPT_FUNCTION_END();
6180 }
6181 
6182 //--------------------------------------------------------------------------------------------
scr_StateIs10(script_state_t * pstate,ai_state_t * pself)6183 Uint8 scr_StateIs10( script_state_t * pstate, ai_state_t * pself )
6184 {
6185     SCRIPT_FUNCTION_BEGIN();
6186 
6187     returncode = ( 10 == pself->state );
6188 
6189     SCRIPT_FUNCTION_END();
6190 }
6191 
6192 //--------------------------------------------------------------------------------------------
scr_StateIs11(script_state_t * pstate,ai_state_t * pself)6193 Uint8 scr_StateIs11( script_state_t * pstate, ai_state_t * pself )
6194 {
6195     SCRIPT_FUNCTION_BEGIN();
6196 
6197     returncode = ( 11 == pself->state );
6198 
6199     SCRIPT_FUNCTION_END();
6200 }
6201 
6202 //--------------------------------------------------------------------------------------------
scr_StateIs12(script_state_t * pstate,ai_state_t * pself)6203 Uint8 scr_StateIs12( script_state_t * pstate, ai_state_t * pself )
6204 {
6205     SCRIPT_FUNCTION_BEGIN();
6206 
6207     returncode = ( 12 == pself->state );
6208 
6209     SCRIPT_FUNCTION_END();
6210 }
6211 
6212 //--------------------------------------------------------------------------------------------
scr_StateIs13(script_state_t * pstate,ai_state_t * pself)6213 Uint8 scr_StateIs13( script_state_t * pstate, ai_state_t * pself )
6214 {
6215     SCRIPT_FUNCTION_BEGIN();
6216 
6217     returncode = ( 13 == pself->state );
6218 
6219     SCRIPT_FUNCTION_END();
6220 }
6221 
6222 //--------------------------------------------------------------------------------------------
scr_StateIs14(script_state_t * pstate,ai_state_t * pself)6223 Uint8 scr_StateIs14( script_state_t * pstate, ai_state_t * pself )
6224 {
6225     SCRIPT_FUNCTION_BEGIN();
6226 
6227     returncode = ( 14 == pself->state );
6228 
6229     SCRIPT_FUNCTION_END();
6230 }
6231 
6232 //--------------------------------------------------------------------------------------------
scr_StateIs15(script_state_t * pstate,ai_state_t * pself)6233 Uint8 scr_StateIs15( script_state_t * pstate, ai_state_t * pself )
6234 {
6235     SCRIPT_FUNCTION_BEGIN();
6236 
6237     returncode = ( 15 == pself->state );
6238 
6239     SCRIPT_FUNCTION_END();
6240 }
6241 
6242 //--------------------------------------------------------------------------------------------
scr_TargetIsAMount(script_state_t * pstate,ai_state_t * pself)6243 Uint8 scr_TargetIsAMount( script_state_t * pstate, ai_state_t * pself )
6244 {
6245     // IfTargetIsAMount()
6246     /// @details ZZ@> This function passes if the Target is a mountable character
6247 
6248     chr_t * pself_target;
6249 
6250     SCRIPT_FUNCTION_BEGIN();
6251 
6252     SCRIPT_REQUIRE_TARGET( pself_target );
6253 
6254     returncode = pself_target->ismount;
6255 
6256     SCRIPT_FUNCTION_END();
6257 }
6258 
6259 //--------------------------------------------------------------------------------------------
scr_TargetIsAPlatform(script_state_t * pstate,ai_state_t * pself)6260 Uint8 scr_TargetIsAPlatform( script_state_t * pstate, ai_state_t * pself )
6261 {
6262     // IfTargetIsAPlatform()
6263     /// @details ZZ@> This function passes if the Target is a platform character
6264 
6265     chr_t * pself_target;
6266 
6267     SCRIPT_FUNCTION_BEGIN();
6268 
6269     SCRIPT_REQUIRE_TARGET( pself_target );
6270 
6271     returncode = pself_target->platform;
6272 
6273     SCRIPT_FUNCTION_END();
6274 }
6275 
6276 //--------------------------------------------------------------------------------------------
scr_AddStat(script_state_t * pstate,ai_state_t * pself)6277 Uint8 scr_AddStat( script_state_t * pstate, ai_state_t * pself )
6278 {
6279     // AddStat()
6280     /// @details ZZ@> This function turns on an NPC's status display
6281 
6282     SCRIPT_FUNCTION_BEGIN();
6283 
6284     if ( !pchr->StatusList_on )
6285     {
6286         statlist_add( pself->index );
6287     }
6288 
6289     SCRIPT_FUNCTION_END();
6290 }
6291 
6292 //--------------------------------------------------------------------------------------------
scr_DisenchantTarget(script_state_t * pstate,ai_state_t * pself)6293 Uint8 scr_DisenchantTarget( script_state_t * pstate, ai_state_t * pself )
6294 {
6295     // DisenchantTarget()
6296     /// @details ZZ@> This function removes all enchantments on the Target character, proceeding
6297     /// if there were any, failing if not
6298 
6299     chr_t * pself_target;
6300 
6301     SCRIPT_FUNCTION_BEGIN();
6302 
6303     SCRIPT_REQUIRE_TARGET( pself_target );
6304 
6305     returncode = ( MAX_ENC != pself_target->firstenchant );
6306 
6307     disenchant_character( pself->target );
6308 
6309     SCRIPT_FUNCTION_END();
6310 }
6311 
6312 //--------------------------------------------------------------------------------------------
scr_DisenchantAll(script_state_t * pstate,ai_state_t * pself)6313 Uint8 scr_DisenchantAll( script_state_t * pstate, ai_state_t * pself )
6314 {
6315     // DisenchantAll()
6316     /// @details ZZ@> This function removes all enchantments in the game
6317 
6318     ENC_REF iTmp;
6319 
6320     SCRIPT_FUNCTION_BEGIN();
6321 
6322     for ( iTmp = 0; iTmp < MAX_ENC; iTmp++ )
6323     {
6324         remove_enchant( iTmp, NULL );
6325     }
6326 
6327     SCRIPT_FUNCTION_END();
6328 }
6329 
6330 //--------------------------------------------------------------------------------------------
scr_set_VolumeNearestTeammate(script_state_t * pstate,ai_state_t * pself)6331 Uint8 scr_set_VolumeNearestTeammate( script_state_t * pstate, ai_state_t * pself )
6332 {
6333     // SetVolumeNearestTeammate( tmpargument = "sound", tmpdistance = "distance" )
6334     /// @details ZZ@> This function lets insects buzz correctly.  The closest Team member
6335     /// is used to determine the overall sound level.
6336 
6337     SCRIPT_FUNCTION_BEGIN();
6338 
6339     /*PORT
6340     if(moduleactive && pstate->distance >= 0)
6341     {
6342     // Find the closest Teammate
6343     iTmp = 10000;
6344     sTmp = 0;
6345     while(sTmp < MAX_CHR)
6346     {
6347     if(INGAME_CHR(sTmp) && ChrList.lst[sTmp].alive && ChrList.lst[sTmp].Team == pchr->Team)
6348     {
6349     distance = ABS(PCamera->trackx-ChrList.lst[sTmp].pos_old.x)+ABS(PCamera->tracky-ChrList.lst[sTmp].pos_old.y);
6350     if(distance < iTmp)  iTmp = distance;
6351     }
6352     sTmp++;
6353     }
6354     distance=iTmp+pstate->distance;
6355     volume = -distance;
6356     volume = volume<<VOLSHIFT;
6357     if(volume < VOLMIN) volume = VOLMIN;
6358     iTmp = CapStack.lst[pro_get_icap(pchr->profile_ref)].wavelist[pstate->argument];
6359     if(iTmp < numsound && iTmp >= 0 && soundon)
6360     {
6361     lpDSBuffer[iTmp]->SetVolume(volume);
6362     }
6363     }
6364     */
6365 
6366     SCRIPT_FUNCTION_END();
6367 }
6368 
6369 //--------------------------------------------------------------------------------------------
scr_AddShopPassage(script_state_t * pstate,ai_state_t * pself)6370 Uint8 scr_AddShopPassage( script_state_t * pstate, ai_state_t * pself )
6371 {
6372     // AddShopPassage( tmpargument = "passage" )
6373     /// @details ZZ@> This function makes a passage behave as a shop area, as long as the
6374     /// character is alive.
6375 
6376     SCRIPT_FUNCTION_BEGIN();
6377 
6378     add_shop_passage( pself->index, ( PASS_REF )pstate->argument );
6379 
6380     SCRIPT_FUNCTION_END();
6381 }
6382 
6383 //--------------------------------------------------------------------------------------------
scr_TargetPayForArmor(script_state_t * pstate,ai_state_t * pself)6384 Uint8 scr_TargetPayForArmor( script_state_t * pstate, ai_state_t * pself )
6385 {
6386     // tmpx, tmpy = TargetPayForArmor( tmpargument = "skin" )
6387 
6388     /// @details ZZ@> This function costs the Target the appropriate amount of money for the
6389     /// given armor type.  Passes if the character has enough, and fails if not.
6390     /// Does trade-in bonus automatically.  tmpy is always set to cost of requested
6391     /// skin tmpx is set to amount needed after trade-in ( 0 for pass ).
6392 
6393     int iTmp;
6394     cap_t * pcap;
6395     chr_t * pself_target;
6396 
6397     SCRIPT_FUNCTION_BEGIN();
6398 
6399     SCRIPT_REQUIRE_TARGET( pself_target );
6400 
6401     if ( !INGAME_CHR( pself->target ) ) return bfalse;
6402 
6403     pself_target = ChrList.lst + pself->target;
6404 
6405     pcap = chr_get_pcap( pself->target );         // The Target's model
6406     if ( NULL == pcap )  return bfalse;
6407 
6408     iTmp = pcap->skincost[pstate->argument&3];
6409     pstate->y = iTmp;                             // Cost of new skin
6410 
6411     iTmp -= pcap->skincost[pself_target->skin];        // Refund
6412 
6413     if ( iTmp > pself_target->money )
6414     {
6415         // Not enough.
6416         pstate->x = iTmp - pself_target->money;        // Amount needed
6417         returncode = bfalse;
6418     }
6419     else
6420     {
6421         // Pay for it.  Cost may be negative after refund.
6422         pself_target->money -= iTmp;
6423         if ( pself_target->money > MAXMONEY )  pself_target->money = MAXMONEY;
6424 
6425         pstate->x = 0;
6426         returncode = btrue;
6427     }
6428 
6429     SCRIPT_FUNCTION_END();
6430 }
6431 
6432 //--------------------------------------------------------------------------------------------
scr_JoinEvilTeam(script_state_t * pstate,ai_state_t * pself)6433 Uint8 scr_JoinEvilTeam( script_state_t * pstate, ai_state_t * pself )
6434 {
6435     // JoinEvilTeam()
6436     /// @details ZZ@> This function adds the character to the evil Team.
6437 
6438     SCRIPT_FUNCTION_BEGIN();
6439 
6440     switch_team( pself->index, ( TEAM_REF )TEAM_EVIL );
6441 
6442     SCRIPT_FUNCTION_END();
6443 }
6444 
6445 //--------------------------------------------------------------------------------------------
scr_JoinNullTeam(script_state_t * pstate,ai_state_t * pself)6446 Uint8 scr_JoinNullTeam( script_state_t * pstate, ai_state_t * pself )
6447 {
6448     // JoinNullTeam()
6449     /// @details ZZ@> This function adds the character to the null Team.
6450 
6451     SCRIPT_FUNCTION_BEGIN();
6452 
6453     switch_team( pself->index, ( TEAM_REF )TEAM_NULL );
6454 
6455     SCRIPT_FUNCTION_END();
6456 }
6457 
6458 //--------------------------------------------------------------------------------------------
scr_JoinGoodTeam(script_state_t * pstate,ai_state_t * pself)6459 Uint8 scr_JoinGoodTeam( script_state_t * pstate, ai_state_t * pself )
6460 {
6461     // JoinGoodTeam()
6462     /// @details ZZ@> This function adds the character to the good Team.
6463 
6464     SCRIPT_FUNCTION_BEGIN();
6465 
6466     switch_team( pself->index, ( TEAM_REF )TEAM_GOOD );
6467 
6468     SCRIPT_FUNCTION_END();
6469 }
6470 
6471 //--------------------------------------------------------------------------------------------
scr_PitsKill(script_state_t * pstate,ai_state_t * pself)6472 Uint8 scr_PitsKill( script_state_t * pstate, ai_state_t * pself )
6473 {
6474     // PitsKill()
6475     /// @details ZZ@> This function activates pit deaths for when characters fall below a
6476     /// certain altitude.
6477 
6478     SCRIPT_FUNCTION_BEGIN();
6479 
6480     pits.kill = btrue;
6481 
6482     SCRIPT_FUNCTION_END();
6483 }
6484 
6485 //--------------------------------------------------------------------------------------------
scr_set_TargetToPassageID(script_state_t * pstate,ai_state_t * pself)6486 Uint8 scr_set_TargetToPassageID( script_state_t * pstate, ai_state_t * pself )
6487 {
6488     // SetTargetToPassageID( tmpargument = "passage", tmpdistance = "idsz" )
6489     /// @details ZZ@> This function finds a character who is both in the passage and who has
6490     /// an item with the given IDSZ
6491 
6492     CHR_REF ichr;
6493 
6494     SCRIPT_FUNCTION_BEGIN();
6495 
6496     ichr = who_is_blocking_passage(( PASS_REF )pstate->argument, pself->index, IDSZ_NONE, TARGET_SELF | TARGET_FRIENDS | TARGET_ENEMIES, pstate->distance );
6497 
6498     if ( INGAME_CHR( ichr ) )
6499     {
6500         SET_TARGET_0( ichr );
6501     }
6502     else
6503     {
6504         returncode = bfalse;
6505     }
6506 
6507     SCRIPT_FUNCTION_END();
6508 }
6509 
6510 //--------------------------------------------------------------------------------------------
scr_MakeNameUnknown(script_state_t * pstate,ai_state_t * pself)6511 Uint8 scr_MakeNameUnknown( script_state_t * pstate, ai_state_t * pself )
6512 {
6513     // MakeNameUnknown()
6514     /// @details ZZ@> This function makes the name of an item/character unknown.
6515     /// Usage: Use if you have subspawning of creatures from a book.
6516 
6517     SCRIPT_FUNCTION_BEGIN();
6518 
6519     pchr->nameknown = bfalse;
6520 
6521     SCRIPT_FUNCTION_END();
6522 }
6523 
6524 //--------------------------------------------------------------------------------------------
scr_SpawnExactParticleEndSpawn(script_state_t * pstate,ai_state_t * pself)6525 Uint8 scr_SpawnExactParticleEndSpawn( script_state_t * pstate, ai_state_t * pself )
6526 {
6527     // SpawnExactParticleEndSpawn( tmpargument = "particle", tmpturn = "state", tmpx = "x", tmpy = "y", tmpdistance = "z" )
6528 
6529     /// @details ZZ@> This function spawns a particle at a specific x, y, z position.
6530     /// When the particle ends, a character is spawned at its final location.
6531     /// The character is the same type of whatever spawned the particle.
6532 
6533     PRT_REF iprt;
6534     CHR_REF ichr;
6535 
6536     SCRIPT_FUNCTION_BEGIN();
6537 
6538     ichr = pself->index;
6539     if ( INGAME_CHR( pchr->attachedto ) )
6540     {
6541         ichr = pchr->attachedto;
6542     }
6543 
6544     {
6545         fvec3_t vtmp = VECT3( pstate->x, pstate->y, pstate->distance );
6546         iprt = spawn_one_particle( vtmp, pchr->ori.facing_z, pchr->profile_ref, pstate->argument, ( CHR_REF )MAX_CHR, 0, pchr->team, ichr, ( PRT_REF )MAX_PRT, 0, ( CHR_REF )MAX_CHR );
6547     }
6548 
6549     returncode = DEFINED_PRT( iprt );
6550 
6551     if ( returncode )
6552     {
6553         PrtList.lst[iprt].spawncharacterstate = pstate->turn;
6554     }
6555 
6556     SCRIPT_FUNCTION_END();
6557 }
6558 
6559 //--------------------------------------------------------------------------------------------
scr_SpawnPoofSpeedSpacingDamage(script_state_t * pstate,ai_state_t * pself)6560 Uint8 scr_SpawnPoofSpeedSpacingDamage( script_state_t * pstate, ai_state_t * pself )
6561 {
6562     // SpawnPoofSpeedSpacingDamage( tmpx = "xy speed", tmpy = "xy spacing", tmpargument = "damage" )
6563 
6564     /// @details ZZ@> This function makes a lovely little poof at the character's location,
6565     /// adjusting the xy speed and spacing and the base damage first
6566     /// Temporarily adjust the values for the particle type
6567 
6568     int   tTmp, iTmp;
6569     float fTmp;
6570 
6571     cap_t * pcap;
6572     pip_t * ppip;
6573 
6574     SCRIPT_FUNCTION_BEGIN();
6575 
6576     pcap = pro_get_pcap( pchr->profile_ref );
6577     if ( NULL == pcap ) return bfalse;
6578 
6579     ppip = pro_get_ppip( pchr->profile_ref, pcap->gopoofprt_lpip );
6580     if ( NULL == ppip ) return bfalse;
6581 
6582     returncode = bfalse;
6583     if ( NULL != ppip )
6584     {
6585         /// @note BB@> if we do not change both the ppip->damage.from AND the ppip->damage.to
6586         /// an error will be generated down the line...
6587 
6588         float damage_rand = ppip->damage.to - ppip->damage.from;
6589 
6590         // save some values
6591         iTmp = ppip->vel_hrz_pair.base;
6592         tTmp = ppip->spacing_hrz_pair.base;
6593         fTmp = ppip->damage.from;
6594 
6595         // set some values
6596         ppip->vel_hrz_pair.base     = pstate->x;
6597         ppip->spacing_hrz_pair.base = pstate->y;
6598         ppip->damage.from           = FP8_TO_FLOAT( pstate->argument );
6599         ppip->damage.to             = ppip->damage.from + damage_rand;
6600 
6601         spawn_poof( pself->index, pchr->profile_ref );
6602 
6603         // Restore the saved values
6604         ppip->vel_hrz_pair.base     = iTmp;
6605         ppip->spacing_hrz_pair.base = tTmp;
6606         ppip->damage.from           = fTmp;
6607         ppip->damage.to             = ppip->damage.from + damage_rand;
6608 
6609         returncode = btrue;
6610     }
6611 
6612     SCRIPT_FUNCTION_END();
6613 }
6614 
6615 //--------------------------------------------------------------------------------------------
scr_GiveExperienceToGoodTeam(script_state_t * pstate,ai_state_t * pself)6616 Uint8 scr_GiveExperienceToGoodTeam( script_state_t * pstate, ai_state_t * pself )
6617 {
6618     // GiveExperienceToGoodTeam(  tmpargument = "amount", tmpdistance = "type" )
6619     /// @details ZZ@> This function gives experience to everyone on the G Team
6620 
6621     SCRIPT_FUNCTION_BEGIN();
6622 
6623     give_team_experience(( TEAM_REF )TEAM_GOOD, pstate->argument, pstate->distance );
6624 
6625     SCRIPT_FUNCTION_END();
6626 }
6627 
6628 //--------------------------------------------------------------------------------------------
scr_DoNothing(script_state_t * pstate,ai_state_t * pself)6629 Uint8 scr_DoNothing( script_state_t * pstate, ai_state_t * pself )
6630 {
6631     // DoNothing()
6632     /// @details ZF@> This function does nothing
6633     /// Use this for debugging or in combination with a Else function
6634 
6635     return btrue;
6636 }
6637 
6638 //--------------------------------------------------------------------------------------------
scr_GrogTarget(script_state_t * pstate,ai_state_t * pself)6639 Uint8 scr_GrogTarget( script_state_t * pstate, ai_state_t * pself )
6640 {
6641     // GrogTarget( tmpargument = "amount" )
6642     /// @details ZF@> This function grogs the Target for a duration equal to tmpargument
6643 
6644     cap_t * pcap;
6645     chr_t * pself_target;
6646 
6647     SCRIPT_FUNCTION_BEGIN();
6648 
6649     SCRIPT_REQUIRE_TARGET( pself_target );
6650 
6651     pcap = chr_get_pcap( pself->target );
6652 
6653     returncode = bfalse;
6654     if ( NULL != pcap && pcap->canbegrogged )
6655     {
6656         pself_target->grog_timer += pstate->argument;
6657         returncode = btrue;
6658     }
6659 
6660     SCRIPT_FUNCTION_END();
6661 }
6662 
6663 //--------------------------------------------------------------------------------------------
scr_DazeTarget(script_state_t * pstate,ai_state_t * pself)6664 Uint8 scr_DazeTarget( script_state_t * pstate, ai_state_t * pself )
6665 {
6666     // DazeTarget( tmpargument = "amount" )
6667     /// @details ZF@> This function dazes the Target for a duration equal to tmpargument
6668 
6669     cap_t * pcap;
6670     chr_t * pself_target;
6671 
6672     SCRIPT_FUNCTION_BEGIN();
6673 
6674     SCRIPT_REQUIRE_TARGET( pself_target );
6675 
6676     pcap = chr_get_pcap( pself->target );
6677 
6678     // Characters who manage to daze themselves are ignore their daze immunity
6679     returncode = bfalse;
6680     if ( NULL != pcap && ( pcap->canbedazed || pself->index == pself->target ) )
6681     {
6682         pself_target->daze_timer += pstate->argument;
6683         returncode = btrue;
6684     }
6685 
6686     SCRIPT_FUNCTION_END();
6687 }
6688 
6689 //--------------------------------------------------------------------------------------------
scr_EnableRespawn(script_state_t * pstate,ai_state_t * pself)6690 Uint8 scr_EnableRespawn( script_state_t * pstate, ai_state_t * pself )
6691 {
6692     // EnableRespawn()
6693     /// @details ZF@> This function turns respawn with JUMP button on
6694 
6695     SCRIPT_FUNCTION_BEGIN();
6696 
6697     PMod->respawnvalid = btrue;
6698 
6699     SCRIPT_FUNCTION_END();
6700 }
6701 
6702 //--------------------------------------------------------------------------------------------
scr_DisableRespawn(script_state_t * pstate,ai_state_t * pself)6703 Uint8 scr_DisableRespawn( script_state_t * pstate, ai_state_t * pself )
6704 {
6705     // DisableRespawn()
6706     /// @details ZF@> This function turns respawn with JUMP button off
6707 
6708     SCRIPT_FUNCTION_BEGIN();
6709 
6710     PMod->respawnvalid = bfalse;
6711 
6712     SCRIPT_FUNCTION_END();
6713 }
6714 
6715 //--------------------------------------------------------------------------------------------
scr_HolderBlocked(script_state_t * pstate,ai_state_t * pself)6716 Uint8 scr_HolderBlocked( script_state_t * pstate, ai_state_t * pself )
6717 {
6718     // IfHolderBlocked()
6719     /// @details ZF@> This function passes if the holder blocked an attack
6720 
6721     CHR_REF iattached;
6722 
6723     SCRIPT_FUNCTION_BEGIN();
6724 
6725     iattached = pchr->attachedto;
6726 
6727     if ( INGAME_CHR( iattached ) )
6728     {
6729         BIT_FIELD bits = ChrList.lst[iattached].ai.alert;
6730 
6731         if ( HAS_SOME_BITS( bits, ALERTIF_BLOCKED ) )
6732         {
6733             CHR_REF iattacked = ChrList.lst[iattached].ai.attacklast;
6734 
6735             if ( INGAME_CHR( iattacked ) )
6736             {
6737                 SET_TARGET_0( iattacked );
6738             }
6739             else
6740             {
6741                 returncode = bfalse;
6742             }
6743         }
6744         else
6745         {
6746             returncode = bfalse;
6747         }
6748     }
6749     else
6750     {
6751         returncode = bfalse;
6752     }
6753 
6754     SCRIPT_FUNCTION_END();
6755 }
6756 
6757 //--------------------------------------------------------------------------------------------
scr_TargetHasNotFullMana(script_state_t * pstate,ai_state_t * pself)6758 Uint8 scr_TargetHasNotFullMana( script_state_t * pstate, ai_state_t * pself )
6759 {
6760     // IfTargetHasNotFullMana()
6761     /// @details ZF@> This function passes only if the Target is not at max mana and alive
6762 
6763     chr_t * pself_target;
6764 
6765     SCRIPT_FUNCTION_BEGIN();
6766 
6767     SCRIPT_REQUIRE_TARGET( pself_target );
6768 
6769     if ( !pself_target->alive || pself_target->mana > pself_target->manamax - HURTDAMAGE )
6770     {
6771         returncode = bfalse;
6772     }
6773 
6774     SCRIPT_FUNCTION_END();
6775 }
6776 
6777 //--------------------------------------------------------------------------------------------
scr_EnableListenSkill(script_state_t * pstate,ai_state_t * pself)6778 Uint8 scr_EnableListenSkill( script_state_t * pstate, ai_state_t * pself )
6779 {
6780     // EnableListenSkill()
6781     /// @details ZF@> This function increases range from which sound can be heard by 33%
6782 
6783     SCRIPT_FUNCTION_BEGIN();
6784 
6785     log_warning( "Depacrated script function used: EnableListenSkill! (%s)\n", chr_get_pmad(pself->index)->name );
6786     returncode = bfalse;
6787 
6788     SCRIPT_FUNCTION_END();
6789 }
6790 
6791 //--------------------------------------------------------------------------------------------
scr_set_TargetToLastItemUsed(script_state_t * pstate,ai_state_t * pself)6792 Uint8 scr_set_TargetToLastItemUsed( script_state_t * pstate, ai_state_t * pself )
6793 {
6794     // SetTargetToLastItemUsed()
6795     /// @details ZF@> This sets the Target to the last item the character used
6796 
6797     SCRIPT_FUNCTION_BEGIN();
6798 
6799     if ( pself->lastitemused != pself->index && INGAME_CHR( pself->lastitemused ) )
6800     {
6801         SET_TARGET_0( pself->lastitemused );
6802     }
6803     else
6804     {
6805         returncode = bfalse;
6806     }
6807 
6808     SCRIPT_FUNCTION_END();
6809 }
6810 
6811 //--------------------------------------------------------------------------------------------
scr_FollowLink(script_state_t * pstate,ai_state_t * pself)6812 Uint8 scr_FollowLink( script_state_t * pstate, ai_state_t * pself )
6813 {
6814     // FollowLink( tmpargument = "index of next module name" )
6815     /// @details BB@> Skips to the next module!
6816 
6817     int message_number, message_index;
6818     char * ptext;
6819 
6820     SCRIPT_FUNCTION_BEGIN();
6821 
6822     message_number = ppro->message_start + pstate->argument;
6823     message_index  = MessageOffset.ary[message_number];
6824 
6825     ptext = message_buffer + message_index;
6826 
6827     returncode = link_follow_modname( ptext, btrue );
6828     if ( !returncode )
6829     {
6830         debug_printf( "That's too scary for %s", pchr->Name );
6831     }
6832 
6833     SCRIPT_FUNCTION_END();
6834 }
6835 
6836 //--------------------------------------------------------------------------------------------
scr_OperatorIsLinux(script_state_t * pstate,ai_state_t * pself)6837 Uint8 scr_OperatorIsLinux( script_state_t * pstate, ai_state_t * pself )
6838 {
6839     // IfOperatorIsLinux()
6840     /// @details ZF@> Proceeds if running on linux
6841 
6842     SCRIPT_FUNCTION_BEGIN();
6843 
6844 #if defined(__unix__)
6845     returncode = btrue;
6846 #else
6847     returncode = bfalse;
6848 #endif
6849 
6850     SCRIPT_FUNCTION_END();
6851 }
6852 
6853 //--------------------------------------------------------------------------------------------
scr_TargetIsAWeapon(script_state_t * pstate,ai_state_t * pself)6854 Uint8 scr_TargetIsAWeapon( script_state_t * pstate, ai_state_t * pself )
6855 {
6856     // IfTargetIsAWeapon()
6857     /// @details ZF@> Proceeds if the AI Target Is a melee or ranged weapon
6858 
6859     cap_t * pcap;
6860 
6861     SCRIPT_FUNCTION_BEGIN();
6862 
6863     if ( !INGAME_CHR( pself->target ) ) return bfalse;
6864 
6865     pcap = chr_get_pcap( pself->target );
6866     if ( NULL == pcap ) return bfalse;
6867 
6868     returncode = pcap->isranged || chr_has_idsz( pself->target, MAKE_IDSZ( 'X', 'W', 'E', 'P' ) );
6869 
6870     SCRIPT_FUNCTION_END();
6871 }
6872 
6873 //--------------------------------------------------------------------------------------------
scr_SomeoneIsStealing(script_state_t * pstate,ai_state_t * pself)6874 Uint8 scr_SomeoneIsStealing( script_state_t * pstate, ai_state_t * pself )
6875 {
6876     // IfSomeoneIsStealing()
6877     /// @details ZF@> This function passes if someone stealed from it's shop
6878 
6879     SCRIPT_FUNCTION_BEGIN();
6880 
6881     returncode = ( pself->order_value == SHOP_STOLEN && pself->order_counter == SHOP_THEFT );
6882 
6883     SCRIPT_FUNCTION_END();
6884 }
6885 
6886 //--------------------------------------------------------------------------------------------
scr_TargetIsASpell(script_state_t * pstate,ai_state_t * pself)6887 Uint8 scr_TargetIsASpell( script_state_t * pstate, ai_state_t * pself )
6888 {
6889     // IfTargetIsASpell()
6890     /// @details ZF@> roceeds if the AI Target has any particle with the [IDAM] or [WDAM] expansion
6891 
6892     int iTmp;
6893 
6894     SCRIPT_FUNCTION_BEGIN();
6895 
6896     returncode = bfalse;
6897     for ( iTmp = 0; iTmp < MAX_PIP_PER_PROFILE; iTmp++ )
6898     {
6899         pip_t * ppip = pro_get_ppip( pchr->profile_ref, iTmp );
6900         if ( NULL == ppip ) continue;
6901 
6902         if ( ppip->intdamagebonus || ppip->wisdamagebonus )
6903         {
6904             returncode = btrue;
6905             break;
6906         }
6907     }
6908 
6909     SCRIPT_FUNCTION_END();
6910 }
6911 
6912 //--------------------------------------------------------------------------------------------
scr_Backstabbed(script_state_t * pstate,ai_state_t * pself)6913 Uint8 scr_Backstabbed( script_state_t * pstate, ai_state_t * pself )
6914 {
6915     // IfBackstabbed()
6916     /// @details ZF@> Proceeds if HitFromBehind, target has [STAB] skill and damage dealt is physical
6917     /// automatically fails if attacker has a code of conduct
6918 
6919     SCRIPT_FUNCTION_BEGIN();
6920 
6921     //Now check if it really was backstabbed
6922     returncode = bfalse;
6923     if ( HAS_SOME_BITS( pself->alert, ALERTIF_ATTACKED ) )
6924     {
6925         //Who is the dirty backstabber?
6926         chr_t * pattacker = ChrList.lst + pself->attacklast;
6927         if ( !ACTIVE_PCHR( pattacker ) ) return bfalse;
6928 
6929         //Only if hit from behind
6930         if ( pself->directionlast >= ATK_BEHIND - 8192 && pself->directionlast < ATK_BEHIND + 8192 )
6931         {
6932             //And require the backstab skill
6933             if ( chr_get_skill( pattacker, MAKE_IDSZ( 'S', 'T', 'A', 'B' ) ) )
6934             {
6935                 //Finally we require it to be physical damage!
6936                 Uint16 sTmp = sTmp = pself->damagetypelast;
6937                 if ( sTmp == DAMAGE_CRUSH || sTmp == DAMAGE_POKE || sTmp == DAMAGE_SLASH ) returncode = btrue;
6938             }
6939         }
6940     }
6941 
6942     SCRIPT_FUNCTION_END();
6943 }
6944 
6945 //--------------------------------------------------------------------------------------------
scr_get_TargetDamageType(script_state_t * pstate,ai_state_t * pself)6946 Uint8 scr_get_TargetDamageType( script_state_t * pstate, ai_state_t * pself )
6947 {
6948     // tmpargument = GetTargetDamageType()
6949     /// @details ZF@> This function gets the last type of damage for the Target
6950 
6951     chr_t * pself_target;
6952 
6953     SCRIPT_FUNCTION_BEGIN();
6954 
6955     SCRIPT_REQUIRE_TARGET( pself_target );
6956 
6957     pstate->argument = pself_target->ai.damagetypelast;
6958 
6959     SCRIPT_FUNCTION_END();
6960 }
6961 
6962 //--------------------------------------------------------------------------------------------
scr_AddQuest(script_state_t * pstate,ai_state_t * pself)6963 Uint8 scr_AddQuest( script_state_t * pstate, ai_state_t * pself )
6964 {
6965     // AddQuest( tmpargument = "quest idsz" )
6966     /// @details ZF@> This function adds a quest idsz set in tmpargument into the targets quest.txt to 0
6967 
6968     egoboo_rv result = rv_fail;
6969     chr_t * pself_target;
6970     PLA_REF ipla;
6971 
6972     SCRIPT_FUNCTION_BEGIN();
6973 
6974     SCRIPT_REQUIRE_TARGET( pself_target );
6975 
6976     ipla = pself_target->is_which_player;
6977     if ( VALID_PLA( ipla ) )
6978     {
6979         player_t * ppla = PlaStack.lst + ipla;
6980 
6981         result = quest_add( ppla->quest_log, SDL_arraysize( ppla->quest_log ), pstate->argument, pstate->distance );
6982     }
6983 
6984     returncode = ( rv_success == result );
6985 
6986     SCRIPT_FUNCTION_END();
6987 }
6988 
6989 //--------------------------------------------------------------------------------------------
scr_BeatQuestAllPlayers(script_state_t * pstate,ai_state_t * pself)6990 Uint8 scr_BeatQuestAllPlayers( script_state_t * pstate, ai_state_t * pself )
6991 {
6992     // BeatQuestAllPlayers()
6993     /// @details ZF@> This function marks a IDSZ in the targets quest.txt as beaten
6994     ///               returns true if at least one quest got marked as beaten.
6995 
6996     PLA_REF ipla;
6997 
6998     SCRIPT_FUNCTION_BEGIN();
6999 
7000     returncode = bfalse;
7001     for ( ipla = 0; ipla < MAX_PLAYER; ipla++ )
7002     {
7003         CHR_REF ichr;
7004         player_t * ppla = PlaStack.lst + ipla;
7005 
7006         if ( !ppla->valid ) continue;
7007 
7008         ichr = ppla->index;
7009         if ( !INGAME_CHR( ichr ) ) continue;
7010 
7011         if ( QUEST_BEATEN == quest_adjust_level( ppla->quest_log, SDL_arraysize( ppla->quest_log ), ( IDSZ )pstate->argument, QUEST_MAXVAL ) )
7012         {
7013             returncode = btrue;
7014         }
7015     }
7016 
7017     SCRIPT_FUNCTION_END();
7018 }
7019 
7020 //--------------------------------------------------------------------------------------------
scr_TargetHasQuest(script_state_t * pstate,ai_state_t * pself)7021 Uint8 scr_TargetHasQuest( script_state_t * pstate, ai_state_t * pself )
7022 {
7023     // tmpdistance = IfTargetHasQuest( tmpargument = "quest idsz )
7024     /// @details ZF@> This function proceeds if the Target has the unfinIshed quest specified in tmpargument
7025     /// and sets tmpdistance to the Quest Level of the specified quest.
7026 
7027     int     quest_level = QUEST_NONE;
7028     chr_t * pself_target = NULL;
7029     PLA_REF ipla;
7030 
7031     SCRIPT_FUNCTION_BEGIN();
7032 
7033     SCRIPT_REQUIRE_TARGET( pself_target );
7034 
7035     returncode = bfalse;
7036 
7037     ipla = pself_target->is_which_player;
7038     if ( VALID_PLA( ipla ) )
7039     {
7040         player_t * ppla = PlaStack.lst + ipla;
7041 
7042         quest_level = quest_get_level( ppla->quest_log, SDL_arraysize( ppla->quest_log ), pstate->argument );
7043     }
7044 
7045     // only find active quests
7046     if ( quest_level >= 0 )
7047     {
7048         pstate->distance = quest_level;
7049         returncode       = btrue;
7050     }
7051 
7052     SCRIPT_FUNCTION_END();
7053 }
7054 
7055 //--------------------------------------------------------------------------------------------
scr_set_QuestLevel(script_state_t * pstate,ai_state_t * pself)7056 Uint8 scr_set_QuestLevel( script_state_t * pstate, ai_state_t * pself )
7057 {
7058     // SetQuestLevel( tmpargument = "idsz", distance = "adjustment" )
7059     /// @details ZF@> This function modifies the quest level for a specific quest IDSZ
7060     /// tmpargument specifies quest idsz (tmpargument) and the adjustment (tmpdistance, which may be negative)
7061 
7062     chr_t * pself_target;
7063     PLA_REF ipla;
7064 
7065     SCRIPT_FUNCTION_BEGIN();
7066 
7067     SCRIPT_REQUIRE_TARGET( pself_target );
7068 
7069     returncode = bfalse;
7070     ipla = pself_target->is_which_player;
7071     if ( VALID_PLA( ipla ) && 0 != pstate->distance )
7072     {
7073         int        quest_level = QUEST_NONE;
7074         player_t * ppla        = PlaStack.lst + ipla;
7075 
7076         quest_level = quest_adjust_level( ppla->quest_log, SDL_arraysize( ppla->quest_log ), pstate->argument, pstate->distance );
7077 
7078         returncode = QUEST_NONE != quest_level;
7079     }
7080 
7081     SCRIPT_FUNCTION_END();
7082 }
7083 
7084 //--------------------------------------------------------------------------------------------
scr_AddQuestAllPlayers(script_state_t * pstate,ai_state_t * pself)7085 Uint8 scr_AddQuestAllPlayers( script_state_t * pstate, ai_state_t * pself )
7086 {
7087     // AddQuestAllPlayers( tmpargument = "quest idsz" )
7088     /// @details ZF@> This function adds a quest idsz set in tmpargument into all local player's quest logs
7089     /// The quest level Is set to tmpdistance if the level Is not already higher
7090 
7091     PLA_REF ipla;
7092     int success_count, player_count;
7093 
7094     SCRIPT_FUNCTION_BEGIN();
7095 
7096     returncode = bfalse;
7097     for ( player_count = 0, success_count = 0, ipla = 0; ipla < MAX_PLAYER; ipla++ )
7098     {
7099         int quest_level;
7100         player_t * ppla = PlaStack.lst + ipla;
7101 
7102         if ( !ppla->valid || !INGAME_CHR( ppla->index ) ) continue;
7103         player_count++;
7104 
7105         // Try to add it or replace it if this one is higher
7106         quest_level = quest_add( ppla->quest_log, SDL_arraysize( ppla->quest_log ), pstate->argument, pstate->distance );
7107         if ( QUEST_NONE != quest_level ) success_count++;
7108     }
7109 
7110     returncode = ( player_count > 0 ) && ( success_count >= player_count );
7111 
7112     SCRIPT_FUNCTION_END();
7113 }
7114 
7115 //--------------------------------------------------------------------------------------------
scr_AddBlipAllEnemies(script_state_t * pstate,ai_state_t * pself)7116 Uint8 scr_AddBlipAllEnemies( script_state_t * pstate, ai_state_t * pself )
7117 {
7118     // AddBlipAllEnemies()
7119     /// @details ZF@> show all enemies on the minimap who match the IDSZ given in tmpargument
7120     /// it show only the enemies of the AI Target
7121 
7122     SCRIPT_FUNCTION_BEGIN();
7123 
7124     if ( INGAME_CHR( pself->target ) )
7125     {
7126         local_stats.sense_enemies_team = chr_get_iteam( pself->target );
7127         local_stats.sense_enemies_idsz = pstate->argument;
7128     }
7129     else
7130     {
7131         local_stats.sense_enemies_team = ( TEAM_REF )TEAM_MAX;
7132         local_stats.sense_enemies_idsz = IDSZ_NONE;
7133     }
7134 
7135     SCRIPT_FUNCTION_END();
7136 }
7137 
7138 //--------------------------------------------------------------------------------------------
scr_PitsFall(script_state_t * pstate,ai_state_t * pself)7139 Uint8 scr_PitsFall( script_state_t * pstate, ai_state_t * pself )
7140 {
7141     // PitsFall( tmpx = "teleprt x", tmpy = "teleprt y", tmpdistance = "teleprt z" )
7142     /// @details ZF@> This function activates pit teleportation.
7143 
7144     SCRIPT_FUNCTION_BEGIN();
7145 
7146     if ( pstate->x > EDGE && pstate->y > EDGE && pstate->x < PMesh->gmem.edge_x - EDGE && pstate->y < PMesh->gmem.edge_y - EDGE )
7147     {
7148         pits.teleport = btrue;
7149         pits.teleport_pos.x = pstate->x;
7150         pits.teleport_pos.y = pstate->y;
7151         pits.teleport_pos.z = pstate->distance;
7152     }
7153     else
7154     {
7155         pits.kill = btrue;          //make it kill instead
7156     }
7157 
7158     SCRIPT_FUNCTION_END();
7159 }
7160 
7161 //--------------------------------------------------------------------------------------------
scr_TargetIsOwner(script_state_t * pstate,ai_state_t * pself)7162 Uint8 scr_TargetIsOwner( script_state_t * pstate, ai_state_t * pself )
7163 {
7164     // IfTargetIsOwner()
7165     /// @details ZF@> This function proceeds only if the Target is the character's owner
7166 
7167     chr_t * pself_target;
7168 
7169     SCRIPT_FUNCTION_BEGIN();
7170 
7171     SCRIPT_REQUIRE_TARGET( pself_target );
7172 
7173     returncode = ( pself_target->alive && pself->owner == pself->target );
7174 
7175     SCRIPT_FUNCTION_END();
7176 }
7177 
7178 //--------------------------------------------------------------------------------------------
scr_SpawnAttachedCharacter(script_state_t * pstate,ai_state_t * pself)7179 Uint8 scr_SpawnAttachedCharacter( script_state_t * pstate, ai_state_t * pself )
7180 {
7181     // SpawnAttachedCharacter( tmpargument = "profile", tmpx = "x", tmpy = "y", tmpdistance = "z" )
7182 
7183     /// @details ZF@> This function spawns a character defined in tmpargument to the characters AI target using
7184     /// the slot specified in tmpdistance (LEFT, RIGHT or INVENTORY). Fails if the inventory or
7185     /// grip specified is full or already in use.
7186     /// DON'T USE THIS FOR EXPORTABLE ITEMS OR CHARACTERS,
7187     /// AS THE MODEL SLOTS MAY VARY FROM MODULE TO MODULE.
7188 
7189     fvec3_t pos;
7190     CHR_REF ichr;
7191     chr_t * pself_target;
7192 
7193     SCRIPT_FUNCTION_BEGIN();
7194 
7195     SCRIPT_REQUIRE_TARGET( pself_target );
7196 
7197     pos.x = pstate->x;
7198     pos.y = pstate->y;
7199     pos.z = pstate->distance;
7200 
7201     ichr = spawn_one_character( pos, ( PRO_REF )pstate->argument, pchr->team, 0, FACE_NORTH, NULL, ( CHR_REF )MAX_CHR );
7202     returncode = DEFINED_CHR( ichr );
7203 
7204     if ( !returncode )
7205     {
7206         if ( ichr > PMod->importamount * MAXIMPORTPERPLAYER )
7207         {
7208             cap_t * pcap = pro_get_pcap( pchr->profile_ref );
7209 
7210             log_warning( "Object \"%s\"(\"%s\") failed to spawn profile index %d\n", pchr->obj_base._name, NULL == pcap ? "INVALID" : pcap->classname, pstate->argument );
7211         }
7212     }
7213     else
7214     {
7215         chr_t * pchild = ChrList.lst + ichr;
7216 
7217         Uint8 grip = CLIP( pstate->distance, ATTACH_INVENTORY, ATTACH_RIGHT );
7218 
7219         if ( grip == ATTACH_INVENTORY )
7220         {
7221             // Inventory character
7222             if ( inventory_add_item( ichr, pself->target ) )
7223             {
7224                 SET_BIT( pchild->ai.alert, ALERTIF_GRABBED );  // Make spellbooks change
7225                 pchild->attachedto = pself->target;  // Make grab work
7226                 scr_run_chr_script( ichr );  // Empty the grabbed messages
7227 
7228                 pchild->attachedto = ( CHR_REF )MAX_CHR;  // Fix grab
7229 
7230                 //Set some AI values
7231                 pself->child = ichr;
7232                 pchild->ai.passage = pself->passage;
7233                 pchild->ai.owner   = pself->owner;
7234             }
7235 
7236             //No more room!
7237             else
7238             {
7239                 chr_request_terminate( ichr );
7240                 ichr = ( CHR_REF )MAX_CHR;
7241             }
7242         }
7243         else if ( grip == ATTACH_LEFT || grip == ATTACH_RIGHT )
7244         {
7245             if ( !INGAME_CHR( pself_target->holdingwhich[grip] ) )
7246             {
7247                 // Wielded character
7248                 grip_offset_t grip_off = ( ATTACH_LEFT == grip ) ? GRIP_LEFT : GRIP_RIGHT;
7249 
7250                 if ( rv_success == attach_character_to_mount( ichr, pself->target, grip_off ) )
7251                 {
7252                     // Handle the "grabbed" messages
7253                     scr_run_chr_script( ichr );
7254                 }
7255 
7256                 //Set some AI values
7257                 pself->child = ichr;
7258                 pchild->ai.passage = pself->passage;
7259                 pchild->ai.owner   = pself->owner;
7260             }
7261 
7262             //Grip is already used
7263             else
7264             {
7265                 chr_request_terminate( ichr );
7266                 ichr = ( CHR_REF )MAX_CHR;
7267             }
7268         }
7269         else
7270         {
7271             // we have been given an invalid attachment point.
7272             // still allow the character to spawn if it is not in an invalid area
7273 
7274             // technically this should never occur since we are limiting the attachment points above
7275             if ( !chr_get_safe( pchild, NULL ) )
7276             {
7277                 chr_request_terminate( ichr );
7278                 ichr = ( CHR_REF )MAX_CHR;
7279             }
7280         }
7281     }
7282 
7283     SCRIPT_FUNCTION_END();
7284 }
7285 
7286 //--------------------------------------------------------------------------------------------
scr_set_TargetToChild(script_state_t * pstate,ai_state_t * pself)7287 Uint8 scr_set_TargetToChild( script_state_t * pstate, ai_state_t * pself )
7288 {
7289     // SetTargetToChild()
7290     /// @details ZF@> This function sets the target to the character it spawned last (also called it's "child")
7291 
7292     SCRIPT_FUNCTION_BEGIN();
7293 
7294     if ( INGAME_CHR( pself->child ) )
7295     {
7296         SET_TARGET_0( pself->child );
7297     }
7298     else
7299     {
7300         returncode = bfalse;
7301     }
7302 
7303     SCRIPT_FUNCTION_END();
7304 }
7305 
7306 //--------------------------------------------------------------------------------------------
scr_set_DamageThreshold(script_state_t * pstate,ai_state_t * pself)7307 Uint8 scr_set_DamageThreshold( script_state_t * pstate, ai_state_t * pself )
7308 {
7309     // SetDamageThreshold()
7310     /// @details ZF@> This sets the damage treshold for this character. Damage below the threshold is ignored
7311 
7312     SCRIPT_FUNCTION_BEGIN();
7313 
7314     if ( pstate->argument > 0 ) pchr->damage_threshold = pstate->argument;
7315 
7316     SCRIPT_FUNCTION_END();
7317 }
7318 
7319 //--------------------------------------------------------------------------------------------
scr_End(script_state_t * pstate,ai_state_t * pself)7320 Uint8 scr_End( script_state_t * pstate, ai_state_t * pself )
7321 {
7322     // End()
7323     /// @details ZZ@> This Is the last function in a script
7324 
7325     SCRIPT_FUNCTION_BEGIN();
7326 
7327     pself->terminate = btrue;
7328     returncode       = bfalse;
7329 
7330     SCRIPT_FUNCTION_END();
7331 }
7332 
7333 //--------------------------------------------------------------------------------------------
scr_TakePicture(script_state_t * pstate,ai_state_t * pself)7334 Uint8 scr_TakePicture( script_state_t * pstate, ai_state_t * pself )
7335 {
7336     // TakePicture()
7337     /// @details ZF@> This function proceeds only if the screenshot was successful
7338 
7339     SCRIPT_FUNCTION_BEGIN();
7340 
7341     returncode = dump_screenshot();
7342 
7343     SCRIPT_FUNCTION_END();
7344 }
7345 
7346 //--------------------------------------------------------------------------------------------
scr_set_Speech(script_state_t * pstate,ai_state_t * pself)7347 Uint8 scr_set_Speech( script_state_t * pstate, ai_state_t * pself )
7348 {
7349     // SetSpeech( tmpargument = "sound" )
7350     /// @details ZZ@> This function sets all of the RTS speech registers to tmpargument
7351 
7352     Uint16 sTmp = 0;
7353 
7354     SCRIPT_FUNCTION_BEGIN();
7355 
7356     for ( sTmp = SPEECH_BEGIN; sTmp <= SPEECH_END; sTmp++ )
7357     {
7358         pchr->sound_index[sTmp] = pstate->argument;
7359     }
7360 
7361     SCRIPT_FUNCTION_END();
7362 }
7363 
7364 //--------------------------------------------------------------------------------------------
scr_set_MoveSpeech(script_state_t * pstate,ai_state_t * pself)7365 Uint8 scr_set_MoveSpeech( script_state_t * pstate, ai_state_t * pself )
7366 {
7367     // SetMoveSpeech( tmpargument = "sound" )
7368     /// @details ZZ@> This function sets the RTS move speech register to tmpargument
7369 
7370     SCRIPT_FUNCTION_BEGIN();
7371 
7372     pchr->sound_index[SPEECH_MOVE] = pstate->argument;
7373 
7374     SCRIPT_FUNCTION_END();
7375 }
7376 
7377 //--------------------------------------------------------------------------------------------
scr_set_SecondMoveSpeech(script_state_t * pstate,ai_state_t * pself)7378 Uint8 scr_set_SecondMoveSpeech( script_state_t * pstate, ai_state_t * pself )
7379 {
7380     // SetSecondMoveSpeech( tmpargument = "sound" )
7381     /// @details ZZ@> This function sets the RTS movealt speech register to tmpargument
7382 
7383     SCRIPT_FUNCTION_BEGIN();
7384 
7385     pchr->sound_index[SPEECH_MOVEALT] = pstate->argument;
7386 
7387     SCRIPT_FUNCTION_END();
7388 }
7389 
7390 //--------------------------------------------------------------------------------------------
scr_set_AttackSpeech(script_state_t * pstate,ai_state_t * pself)7391 Uint8 scr_set_AttackSpeech( script_state_t * pstate, ai_state_t * pself )
7392 {
7393     // SetAttacksSpeech( tmpargument = "sound" )
7394     /// @details ZZ@> This function sets the RTS attack speech register to tmpargument
7395 
7396     SCRIPT_FUNCTION_BEGIN();
7397 
7398     pchr->sound_index[SPEECH_ATTACK] = pstate->argument;
7399 
7400     SCRIPT_FUNCTION_END();
7401 }
7402 
7403 //--------------------------------------------------------------------------------------------
scr_set_AssistSpeech(script_state_t * pstate,ai_state_t * pself)7404 Uint8 scr_set_AssistSpeech( script_state_t * pstate, ai_state_t * pself )
7405 {
7406     // SetAssistSpeech( tmpargument = "sound" )
7407     /// @details ZZ@> This function sets the RTS assist speech register to tmpargument
7408 
7409     SCRIPT_FUNCTION_BEGIN();
7410 
7411     pchr->sound_index[SPEECH_ASSIST] = pstate->argument;
7412 
7413     SCRIPT_FUNCTION_END();
7414 }
7415 
7416 //--------------------------------------------------------------------------------------------
scr_set_TerrainSpeech(script_state_t * pstate,ai_state_t * pself)7417 Uint8 scr_set_TerrainSpeech( script_state_t * pstate, ai_state_t * pself )
7418 {
7419     // SetTerrainSpeech( tmpargument = "sound" )
7420     /// @details ZZ@> This function sets the RTS terrain speech register to tmpargument
7421 
7422     SCRIPT_FUNCTION_BEGIN();
7423 
7424     pchr->sound_index[SPEECH_TERRAIN] = pstate->argument;
7425 
7426     SCRIPT_FUNCTION_END();
7427 }
7428 
7429 //--------------------------------------------------------------------------------------------
scr_set_SelectSpeech(script_state_t * pstate,ai_state_t * pself)7430 Uint8 scr_set_SelectSpeech( script_state_t * pstate, ai_state_t * pself )
7431 {
7432     // SetSelectSpeech( tmpargument = "sound" )
7433     /// @details ZZ@> This function sets the RTS select speech register to tmpargument
7434 
7435     SCRIPT_FUNCTION_BEGIN();
7436 
7437     pchr->sound_index[SPEECH_SELECT] = pstate->argument;
7438 
7439     SCRIPT_FUNCTION_END();
7440 }
7441 
7442 //--------------------------------------------------------------------------------------------
scr_OperatorIsMacintosh(script_state_t * pstate,ai_state_t * pself)7443 Uint8 scr_OperatorIsMacintosh( script_state_t * pstate, ai_state_t * pself )
7444 {
7445     // IfOperatorIsMacintosh()
7446     /// @details ZF@> Proceeds if the current running OS is mac
7447 
7448     SCRIPT_FUNCTION_BEGIN();
7449 
7450 #if defined(__APPLE__)
7451     returncode = btrue;
7452 #else
7453     returncode = bfalse;
7454 #endif
7455 
7456     SCRIPT_FUNCTION_END();
7457 }
7458 
7459 //--------------------------------------------------------------------------------------------
scr_ModuleHasIDSZ(script_state_t * pstate,ai_state_t * pself)7460 Uint8 scr_ModuleHasIDSZ( script_state_t * pstate, ai_state_t * pself )
7461 {
7462     // IfModuleHasIDSZ( tmpargument = "message number with module name", tmpdistance = "idsz" )
7463 
7464     /// @details ZF@> Proceeds if the specified module has the required IDSZ specified in tmpdistance
7465     /// The module folder name to be checked is a string from message.txt
7466 
7467     int message_number, message_index;
7468     char *ptext;
7469 
7470     SCRIPT_FUNCTION_BEGIN();
7471 
7472     ///use message.txt to send the module name
7473     message_number = ppro->message_start + pstate->argument;
7474     message_index  = MessageOffset.ary[message_number];
7475     ptext = message_buffer + message_index;
7476 
7477     returncode = module_has_idsz_vfs( PMod->loadname, pstate->distance, 0, ptext );
7478 
7479     SCRIPT_FUNCTION_END();
7480 }
7481 
7482 //--------------------------------------------------------------------------------------------
scr_MorphToTarget(script_state_t * pstate,ai_state_t * pself)7483 Uint8 scr_MorphToTarget( script_state_t * pstate, ai_state_t * pself )
7484 {
7485     // MorphToTarget()
7486     /// @details ZF@> This morphs the character into the target
7487     /// Also set size and keeps the previous AI type
7488 
7489     chr_t * pself_target;
7490 
7491     SCRIPT_FUNCTION_BEGIN();
7492 
7493     SCRIPT_REQUIRE_TARGET( pself_target );
7494 
7495     if ( !INGAME_CHR( pself->target ) ) return bfalse;
7496 
7497     change_character( pself->index, pself_target->basemodel_ref, pself_target->skin, ENC_LEAVE_ALL );
7498 
7499     // let the resizing take some time
7500     pchr->fat_goto      = pself_target->fat;
7501     pchr->fat_goto_time = SIZETIME;
7502 
7503     // change back to our original AI
7504     pself->type      = ProList.lst[pchr->basemodel_ref].iai;
7505 
7506     SCRIPT_FUNCTION_END();
7507 }
7508 
7509 //--------------------------------------------------------------------------------------------
scr_GiveManaFlowToTarget(script_state_t * pstate,ai_state_t * pself)7510 Uint8 scr_GiveManaFlowToTarget( script_state_t * pstate, ai_state_t * pself )
7511 {
7512     // GiveManaFlowToTarget()
7513     /// @details ZF@> Permanently boost the target's mana flow
7514 
7515     int iTmp;
7516     chr_t * pself_target;
7517 
7518     SCRIPT_FUNCTION_BEGIN();
7519 
7520     SCRIPT_REQUIRE_TARGET( pself_target );
7521 
7522     if ( pself_target->alive )
7523     {
7524         iTmp = pstate->argument;
7525         getadd( 0, pself_target->manaflow, PERFECTSTAT, &iTmp );
7526         pself_target->manaflow += iTmp;
7527     }
7528 
7529     SCRIPT_FUNCTION_END();
7530 }
7531 
7532 //--------------------------------------------------------------------------------------------
scr_GiveManaReturnToTarget(script_state_t * pstate,ai_state_t * pself)7533 Uint8 scr_GiveManaReturnToTarget( script_state_t * pstate, ai_state_t * pself )
7534 {
7535     // GiveManaReturnToTarget()
7536     /// @details ZF@> Permanently boost the target's mana return
7537 
7538     int iTmp;
7539     chr_t * pself_target;
7540 
7541     SCRIPT_FUNCTION_BEGIN();
7542 
7543     SCRIPT_REQUIRE_TARGET( pself_target );
7544 
7545     if ( pself_target->alive )
7546     {
7547         iTmp = pstate->argument;
7548         getadd( 0, pself_target->manareturn, PERFECTSTAT, &iTmp );
7549         pself_target->manareturn += iTmp;
7550     }
7551 
7552     SCRIPT_FUNCTION_END();
7553 }
7554 
7555 //--------------------------------------------------------------------------------------------
scr_set_Money(script_state_t * pstate,ai_state_t * pself)7556 Uint8 scr_set_Money( script_state_t * pstate, ai_state_t * pself )
7557 {
7558     // SetMoney()
7559     /// @details ZF@> Permanently sets the money for the character to tmpargument
7560 
7561     SCRIPT_FUNCTION_BEGIN();
7562 
7563     pchr->money = CLIP( pstate->argument, 0, MAXMONEY );
7564 
7565     SCRIPT_FUNCTION_END();
7566 }
7567 
7568 //--------------------------------------------------------------------------------------------
scr_TargetCanSeeKurses(script_state_t * pstate,ai_state_t * pself)7569 Uint8 scr_TargetCanSeeKurses( script_state_t * pstate, ai_state_t * pself )
7570 {
7571     // IfTargetCanSeeKurses()
7572     /// @details ZF@> Proceeds if the target can see kursed stuff.
7573 
7574     chr_t * pself_target;
7575 
7576     SCRIPT_FUNCTION_BEGIN();
7577 
7578     SCRIPT_REQUIRE_TARGET( pself_target );
7579 
7580     returncode = pself_target->see_kurse_level;
7581 
7582     SCRIPT_FUNCTION_END();
7583 }
7584 
7585 //--------------------------------------------------------------------------------------------
scr_DispelTargetEnchantID(script_state_t * pstate,ai_state_t * pself)7586 Uint8 scr_DispelTargetEnchantID( script_state_t * pstate, ai_state_t * pself )
7587 {
7588     // DispelEnchantID( tmpargument = "idsz" )
7589     /// @details ZF@> This function removes all enchants from the target who match the specified RemovedByIDSZ
7590 
7591     chr_t * pself_target;
7592 
7593     SCRIPT_FUNCTION_BEGIN();
7594 
7595     SCRIPT_REQUIRE_TARGET( pself_target );
7596 
7597     returncode = bfalse;
7598     if ( pself_target->alive )
7599     {
7600         // Check all enchants to see if they are removed
7601         returncode = remove_all_enchants_with_idsz( pself->target, pstate->argument );
7602     }
7603 
7604     SCRIPT_FUNCTION_END();
7605 }
7606 
7607 //--------------------------------------------------------------------------------------------
scr_KurseTarget(script_state_t * pstate,ai_state_t * pself)7608 Uint8 scr_KurseTarget( script_state_t * pstate, ai_state_t * pself )
7609 {
7610     // KurseTarget()
7611     /// @details ZF@> This makes the target kursed
7612 
7613     chr_t * pself_target;
7614 
7615     SCRIPT_FUNCTION_BEGIN();
7616 
7617     SCRIPT_REQUIRE_TARGET( pself_target );
7618 
7619     returncode = bfalse;
7620     if ( pself_target->isitem && !pself_target->iskursed )
7621     {
7622         pself_target->iskursed = btrue;
7623         returncode = btrue;
7624     }
7625 
7626     SCRIPT_FUNCTION_END();
7627 }
7628 
7629 //--------------------------------------------------------------------------------------------
scr_set_ChildContent(script_state_t * pstate,ai_state_t * pself)7630 Uint8 scr_set_ChildContent( script_state_t * pstate, ai_state_t * pself )
7631 {
7632     // SetChildContent( tmpargument = "content" )
7633     /// @details ZF@> This function lets a character set the content of the last character it
7634     /// spawned last
7635 
7636     SCRIPT_FUNCTION_BEGIN();
7637 
7638     ChrList.lst[pself->child].ai.content = pstate->argument;
7639 
7640     SCRIPT_FUNCTION_END();
7641 }
7642 
7643 //--------------------------------------------------------------------------------------------
scr_AccelerateTargetUp(script_state_t * pstate,ai_state_t * pself)7644 Uint8 scr_AccelerateTargetUp( script_state_t * pstate, ai_state_t * pself )
7645 {
7646     // AccelerateTargetUp( tmpargument = "acc z" )
7647     /// @details ZF@> This function makes the target accelerate up and down
7648 
7649     chr_t * pself_target;
7650 
7651     SCRIPT_FUNCTION_BEGIN();
7652 
7653     SCRIPT_REQUIRE_TARGET( pself_target );
7654 
7655     pself_target->vel.z += pstate->argument / 100.0f;
7656 
7657     SCRIPT_FUNCTION_END();
7658 }
7659 
7660 //--------------------------------------------------------------------------------------------
scr_set_TargetAmmo(script_state_t * pstate,ai_state_t * pself)7661 Uint8 scr_set_TargetAmmo( script_state_t * pstate, ai_state_t * pself )
7662 {
7663     // SetTargetAmmo( tmpargument = "ammo" )
7664     /// @details ZF@> This function sets the ammo of the character's current AI target
7665 
7666     chr_t * pself_target;
7667 
7668     SCRIPT_FUNCTION_BEGIN();
7669 
7670     SCRIPT_REQUIRE_TARGET( pself_target );
7671 
7672     pself_target->ammo = MIN( pstate->argument, pself_target->ammomax );
7673 
7674     SCRIPT_FUNCTION_END();
7675 }
7676 
7677 //--------------------------------------------------------------------------------------------
scr_EnableInvictus(script_state_t * pstate,ai_state_t * pself)7678 Uint8 scr_EnableInvictus( script_state_t * pstate, ai_state_t * pself )
7679 {
7680     // EnableInvictus()
7681     /// @details ZF@> This function makes the character invulerable
7682 
7683     SCRIPT_FUNCTION_BEGIN();
7684 
7685     pchr->invictus = btrue;
7686 
7687     SCRIPT_FUNCTION_END();
7688 }
7689 
7690 //--------------------------------------------------------------------------------------------
scr_DisableInvictus(script_state_t * pstate,ai_state_t * pself)7691 Uint8 scr_DisableInvictus( script_state_t * pstate, ai_state_t * pself )
7692 {
7693     // DisableInvictus()
7694     /// @details ZF@> This function makes the character not invulerable
7695 
7696     SCRIPT_FUNCTION_BEGIN();
7697 
7698     pchr->invictus = bfalse;
7699 
7700     SCRIPT_FUNCTION_END();
7701 }
7702 
7703 //--------------------------------------------------------------------------------------------
scr_TargetDamageSelf(script_state_t * pstate,ai_state_t * pself)7704 Uint8 scr_TargetDamageSelf( script_state_t * pstate, ai_state_t * pself )
7705 {
7706     // TargetDamageSelf( tmpargument = "damage" )
7707     /// @details ZF@> This function applies little bit of hate from the character's target to
7708     /// the character itself. The amount is set in tmpargument
7709 
7710     IPair tmp_damage;
7711 
7712     SCRIPT_FUNCTION_BEGIN();
7713 
7714     tmp_damage.base = pstate->argument;
7715     tmp_damage.rand = 1;
7716 
7717     damage_character( pself->index, ATK_FRONT, tmp_damage, pstate->distance, chr_get_iteam( pself->target ), pself->target, DAMFX_NBLOC, btrue );
7718 
7719     SCRIPT_FUNCTION_END();
7720 }
7721 
7722 //--------------------------------------------------------------------------------------------
scr_SetTargetSize(script_state_t * pstate,ai_state_t * pself)7723 Uint8 scr_SetTargetSize( script_state_t * pstate, ai_state_t * pself )
7724 {
7725     // SetSize( tmpargument = "percent" )
7726     /// @details ZF@> This changes the AI target's size
7727 
7728     chr_t * pself_target;
7729 
7730     SCRIPT_FUNCTION_BEGIN();
7731 
7732     SCRIPT_REQUIRE_TARGET( pself_target );
7733 
7734     pself_target->fat_goto *= pstate->argument / 100.0f;
7735     pself_target->fat_goto_time += SIZETIME;
7736 
7737     SCRIPT_FUNCTION_END();
7738 }
7739 
7740 //--------------------------------------------------------------------------------------------
scr_DrawBillboard(script_state_t * pstate,ai_state_t * pself)7741 Uint8 scr_DrawBillboard( script_state_t * pstate, ai_state_t * pself )
7742 {
7743     // DrawBillboard( tmpargument = "message", tmpdistance = "duration", tmpturn = "color" )
7744     /// @details ZF@> This function draws one of those billboards above the character
7745 
7746     SCRIPT_FUNCTION_BEGIN();
7747 
7748     returncode = bfalse;
7749     if ( LOADED_PRO( pchr->profile_ref ) )
7750     {
7751         SDL_Color text_color = {0xFF, 0xFF, 0xFF, 0xFF};
7752         int message_number, message_index;
7753         char *ptext;
7754 
7755         //List of avalible colours
7756         GLXvector4f tint_red  = { 1.00f, 0.25f, 0.25f, 1.00f };
7757         GLXvector4f tint_purple = { 0.88f, 0.75f, 1.00f, 1.00f };
7758         GLXvector4f tint_white = { 1.00f, 1.00f, 1.00f, 1.00f };
7759         GLXvector4f tint_yellow = { 1.00f, 1.00f, 0.75f, 1.00f };
7760         GLXvector4f tint_green = { 0.25f, 1.00f, 0.25f, 1.00f };
7761         GLXvector4f tint_blue = { 0.25f, 0.25f, 1.00f, 1.00f };
7762 
7763         //Figure out which color to use
7764         GLfloat *do_tint;
7765         switch ( pstate->turn )
7766         {
7767             default:
7768             case COLOR_WHITE:   do_tint = tint_white;   break;
7769             case COLOR_RED:     do_tint = tint_red;     break;
7770             case COLOR_PURPLE:  do_tint = tint_purple;  break;
7771             case COLOR_YELLOW:  do_tint = tint_yellow;  break;
7772             case COLOR_GREEN:   do_tint = tint_green;   break;
7773             case COLOR_BLUE:    do_tint = tint_blue;    break;
7774         }
7775 
7776         message_number = ppro->message_start + pstate->argument;
7777         message_index  = MessageOffset.ary[message_number];
7778         ptext = message_buffer + message_index;
7779 
7780         returncode = NULL != chr_make_text_billboard( pself->index, ptext, text_color, do_tint, pstate->distance, bb_opt_none );
7781     }
7782 
7783     SCRIPT_FUNCTION_END();
7784 }
7785 
7786 //--------------------------------------------------------------------------------------------
scr_set_TargetToBlahInPassage(script_state_t * pstate,ai_state_t * pself)7787 Uint8 scr_set_TargetToBlahInPassage( script_state_t * pstate, ai_state_t * pself )
7788 {
7789     // SetTargetToBlahInPassage()
7790     /// @details ZF@> This function sets the target to whatever object with the specified bits
7791     /// in tmpdistance is blocking the given passage. This function lets passage rectangles be used as event triggers
7792 
7793     CHR_REF ichr;
7794 
7795     SCRIPT_FUNCTION_BEGIN();
7796 
7797     ichr = who_is_blocking_passage(( PASS_REF )pstate->argument, pself->index, pstate->turn, TARGET_SELF | pstate->distance, IDSZ_NONE );
7798 
7799     if ( INGAME_CHR( ichr ) )
7800     {
7801         SET_TARGET_0( ichr );
7802     }
7803     else
7804     {
7805         returncode = bfalse;
7806     }
7807 
7808     SCRIPT_FUNCTION_END();
7809 }
7810 
7811 //--------------------------------------------------------------------------------------------
scr_TargetIsFacingSelf(script_state_t * pstate,ai_state_t * pself)7812 Uint8 scr_TargetIsFacingSelf( script_state_t * pstate, ai_state_t * pself )
7813 {
7814     // IfTargetIsFacingSelf()
7815     /// @details ZF@> This function proceeds if the target is more or less facing the character
7816     FACING_T sTmp = 0;
7817     chr_t *  pself_target;
7818 
7819     SCRIPT_FUNCTION_BEGIN();
7820 
7821     SCRIPT_REQUIRE_TARGET( pself_target );
7822 
7823     sTmp = vec_to_facing( pchr->pos.x - pself_target->pos.x , pchr->pos.y - pself_target->pos.y );
7824     sTmp -= pself_target->ori.facing_z;
7825     returncode = ( sTmp > 55535 || sTmp < 10000 );
7826 
7827     SCRIPT_FUNCTION_END();
7828 }
7829 
7830 //--------------------------------------------------------------------------------------------
scr_LevelUp(script_state_t * pstate,ai_state_t * pself)7831 Uint8 scr_LevelUp( script_state_t * pstate, ai_state_t * pself )
7832 {
7833     // IfLevelUp()
7834     /// @details ZF@> This function proceeds if the character gained a new level this update
7835     SCRIPT_FUNCTION_BEGIN();
7836 
7837     returncode = HAS_SOME_BITS( pself->alert, ALERTIF_LEVELUP );
7838 
7839     SCRIPT_FUNCTION_END();
7840 }
7841 
7842 //--------------------------------------------------------------------------------------------
scr_GiveSkillToTarget(script_state_t * pstate,ai_state_t * pself)7843 Uint8 scr_GiveSkillToTarget( script_state_t * pstate, ai_state_t * pself )
7844 {
7845     // GiveSkillToTarget( tmpargument = "skill_IDSZ", tmpdistance = "skill_level" )
7846     /// @details ZF@> This function permanently gives the target character a skill
7847     chr_t *ptarget;
7848     egoboo_rv rv;
7849 
7850     SCRIPT_FUNCTION_BEGIN();
7851 
7852     SCRIPT_REQUIRE_TARGET( ptarget );
7853 
7854     rv = idsz_map_add( ptarget->skills, SDL_arraysize( ptarget->skills ), pstate->argument, pstate->distance );
7855 
7856     returncode = ( rv_success == rv );
7857 
7858     SCRIPT_FUNCTION_END();
7859 }
7860 
7861 //--------------------------------------------------------------------------------------------
7862 //--------------------------------------------------------------------------------------------
7863 //--------------------------------------------------------------------------------------------
_break_passage(int mesh_fx_or,int become,int frames,int starttile,const PASS_REF passage,int * ptilex,int * ptiley)7864 Uint8 _break_passage( int mesh_fx_or, int become, int frames, int starttile, const PASS_REF passage, int *ptilex, int *ptiley )
7865 {
7866     /// @details ZZ@> This function breaks the tiles of a passage if there is a character standing
7867     ///               on 'em.  Turns the tiles into damage terrain if it reaches last frame.
7868 
7869     Uint32 endtile;
7870     Uint32 fan;
7871     int useful;
7872 
7873     if ( INVALID_PASSAGE( passage ) ) return bfalse;
7874 
7875     // limit the start tile the the 256 tile images that we have
7876     starttile = CLIP_TO_08BITS( starttile );
7877 
7878     // same with the end tile
7879     endtile   =  starttile + frames - 1;
7880     endtile = CLIP( endtile, 0, 255 );
7881 
7882     useful = bfalse;
7883     CHR_BEGIN_LOOP_ACTIVE( character, pchr )
7884     {
7885         float lerp_z;
7886 
7887         // nothing in packs
7888         if ( pchr->pack.is_packed || INGAME_CHR( pchr->attachedto ) ) continue;
7889 
7890         // nothing flying
7891         if ( 0 != pchr->flyheight ) continue;
7892 
7893         lerp_z = ( pchr->pos.z - pchr->enviro.floor_level ) / DAMAGERAISE;
7894         lerp_z = 1.0f - CLIP( lerp_z, 0.0f, 1.0f );
7895 
7896         if ( pchr->phys.weight * lerp_z <= 20 ) continue;
7897 
7898         fan = mesh_get_grid( PMesh, pchr->pos.x, pchr->pos.y );
7899         if ( mesh_grid_is_valid( PMesh, fan ) )
7900         {
7901             Uint16 img      = PMesh->tmem.tile_list[fan].img & 0x00FF;
7902             int highbits = PMesh->tmem.tile_list[fan].img & 0xFF00;
7903 
7904             if ( img >= starttile && img < endtile )
7905             {
7906                 if ( object_is_in_passage(( PASS_REF )passage, pchr->pos.x, pchr->pos.y, pchr->bump_1.size ) )
7907                 {
7908                     // Remember where the hit occured.
7909                     *ptilex = pchr->pos.x;
7910                     *ptiley = pchr->pos.y;
7911 
7912                     useful = btrue;
7913 
7914                     // Change the tile image
7915                     img++;
7916                 }
7917             }
7918 
7919             if ( img == endtile )
7920             {
7921                 useful = mesh_add_fx( PMesh, fan, mesh_fx_or );
7922 
7923                 if ( become != 0 )
7924                 {
7925                     img = become;
7926                 }
7927             }
7928 
7929             if ( PMesh->tmem.tile_list[fan].img != ( img | highbits ) )
7930             {
7931                 mesh_set_texture( PMesh, fan, img | highbits );
7932             }
7933         }
7934     }
7935     CHR_END_LOOP();
7936 
7937     return useful;
7938 }
7939 
7940 //--------------------------------------------------------------------------------------------
_append_end_text(chr_t * pchr,const int message,script_state_t * pstate)7941 Uint8 _append_end_text( chr_t * pchr, const int message, script_state_t * pstate )
7942 {
7943     /// @details ZZ@> This function appends a message to the end-module text
7944 
7945     int read, message_offset;
7946     CHR_REF ichr;
7947 
7948     FUNCTION_BEGIN();
7949 
7950     if ( !LOADED_PRO( pchr->profile_ref ) ) return bfalse;
7951 
7952     message_offset = ProList.lst[pchr->profile_ref].message_start + message;
7953     ichr           = GET_REF_PCHR( pchr );
7954 
7955     if ( message_offset < MessageOffset.count )
7956     {
7957         char * src, * src_end;
7958         char * dst, * dst_end;
7959 
7960         // Copy the message_offset
7961         read = MessageOffset.ary[message_offset];
7962 
7963         src     = message_buffer + read;
7964         src_end = message_buffer + MESSAGEBUFFERSIZE;
7965 
7966         dst     = endtext + endtext_carat;
7967         dst_end = endtext + MAXENDTEXT - 1;
7968 
7969         expand_escape_codes( ichr, pstate, src, src_end, dst, dst_end );
7970 
7971         endtext_carat = strlen( endtext );
7972     }
7973 
7974     str_add_linebreaks( endtext, strlen( endtext ), 30 );
7975 
7976     FUNCTION_END();
7977 }
7978 
7979 //--------------------------------------------------------------------------------------------
_find_grid_in_passage(const int x0,const int y0,const int tiletype,const PASS_REF passage,int * px1,int * py1)7980 Uint8 _find_grid_in_passage( const int x0, const int y0, const int tiletype, const PASS_REF passage, int *px1, int *py1 )
7981 {
7982     /// @details ZZ@> This function finds the next tile in the passage, x0 and y0
7983     ///    must be set first, and are set on a find.  Returns btrue or bfalse
7984     ///    depending on if it finds one or not
7985 
7986     int x, y;
7987     Uint32 fan;
7988     passage_t * ppass;
7989 
7990     if ( INVALID_PASSAGE( passage ) ) return bfalse;
7991     ppass = PassageStack.lst + passage;
7992 
7993     // Do the first row
7994     x = x0 >> GRID_BITS;
7995     y = y0 >> GRID_BITS;
7996 
7997     if ( x < ppass->area.left )  x = ppass->area.left;
7998     if ( y < ppass->area.top )  y = ppass->area.top;
7999 
8000     if ( y < ppass->area.bottom )
8001     {
8002         for ( /*nothing*/; x <= ppass->area.right; x++ )
8003         {
8004             fan = mesh_get_tile_int( PMesh, x, y );
8005 
8006             if ( mesh_grid_is_valid( PMesh, fan ) )
8007             {
8008                 if ( CLIP_TO_08BITS( PMesh->tmem.tile_list[fan].img ) == tiletype )
8009                 {
8010                     *px1 = ( x << GRID_BITS ) + 64;
8011                     *py1 = ( y << GRID_BITS ) + 64;
8012                     return btrue;
8013                 }
8014 
8015             }
8016         }
8017         y++;
8018     }
8019 
8020     // Do all remaining rows
8021     for ( /* nothing */; y <= ppass->area.bottom; y++ )
8022     {
8023         for ( x = ppass->area.left; x <= ppass->area.right; x++ )
8024         {
8025             fan = mesh_get_tile_int( PMesh, x, y );
8026 
8027             if ( mesh_grid_is_valid( PMesh, fan ) )
8028             {
8029 
8030                 if ( CLIP_TO_08BITS( PMesh->tmem.tile_list[fan].img ) == tiletype )
8031                 {
8032                     *px1 = ( x << GRID_BITS ) + 64;
8033                     *py1 = ( y << GRID_BITS ) + 64;
8034                     return btrue;
8035                 }
8036             }
8037         }
8038     }
8039 
8040     return bfalse;
8041 }
8042 
8043 //--------------------------------------------------------------------------------------------
_display_message(const CHR_REF ichr,const PRO_REF iprofile,int message,script_state_t * pstate)8044 Uint8 _display_message( const CHR_REF ichr, const PRO_REF iprofile, int message, script_state_t * pstate )
8045 {
8046     /// @details ZZ@> This function sticks a message_offset in the display queue and sets its timer
8047 
8048     int slot, read;
8049     int message_offset;
8050     Uint8 retval;
8051 
8052     message_offset = ProList.lst[iprofile].message_start + message;
8053 
8054     retval = 0;
8055     if ( message_offset < MessageOffset.count )
8056     {
8057         char * src, * src_end;
8058         char * dst, * dst_end;
8059 
8060         slot = DisplayMsg_get_free();
8061         DisplayMsg.ary[slot].time = cfg.message_duration;
8062 
8063         // Copy the message_offset
8064         read = MessageOffset.ary[message_offset];
8065 
8066         src     = message_buffer + read;
8067         src_end = message_buffer + MESSAGEBUFFERSIZE;
8068 
8069         dst     = DisplayMsg.ary[slot].textdisplay;
8070         dst_end = DisplayMsg.ary[slot].textdisplay + MESSAGESIZE - 1;
8071 
8072         expand_escape_codes( ichr, pstate, src, src_end, dst, dst_end );
8073 
8074         *dst_end = CSTR_END;
8075 
8076         retval = 1;
8077     }
8078 
8079     return retval;
8080 }
8081 
8082 //--------------------------------------------------------------------------------------------
8083 // Uint8 scr_get_SkillLevel( script_state_t * pstate, ai_state_t * pself )
8084 // {
8085 //    // tmpargument = GetSkillLevel()
8086 //    /// @details ZZ@> This function sets tmpargument to the shield profiency level of the Target
8087 //   SCRIPT_FUNCTION_BEGIN();
8088 //   pstate->argument = CapStack.lst[pchr->attachedto].shieldprofiency;
8089 //   SCRIPT_FUNCTION_END();
8090 // }
8091