1 /* Catacomb 3-D Source Code
\r
2 * Copyright (C) 1993-2014 Flat Rock Software
\r
4 * This program is free software; you can redistribute it and/or modify
\r
5 * it under the terms of the GNU General Public License as published by
\r
6 * the Free Software Foundation; either version 2 of the License, or
\r
7 * (at your option) any later version.
\r
9 * This program is distributed in the hope that it will be useful,
\r
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 * GNU General Public License for more details.
\r
14 * You should have received a copy of the GNU General Public License along
\r
15 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
25 =============================================================================
\r
29 =============================================================================
\r
34 =============================================================================
\r
38 =============================================================================
\r
44 =============================================================================
\r
48 =============================================================================
\r
52 dirtype opposite[9] =
\r
53 {south,west,north,east,southwest,northwest,northeast,southeast,nodir};
\r
57 //===========================================================================
\r
68 void SpawnNewObj (unsigned x, unsigned y, statetype *state, unsigned size)
\r
73 new->ticcount = random (state->tictime)+1;
\r
77 new->x = ((long)x<<TILESHIFT)+TILEGLOBAL/2;
\r
78 new->y = ((long)y<<TILESHIFT)+TILEGLOBAL/2;
\r
82 actorat[new->tilex][new->tiley] = new;
\r
85 void SpawnNewObjFrac (long x, long y, statetype *state, unsigned size)
\r
90 new->ticcount = random (state->tictime)+1;
\r
95 new->tilex = x>>TILESHIFT;
\r
96 new->tiley = y>>TILESHIFT;
\r
98 new->distance = 100;
\r
105 ===================
\r
109 = If the object can move next to the player, it will return true
\r
111 ===================
\r
114 boolean CheckHandAttack (objtype *ob)
\r
116 long deltax,deltay,size;
\r
118 size = (long)ob->size + player->size + ob->speed*tics;
\r
119 deltax = ob->x - player->x;
\r
120 deltay = ob->y - player->y;
\r
122 if (deltax > size || deltax < -size || deltay > size || deltay < -size)
\r
130 ===================
\r
134 = Attacks the player if still nearby, then immediately changes to next state
\r
136 ===================
\r
139 void T_DoDamage (objtype *ob)
\r
144 if (!CheckHandAttack (ob))
\r
146 SD_PlaySound (MONSTERMISSSND);
\r
152 switch (ob->obclass)
\r
164 TakeDamage (points);
\r
167 ob->state = ob->state->next;
\r
171 //==========================================================================
\r
174 ==================================
\r
178 ==================================
\r
181 boolean Walk (objtype *ob)
\r
186 if (actorat[ob->tilex][ob->tiley-1])
\r
189 ob->distance = TILEGLOBAL;
\r
193 if (actorat[ob->tilex+1][ob->tiley-1])
\r
197 ob->distance = TILEGLOBAL;
\r
201 if (actorat[ob->tilex+1][ob->tiley])
\r
204 ob->distance = TILEGLOBAL;
\r
208 if (actorat[ob->tilex+1][ob->tiley+1])
\r
212 ob->distance = TILEGLOBAL;
\r
216 if (actorat[ob->tilex][ob->tiley+1])
\r
219 ob->distance = TILEGLOBAL;
\r
223 if (actorat[ob->tilex-1][ob->tiley+1])
\r
227 ob->distance = TILEGLOBAL;
\r
231 if (actorat[ob->tilex-1][ob->tiley])
\r
234 ob->distance = TILEGLOBAL;
\r
238 if (actorat[ob->tilex-1][ob->tiley-1])
\r
242 ob->distance = TILEGLOBAL;
\r
249 Quit ("Walk: Bad dir");
\r
256 ==================================
\r
259 = have the current monster go after the player,
\r
260 = either diagonally or straight on
\r
262 ==================================
\r
265 void ChaseThink (objtype *obj, boolean diagonal)
\r
267 int deltax,deltay,i;
\r
269 dirtype tdir, olddir, turnaround;
\r
273 turnaround=opposite[olddir];
\r
275 deltax=player->tilex - obj->tilex;
\r
276 deltay=player->tiley - obj->tiley;
\r
290 if (abs(deltay)>abs(deltax))
\r
297 if (d[1]==turnaround)
\r
299 if (d[2]==turnaround)
\r
304 { /*ramdiagonals try the best dir first*/
\r
309 return; /*either moved forward or attacked*/
\r
320 { /*ramstraights try the second best dir first*/
\r
337 /* there is no direct path to the player, so pick another direction */
\r
343 if (US_RndT()>128) /*randomly determine direction of search*/
\r
345 for (tdir=north;tdir<=west;tdir++)
\r
347 if (tdir!=turnaround)
\r
357 for (tdir=west;tdir>=north;tdir--)
\r
359 if (tdir!=turnaround)
\r
368 obj->dir=turnaround;
\r
369 Walk(obj); /*last chance, don't worry about returned value*/
\r
381 void MoveObj (objtype *ob, long move)
\r
383 ob->distance -=move;
\r
427 = returns true if hand attack range
\r
432 boolean Chase (objtype *ob, boolean diagonal)
\r
435 long deltax,deltay,size;
\r
437 move = ob->speed*tics;
\r
438 size = (long)ob->size + player->size + move;
\r
442 deltax = ob->x - player->x;
\r
443 deltay = ob->y - player->y;
\r
445 if (deltax <= size && deltax >= -size
\r
446 && deltay <= size && deltay >= -size)
\r
452 if (move < ob->distance)
\r
457 actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal
\r
458 if (ob->dir == nodir)
\r
461 ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;
\r
462 ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;
\r
463 move -= ob->distance;
\r
465 ChaseThink (ob,diagonal);
\r
467 break; // no possible move
\r
468 actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker
\r
474 //===========================================================================
\r
478 ===================
\r
482 ===================
\r
485 void ShootActor (objtype *ob, unsigned damage)
\r
487 ob->hitpoints -= damage;
\r
488 if (ob->hitpoints<=0)
\r
490 switch (ob->obclass)
\r
493 ob->state = &s_orcdie1;
\r
497 ob->state = &s_trolldie1;
\r
501 ob->state = &s_demondie1;
\r
505 ob->state = &s_magedie1;
\r
509 ob->state = &s_batdie1;
\r
513 ob->state = &s_greldie1;
\r
514 GivePoints (10000);
\r
518 ob->obclass = inertobj;
\r
519 ob->shootable = false;
\r
520 actorat[ob->tilex][ob->tiley] = NULL;
\r
524 switch (ob->obclass)
\r
527 ob->state = &s_orcouch;
\r
530 ob->state = &s_trollouch;
\r
533 ob->state = &s_demonouch;
\r
536 ob->state = &s_mageouch;
\r
539 ob->state = &s_grelouch;
\r
544 ob->ticcount = ob->state->tictime;
\r