1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4 
5 This file is part of Shadow Warrior version 1.2
6 
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 #include "build.h"
27 
28 #include "keys.h"
29 #include "names2.h"
30 #include "panel.h"
31 #include "game.h"
32 #include "tags.h"
33 #include "weapon.h"
34 #include "sprite.h"
35 #include "actor.h"
36 
37 extern int jump_grav;
38 
39 extern STATE s_DebrisNinja[];
40 extern STATE s_DebrisRat[];
41 extern STATE s_DebrisCrab[];
42 extern STATE s_DebrisStarFish[];
43 extern STATE s_NinjaDieSliced[];
44 
45 extern STATEp sg_NinjaGrabThroat[];
46 
47 int DoActorStopFall(short SpriteNum);
48 
49 
50 int
DoScaleSprite(short SpriteNum)51 DoScaleSprite(short SpriteNum)
52 {
53     SPRITEp sp = &sprite[SpriteNum];
54     USERp u = User[SpriteNum];
55     int scale_value;
56 
57     if (u->scale_speed)
58     {
59         u->scale_value += u->scale_speed * ACTORMOVETICS;
60 
61         scale_value = u->scale_value >> 8;
62 
63         if (u->scale_speed > 0)
64         {
65             if (scale_value > u->scale_tgt)
66                 u->scale_speed = 0;
67             else
68                 sp->xrepeat = sp->yrepeat = scale_value;
69         }
70         else
71         {
72             if (scale_value < u->scale_tgt)
73                 u->scale_speed = 0;
74             else
75                 sp->xrepeat = sp->yrepeat = scale_value;
76         }
77 
78     }
79 
80     return 0;
81 }
82 
83 int
DoActorDie(short SpriteNum,short weapon)84 DoActorDie(short SpriteNum, short weapon)
85 {
86     USERp u = User[SpriteNum];
87     SPRITEp sp = &sprite[SpriteNum];
88 
89 
90     change_sprite_stat(SpriteNum, STAT_DEAD_ACTOR);
91     SET(u->Flags, SPR_DEAD);
92     RESET(u->Flags, SPR_FALLING | SPR_JUMPING);
93     u->floor_dist = Z(40);
94 
95     // test for gibable dead bodies
96     SET(sp->extra, SPRX_BREAKABLE);
97     SET(sp->cstat, CSTAT_SPRITE_BREAKABLE);
98 
99     if (weapon < 0)
100     {
101         // killed by one of these non-sprites
102         switch (weapon)
103         {
104         case WPN_NM_LAVA:
105             ChangeState(SpriteNum, u->StateEnd);
106             u->RotNum = 0;
107             break;
108 
109         case WPN_NM_SECTOR_SQUISH:
110             ChangeState(SpriteNum, u->StateEnd);
111             u->RotNum = 0;
112             break;
113         }
114 
115         return 0;
116     }
117 
118 
119     // killed by one of these sprites
120     switch (User[weapon]->ID)
121     {
122     // Coolie actually explodes himself
123     // he is the Sprite AND Weapon
124     case COOLIE_RUN_R0:
125         ChangeState(SpriteNum, u->StateEnd);
126         u->RotNum = 0;
127         sp->xvel <<= 1;
128         u->ActorActionFunc = NULL;
129         sprite[SpriteNum].ang = NORM_ANGLE(sprite[SpriteNum].ang + 1024);
130         break;
131 
132     case NINJA_RUN_R0:
133         if (u->ID == NINJA_RUN_R0) // Cut in half!
134         {
135             SPRITEp wp = &sprite[weapon];
136 
137             if (User[weapon]->WeaponNum != WPN_FIST)
138             {
139                 //SpawnBlood(SpriteNum, SpriteNum, -1, -1, -1, -1);
140                 InitPlasmaFountain(wp, sp);
141                 InitPlasmaFountain(wp, sp);
142                 PlaySound(DIGI_NINJAINHALF,&sp->x,&sp->y,&sp->z,v3df_none);
143                 ChangeState(SpriteNum, &s_NinjaDieSliced[0]);
144             }
145             else
146             {
147                 if (RANDOM_RANGE(1000) > 500)
148                 {
149                     SPRITEp wp = &sprite[weapon];
150                     InitPlasmaFountain(wp, sp);
151                 }
152 
153                 ChangeState(SpriteNum, u->StateEnd);
154                 u->RotNum = 0;
155                 u->ActorActionFunc = NULL;
156                 sp->xvel = 200 + RANDOM_RANGE(200);
157                 u->jump_speed = -200 - RANDOM_RANGE(250);
158                 DoActorBeginJump(SpriteNum);
159                 sprite[SpriteNum].ang = sprite[weapon].ang;
160             }
161         }
162         else
163         {
164             // test for gibable dead bodies
165             if (RANDOM_RANGE(1000) > 500)
166                 SET(sp->cstat, CSTAT_SPRITE_YFLIP);
167             ChangeState(SpriteNum, u->StateEnd);
168             sp->xvel = 0;
169             u->jump_speed = 0;
170             DoActorBeginJump(SpriteNum);
171         }
172 
173         u->RotNum = 0;
174 
175         u->ActorActionFunc = NULL;
176         //u->ActorActionFunc = NullAnimator;
177         sprite[SpriteNum].ang = sprite[weapon].ang;
178         break;
179 
180     case COOLG_RUN_R0:
181     case SKEL_RUN_R0:
182     case RIPPER_RUN_R0:
183     case RIPPER2_RUN_R0:
184     case EEL_RUN_R0:
185     case STAR1:
186     case SUMO_RUN_R0:
187         ChangeState(SpriteNum, u->StateEnd);
188         u->RotNum = 0;
189         break;
190 
191     case UZI_SMOKE:
192         if (RANDOM_RANGE(1000) > 500)
193             SET(sp->cstat, CSTAT_SPRITE_YFLIP);
194         ChangeState(SpriteNum, u->StateEnd);
195         u->RotNum = 0;
196         // Rippers still gotta jump or they fall off walls weird
197         if (u->ID == RIPPER_RUN_R0 || u->ID == RIPPER2_RUN_R0)
198         {
199             sp->xvel <<= 1;
200             u->jump_speed = -100 - RANDOM_RANGE(250);
201             DoActorBeginJump(SpriteNum);
202         }
203         else
204         {
205             sp->xvel = 0;
206             u->jump_speed = -10 - RANDOM_RANGE(25);
207             DoActorBeginJump(SpriteNum);
208         }
209         u->ActorActionFunc = NULL;
210         // Get angle to player
211         sp->ang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y) + 1024);
212         break;
213 
214     case UZI_SMOKE+1: // Shotgun
215         if (RANDOM_RANGE(1000) > 500)
216             SET(sp->cstat, CSTAT_SPRITE_YFLIP);
217         ChangeState(SpriteNum, u->StateEnd);
218         u->RotNum = 0;
219 
220         // Rippers still gotta jump or they fall off walls weird
221         if (u->ID == RIPPER_RUN_R0 || u->ID == RIPPER2_RUN_R0)
222         {
223             sp->xvel = 75 + RANDOM_RANGE(100);
224             u->jump_speed = -100 - RANDOM_RANGE(150);
225         }
226         else
227         {
228             sp->xvel = 100 + RANDOM_RANGE(200);
229             u->jump_speed = -100 - RANDOM_RANGE(250);
230         }
231         DoActorBeginJump(SpriteNum);
232         u->ActorActionFunc = NULL;
233         // Get angle to player
234         sp->ang = NORM_ANGLE(getangle(u->tgt_sp->x - sp->x, u->tgt_sp->y - sp->y) + 1024);
235         break;
236 
237     default:
238         ASSERT(weapon >= 0);
239         switch (u->ID)
240         {
241         case SKULL_R0:
242         case BETTY_R0:
243             ChangeState(SpriteNum, u->StateEnd);
244             break;
245 
246         default:
247             if (RANDOM_RANGE(1000) > 700)
248             {
249                 SPRITEp wp = &sprite[weapon];
250                 InitPlasmaFountain(wp, sp);
251             }
252 
253             if (RANDOM_RANGE(1000) > 500)
254                 SET(sp->cstat, CSTAT_SPRITE_YFLIP);
255             ChangeState(SpriteNum, u->StateEnd);
256             u->RotNum = 0;
257             u->ActorActionFunc = NULL;
258             sp->xvel = 300 + RANDOM_RANGE(400);
259             u->jump_speed = -300 - RANDOM_RANGE(350);
260             DoActorBeginJump(SpriteNum);
261             sprite[SpriteNum].ang = sprite[weapon].ang;
262             break;
263         }
264         break;
265     }
266 
267     // These are too big to flip upside down
268     switch (u->ID)
269     {
270     case RIPPER2_RUN_R0:
271     case COOLIE_RUN_R0:
272     case SUMO_RUN_R0:
273     case ZILLA_RUN_R0:
274         RESET(sp->cstat, CSTAT_SPRITE_YFLIP);
275         break;
276     }
277 
278     u->ID = 0;
279 
280     return 0;
281 }
282 
283 void
DoDebrisCurrent(SPRITEp sp)284 DoDebrisCurrent(SPRITEp sp)
285 {
286     int nx, ny;
287     int ret=0;
288     USERp u = User[sp - sprite];
289     SECT_USERp sectu = SectUser[sp->sectnum];
290 
291     //sp->clipdist = (256+128)>>2;
292 
293     nx = DIV4(sectu->speed) * (int) sintable[NORM_ANGLE(sectu->ang + 512)] >> 14;
294     ny = DIV4(sectu->speed) * (int) sintable[sectu->ang] >> 14;
295 
296     // faster than move_sprite
297     //move_missile(sp-sprite, nx, ny, 0, Z(2), Z(0), 0, ACTORMOVETICS);
298     ret = move_sprite(sp-sprite, nx, ny, 0, u->ceiling_dist, u->floor_dist, 0, ACTORMOVETICS);
299 
300     // attempt to move away from wall
301     if (ret)
302     {
303         short rang = RANDOM_P2(2048);
304 
305         nx = DIV4(sectu->speed) * (int) sintable[NORM_ANGLE(sectu->ang + rang + 512)] >> 14;
306         ny = DIV4(sectu->speed) * (int) sintable[NORM_ANGLE(sectu->ang + rang)] >> 14;
307 
308         move_sprite(sp-sprite, nx, ny, 0, u->ceiling_dist, u->floor_dist, 0, ACTORMOVETICS);
309     }
310 
311     sp->z = u->loz;
312 }
313 
314 int
DoActorSectorDamage(short SpriteNum)315 DoActorSectorDamage(short SpriteNum)
316 {
317     SPRITEp sp = &sprite[SpriteNum];
318     USERp u = User[SpriteNum];
319     SECT_USERp sectu = SectUser[sp->sectnum];
320     SECTORp sectp = &sector[sp->sectnum];
321 
322     if (u->Health <= 0)
323         return FALSE;
324 
325     if (sectu && sectu->damage)
326     {
327         if (TEST(sectu->flags, SECTFU_DAMAGE_ABOVE_SECTOR))
328         {
329             if ((u->DamageTics -= synctics) < 0)
330             {
331                 u->DamageTics = 60;
332                 u->Health -= sectu->damage;
333 
334                 if (u->Health <= 0)
335                 {
336                     UpdateSinglePlayKills(SpriteNum);
337                     DoActorDie(SpriteNum, WPN_NM_LAVA);
338                     return TRUE;
339                 }
340             }
341         }
342         else if (SPRITEp_BOS(sp) >= sectp->floorz)
343         {
344             if ((u->DamageTics -= synctics) < 0)
345             {
346                 u->DamageTics = 60;
347                 u->Health -= sectu->damage;
348 
349                 if (u->Health <= 0)
350                 {
351                     UpdateSinglePlayKills(SpriteNum);
352                     DoActorDie(SpriteNum, WPN_NM_LAVA);
353                     return TRUE;
354                 }
355             }
356         }
357     }
358 
359     // note that most squishing is done in vator.c
360     if (u->lo_sectp && u->hi_sectp && labs(u->loz - u->hiz) < DIV2(SPRITEp_SIZE_Z(sp)))
361     //if (u->lo_sectp && u->hi_sectp && labs(u->loz - u->hiz) < SPRITEp_SIZE_Z(sp))
362     {
363         u->Health = 0;
364         if (SpawnShrap(SpriteNum, WPN_NM_SECTOR_SQUISH))
365         {
366             UpdateSinglePlayKills(SpriteNum);
367             SetSuicide(SpriteNum);
368         }
369         else
370         {
371             ASSERT(TRUE == FALSE);
372             //DoActorDie(SpriteNum, WPN_NM_SECTOR_SQUISH);
373         }
374 
375         return TRUE;
376     }
377 
378     return FALSE;
379 }
380 
381 
382 int
move_debris(short SpriteNum,int xchange,int ychange,int zchange)383 move_debris(short SpriteNum, int xchange, int ychange, int zchange)
384 {
385     USERp u = User[SpriteNum];
386 
387     u->ret = move_sprite(SpriteNum, xchange, ychange, zchange,
388                          u->ceiling_dist, u->floor_dist, 0, ACTORMOVETICS);
389 
390     return !u->ret;
391 }
392 
393 // !AIC - Supposed to allow floating of DEBRIS (dead bodies, flotsam, jetsam).  Or if water has
394 // current move with the current.
395 
396 int
DoActorDebris(short SpriteNum)397 DoActorDebris(short SpriteNum)
398 {
399     SPRITEp sp = &sprite[SpriteNum];
400     USERp u = User[SpriteNum];
401     SECTORp sectp = &sector[sp->sectnum];
402     int nx, ny;
403 
404     // This was move from DoActorDie so actor's can't be walked through until they are on the floor
405     RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
406 
407     // Don't let some actors float
408     switch (u->ID)
409     {
410     case HORNET_RUN_R0:
411     case BUNNY_RUN_R0:
412         KillSprite(SpriteNum);
413         return 0;
414     case ZILLA_RUN_R0:
415         getzsofslope(sp->sectnum, sp->x, sp->y, &u->hiz, &u->loz);
416         u->lo_sectp = &sector[sp->sectnum];
417         u->hi_sectp = &sector[sp->sectnum];
418         u->lo_sp = NULL;
419         u->hi_sp = NULL;
420         break;
421     }
422 
423     if (TEST(sectp->extra, SECTFX_SINK))
424     {
425         if (TEST(sectp->extra, SECTFX_CURRENT))
426         {
427             DoDebrisCurrent(sp);
428         }
429         else
430         {
431             //nx = sp->xvel * ACTORMOVETICS * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
432             //ny = sp->xvel * ACTORMOVETICS * (int) sintable[sp->ang] >> 14;
433             nx = ACTORMOVETICS * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
434             ny = ACTORMOVETICS * (int) sintable[sp->ang] >> 14;
435 
436             //sp->clipdist = (256+128)>>2;
437 
438             if (!move_debris(SpriteNum, nx, ny, 0L))
439             {
440                 sp->ang = RANDOM_P2(2048);
441             }
442         }
443 
444         if (SectUser[sp->sectnum] && SectUser[sp->sectnum]->depth > 10) // JBF: added null check
445         {
446             u->WaitTics = (u->WaitTics + (ACTORMOVETICS << 3)) & 1023;
447             //sp->z = Z(2) + u->loz + ((Z(4) * (int) sintable[u->WaitTics]) >> 14);
448             sp->z = u->loz - ((Z(2) * (int) sintable[u->WaitTics]) >> 14);
449         }
450     }
451     else
452     {
453         sp->z = u->loz;
454     }
455 
456     return 0;
457 }
458 
459 
460 int
DoFireFly(short SpriteNum)461 DoFireFly(short SpriteNum)
462 {
463     SPRITEp sp = &sprite[SpriteNum];
464     USERp u = User[SpriteNum];
465     int nx, ny;
466 
467     nx = 4 * ACTORMOVETICS * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
468     ny = 4 * ACTORMOVETICS * (int) sintable[sp->ang] >> 14;
469 
470     sp->clipdist = 256>>2;
471     if (!move_actor(SpriteNum, nx, ny, 0L))
472     {
473         sp->ang = NORM_ANGLE(sp->ang + 1024);
474     }
475 
476     u->WaitTics = (u->WaitTics + (ACTORMOVETICS << 1)) & 2047;
477 
478     sp->z = u->sz + ((Z(32) * (int) sintable[u->WaitTics]) >> 14);
479     return 0;
480 }
481 
482 int
DoGenerateSewerDebris(short SpriteNum)483 DoGenerateSewerDebris(short SpriteNum)
484 {
485     SPRITEp sp = &sprite[SpriteNum];
486     USERp u = User[SpriteNum];
487     short n;
488 
489     static STATEp Debris[] =
490     {
491         s_DebrisNinja,
492         s_DebrisRat,
493         s_DebrisCrab,
494         s_DebrisStarFish
495     };
496 
497     u->Tics -= ACTORMOVETICS;
498 
499     if (u->Tics <= 0)
500     {
501         u->Tics = u->WaitTics;
502 
503         n = SpawnSprite(STAT_DEAD_ACTOR, 0, Debris[RANDOM_P2(4<<8)>>8], sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 200);
504 
505         SetOwner(SpriteNum, n);
506     }
507 
508     return 0;
509 }
510 
511 // !AIC - Tries to keep actors correctly on the floor.  More that a bit messy.
512 
513 void
KeepActorOnFloor(short SpriteNum)514 KeepActorOnFloor(short SpriteNum)
515 {
516     USERp u = User[SpriteNum];
517     SPRITEp sp = User[SpriteNum]->SpriteP;
518     SECTORp sectp;
519     int depth;
520 
521     sectp = &sector[sp->sectnum];
522 
523     RESET(sp->cstat, CSTAT_SPRITE_YFLIP); // If upside down, reset it
524 
525     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
526         return;
527 
528     if (u->lo_sectp && SectUser[u->lo_sectp - sector])
529         depth = SectUser[u->lo_sectp - sector]->depth;
530     else
531         depth = 0;
532 
533     if (TEST(sectp->extra, SECTFX_SINK) &&
534         depth > 35 &&
535         u->ActorActionSet && u->ActorActionSet->Swim)
536     {
537         if (TEST(u->Flags, SPR_SWIMMING))
538         {
539             if (u->Rot != u->ActorActionSet->Run && u->Rot != u->ActorActionSet->Swim && u->Rot != u->ActorActionSet->Stand)
540             {
541                 // was swimming but have now stopped
542                 RESET(u->Flags, SPR_SWIMMING);
543                 RESET(sp->cstat, CSTAT_SPRITE_YCENTER);
544                 u->oz = sp->z = u->loz;
545                 return;
546             }
547 
548             if (u->Rot == u->ActorActionSet->Run)
549             {
550                 NewStateGroup(SpriteNum, u->ActorActionSet->Swim);
551             }
552 
553             // are swimming
554             u->oz = sp->z = u->loz - Z(depth);
555         }
556         else
557         {
558             // only start swimming if you are running
559             if (u->Rot == u->ActorActionSet->Run || u->Rot == u->ActorActionSet->Swim)
560             {
561                 NewStateGroup(SpriteNum, u->ActorActionSet->Swim);
562                 u->oz = sp->z = u->loz - Z(depth);
563                 SET(u->Flags, SPR_SWIMMING);
564                 SET(sp->cstat, CSTAT_SPRITE_YCENTER);
565             }
566             else
567             {
568                 RESET(u->Flags, SPR_SWIMMING);
569                 RESET(sp->cstat, CSTAT_SPRITE_YCENTER);
570                 u->oz = sp->z = u->loz;
571             }
572         }
573 
574         return;
575     }
576 
577     // NOT in a swimming situation
578     RESET(u->Flags, SPR_SWIMMING);
579     RESET(sp->cstat, CSTAT_SPRITE_YCENTER);
580 
581 #if 1
582     if (TEST(u->Flags, SPR_MOVED))
583     {
584         u->oz = sp->z = u->loz;
585     }
586     else
587     {
588         int ceilz,ceilhit,florz,florhit;
589         FAFgetzrangepoint(sp->x, sp->y, sp->z, sp->sectnum,
590                           &ceilz, &ceilhit, &florz, &florhit);
591 
592         u->oz = sp->z = florz;
593     }
594 #endif
595 
596 
597 }
598 
599 int
DoActorBeginSlide(short SpriteNum,short ang,short vel,short dec)600 DoActorBeginSlide(short SpriteNum, short ang, short vel, short dec)
601 {
602     USERp u = User[SpriteNum];
603 
604     SET(u->Flags, SPR_SLIDING);
605 
606     u->slide_ang = ang;
607     u->slide_vel = vel;
608     u->slide_dec = dec;
609 
610     //DoActorSlide(SpriteNum);
611 
612     return 0;
613 }
614 
615 // !AIC - Sliding can occur in different directions from movement of the actor.
616 // Has its own set of variables
617 
618 int
DoActorSlide(short SpriteNum)619 DoActorSlide(short SpriteNum)
620 {
621     USERp u = User[SpriteNum];
622     int nx, ny;
623 
624     nx = u->slide_vel * (int) sintable[NORM_ANGLE(u->slide_ang + 512)] >> 14;
625     ny = u->slide_vel * (int) sintable[u->slide_ang] >> 14;
626 
627     if (!move_actor(SpriteNum, nx, ny, 0L))
628     {
629         RESET(u->Flags, SPR_SLIDING);
630         return FALSE;
631     }
632 
633     u->slide_vel -= u->slide_dec * ACTORMOVETICS;
634 
635     if (u->slide_vel < 20)
636     {
637         RESET(u->Flags, SPR_SLIDING);
638     }
639 
640     return TRUE;
641 }
642 
643 // !AIC - Actor jumping and falling
644 
645 int
DoActorBeginJump(short SpriteNum)646 DoActorBeginJump(short SpriteNum)
647 {
648     USERp u = User[SpriteNum];
649 
650     SET(u->Flags, SPR_JUMPING);
651     RESET(u->Flags, SPR_FALLING);
652 
653     // u->jump_speed = should be set before calling
654 
655     // set up individual actor jump gravity
656     u->jump_grav = ACTOR_GRAVITY;
657 
658     // Change sprites state to jumping
659     if (u->ActorActionSet)
660     {
661         if (TEST(u->Flags, SPR_DEAD))
662             NewStateGroup(SpriteNum, u->ActorActionSet->DeathJump);
663         else
664             NewStateGroup(SpriteNum, u->ActorActionSet->Jump);
665     }
666     u->StateFallOverride = NULL;
667 
668     //DO NOT CALL DoActorJump! DoActorStopFall can cause an infinite loop and
669     //stack overflow if it is called.
670     //DoActorJump(SpriteNum);
671 
672     return 0;
673 }
674 
675 int
DoActorJump(short SpriteNum)676 DoActorJump(short SpriteNum)
677 {
678     USERp u = User[SpriteNum];
679     SPRITEp sp = User[SpriteNum]->SpriteP;
680 
681     int jump_adj;
682 
683     // precalculate jump value to adjust jump speed by
684     jump_adj = u->jump_grav * ACTORMOVETICS;
685 
686     // adjust jump speed by gravity - if jump speed greater than 0 player
687     // have started falling
688     if ((u->jump_speed += jump_adj) > 0)
689     {
690         //DSPRINTF(ds,"Actor Jump Height %d", labs(sp->z - sector[sp->sectnum].floorz)>>8 );
691         MONO_PRINT(ds);
692 
693         // Start falling
694         DoActorBeginFall(SpriteNum);
695         return 0;
696     }
697 
698     // adjust height by jump speed
699     sp->z += u->jump_speed * ACTORMOVETICS;
700 
701     // if player gets to close the ceiling while jumping
702     if (sp->z < u->hiz + Z(PIC_SIZY(SpriteNum)))
703     {
704         // put player at the ceiling
705         sp->z = u->hiz + Z(PIC_SIZY(SpriteNum));
706 
707         // reverse your speed to falling
708         u->jump_speed = -u->jump_speed;
709 
710         //DSPRINTF(ds,"Jump: sp_num %d, hi_num %d, hi_sect %d",SpriteNum, u->hi_sp - sprite, u->hi_sectp - sector);
711         MONO_PRINT(ds);
712 
713         // Change sprites state to falling
714         DoActorBeginFall(SpriteNum);
715     }
716 
717     return 0;
718 }
719 
720 
721 int
DoActorBeginFall(short SpriteNum)722 DoActorBeginFall(short SpriteNum)
723 {
724     USERp u = User[SpriteNum];
725 
726     SET(u->Flags, SPR_FALLING);
727     RESET(u->Flags, SPR_JUMPING);
728 
729     u->jump_grav = ACTOR_GRAVITY;
730 
731     // Change sprites state to falling
732     if (u->ActorActionSet)
733     {
734         if (TEST(u->Flags, SPR_DEAD))
735         {
736             NewStateGroup(SpriteNum, u->ActorActionSet->DeathFall);
737         }
738         else
739             NewStateGroup(SpriteNum, u->ActorActionSet->Fall);
740 
741         if (u->StateFallOverride)
742         {
743             NewStateGroup(SpriteNum, u->StateFallOverride);
744         }
745     }
746 
747     DoActorFall(SpriteNum);
748 
749     return 0;
750 }
751 
752 
753 int
DoActorFall(short SpriteNum)754 DoActorFall(short SpriteNum)
755 {
756     USERp u = User[SpriteNum];
757     SPRITEp sp = User[SpriteNum]->SpriteP;
758 
759     // adjust jump speed by gravity
760     u->jump_speed += u->jump_grav * ACTORMOVETICS;
761 
762     // adjust player height by jump speed
763     sp->z += u->jump_speed * ACTORMOVETICS;
764 
765     // Stick like glue when you hit the ground
766     if (sp->z > u->loz)
767     {
768         DoActorStopFall(SpriteNum);
769     }
770 
771     return 0;
772 }
773 
774 int
DoActorStopFall(short SpriteNum)775 DoActorStopFall(short SpriteNum)
776 {
777     USERp u = User[SpriteNum];
778     SPRITEp sp = User[SpriteNum]->SpriteP;
779 
780     sp->z = u->loz;
781 
782     RESET(u->Flags, SPR_FALLING | SPR_JUMPING);
783     RESET(sp->cstat, CSTAT_SPRITE_YFLIP);
784 
785 
786     // don't stand on face or wall sprites - jump again
787     if (u->lo_sp && !TEST(u->lo_sp->cstat, CSTAT_SPRITE_ALIGNMENT_FLOOR))
788     {
789         //sp->ang = NORM_ANGLE(sp->ang + (RANDOM_P2(64<<8)>>8) - 32);
790         sp->ang = NORM_ANGLE(sp->ang + 1024 + (RANDOM_P2(512<<8)>>8));
791         u->jump_speed = -350;
792 
793         //DSPRINTF(ds,"StopFall: sp_num %d, sp->picnum %d, lo_num %d, lo_sp->picnum %d",SpriteNum, sp->picnum, u->lo_sp - sprite, u->lo_sp->picnum);
794         MONO_PRINT(ds);
795 
796         DoActorBeginJump(SpriteNum);
797         return 0;
798     }
799 
800     // Change sprites state to running
801     if (u->ActorActionSet)
802     {
803         if (TEST(u->Flags, SPR_DEAD))
804         {
805             NewStateGroup(SpriteNum, u->ActorActionSet->Dead);
806             PlaySound(DIGI_ACTORBODYFALL1,&sp->x,&sp->y,&sp->z,v3df_none);
807         }
808         else
809         {
810             PlaySound(DIGI_ACTORHITGROUND,&sp->x,&sp->y,&sp->z,v3df_none);
811 
812             NewStateGroup(SpriteNum, u->ActorActionSet->Run);
813 
814             if ((u->track >= 0) && (u->jump_speed) > 800 && (u->ActorActionSet->Sit))
815             {
816                 u->WaitTics = 80;
817                 NewStateGroup(SpriteNum, u->ActorActionSet->Sit);
818             }
819         }
820     }
821 
822     return 0;
823 }
824 
825 int
DoActorDeathMove(short SpriteNum)826 DoActorDeathMove(short SpriteNum)
827 {
828     ANIMATOR DoFindGround;
829 
830     USERp u = User[SpriteNum];
831     SPRITEp sp = User[SpriteNum]->SpriteP;
832     int nx, ny;
833 
834     if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
835     {
836         if (TEST(u->Flags, SPR_JUMPING))
837             DoActorJump(SpriteNum);
838         else
839             DoActorFall(SpriteNum);
840     }
841 
842     nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
843     ny = sp->xvel * (int) sintable[sp->ang] >> 14;
844 
845     sp->clipdist = (128+64)>>2;
846     move_actor(SpriteNum, nx, ny, 0);
847 
848     // only fall on top of floor sprite or sector
849     DoFindGroundPoint(SpriteNum);
850 
851     return 0;
852 }
853 
854 // !AIC - Jumping a falling for shrapnel and other stuff, not actors.
855 
856 int
DoBeginJump(short SpriteNum)857 DoBeginJump(short SpriteNum)
858 {
859     USERp u = User[SpriteNum];
860 
861     SET(u->Flags, SPR_JUMPING);
862     RESET(u->Flags, SPR_FALLING);
863 
864     // set up individual actor jump gravity
865     u->jump_grav = ACTOR_GRAVITY;
866 
867     DoJump(SpriteNum);
868 
869     return 0;
870 }
871 
872 int
DoJump(short SpriteNum)873 DoJump(short SpriteNum)
874 {
875     USERp u = User[SpriteNum];
876     SPRITEp sp = User[SpriteNum]->SpriteP;
877 
878     int jump_adj;
879 
880     // precalculate jump value to adjust jump speed by
881     jump_adj = u->jump_grav * ACTORMOVETICS;
882 
883     // adjust jump speed by gravity - if jump speed greater than 0 player
884     // have started falling
885     if ((u->jump_speed += jump_adj) > 0)
886     {
887         // Start falling
888         DoBeginFall(SpriteNum);
889         return 0;
890     }
891 
892     // adjust height by jump speed
893     sp->z += u->jump_speed * ACTORMOVETICS;
894 
895     // if player gets to close the ceiling while jumping
896     if (sp->z < u->hiz + Z(PIC_SIZY(SpriteNum)))
897     {
898         // put player at the ceiling
899         sp->z = u->hiz + Z(PIC_SIZY(SpriteNum));
900 
901         // reverse your speed to falling
902         u->jump_speed = -u->jump_speed;
903 
904         // Change sprites state to falling
905         DoBeginFall(SpriteNum);
906     }
907 
908     return 0;
909 }
910 
911 
912 int
DoBeginFall(short SpriteNum)913 DoBeginFall(short SpriteNum)
914 {
915     USERp u = User[SpriteNum];
916 
917     SET(u->Flags, SPR_FALLING);
918     RESET(u->Flags, SPR_JUMPING);
919 
920     u->jump_grav = ACTOR_GRAVITY;
921 
922     DoFall(SpriteNum);
923 
924     return 0;
925 }
926 
927 #if 0
928 int
929 DoFall(short SpriteNum)
930 {
931     USERp u = User[SpriteNum];
932     SPRITEp sp = User[SpriteNum]->SpriteP;
933 
934     // adjust jump speed by gravity
935     u->jump_speed += u->jump_grav * ACTORMOVETICS;
936 
937     // adjust player height by jump speed
938     sp->z += u->jump_speed * ACTORMOVETICS;
939 
940     // Stick like glue when you hit the ground
941     if (sp->z > u->loz)
942     {
943         sp->z = u->loz;
944         RESET(u->Flags, SPR_FALLING);
945     }
946 
947     return 0;
948 }
949 #else
950 int
DoFall(short SpriteNum)951 DoFall(short SpriteNum)
952 {
953     USERp u = User[SpriteNum];
954     SPRITEp sp = User[SpriteNum]->SpriteP;
955 
956     // adjust jump speed by gravity
957     u->jump_speed += u->jump_grav * ACTORMOVETICS;
958 
959     // adjust player height by jump speed
960     sp->z += u->jump_speed * ACTORMOVETICS;
961 
962     // Stick like glue when you hit the ground
963     if (sp->z > u->loz - u->floor_dist)
964     {
965         sp->z = u->loz - u->floor_dist;
966         RESET(u->Flags, SPR_FALLING);
967     }
968 
969     return 0;
970 }
971 #endif
972 
973 
974 #include "saveable.h"
975 
976 static saveable_code saveable_actor_code[] =
977 {
978     SAVE_CODE(DoScaleSprite),
979     SAVE_CODE(DoActorDie),
980     SAVE_CODE(DoDebrisCurrent),
981     SAVE_CODE(DoActorSectorDamage),
982     SAVE_CODE(DoActorDebris),
983     SAVE_CODE(DoFireFly),
984     SAVE_CODE(DoGenerateSewerDebris),
985     SAVE_CODE(KeepActorOnFloor),
986     SAVE_CODE(DoActorBeginSlide),
987     SAVE_CODE(DoActorSlide),
988     SAVE_CODE(DoActorBeginJump),
989     SAVE_CODE(DoActorJump),
990     SAVE_CODE(DoActorBeginFall),
991     SAVE_CODE(DoActorFall),
992     SAVE_CODE(DoActorStopFall),
993     SAVE_CODE(DoActorDeathMove),
994     SAVE_CODE(DoBeginJump),
995     SAVE_CODE(DoJump),
996     SAVE_CODE(DoBeginFall),
997     SAVE_CODE(DoFall)
998 };
999 
1000 saveable_module saveable_actor =
1001 {
1002     // code
1003     saveable_actor_code,
1004     SIZ(saveable_actor_code),
1005 
1006     // data
1007     NULL,0
1008 };
1009