[docs] Replace cyrillic 'с' with latin 'c' in register names
[kolibrios.git] / contrib / games / wolf3d / wl_state.cpp
blob92b8ca17138243e4335e244db05e0e8698443459
1 // WL_STATE.C
3 #include "wl_def.h"
4 #pragma hdrstop
6 /*
7 =============================================================================
9 LOCAL CONSTANTS
11 =============================================================================
16 =============================================================================
18 GLOBAL VARIABLES
20 =============================================================================
24 static const dirtype opposite[9] =
25 {west,southwest,south,southeast,east,northeast,north,northwest,nodir};
27 static const dirtype diagonal[9][9] =
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}
42 void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state);
43 void NewState (objtype *ob, statetype *state);
45 boolean TryWalk (objtype *ob);
46 void MoveObj (objtype *ob, int32_t move);
48 void KillActor (objtype *ob);
49 void DamageActor (objtype *ob, unsigned damage);
51 boolean CheckLine (objtype *ob);
52 void FirstSighting (objtype *ob);
53 boolean CheckSight (objtype *ob);
56 =============================================================================
58 LOCAL VARIABLES
60 =============================================================================
65 //===========================================================================
69 ===================
71 = SpawnNewObj
73 = Spaws a new actor at the given TILE coordinates, with the given state, and
74 = the given size in GLOBAL units.
76 = newobj = a pointer to an initialized new actor
78 ===================
81 void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state)
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;
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;
98 actorat[tilex][tiley] = newobj;
99 newobj->areanumber =
100 *(mapsegs[0] + (newobj->tiley<<mapshift)+newobj->tilex) - AREATILE;
106 ===================
108 = NewState
110 = Changes ob to a new state, setting ticcount to the max for that state
112 ===================
115 void NewState (objtype *ob, statetype *state)
117 ob->state = state;
118 ob->ticcount = state->tictime;
124 =============================================================================
126 ENEMY TILE WORLD MOVEMENT CODE
128 =============================================================================
133 ==================================
135 = TryWalk
137 = Attempts to move ob in its current (ob->dir) direction.
139 = If blocked by either a wall or an actor returns FALSE
141 = If move is either clear or blocked only by a door, returns TRUE and sets
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
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
153 ==================================
156 #define CHECKDIAG(x,y) \
158 temp=(uintptr_t)actorat[x][y]; \
159 if (temp) \
161 if (temp<256) \
162 return false; \
163 if (((objtype *)temp)->flags&FL_SHOOTABLE) \
164 return false; \
168 #ifdef PLAYDEMOLIKEORIGINAL
169 #define DOORCHECK \
170 if(DEMOCOND_ORIG) \
171 doornum = temp&63; \
172 else \
174 doornum = (int) temp & 127; \
175 OpenDoor(doornum); \
176 ob->distance = -doornum - 1; \
177 return true; \
179 #else
180 #define DOORCHECK \
181 doornum = (int) temp & 127; \
182 OpenDoor(doornum); \
183 ob->distance = -doornum - 1; \
184 return true;
185 #endif
187 #define CHECKSIDE(x,y) \
189 temp=(uintptr_t)actorat[x][y]; \
190 if (temp) \
192 if (temp<128) \
193 return false; \
194 if (temp<256) \
196 DOORCHECK \
198 else if (((objtype *)temp)->flags&FL_SHOOTABLE) \
199 return false; \
204 boolean TryWalk (objtype *ob)
206 int doornum = -1;
207 uintptr_t temp;
209 if (ob->obclass == inertobj)
211 switch (ob->dir)
213 case north:
214 ob->tiley--;
215 break;
217 case northeast:
218 ob->tilex++;
219 ob->tiley--;
220 break;
222 case east:
223 ob->tilex++;
224 break;
226 case southeast:
227 ob->tilex++;
228 ob->tiley++;
229 break;
231 case south:
232 ob->tiley++;
233 break;
235 case southwest:
236 ob->tilex--;
237 ob->tiley++;
238 break;
240 case west:
241 ob->tilex--;
242 break;
244 case northwest:
245 ob->tilex--;
246 ob->tiley--;
247 break;
250 else
252 switch (ob->dir)
254 case north:
255 if (ob->obclass == dogobj || ob->obclass == fakeobj
256 || ob->obclass == ghostobj || ob->obclass == spectreobj)
258 CHECKDIAG(ob->tilex,ob->tiley-1);
260 else
262 CHECKSIDE(ob->tilex,ob->tiley-1);
264 ob->tiley--;
265 break;
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;
275 case east:
276 if (ob->obclass == dogobj || ob->obclass == fakeobj
277 || ob->obclass == ghostobj || ob->obclass == spectreobj)
279 CHECKDIAG(ob->tilex+1,ob->tiley);
281 else
283 CHECKSIDE(ob->tilex+1,ob->tiley);
285 ob->tilex++;
286 break;
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;
296 case south:
297 if (ob->obclass == dogobj || ob->obclass == fakeobj
298 || ob->obclass == ghostobj || ob->obclass == spectreobj)
300 CHECKDIAG(ob->tilex,ob->tiley+1);
302 else
304 CHECKSIDE(ob->tilex,ob->tiley+1);
306 ob->tiley++;
307 break;
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;
317 case west:
318 if (ob->obclass == dogobj || ob->obclass == fakeobj
319 || ob->obclass == ghostobj || ob->obclass == spectreobj)
321 CHECKDIAG(ob->tilex-1,ob->tiley);
323 else
325 CHECKSIDE(ob->tilex-1,ob->tiley);
327 ob->tilex--;
328 break;
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;
338 case nodir:
339 return false;
341 default:
342 Quit ("Walk: Bad dir");
346 #ifdef PLAYDEMOLIKEORIGINAL
347 if (DEMOCOND_ORIG && doornum != -1)
349 OpenDoor(doornum);
350 ob->distance = -doornum-1;
351 return true;
353 #endif
355 ob->areanumber =
356 *(mapsegs[0] + (ob->tiley<<mapshift)+ob->tilex) - AREATILE;
358 ob->distance = TILEGLOBAL;
359 return true;
364 ==================================
366 = SelectDodgeDir
368 = Attempts to choose and initiate a movement for ob that sends it towards
369 = the player while dodging
371 = If there is no possible move (ob is totally surrounded)
373 = ob->dir = nodir
375 = Otherwise
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
383 ==================================
386 void SelectDodgeDir (objtype *ob)
388 int deltax,deltay,i;
389 unsigned absdx,absdy;
390 dirtype dirtry[5];
391 dirtype turnaround,tdir;
393 if (ob->flags & FL_FIRSTATTACK)
396 // turning around is only ok the very first time after noticing the
397 // player
399 turnaround = nodir;
400 ob->flags &= ~FL_FIRSTATTACK;
402 else
403 turnaround=opposite[ob->dir];
405 deltax = player->tilex - ob->tilex;
406 deltay = player->tiley - ob->tiley;
409 // arange 5 direction choices in order of preference
410 // the four cardinal directions plus the diagonal straight towards
411 // the player
414 if (deltax>0)
416 dirtry[1]= east;
417 dirtry[3]= west;
419 else
421 dirtry[1]= west;
422 dirtry[3]= east;
425 if (deltay>0)
427 dirtry[2]= south;
428 dirtry[4]= north;
430 else
432 dirtry[2]= north;
433 dirtry[4]= south;
437 // randomize a bit for dodging
439 absdx = abs(deltax);
440 absdy = abs(deltay);
442 if (absdx > absdy)
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;
452 if (US_RndT() < 128)
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;
462 dirtry[0] = diagonal [ dirtry[1] ] [ dirtry[2] ];
465 // try the directions util one works
467 for (i=0;i<5;i++)
469 if ( dirtry[i] == nodir || dirtry[i] == turnaround)
470 continue;
472 ob->dir = dirtry[i];
473 if (TryWalk(ob))
474 return;
478 // turn around only as a last resort
480 if (turnaround != nodir)
482 ob->dir = turnaround;
484 if (TryWalk(ob))
485 return;
488 ob->dir = nodir;
493 ============================
495 = SelectChaseDir
497 = As SelectDodgeDir, but doesn't try to dodge
499 ============================
502 void SelectChaseDir (objtype *ob)
504 int deltax,deltay;
505 dirtype d[3];
506 dirtype tdir, olddir, turnaround;
509 olddir=ob->dir;
510 turnaround=opposite[olddir];
512 deltax=player->tilex - ob->tilex;
513 deltay=player->tiley - ob->tiley;
515 d[1]=nodir;
516 d[2]=nodir;
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;
527 if (abs(deltay)>abs(deltax))
529 tdir=d[1];
530 d[1]=d[2];
531 d[2]=tdir;
534 if (d[1]==turnaround)
535 d[1]=nodir;
536 if (d[2]==turnaround)
537 d[2]=nodir;
540 if (d[1]!=nodir)
542 ob->dir=d[1];
543 if (TryWalk(ob))
544 return; /*either moved forward or attacked*/
547 if (d[2]!=nodir)
549 ob->dir=d[2];
550 if (TryWalk(ob))
551 return;
554 /* there is no direct path to the player, so pick another direction */
556 if (olddir!=nodir)
558 ob->dir=olddir;
559 if (TryWalk(ob))
560 return;
563 if (US_RndT()>128) /*randomly determine direction of search*/
565 for (tdir=north; tdir<=west; tdir=(dirtype)(tdir+1))
567 if (tdir!=turnaround)
569 ob->dir=tdir;
570 if ( TryWalk(ob) )
571 return;
575 else
577 for (tdir=west; tdir>=north; tdir=(dirtype)(tdir-1))
579 if (tdir!=turnaround)
581 ob->dir=tdir;
582 if ( TryWalk(ob) )
583 return;
588 if (turnaround != nodir)
590 ob->dir=turnaround;
591 if (ob->dir != nodir)
593 if ( TryWalk(ob) )
594 return;
598 ob->dir = nodir; // can't move
603 ============================
605 = SelectRunDir
607 = Run Away from player
609 ============================
612 void SelectRunDir (objtype *ob)
614 int deltax,deltay;
615 dirtype d[3];
616 dirtype tdir;
619 deltax=player->tilex - ob->tilex;
620 deltay=player->tiley - ob->tiley;
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;
631 if (abs(deltay)>abs(deltax))
633 tdir=d[1];
634 d[1]=d[2];
635 d[2]=tdir;
638 ob->dir=d[1];
639 if (TryWalk(ob))
640 return; /*either moved forward or attacked*/
642 ob->dir=d[2];
643 if (TryWalk(ob))
644 return;
646 /* there is no direct path to the player, so pick another direction */
648 if (US_RndT()>128) /*randomly determine direction of search*/
650 for (tdir=north; tdir<=west; tdir=(dirtype)(tdir+1))
652 ob->dir=tdir;
653 if ( TryWalk(ob) )
654 return;
657 else
659 for (tdir=west; tdir>=north; tdir=(dirtype)(tdir-1))
661 ob->dir=tdir;
662 if ( TryWalk(ob) )
663 return;
667 ob->dir = nodir; // can't move
672 =================
674 = MoveObj
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
680 = ob->x = adjusted for new position
681 = ob->y
683 =================
686 void MoveObj (objtype *ob, int32_t move)
688 int32_t deltax,deltay;
690 switch (ob->dir)
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;
721 case nodir:
722 return;
724 default:
725 Quit ("MoveObj: bad dir!");
729 // check to make sure it's not on top of player
731 if (areabyplayer[ob->areanumber])
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;
740 if (ob->hidden) // move closer until he meets CheckLine
741 goto moveok;
743 if (ob->obclass == ghostobj || ob->obclass == spectreobj)
744 TakeDamage (tics*2,ob);
747 // back up
749 switch (ob->dir)
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;
780 case nodir:
781 return;
783 return;
785 moveok:
786 ob->distance -=move;
790 =============================================================================
792 STUFF
794 =============================================================================
798 ===============
800 = DropItem
802 = Tries to drop a bonus item somewhere in the tiles surrounding the
803 = given tilex/tiley
805 ===============
808 void DropItem (wl_stat_t itemtype, int tilex, int tiley)
810 int x,y,xl,xh,yl,yh;
813 // find a free spot to put it in
815 if (!actorat[tilex][tiley])
817 PlaceItemType (itemtype, tilex,tiley);
818 return;
821 xl = tilex-1;
822 xh = tilex+1;
823 yl = tiley-1;
824 yh = tiley+1;
826 for (x=xl ; x<= xh ; x++)
828 for (y=yl ; y<= yh ; y++)
830 if (!actorat[x][y])
832 PlaceItemType (itemtype, x,y);
833 return;
842 ===============
844 = KillActor
846 ===============
849 void KillActor (objtype *ob)
851 int tilex,tiley;
853 tilex = ob->tilex = (word)(ob->x >> TILESHIFT); // drop item on center
854 tiley = ob->tiley = (word)(ob->y >> TILESHIFT);
856 switch (ob->obclass)
858 case guardobj:
859 GivePoints (100);
860 NewState (ob,&s_grddie1);
861 PlaceItemType (bo_clip2,tilex,tiley);
862 break;
864 case officerobj:
865 GivePoints (400);
866 NewState (ob,&s_ofcdie1);
867 PlaceItemType (bo_clip2,tilex,tiley);
868 break;
870 case mutantobj:
871 GivePoints (700);
872 NewState (ob,&s_mutdie1);
873 PlaceItemType (bo_clip2,tilex,tiley);
874 break;
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;
885 case dogobj:
886 GivePoints (200);
887 NewState (ob,&s_dogdie1);
888 break;
890 #ifndef SPEAR
891 case bossobj:
892 GivePoints (5000);
893 NewState (ob,&s_bossdie1);
894 PlaceItemType (bo_key1,tilex,tiley);
895 break;
897 case gretelobj:
898 GivePoints (5000);
899 NewState (ob,&s_greteldie1);
900 PlaceItemType (bo_key1,tilex,tiley);
901 break;
903 case giftobj:
904 GivePoints (5000);
905 gamestate.killx = player->x;
906 gamestate.killy = player->y;
907 NewState (ob,&s_giftdie1);
908 break;
910 case fatobj:
911 GivePoints (5000);
912 gamestate.killx = player->x;
913 gamestate.killy = player->y;
914 NewState (ob,&s_fatdie1);
915 break;
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;
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)
942 GivePoints (200); // Get points once for each
943 ob->flags &= ~FL_BONUS;
945 NewState (ob,&s_spectredie1);
946 break;
948 case angelobj:
949 GivePoints (5000);
950 NewState (ob,&s_angeldie1);
951 break;
953 case transobj:
954 GivePoints (5000);
955 NewState (ob,&s_transdie0);
956 PlaceItemType (bo_key1,tilex,tiley);
957 break;
959 case uberobj:
960 GivePoints (5000);
961 NewState (ob,&s_uberdie0);
962 PlaceItemType (bo_key1,tilex,tiley);
963 break;
965 case willobj:
966 GivePoints (5000);
967 NewState (ob,&s_willdie1);
968 PlaceItemType (bo_key1,tilex,tiley);
969 break;
971 case deathobj:
972 GivePoints (5000);
973 NewState (ob,&s_deathdie1);
974 PlaceItemType (bo_key1,tilex,tiley);
975 break;
976 #endif
979 gamestate.killcount++;
980 ob->flags &= ~FL_SHOOTABLE;
981 actorat[ob->tilex][ob->tiley] = NULL;
982 ob->flags |= FL_NONMARK;
988 ===================
990 = DamageActor
992 = Called when the player succesfully hits an enemy.
994 = Does damage points to enemy ob, either putting it into a stun frame or
995 = killing it.
997 ===================
1000 void DamageActor (objtype *ob, unsigned damage)
1002 madenoise = true;
1005 // do double damage if shooting a non attack mode actor
1007 if ( !(ob->flags & FL_ATTACKMODE) )
1008 damage <<= 1;
1010 ob->hitpoints -= (short)damage;
1012 if (ob->hitpoints<=0)
1013 KillActor (ob);
1014 else
1016 if (! (ob->flags & FL_ATTACKMODE) )
1017 FirstSighting (ob); // put into combat mode
1019 switch (ob->obclass) // dogs only have one hit point
1021 case guardobj:
1022 if (ob->hitpoints&1)
1023 NewState (ob,&s_grdpain);
1024 else
1025 NewState (ob,&s_grdpain1);
1026 break;
1028 case officerobj:
1029 if (ob->hitpoints&1)
1030 NewState (ob,&s_ofcpain);
1031 else
1032 NewState (ob,&s_ofcpain1);
1033 break;
1035 case mutantobj:
1036 if (ob->hitpoints&1)
1037 NewState (ob,&s_mutpain);
1038 else
1039 NewState (ob,&s_mutpain1);
1040 break;
1042 case ssobj:
1043 if (ob->hitpoints&1)
1044 NewState (ob,&s_sspain);
1045 else
1046 NewState (ob,&s_sspain1);
1048 break;
1054 =============================================================================
1056 CHECKSIGHT
1058 =============================================================================
1063 =====================
1065 = CheckLine
1067 = Returns true if a straight line between the player and ob is unobstructed
1069 =====================
1072 boolean CheckLine (objtype *ob)
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;
1082 x1 = ob->x >> UNSIGNEDSHIFT; // 1/256 tile precision
1083 y1 = ob->y >> UNSIGNEDSHIFT;
1084 xt1 = x1 >> 8;
1085 yt1 = y1 >> 8;
1087 x2 = plux;
1088 y2 = pluy;
1089 xt2 = player->tilex;
1090 yt2 = player->tiley;
1092 xdist = abs(xt2-xt1);
1094 if (xdist > 0)
1096 if (xt2 > xt1)
1098 partial = 256-(x1&0xff);
1099 xstep = 1;
1101 else
1103 partial = x1&0xff;
1104 xstep = -1;
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);
1118 x = xt1+xstep;
1119 xt2 += xstep;
1122 y = yfrac>>8;
1123 yfrac += ystep;
1125 value = (unsigned)tilemap[x][y];
1126 x += xstep;
1128 if (!value)
1129 continue;
1131 if (value<128 || value>256)
1132 return false;
1135 // see if the door is open enough
1137 value &= ~0x80;
1138 intercept = yfrac-ystep/2;
1140 if (intercept>doorposition[value])
1141 return false;
1143 } while (x != xt2);
1146 ydist = abs(yt2-yt1);
1148 if (ydist > 0)
1150 if (yt2 > yt1)
1152 partial = 256-(y1&0xff);
1153 ystep = 1;
1155 else
1157 partial = y1&0xff;
1158 ystep = -1;
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);
1172 y = yt1 + ystep;
1173 yt2 += ystep;
1176 x = xfrac>>8;
1177 xfrac += xstep;
1179 value = (unsigned)tilemap[x][y];
1180 y += ystep;
1182 if (!value)
1183 continue;
1185 if (value<128 || value>256)
1186 return false;
1189 // see if the door is open enough
1191 value &= ~0x80;
1192 intercept = xfrac-xstep/2;
1194 if (intercept>doorposition[value])
1195 return false;
1196 } while (y != yt2);
1199 return true;
1204 ================
1206 = CheckSight
1208 = Checks a straight line between player and current object
1210 = If the sight is ok, check alertness and angle to see if they notice
1212 = returns true if the player has been spoted
1214 ================
1217 #define MINSIGHT 0x18000l
1219 boolean CheckSight (objtype *ob)
1221 int32_t deltax,deltay;
1224 // don't bother tracing a line if the area isn't connected to the player's
1226 if (!areabyplayer[ob->areanumber])
1227 return false;
1230 // if the player is real close, sight is automatic
1232 deltax = player->x - ob->x;
1233 deltay = player->y - ob->y;
1235 if (deltax > -MINSIGHT && deltax < MINSIGHT
1236 && deltay > -MINSIGHT && deltay < MINSIGHT)
1237 return true;
1240 // see if they are looking in the right direction
1242 switch (ob->dir)
1244 case north:
1245 if (deltay > 0)
1246 return false;
1247 break;
1249 case east:
1250 if (deltax < 0)
1251 return false;
1252 break;
1254 case south:
1255 if (deltay < 0)
1256 return false;
1257 break;
1259 case west:
1260 if (deltax > 0)
1261 return false;
1262 break;
1264 // check diagonal moving guards fix
1266 case northwest:
1267 if (DEMOCOND_SDL && deltay > -deltax)
1268 return false;
1269 break;
1271 case northeast:
1272 if (DEMOCOND_SDL && deltay > deltax)
1273 return false;
1274 break;
1276 case southwest:
1277 if (DEMOCOND_SDL && deltax > deltay)
1278 return false;
1279 break;
1281 case southeast:
1282 if (DEMOCOND_SDL && -deltax > deltay)
1283 return false;
1284 break;
1288 // trace a line to check for blocking tiles (corners)
1290 return CheckLine (ob);
1295 ===============
1297 = FirstSighting
1299 = Puts an actor into attack mode and possibly reverses the direction
1300 = if the player is behind it
1302 ===============
1305 void FirstSighting (objtype *ob)
1308 // react to the player
1310 switch (ob->obclass)
1312 case guardobj:
1313 PlaySoundLocActor(HALTSND,ob);
1314 NewState (ob,&s_grdchase1);
1315 ob->speed *= 3; // go faster when chasing player
1316 break;
1318 case officerobj:
1319 PlaySoundLocActor(SPIONSND,ob);
1320 NewState (ob,&s_ofcchase1);
1321 ob->speed *= 5; // go faster when chasing player
1322 break;
1324 case mutantobj:
1325 NewState (ob,&s_mutchase1);
1326 ob->speed *= 3; // go faster when chasing player
1327 break;
1329 case ssobj:
1330 PlaySoundLocActor(SCHUTZADSND,ob);
1331 NewState (ob,&s_sschase1);
1332 ob->speed *= 4; // go faster when chasing player
1333 break;
1335 case dogobj:
1336 PlaySoundLocActor(DOGBARKSND,ob);
1337 NewState (ob,&s_dogchase1);
1338 ob->speed *= 2; // go faster when chasing player
1339 break;
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;
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;
1355 case giftobj:
1356 SD_PlaySound(EINESND);
1357 NewState (ob,&s_giftchase1);
1358 ob->speed *= 3; // go faster when chasing player
1359 break;
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
1368 case schabbobj:
1369 SD_PlaySound(SCHABBSHASND);
1370 NewState (ob,&s_schabbchase1);
1371 ob->speed *= 3; // go faster when chasing player
1372 break;
1374 case fakeobj:
1375 SD_PlaySound(TOT_HUNDSND);
1376 NewState (ob,&s_fakechase1);
1377 ob->speed *= 3; // go faster when chasing player
1378 break;
1380 case mechahitlerobj:
1381 SD_PlaySound(DIESND);
1382 NewState (ob,&s_mechachase1);
1383 ob->speed *= 3; // go faster when chasing player
1384 break;
1386 case realhitlerobj:
1387 SD_PlaySound(DIESND);
1388 NewState (ob,&s_hitlerchase1);
1389 ob->speed *= 5; // go faster when chasing player
1390 break;
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;
1403 case angelobj:
1404 SD_PlaySound(ANGELSIGHTSND);
1405 NewState (ob,&s_angelchase1);
1406 ob->speed = 1536; // go faster when chasing player
1407 break;
1409 case transobj:
1410 SD_PlaySound(TRANSSIGHTSND);
1411 NewState (ob,&s_transchase1);
1412 ob->speed = 1536; // go faster when chasing player
1413 break;
1415 case uberobj:
1416 NewState (ob,&s_uberchase1);
1417 ob->speed = 3000; // go faster when chasing player
1418 break;
1420 case willobj:
1421 SD_PlaySound(WILHELMSIGHTSND);
1422 NewState (ob,&s_willchase1);
1423 ob->speed = 2048; // go faster when chasing player
1424 break;
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
1434 if (ob->distance < 0)
1435 ob->distance = 0; // ignore the door opening command
1437 ob->flags |= FL_ATTACKMODE|FL_FIRSTATTACK;
1443 ===============
1445 = SightPlayer
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.
1451 = Incorporates a random reaction delay
1453 ===============
1456 boolean SightPlayer (objtype *ob)
1458 if (ob->flags & FL_ATTACKMODE)
1459 Quit ("An actor in ATTACKMODE called SightPlayer!");
1461 if (ob->temp2)
1464 // count down reaction time
1466 ob->temp2 -= (short) tics;
1467 if (ob->temp2 > 0)
1468 return false;
1469 ob->temp2 = 0; // time to react
1471 else
1473 if (!areabyplayer[ob->areanumber])
1474 return false;
1476 if (ob->flags & FL_AMBUSH)
1478 if (!CheckSight (ob))
1479 return false;
1480 ob->flags &= ~FL_AMBUSH;
1482 else
1484 if (!madenoise && !CheckSight (ob))
1485 return false;
1489 switch (ob->obclass)
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;
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;
1524 return false;
1527 FirstSighting (ob);
1529 return true;