Wolf3D-Mac/Sight.c

1 line
5.0 KiB
C

#include "wolfdef.h"
/**********************************
Returns True if a straight line between the player and actor is unobstructed
**********************************/
Boolean CheckLine(actor_t *ActorPtr)
{
Word actorx,actory,actortx,actorty; /* Current actor's coords */
Word playerx,playery,playertx,playerty; /* Player's coords */
Word xl,xh,yl,yh; /* Min x,y Max x,y for test */
int delta; /* Pixel differance to calc Step and Frac */
int Step; /* Step value for each whole xy */
Word Frac; /* Fractional xy stepper */
Word deltafrac; /* True distance for whole numbers */
Word intercept; /* Temp for door code */
Word tile; /* Temp for tile check */
Byte partial; /* Fraction to force whole numbers */
actorx = ActorPtr->x; /* Get the actor's x,y */
actortx = actorx>>FRACBITS; /* Get the actor's tile x,y */
actory = ActorPtr->y;
actorty = actory>>FRACBITS;
playerx = actors[0].x; /* Get the player's x,y */
playertx = playerx>>FRACBITS; /* Get the player's tile x,y */
playery = actors[0].y;
playerty = playery>>FRACBITS;
/* The actor COULD be standing on a blocked tile (On a CLOSING door tile) */
#if 0
if (tilemap[actorty][actortx] & TI_BLOCKSIGHT) { /* Is the actor IN a wall? */
return FALSE; /* This could happen on a closing door */
}
#endif
/* check for solid tiles at x crossings */
if (playertx!=actortx) { /* Scan in the x direction? */
if (actortx<playertx) {
partial = -actorx; /* Isolate the fraction */
xl = actortx-1; /* Actor is on the left side */
xh = playertx-1;
yl = actory;
yh = playery;
deltafrac = playerx-actorx; /* Distance in pixels */
} else {
partial = -playerx;
xl = playertx; /* Player is on the left side */
xh = actortx;
yl = playery;
yh = actory;
deltafrac = actorx-playerx; /* Distance in pixels */
}
delta = yh-yl; /* Y adjust (Signed) */
if (w_abs(delta) >= (16*FRACUNIT) || deltafrac >= (16*FRACUNIT)) { /* Farther than 16 tiles? */
return FALSE;
}
Step = FixedDiv(delta,deltafrac); /* How much to y step */
Frac = FixedByFrac(Step,partial)+yl; /* Init the Y coord */
do {
++xl;
tile = tilemap[Frac>>FRACBITS][xl]; /* Get the current tile */
if (tile & TI_BLOCKSIGHT) {
return FALSE; /* Can't see! */
}
if (tile & TI_DOOR) { /* see if the door is open enough*/
intercept = ((Step/2)+Frac)&0xff;
if (intercept > doors[tile&TI_NUMMASK].position) {
return FALSE; /* Can't see! */
}
}
Frac += Step;
} while (xl<xh);
}
/* check for solid tiles at y crossings */
if (playerty!=actorty) {
if (actorty<playerty) {
partial = -actory;
xl = actorx;
xh = playerx;
yl = actorty-1;
yh = playerty-1;
deltafrac = playery-actory;
} else {
partial = -playery;
xl = playerx;
xh = actorx;
yl = playerty;
yh = actorty;
deltafrac = actory-playery;
}
delta = xh-xl; /* Number of tiles to scan */
if (w_abs(delta) >= 16*FRACUNIT || deltafrac >= 16*FRACUNIT) {
return FALSE;
}
Step = FixedDiv(delta,deltafrac);
Frac = FixedByFrac(Step,partial)+xl;
do {
++yl;
tile = tilemap[yl][Frac>>FRACBITS];
if (tile & TI_BLOCKSIGHT) {
return FALSE;
}
if (tile & TI_DOOR) { /* see if the door is open enough*/
intercept = ((Step/2)+Frac)&0xff;
if (intercept > doors[tile&TI_NUMMASK].position) {
return FALSE; /* Can't see! */
}
}
Frac += Step;
} while (yl<yh);
}
return TRUE; /* You are visible */
}
/**********************************
Puts actor into attack mode, either after reaction time or being shot
**********************************/
void FirstSighting(actor_t *ActorPtr)
{
classinfo_t *info;
Word sound;
info = &classinfo[ActorPtr->class]; /* Get pointer to info record */
sound = info->sightsound; /* Get the requested sound */
if (sound == SND_ESEE) { /* make random human sound*/
sound = NaziSound[w_rnd()&3]; /* Make a differant sound */
}
PlaySound(sound|0x8000); /* Play the sight sound */
NewState(ActorPtr,info->sightstate); /* Set the next state */
ActorPtr->flags |= FL_ACTIVE; /* Make it active */
}
/**********************************
Called by actors that ARE NOT chasing the player. If the player
is detected (by sight, noise, or proximity), the actor is put into
it's combat frame.
Incorporates a random reaction delay.
**********************************/
void T_Stand(actor_t *ActorPtr)
{
if (ActorPtr->reacttime) { /* Waiting to react? */
if (ActorPtr->reacttime>TicCount) { /* Still waiting? */
ActorPtr->reacttime-=TicCount; /* Count down */
return;
}
if (ActorPtr->flags&FL_AMBUSH ) { /* Ambush actor? */
if (!CheckLine(ActorPtr)) { /* Can I see you? */
ActorPtr->reacttime=1; /* be very ready, but*/
return; /* don't attack yet*/
}
ActorPtr->flags &= ~FL_AMBUSH; /* Clear the ambush flag */
}
FirstSighting(ActorPtr); /* Attack the player! */
ActorPtr->reacttime=0;
}
/* Haven't seen player yet*/
if (madenoise || CheckLine(ActorPtr)) { /* Made a gun shot? Seen? */
ActorPtr->reacttime = (w_rnd() & classinfo[ActorPtr->class].reactionmask)*4+1;
}
}