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