7 =============================================================================
11 =============================================================================
16 =============================================================================
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 =============================================================================
60 =============================================================================
65 //===========================================================================
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
81 void SpawnNewObj (unsigned tilex
, unsigned tiley
, statetype
*state
)
84 newobj
->state
= state
;
86 newobj
->ticcount
= DEMOCHOOSE_ORIG_SDL(
87 US_RndT () % state
->tictime
,
88 US_RndT () % state
->tictime
+ 1); // Chris' moonwalk bugfix ;D
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;
98 actorat
[tilex
][tiley
] = newobj
;
100 *(mapsegs
[0] + (newobj
->tiley
<<mapshift
)+newobj
->tilex
) - AREATILE
;
110 = Changes ob to a new state, setting ticcount to the max for that state
115 void NewState (objtype
*ob
, statetype
*state
)
118 ob
->ticcount
= state
->tictime
;
124 =============================================================================
126 ENEMY TILE WORLD MOVEMENT CODE
128 =============================================================================
133 ==================================
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
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
153 ==================================
156 #define CHECKDIAG(x,y) \
158 temp=(uintptr_t)actorat[x][y]; \
163 if (((objtype *)temp)->flags&FL_SHOOTABLE) \
168 #ifdef PLAYDEMOLIKEORIGINAL
174 doornum = (int) temp & 127; \
176 ob->distance = -doornum - 1; \
181 doornum = (int) temp & 127; \
183 ob->distance = -doornum - 1; \
187 #define CHECKSIDE(x,y) \
189 temp=(uintptr_t)actorat[x][y]; \
198 else if (((objtype *)temp)->flags&FL_SHOOTABLE) \
204 boolean
TryWalk (objtype
*ob
)
209 if (ob
->obclass
== inertobj
)
255 if (ob
->obclass
== dogobj
|| ob
->obclass
== fakeobj
256 || ob
->obclass
== ghostobj
|| ob
->obclass
== spectreobj
)
258 CHECKDIAG(ob
->tilex
,ob
->tiley
-1);
262 CHECKSIDE(ob
->tilex
,ob
->tiley
-1);
268 CHECKDIAG(ob
->tilex
+1,ob
->tiley
-1);
269 CHECKDIAG(ob
->tilex
+1,ob
->tiley
);
270 CHECKDIAG(ob
->tilex
,ob
->tiley
-1);
276 if (ob
->obclass
== dogobj
|| ob
->obclass
== fakeobj
277 || ob
->obclass
== ghostobj
|| ob
->obclass
== spectreobj
)
279 CHECKDIAG(ob
->tilex
+1,ob
->tiley
);
283 CHECKSIDE(ob
->tilex
+1,ob
->tiley
);
289 CHECKDIAG(ob
->tilex
+1,ob
->tiley
+1);
290 CHECKDIAG(ob
->tilex
+1,ob
->tiley
);
291 CHECKDIAG(ob
->tilex
,ob
->tiley
+1);
297 if (ob
->obclass
== dogobj
|| ob
->obclass
== fakeobj
298 || ob
->obclass
== ghostobj
|| ob
->obclass
== spectreobj
)
300 CHECKDIAG(ob
->tilex
,ob
->tiley
+1);
304 CHECKSIDE(ob
->tilex
,ob
->tiley
+1);
310 CHECKDIAG(ob
->tilex
-1,ob
->tiley
+1);
311 CHECKDIAG(ob
->tilex
-1,ob
->tiley
);
312 CHECKDIAG(ob
->tilex
,ob
->tiley
+1);
318 if (ob
->obclass
== dogobj
|| ob
->obclass
== fakeobj
319 || ob
->obclass
== ghostobj
|| ob
->obclass
== spectreobj
)
321 CHECKDIAG(ob
->tilex
-1,ob
->tiley
);
325 CHECKSIDE(ob
->tilex
-1,ob
->tiley
);
331 CHECKDIAG(ob
->tilex
-1,ob
->tiley
-1);
332 CHECKDIAG(ob
->tilex
-1,ob
->tiley
);
333 CHECKDIAG(ob
->tilex
,ob
->tiley
-1);
342 Quit ("Walk: Bad dir");
346 #ifdef PLAYDEMOLIKEORIGINAL
347 if (DEMOCOND_ORIG
&& doornum
!= -1)
350 ob
->distance
= -doornum
-1;
356 *(mapsegs
[0] + (ob
->tiley
<<mapshift
)+ob
->tilex
) - AREATILE
;
358 ob
->distance
= TILEGLOBAL
;
364 ==================================
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)
377 = ob->dir = new direction to follow
378 = ob->distance = TILEGLOBAL or -doornumber
379 = ob->tilex = new destination
381 = ob->areanumber = the floor tile number (0-(NUMAREAS-1)) of destination
383 ==================================
386 void SelectDodgeDir (objtype
*ob
)
389 unsigned absdx
,absdy
;
391 dirtype turnaround
,tdir
;
393 if (ob
->flags
& FL_FIRSTATTACK
)
396 // turning around is only ok the very first time after noticing the
400 ob
->flags
&= ~FL_FIRSTATTACK
;
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
437 // randomize a bit for dodging
445 dirtry
[1] = dirtry
[2];
448 dirtry
[3] = dirtry
[4];
455 dirtry
[1] = dirtry
[2];
458 dirtry
[3] = dirtry
[4];
462 dirtry
[0] = diagonal
[ dirtry
[1] ] [ dirtry
[2] ];
465 // try the directions util one works
469 if ( dirtry
[i
] == nodir
|| dirtry
[i
] == turnaround
)
478 // turn around only as a last resort
480 if (turnaround
!= nodir
)
482 ob
->dir
= turnaround
;
493 ============================
497 = As SelectDodgeDir, but doesn't try to dodge
499 ============================
502 void SelectChaseDir (objtype
*ob
)
506 dirtype tdir
, olddir
, turnaround
;
510 turnaround
=opposite
[olddir
];
512 deltax
=player
->tilex
- ob
->tilex
;
513 deltay
=player
->tiley
- ob
->tiley
;
527 if (abs(deltay
)>abs(deltax
))
534 if (d
[1]==turnaround
)
536 if (d
[2]==turnaround
)
544 return; /*either moved forward or attacked*/
554 /* there is no direct path to the player, so pick another direction */
563 if (US_RndT()>128) /*randomly determine direction of search*/
565 for (tdir
=north
; tdir
<=west
; tdir
=(dirtype
)(tdir
+1))
567 if (tdir
!=turnaround
)
577 for (tdir
=west
; tdir
>=north
; tdir
=(dirtype
)(tdir
-1))
579 if (tdir
!=turnaround
)
588 if (turnaround
!= nodir
)
591 if (ob
->dir
!= nodir
)
598 ob
->dir
= nodir
; // can't move
603 ============================
607 = Run Away from player
609 ============================
612 void SelectRunDir (objtype
*ob
)
619 deltax
=player
->tilex
- ob
->tilex
;
620 deltay
=player
->tiley
- ob
->tiley
;
631 if (abs(deltay
)>abs(deltax
))
640 return; /*either moved forward or attacked*/
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))
659 for (tdir
=west
; tdir
>=north
; tdir
=(dirtype
)(tdir
-1))
667 ob
->dir
= nodir
; // can't move
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
686 void MoveObj (objtype
*ob
, int32_t move
)
688 int32_t deltax
,deltay
;
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
)
736 deltay
= ob
->y
- player
->y
;
737 if (deltay
< -MINACTORDIST
|| deltay
> MINACTORDIST
)
740 if (ob
->hidden
) // move closer until he meets CheckLine
743 if (ob
->obclass
== ghostobj
|| ob
->obclass
== spectreobj
)
744 TakeDamage (tics
*2,ob
);
790 =============================================================================
794 =============================================================================
802 = Tries to drop a bonus item somewhere in the tiles surrounding the
808 void DropItem (wl_stat_t itemtype
, int tilex
, int tiley
)
813 // find a free spot to put it in
815 if (!actorat
[tilex
][tiley
])
817 PlaceItemType (itemtype
, tilex
,tiley
);
826 for (x
=xl
; x
<= xh
; x
++)
828 for (y
=yl
; y
<= yh
; y
++)
832 PlaceItemType (itemtype
, x
,y
);
849 void KillActor (objtype
*ob
)
853 tilex
= ob
->tilex
= (word
)(ob
->x
>> TILESHIFT
); // drop item on center
854 tiley
= ob
->tiley
= (word
)(ob
->y
>> TILESHIFT
);
860 NewState (ob
,&s_grddie1
);
861 PlaceItemType (bo_clip2
,tilex
,tiley
);
866 NewState (ob
,&s_ofcdie1
);
867 PlaceItemType (bo_clip2
,tilex
,tiley
);
872 NewState (ob
,&s_mutdie1
);
873 PlaceItemType (bo_clip2
,tilex
,tiley
);
878 NewState (ob
,&s_ssdie1
);
879 if (gamestate
.bestweapon
< wp_machinegun
)
880 PlaceItemType (bo_machinegun
,tilex
,tiley
);
882 PlaceItemType (bo_clip2
,tilex
,tiley
);
887 NewState (ob
,&s_dogdie1
);
893 NewState (ob
,&s_bossdie1
);
894 PlaceItemType (bo_key1
,tilex
,tiley
);
899 NewState (ob
,&s_greteldie1
);
900 PlaceItemType (bo_key1
,tilex
,tiley
);
905 gamestate
.killx
= player
->x
;
906 gamestate
.killy
= player
->y
;
907 NewState (ob
,&s_giftdie1
);
912 gamestate
.killx
= player
->x
;
913 gamestate
.killy
= player
->y
;
914 NewState (ob
,&s_fatdie1
);
919 gamestate
.killx
= player
->x
;
920 gamestate
.killy
= player
->y
;
921 NewState (ob
,&s_schabbdie1
);
925 NewState (ob
,&s_fakedie1
);
930 NewState (ob
,&s_mechadie1
);
934 gamestate
.killx
= player
->x
;
935 gamestate
.killy
= player
->y
;
936 NewState (ob
,&s_hitlerdie1
);
940 if (ob
->flags
&FL_BONUS
)
942 GivePoints (200); // Get points once for each
943 ob
->flags
&= ~FL_BONUS
;
945 NewState (ob
,&s_spectredie1
);
950 NewState (ob
,&s_angeldie1
);
955 NewState (ob
,&s_transdie0
);
956 PlaceItemType (bo_key1
,tilex
,tiley
);
961 NewState (ob
,&s_uberdie0
);
962 PlaceItemType (bo_key1
,tilex
,tiley
);
967 NewState (ob
,&s_willdie1
);
968 PlaceItemType (bo_key1
,tilex
,tiley
);
973 NewState (ob
,&s_deathdie1
);
974 PlaceItemType (bo_key1
,tilex
,tiley
);
979 gamestate
.killcount
++;
980 ob
->flags
&= ~FL_SHOOTABLE
;
981 actorat
[ob
->tilex
][ob
->tiley
] = NULL
;
982 ob
->flags
|= FL_NONMARK
;
992 = Called when the player succesfully hits an enemy.
994 = Does damage points to enemy ob, either putting it into a stun frame or
1000 void DamageActor (objtype
*ob
, unsigned damage
)
1005 // do double damage if shooting a non attack mode actor
1007 if ( !(ob
->flags
& FL_ATTACKMODE
) )
1010 ob
->hitpoints
-= (short)damage
;
1012 if (ob
->hitpoints
<=0)
1016 if (! (ob
->flags
& FL_ATTACKMODE
) )
1017 FirstSighting (ob
); // put into combat mode
1019 switch (ob
->obclass
) // dogs only have one hit point
1022 if (ob
->hitpoints
&1)
1023 NewState (ob
,&s_grdpain
);
1025 NewState (ob
,&s_grdpain1
);
1029 if (ob
->hitpoints
&1)
1030 NewState (ob
,&s_ofcpain
);
1032 NewState (ob
,&s_ofcpain1
);
1036 if (ob
->hitpoints
&1)
1037 NewState (ob
,&s_mutpain
);
1039 NewState (ob
,&s_mutpain1
);
1043 if (ob
->hitpoints
&1)
1044 NewState (ob
,&s_sspain
);
1046 NewState (ob
,&s_sspain1
);
1054 =============================================================================
1058 =============================================================================
1063 =====================
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
;
1076 int xdist
,ydist
,xstep
,ystep
;
1079 int xfrac
,yfrac
,deltafrac
;
1080 unsigned value
,intercept
;
1082 x1
= ob
->x
>> UNSIGNEDSHIFT
; // 1/256 tile precision
1083 y1
= ob
->y
>> UNSIGNEDSHIFT
;
1089 xt2
= player
->tilex
;
1090 yt2
= player
->tiley
;
1092 xdist
= abs(xt2
-xt1
);
1098 partial
= 256-(x1
&0xff);
1107 deltafrac
= abs(x2
-x1
);
1109 ltemp
= ((int32_t)delta
<<8)/deltafrac
;
1110 if (ltemp
> 0x7fffl
)
1112 else if (ltemp
< -0x7fffl
)
1116 yfrac
= y1
+ (((int32_t)ystep
*partial
) >>8);
1125 value
= (unsigned)tilemap
[x
][y
];
1131 if (value
<128 || value
>256)
1135 // see if the door is open enough
1138 intercept
= yfrac
-ystep
/2;
1140 if (intercept
>doorposition
[value
])
1146 ydist
= abs(yt2
-yt1
);
1152 partial
= 256-(y1
&0xff);
1161 deltafrac
= abs(y2
-y1
);
1163 ltemp
= ((int32_t)delta
<<8)/deltafrac
;
1164 if (ltemp
> 0x7fffl
)
1166 else if (ltemp
< -0x7fffl
)
1170 xfrac
= x1
+ (((int32_t)xstep
*partial
) >>8);
1179 value
= (unsigned)tilemap
[x
][y
];
1185 if (value
<128 || value
>256)
1189 // see if the door is open enough
1192 intercept
= xfrac
-xstep
/2;
1194 if (intercept
>doorposition
[value
])
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
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
])
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
)
1240 // see if they are looking in the right direction
1264 // check diagonal moving guards fix
1267 if (DEMOCOND_SDL
&& deltay
> -deltax
)
1272 if (DEMOCOND_SDL
&& deltay
> deltax
)
1277 if (DEMOCOND_SDL
&& deltax
> deltay
)
1282 if (DEMOCOND_SDL
&& -deltax
> deltay
)
1288 // trace a line to check for blocking tiles (corners)
1290 return CheckLine (ob
);
1299 = Puts an actor into attack mode and possibly reverses the direction
1300 = if the player is behind it
1305 void FirstSighting (objtype
*ob
)
1308 // react to the player
1310 switch (ob
->obclass
)
1313 PlaySoundLocActor(HALTSND
,ob
);
1314 NewState (ob
,&s_grdchase1
);
1315 ob
->speed
*= 3; // go faster when chasing player
1319 PlaySoundLocActor(SPIONSND
,ob
);
1320 NewState (ob
,&s_ofcchase1
);
1321 ob
->speed
*= 5; // go faster when chasing player
1325 NewState (ob
,&s_mutchase1
);
1326 ob
->speed
*= 3; // go faster when chasing player
1330 PlaySoundLocActor(SCHUTZADSND
,ob
);
1331 NewState (ob
,&s_sschase1
);
1332 ob
->speed
*= 4; // go faster when chasing player
1336 PlaySoundLocActor(DOGBARKSND
,ob
);
1337 NewState (ob
,&s_dogchase1
);
1338 ob
->speed
*= 2; // go faster when chasing player
1343 SD_PlaySound(GUTENTAGSND
);
1344 NewState (ob
,&s_bosschase1
);
1345 ob
->speed
= SPDPATROL
*3; // go faster when chasing player
1350 SD_PlaySound(KEINSND
);
1351 NewState (ob
,&s_gretelchase1
);
1352 ob
->speed
*= 3; // go faster when chasing player
1356 SD_PlaySound(EINESND
);
1357 NewState (ob
,&s_giftchase1
);
1358 ob
->speed
*= 3; // go faster when chasing player
1362 SD_PlaySound(ERLAUBENSND
);
1363 NewState (ob
,&s_fatchase1
);
1364 ob
->speed
*= 3; // go faster when chasing player
1369 SD_PlaySound(SCHABBSHASND
);
1370 NewState (ob
,&s_schabbchase1
);
1371 ob
->speed
*= 3; // go faster when chasing player
1375 SD_PlaySound(TOT_HUNDSND
);
1376 NewState (ob
,&s_fakechase1
);
1377 ob
->speed
*= 3; // go faster when chasing player
1380 case mechahitlerobj
:
1381 SD_PlaySound(DIESND
);
1382 NewState (ob
,&s_mechachase1
);
1383 ob
->speed
*= 3; // go faster when chasing player
1387 SD_PlaySound(DIESND
);
1388 NewState (ob
,&s_hitlerchase1
);
1389 ob
->speed
*= 5; // go faster when chasing player
1393 NewState (ob
,&s_blinkychase1
);
1394 ob
->speed
*= 2; // go faster when chasing player
1398 SD_PlaySound(GHOSTSIGHTSND
);
1399 NewState (ob
,&s_spectrechase1
);
1400 ob
->speed
= 800; // go faster when chasing player
1404 SD_PlaySound(ANGELSIGHTSND
);
1405 NewState (ob
,&s_angelchase1
);
1406 ob
->speed
= 1536; // go faster when chasing player
1410 SD_PlaySound(TRANSSIGHTSND
);
1411 NewState (ob
,&s_transchase1
);
1412 ob
->speed
= 1536; // go faster when chasing player
1416 NewState (ob
,&s_uberchase1
);
1417 ob
->speed
= 3000; // go faster when chasing player
1421 SD_PlaySound(WILHELMSIGHTSND
);
1422 NewState (ob
,&s_willchase1
);
1423 ob
->speed
= 2048; // go faster when chasing player
1427 SD_PlaySound(KNIGHTSIGHTSND
);
1428 NewState (ob
,&s_deathchase1
);
1429 ob
->speed
= 2048; // go faster when chasing player
1434 if (ob
->distance
< 0)
1435 ob
->distance
= 0; // ignore the door opening command
1437 ob
->flags
|= FL_ATTACKMODE
|FL_FIRSTATTACK
;
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
1456 boolean
SightPlayer (objtype
*ob
)
1458 if (ob
->flags
& FL_ATTACKMODE
)
1459 Quit ("An actor in ATTACKMODE called SightPlayer!");
1464 // count down reaction time
1466 ob
->temp2
-= (short) tics
;
1469 ob
->temp2
= 0; // time to react
1473 if (!areabyplayer
[ob
->areanumber
])
1476 if (ob
->flags
& FL_AMBUSH
)
1478 if (!CheckSight (ob
))
1480 ob
->flags
&= ~FL_AMBUSH
;
1484 if (!madenoise
&& !CheckSight (ob
))
1489 switch (ob
->obclass
)
1492 ob
->temp2
= 1+US_RndT()/4;
1498 ob
->temp2
= 1+US_RndT()/6;
1501 ob
->temp2
= 1+US_RndT()/6;
1504 ob
->temp2
= 1+US_RndT()/8;
1510 case mechahitlerobj
: