1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#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;
}
}