ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/monster.C
(Generate patch)

Comparing deliantra/server/server/monster.C (file contents):
Revision 1.3 by root, Tue Aug 29 05:03:55 2006 UTC vs.
Revision 1.21 by root, Sun Jan 14 23:35:04 2007 UTC

1/*
2 * static char *rcsid_monster_c =
3 * "$Id: monster.C,v 1.3 2006/08/29 05:03:55 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
11 7
12 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by 9 it under the terms of the GNU General Public License as published by
21 17
22 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 21
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 22 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 23*/
28 24
29#include <global.h> 25#include <global.h>
30#ifndef __CEXTRACT__
31#include <sproto.h> 26#include <sproto.h>
32#include <spells.h> 27#include <spells.h>
33#include <skills.h> 28#include <skills.h>
34#endif
35 29
36
37#define MIN_MON_RADIUS 3 /* minimum monster detection radius */ 30#define MIN_MON_RADIUS 3 /* minimum monster detection radius */
38
39 31
40/* checks npc->enemy and returns that enemy if still valid, 32/* checks npc->enemy and returns that enemy if still valid,
41 * NULL otherwise. 33 * NULL otherwise.
42 * this is map tile aware. 34 * this is map tile aware.
43 * If this returns an enemy, the range vector rv should also be 35 * If this returns an enemy, the range vector rv should also be
44 * set to sane values. 36 * set to sane values.
45 */ 37 */
38object *
46object *check_enemy(object *npc, rv_vector *rv) { 39check_enemy (object *npc, rv_vector * rv)
47 40{
41
48 /* if this is pet, let him attack the same enemy as his owner 42 /* if this is pet, let him attack the same enemy as his owner
49 * TODO: when there is no ower enemy, try to find a target, 43 * TODO: when there is no ower enemy, try to find a target,
50 * which CAN attack the owner. */ 44 * which CAN attack the owner. */
51 if ((npc->attack_movement & HI4) == PETMOVE) 45 if ((npc->attack_movement & HI4) == PETMOVE)
52 { 46 {
53 if (npc->owner == NULL) 47 if (npc->owner == NULL)
54 npc->enemy = NULL; 48 npc->enemy = NULL;
55 else if (npc->enemy == NULL) 49 else if (npc->enemy == NULL)
56 npc->enemy = npc->owner->enemy; 50 npc->enemy = npc->owner->enemy;
57 } 51 }
58 52
59 /* periodically, a monster mayu change its target. Also, if the object 53 /* periodically, a monster mayu change its target. Also, if the object
60 * has been destroyed, etc, clear the enemy. 54 * has been destroyed, etc, clear the enemy.
61 * TODO: this should be changed, because it invokes to attack forced or 55 * TODO: this should be changed, because it invokes to attack forced or
62 * attacked monsters to leave the attacker alone, before it is destroyed 56 * attacked monsters to leave the attacker alone, before it is destroyed
63 */ 57 */
64 /* i had removed the random target leave, this invokes problems with friendly 58 /* i had removed the random target leave, this invokes problems with friendly
65 * objects, getting attacked and defending herself - they don't try to attack 59 * objects, getting attacked and defending herself - they don't try to attack
66 * again then but perhaps get attack on and on 60 * again then but perhaps get attack on and on
67 * If we include a aggravated flag in , we can handle evil vs evil and good vs good 61 * If we include a aggravated flag in , we can handle evil vs evil and good vs good
68 * too. */ 62 * too. */
69 63
70 if(npc->enemy) 64 if (npc->enemy)
71 { 65 {
72 /* I broke these if's apart to better be able to see what 66 /* I broke these if's apart to better be able to see what
73 * the grouping checks are. Code is the same. 67 * the grouping checks are. Code is the same.
74 */ 68 */
75 if ( QUERY_FLAG(npc->enemy,FLAG_REMOVED) || 69 if (QUERY_FLAG (npc->enemy, FLAG_REMOVED) ||
76 QUERY_FLAG(npc->enemy,FLAG_FREED) || 70 QUERY_FLAG (npc->enemy, FLAG_FREED) ||
77 !on_same_map(npc, npc->enemy) || 71 !on_same_map (npc, npc->enemy) || npc == npc->enemy || QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (npc->enemy, FLAG_NEUTRAL))
78 npc == npc->enemy ||
79 QUERY_FLAG(npc, FLAG_NEUTRAL) ||
80 QUERY_FLAG(npc->enemy, FLAG_NEUTRAL))
81 npc->enemy = NULL;
82
83 else if (QUERY_FLAG(npc, FLAG_FRIENDLY) && (
84 (QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && !(should_arena_attack(npc, npc->owner, npc->enemy))) ||
85 ((npc->enemy->type == PLAYER) && !(should_arena_attack(npc, npc->owner, npc->enemy)))
86 || npc->enemy == npc->owner))
87 npc->enemy = NULL; 72 npc->enemy = NULL;
88 73
89 74 else if (QUERY_FLAG (npc, FLAG_FRIENDLY) && ((QUERY_FLAG (npc->enemy, FLAG_FRIENDLY)
90 else if (!QUERY_FLAG(npc, FLAG_FRIENDLY) && 75 && !(should_arena_attack (npc, npc->owner, npc->enemy)))
91 (!QUERY_FLAG(npc->enemy, FLAG_FRIENDLY) && npc->enemy->type!=PLAYER)) 76 || ((npc->enemy->type == PLAYER) && !(should_arena_attack (npc, npc->owner, npc->enemy)))
77 || npc->enemy == npc->owner))
92 npc->enemy=NULL; 78 npc->enemy = NULL;
93 79
80
81 else if (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (npc->enemy, FLAG_FRIENDLY) && npc->enemy->type != PLAYER))
82 npc->enemy = NULL;
83
94 /* I've noticed that pets could sometimes get an arrow as the 84 /* I've noticed that pets could sometimes get an arrow as the
95 * target enemy - this code below makes sure the enemy is something 85 * target enemy - this code below makes sure the enemy is something
96 * that should be attacked. My guess is that the arrow hits 86 * that should be attacked. My guess is that the arrow hits
97 * the creature/owner, and so the creature then takes that 87 * the creature/owner, and so the creature then takes that
98 * as the enemy to attack. 88 * as the enemy to attack.
99 */ 89 */
100 else if (!QUERY_FLAG(npc->enemy, FLAG_MONSTER) && 90 else if (!QUERY_FLAG (npc->enemy, FLAG_MONSTER) &&
101 !QUERY_FLAG(npc->enemy,FLAG_GENERATOR) && 91 !QUERY_FLAG (npc->enemy, FLAG_GENERATOR) && npc->enemy->type != PLAYER && npc->enemy->type != GOLEM)
102 npc->enemy->type!=PLAYER && npc->enemy->type != GOLEM)
103 npc->enemy=NULL; 92 npc->enemy = NULL;
104 93
105 } 94 }
106 return can_detect_enemy(npc,npc->enemy,rv)?npc->enemy:NULL; 95 return can_detect_enemy (npc, npc->enemy, rv) ? npc->enemy : NULL;
107} 96}
108 97
109/* Returns the nearest living creature (monster or generator). 98/* Returns the nearest living creature (monster or generator).
110 * Modified to deal with tiled maps properly. 99 * Modified to deal with tiled maps properly.
111 * Also fixed logic so that monsters in the lower directions were more 100 * Also fixed logic so that monsters in the lower directions were more
118 * the first few directions, it could very well choose something 107 * the first few directions, it could very well choose something
119 * 3 spaces away even though something directly north is closer. 108 * 3 spaces away even though something directly north is closer.
120 * 109 *
121 * this function is map tile aware. 110 * this function is map tile aware.
122 */ 111 */
112object *
123object *find_nearest_living_creature(object *npc) { 113find_nearest_living_creature (object *npc)
114{
124 int i,mflags; 115 int i, mflags;
125 sint16 nx,ny; 116 sint16 nx, ny;
126 mapstruct *m; 117 maptile *m;
127 object *tmp;
128 int search_arr[SIZEOFFREE]; 118 int search_arr[SIZEOFFREE];
129 119
130 get_search_arr(search_arr); 120 get_search_arr (search_arr);
121
131 for(i=0;i<SIZEOFFREE;i++) { 122 for (i = 0; i < SIZEOFFREE; i++)
123 {
132 /* modified to implement smart searching using search_arr 124 /* modified to implement smart searching using search_arr
133 * guidance array to determine direction of search order 125 * guidance array to determine direction of search order
134 */ 126 */
135 nx = npc->x + freearr_x[search_arr[i]]; 127 nx = npc->x + freearr_x[search_arr[i]];
136 ny = npc->y + freearr_y[search_arr[i]]; 128 ny = npc->y + freearr_y[search_arr[i]];
137 m = npc->map; 129 m = npc->map;
138 130
139 mflags = get_map_flags(m, &m, nx, ny, &nx, &ny); 131 mflags = get_map_flags (m, &m, nx, ny, &nx, &ny);
132
140 if (mflags & P_OUT_OF_MAP) continue; 133 if (mflags & P_OUT_OF_MAP)
134 continue;
141 135
142 if (mflags & P_IS_ALIVE) { 136 if (mflags & P_IS_ALIVE)
143 tmp=get_map_ob(m,nx,ny); 137 {
144 while(tmp!=NULL && !QUERY_FLAG(tmp,FLAG_MONSTER)&& 138 for (object *tmp = m->at (nx, ny).top; tmp; tmp = tmp->below)
145 !QUERY_FLAG(tmp,FLAG_GENERATOR ) && tmp->type!=PLAYER) 139 if (tmp->flag [FLAG_MONSTER] || tmp->flag [FLAG_GENERATOR] || tmp->type == PLAYER)
146 tmp=tmp->above; 140 if (can_see_monsterP (m, nx, ny, i))
147 141 return tmp;
148 if (!tmp) { 142 }
149 LOG(llevDebug,"find_nearest_living_creature: map %s (%d,%d) has is_alive set but did not find a monster?\n",
150 m->path, nx, ny);
151 } 143 }
152 else { 144
153 if(can_see_monsterP(m,nx,ny,i)) 145 return 0;
154 return tmp;
155 }
156 } /* is something living on this space */
157 }
158 return NULL; /* nothing found */
159} 146}
160 147
161 148
162/* Tries to find an enmy for npc. We pass the range vector since 149/* Tries to find an enmy for npc. We pass the range vector since
163 * our caller will find the information useful. 150 * our caller will find the information useful.
165 * Fix function so that we always make calls to get_rangevector 152 * Fix function so that we always make calls to get_rangevector
166 * if we have a valid target - function as not doing so in 153 * if we have a valid target - function as not doing so in
167 * many cases. 154 * many cases.
168 */ 155 */
169 156
157object *
170object *find_enemy(object *npc, rv_vector *rv) 158find_enemy (object *npc, rv_vector * rv)
171{ 159{
172 object *attacker, *tmp=NULL; 160 object *attacker, *tmp = NULL;
173 161
174 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */ 162 attacker = npc->attacked_by; /* save this for later use. This can be a attacker. */
175 npc->attacked_by = NULL; /* always clear the attacker entry */ 163 npc->attacked_by = 0; /* always clear the attacker entry */
176 164
177 /* if we berserk, we don't care about others - we attack all we can find */ 165 /* if we berserk, we don't care about others - we attack all we can find */
178 if(QUERY_FLAG(npc,FLAG_BERSERK)) { 166 if (QUERY_FLAG (npc, FLAG_BERSERK))
167 {
179 tmp = find_nearest_living_creature(npc); 168 tmp = find_nearest_living_creature (npc);
169
170 if (tmp)
180 if (tmp) get_rangevector(npc, tmp, rv, 0); 171 get_rangevector (npc, tmp, rv, 0);
181 return tmp; 172 return tmp;
182 } 173 }
183 174
184 /* Here is the main enemy selection. 175 /* Here is the main enemy selection.
185 * We want this: if there is an enemy, attack him until its not possible or 176 * We want this: if there is an enemy, attack him until its not possible or
186 * one of both is dead. 177 * one of both is dead.
187 * If we have no enemy and we are... 178 * If we have no enemy and we are...
188 * a monster: try to find a player, a pet or a friendly monster 179 * a monster: try to find a player, a pet or a friendly monster
189 * a friendly: only target a monster which is targeting you first or targeting a player 180 * a friendly: only target a monster which is targeting you first or targeting a player
190 * a neutral: fight a attacker (but there should be none), then do nothing 181 * a neutral: fight a attacker (but there should be none), then do nothing
191 * a pet: attack player enemy or a monster 182 * a pet: attack player enemy or a monster
192 */ 183 */
193 184
194 /* pet move */ 185 /* pet move */
195 if ((npc->attack_movement & HI4) == PETMOVE) { 186 if ((npc->attack_movement & HI4) == PETMOVE)
187 {
196 tmp= get_pet_enemy(npc,rv); 188 tmp = get_pet_enemy (npc, rv);
189
190 if (tmp)
197 if (tmp) get_rangevector(npc, tmp, rv, 0); 191 get_rangevector (npc, tmp, rv, 0);
192
198 return tmp; 193 return tmp;
199 }
200 194 }
195
201 /* we check our old enemy. */ 196 /* we check our old enemy. */
202 if((tmp=check_enemy(npc, rv))==NULL) 197 if (!(tmp = check_enemy (npc, rv)))
203 { 198 {
204 if(attacker) /* if we have an attacker, check him */ 199 if (attacker) /* if we have an attacker, check him */
205 { 200 {
206 /* we want be sure this is the right one! */ 201 /* TODO: thats not finished */
207 if(attacker->count == npc->attacked_by_count) 202 /* we don't want a fight evil vs evil or good against non evil */
203
204 if (QUERY_FLAG (npc, FLAG_NEUTRAL) || QUERY_FLAG (attacker, FLAG_NEUTRAL) || /* neutral */
205 (QUERY_FLAG (npc, FLAG_FRIENDLY) && QUERY_FLAG (attacker, FLAG_FRIENDLY)) ||
206 (!QUERY_FLAG (npc, FLAG_FRIENDLY) && (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && attacker->type != PLAYER)))
207 CLEAR_FLAG (npc, FLAG_SLEEP); /* skip it, but lets wakeup */
208 else if (on_same_map (npc, attacker)) /* thats the only thing we must know... */
208 { 209 {
209 /* TODO: thats not finished */
210 /* we don't want a fight evil vs evil or good against non evil */
211
212 if( QUERY_FLAG(npc, FLAG_NEUTRAL) || QUERY_FLAG(attacker, FLAG_NEUTRAL) || /* neutral */
213 (QUERY_FLAG(npc, FLAG_FRIENDLY) && QUERY_FLAG(attacker, FLAG_FRIENDLY)) ||
214 (!QUERY_FLAG(npc, FLAG_FRIENDLY) &&
215 (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && attacker->type!=PLAYER)) )
216 CLEAR_FLAG(npc,FLAG_SLEEP); /* skip it, but lets wakeup */
217 else if(on_same_map(npc, attacker)) /* thats the only thing we must know... */
218 {
219 CLEAR_FLAG(npc,FLAG_SLEEP); /* well, NOW we really should wake up! */ 210 CLEAR_FLAG (npc, FLAG_SLEEP); /* well, NOW we really should wake up! */
220 npc->enemy = attacker; 211 npc->enemy = attacker;
221 return attacker; /* yes, we face our attacker! */ 212 return attacker; /* yes, we face our attacker! */
222 }
223 } 213 }
224 } 214 }
225 215
226 /* we have no legal enemy or attacker, so we try to target a new one */ 216 /* we have no legal enemy or attacker, so we try to target a new one */
227 if(!QUERY_FLAG(npc, FLAG_UNAGGRESSIVE) && !QUERY_FLAG(npc, FLAG_FRIENDLY) && 217 if (!QUERY_FLAG (npc, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (npc, FLAG_FRIENDLY) && !QUERY_FLAG (npc, FLAG_NEUTRAL))
228 !QUERY_FLAG(npc, FLAG_NEUTRAL))
229 {
230 npc->enemy = get_nearest_player(npc);
231 if (npc->enemy)
232 tmp = check_enemy(npc,rv);
233 }
234 218 {
235 } 219 npc->enemy = get_nearest_player (npc);
220 if (npc->enemy)
221 tmp = check_enemy (npc, rv);
222 }
236 223
224 }
225
237 return tmp; 226 return tmp;
238} 227}
239 228
240/* Sees if this monster should wake up. 229/* Sees if this monster should wake up.
241 * Currently, this is only called from move_monster, and 230 * Currently, this is only called from move_monster, and
242 * if enemy is set, then so should be rv. 231 * if enemy is set, then so should be rv.
243 * returns 1 if the monster should wake up, 0 otherwise. 232 * returns 1 if the monster should wake up, 0 otherwise.
244 */ 233 */
245 234
235int
246int check_wakeup(object *op, object *enemy, rv_vector *rv) { 236check_wakeup (object *op, object *enemy, rv_vector * rv)
237{
247 int radius = op->stats.Wis>MIN_MON_RADIUS?op->stats.Wis:MIN_MON_RADIUS; 238 int radius = op->stats.Wis > MIN_MON_RADIUS ? op->stats.Wis : MIN_MON_RADIUS;
248 239
249 /* Trim work - if no enemy, no need to do anything below */ 240 /* Trim work - if no enemy, no need to do anything below */
250 if (!enemy) return 0; 241 if (!enemy)
242 return 0;
251 243
252 /* blinded monsters can only find nearby objects to attack */ 244 /* blinded monsters can only find nearby objects to attack */
253 if(QUERY_FLAG(op, FLAG_BLIND)) 245 if (QUERY_FLAG (op, FLAG_BLIND))
254 radius = MIN_MON_RADIUS; 246 radius = MIN_MON_RADIUS;
255 247
256 /* This covers the situation where the monster is in the dark 248 /* This covers the situation where the monster is in the dark
257 * and has an enemy. If the enemy has no carried light (or isnt 249 * and has an enemy. If the enemy has no carried light (or isnt
258 * glowing!) then the monster has trouble finding the enemy. 250 * glowing!) then the monster has trouble finding the enemy.
259 * Remember we already checked to see if the monster can see in 251 * Remember we already checked to see if the monster can see in
260 * the dark. */ 252 * the dark. */
261 253
262 else if(op->map && op->map->darkness>0 && enemy && !enemy->invisible && 254 else if (op->map && op->map->darkness > 0 && enemy && !enemy->invisible &&
263 !stand_in_light(enemy) &&
264 (!QUERY_FLAG(op,FLAG_SEE_IN_DARK) || !QUERY_FLAG(op,FLAG_SEE_INVISIBLE))) { 255 !stand_in_light (enemy) && (!QUERY_FLAG (op, FLAG_SEE_IN_DARK) || !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
256 {
265 int dark = radius/(op->map->darkness); 257 int dark = radius / (op->map->darkness);
258
266 radius = (dark>MIN_MON_RADIUS)?(dark+1):MIN_MON_RADIUS; 259 radius = (dark > MIN_MON_RADIUS) ? (dark + 1) : MIN_MON_RADIUS;
267 } 260 }
268 else if(!QUERY_FLAG(op,FLAG_SLEEP)) return 1; 261 else if (!QUERY_FLAG (op, FLAG_SLEEP))
262 return 1;
269 263
270 /* enemy should already be on this map, so don't really need to check 264 /* enemy should already be on this map, so don't really need to check
271 * for that. 265 * for that.
272 */ 266 */
273 if (rv->distance < (QUERY_FLAG(enemy, FLAG_STEALTH)?(radius/2)+1:radius)) { 267 if (rv->distance < (unsigned int) (QUERY_FLAG (enemy, FLAG_STEALTH) ? (radius / 2) + 1 : radius))
268 {
274 CLEAR_FLAG(op,FLAG_SLEEP); 269 CLEAR_FLAG (op, FLAG_SLEEP);
275 return 1; 270 return 1;
276 } 271 }
277 return 0; 272 return 0;
278} 273}
279 274
275int
280int move_randomly(object *op) { 276move_randomly (object *op)
277{
281 int i; 278 int i;
282 279
283 /* Give up to 15 chances for a monster to move randomly */ 280 /* Give up to 15 chances for a monster to move randomly */
284 for(i=0;i<15;i++) { 281 for (i = 0; i < 15; i++)
282 {
285 if(move_object(op,RANDOM()%8+1)) 283 if (move_object (op, RANDOM () % 8 + 1))
286 return 1; 284 return 1;
287 } 285 }
288 return 0; 286 return 0;
289} 287}
290 288
291/* 289/*
292 * Move-monster returns 1 if the object has been freed, otherwise 0. 290 * Move-monster returns 1 if the object has been freed, otherwise 0.
293 */ 291 */
294 292
293int
295int move_monster(object *op) { 294move_monster (object *op)
295{
296 int dir, diff, pre_att_dir; /* elmex: pre_att_dir remembers the direction before attack movement */ 296 int dir, diff, pre_att_dir; /* elmex: pre_att_dir remembers the direction before attack movement */
297 object *owner, *enemy, *part, *oph=op; 297 object *owner, *enemy, *part, *oph = op;
298 rv_vector rv; 298 rv_vector rv;
299 299
300 /* Monsters not on maps don't do anything. These monsters are things 300 /* Monsters not on maps don't do anything. These monsters are things
301 * Like royal guards in city dwellers inventories. 301 * Like royal guards in city dwellers inventories.
302 */ 302 */
303 if (!op->map) return 0; 303 if (!op->map)
304 return 0;
304 305
305 /* for target facing, we copy this value here for fast access */ 306 /* for target facing, we copy this value here for fast access */
306 if(oph->head) /* force update the head - one arch one pic */ 307 if (oph->head) /* force update the head - one arch one pic */
307 oph = oph->head; 308 oph = oph->head;
308 309
309 if (QUERY_FLAG(op, FLAG_NO_ATTACK)) /* we never ever attack */ 310 if (QUERY_FLAG (op, FLAG_NO_ATTACK)) /* we never ever attack */
310 enemy = op->enemy = NULL; 311 enemy = op->enemy = NULL;
311 else if((enemy= find_enemy(op, &rv))) 312 else if ((enemy = find_enemy (op, &rv)))
312 {
313 /* we have an enemy, just tell him we want him dead */ 313 /* we have an enemy, just tell him we want him dead */
314 enemy->attacked_by = op; /* our ptr */ 314 enemy->attacked_by = op; /* our ptr */
315 enemy->attacked_by_count = op->count; /* our tag */ 315
316 }
317
318 /* generate hp, if applicable */ 316 /* generate hp, if applicable */
319 if(op->stats.Con > 0 && op->stats.hp < op->stats.maxhp) { 317 if (op->stats.Con > 0 && op->stats.hp < op->stats.maxhp)
318 {
320 319
321 /* last heal is in funny units. Dividing by speed puts 320 /* last heal is in funny units. Dividing by speed puts
322 * the regeneration rate on a basis of time instead of
323 * #moves the monster makes. The scaling by 8 is
324 * to capture 8th's of a hp fraction regens
325 *
326 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
327 * overflow might produce monsters with negative hp.
328 */
329
330 op->last_heal+= (int)((float)(8*op->stats.Con)/FABS(op->speed));
331 op->stats.hp = MIN((sint32)op->stats.hp+op->last_heal/32, op->stats.maxhp); /* causes Con/4 hp/tick */
332 op->last_heal%=32;
333
334 /* So if the monster has gained enough HP that they are no longer afraid */
335 if (QUERY_FLAG(op,FLAG_RUN_AWAY) &&
336 op->stats.hp >= (signed short)(((float)op->run_away/(float)100)*
337 (float)op->stats.maxhp))
338 CLEAR_FLAG(op, FLAG_RUN_AWAY);
339
340 if(op->stats.hp>op->stats.maxhp)
341 op->stats.hp=op->stats.maxhp;
342 }
343
344 /* generate sp, if applicable */
345 if(op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp) {
346
347 /* last_sp is in funny units. Dividing by speed puts
348 * the regeneration rate on a basis of time instead of 321 * the regeneration rate on a basis of time instead of
349 * #moves the monster makes. The scaling by 8 is 322 * #moves the monster makes. The scaling by 8 is
323 * to capture 8th's of a hp fraction regens
324 *
325 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
326 * overflow might produce monsters with negative hp.
327 */
328
329 op->last_heal += (int) ((float) (8 * op->stats.Con) / FABS (op->speed));
330 op->stats.hp = MIN ((sint32) op->stats.hp + op->last_heal / 32, op->stats.maxhp); /* causes Con/4 hp/tick */
331 op->last_heal %= 32;
332
333 /* So if the monster has gained enough HP that they are no longer afraid */
334 if (QUERY_FLAG (op, FLAG_RUN_AWAY) && op->stats.hp >= (signed short) (((float) op->run_away / (float) 100) * (float) op->stats.maxhp))
335 CLEAR_FLAG (op, FLAG_RUN_AWAY);
336
337 if (op->stats.hp > op->stats.maxhp)
338 op->stats.hp = op->stats.maxhp;
339 }
340
341 /* generate sp, if applicable */
342 if (op->stats.Pow > 0 && op->stats.sp < op->stats.maxsp)
343 {
344
345 /* last_sp is in funny units. Dividing by speed puts
346 * the regeneration rate on a basis of time instead of
347 * #moves the monster makes. The scaling by 8 is
350 * to capture 8th's of a sp fraction regens 348 * to capture 8th's of a sp fraction regens
351 * 349 *
352 * Cast to sint32 before comparing to maxhp since otherwise an (sint16) 350 * Cast to sint32 before comparing to maxhp since otherwise an (sint16)
353 * overflow might produce monsters with negative sp. 351 * overflow might produce monsters with negative sp.
354 */ 352 */
355 353
356 op->last_sp+= (int)((float)(8*op->stats.Pow)/FABS(op->speed)); 354 op->last_sp += (int) ((float) (8 * op->stats.Pow) / FABS (op->speed));
357 op->stats.sp = MIN(op->stats.sp+op->last_sp/128, op->stats.maxsp); /* causes Pow/16 sp/tick */ 355 op->stats.sp = MIN (op->stats.sp + op->last_sp / 128, op->stats.maxsp); /* causes Pow/16 sp/tick */
358 op->last_sp%=128; 356 op->last_sp %= 128;
359 } 357 }
360 358
361 /* this should probably get modified by many more values. 359 /* this should probably get modified by many more values.
362 * (eg, creatures resistance to fear, level, etc. ) 360 * (eg, creatures resistance to fear, level, etc. )
363 */ 361 */
364 if(QUERY_FLAG(op, FLAG_SCARED) &&!(RANDOM()%20)) { 362 if (QUERY_FLAG (op, FLAG_SCARED) && !(RANDOM () % 20))
363 {
365 CLEAR_FLAG(op,FLAG_SCARED); /* Time to regain some "guts"... */ 364 CLEAR_FLAG (op, FLAG_SCARED); /* Time to regain some "guts"... */
365 }
366
367 if (INVOKE_OBJECT (MONSTER_MOVE, op, ARG_OBJECT (op->enemy)))
368 return QUERY_FLAG (op, FLAG_FREED);
369
370 if (QUERY_FLAG (op, FLAG_SLEEP) || QUERY_FLAG (op, FLAG_BLIND) ||
371 ((op->map->darkness > 0) && !QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !QUERY_FLAG (op, FLAG_SEE_INVISIBLE)))
366 } 372 {
373 if (!check_wakeup (op, enemy, &rv))
374 return 0;
375 }
367 376
368 if (INVOKE_OBJECT (MOVE, op, ARG_OBJECT (op->enemy)))//TODO: should go away 377 /* check if monster pops out of hidden spot */
378 if (op->hide)
379 do_hidden_move (op);
380
381 if (op->pick_up)
382 monster_check_pickup (op);
383
384 if (op->will_apply)
385 monster_apply_below (op); /* Check for items to apply below */
386
387 /* If we don't have an enemy, do special movement or the like */
388 if (!enemy)
389 {
390 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
391 {
392 op->destroy ();
393 return 1;
394 }
395
396 /* Probably really a bug for a creature to have both
397 * stand still and a movement type set.
398 */
399 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
400 {
401 if (op->attack_movement & HI4)
402 {
403 switch (op->attack_movement & HI4)
404 {
405 case (PETMOVE):
406 pet_move (op);
407 break;
408
409 case (CIRCLE1):
410 circ1_move (op);
411 break;
412
413 case (CIRCLE2):
414 circ2_move (op);
415 break;
416
417 case (PACEV):
418 pace_movev (op);
419 break;
420
421 case (PACEH):
422 pace_moveh (op);
423 break;
424
425 case (PACEV2):
426 pace2_movev (op);
427 break;
428
429 case (PACEH2):
430 pace2_moveh (op);
431 break;
432
433 case (RANDO):
434 rand_move (op);
435 break;
436
437 case (RANDO2):
438 move_randomly (op);
439 break;
440 }
441 return 0;
442 }
443 else if (QUERY_FLAG (op, FLAG_RANDOM_MOVE))
444 (void) move_randomly (op);
445
446 } /* stand still */
369 return 0; 447 return 0;
448 } /* no enemy */
370 449
371 if ( QUERY_FLAG(op, FLAG_SLEEP) || QUERY_FLAG(op, FLAG_BLIND) || 450 /* We have an enemy. Block immediately below is for pets */
372 ((op->map->darkness>0) && !QUERY_FLAG(op,FLAG_SEE_IN_DARK) && 451 if ((op->attack_movement & HI4) == PETMOVE && (owner = op->owner) != NULL && !on_same_map (op, owner))
373 !QUERY_FLAG(op,FLAG_SEE_INVISIBLE))) { 452 return follow_owner (op, owner);
374 if(!check_wakeup(op,enemy,&rv)) 453
375 return 0; 454 /* doppleganger code to change monster facing to that of the nearest
455 * player. Hmm. The code is here, but no monster in the current
456 * arch set uses it.
457 */
458 if ((op->race != NULL) && strcmp (op->race, "doppleganger") == 0)
376 } 459 {
460 op->face = enemy->face;
461 op->name = enemy->name;
462 }
377 463
378 /* check if monster pops out of hidden spot */ 464 /* Calculate range information for closest body part - this
379 if(op->hide) do_hidden_move(op); 465 * is used for the 'skill' code, which isn't that smart when
466 * it comes to figuring it out - otherwise, giants throw boulders
467 * into themselves.
468 */
469 get_rangevector (op, enemy, &rv, 0);
380 470
381 if(op->pick_up) 471 /* Move the check for scared up here - if the monster was scared,
382 monster_check_pickup(op); 472 * we were not doing any of the logic below, so might as well save
473 * a few cpu cycles.
474 */
475 if (!QUERY_FLAG (op, FLAG_SCARED))
476 {
477 rv_vector rv1;
383 478
384 if(op->will_apply) 479 /* now we test every part of an object .... this is a real ugly piece of code */
385 monster_apply_below(op); /* Check for items to apply below */ 480 for (part = op; part != NULL; part = part->more)
481 {
482 get_rangevector (part, enemy, &rv1, 0x1);
483 dir = rv1.direction;
386 484
387 /* If we don't have an enemy, do special movement or the like */ 485 /* hm, not sure about this part - in original was a scared flag here too
388 if(!enemy) { 486 * but that we test above... so can be old code here
487 */
389 if(QUERY_FLAG(op, FLAG_ONLY_ATTACK)) { 488 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
390 remove_ob(op); 489 dir = absdir (dir + 4);
391 free_object(op);
392 return 1;
393 }
394
395 /* Probably really a bug for a creature to have both
396 * stand still and a movement type set.
397 */
398 if(!QUERY_FLAG(op, FLAG_STAND_STILL)) { 490 if (QUERY_FLAG (op, FLAG_CONFUSED))
399 if (op->attack_movement & HI4) 491 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
492
493 if (QUERY_FLAG (op, FLAG_CAST_SPELL) && !(RANDOM () % 3))
400 { 494 {
401 switch (op->attack_movement & HI4) {
402 case (PETMOVE):
403 pet_move (op);
404 break;
405
406 case (CIRCLE1):
407 circ1_move (op);
408 break;
409
410 case (CIRCLE2):
411 circ2_move (op);
412 break;
413
414 case (PACEV):
415 pace_movev(op);
416 break;
417
418 case (PACEH):
419 pace_moveh(op);
420 break;
421
422 case (PACEV2):
423 pace2_movev (op);
424 break;
425
426 case (PACEH2):
427 pace2_moveh (op);
428 break;
429
430 case (RANDO):
431 rand_move (op);
432 break;
433
434 case (RANDO2):
435 move_randomly (op);
436 break;
437 }
438 return 0;
439 }
440 else if (QUERY_FLAG(op,FLAG_RANDOM_MOVE))
441 (void) move_randomly(op);
442
443 } /* stand still */
444 return 0;
445 } /* no enemy */
446
447 /* We have an enemy. Block immediately below is for pets */
448 if((op->attack_movement&HI4) == PETMOVE && (owner = get_owner(op)) != NULL && !on_same_map(op,owner))
449 return follow_owner(op, owner);
450
451 /* doppleganger code to change monster facing to that of the nearest
452 * player. Hmm. The code is here, but no monster in the current
453 * arch set uses it.
454 */
455 if ( (op->race != NULL)&& strcmp(op->race,"doppleganger") == 0)
456 {
457 op->face = enemy->face;
458 if (op->name)
459 free_string(op->name);
460 add_refcount(op->name = enemy->name);
461 }
462
463 /* Calculate range information for closest body part - this
464 * is used for the 'skill' code, which isn't that smart when
465 * it comes to figuring it out - otherwise, giants throw boulders
466 * into themselves.
467 */
468 get_rangevector(op, enemy, &rv, 0);
469
470 /* Move the check for scared up here - if the monster was scared,
471 * we were not doing any of the logic below, so might as well save
472 * a few cpu cycles.
473 */
474 if (!QUERY_FLAG(op, FLAG_SCARED))
475 {
476 rv_vector rv1;
477
478 /* now we test every part of an object .... this is a real ugly piece of code */
479 for (part=op; part!=NULL; part=part->more) {
480 get_rangevector(part, enemy, &rv1, 0x1);
481 dir=rv1.direction;
482
483 /* hm, not sure about this part - in original was a scared flag here too
484 * but that we test above... so can be old code here
485 */
486 if(QUERY_FLAG(op,FLAG_RUN_AWAY))
487 dir=absdir(dir+4);
488 if(QUERY_FLAG(op,FLAG_CONFUSED))
489 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2);
490
491 if(QUERY_FLAG(op,FLAG_CAST_SPELL) && !(RANDOM()%3)) {
492 if(monster_cast_spell(op,part,enemy,dir,&rv1)) 495 if (monster_cast_spell (op, part, enemy, dir, &rv1))
493 return 0; 496 return 0;
494 } 497 }
495 498
496 if(QUERY_FLAG(op,FLAG_READY_SCROLL) && !(RANDOM()%3)) { 499 if (QUERY_FLAG (op, FLAG_READY_SCROLL) && !(RANDOM () % 3))
500 {
497 if(monster_use_scroll(op,part,enemy,dir,&rv1)) 501 if (monster_use_scroll (op, part, enemy, dir, &rv1))
498 return 0; 502 return 0;
499 } 503 }
500 504
501 if(QUERY_FLAG(op,FLAG_READY_RANGE)&&!(RANDOM()%3)) { 505 if (QUERY_FLAG (op, FLAG_READY_RANGE) && !(RANDOM () % 3))
506 {
502 if(monster_use_range(op,part,enemy,dir)) 507 if (monster_use_range (op, part, enemy, dir))
503 return 0; 508 return 0;
504 } 509 }
505 if(QUERY_FLAG(op,FLAG_READY_SKILL)&&!(RANDOM()%3)) { 510 if (QUERY_FLAG (op, FLAG_READY_SKILL) && !(RANDOM () % 3))
511 {
506 if(monster_use_skill(op,rv.part,enemy,rv.direction)) 512 if (monster_use_skill (op, rv.part, enemy, rv.direction))
507 return 0; 513 return 0;
508 } 514 }
509 if(QUERY_FLAG(op,FLAG_READY_BOW)&&!(RANDOM()%2)) { 515 if (QUERY_FLAG (op, FLAG_READY_BOW) && !(RANDOM () % 2))
516 {
510 if(monster_use_bow(op,part,enemy,dir)) 517 if (monster_use_bow (op, part, enemy, dir))
511 return 0; 518 return 0;
512 } 519 }
513 } /* for processing of all parts */ 520 } /* for processing of all parts */
514 } /* If not scared */ 521 } /* If not scared */
515 522
516 523
517 part = rv.part; 524 part = rv.part;
518 dir=rv.direction; 525 dir = rv.direction;
519 526
520 if(QUERY_FLAG(op, FLAG_SCARED) || QUERY_FLAG(op,FLAG_RUN_AWAY)) 527 if (QUERY_FLAG (op, FLAG_SCARED) || QUERY_FLAG (op, FLAG_RUN_AWAY))
521 dir=absdir(dir+4); 528 dir = absdir (dir + 4);
522 529
523 if(QUERY_FLAG(op,FLAG_CONFUSED)) 530 if (QUERY_FLAG (op, FLAG_CONFUSED))
524 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2); 531 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
525 532
526 pre_att_dir = dir; /* remember the original direction */ 533 pre_att_dir = dir; /* remember the original direction */
527 534
528 if ((op->attack_movement & LO4) && !QUERY_FLAG(op, FLAG_SCARED)) 535 if ((op->attack_movement & LO4) && !QUERY_FLAG (op, FLAG_SCARED))
529 { 536 {
530 switch (op->attack_movement & LO4) { 537 switch (op->attack_movement & LO4)
538 {
531 case DISTATT: 539 case DISTATT:
532 dir = dist_att (dir,op,enemy,part,&rv); 540 dir = dist_att (dir, op, enemy, part, &rv);
533 break; 541 break;
534 542
535 case RUNATT: 543 case RUNATT:
536 dir = run_att (dir,op,enemy,part,&rv); 544 dir = run_att (dir, op, enemy, part, &rv);
537 break; 545 break;
538 546
539 case HITRUN: 547 case HITRUN:
540 dir = hitrun_att(dir,op,enemy); 548 dir = hitrun_att (dir, op, enemy);
541 break; 549 break;
542 550
543 case WAITATT: 551 case WAITATT:
544 dir = wait_att (dir,op,enemy,part,&rv); 552 dir = wait_att (dir, op, enemy, part, &rv);
545 break; 553 break;
546 554
547 case RUSH: /* default - monster normally moves towards player */ 555 case RUSH: /* default - monster normally moves towards player */
548 case ALLRUN: 556 case ALLRUN:
549 break; 557 break;
550 558
551 case DISTHIT: 559 case DISTHIT:
552 dir = disthit_att (dir,op,enemy,part,&rv); 560 dir = disthit_att (dir, op, enemy, part, &rv);
553 break; 561 break;
554 562
555 case WAIT2: 563 case WAIT2:
556 dir = wait_att2 (dir,op,enemy,part,&rv); 564 dir = wait_att2 (dir, op, enemy, part, &rv);
557 break; 565 break;
558 566
559 default: 567 default:
560 LOG(llevDebug,"Illegal low mon-move: %d\n",op->attack_movement & LO4); 568 LOG (llevDebug, "Illegal low mon-move: %d\n", op->attack_movement & LO4);
561 } 569 }
562 } 570 }
563 571
564 if (!dir) 572 if (!dir)
565 return 0; 573 return 0;
566 574
567 if (!QUERY_FLAG(op,FLAG_STAND_STILL)) { 575 if (!QUERY_FLAG (op, FLAG_STAND_STILL))
576 {
568 if(move_object(op,dir)) /* Can the monster move directly toward player? */ 577 if (move_object (op, dir)) /* Can the monster move directly toward player? */
569 { 578 {
570 /* elmex: Turn our monster after it moved if it has DISTATT attack */ 579 /* elmex: Turn our monster after it moved if it has DISTATT attack */
571 if ((op->attack_movement & LO4) == DISTATT) 580 if ((op->attack_movement & LO4) == DISTATT)
572 op->direction = pre_att_dir; 581 op->direction = pre_att_dir;
573 582
574 return 0; 583 return 0;
575 } 584 }
576 585
577 if(QUERY_FLAG(op, FLAG_SCARED) || !can_hit(part,enemy,&rv) 586 if (QUERY_FLAG (op, FLAG_SCARED) || !can_hit (part, enemy, &rv) || QUERY_FLAG (op, FLAG_RUN_AWAY))
578 || QUERY_FLAG(op,FLAG_RUN_AWAY)) { 587 {
579 588
580 /* Try move around corners if !close */ 589 /* Try move around corners if !close */
581 int maxdiff = (QUERY_FLAG(op, FLAG_ONLY_ATTACK) || RANDOM()&1) ? 1 : 2; 590 int maxdiff = (QUERY_FLAG (op, FLAG_ONLY_ATTACK) || RANDOM () & 1) ? 1 : 2;
591
582 for(diff = 1; diff <= maxdiff; diff++) { 592 for (diff = 1; diff <= maxdiff; diff++)
593 {
583 /* try different detours */ 594 /* try different detours */
584 int m = 1-(RANDOM()&2); /* Try left or right first? */ 595 int m = 1 - (RANDOM () & 2); /* Try left or right first? */
585 if(move_object(op,absdir(dir + diff*m)) || 596
586 move_object(op,absdir(dir - diff*m))) 597 if (move_object (op, absdir (dir + diff * m)) || move_object (op, absdir (dir - diff * m)))
587 return 0; 598 return 0;
588 } 599 }
589 } 600 }
590 } /* if monster is not standing still */ 601 } /* if monster is not standing still */
591 602
592 /* elmex: Turn our monster after it moved if it has DISTATT attack */ 603 /* elmex: Turn our monster after it moved if it has DISTATT attack */
593 if ((op->attack_movement & LO4) == DISTATT) 604 if ((op->attack_movement & LO4) == DISTATT)
594 op->direction = pre_att_dir; 605 op->direction = pre_att_dir;
595 606
596 /* 607 /*
597 * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random 608 * Eneq(@csd.uu.se): Patch to make RUN_AWAY or SCARED monsters move a random
598 * direction if they can't move away. 609 * direction if they can't move away.
599 */ 610 */
600 if (!QUERY_FLAG(op, FLAG_ONLY_ATTACK)&&(QUERY_FLAG(op,FLAG_RUN_AWAY)||QUERY_FLAG(op, FLAG_SCARED))) 611 if (!QUERY_FLAG (op, FLAG_ONLY_ATTACK) && (QUERY_FLAG (op, FLAG_RUN_AWAY) || QUERY_FLAG (op, FLAG_SCARED)))
601 if(move_randomly(op)) 612 if (move_randomly (op))
602 return 0; 613 return 0;
603 614
604 /* 615 /*
605 * Try giving the monster a new enemy - the player that is closest 616 * Try giving the monster a new enemy - the player that is closest
606 * to it. In this way, it won't just keep trying to get to a target 617 * to it. In this way, it won't just keep trying to get to a target
607 * that is inaccessible. 618 * that is inaccessible.
608 * This could be more clever - it should go through a list of several 619 * This could be more clever - it should go through a list of several
609 * enemies, as it is now, you could perhaps get situations where there 620 * enemies, as it is now, you could perhaps get situations where there
610 * are two players flanking the monster at close distance, but which 621 * are two players flanking the monster at close distance, but which
611 * the monster can't get to, and a third one at a far distance that 622 * the monster can't get to, and a third one at a far distance that
612 * the monster could get to - as it is, the monster won't look at that 623 * the monster could get to - as it is, the monster won't look at that
613 * third one. 624 * third one.
614 */ 625 */
615 if (!QUERY_FLAG(op, FLAG_FRIENDLY) && enemy == op->enemy) 626 if (!QUERY_FLAG (op, FLAG_FRIENDLY) && enemy == op->enemy)
616 { 627 {
617 object *nearest_player = get_nearest_player(op); 628 object *nearest_player = get_nearest_player (op);
629
618 if (nearest_player && nearest_player != enemy && !can_hit(part,enemy,&rv)) { 630 if (nearest_player && nearest_player != enemy && !can_hit (part, enemy, &rv))
631 {
619 op->enemy = NULL; 632 op->enemy = NULL;
620 enemy = nearest_player; 633 enemy = nearest_player;
621 } 634 }
622 } 635 }
623 636
624 if(!QUERY_FLAG(op, FLAG_SCARED)&&can_hit(part,enemy,&rv)) 637 if (!QUERY_FLAG (op, FLAG_SCARED) && can_hit (part, enemy, &rv))
625 { 638 {
626 /* The adjustement to wc that was here before looked totally bogus - 639 /* The adjustement to wc that was here before looked totally bogus -
627 * since wc can in fact get negative, that would mean by adding 640 * since wc can in fact get negative, that would mean by adding
628 * the current wc, the creature gets better? Instead, just 641 * the current wc, the creature gets better? Instead, just
629 * add a fixed amount - nasty creatures that are runny away should 642 * add a fixed amount - nasty creatures that are runny away should
630 * still be pretty nasty. 643 * still be pretty nasty.
631 */ 644 */
632 if(QUERY_FLAG(op,FLAG_RUN_AWAY)) 645 if (QUERY_FLAG (op, FLAG_RUN_AWAY))
633 { 646 {
634 part->stats.wc+=10; 647 part->stats.wc += 10;
635 (void)skill_attack(enemy,part,0,NULL, NULL);
636 part->stats.wc-=10;
637 }
638 else
639 (void)skill_attack(enemy,part,0,NULL, NULL); 648 (void) skill_attack (enemy, part, 0, NULL, NULL);
649 part->stats.wc -= 10;
650 }
651 else
652 (void) skill_attack (enemy, part, 0, NULL, NULL);
640 } /* if monster is in attack range */ 653 } /* if monster is in attack range */
641 654
642 if(QUERY_FLAG(part,FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */ 655 if (QUERY_FLAG (part, FLAG_FREED)) /* Might be freed by ghost-attack or hit-back */
643 return 1; 656 return 1;
644 657
645 if(QUERY_FLAG(op, FLAG_ONLY_ATTACK)) 658 if (QUERY_FLAG (op, FLAG_ONLY_ATTACK))
646 {
647 remove_ob(op);
648 free_object(op);
649 return 1;
650 } 659 {
660 op->remove ();
661 op->destroy ();
662 return 1;
663 }
651 return 0; 664 return 0;
652} 665}
666
667int
653int can_hit(object *ob1,object *ob2, rv_vector *rv) { 668can_hit (object *ob1, object *ob2, rv_vector * rv)
669{
654 object *more; 670 object *more;
655 rv_vector rv1; 671 rv_vector rv1;
656 672
657 if(QUERY_FLAG(ob1,FLAG_CONFUSED)&&!(RANDOM()%3)) 673 if (QUERY_FLAG (ob1, FLAG_CONFUSED) && !(RANDOM () % 3))
658 return 0; 674 return 0;
659 675
660 if (abs(rv->distance_x)<2&&abs(rv->distance_y)<2) return 1; 676 if (abs (rv->distance_x) < 2 && abs (rv->distance_y) < 2)
677 return 1;
661 678
662 /* check all the parts of ob2 - just because we can't get to 679 /* check all the parts of ob2 - just because we can't get to
663 * its head doesn't mean we don't want to pound its feet 680 * its head doesn't mean we don't want to pound its feet
664 */ 681 */
665 for (more = ob2->more; more!=NULL; more = more->more) { 682 for (more = ob2->more; more != NULL; more = more->more)
683 {
666 get_rangevector(ob1, more, &rv1, 0); 684 get_rangevector (ob1, more, &rv1, 0);
667 if (abs(rv1.distance_x)<2&&abs(rv1.distance_y)<2) return 1; 685 if (abs (rv1.distance_x) < 2 && abs (rv1.distance_y) < 2)
686 return 1;
668 } 687 }
669 return 0; 688 return 0;
670 689
671} 690}
672 691
673/* Returns 1 is monster should cast spell sp at an enemy 692/* Returns 1 is monster should cast spell sp at an enemy
674 * Returns 0 if the monster should not cast this spell. 693 * Returns 0 if the monster should not cast this spell.
684 * This could be a lot smarter - if there are few monsters around, 703 * This could be a lot smarter - if there are few monsters around,
685 * then disease might not be as bad. Likewise, if the monster is damaged, 704 * then disease might not be as bad. Likewise, if the monster is damaged,
686 * the right type of healing spell could be useful. 705 * the right type of healing spell could be useful.
687 */ 706 */
688 707
708static int
689static int monster_should_cast_spell(object *monster, object *spell_ob) 709monster_should_cast_spell (object *monster, object *spell_ob)
690{ 710{
691 if (spell_ob->subtype == SP_BOLT || spell_ob->subtype == SP_BULLET || 711 if (spell_ob->subtype == SP_BOLT || spell_ob->subtype == SP_BULLET ||
692 spell_ob->subtype == SP_EXPLOSION || spell_ob->subtype == SP_CONE || 712 spell_ob->subtype == SP_EXPLOSION || spell_ob->subtype == SP_CONE ||
693 spell_ob->subtype == SP_BOMB || spell_ob->subtype == SP_SMITE || 713 spell_ob->subtype == SP_BOMB || spell_ob->subtype == SP_SMITE ||
694 spell_ob->subtype == SP_MAGIC_MISSILE || spell_ob->subtype == SP_SUMMON_GOLEM || 714 spell_ob->subtype == SP_MAGIC_MISSILE || spell_ob->subtype == SP_SUMMON_GOLEM ||
695 spell_ob->subtype == SP_MAGIC_WALL || spell_ob->subtype == SP_SUMMON_MONSTER || 715 spell_ob->subtype == SP_MAGIC_WALL || spell_ob->subtype == SP_SUMMON_MONSTER ||
696 spell_ob->subtype == SP_MOVING_BALL || spell_ob->subtype == SP_SWARM || 716 spell_ob->subtype == SP_MOVING_BALL || spell_ob->subtype == SP_SWARM || spell_ob->subtype == SP_INVISIBLE)
697 spell_ob->subtype == SP_INVISIBLE)
698 717
699 return 1;
700
701 return 0; 718 return 1;
719
720 return 0;
702} 721}
703 722
704 723
705#define MAX_KNOWN_SPELLS 20 724#define MAX_KNOWN_SPELLS 20
706 725
707/* Returns a randomly selected spell. This logic is still 726/* Returns a randomly selected spell. This logic is still
708 * less than ideal. This code also only seems to deal with 727 * less than ideal. This code also only seems to deal with
709 * wizard spells, as the check is against sp, and not grace. 728 * wizard spells, as the check is against sp, and not grace.
710 * can mosnters know cleric spells? 729 * can mosnters know cleric spells?
711 */ 730 */
731object *
712object *monster_choose_random_spell(object *monster) { 732monster_choose_random_spell (object *monster)
733{
713 object *altern[MAX_KNOWN_SPELLS]; 734 object *altern[MAX_KNOWN_SPELLS];
714 object *tmp; 735 object *tmp;
715 int i=0; 736 int i = 0;
716 737
717 for(tmp=monster->inv;tmp!=NULL;tmp=tmp->below) 738 for (tmp = monster->inv; tmp != NULL; tmp = tmp->below)
718 if (tmp->type==SPELLBOOK || tmp->type==SPELL) { 739 if (tmp->type == SPELLBOOK || tmp->type == SPELL)
740 {
719 /* Check and see if it's actually a useful spell. 741 /* Check and see if it's actually a useful spell.
720 * If its a spellbook, the spell is actually the inventory item. 742 * If its a spellbook, the spell is actually the inventory item.
721 * if it is a spell, then it is just the object itself. 743 * if it is a spell, then it is just the object itself.
722 */ 744 */
723 if (monster_should_cast_spell(monster, (tmp->type==SPELLBOOK)?tmp->inv:tmp)) { 745 if (monster_should_cast_spell (monster, (tmp->type == SPELLBOOK) ? tmp->inv : tmp))
724 altern[i++]=tmp; 746 {
725 if(i==MAX_KNOWN_SPELLS) 747 altern[i++] = tmp;
726 break; 748 if (i == MAX_KNOWN_SPELLS)
749 break;
750 }
727 } 751 }
728 }
729 if(!i) 752 if (!i)
730 return NULL; 753 return NULL;
731 return altern[RANDOM()%i]; 754 return altern[RANDOM () % i];
732} 755}
733 756
734/* This checks to see if the monster should cast a spell/ability. 757/* This checks to see if the monster should cast a spell/ability.
735 * it returns true if the monster casts a spell, 0 if he doesn't. 758 * it returns true if the monster casts a spell, 0 if he doesn't.
736 * head is the head of the monster. 759 * head is the head of the monster.
738 * pl is the target. 761 * pl is the target.
739 * dir is the direction to case. 762 * dir is the direction to case.
740 * rv is the vector which describes where the enemy is. 763 * rv is the vector which describes where the enemy is.
741 */ 764 */
742 765
766int
743int monster_cast_spell(object *head, object *part,object *pl,int dir, rv_vector *rv) { 767monster_cast_spell (object *head, object *part, object *pl, int dir, rv_vector * rv)
768{
744 object *spell_item; 769 object *spell_item;
745 object *owner; 770 object *owner;
746 rv_vector rv1; 771 rv_vector rv1;
747 772
748 /* If you want monsters to cast spells over friends, this spell should 773 /* If you want monsters to cast spells over friends, this spell should
749 * be removed. It probably should be in most cases, since monsters still 774 * be removed. It probably should be in most cases, since monsters still
750 * don't care about residual effects (ie, casting a cone which may have a 775 * don't care about residual effects (ie, casting a cone which may have a
751 * clear path to the player, the side aspects of the code will still hit 776 * clear path to the player, the side aspects of the code will still hit
752 * other monsters) 777 * other monsters)
753 */ 778 */
754 if(!(dir=path_to_player(part,pl,0))) 779 if (!(dir = path_to_player (part, pl, 0)))
755 return 0; 780 return 0;
781
782 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
756 783 {
757 if(QUERY_FLAG(head,FLAG_FRIENDLY) && (owner = get_owner(head)) != NULL) {
758 get_rangevector(head, owner, &rv1, 0x1); 784 get_rangevector (head, owner, &rv1, 0x1);
759 if(dirdiff(dir,rv1.direction) < 2) { 785 if (dirdiff (dir, rv1.direction) < 2)
786 {
760 return 0; /* Might hit owner with spell */ 787 return 0; /* Might hit owner with spell */
761 } 788 }
762 } 789 }
763 790
764 if(QUERY_FLAG(head,FLAG_CONFUSED)) 791 if (QUERY_FLAG (head, FLAG_CONFUSED))
765 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2); 792 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
766 793
767 /* If the monster hasn't already chosen a spell, choose one 794 /* If the monster hasn't already chosen a spell, choose one
768 * I'm not sure if it really make sense to pre-select spells (events 795 * I'm not sure if it really make sense to pre-select spells (events
769 * could be different by the time the monster goes again). 796 * could be different by the time the monster goes again).
770 */ 797 */
771 if(head->spellitem==NULL) { 798 if (head->spellitem == NULL)
799 {
772 if((spell_item=monster_choose_random_spell(head))==NULL) { 800 if ((spell_item = monster_choose_random_spell (head)) == NULL)
801 {
773 LOG(llevMonster,"Turned off spells in %s\n",head->name); 802 LOG (llevMonster, "Turned off spells in %s\n", &head->name);
774 CLEAR_FLAG(head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */ 803 CLEAR_FLAG (head, FLAG_CAST_SPELL); /* Will be turned on when picking up book */
804 return 0;
805 }
806 if (spell_item->type == SPELLBOOK)
807 {
808 if (!spell_item->inv)
809 {
810 LOG (llevError, "spellbook %s does not contain a spell?\n", &spell_item->name);
811 return 0;
812 }
813 spell_item = spell_item->inv;
814 }
815 }
816 else
817 spell_item = head->spellitem;
818
819 if (!spell_item)
775 return 0; 820 return 0;
776 }
777 if (spell_item->type == SPELLBOOK) {
778 if (!spell_item->inv) {
779 LOG(llevError,"spellbook %s does not contain a spell?\n", spell_item->name);
780 return 0;
781 }
782 spell_item=spell_item->inv;
783 }
784 }
785 else
786 spell_item=head->spellitem;
787 821
788 if (!spell_item) return 0;
789
790 /* Best guess this is a defensive/healing spell */ 822 /* Best guess this is a defensive/healing spell */
791 if (spell_item->range<=1 || spell_item->stats.dam < 0) 823 if (spell_item->range <= 1 || spell_item->stats.dam < 0)
792 dir = 0; 824 dir = 0;
793 825
794 /* Monster doesn't have enough spell-points */ 826 /* Monster doesn't have enough spell-points */
795 if(head->stats.sp<SP_level_spellpoint_cost(head,spell_item, SPELL_MANA)) 827 if (head->stats.sp < SP_level_spellpoint_cost (head, spell_item, SPELL_MANA))
796 return 0; 828 return 0;
797 829
798 if(head->stats.grace<SP_level_spellpoint_cost(head,spell_item, SPELL_GRACE)) 830 if (head->stats.grace < SP_level_spellpoint_cost (head, spell_item, SPELL_GRACE))
799 return 0; 831 return 0;
800 832
801 head->stats.sp-=SP_level_spellpoint_cost(head,spell_item, SPELL_MANA); 833 head->stats.sp -= SP_level_spellpoint_cost (head, spell_item, SPELL_MANA);
802 head->stats.grace-=SP_level_spellpoint_cost(head,spell_item, SPELL_GRACE); 834 head->stats.grace -= SP_level_spellpoint_cost (head, spell_item, SPELL_GRACE);
803 835
804 /* set this to null, so next time monster will choose something different */ 836 /* set this to null, so next time monster will choose something different */
805 head->spellitem = NULL; 837 head->spellitem = NULL;
806 838
807 return cast_spell(part,part,dir, spell_item, NULL); 839 return cast_spell (part, part, dir, spell_item, NULL);
808} 840}
809 841
810 842
843int
811int monster_use_scroll(object *head, object *part,object *pl,int dir, rv_vector *rv) { 844monster_use_scroll (object *head, object *part, object *pl, int dir, rv_vector * rv)
845{
812 object *scroll; 846 object *scroll;
813 object *owner; 847 object *owner;
814 rv_vector rv1; 848 rv_vector rv1;
815 849
816 /* If you want monsters to cast spells over friends, this spell should 850 /* If you want monsters to cast spells over friends, this spell should
817 * be removed. It probably should be in most cases, since monsters still 851 * be removed. It probably should be in most cases, since monsters still
818 * don't care about residual effects (ie, casting a cone which may have a 852 * don't care about residual effects (ie, casting a cone which may have a
819 * clear path to the player, the side aspects of the code will still hit 853 * clear path to the player, the side aspects of the code will still hit
820 * other monsters) 854 * other monsters)
821 */ 855 */
822 if(!(dir=path_to_player(part,pl,0))) 856 if (!(dir = path_to_player (part, pl, 0)))
823 return 0; 857 return 0;
858
859 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
824 860 {
825 if(QUERY_FLAG(head,FLAG_FRIENDLY) && (owner = get_owner(head)) != NULL) {
826 get_rangevector(head, owner, &rv1, 0x1); 861 get_rangevector (head, owner, &rv1, 0x1);
827 if(dirdiff(dir,rv1.direction) < 2) { 862 if (dirdiff (dir, rv1.direction) < 2)
863 {
828 return 0; /* Might hit owner with spell */ 864 return 0; /* Might hit owner with spell */
829 } 865 }
830 } 866 }
831 867
832 if(QUERY_FLAG(head,FLAG_CONFUSED)) 868 if (QUERY_FLAG (head, FLAG_CONFUSED))
833 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2); 869 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
834 870
835 for (scroll=head->inv; scroll; scroll=scroll->below) 871 for (scroll = head->inv; scroll; scroll = scroll->below)
836 if (scroll->type == SCROLL && monster_should_cast_spell(head, scroll->inv)) break; 872 if (scroll->type == SCROLL && monster_should_cast_spell (head, scroll->inv))
873 break;
837 874
838 /* Used up all his scrolls, so nothing do to */ 875 /* Used up all his scrolls, so nothing do to */
839 if (!scroll) { 876 if (!scroll)
877 {
840 CLEAR_FLAG(head, FLAG_READY_SCROLL); 878 CLEAR_FLAG (head, FLAG_READY_SCROLL);
841 return 0; 879 return 0;
842 } 880 }
843 881
844 /* Spell should be cast on caster (ie, heal, strength) */ 882 /* Spell should be cast on caster (ie, heal, strength) */
845 if (scroll->inv->range==0) 883 if (scroll->inv->range == 0)
846 dir = 0; 884 dir = 0;
847 885
848 apply_scroll(part, scroll, dir); 886 apply_scroll (part, scroll, dir);
849 return 1; 887 return 1;
850} 888}
851 889
852/* monster_use_skill()-implemented 95-04-28 to allow monster skill use. 890/* monster_use_skill()-implemented 95-04-28 to allow monster skill use.
853 * Note that monsters do not need the skills SK_MELEE_WEAPON and 891 * Note that monsters do not need the skills SK_MELEE_WEAPON and
854 * SK_MISSILE_WEAPON to make those respective attacks, if we 892 * SK_MISSILE_WEAPON to make those respective attacks, if we
857 * 895 *
858 * The skills we are treating here are all but those. -b.t. 896 * The skills we are treating here are all but those. -b.t.
859 * 897 *
860 * At the moment this is only useful for throwing, perhaps for 898 * At the moment this is only useful for throwing, perhaps for
861 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01 899 * stealing. TODO: This should be more integrated in the game. -MT, 25.11.01
862 */ 900 */
863 901
902int
864int monster_use_skill(object *head, object *part, object *pl,int dir) { 903monster_use_skill (object *head, object *part, object *pl, int dir)
904{
865 object *skill, *owner; 905 object *skill, *owner;
866 906
867 if(!(dir=path_to_player(part,pl,0))) 907 if (!(dir = path_to_player (part, pl, 0)))
868 return 0; 908 return 0;
869 909
870 if(QUERY_FLAG(head,FLAG_FRIENDLY) && (owner = get_owner(head)) != NULL) { 910 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
911 {
871 int dir2 = find_dir_2(head->x-owner->x, head->y-owner->y); 912 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
913
872 if(dirdiff(dir,dir2) < 1) 914 if (dirdiff (dir, dir2) < 1)
873 return 0; /* Might hit owner with skill -thrown rocks for example ?*/ 915 return 0; /* Might hit owner with skill -thrown rocks for example ? */
874 } 916 }
875 if(QUERY_FLAG(head,FLAG_CONFUSED)) 917 if (QUERY_FLAG (head, FLAG_CONFUSED))
876 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2); 918 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
877 919
878 /* skill selection - monster will use the next unused skill. 920 /* skill selection - monster will use the next unused skill.
879 * well...the following scenario will allow the monster to 921 * well...the following scenario will allow the monster to
880 * toggle between 2 skills. One day it would be nice to make 922 * toggle between 2 skills. One day it would be nice to make
881 * more skills available to monsters. 923 * more skills available to monsters.
882 */ 924 */
883 925
884 for(skill=head->inv;skill!=NULL;skill=skill->below) 926 for (skill = head->inv; skill != NULL; skill = skill->below)
885 if(skill->type==SKILL && skill!=head->chosen_skill) { 927 if (skill->type == SKILL && skill != head->chosen_skill)
928 {
886 head->chosen_skill=skill; 929 head->chosen_skill = skill;
887 break; 930 break;
888 } 931 }
889 932
890 if(!skill && !head->chosen_skill) { 933 if (!skill && !head->chosen_skill)
934 {
891 LOG(llevDebug,"Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", 935 LOG (llevDebug, "Error: Monster %s (%d) has FLAG_READY_SKILL without skill.\n", &head->name, head->count);
892 head->name,head->count);
893 CLEAR_FLAG(head, FLAG_READY_SKILL); 936 CLEAR_FLAG (head, FLAG_READY_SKILL);
894 return 0; 937 return 0;
895 } 938 }
896 /* use skill */ 939 /* use skill */
897 return do_skill(head, part, head->chosen_skill,dir,NULL); 940 return do_skill (head, part, head->chosen_skill, dir, NULL);
898} 941}
899 942
900/* Monster will use a ranged spell attack. */ 943/* Monster will use a ranged spell attack. */
901 944
945int
902int monster_use_range(object *head,object *part,object *pl,int dir) 946monster_use_range (object *head, object *part, object *pl, int dir)
903 { 947{
904 object *wand, *owner; 948 object *wand, *owner;
905 int at_least_one = 0; 949 int at_least_one = 0;
906 950
907 if(!(dir=path_to_player(part,pl,0))) 951 if (!(dir = path_to_player (part, pl, 0)))
908 return 0; 952 return 0;
909 953
910 if(QUERY_FLAG(head,FLAG_FRIENDLY) && (owner = get_owner(head)) != NULL) { 954 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
955 {
911 int dir2 = find_dir_2(head->x-owner->x, head->y-owner->y); 956 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
957
912 if(dirdiff(dir,dir2) < 2) 958 if (dirdiff (dir, dir2) < 2)
913 return 0; /* Might hit owner with spell */ 959 return 0; /* Might hit owner with spell */
914 } 960 }
915 if(QUERY_FLAG(head,FLAG_CONFUSED)) 961 if (QUERY_FLAG (head, FLAG_CONFUSED))
916 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2); 962 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
917 963
918 for(wand=head->inv;wand!=NULL;wand=wand->below) 964 for (wand = head->inv; wand != NULL; wand = wand->below)
919 { 965 {
920 if (wand->type == WAND) 966 if (wand->type == WAND)
967 {
968 /* Found a wand, let's see if it has charges left */
969 at_least_one = 1;
970 if (wand->stats.food <= 0)
971 continue;
972
973 cast_spell (head, wand, dir, wand->inv, NULL);
974
975 if (!(--wand->stats.food))
921 { 976 {
922 /* Found a wand, let's see if it has charges left */ 977 if (wand->arch)
923 at_least_one = 1;
924 if( wand->stats.food<=0 )
925 continue;
926
927 cast_spell( head, wand, dir, wand->inv, NULL );
928
929 if ( !( --wand->stats.food ) )
930 { 978 {
931 if ( wand->arch )
932 {
933 CLEAR_FLAG(wand, FLAG_ANIMATE); 979 CLEAR_FLAG (wand, FLAG_ANIMATE);
934 wand->face = wand->arch->clone.face; 980 wand->face = wand->arch->clone.face;
935 wand->speed = 0; 981 wand->set_speed (0);
936 update_ob_speed(wand);
937 }
938 } 982 }
939 /* Success */
940 return 1;
941 } 983 }
984 /* Success */
985 return 1;
986 }
942 else if ( wand->type == ROD || wand->type==HORN ) { 987 else if (wand->type == ROD || wand->type == HORN)
988 {
943 /* Found rod/horn, let's use it if possible */ 989 /* Found rod/horn, let's use it if possible */
944 at_least_one = 1; 990 at_least_one = 1;
945 if( wand->stats.hp < MAX( wand->inv->stats.sp, wand->inv->stats.grace ) ) 991 if (wand->stats.hp < MAX (wand->inv->stats.sp, wand->inv->stats.grace))
946 continue; 992 continue;
947 993
948 /* drain charge before casting spell - can be a case where the 994 /* drain charge before casting spell - can be a case where the
949 * spell destroys the monster, and rod, so if done after, results 995 * spell destroys the monster, and rod, so if done after, results
950 * in crash. 996 * in crash.
951 */ 997 */
952 drain_rod_charge( wand ); 998 drain_rod_charge (wand);
953 cast_spell( head, wand, dir, wand->inv, NULL ); 999 cast_spell (head, wand, dir, wand->inv, NULL);
954 1000
955 /* Success */ 1001 /* Success */
956 return 1; 1002 return 1;
957 } 1003 }
958 } 1004 }
959 1005
960 if ( at_least_one ) 1006 if (at_least_one)
961 return 0; 1007 return 0;
962 1008
963 LOG(llevError,"Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", 1009 LOG (llevError, "Error: Monster %s (%d) HAS_READY_RANG() without wand/horn/rod.\n", &head->name, head->count);
964 head->name,head->count);
965 CLEAR_FLAG(head, FLAG_READY_RANGE); 1010 CLEAR_FLAG (head, FLAG_READY_RANGE);
966 return 0; 1011 return 0;
967 } 1012}
968 1013
1014int
969int monster_use_bow(object *head, object *part, object *pl, int dir) { 1015monster_use_bow (object *head, object *part, object *pl, int dir)
1016{
970 object *owner; 1017 object *owner;
971 1018
972 if(!(dir=path_to_player(part,pl,0))) 1019 if (!(dir = path_to_player (part, pl, 0)))
973 return 0; 1020 return 0;
974 if(QUERY_FLAG(head,FLAG_CONFUSED)) 1021 if (QUERY_FLAG (head, FLAG_CONFUSED))
975 dir = absdir(dir + RANDOM()%3 + RANDOM()%3 - 2); 1022 dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2);
976 1023
977 if(QUERY_FLAG(head,FLAG_FRIENDLY) && (owner = get_owner(head)) != NULL) { 1024 if (QUERY_FLAG (head, FLAG_FRIENDLY) && (owner = head->owner) != NULL)
1025 {
978 int dir2 = find_dir_2(head->x-owner->x, head->y-owner->y); 1026 int dir2 = find_dir_2 (head->x - owner->x, head->y - owner->y);
1027
979 if(dirdiff(dir,dir2) < 1) 1028 if (dirdiff (dir, dir2) < 1)
980 return 0; /* Might hit owner with arrow */ 1029 return 0; /* Might hit owner with arrow */
981 } 1030 }
982 1031
983 /* in server/player.c */ 1032 /* in server/player.c */
984 return fire_bow(head, part, NULL, dir, 0, part->x, part->y); 1033 return fire_bow (head, part, NULL, dir, 0, part->x, part->y);
985 1034
986} 1035}
987 1036
988/* Checks if putting on 'item' will make 'who' do more 1037/* Checks if putting on 'item' will make 'who' do more
989 * damage. This is a very simplistic check - also checking things 1038 * damage. This is a very simplistic check - also checking things
990 * like speed and ac are also relevant. 1039 * like speed and ac are also relevant.
991 * 1040 *
992 * return true if item is a better object. 1041 * return true if item is a better object.
993 */ 1042 */
994 1043
1044int
995int check_good_weapon(object *who, object *item) { 1045check_good_weapon (object *who, object *item)
1046{
996 object *other_weap; 1047 object *other_weap;
997 int val=0, i; 1048 int val = 0, i;
998 1049
999 for(other_weap=who->inv;other_weap!=NULL;other_weap=other_weap->below) 1050 for (other_weap = who->inv; other_weap != NULL; other_weap = other_weap->below)
1000 if(other_weap->type==item->type&&QUERY_FLAG(other_weap,FLAG_APPLIED)) 1051 if (other_weap->type == item->type && QUERY_FLAG (other_weap, FLAG_APPLIED))
1001 break; 1052 break;
1002 1053
1003 if(other_weap==NULL) /* No other weapons */ 1054 if (other_weap == NULL) /* No other weapons */
1004 return 1; 1055 return 1;
1005 1056
1006 /* Rather than go through and apply the new one, and see if it is 1057 /* Rather than go through and apply the new one, and see if it is
1007 * better, just do some simple checks 1058 * better, just do some simple checks
1008 * Put some multipliers for things that hvae several effects, 1059 * Put some multipliers for things that hvae several effects,
1009 * eg, magic affects both damage and wc, so it has more weight 1060 * eg, magic affects both damage and wc, so it has more weight
1010 */ 1061 */
1011 1062
1012 val = item->stats.dam - other_weap->stats.dam; 1063 val = item->stats.dam - other_weap->stats.dam;
1013 val += (item->magic - other_weap->magic) * 3; 1064 val += (item->magic - other_weap->magic) * 3;
1014 /* Monsters don't really get benefits from things like regen rates 1065 /* Monsters don't really get benefits from things like regen rates
1015 * from items. But the bonus for their stats are very important. 1066 * from items. But the bonus for their stats are very important.
1016 */ 1067 */
1017 for (i=0; i<NUM_STATS; i++) 1068 for (i = 0; i < NUM_STATS; i++)
1018 val += (get_attr_value(&item->stats, i) - get_attr_value(&other_weap->stats, i))*2; 1069 val += (get_attr_value (&item->stats, i) - get_attr_value (&other_weap->stats, i)) * 2;
1019 1070
1020 if (val > 0) return 1; 1071 if (val > 0)
1072 return 1;
1073 else
1021 else return 0; 1074 return 0;
1022 1075
1023} 1076}
1024 1077
1078int
1025int check_good_armour(object *who, object *item) { 1079check_good_armour (object *who, object *item)
1080{
1026 object *other_armour; 1081 object *other_armour;
1027 int val=0,i; 1082 int val = 0, i;
1028 1083
1029 for (other_armour = who->inv; other_armour != NULL; 1084 for (other_armour = who->inv; other_armour != NULL; other_armour = other_armour->below)
1030 other_armour = other_armour->below)
1031 if (other_armour->type == item->type && QUERY_FLAG(other_armour,FLAG_APPLIED)) 1085 if (other_armour->type == item->type && QUERY_FLAG (other_armour, FLAG_APPLIED))
1032 break; 1086 break;
1033 1087
1034 if (other_armour == NULL) /* No other armour, use the new */ 1088 if (other_armour == NULL) /* No other armour, use the new */
1035 return 1; 1089 return 1;
1036 1090
1037 /* Like above function , see which is better */ 1091 /* Like above function , see which is better */
1038 val = item->stats.ac - other_armour->stats.ac; 1092 val = item->stats.ac - other_armour->stats.ac;
1039 val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL])/5; 1093 val = (item->resist[ATNR_PHYSICAL] - other_armour->resist[ATNR_PHYSICAL]) / 5;
1040 val += (item->magic - other_armour->magic) * 3; 1094 val += (item->magic - other_armour->magic) * 3;
1041 1095
1042 /* for the other protections, do weigh them very much in the equation - 1096 /* for the other protections, do weigh them very much in the equation -
1043 * it is the armor protection which is most important, because there is 1097 * it is the armor protection which is most important, because there is
1044 * no good way to know what the player may attack the monster with. 1098 * no good way to know what the player may attack the monster with.
1045 * So if the new item has better protection than the old, give that higher 1099 * So if the new item has better protection than the old, give that higher
1046 * value. If the reverse, then decrease the value of this item some. 1100 * value. If the reverse, then decrease the value of this item some.
1047 */ 1101 */
1048 for (i=1; i <NROFATTACKS; i++) { 1102 for (i = 1; i < NROFATTACKS; i++)
1103 {
1049 if (item->resist[i] > other_armour->resist[i]) val++; 1104 if (item->resist[i] > other_armour->resist[i])
1105 val++;
1050 else if (item->resist[i] < other_armour->resist[i]) val--; 1106 else if (item->resist[i] < other_armour->resist[i])
1107 val--;
1051 } 1108 }
1052 1109
1053 /* Very few armours have stats, so not much need to worry about those. */ 1110 /* Very few armours have stats, so not much need to worry about those. */
1054 1111
1055 if (val > 0) return 1; 1112 if (val > 0)
1113 return 1;
1114 else
1056 else return 0; 1115 return 0;
1057 1116
1058} 1117}
1059 1118
1060/* 1119/*
1061 * monster_check_pickup(): checks for items that monster can pick up. 1120 * monster_check_pickup(): checks for items that monster can pick up.
1071 * became a recursive loop. It may be better to call monster_check_apply 1130 * became a recursive loop. It may be better to call monster_check_apply
1072 * after we pick everything up, since that function may call others which 1131 * after we pick everything up, since that function may call others which
1073 * affect stacking on this space. 1132 * affect stacking on this space.
1074 */ 1133 */
1075 1134
1135void
1076void monster_check_pickup(object *monster) { 1136monster_check_pickup (object *monster)
1137{
1077 object *tmp,*next; 1138 object *tmp, *next;
1078 int next_tag;
1079 1139
1080 for(tmp=monster->below;tmp!=NULL;tmp=next) { 1140 for (tmp = monster->below; tmp != NULL; tmp = next)
1141 {
1081 next=tmp->below; 1142 next = tmp->below;
1082 next_tag = next ? next->count : 0;
1083 if (monster_can_pick(monster,tmp)) { 1143 if (monster_can_pick (monster, tmp))
1084 remove_ob(tmp); 1144 {
1145 tmp->remove ();
1085 tmp = insert_ob_in_ob(tmp,monster); 1146 tmp = insert_ob_in_ob (tmp, monster);
1086 (void) monster_check_apply(monster,tmp); 1147 (void) monster_check_apply (monster, tmp);
1087 } 1148 }
1088 /* We could try to re-establish the cycling, of the space, but probably 1149 /* We could try to re-establish the cycling, of the space, but probably
1089 * not a big deal to just bail out. 1150 * not a big deal to just bail out.
1090 */ 1151 */
1091 if (next && was_destroyed(next, next_tag)) return; 1152 if (next && next->destroyed ())
1153 return;
1092 } 1154 }
1093} 1155}
1094 1156
1095/* 1157/*
1096 * monster_can_pick(): If the monster is interested in picking up 1158 * monster_can_pick(): If the monster is interested in picking up
1097 * the item, then return 0. Otherwise 0. 1159 * the item, then return 0. Otherwise 0.
1098 * Instead of pick_up, flags for "greed", etc, should be used. 1160 * Instead of pick_up, flags for "greed", etc, should be used.
1099 * I've already utilized flags for bows, wands, rings, etc, etc. -Frank. 1161 * I've already utilized flags for bows, wands, rings, etc, etc. -Frank.
1100 */ 1162 */
1101 1163
1164int
1102int monster_can_pick(object *monster, object *item) { 1165monster_can_pick (object *monster, object *item)
1166{
1103 int flag=0; 1167 int flag = 0;
1104 int i; 1168 int i;
1105 1169
1106 if(!can_pick(monster,item)) 1170 if (!can_pick (monster, item))
1107 return 0; 1171 return 0;
1108 1172
1109 if(QUERY_FLAG(item,FLAG_UNPAID)) 1173 if (QUERY_FLAG (item, FLAG_UNPAID))
1110 return 0; 1174 return 0;
1111 1175
1112 if (monster->pick_up&64) /* All */ 1176 if (monster->pick_up & 64) /* All */
1113 flag=1; 1177 flag = 1;
1114 1178
1179 else
1115 else switch(item->type) { 1180 switch (item->type)
1116 case MONEY: 1181 {
1117 case GEM: 1182 case MONEY:
1183 case GEM:
1118 flag=monster->pick_up&2; 1184 flag = monster->pick_up & 2;
1119 break; 1185 break;
1120 1186
1121 case FOOD: 1187 case FOOD:
1122 flag=monster->pick_up&4; 1188 flag = monster->pick_up & 4;
1123 break; 1189 break;
1124 1190
1125 case WEAPON: 1191 case WEAPON:
1126 flag=(monster->pick_up&8)||QUERY_FLAG(monster,FLAG_USE_WEAPON); 1192 flag = (monster->pick_up & 8) || QUERY_FLAG (monster, FLAG_USE_WEAPON);
1127 break; 1193 break;
1128 1194
1129 case ARMOUR: 1195 case ARMOUR:
1130 case SHIELD: 1196 case SHIELD:
1131 case HELMET: 1197 case HELMET:
1132 case BOOTS: 1198 case BOOTS:
1133 case GLOVES: 1199 case GLOVES:
1134 case GIRDLE: 1200 case GIRDLE:
1135 flag=(monster->pick_up&16)||QUERY_FLAG(monster,FLAG_USE_ARMOUR); 1201 flag = (monster->pick_up & 16) || QUERY_FLAG (monster, FLAG_USE_ARMOUR);
1136 break; 1202 break;
1137 1203
1138 case SKILL: 1204 case SKILL:
1139 flag=QUERY_FLAG(monster,FLAG_CAN_USE_SKILL); 1205 flag = QUERY_FLAG (monster, FLAG_CAN_USE_SKILL);
1140 break; 1206 break;
1141 1207
1142 case RING: 1208 case RING:
1143 flag=QUERY_FLAG(monster,FLAG_USE_RING); 1209 flag = QUERY_FLAG (monster, FLAG_USE_RING);
1144 break; 1210 break;
1145 1211
1146 case WAND: 1212 case WAND:
1147 case HORN: 1213 case HORN:
1148 case ROD: 1214 case ROD:
1149 flag=QUERY_FLAG(monster,FLAG_USE_RANGE); 1215 flag = QUERY_FLAG (monster, FLAG_USE_RANGE);
1150 break; 1216 break;
1151 1217
1152 case SPELLBOOK: 1218 case SPELLBOOK:
1153 flag=(monster->arch!=NULL&&QUERY_FLAG((&monster->arch->clone),FLAG_CAST_SPELL)); 1219 flag = (monster->arch != NULL && QUERY_FLAG ((&monster->arch->clone), FLAG_CAST_SPELL));
1154 break; 1220 break;
1155 1221
1156 case SCROLL: 1222 case SCROLL:
1157 flag = QUERY_FLAG(monster,FLAG_USE_SCROLL); 1223 flag = QUERY_FLAG (monster, FLAG_USE_SCROLL);
1158 break; 1224 break;
1159 1225
1160 case BOW: 1226 case BOW:
1161 case ARROW: 1227 case ARROW:
1162 flag=QUERY_FLAG(monster,FLAG_USE_BOW); 1228 flag = QUERY_FLAG (monster, FLAG_USE_BOW);
1163 break; 1229 break;
1164 } 1230 }
1165 /* Simplistic check - if the monster has a location to equip it, he will 1231 /* Simplistic check - if the monster has a location to equip it, he will
1166 * pick it up. Note that this doesn't handle cases where an item may 1232 * pick it up. Note that this doesn't handle cases where an item may
1167 * use several locations. 1233 * use several locations.
1168 */ 1234 */
1169 for (i=0; i < NUM_BODY_LOCATIONS; i++) { 1235 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1236 {
1170 if (monster->body_info[i] && item->body_info[i]) { 1237 if (monster->body_info[i] && item->body_info[i])
1171 flag=1; 1238 {
1172 break; 1239 flag = 1;
1173 } 1240 break;
1241 }
1174 } 1242 }
1175 1243
1176 if (((!(monster->pick_up&32))&&flag) || ((monster->pick_up&32)&&(!flag))) 1244 if (((!(monster->pick_up & 32)) && flag) || ((monster->pick_up & 32) && (!flag)))
1177 return 1;
1178 return 0; 1245 return 1;
1246 return 0;
1179} 1247}
1180 1248
1181/* 1249/*
1182 * monster_apply_below(): 1250 * monster_apply_below():
1183 * Vick's (vick@bern.docs.uu.se) @921107 -> If a monster who's 1251 * Vick's (vick@bern.docs.uu.se) @921107 -> If a monster who's
1184 * eager to apply things, encounters something apply-able, 1252 * eager to apply things, encounters something apply-able,
1185 * then make him apply it 1253 * then make him apply it
1186 */ 1254 */
1187 1255
1256void
1188void monster_apply_below(object *monster) { 1257monster_apply_below (object *monster)
1258{
1189 object *tmp, *next; 1259 object *tmp, *next;
1190 1260
1191 for(tmp=monster->below;tmp!=NULL;tmp=next) { 1261 for (tmp = monster->below; tmp != NULL; tmp = next)
1262 {
1192 next=tmp->below; 1263 next = tmp->below;
1193 switch (tmp->type) { 1264 switch (tmp->type)
1265 {
1194 case CF_HANDLE: 1266 case CF_HANDLE:
1195 case TRIGGER: 1267 case TRIGGER:
1196 if (monster->will_apply&1) 1268 if (monster->will_apply & 1)
1197 manual_apply(monster,tmp,0); 1269 manual_apply (monster, tmp, 0);
1198 break; 1270 break;
1199 1271
1200 case TREASURE: 1272 case TREASURE:
1201 if (monster->will_apply&2) 1273 if (monster->will_apply & 2)
1202 manual_apply(monster,tmp,0); 1274 manual_apply (monster, tmp, 0);
1203 break; 1275 break;
1204 1276
1205 } 1277 }
1206 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 1278 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1207 break; 1279 break;
1208 } 1280 }
1209} 1281}
1210 1282
1211/* 1283/*
1212 * monster_check_apply() is meant to be called after an item is 1284 * monster_check_apply() is meant to be called after an item is
1218 * they can pick up all that they can use. 1290 * they can pick up all that they can use.
1219 */ 1291 */
1220 1292
1221/* Sept 96, fixed this so skills will be readied -b.t.*/ 1293/* Sept 96, fixed this so skills will be readied -b.t.*/
1222 1294
1295void
1223void monster_check_apply(object *mon, object *item) { 1296monster_check_apply (object *mon, object *item)
1297{
1224 1298
1225 int flag = 0; 1299 int flag = 0;
1226 1300
1227 if(item->type==SPELLBOOK&&
1228 mon->arch!=NULL&&(QUERY_FLAG((&mon->arch->clone),FLAG_CAST_SPELL))) { 1301 if (item->type == SPELLBOOK && mon->arch != NULL && (QUERY_FLAG ((&mon->arch->clone), FLAG_CAST_SPELL)))
1302 {
1229 SET_FLAG(mon, FLAG_CAST_SPELL); 1303 SET_FLAG (mon, FLAG_CAST_SPELL);
1230 return; 1304 return;
1231 } 1305 }
1232 1306
1233 /* If for some reason, this item is already applied, no more work to do */ 1307 /* If for some reason, this item is already applied, no more work to do */
1234 if(QUERY_FLAG(item,FLAG_APPLIED)) return; 1308 if (QUERY_FLAG (item, FLAG_APPLIED))
1235
1236 /* Might be better not to do this - if the monster can fire a bow,
1237 * it is possible in his wanderings, he will find one to use. In
1238 * which case, it would be nice to have ammo for it.
1239 */
1240 if(QUERY_FLAG(mon,FLAG_USE_BOW) && item->type==ARROW) {
1241 /* Check for the right kind of bow */
1242 object *bow;
1243 for(bow=mon->inv;bow!=NULL;bow=bow->below)
1244 if(bow->type==BOW && bow->race==item->race) {
1245 SET_FLAG(mon, FLAG_READY_BOW);
1246 LOG(llevMonster,"Found correct bow for arrows.\n");
1247 return; /* nothing more to do for arrows */
1248 }
1249 }
1250
1251 if (item->type == TREASURE && mon->will_apply & WILL_APPLY_TREASURE) flag=1;
1252 /* Eating food gets hp back */
1253 else if (item->type == FOOD && mon->will_apply & WILL_APPLY_FOOD) flag=1;
1254 else if (item->type == SCROLL && QUERY_FLAG(mon, FLAG_USE_SCROLL)) {
1255 if (!item->inv)
1256 LOG(llevDebug,"Monster %d having scroll %d with empty inventory!", mon->count, item->count);
1257 else if (monster_should_cast_spell(mon, item->inv))
1258 SET_FLAG(mon, FLAG_READY_SCROLL);
1259 /* Don't use it right now */
1260 return;
1261 }
1262 else if (item->type == WEAPON) flag = check_good_weapon(mon,item);
1263 else if (IS_ARMOR(item)) flag = check_good_armour(mon,item);
1264 /* Should do something more, like make sure this is a better item */
1265 else if (item->type == RING)
1266 flag=1;
1267 else if ( item->type==WAND || item->type == ROD || item->type==HORN )
1268 {
1269 /* We never really 'ready' the wand/rod/horn, because that would mean the
1270 * weapon would get undone.
1271 */
1272 if (!(can_apply_object(mon, item) & CAN_APPLY_NOT_MASK))
1273 {
1274 SET_FLAG(mon, FLAG_READY_RANGE);
1275 SET_FLAG(item, FLAG_APPLIED);
1276 }
1277 return;
1278 }
1279 else if (item->type == BOW) {
1280 /* We never really 'ready' the bow, because that would mean the
1281 * weapon would get undone.
1282 */
1283 if (!(can_apply_object(mon, item) & CAN_APPLY_NOT_MASK))
1284 SET_FLAG(mon, FLAG_READY_BOW);
1285 return;
1286 }
1287 else if ( item->type == SKILL )
1288 {
1289 /*
1290 * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1291 * else they can't use the skill...
1292 * Skills also don't need to get applied, so return now.
1293 */
1294 SET_FLAG(mon, FLAG_READY_SKILL);
1295 return;
1296 }
1297
1298
1299 /* if we don't match one of the above types, return now.
1300 * can_apply_object will say that we can apply things like flesh,
1301 * bolts, and whatever else, because it only checks against the
1302 * body_info locations.
1303 */
1304 if (!flag) return;
1305
1306 /* Check to see if the monster can use this item. If not, no need
1307 * to do further processing. Note that can_apply_object already checks
1308 * for the CAN_USE flags.
1309 */
1310 if (can_apply_object(mon, item) & CAN_APPLY_NOT_MASK) return;
1311
1312 /* should only be applying this item, not unapplying it.
1313 * also, ignore status of curse so they can take off old armour.
1314 * monsters have some advantages after all.
1315 */
1316 manual_apply(mon, item, AP_APPLY | AP_IGNORE_CURSE);
1317
1318 return; 1309 return;
1319}
1320 1310
1311 /* Might be better not to do this - if the monster can fire a bow,
1312 * it is possible in his wanderings, he will find one to use. In
1313 * which case, it would be nice to have ammo for it.
1314 */
1315 if (QUERY_FLAG (mon, FLAG_USE_BOW) && item->type == ARROW)
1316 {
1317 /* Check for the right kind of bow */
1318 object *bow;
1319
1320 for (bow = mon->inv; bow != NULL; bow = bow->below)
1321 if (bow->type == BOW && bow->race == item->race)
1322 {
1323 SET_FLAG (mon, FLAG_READY_BOW);
1324 LOG (llevMonster, "Found correct bow for arrows.\n");
1325 return; /* nothing more to do for arrows */
1326 }
1327 }
1328
1329 if (item->type == TREASURE && mon->will_apply & WILL_APPLY_TREASURE)
1330 flag = 1;
1331 /* Eating food gets hp back */
1332 else if (item->type == FOOD && mon->will_apply & WILL_APPLY_FOOD)
1333 flag = 1;
1334 else if (item->type == SCROLL && QUERY_FLAG (mon, FLAG_USE_SCROLL))
1335 {
1336 if (!item->inv)
1337 LOG (llevDebug, "Monster %d having scroll %d with empty inventory!", mon->count, item->count);
1338 else if (monster_should_cast_spell (mon, item->inv))
1339 SET_FLAG (mon, FLAG_READY_SCROLL);
1340 /* Don't use it right now */
1341 return;
1342 }
1343 else if (item->type == WEAPON)
1344 flag = check_good_weapon (mon, item);
1345 else if (item->is_armor ())
1346 flag = check_good_armour (mon, item);
1347 /* Should do something more, like make sure this is a better item */
1348 else if (item->type == RING)
1349 flag = 1;
1350 else if (item->type == WAND || item->type == ROD || item->type == HORN)
1351 {
1352 /* We never really 'ready' the wand/rod/horn, because that would mean the
1353 * weapon would get undone.
1354 */
1355 if (!(can_apply_object (mon, item) & CAN_APPLY_NOT_MASK))
1356 {
1357 SET_FLAG (mon, FLAG_READY_RANGE);
1358 SET_FLAG (item, FLAG_APPLIED);
1359 }
1360 return;
1361 }
1362 else if (item->type == BOW)
1363 {
1364 /* We never really 'ready' the bow, because that would mean the
1365 * weapon would get undone.
1366 */
1367 if (!(can_apply_object (mon, item) & CAN_APPLY_NOT_MASK))
1368 SET_FLAG (mon, FLAG_READY_BOW);
1369 return;
1370 }
1371 else if (item->type == SKILL)
1372 {
1373 /*
1374 * skills are specials: monsters must have the 'FLAG_READY_SKILL' flag set,
1375 * else they can't use the skill...
1376 * Skills also don't need to get applied, so return now.
1377 */
1378 SET_FLAG (mon, FLAG_READY_SKILL);
1379 return;
1380 }
1381
1382
1383 /* if we don't match one of the above types, return now.
1384 * can_apply_object will say that we can apply things like flesh,
1385 * bolts, and whatever else, because it only checks against the
1386 * body_info locations.
1387 */
1388 if (!flag)
1389 return;
1390
1391 /* Check to see if the monster can use this item. If not, no need
1392 * to do further processing. Note that can_apply_object already checks
1393 * for the CAN_USE flags.
1394 */
1395 if (can_apply_object (mon, item) & CAN_APPLY_NOT_MASK)
1396 return;
1397
1398 /* should only be applying this item, not unapplying it.
1399 * also, ignore status of curse so they can take off old armour.
1400 * monsters have some advantages after all.
1401 */
1402 manual_apply (mon, item, AP_APPLY | AP_IGNORE_CURSE);
1403
1404 return;
1405}
1406
1407void
1321void npc_call_help(object *op) { 1408npc_call_help (object *op)
1409{
1322 int x,y, mflags; 1410 int x, y, mflags;
1323 object *npc; 1411 object *npc;
1324 sint16 sx, sy; 1412 sint16 sx, sy;
1325 mapstruct *m; 1413 maptile *m;
1326 1414
1327 for(x = -3; x < 4; x++) 1415 for (x = -3; x < 4; x++)
1328 for(y = -3; y < 4; y++) { 1416 for (y = -3; y < 4; y++)
1417 {
1329 m = op->map; 1418 m = op->map;
1330 sx = op->x + x; 1419 sx = op->x + x;
1331 sy = op->y + y; 1420 sy = op->y + y;
1332 mflags = get_map_flags(m, &m, sx, sy, &sx, &sy); 1421 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1333 /* If nothing alive on this space, no need to search the space. */ 1422 /* If nothing alive on this space, no need to search the space. */
1334 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE)) 1423 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE))
1335 continue; 1424 continue;
1336 1425
1337 for(npc = get_map_ob(m,sx,sy);npc!=NULL;npc=npc->above) 1426 for (npc = GET_MAP_OB (m, sx, sy); npc != NULL; npc = npc->above)
1338 if(QUERY_FLAG(npc, FLAG_ALIVE)&&QUERY_FLAG(npc, FLAG_UNAGGRESSIVE)) 1427 if (QUERY_FLAG (npc, FLAG_ALIVE) && QUERY_FLAG (npc, FLAG_UNAGGRESSIVE))
1339 npc->enemy = op->enemy; 1428 npc->enemy = op->enemy;
1340 } 1429 }
1341} 1430}
1342 1431
1343 1432
1433int
1344int dist_att (int dir , object *ob, object *enemy, object *part, rv_vector *rv) { 1434dist_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1435{
1345 1436
1346 if (can_hit(part,enemy,rv)) 1437 if (can_hit (part, enemy, rv))
1347 return dir; 1438 return dir;
1348 if (rv->distance < 10) 1439 if (rv->distance < 10)
1349 return absdir(dir+4); 1440 return absdir (dir + 4);
1350 else if (rv->distance>18) 1441 else if (rv->distance > 18)
1351 return dir; 1442 return dir;
1352 return 0; 1443 return 0;
1353} 1444}
1354 1445
1446int
1355int run_att (int dir, object *ob, object *enemy,object *part, rv_vector *rv) { 1447run_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1448{
1356 1449
1357 if ((can_hit (part,enemy,rv) && ob->move_status <20) || ob->move_status <20) { 1450 if ((can_hit (part, enemy, rv) && ob->move_status < 20) || ob->move_status < 20)
1451 {
1358 ob->move_status++; 1452 ob->move_status++;
1359 return (dir); 1453 return (dir);
1360 } 1454 }
1361 else if (ob->move_status >20) 1455 else if (ob->move_status > 20)
1362 ob->move_status = 0;
1363 return absdir (dir+4);
1364}
1365
1366int hitrun_att (int dir, object *ob,object *enemy) {
1367 if (ob->move_status ++ < 25)
1368 return dir;
1369 else if (ob->move_status <50)
1370 return absdir (dir+4);
1371 else
1372 ob->move_status = 0;
1373 return absdir(dir+4);
1374}
1375
1376int wait_att (int dir, object *ob,object *enemy,object *part,rv_vector *rv) {
1377
1378 int inrange = can_hit (part, enemy,rv);
1379
1380 if (ob->move_status || inrange)
1381 ob->move_status++;
1382
1383 if (ob->move_status == 0)
1384 return 0;
1385 else if (ob->move_status <10)
1386 return dir;
1387 else if (ob->move_status <15)
1388 return absdir(dir+4);
1389 ob->move_status = 0; 1456 ob->move_status = 0;
1390 return 0;
1391}
1392
1393int disthit_att (int dir, object *ob, object *enemy, object *part,rv_vector *rv) {
1394
1395 /* The logic below here looked plain wrong before. Basically, what should
1396 * happen is that if the creatures hp percentage falls below run_away,
1397 * the creature should run away (dir+4)
1398 * I think its wrong for a creature to have a zero maxhp value, but
1399 * at least one map has this set, and whatever the map contains, the
1400 * server should try to be resilant enough to avoid the problem
1401 */
1402 if (ob->stats.maxhp && (ob->stats.hp*100)/ob->stats.maxhp < ob->run_away)
1403 return absdir(dir+4);
1404 return dist_att (dir,ob,enemy,part,rv);
1405}
1406
1407int wait_att2 (int dir, object *ob,object *enemy,object *part, rv_vector *rv) {
1408 if (rv->distance < 9)
1409 return absdir (dir+4); 1457 return absdir (dir + 4);
1458}
1459
1460int
1461hitrun_att (int dir, object *ob, object *enemy)
1462{
1463 if (ob->move_status++ < 25)
1410 return 0; 1464 return dir;
1411} 1465 else if (ob->move_status < 50)
1412 1466 return absdir (dir + 4);
1413void circ1_move (object *ob) { 1467 else
1414 static int circle [12] = {3,3,4,5,5,6,7,7,8,1,1,2};
1415 if(++ob->move_status > 11)
1416 ob->move_status = 0; 1468 ob->move_status = 0;
1417 if (!(move_object(ob,circle[ob->move_status]))) 1469 return absdir (dir + 4);
1418 (void) move_object(ob,RANDOM()%8+1);
1419} 1470}
1420 1471
1472int
1473wait_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1474{
1475
1476 int inrange = can_hit (part, enemy, rv);
1477
1478 if (ob->move_status || inrange)
1479 ob->move_status++;
1480
1481 if (ob->move_status == 0)
1482 return 0;
1483 else if (ob->move_status < 10)
1484 return dir;
1485 else if (ob->move_status < 15)
1486 return absdir (dir + 4);
1487 ob->move_status = 0;
1488 return 0;
1489}
1490
1491int
1492disthit_att (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1493{
1494
1495 /* The logic below here looked plain wrong before. Basically, what should
1496 * happen is that if the creatures hp percentage falls below run_away,
1497 * the creature should run away (dir+4)
1498 * I think its wrong for a creature to have a zero maxhp value, but
1499 * at least one map has this set, and whatever the map contains, the
1500 * server should try to be resilant enough to avoid the problem
1501 */
1502 if (ob->stats.maxhp && (ob->stats.hp * 100) / ob->stats.maxhp < ob->run_away)
1503 return absdir (dir + 4);
1504 return dist_att (dir, ob, enemy, part, rv);
1505}
1506
1507int
1508wait_att2 (int dir, object *ob, object *enemy, object *part, rv_vector * rv)
1509{
1510 if (rv->distance < 9)
1511 return absdir (dir + 4);
1512 return 0;
1513}
1514
1515void
1421void circ2_move (object *ob) { 1516circ1_move (object *ob)
1517{
1422 static int circle[20] = {3,3,3,4,4,5,5,5,6,6,7,7,7,8,8,1,1,1,2,2}; 1518 static int circle[12] = { 3, 3, 4, 5, 5, 6, 7, 7, 8, 1, 1, 2 };
1423 if(++ob->move_status > 19) 1519 if (++ob->move_status > 11)
1424 ob->move_status = 0; 1520 ob->move_status = 0;
1425 if(!(move_object(ob,circle[ob->move_status]))) 1521 if (!(move_object (ob, circle[ob->move_status])))
1426 (void) move_object(ob,RANDOM()%8+1); 1522 (void) move_object (ob, RANDOM () % 8 + 1);
1427} 1523}
1428 1524
1525void
1526circ2_move (object *ob)
1527{
1528 static int circle[20] = { 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 1, 1, 1, 2, 2 };
1529 if (++ob->move_status > 19)
1530 ob->move_status = 0;
1531 if (!(move_object (ob, circle[ob->move_status])))
1532 (void) move_object (ob, RANDOM () % 8 + 1);
1533}
1534
1535void
1429void pace_movev(object *ob) { 1536pace_movev (object *ob)
1537{
1430 if (ob->move_status++ > 6) 1538 if (ob->move_status++ > 6)
1431 ob->move_status = 0; 1539 ob->move_status = 0;
1432 if (ob->move_status < 4) 1540 if (ob->move_status < 4)
1433 (void) move_object (ob,5); 1541 (void) move_object (ob, 5);
1434 else 1542 else
1435 (void) move_object(ob,1); 1543 (void) move_object (ob, 1);
1436} 1544}
1437 1545
1546void
1438void pace_moveh (object *ob) { 1547pace_moveh (object *ob)
1548{
1439 if (ob->move_status++ > 6) 1549 if (ob->move_status++ > 6)
1440 ob->move_status = 0; 1550 ob->move_status = 0;
1441 if (ob->move_status < 4) 1551 if (ob->move_status < 4)
1442 (void) move_object(ob,3); 1552 (void) move_object (ob, 3);
1443 else 1553 else
1444 (void) move_object(ob,7); 1554 (void) move_object (ob, 7);
1445} 1555}
1446 1556
1557void
1447void pace2_movev (object *ob) { 1558pace2_movev (object *ob)
1559{
1448 if (ob->move_status ++ > 16) 1560 if (ob->move_status++ > 16)
1449 ob->move_status = 0; 1561 ob->move_status = 0;
1450 if (ob->move_status <6) 1562 if (ob->move_status < 6)
1451 (void) move_object (ob,5); 1563 (void) move_object (ob, 5);
1452 else if (ob->move_status < 8) 1564 else if (ob->move_status < 8)
1453 return; 1565 return;
1454 else if (ob->move_status <13) 1566 else if (ob->move_status < 13)
1455 (void) move_object (ob,1); 1567 (void) move_object (ob, 1);
1568 else
1456 else return; 1569 return;
1457} 1570}
1458 1571
1572void
1459void pace2_moveh (object *ob) { 1573pace2_moveh (object *ob)
1574{
1460 if (ob->move_status ++ > 16) 1575 if (ob->move_status++ > 16)
1461 ob->move_status = 0; 1576 ob->move_status = 0;
1462 if (ob->move_status <6) 1577 if (ob->move_status < 6)
1463 (void) move_object (ob,3); 1578 (void) move_object (ob, 3);
1464 else if (ob->move_status < 8) 1579 else if (ob->move_status < 8)
1465 return; 1580 return;
1466 else if (ob->move_status <13) 1581 else if (ob->move_status < 13)
1467 (void) move_object (ob,7); 1582 (void) move_object (ob, 7);
1583 else
1468 else return; 1584 return;
1469} 1585}
1470 1586
1587void
1471void rand_move (object *ob) { 1588rand_move (object *ob)
1589{
1472 int i; 1590 int i;
1473 if (ob->move_status <1 || ob->move_status >8 || 1591
1474 !(move_object(ob,ob->move_status|| ! (RANDOM()% 9)))) 1592 if (ob->move_status < 1 || ob->move_status > 8 || !(move_object (ob, ob->move_status || !(RANDOM () % 9))))
1475 for (i = 0; i < 5; i++) 1593 for (i = 0; i < 5; i++)
1476 if (move_object(ob,ob->move_status = RANDOM()%8+1)) 1594 if (move_object (ob, ob->move_status = RANDOM () % 8 + 1))
1477 return; 1595 return;
1478} 1596}
1479 1597
1598void
1480void check_earthwalls(object *op, mapstruct *m, int x, int y) { 1599check_earthwalls (object *op, maptile *m, int x, int y)
1600{
1481 object *tmp; 1601 object *tmp;
1602
1482 for (tmp = get_map_ob(m, x, y); tmp!=NULL; tmp=tmp->above) { 1603 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1604 {
1483 if (tmp->type == EARTHWALL) { 1605 if (tmp->type == EARTHWALL)
1606 {
1484 hit_player(tmp,op->stats.dam,op,AT_PHYSICAL,1); 1607 hit_player (tmp, op->stats.dam, op, AT_PHYSICAL, 1);
1485 return; 1608 return;
1486 } 1609 }
1487 } 1610 }
1488} 1611}
1489 1612
1613void
1490void check_doors(object *op, mapstruct *m, int x, int y) { 1614check_doors (object *op, maptile *m, int x, int y)
1615{
1491 object *tmp; 1616 object *tmp;
1617
1492 for (tmp = get_map_ob(m, x, y); tmp!=NULL; tmp=tmp->above) { 1618 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above)
1619 {
1493 if (tmp->type == DOOR) { 1620 if (tmp->type == DOOR)
1621 {
1494 hit_player(tmp,1000,op,AT_PHYSICAL,1); 1622 hit_player (tmp, 1000, op, AT_PHYSICAL, 1);
1495 return; 1623 return;
1496 } 1624 }
1497 } 1625 }
1498} 1626}
1499 1627
1500/* find_mon_throw_ob() - modeled on find_throw_ob 1628/* find_mon_throw_ob() - modeled on find_throw_ob
1501 * This is probably overly simplistic as it is now - We want 1629 * This is probably overly simplistic as it is now - We want
1503 * furniture, even if they are not good throwable objects. 1631 * furniture, even if they are not good throwable objects.
1504 * Probably better to have the monster throw a throwable object 1632 * Probably better to have the monster throw a throwable object
1505 * first, then throw any non equipped weapon. 1633 * first, then throw any non equipped weapon.
1506 */ 1634 */
1507 1635
1636object *
1508object *find_mon_throw_ob( object *op ) { 1637find_mon_throw_ob (object *op)
1638{
1509 object *tmp = NULL; 1639 object *tmp = NULL;
1510
1511 if(op->head) tmp=op->head; else tmp=op;
1512 1640
1641 if (op->head)
1642 tmp = op->head;
1643 else
1644 tmp = op;
1645
1513 /* New throw code: look through the inventory. Grap the first legal is_thrown 1646 /* New throw code: look through the inventory. Grap the first legal is_thrown
1514 * marked item and throw it to the enemy. 1647 * marked item and throw it to the enemy.
1515 */ 1648 */
1516 1649
1517 for(tmp=op->inv;tmp;tmp=tmp->below) { 1650 for (tmp = op->inv; tmp; tmp = tmp->below)
1651 {
1518 1652
1519 /* Can't throw invisible objects or items that are applied */ 1653 /* Can't throw invisible objects or items that are applied */
1520 if(tmp->invisible || QUERY_FLAG(tmp,FLAG_APPLIED)) continue; 1654 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_APPLIED))
1655 continue;
1521 1656
1522 if(QUERY_FLAG(tmp,FLAG_IS_THROWN)) 1657 if (QUERY_FLAG (tmp, FLAG_IS_THROWN))
1523 break; 1658 break;
1524 1659
1525 } 1660 }
1526 1661
1527#ifdef DEBUG_THROW 1662#ifdef DEBUG_THROW
1528 LOG(llevDebug,"%s chooses to throw: %s (%d)\n",op->name, 1663 LOG (llevDebug, "%s chooses to throw: %s (%d)\n", op->name, !(tmp) ? "(nothing)" : query_name (tmp), tmp ? tmp->count : -1);
1529 !(tmp)?"(nothing)":query_name(tmp),tmp?tmp->count:-1);
1530#endif 1664#endif
1531 1665
1532 return tmp; 1666 return tmp;
1533} 1667}
1534 1668
1535/* determine if we can 'detect' the enemy. Check for walls blocking the 1669/* determine if we can 'detect' the enemy. Check for walls blocking the
1536 * los. Also, just because its hidden/invisible, we may be sensitive/smart 1670 * los. Also, just because its hidden/invisible, we may be sensitive/smart
1537 * enough (based on Wis & Int) to figure out where the enemy is. -b.t. 1671 * enough (based on Wis & Int) to figure out where the enemy is. -b.t.
1540 * OR y distance being within some range - that seemed wrong - both should 1674 * OR y distance being within some range - that seemed wrong - both should
1541 * be within the valid range. MSW 2001-08-05 1675 * be within the valid range. MSW 2001-08-05
1542 * Returns 0 if enemy can not be detected, 1 if it is detected 1676 * Returns 0 if enemy can not be detected, 1 if it is detected
1543 */ 1677 */
1544 1678
1679int
1545int can_detect_enemy (object *op, object *enemy, rv_vector *rv) { 1680can_detect_enemy (object *op, object *enemy, rv_vector * rv)
1681{
1546 int radius = MIN_MON_RADIUS, hide_discovery; 1682 int radius = MIN_MON_RADIUS, hide_discovery;
1547 1683
1548 /* null detection for any of these condtions always */ 1684 /* null detection for any of these condtions always */
1549 if(!op || !enemy || !op->map || !enemy->map) 1685 if (!op || !enemy || !op->map || !enemy->map)
1550 return 0; 1686 return 0;
1551 1687
1552 /* If the monster (op) has no way to get to the enemy, do nothing */ 1688 /* If the monster (op) has no way to get to the enemy, do nothing */
1553 if (!on_same_map(op, enemy)) 1689 if (!on_same_map (op, enemy))
1554 return 0; 1690 return 0;
1555 1691
1556 get_rangevector(op, enemy, rv, 0); 1692 get_rangevector (op, enemy, rv, 0);
1557 1693
1558 /* Monsters always ignore the DM */ 1694 /* Monsters always ignore the DM */
1559 if ( ( op->type != PLAYER ) && QUERY_FLAG( enemy, FLAG_WIZ ) ) 1695 if ((op->type != PLAYER) && QUERY_FLAG (enemy, FLAG_WIZ))
1560 return 0; 1696 return 0;
1561 1697
1562 /* simple check. Should probably put some range checks in here. */ 1698 /* simple check. Should probably put some range checks in here. */
1563 if(can_see_enemy(op,enemy)) return 1; 1699 if (can_see_enemy (op, enemy))
1700 return 1;
1564 1701
1565 /* The rest of this is for monsters. Players are on their own for 1702 /* The rest of this is for monsters. Players are on their own for
1566 * finding enemies! 1703 * finding enemies!
1567 */ 1704 */
1568 if(op->type==PLAYER) return 0; 1705 if (op->type == PLAYER)
1706 return 0;
1569 1707
1570 /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE 1708 /* Quality invisible? Bah, we wont see them w/o SEE_INVISIBLE
1571 * flag (which was already checked) in can_see_enmy (). Lets get out of here 1709 * flag (which was already checked) in can_see_enmy (). Lets get out of here
1572 */ 1710 */
1573 if(enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden))) 1711 if (enemy->invisible && (!enemy->contr || (!enemy->contr->tmp_invis && !enemy->contr->hidden)))
1574 return 0; 1712 return 0;
1575 1713
1576 /* use this for invis also */ 1714 /* use this for invis also */
1577 hide_discovery = op->stats.Int/5; 1715 hide_discovery = op->stats.Int / 5;
1578 1716
1579 /* Determine Detection radii */ 1717 /* Determine Detection radii */
1580 if(!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */ 1718 if (!enemy->hide) /* to detect non-hidden (eg dark/invis enemy) */
1581 radius = (op->stats.Wis/5)+1>MIN_MON_RADIUS?(op->stats.Wis/5)+1:MIN_MON_RADIUS; 1719 radius = (op->stats.Wis / 5) + 1 > MIN_MON_RADIUS ? (op->stats.Wis / 5) + 1 : MIN_MON_RADIUS;
1720 else
1582 else { /* a level/INT/Dex adjustment for hiding */ 1721 { /* a level/INT/Dex adjustment for hiding */
1583 object *sk_hide; 1722 object *sk_hide;
1584 int bonus = (op->level/2) + (op->stats.Int/5); 1723 int bonus = (op->level / 2) + (op->stats.Int / 5);
1585 1724
1586 if(enemy->type==PLAYER) { 1725 if (enemy->type == PLAYER)
1726 {
1587 if((sk_hide = find_skill_by_number(enemy,SK_HIDING))) 1727 if ((sk_hide = find_skill_by_number (enemy, SK_HIDING)))
1588 bonus -= sk_hide->level; 1728 bonus -= sk_hide->level;
1589 else { 1729 else
1730 {
1590 LOG(llevError,"can_detect_enemy() got hidden player w/o hiding skill!\n"); 1731 LOG (llevError, "can_detect_enemy() got hidden player w/o hiding skill!\n");
1591 make_visible(enemy); 1732 make_visible (enemy);
1592 radius=radius<MIN_MON_RADIUS?MIN_MON_RADIUS:radius; 1733 radius = radius < MIN_MON_RADIUS ? MIN_MON_RADIUS : radius;
1593 } 1734 }
1594 } 1735 }
1595 else /* enemy is not a player */ 1736 else /* enemy is not a player */
1596 bonus -= enemy->level; 1737 bonus -= enemy->level;
1597 1738
1598 radius += bonus/5; 1739 radius += bonus / 5;
1599 hide_discovery += bonus*5; 1740 hide_discovery += bonus * 5;
1600 } /* else creature has modifiers for hiding */ 1741 } /* else creature has modifiers for hiding */
1601 1742
1602 /* Radii stealth adjustment. Only if you are stealthy 1743 /* Radii stealth adjustment. Only if you are stealthy
1603 * will you be able to sneak up closer to creatures */ 1744 * will you be able to sneak up closer to creatures */
1604 if(QUERY_FLAG(enemy,FLAG_STEALTH)) 1745 if (QUERY_FLAG (enemy, FLAG_STEALTH))
1605 radius = radius/2, hide_discovery = hide_discovery/3; 1746 radius = radius / 2, hide_discovery = hide_discovery / 3;
1606 1747
1607 /* Radii adjustment for enemy standing in the dark */ 1748 /* Radii adjustment for enemy standing in the dark */
1608 if(op->map->darkness>0 && !stand_in_light(enemy)) { 1749 if (op->map->darkness > 0 && !stand_in_light (enemy))
1750 {
1609 /* on dark maps body heat can help indicate location with infravision 1751 /* on dark maps body heat can help indicate location with infravision
1610 * undead don't have body heat, so no benefit detecting them. 1752 * undead don't have body heat, so no benefit detecting them.
1611 */ 1753 */
1612 if(QUERY_FLAG(op,FLAG_SEE_IN_DARK) && !is_true_undead(enemy)) 1754 if (QUERY_FLAG (op, FLAG_SEE_IN_DARK) && !is_true_undead (enemy))
1613 radius += op->map->darkness/2; 1755 radius += op->map->darkness / 2;
1614 else 1756 else
1615 radius -= op->map->darkness/2; 1757 radius -= op->map->darkness / 2;
1616 1758
1617 /* op next to a monster (and not in complete darkness) 1759 /* op next to a monster (and not in complete darkness)
1618 * the monster should have a chance to see you. 1760 * the monster should have a chance to see you.
1619 */ 1761 */
1620 if(radius<MIN_MON_RADIUS && op->map->darkness<5 && rv->distance<=1) 1762 if (radius < MIN_MON_RADIUS && op->map->darkness < 5 && rv->distance <= 1)
1621 radius = MIN_MON_RADIUS; 1763 radius = MIN_MON_RADIUS;
1622 } /* if on dark map */ 1764 } /* if on dark map */
1623 1765
1624 /* Lets not worry about monsters that have incredible detection 1766 /* Lets not worry about monsters that have incredible detection
1625 * radii, we only need to worry here about things the player can 1767 * radii, we only need to worry here about things the player can
1626 * (potentially) see. This is 13, as that is the maximum size the player 1768 * (potentially) see. This is 13, as that is the maximum size the player
1627 * may have for their map - in that way, creatures at the edge will 1769 * may have for their map - in that way, creatures at the edge will
1628 * do something. Note that the distance field in the 1770 * do something. Note that the distance field in the
1629 * vector is real distance, so in theory this should be 18 to 1771 * vector is real distance, so in theory this should be 18 to
1630 * find that. 1772 * find that.
1631 */ 1773 */
1632 if(radius>13) radius = 13; 1774 if (radius > 13)
1775 radius = 13;
1633 1776
1634 /* Enemy in range! Now test for detection */ 1777 /* Enemy in range! Now test for detection */
1635 if ((int) rv->distance <= radius) { 1778 if ((int) rv->distance <= radius)
1779 {
1636 /* ah, we are within range, detected? take cases */ 1780 /* ah, we are within range, detected? take cases */
1637 if(!enemy->invisible) /* enemy in dark squares... are seen! */ 1781 if (!enemy->invisible) /* enemy in dark squares... are seen! */
1638 return 1; 1782 return 1;
1639 1783
1640 /* hidden or low-quality invisible */ 1784 /* hidden or low-quality invisible */
1641 if(enemy->hide && (rv->distance <= 1) && (RANDOM()%100<=hide_discovery)) { 1785 if (enemy->hide && (rv->distance <= 1) && (RANDOM () % 100 <= hide_discovery))
1786 {
1642 make_visible(enemy); 1787 make_visible (enemy);
1643 /* inform players of new status */ 1788 /* inform players of new status */
1644 if(enemy->type==PLAYER && player_can_view(enemy,op)) 1789 if (enemy->type == PLAYER && player_can_view (enemy, op))
1645 new_draw_info_format(NDI_UNIQUE,0, enemy, 1790 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You are discovered by %s!", &op->name);
1646 "You are discovered by %s!",op->name); 1791 return 1; /* detected enemy */
1647 return 1; /* detected enemy */ 1792 }
1648 }
1649 else if (enemy->invisible) { 1793 else if (enemy->invisible)
1794 {
1650 /* Change this around - instead of negating the invisible, just 1795 /* Change this around - instead of negating the invisible, just
1651 * return true so that the mosnter that managed to detect you can 1796 * return true so that the mosnter that managed to detect you can
1652 * do something to you. Decreasing the duration of invisible 1797 * do something to you. Decreasing the duration of invisible
1653 * doesn't make a lot of sense IMO, as a bunch of stupid creatures 1798 * doesn't make a lot of sense IMO, as a bunch of stupid creatures
1654 * can then basically negate the spell. The spell isn't negated - 1799 * can then basically negate the spell. The spell isn't negated -
1655 * they just know where you are! 1800 * they just know where you are!
1656 */ 1801 */
1657 if ((RANDOM() % 50) <= hide_discovery) { 1802 if ((RANDOM () % 50) <= hide_discovery)
1658 if (enemy->type == PLAYER) { 1803 {
1659 new_draw_info_format(NDI_UNIQUE,0, enemy, 1804 if (enemy->type == PLAYER)
1660 "You see %s noticing your position.", query_name(op)); 1805 {
1661 } 1806 new_draw_info_format (NDI_UNIQUE, 0, enemy, "You see %s noticing your position.", query_name (op));
1662 return 1; 1807 }
1663 } 1808 return 1;
1664 } 1809 }
1665 } /* within range */ 1810 }
1811 } /* within range */
1666 1812
1667 /* Wasn't detected above, so still hidden */ 1813 /* Wasn't detected above, so still hidden */
1668 return 0; 1814 return 0;
1669} 1815}
1670 1816
1671/* determine if op stands in a lighted square. This is not a very 1817/* determine if op stands in a lighted square. This is not a very
1672 * intellegent algorithm. For one thing, we ignore los here, SO it 1818 * intellegent algorithm. For one thing, we ignore los here, SO it
1673 * is possible for a bright light to illuminate a player on the 1819 * is possible for a bright light to illuminate a player on the
1674 * other side of a wall (!). 1820 * other side of a wall (!).
1675 */ 1821 */
1676 1822
1823int
1677int stand_in_light( object *op) { 1824stand_in_light (object *op)
1825{
1678 sint16 nx,ny; 1826 sint16 nx, ny;
1679 mapstruct *m; 1827 maptile *m;
1680 1828
1681 1829
1830 if (!op)
1682 if(!op) return 0; 1831 return 0;
1683 if(op->glow_radius > 0) return 1; 1832 if (op->glow_radius > 0)
1833 return 1;
1684 1834
1685 if(op->map) { 1835 if (op->map)
1836 {
1686 int x, y, x1, y1; 1837 int x, y, x1, y1;
1687
1688
1689 1838
1839
1840
1690 /* Check the spaces with the max light radius to see if any of them 1841 /* Check the spaces with the max light radius to see if any of them
1691 * have lights, and if any of them light the player enough, then return 1. 1842 * have lights, and if any of them light the player enough, then return 1.
1692 */ 1843 */
1693 for (x = op->x - MAX_LIGHT_RADII; x <= op->x + MAX_LIGHT_RADII; x++) { 1844 for (x = op->x - MAX_LIGHT_RADII; x <= op->x + MAX_LIGHT_RADII; x++)
1845 {
1694 for (y = op->y - MAX_LIGHT_RADII; y <= op->y + MAX_LIGHT_RADII; y++) { 1846 for (y = op->y - MAX_LIGHT_RADII; y <= op->y + MAX_LIGHT_RADII; y++)
1695 m = op->map; 1847 {
1696 nx = x; 1848 m = op->map;
1697 ny = y; 1849 nx = x;
1850 ny = y;
1698 1851
1699 if (get_map_flags(m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) continue; 1852 if (get_map_flags (m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP)
1853 continue;
1700 1854
1701 x1 = abs(x - op->x)*abs(x - op->x); 1855 x1 = abs (x - op->x) * abs (x - op->x);
1702 y1 = abs(y - op->y)*abs(y - op->y); 1856 y1 = abs (y - op->y) * abs (y - op->y);
1703 if (isqrt(x1 + y1) < GET_MAP_LIGHT(m, nx, ny)) return 1; 1857 if (isqrt (x1 + y1) < GET_MAP_LIGHT (m, nx, ny))
1858 return 1;
1859 }
1860 }
1704 } 1861 }
1705 }
1706 }
1707 return 0; 1862 return 0;
1708} 1863}
1709 1864
1710 1865
1711/* assuming no walls/barriers, lets check to see if its *possible* 1866/* assuming no walls/barriers, lets check to see if its *possible*
1712 * to see an enemy. Note, "detection" is different from "seeing". 1867 * to see an enemy. Note, "detection" is different from "seeing".
1713 * See can_detect_enemy() for more details. -b.t. 1868 * See can_detect_enemy() for more details. -b.t.
1714 * return 0 if can't be seen, 1 if can be 1869 * return 0 if can't be seen, 1 if can be
1715 */ 1870 */
1716 1871
1872int
1717int can_see_enemy (object *op, object *enemy) { 1873can_see_enemy (object *op, object *enemy)
1874{
1718 object *looker = op->head?op->head:op; 1875 object *looker = op->head ? op->head : op;
1719 1876
1720 /* safety */ 1877 /* safety */
1721 if(!looker||!enemy||!QUERY_FLAG(looker,FLAG_ALIVE)) 1878 if (!looker || !enemy || !QUERY_FLAG (looker, FLAG_ALIVE))
1722 return 0; 1879 return 0;
1723 1880
1724 /* we dont give a full treatment of xrays here (shorter range than normal, 1881 /* we dont give a full treatment of xrays here (shorter range than normal,
1725 * see through walls). Should we change the code elsewhere to make you 1882 * see through walls). Should we change the code elsewhere to make you
1726 * blind even if you can xray? 1883 * blind even if you can xray?
1727 */ 1884 */
1728 if(QUERY_FLAG(looker,FLAG_BLIND) && !QUERY_FLAG(looker,FLAG_XRAYS)) 1885 if (QUERY_FLAG (looker, FLAG_BLIND) && !QUERY_FLAG (looker, FLAG_XRAYS))
1729 return 0; 1886 return 0;
1730 1887
1731 /* checking for invisible things */ 1888 /* checking for invisible things */
1732 if(enemy->invisible) { 1889 if (enemy->invisible)
1890 {
1733 /* HIDDEN ENEMY. by definition, you can't see hidden stuff! 1891 /* HIDDEN ENEMY. by definition, you can't see hidden stuff!
1734 * However,if you carry any source of light, then the hidden 1892 * However,if you carry any source of light, then the hidden
1735 * creature is seeable (and stupid) */ 1893 * creature is seeable (and stupid) */
1736 1894
1737 if(has_carried_lights(enemy)) { 1895 if (has_carried_lights (enemy))
1896 {
1738 if(enemy->hide) { 1897 if (enemy->hide)
1739 make_visible(enemy); 1898 {
1740 new_draw_info(NDI_UNIQUE,0, enemy, 1899 make_visible (enemy);
1741 "Your light reveals your hiding spot!"); 1900 new_draw_info (NDI_UNIQUE, 0, enemy, "Your light reveals your hiding spot!");
1742 } 1901 }
1743 return 1; 1902 return 1;
1744 } else if (enemy->hide) return 0; 1903 }
1904 else if (enemy->hide)
1905 return 0;
1745 1906
1746 /* Invisible enemy. Break apart the check for invis undead/invis looker 1907 /* Invisible enemy. Break apart the check for invis undead/invis looker
1747 * into more simple checks - the QUERY_FLAG doesn't return 1/0 values, 1908 * into more simple checks - the QUERY_FLAG doesn't return 1/0 values,
1748 * and making it a conditional makes the code pretty ugly. 1909 * and making it a conditional makes the code pretty ugly.
1749 */ 1910 */
1750 if (!QUERY_FLAG(looker,FLAG_SEE_INVISIBLE)) { 1911 if (!QUERY_FLAG (looker, FLAG_SEE_INVISIBLE))
1912 {
1751 if (makes_invisible_to(enemy, looker)) return 0; 1913 if (makes_invisible_to (enemy, looker))
1752 } 1914 return 0;
1915 }
1916 }
1753 } else if(looker->type==PLAYER) /* for players, a (possible) shortcut */ 1917 else if (looker->type == PLAYER) /* for players, a (possible) shortcut */
1754 if(player_can_view(looker,enemy)) return 1; 1918 if (player_can_view (looker, enemy))
1919 return 1;
1755 1920
1756 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen 1921 /* ENEMY IN DARK MAP. Without infravision, the enemy is not seen
1757 * unless they carry a light or stand in light. Darkness doesnt 1922 * unless they carry a light or stand in light. Darkness doesnt
1758 * inhibit the undead per se (but we should give their archs 1923 * inhibit the undead per se (but we should give their archs
1759 * CAN_SEE_IN_DARK, this is just a safety 1924 * CAN_SEE_IN_DARK, this is just a safety
1760 * we care about the enemy maps status, not the looker. 1925 * we care about the enemy maps status, not the looker.
1761 * only relevant for tiled maps, but it is possible that the 1926 * only relevant for tiled maps, but it is possible that the
1762 * enemy is on a bright map and the looker on a dark - in that 1927 * enemy is on a bright map and the looker on a dark - in that
1763 * case, the looker can still see the enemy 1928 * case, the looker can still see the enemy
1764 */ 1929 */
1765 if(enemy->map->darkness>0&&!stand_in_light(enemy) 1930 if (enemy->map->darkness > 0 && !stand_in_light (enemy)
1766 &&(!QUERY_FLAG(looker,FLAG_SEE_IN_DARK)|| 1931 && (!QUERY_FLAG (looker, FLAG_SEE_IN_DARK) || !is_true_undead (looker) || !QUERY_FLAG (looker, FLAG_XRAYS)))
1767 !is_true_undead(looker)||!QUERY_FLAG(looker,FLAG_XRAYS)))
1768 return 0; 1932 return 0;
1769 1933
1770 return 1; 1934 return 1;
1771} 1935}
1772

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines