summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/wolf3d/wl_state.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2019-07-07 22:00:20 -0400
committerFranklin Wei <git@fwei.tk>2019-07-09 11:20:55 -0400
commit3f59fc8b771625aca9c3aefe03cf1038d8461963 (patch)
treee0623a323613baa0b0993411b38bcaed144b27ed /apps/plugins/sdl/progs/wolf3d/wl_state.c
parent439a0d1d91fa040d261fc39b87278bc9f5391dcc (diff)
downloadrockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.gz
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.zip
Wolfenstein 3-D!
This is a port of Wolf4SDL, which is derived from the original id software source release. The port runs on top of the SDL plugin runtime and is loaded as an overlay. Licensing of the game code is not an issue, as discussed below (essentially, the Debian project treats Wolf4SDL as GPLv2, with an email from John Carmack backing it up): http://forums.rockbox.org/index.php?topic=52872 Included is a copy of MAME's Yamaha OPL sound chip emulator (fmopl_gpl.c). This file was not part of the original Wolf4SDL source (which includes a non-GPL'd version), but was rather rebased from from a later MAME source which had been relicensed to GPLv2. Change-Id: I64c2ba035e0be7e2f49252f40640641416613439
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_state.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/wl_state.c1530
1 files changed, 1530 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_state.c b/apps/plugins/sdl/progs/wolf3d/wl_state.c
new file mode 100644
index 0000000000..92b8ca1713
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/wl_state.c
@@ -0,0 +1,1530 @@
1// WL_STATE.C
2
3#include "wl_def.h"
4#pragma hdrstop
5
6/*
7=============================================================================
8
9 LOCAL CONSTANTS
10
11=============================================================================
12*/
13
14
15/*
16=============================================================================
17
18 GLOBAL VARIABLES
19
20=============================================================================
21*/
22
23
24static const dirtype opposite[9] =
25 {west,southwest,south,southeast,east,northeast,north,northwest,nodir};
26
27static const dirtype diagonal[9][9] =
28{
29 /* east */ {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},
30 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
31 /* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},
32 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
33 /* west */ {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},
34 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
35 /* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},
36 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
37 {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}
38};
39
40
41
42void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);
43void NewState (objtype *ob, statetype *state);
44
45boolean TryWalk (objtype *ob);
46void MoveObj (objtype *ob, int32_t move);
47
48void KillActor (objtype *ob);
49void DamageActor (objtype *ob, unsigned damage);
50
51boolean CheckLine (objtype *ob);
52void FirstSighting (objtype *ob);
53boolean CheckSight (objtype *ob);
54
55/*
56=============================================================================
57
58 LOCAL VARIABLES
59
60=============================================================================
61*/
62
63
64
65//===========================================================================
66
67
68/*
69===================
70=
71= SpawnNewObj
72=
73= Spaws a new actor at the given TILE coordinates, with the given state, and
74= the given size in GLOBAL units.
75=
76= newobj = a pointer to an initialized new actor
77=
78===================
79*/
80
81void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state)
82{
83 GetNewActor ();
84 newobj->state = state;
85 if (state->tictime)
86 newobj->ticcount = DEMOCHOOSE_ORIG_SDL(
87 US_RndT () % state->tictime,
88 US_RndT () % state->tictime + 1); // Chris' moonwalk bugfix ;D
89 else
90 newobj->ticcount = 0;
91
92 newobj->tilex = (short) tilex;
93 newobj->tiley = (short) tiley;
94 newobj->x = ((int32_t)tilex<<TILESHIFT)+TILEGLOBAL/2;
95 newobj->y = ((int32_t)tiley<<TILESHIFT)+TILEGLOBAL/2;
96 newobj->dir = nodir;
97
98 actorat[tilex][tiley] = newobj;
99 newobj->areanumber =
100 *(mapsegs[0] + (newobj->tiley<<mapshift)+newobj->tilex) - AREATILE;
101}
102
103
104
105/*
106===================
107=
108= NewState
109=
110= Changes ob to a new state, setting ticcount to the max for that state
111=
112===================
113*/
114
115void NewState (objtype *ob, statetype *state)
116{
117 ob->state = state;
118 ob->ticcount = state->tictime;
119}
120
121
122
123/*
124=============================================================================
125
126 ENEMY TILE WORLD MOVEMENT CODE
127
128=============================================================================
129*/
130
131
132/*
133==================================
134=
135= TryWalk
136=
137= Attempts to move ob in its current (ob->dir) direction.
138=
139= If blocked by either a wall or an actor returns FALSE
140=
141= If move is either clear or blocked only by a door, returns TRUE and sets
142=
143= ob->tilex = new destination
144= ob->tiley
145= ob->areanumber = the floor tile number (0-(NUMAREAS-1)) of destination
146= ob->distance = TILEGLOBAl, or -doornumber if a door is blocking the way
147=
148= If a door is in the way, an OpenDoor call is made to start it opening.
149= The actor code should wait until
150= doorobjlist[-ob->distance].action = dr_open, meaning the door has been
151= fully opened
152=
153==================================
154*/
155
156#define CHECKDIAG(x,y) \
157{ \
158 temp=(uintptr_t)actorat[x][y]; \
159 if (temp) \
160 { \
161 if (temp<256) \
162 return false; \
163 if (((objtype *)temp)->flags&FL_SHOOTABLE) \
164 return false; \
165 } \
166}
167
168#ifdef PLAYDEMOLIKEORIGINAL
169 #define DOORCHECK \
170 if(DEMOCOND_ORIG) \
171 doornum = temp&63; \
172 else \
173 { \
174 doornum = (int) temp & 127; \
175 OpenDoor(doornum); \
176 ob->distance = -doornum - 1; \
177 return true; \
178 }
179#else
180 #define DOORCHECK \
181 doornum = (int) temp & 127; \
182 OpenDoor(doornum); \
183 ob->distance = -doornum - 1; \
184 return true;
185#endif
186
187#define CHECKSIDE(x,y) \
188{ \
189 temp=(uintptr_t)actorat[x][y]; \
190 if (temp) \
191 { \
192 if (temp<128) \
193 return false; \
194 if (temp<256) \
195 { \
196 DOORCHECK \
197 } \
198 else if (((objtype *)temp)->flags&FL_SHOOTABLE) \
199 return false; \
200 } \
201}
202
203
204boolean TryWalk (objtype *ob)
205{
206 int doornum = -1;
207 uintptr_t temp;
208
209 if (ob->obclass == inertobj)
210 {
211 switch (ob->dir)
212 {
213 case north:
214 ob->tiley--;
215 break;
216
217 case northeast:
218 ob->tilex++;
219 ob->tiley--;
220 break;
221
222 case east:
223 ob->tilex++;
224 break;
225
226 case southeast:
227 ob->tilex++;
228 ob->tiley++;
229 break;
230
231 case south:
232 ob->tiley++;
233 break;
234
235 case southwest:
236 ob->tilex--;
237 ob->tiley++;
238 break;
239
240 case west:
241 ob->tilex--;
242 break;
243
244 case northwest:
245 ob->tilex--;
246 ob->tiley--;
247 break;
248 }
249 }
250 else
251 {
252 switch (ob->dir)
253 {
254 case north:
255 if (ob->obclass == dogobj || ob->obclass == fakeobj
256 || ob->obclass == ghostobj || ob->obclass == spectreobj)
257 {
258 CHECKDIAG(ob->tilex,ob->tiley-1);
259 }
260 else
261 {
262 CHECKSIDE(ob->tilex,ob->tiley-1);
263 }
264 ob->tiley--;
265 break;
266
267 case northeast:
268 CHECKDIAG(ob->tilex+1,ob->tiley-1);
269 CHECKDIAG(ob->tilex+1,ob->tiley);
270 CHECKDIAG(ob->tilex,ob->tiley-1);
271 ob->tilex++;
272 ob->tiley--;
273 break;
274
275 case east:
276 if (ob->obclass == dogobj || ob->obclass == fakeobj
277 || ob->obclass == ghostobj || ob->obclass == spectreobj)
278 {
279 CHECKDIAG(ob->tilex+1,ob->tiley);
280 }
281 else
282 {
283 CHECKSIDE(ob->tilex+1,ob->tiley);
284 }
285 ob->tilex++;
286 break;
287
288 case southeast:
289 CHECKDIAG(ob->tilex+1,ob->tiley+1);
290 CHECKDIAG(ob->tilex+1,ob->tiley);
291 CHECKDIAG(ob->tilex,ob->tiley+1);
292 ob->tilex++;
293 ob->tiley++;
294 break;
295
296 case south:
297 if (ob->obclass == dogobj || ob->obclass == fakeobj
298 || ob->obclass == ghostobj || ob->obclass == spectreobj)
299 {
300 CHECKDIAG(ob->tilex,ob->tiley+1);
301 }
302 else
303 {
304 CHECKSIDE(ob->tilex,ob->tiley+1);
305 }
306 ob->tiley++;
307 break;
308
309 case southwest:
310 CHECKDIAG(ob->tilex-1,ob->tiley+1);
311 CHECKDIAG(ob->tilex-1,ob->tiley);
312 CHECKDIAG(ob->tilex,ob->tiley+1);
313 ob->tilex--;
314 ob->tiley++;
315 break;
316
317 case west:
318 if (ob->obclass == dogobj || ob->obclass == fakeobj
319 || ob->obclass == ghostobj || ob->obclass == spectreobj)
320 {
321 CHECKDIAG(ob->tilex-1,ob->tiley);
322 }
323 else
324 {
325 CHECKSIDE(ob->tilex-1,ob->tiley);
326 }
327 ob->tilex--;
328 break;
329
330 case northwest:
331 CHECKDIAG(ob->tilex-1,ob->tiley-1);
332 CHECKDIAG(ob->tilex-1,ob->tiley);
333 CHECKDIAG(ob->tilex,ob->tiley-1);
334 ob->tilex--;
335 ob->tiley--;
336 break;
337
338 case nodir:
339 return false;
340
341 default:
342 Quit ("Walk: Bad dir");
343 }
344 }
345
346#ifdef PLAYDEMOLIKEORIGINAL
347 if (DEMOCOND_ORIG && doornum != -1)
348 {
349 OpenDoor(doornum);
350 ob->distance = -doornum-1;
351 return true;
352 }
353#endif
354
355 ob->areanumber =
356 *(mapsegs[0] + (ob->tiley<<mapshift)+ob->tilex) - AREATILE;
357
358 ob->distance = TILEGLOBAL;
359 return true;
360}
361
362
363/*
364==================================
365=
366= SelectDodgeDir
367=
368= Attempts to choose and initiate a movement for ob that sends it towards
369= the player while dodging
370=
371= If there is no possible move (ob is totally surrounded)
372=
373= ob->dir = nodir
374=
375= Otherwise
376=
377= ob->dir = new direction to follow
378= ob->distance = TILEGLOBAL or -doornumber
379= ob->tilex = new destination
380= ob->tiley
381= ob->areanumber = the floor tile number (0-(NUMAREAS-1)) of destination
382=
383==================================
384*/
385
386void SelectDodgeDir (objtype *ob)
387{
388 int deltax,deltay,i;
389 unsigned absdx,absdy;
390 dirtype dirtry[5];
391 dirtype turnaround,tdir;
392
393 if (ob->flags & FL_FIRSTATTACK)
394 {
395 //
396 // turning around is only ok the very first time after noticing the
397 // player
398 //
399 turnaround = nodir;
400 ob->flags &= ~FL_FIRSTATTACK;
401 }
402 else
403 turnaround=opposite[ob->dir];
404
405 deltax = player->tilex - ob->tilex;
406 deltay = player->tiley - ob->tiley;
407
408 //
409 // arange 5 direction choices in order of preference
410 // the four cardinal directions plus the diagonal straight towards
411 // the player
412 //
413
414 if (deltax>0)
415 {
416 dirtry[1]= east;
417 dirtry[3]= west;
418 }
419 else
420 {
421 dirtry[1]= west;
422 dirtry[3]= east;
423 }
424
425 if (deltay>0)
426 {
427 dirtry[2]= south;
428 dirtry[4]= north;
429 }
430 else
431 {
432 dirtry[2]= north;
433 dirtry[4]= south;
434 }
435
436 //
437 // randomize a bit for dodging
438 //
439 absdx = abs(deltax);
440 absdy = abs(deltay);
441
442 if (absdx > absdy)
443 {
444 tdir = dirtry[1];
445 dirtry[1] = dirtry[2];
446 dirtry[2] = tdir;
447 tdir = dirtry[3];
448 dirtry[3] = dirtry[4];
449 dirtry[4] = tdir;
450 }
451
452 if (US_RndT() < 128)
453 {
454 tdir = dirtry[1];
455 dirtry[1] = dirtry[2];
456 dirtry[2] = tdir;
457 tdir = dirtry[3];
458 dirtry[3] = dirtry[4];
459 dirtry[4] = tdir;
460 }
461
462 dirtry[0] = diagonal [ dirtry[1] ] [ dirtry[2] ];
463
464 //
465 // try the directions util one works
466 //
467 for (i=0;i<5;i++)
468 {
469 if ( dirtry[i] == nodir || dirtry[i] == turnaround)
470 continue;
471
472 ob->dir = dirtry[i];
473 if (TryWalk(ob))
474 return;
475 }
476
477 //
478 // turn around only as a last resort
479 //
480 if (turnaround != nodir)
481 {
482 ob->dir = turnaround;
483
484 if (TryWalk(ob))
485 return;
486 }
487
488 ob->dir = nodir;
489}
490
491
492/*
493============================
494=
495= SelectChaseDir
496=
497= As SelectDodgeDir, but doesn't try to dodge
498=
499============================
500*/
501
502void SelectChaseDir (objtype *ob)
503{
504 int deltax,deltay;
505 dirtype d[3];
506 dirtype tdir, olddir, turnaround;
507
508
509 olddir=ob->dir;
510 turnaround=opposite[olddir];
511
512 deltax=player->tilex - ob->tilex;
513 deltay=player->tiley - ob->tiley;
514
515 d[1]=nodir;
516 d[2]=nodir;
517
518 if (deltax>0)
519 d[1]= east;
520 else if (deltax<0)
521 d[1]= west;
522 if (deltay>0)
523 d[2]=south;
524 else if (deltay<0)
525 d[2]=north;
526
527 if (abs(deltay)>abs(deltax))
528 {
529 tdir=d[1];
530 d[1]=d[2];
531 d[2]=tdir;
532 }
533
534 if (d[1]==turnaround)
535 d[1]=nodir;
536 if (d[2]==turnaround)
537 d[2]=nodir;
538
539
540 if (d[1]!=nodir)
541 {
542 ob->dir=d[1];
543 if (TryWalk(ob))
544 return; /*either moved forward or attacked*/
545 }
546
547 if (d[2]!=nodir)
548 {
549 ob->dir=d[2];
550 if (TryWalk(ob))
551 return;
552 }
553
554 /* there is no direct path to the player, so pick another direction */
555
556 if (olddir!=nodir)
557 {
558 ob->dir=olddir;
559 if (TryWalk(ob))
560 return;
561 }
562
563 if (US_RndT()>128) /*randomly determine direction of search*/
564 {
565 for (tdir=north; tdir<=west; tdir=(dirtype)(tdir+1))
566 {
567 if (tdir!=turnaround)
568 {
569 ob->dir=tdir;
570 if ( TryWalk(ob) )
571 return;
572 }
573 }
574 }
575 else
576 {
577 for (tdir=west; tdir>=north; tdir=(dirtype)(tdir-1))
578 {
579 if (tdir!=turnaround)
580 {
581 ob->dir=tdir;
582 if ( TryWalk(ob) )
583 return;
584 }
585 }
586 }
587
588 if (turnaround != nodir)
589 {
590 ob->dir=turnaround;
591 if (ob->dir != nodir)
592 {
593 if ( TryWalk(ob) )
594 return;
595 }
596 }
597
598 ob->dir = nodir; // can't move
599}
600
601
602/*
603============================
604=
605= SelectRunDir
606=
607= Run Away from player
608=
609============================
610*/
611
612void SelectRunDir (objtype *ob)
613{
614 int deltax,deltay;
615 dirtype d[3];
616 dirtype tdir;
617
618
619 deltax=player->tilex - ob->tilex;
620 deltay=player->tiley - ob->tiley;
621
622 if (deltax<0)
623 d[1]= east;
624 else
625 d[1]= west;
626 if (deltay<0)
627 d[2]=south;
628 else
629 d[2]=north;
630
631 if (abs(deltay)>abs(deltax))
632 {
633 tdir=d[1];
634 d[1]=d[2];
635 d[2]=tdir;
636 }
637
638 ob->dir=d[1];
639 if (TryWalk(ob))
640 return; /*either moved forward or attacked*/
641
642 ob->dir=d[2];
643 if (TryWalk(ob))
644 return;
645
646 /* there is no direct path to the player, so pick another direction */
647
648 if (US_RndT()>128) /*randomly determine direction of search*/
649 {
650 for (tdir=north; tdir<=west; tdir=(dirtype)(tdir+1))
651 {
652 ob->dir=tdir;
653 if ( TryWalk(ob) )
654 return;
655 }
656 }
657 else
658 {
659 for (tdir=west; tdir>=north; tdir=(dirtype)(tdir-1))
660 {
661 ob->dir=tdir;
662 if ( TryWalk(ob) )
663 return;
664 }
665 }
666
667 ob->dir = nodir; // can't move
668}
669
670
671/*
672=================
673=
674= MoveObj
675=
676= Moves ob be move global units in ob->dir direction
677= Actors are not allowed to move inside the player
678= Does NOT check to see if the move is tile map valid
679=
680= ob->x = adjusted for new position
681= ob->y
682=
683=================
684*/
685
686void MoveObj (objtype *ob, int32_t move)
687{
688 int32_t deltax,deltay;
689
690 switch (ob->dir)
691 {
692 case north:
693 ob->y -= move;
694 break;
695 case northeast:
696 ob->x += move;
697 ob->y -= move;
698 break;
699 case east:
700 ob->x += move;
701 break;
702 case southeast:
703 ob->x += move;
704 ob->y += move;
705 break;
706 case south:
707 ob->y += move;
708 break;
709 case southwest:
710 ob->x -= move;
711 ob->y += move;
712 break;
713 case west:
714 ob->x -= move;
715 break;
716 case northwest:
717 ob->x -= move;
718 ob->y -= move;
719 break;
720
721 case nodir:
722 return;
723
724 default:
725 Quit ("MoveObj: bad dir!");
726 }
727
728 //
729 // check to make sure it's not on top of player
730 //
731 if (areabyplayer[ob->areanumber])
732 {
733 deltax = ob->x - player->x;
734 if (deltax < -MINACTORDIST || deltax > MINACTORDIST)
735 goto moveok;
736 deltay = ob->y - player->y;
737 if (deltay < -MINACTORDIST || deltay > MINACTORDIST)
738 goto moveok;
739
740 if (ob->hidden) // move closer until he meets CheckLine
741 goto moveok;
742
743 if (ob->obclass == ghostobj || ob->obclass == spectreobj)
744 TakeDamage (tics*2,ob);
745
746 //
747 // back up
748 //
749 switch (ob->dir)
750 {
751 case north:
752 ob->y += move;
753 break;
754 case northeast:
755 ob->x -= move;
756 ob->y += move;
757 break;
758 case east:
759 ob->x -= move;
760 break;
761 case southeast:
762 ob->x -= move;
763 ob->y -= move;
764 break;
765 case south:
766 ob->y -= move;
767 break;
768 case southwest:
769 ob->x += move;
770 ob->y -= move;
771 break;
772 case west:
773 ob->x += move;
774 break;
775 case northwest:
776 ob->x += move;
777 ob->y += move;
778 break;
779
780 case nodir:
781 return;
782 }
783 return;
784 }
785moveok:
786 ob->distance -=move;
787}
788
789/*
790=============================================================================
791
792 STUFF
793
794=============================================================================
795*/
796
797/*
798===============
799=
800= DropItem
801=
802= Tries to drop a bonus item somewhere in the tiles surrounding the
803= given tilex/tiley
804=
805===============
806*/
807
808void DropItem (wl_stat_t itemtype, int tilex, int tiley)
809{
810 int x,y,xl,xh,yl,yh;
811
812 //
813 // find a free spot to put it in
814 //
815 if (!actorat[tilex][tiley])
816 {
817 PlaceItemType (itemtype, tilex,tiley);
818 return;
819 }
820
821 xl = tilex-1;
822 xh = tilex+1;
823 yl = tiley-1;
824 yh = tiley+1;
825
826 for (x=xl ; x<= xh ; x++)
827 {
828 for (y=yl ; y<= yh ; y++)
829 {
830 if (!actorat[x][y])
831 {
832 PlaceItemType (itemtype, x,y);
833 return;
834 }
835 }
836 }
837}
838
839
840
841/*
842===============
843=
844= KillActor
845=
846===============
847*/
848
849void KillActor (objtype *ob)
850{
851 int tilex,tiley;
852
853 tilex = ob->tilex = (word)(ob->x >> TILESHIFT); // drop item on center
854 tiley = ob->tiley = (word)(ob->y >> TILESHIFT);
855
856 switch (ob->obclass)
857 {
858 case guardobj:
859 GivePoints (100);
860 NewState (ob,&s_grddie1);
861 PlaceItemType (bo_clip2,tilex,tiley);
862 break;
863
864 case officerobj:
865 GivePoints (400);
866 NewState (ob,&s_ofcdie1);
867 PlaceItemType (bo_clip2,tilex,tiley);
868 break;
869
870 case mutantobj:
871 GivePoints (700);
872 NewState (ob,&s_mutdie1);
873 PlaceItemType (bo_clip2,tilex,tiley);
874 break;
875
876 case ssobj:
877 GivePoints (500);
878 NewState (ob,&s_ssdie1);
879 if (gamestate.bestweapon < wp_machinegun)
880 PlaceItemType (bo_machinegun,tilex,tiley);
881 else
882 PlaceItemType (bo_clip2,tilex,tiley);
883 break;
884
885 case dogobj:
886 GivePoints (200);
887 NewState (ob,&s_dogdie1);
888 break;
889
890#ifndef SPEAR
891 case bossobj:
892 GivePoints (5000);
893 NewState (ob,&s_bossdie1);
894 PlaceItemType (bo_key1,tilex,tiley);
895 break;
896
897 case gretelobj:
898 GivePoints (5000);
899 NewState (ob,&s_greteldie1);
900 PlaceItemType (bo_key1,tilex,tiley);
901 break;
902
903 case giftobj:
904 GivePoints (5000);
905 gamestate.killx = player->x;
906 gamestate.killy = player->y;
907 NewState (ob,&s_giftdie1);
908 break;
909
910 case fatobj:
911 GivePoints (5000);
912 gamestate.killx = player->x;
913 gamestate.killy = player->y;
914 NewState (ob,&s_fatdie1);
915 break;
916
917 case schabbobj:
918 GivePoints (5000);
919 gamestate.killx = player->x;
920 gamestate.killy = player->y;
921 NewState (ob,&s_schabbdie1);
922 break;
923 case fakeobj:
924 GivePoints (2000);
925 NewState (ob,&s_fakedie1);
926 break;
927
928 case mechahitlerobj:
929 GivePoints (5000);
930 NewState (ob,&s_mechadie1);
931 break;
932 case realhitlerobj:
933 GivePoints (5000);
934 gamestate.killx = player->x;
935 gamestate.killy = player->y;
936 NewState (ob,&s_hitlerdie1);
937 break;
938#else
939 case spectreobj:
940 if (ob->flags&FL_BONUS)
941 {
942 GivePoints (200); // Get points once for each
943 ob->flags &= ~FL_BONUS;
944 }
945 NewState (ob,&s_spectredie1);
946 break;
947
948 case angelobj:
949 GivePoints (5000);
950 NewState (ob,&s_angeldie1);
951 break;
952
953 case transobj:
954 GivePoints (5000);
955 NewState (ob,&s_transdie0);
956 PlaceItemType (bo_key1,tilex,tiley);
957 break;
958
959 case uberobj:
960 GivePoints (5000);
961 NewState (ob,&s_uberdie0);
962 PlaceItemType (bo_key1,tilex,tiley);
963 break;
964
965 case willobj:
966 GivePoints (5000);
967 NewState (ob,&s_willdie1);
968 PlaceItemType (bo_key1,tilex,tiley);
969 break;
970
971 case deathobj:
972 GivePoints (5000);
973 NewState (ob,&s_deathdie1);
974 PlaceItemType (bo_key1,tilex,tiley);
975 break;
976#endif
977 }
978
979 gamestate.killcount++;
980 ob->flags &= ~FL_SHOOTABLE;
981 actorat[ob->tilex][ob->tiley] = NULL;
982 ob->flags |= FL_NONMARK;
983}
984
985
986
987/*
988===================
989=
990= DamageActor
991=
992= Called when the player succesfully hits an enemy.
993=
994= Does damage points to enemy ob, either putting it into a stun frame or
995= killing it.
996=
997===================
998*/
999
1000void DamageActor (objtype *ob, unsigned damage)
1001{
1002 madenoise = true;
1003
1004 //
1005 // do double damage if shooting a non attack mode actor
1006 //
1007 if ( !(ob->flags & FL_ATTACKMODE) )
1008 damage <<= 1;
1009
1010 ob->hitpoints -= (short)damage;
1011
1012 if (ob->hitpoints<=0)
1013 KillActor (ob);
1014 else
1015 {
1016 if (! (ob->flags & FL_ATTACKMODE) )
1017 FirstSighting (ob); // put into combat mode
1018
1019 switch (ob->obclass) // dogs only have one hit point
1020 {
1021 case guardobj:
1022 if (ob->hitpoints&1)
1023 NewState (ob,&s_grdpain);
1024 else
1025 NewState (ob,&s_grdpain1);
1026 break;
1027
1028 case officerobj:
1029 if (ob->hitpoints&1)
1030 NewState (ob,&s_ofcpain);
1031 else
1032 NewState (ob,&s_ofcpain1);
1033 break;
1034
1035 case mutantobj:
1036 if (ob->hitpoints&1)
1037 NewState (ob,&s_mutpain);
1038 else
1039 NewState (ob,&s_mutpain1);
1040 break;
1041
1042 case ssobj:
1043 if (ob->hitpoints&1)
1044 NewState (ob,&s_sspain);
1045 else
1046 NewState (ob,&s_sspain1);
1047
1048 break;
1049 }
1050 }
1051}
1052
1053/*
1054=============================================================================
1055
1056 CHECKSIGHT
1057
1058=============================================================================
1059*/
1060
1061
1062/*
1063=====================
1064=
1065= CheckLine
1066=
1067= Returns true if a straight line between the player and ob is unobstructed
1068=
1069=====================
1070*/
1071
1072boolean CheckLine (objtype *ob)
1073{
1074 int x1,y1,xt1,yt1,x2,y2,xt2,yt2;
1075 int x,y;
1076 int xdist,ydist,xstep,ystep;
1077 int partial,delta;
1078 int32_t ltemp;
1079 int xfrac,yfrac,deltafrac;
1080 unsigned value,intercept;
1081
1082 x1 = ob->x >> UNSIGNEDSHIFT; // 1/256 tile precision
1083 y1 = ob->y >> UNSIGNEDSHIFT;
1084 xt1 = x1 >> 8;
1085 yt1 = y1 >> 8;
1086
1087 x2 = plux;
1088 y2 = pluy;
1089 xt2 = player->tilex;
1090 yt2 = player->tiley;
1091
1092 xdist = abs(xt2-xt1);
1093
1094 if (xdist > 0)
1095 {
1096 if (xt2 > xt1)
1097 {
1098 partial = 256-(x1&0xff);
1099 xstep = 1;
1100 }
1101 else
1102 {
1103 partial = x1&0xff;
1104 xstep = -1;
1105 }
1106
1107 deltafrac = abs(x2-x1);
1108 delta = y2-y1;
1109 ltemp = ((int32_t)delta<<8)/deltafrac;
1110 if (ltemp > 0x7fffl)
1111 ystep = 0x7fff;
1112 else if (ltemp < -0x7fffl)
1113 ystep = -0x7fff;
1114 else
1115 ystep = ltemp;
1116 yfrac = y1 + (((int32_t)ystep*partial) >>8);
1117
1118 x = xt1+xstep;
1119 xt2 += xstep;
1120 do
1121 {
1122 y = yfrac>>8;
1123 yfrac += ystep;
1124
1125 value = (unsigned)tilemap[x][y];
1126 x += xstep;
1127
1128 if (!value)
1129 continue;
1130
1131 if (value<128 || value>256)
1132 return false;
1133
1134 //
1135 // see if the door is open enough
1136 //
1137 value &= ~0x80;
1138 intercept = yfrac-ystep/2;
1139
1140 if (intercept>doorposition[value])
1141 return false;
1142
1143 } while (x != xt2);
1144 }
1145
1146 ydist = abs(yt2-yt1);
1147
1148 if (ydist > 0)
1149 {
1150 if (yt2 > yt1)
1151 {
1152 partial = 256-(y1&0xff);
1153 ystep = 1;
1154 }
1155 else
1156 {
1157 partial = y1&0xff;
1158 ystep = -1;
1159 }
1160
1161 deltafrac = abs(y2-y1);
1162 delta = x2-x1;
1163 ltemp = ((int32_t)delta<<8)/deltafrac;
1164 if (ltemp > 0x7fffl)
1165 xstep = 0x7fff;
1166 else if (ltemp < -0x7fffl)
1167 xstep = -0x7fff;
1168 else
1169 xstep = ltemp;
1170 xfrac = x1 + (((int32_t)xstep*partial) >>8);
1171
1172 y = yt1 + ystep;
1173 yt2 += ystep;
1174 do
1175 {
1176 x = xfrac>>8;
1177 xfrac += xstep;
1178
1179 value = (unsigned)tilemap[x][y];
1180 y += ystep;
1181
1182 if (!value)
1183 continue;
1184
1185 if (value<128 || value>256)
1186 return false;
1187
1188 //
1189 // see if the door is open enough
1190 //
1191 value &= ~0x80;
1192 intercept = xfrac-xstep/2;
1193
1194 if (intercept>doorposition[value])
1195 return false;
1196 } while (y != yt2);
1197 }
1198
1199 return true;
1200}
1201
1202
1203/*
1204================
1205=
1206= CheckSight
1207=
1208= Checks a straight line between player and current object
1209=
1210= If the sight is ok, check alertness and angle to see if they notice
1211=
1212= returns true if the player has been spoted
1213=
1214================
1215*/
1216
1217#define MINSIGHT 0x18000l
1218
1219boolean CheckSight (objtype *ob)
1220{
1221 int32_t deltax,deltay;
1222
1223 //
1224 // don't bother tracing a line if the area isn't connected to the player's
1225 //
1226 if (!areabyplayer[ob->areanumber])
1227 return false;
1228
1229 //
1230 // if the player is real close, sight is automatic
1231 //
1232 deltax = player->x - ob->x;
1233 deltay = player->y - ob->y;
1234
1235 if (deltax > -MINSIGHT && deltax < MINSIGHT
1236 && deltay > -MINSIGHT && deltay < MINSIGHT)
1237 return true;
1238
1239 //
1240 // see if they are looking in the right direction
1241 //
1242 switch (ob->dir)
1243 {
1244 case north:
1245 if (deltay > 0)
1246 return false;
1247 break;
1248
1249 case east:
1250 if (deltax < 0)
1251 return false;
1252 break;
1253
1254 case south:
1255 if (deltay < 0)
1256 return false;
1257 break;
1258
1259 case west:
1260 if (deltax > 0)
1261 return false;
1262 break;
1263
1264 // check diagonal moving guards fix
1265
1266 case northwest:
1267 if (DEMOCOND_SDL && deltay > -deltax)
1268 return false;
1269 break;
1270
1271 case northeast:
1272 if (DEMOCOND_SDL && deltay > deltax)
1273 return false;
1274 break;
1275
1276 case southwest:
1277 if (DEMOCOND_SDL && deltax > deltay)
1278 return false;
1279 break;
1280
1281 case southeast:
1282 if (DEMOCOND_SDL && -deltax > deltay)
1283 return false;
1284 break;
1285 }
1286
1287 //
1288 // trace a line to check for blocking tiles (corners)
1289 //
1290 return CheckLine (ob);
1291}
1292
1293
1294/*
1295===============
1296=
1297= FirstSighting
1298=
1299= Puts an actor into attack mode and possibly reverses the direction
1300= if the player is behind it
1301=
1302===============
1303*/
1304
1305void FirstSighting (objtype *ob)
1306{
1307 //
1308 // react to the player
1309 //
1310 switch (ob->obclass)
1311 {
1312 case guardobj:
1313 PlaySoundLocActor(HALTSND,ob);
1314 NewState (ob,&s_grdchase1);
1315 ob->speed *= 3; // go faster when chasing player
1316 break;
1317
1318 case officerobj:
1319 PlaySoundLocActor(SPIONSND,ob);
1320 NewState (ob,&s_ofcchase1);
1321 ob->speed *= 5; // go faster when chasing player
1322 break;
1323
1324 case mutantobj:
1325 NewState (ob,&s_mutchase1);
1326 ob->speed *= 3; // go faster when chasing player
1327 break;
1328
1329 case ssobj:
1330 PlaySoundLocActor(SCHUTZADSND,ob);
1331 NewState (ob,&s_sschase1);
1332 ob->speed *= 4; // go faster when chasing player
1333 break;
1334
1335 case dogobj:
1336 PlaySoundLocActor(DOGBARKSND,ob);
1337 NewState (ob,&s_dogchase1);
1338 ob->speed *= 2; // go faster when chasing player
1339 break;
1340
1341#ifndef SPEAR
1342 case bossobj:
1343 SD_PlaySound(GUTENTAGSND);
1344 NewState (ob,&s_bosschase1);
1345 ob->speed = SPDPATROL*3; // go faster when chasing player
1346 break;
1347
1348#ifndef APOGEE_1_0
1349 case gretelobj:
1350 SD_PlaySound(KEINSND);
1351 NewState (ob,&s_gretelchase1);
1352 ob->speed *= 3; // go faster when chasing player
1353 break;
1354
1355 case giftobj:
1356 SD_PlaySound(EINESND);
1357 NewState (ob,&s_giftchase1);
1358 ob->speed *= 3; // go faster when chasing player
1359 break;
1360
1361 case fatobj:
1362 SD_PlaySound(ERLAUBENSND);
1363 NewState (ob,&s_fatchase1);
1364 ob->speed *= 3; // go faster when chasing player
1365 break;
1366#endif
1367
1368 case schabbobj:
1369 SD_PlaySound(SCHABBSHASND);
1370 NewState (ob,&s_schabbchase1);
1371 ob->speed *= 3; // go faster when chasing player
1372 break;
1373
1374 case fakeobj:
1375 SD_PlaySound(TOT_HUNDSND);
1376 NewState (ob,&s_fakechase1);
1377 ob->speed *= 3; // go faster when chasing player
1378 break;
1379
1380 case mechahitlerobj:
1381 SD_PlaySound(DIESND);
1382 NewState (ob,&s_mechachase1);
1383 ob->speed *= 3; // go faster when chasing player
1384 break;
1385
1386 case realhitlerobj:
1387 SD_PlaySound(DIESND);
1388 NewState (ob,&s_hitlerchase1);
1389 ob->speed *= 5; // go faster when chasing player
1390 break;
1391
1392 case ghostobj:
1393 NewState (ob,&s_blinkychase1);
1394 ob->speed *= 2; // go faster when chasing player
1395 break;
1396#else
1397 case spectreobj:
1398 SD_PlaySound(GHOSTSIGHTSND);
1399 NewState (ob,&s_spectrechase1);
1400 ob->speed = 800; // go faster when chasing player
1401 break;
1402
1403 case angelobj:
1404 SD_PlaySound(ANGELSIGHTSND);
1405 NewState (ob,&s_angelchase1);
1406 ob->speed = 1536; // go faster when chasing player
1407 break;
1408
1409 case transobj:
1410 SD_PlaySound(TRANSSIGHTSND);
1411 NewState (ob,&s_transchase1);
1412 ob->speed = 1536; // go faster when chasing player
1413 break;
1414
1415 case uberobj:
1416 NewState (ob,&s_uberchase1);
1417 ob->speed = 3000; // go faster when chasing player
1418 break;
1419
1420 case willobj:
1421 SD_PlaySound(WILHELMSIGHTSND);
1422 NewState (ob,&s_willchase1);
1423 ob->speed = 2048; // go faster when chasing player
1424 break;
1425
1426 case deathobj:
1427 SD_PlaySound(KNIGHTSIGHTSND);
1428 NewState (ob,&s_deathchase1);
1429 ob->speed = 2048; // go faster when chasing player
1430 break;
1431#endif
1432 }
1433
1434 if (ob->distance < 0)
1435 ob->distance = 0; // ignore the door opening command
1436
1437 ob->flags |= FL_ATTACKMODE|FL_FIRSTATTACK;
1438}
1439
1440
1441
1442/*
1443===============
1444=
1445= SightPlayer
1446=
1447= Called by actors that ARE NOT chasing the player. If the player
1448= is detected (by sight, noise, or proximity), the actor is put into
1449= it's combat frame and true is returned.
1450=
1451= Incorporates a random reaction delay
1452=
1453===============
1454*/
1455
1456boolean SightPlayer (objtype *ob)
1457{
1458 if (ob->flags & FL_ATTACKMODE)
1459 Quit ("An actor in ATTACKMODE called SightPlayer!");
1460
1461 if (ob->temp2)
1462 {
1463 //
1464 // count down reaction time
1465 //
1466 ob->temp2 -= (short) tics;
1467 if (ob->temp2 > 0)
1468 return false;
1469 ob->temp2 = 0; // time to react
1470 }
1471 else
1472 {
1473 if (!areabyplayer[ob->areanumber])
1474 return false;
1475
1476 if (ob->flags & FL_AMBUSH)
1477 {
1478 if (!CheckSight (ob))
1479 return false;
1480 ob->flags &= ~FL_AMBUSH;
1481 }
1482 else
1483 {
1484 if (!madenoise && !CheckSight (ob))
1485 return false;
1486 }
1487
1488
1489 switch (ob->obclass)
1490 {
1491 case guardobj:
1492 ob->temp2 = 1+US_RndT()/4;
1493 break;
1494 case officerobj:
1495 ob->temp2 = 2;
1496 break;
1497 case mutantobj:
1498 ob->temp2 = 1+US_RndT()/6;
1499 break;
1500 case ssobj:
1501 ob->temp2 = 1+US_RndT()/6;
1502 break;
1503 case dogobj:
1504 ob->temp2 = 1+US_RndT()/8;
1505 break;
1506
1507 case bossobj:
1508 case schabbobj:
1509 case fakeobj:
1510 case mechahitlerobj:
1511 case realhitlerobj:
1512 case gretelobj:
1513 case giftobj:
1514 case fatobj:
1515 case spectreobj:
1516 case angelobj:
1517 case transobj:
1518 case uberobj:
1519 case willobj:
1520 case deathobj:
1521 ob->temp2 = 1;
1522 break;
1523 }
1524 return false;
1525 }
1526
1527 FirstSighting (ob);
1528
1529 return true;
1530}