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 = §or[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 = §or[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 = §or[sp->sectnum];
417 u->hi_sectp = §or[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 = §or[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