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