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

Comparing deliantra/server/server/attack.C (file contents):
Revision 1.8 by root, Sun Sep 3 00:18:42 2006 UTC vs.
Revision 1.17 by root, Thu Sep 14 22:34:03 2006 UTC

1/*
2 * static char *rcsid_attack_c =
3 * "$Id: attack.C,v 1.8 2006/09/03 00:18:42 root Exp $";
4 */
5/* 1/*
6 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
7 3
8 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
9 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
20 16
21 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 20
25 The authors can be reached via e-mail to crossfire-devel@real-time.com 21 The authors can be reached via e-mail to <crossfire@schmorp.de>
26*/ 22*/
27#include <assert.h> 23#include <assert.h>
28#include <global.h> 24#include <global.h>
29#include <living.h> 25#include <living.h>
30#include <material.h> 26#include <material.h>
31#include <skills.h> 27#include <skills.h>
32 28
33#ifndef __CEXTRACT__ 29#ifndef __CEXTRACT__
34#include <sproto.h> 30# include <sproto.h>
35#endif 31#endif
36 32
37#include <sounds.h> 33#include <sounds.h>
38 34
39typedef struct att_msg_str { 35typedef struct att_msg_str
36{
40 char *msg1; 37 char *msg1;
41 char *msg2; 38 char *msg2;
42} att_msg; 39} att_msg;
43 40
44/*#define ATTACK_DEBUG*/ 41/*#define ATTACK_DEBUG*/
45 42
46/* cancels object *op. Cancellation basically means an object loses 43/* cancels object *op. Cancellation basically means an object loses
47 * its magical benefits. 44 * its magical benefits.
48 */ 45 */
46void
49void cancellation(object *op) 47cancellation (object *op)
50{ 48{
51 object *tmp; 49 object *tmp;
52 50
53 if (op->invisible) 51 if (op->invisible)
54 return; 52 return;
55 53
56 if (QUERY_FLAG (op, FLAG_ALIVE) || op->type == CONTAINER || op->type == THROWN_OBJ) { 54 if (QUERY_FLAG (op, FLAG_ALIVE) || op->type == CONTAINER || op->type == THROWN_OBJ)
55 {
57 /* Recur through the inventory */ 56 /* Recur through the inventory */
58 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 57 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
59 if (!did_make_save_item(tmp, AT_CANCELLATION,op)) 58 if (!did_make_save_item (tmp, AT_CANCELLATION, op))
60 cancellation(tmp); 59 cancellation (tmp);
61 } 60 }
62 else if(FABS(op->magic)<=(rndm(0, 5))) { 61 else if (FABS (op->magic) <= (rndm (0, 5)))
62 {
63 /* Nullify this object. This code could probably be more complete */ 63 /* Nullify this object. This code could probably be more complete */
64 /* in what abilities it should cancel */ 64 /* in what abilities it should cancel */
65 op->magic=0; 65 op->magic = 0;
66 CLEAR_FLAG(op, FLAG_DAMNED); 66 CLEAR_FLAG (op, FLAG_DAMNED);
67 CLEAR_FLAG(op, FLAG_CURSED); 67 CLEAR_FLAG (op, FLAG_CURSED);
68 CLEAR_FLAG(op, FLAG_KNOWN_MAGICAL); 68 CLEAR_FLAG (op, FLAG_KNOWN_MAGICAL);
69 CLEAR_FLAG(op, FLAG_KNOWN_CURSED); 69 CLEAR_FLAG (op, FLAG_KNOWN_CURSED);
70 if (op->env && op->env->type == PLAYER) { 70 if (op->env && op->env->type == PLAYER)
71 {
71 esrv_send_item (op->env, op); 72 esrv_send_item (op->env, op);
72 } 73 }
73 } 74 }
74} 75}
75 76
76 77
78/* did_make_save_item just checks to make sure the item actually 79/* did_make_save_item just checks to make sure the item actually
79 * made its saving throw based on the tables. It does not take 80 * made its saving throw based on the tables. It does not take
80 * any further action (like destroying the item). 81 * any further action (like destroying the item).
81 */ 82 */
82 83
84int
83int did_make_save_item(object *op, int type, object *originator) { 85did_make_save_item (object *op, int type, object *originator)
86{
84 int i, roll, saves=0, attacks=0, number; 87 int i, roll, saves = 0, attacks = 0, number;
85 materialtype_t *mt; 88 materialtype_t *mt;
86 89
87 if (op->materialname == NULL) { 90 if (op->materialname == NULL)
91 {
88 for (mt = materialt; mt != NULL && mt->next != NULL; mt=mt->next) { 92 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
93 {
89 if (op->material & mt->material) 94 if (op->material & mt->material)
90 break; 95 break;
91 } 96 }
97 }
92 } else 98 else
93 mt = name_to_material(op->materialname); 99 mt = name_to_material (op->materialname);
94 if (mt == NULL) 100 if (mt == NULL)
95 return TRUE;
96 roll = rndm(1, 20);
97
98 /* the attacktypes have no meaning for object saves
99 * If the type is only magic, don't adjust type - basically, if
100 * pure magic is hitting an object, it should save. However, if it
101 * is magic teamed with something else, then strip out the
102 * magic type, and instead let the fire, cold, or whatever component
103 * destroy the item. Otherwise, you get the case of poisoncloud
104 * destroying objects because it has magic attacktype.
105 */
106 if (type != AT_MAGIC)
107 type &= ~(AT_CONFUSION|AT_DRAIN|AT_GHOSTHIT|AT_POISON|AT_SLOW|
108 AT_PARALYZE|AT_TURN_UNDEAD|AT_FEAR|AT_DEPLETE|AT_DEATH|
109 AT_COUNTERSPELL|AT_HOLYWORD|AT_BLIND|AT_LIFE_STEALING|
110 AT_MAGIC);
111
112 if (type == 0)
113 return TRUE;
114 if (roll == 20)
115 return TRUE;
116 if (roll == 1)
117 return FALSE;
118
119 for (number=0; number < NROFATTACKS; number++) {
120 i = 1<<number;
121 if (!(i&type))
122 continue;
123 attacks++;
124 if (op->resist[number] == 100)
125 saves++;
126 else if (roll >= mt->save[number] - op->magic - op->resist[number]/100)
127 saves++;
128 else if ((20-mt->save[number])/3 > originator->stats.dam)
129 saves++;
130 }
131
132 if (saves==attacks || attacks==0)
133 return TRUE;
134 if ((saves==0) || (rndm(1, attacks) > saves))
135 return FALSE;
136 return TRUE; 101 return TRUE;
102 roll = rndm (1, 20);
103
104 /* the attacktypes have no meaning for object saves
105 * If the type is only magic, don't adjust type - basically, if
106 * pure magic is hitting an object, it should save. However, if it
107 * is magic teamed with something else, then strip out the
108 * magic type, and instead let the fire, cold, or whatever component
109 * destroy the item. Otherwise, you get the case of poisoncloud
110 * destroying objects because it has magic attacktype.
111 */
112 if (type != AT_MAGIC)
113 type &= ~(AT_CONFUSION | AT_DRAIN | AT_GHOSTHIT | AT_POISON | AT_SLOW |
114 AT_PARALYZE | AT_TURN_UNDEAD | AT_FEAR | AT_DEPLETE | AT_DEATH |
115 AT_COUNTERSPELL | AT_HOLYWORD | AT_BLIND | AT_LIFE_STEALING | AT_MAGIC);
116
117 if (type == 0)
118 return TRUE;
119 if (roll == 20)
120 return TRUE;
121 if (roll == 1)
122 return FALSE;
123
124 for (number = 0; number < NROFATTACKS; number++)
125 {
126 i = 1 << number;
127 if (!(i & type))
128 continue;
129 attacks++;
130 if (op->resist[number] == 100)
131 saves++;
132 else if (roll >= mt->save[number] - op->magic - op->resist[number] / 100)
133 saves++;
134 else if ((20 - mt->save[number]) / 3 > originator->stats.dam)
135 saves++;
136 }
137
138 if (saves == attacks || attacks == 0)
139 return TRUE;
140 if ((saves == 0) || (rndm (1, attacks) > saves))
141 return FALSE;
142 return TRUE;
137} 143}
138 144
139/* This function calls did_make_save_item. It then performs the 145/* This function calls did_make_save_item. It then performs the
140 * appropriate actions to the item (such as burning the item up, 146 * appropriate actions to the item (such as burning the item up,
141 * calling cancellation, etc.) 147 * calling cancellation, etc.)
142 */ 148 */
143 149
150void
144void save_throw_object (object *op, int type, object *originator) 151save_throw_object (object *op, int type, object *originator)
145{ 152{
146 if ( ! did_make_save_item (op, type,originator)) 153 if (!did_make_save_item (op, type, originator))
147 { 154 {
148 object *env=op->env; 155 object *env = op->env;
149 int x=op->x,y=op->y; 156 int x = op->x, y = op->y;
150 mapstruct *m=op->map; 157 mapstruct *m = op->map;
151 158
152 op = stop_item (op); 159 op = stop_item (op);
153 if (op == NULL) 160 if (op == NULL)
154 return; 161 return;
155 162
156 /* Hacked the following so that type LIGHTER will work. 163 /* Hacked the following so that type LIGHTER will work.
157 * Also, objects which are potenital "lights" that are hit by 164 * Also, objects which are potenital "lights" that are hit by
158 * flame/elect attacks will be set to glow. "lights" are any 165 * flame/elect attacks will be set to glow. "lights" are any
159 * object with +/- glow_radius and an "other_arch" to change to. 166 * object with +/- glow_radius and an "other_arch" to change to.
160 * (and please note that we cant fail our save and reach this 167 * (and please note that we cant fail our save and reach this
161 * function if the object doesnt contain a material that can burn. 168 * function if the object doesnt contain a material that can burn.
162 * So forget lighting magical swords on fire with this!) -b.t. 169 * So forget lighting magical swords on fire with this!) -b.t.
163 */ 170 */
164 if(type&(AT_FIRE|AT_ELECTRICITY) 171 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE))
165 &&op->other_arch&&QUERY_FLAG(op, FLAG_IS_LIGHTABLE)) { 172 {
166 const char *arch=op->other_arch->name; 173 const char *arch = op->other_arch->name;
167 174
168 op = decrease_ob_nr (op, 1); 175 op = decrease_ob_nr (op, 1);
176
169 if (op) 177 if (op)
170 fix_stopped_item (op, m, originator); 178 fix_stopped_item (op, m, originator);
179
171 if((op = get_archetype(arch))!=NULL) { 180 if ((op = get_archetype (arch)) != NULL)
181 {
172 if(env) { 182 if (env)
183 {
173 op->x=env->x,op->y=env->y; 184 op->x = env->x, op->y = env->y;
174 insert_ob_in_ob(op,env); 185 insert_ob_in_ob (op, env);
175 if (env->contr) 186 if (env->contr)
176 esrv_send_item(env, op); 187 esrv_send_item (env, op);
177 } else {
178 op->x=x,op->y=y;
179 insert_ob_in_map(op,m,originator,0);
180 }
181 } 188 }
189 else
182 return; 190 {
183 } 191 op->x = x, op->y = y;
184 if(type&AT_CANCELLATION) { /* Cancellation. */
185 cancellation(op);
186 fix_stopped_item (op, m, originator);
187 return;
188 }
189 if(op->nrof>1) {
190 op = decrease_ob_nr(op,rndm(0, op->nrof-1));
191 if (op)
192 fix_stopped_item (op, m, originator); 192 insert_ob_in_map (op, m, originator, 0);
193 } else {
194 if (op->env) {
195 object *tmp= is_player_inv(op->env);
196
197 if (tmp) {
198 esrv_del_item(tmp->contr, op->count);
199 } 193 }
200 } 194 }
195
196 return;
197 }
198
199 if (type & AT_CANCELLATION)
200 { /* Cancellation. */
201 cancellation (op);
202 fix_stopped_item (op, m, originator);
203 return;
204 }
205
206 if (op->nrof > 1)
207 {
208 op = decrease_ob_nr (op, rndm (0, op->nrof - 1));
209
210 if (op)
211 fix_stopped_item (op, m, originator);
212 }
213 else
214 {
215 if (op->env)
216 {
217 object *tmp = is_player_inv (op->env);
218
219 if (tmp)
220 esrv_del_item (tmp->contr, op->count);
221 }
222
201 if ( ! QUERY_FLAG (op, FLAG_REMOVED)) 223 if (!QUERY_FLAG (op, FLAG_REMOVED))
202 remove_ob(op); 224 remove_ob (op);
225
203 free_object(op); 226 free_object (op);
204 } 227 }
228
205 if(type&(AT_FIRE|AT_ELECTRICITY)) { 229 if (type & (AT_FIRE | AT_ELECTRICITY))
206 if(env) { 230 if (env)
231 {
207 op=get_archetype("burnout"); 232 op = get_archetype ("burnout");
208 op->x=env->x,op->y=env->y; 233 op->x = env->x, op->y = env->y;
209 insert_ob_in_ob(op,env); 234 insert_ob_in_ob (op, env);
210 } else { 235 }
236 else
211 replace_insert_ob_in_map("burnout",originator); 237 replace_insert_ob_in_map ("burnout", originator);
212 } 238
213 } 239 return;
240 }
241
242 /* The value of 50 is arbitrary. */
243 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
244 {
245 object *tmp;
246 archetype *at = archetype::find ("icecube");
247
248 if (at == NULL)
214 return; 249 return;
215 } 250
216 /* The value of 50 is arbitrary. */
217 if(type&AT_COLD &&(op->resist[ATNR_COLD]<50) &&
218 !QUERY_FLAG(op,FLAG_NO_PICK)&&(RANDOM()&2)) {
219 object *tmp;
220 archetype *at = find_archetype("icecube");
221 if (at == NULL)
222 return;
223 op = stop_item (op); 251 op = stop_item (op);
224 if (op == NULL) 252 if (op == NULL)
225 return;
226 if ((tmp = present_arch(at,op->map,op->x,op->y)) == NULL) {
227 tmp = arch_to_object(at);
228 tmp->x=op->x,tmp->y=op->y;
229 /* This was in the old (pre new movement code) -
230 * icecubes have slow_move set to 1 - don't want
231 * that for ones we create.
232 */
233 tmp->move_slow_penalty=0;
234 tmp->move_slow=0;
235 insert_ob_in_map(tmp,op->map,originator,0);
236 }
237 if ( ! QUERY_FLAG (op, FLAG_REMOVED))
238 remove_ob(op);
239 (void) insert_ob_in_ob(op,tmp);
240 return; 253 return;
254
255 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL)
256 {
257 tmp = arch_to_object (at);
258 tmp->x = op->x, tmp->y = op->y;
259 /* This was in the old (pre new movement code) -
260 * icecubes have slow_move set to 1 - don't want
261 * that for ones we create.
262 */
263 tmp->move_slow_penalty = 0;
264 tmp->move_slow = 0;
265 insert_ob_in_map (tmp, op->map, originator, 0);
266 }
267
268 if (!QUERY_FLAG (op, FLAG_REMOVED))
269 remove_ob (op);
270
271 insert_ob_in_ob (op, tmp);
272 return;
241 } 273 }
242} 274}
243 275
244/* Object op is hitting the map. 276/* Object op is hitting the map.
245 * op is going in direction 'dir' 277 * op is going in direction 'dir'
246 * type is the attacktype of the object. 278 * type is the attacktype of the object.
247 * full_hit is set if monster area does not matter. 279 * full_hit is set if monster area does not matter.
248 * returns 1 if it hits something, 0 otherwise. 280 * returns 1 if it hits something, 0 otherwise.
249 */ 281 */
250 282
283int
251int hit_map(object *op, int dir, int type, int full_hit) { 284hit_map (object *op, int dir, int type, int full_hit)
285{
252 object *tmp, *next; 286 object *tmp, *next;
253 mapstruct *map; 287 mapstruct *map;
254 sint16 x, y; 288 sint16 x, y;
255 int retflag=0; /* added this flag.. will return 1 if it hits a monster */ 289 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
256 290
257 tag_t op_tag, next_tag=0; 291 tag_t op_tag, next_tag = 0;
258 292
259 if (QUERY_FLAG (op, FLAG_FREED)) { 293 if (QUERY_FLAG (op, FLAG_FREED))
294 {
260 LOG (llevError, "BUG: hit_map(): free object\n"); 295 LOG (llevError, "BUG: hit_map(): free object\n");
296 return 0;
297 }
298
299 if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL)
300 {
301 LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n", &op->arch->name, &op->name);
302 return 0;
303 }
304
305 if (!op->map)
306 {
307 LOG (llevError, "BUG: hit_map(): %s has no map\n", &op->name);
308 return 0;
309 }
310
311 if (op->head)
312 op = op->head;
313
314 op_tag = op->count;
315
316 map = op->map;
317 x = op->x + freearr_x[dir];
318 y = op->y + freearr_y[dir];
319
320 int mflags = get_map_flags (map, &map, x, y, &x, &y);
321
322 // elmex: a safe map tile can't be hit!
323 // this should prevent most harmful effects on items and players there.
324 if (mflags & (P_OUT_OF_MAP | P_SAFE))
325 return 0;
326
327 /* peterm: a few special cases for special attacktypes --counterspell
328 * must be out here because it strikes things which are not alive
329 */
330
331 if (type & AT_COUNTERSPELL)
332 {
333 counterspell (op, dir); /* see spell_effect.c */
334
335 /* If the only attacktype is counterspell or magic, don't need
336 * to do any further processing.
337 */
338 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
261 return 0; 339 return 0;
262 }
263 340
264 if (QUERY_FLAG (op, FLAG_REMOVED) || op->env != NULL) {
265 LOG (llevError, "BUG: hit_map(): hitter (arch %s, name %s) not on a map\n",
266 &op->arch->name, &op->name);
267 return 0;
268 }
269
270 if ( ! op->map) {
271 LOG (llevError,"BUG: hit_map(): %s has no map\n", &op->name);
272 return 0;
273 }
274
275 if (op->head) op=op->head;
276
277 op_tag = op->count;
278
279 map = op->map;
280 x = op->x + freearr_x[dir];
281 y = op->y + freearr_y[dir];
282
283 int mflags = get_map_flags(map, &map, x, y, &x, &y);
284 // elmex: a safe map tile can't be hit!
285 // this should prevent most harmful effects on items and players there.
286 if ((mflags & P_OUT_OF_MAP) || (mflags & P_SAFE))
287 return 0;
288
289 /* peterm: a few special cases for special attacktypes --counterspell
290 * must be out here because it strikes things which are not alive
291 */
292
293 if (type & AT_COUNTERSPELL) {
294 counterspell(op,dir); /* see spell_effect.c */
295
296 /* If the only attacktype is counterspell or magic, don't need
297 * to do any further processing.
298 */
299 if(!(type & ~(AT_COUNTERSPELL|AT_MAGIC))){
300 return 0;
301 }
302 type &= ~AT_COUNTERSPELL; 341 type &= ~AT_COUNTERSPELL;
303 } 342 }
304 343
305 if(type & AT_CHAOS){ 344 if (type & AT_CHAOS)
345 {
306 shuffle_attack(op,1); /*1 flag tells it to change the face */ 346 shuffle_attack (op, 1); /*1 flag tells it to change the face */
307 update_object(op,UP_OBJ_FACE); 347 update_object (op, UP_OBJ_FACE);
308 type &= ~AT_CHAOS; 348 type &= ~AT_CHAOS;
309 } 349 }
310 350
311 next = get_map_ob (map, x, y); 351 next = get_map_ob (map, x, y);
352 if (next)
353 next_tag = next->count;
354
355 while (next)
356 {
357 if (was_destroyed (next, next_tag))
358 {
359 /* There may still be objects that were above 'next', but there is no
360 * simple way to find out short of copying all object references and
361 * tags into a temporary array before we start processing the first
362 * object. That's why we just abort.
363 *
364 * This happens whenever attack spells (like fire) hit a pile
365 * of objects. This is not a bug - nor an error. The errormessage
366 * below was spamming the logs for absolutely no reason.
367 */
368 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
369 break;
370 }
371
372 tmp = next;
373 next = tmp->above;
374
312 if (next) 375 if (next)
313 next_tag = next->count; 376 next_tag = next->count;
314 377
315 while (next) { 378 if (QUERY_FLAG (tmp, FLAG_FREED))
379 {
380 LOG (llevError, "BUG: hit_map(): found freed object\n");
381 break;
382 }
383
384 /* Something could have happened to 'tmp' while 'tmp->below' was processed.
385 * For example, 'tmp' was put in an icecube.
386 * This is one of the few cases where on_same_map should not be used.
387 */
388 if (tmp->map != map || tmp->x != x || tmp->y != y)
389 continue;
390
391 if (QUERY_FLAG (tmp, FLAG_ALIVE))
392 {
393 hit_player (tmp, op->stats.dam, op, type, full_hit);
394 retflag |= 1;
316 if (was_destroyed (next, next_tag)) { 395 if (was_destroyed (op, op_tag))
317 /* There may still be objects that were above 'next', but there is no
318 * simple way to find out short of copying all object references and
319 * tags into a temporary array before we start processing the first
320 * object. That's why we just abort.
321 *
322 * This happens whenever attack spells (like fire) hit a pile
323 * of objects. This is not a bug - nor an error. The errormessage
324 * below was spamming the logs for absolutely no reason.
325 */
326 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
327 break; 396 break;
328 } 397 }
329 tmp = next;
330 next = tmp->above;
331 if (next)
332 next_tag = next->count;
333 398
334 if (QUERY_FLAG (tmp, FLAG_FREED)) { 399 /* Here we are potentially destroying an object. If the object has
335 LOG (llevError, "BUG: hit_map(): found freed object\n"); 400 * NO_PASS set, it is also immune - you can't destroy walls. Note
401 * that weak walls have is_alive set, which prevent objects from
402 * passing over/through them. We don't care what type of movement
403 * the wall blocks - if it blocks any type of movement, can't be
404 * destroyed right now.
405 */
406 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
407 {
408 save_throw_object (tmp, type, op);
409 if (was_destroyed (op, op_tag))
336 break; 410 break;
337 } 411 }
338
339 /* Something could have happened to 'tmp' while 'tmp->below' was processed.
340 * For example, 'tmp' was put in an icecube.
341 * This is one of the few cases where on_same_map should not be used.
342 */
343 if (tmp->map != map || tmp->x != x || tmp->y != y)
344 continue;
345
346 if (QUERY_FLAG (tmp, FLAG_ALIVE)) {
347 hit_player(tmp,op->stats.dam,op,type,full_hit);
348 retflag |=1;
349 if (was_destroyed (op, op_tag))
350 break;
351 }
352 /* Here we are potentially destroying an object. If the object has
353 * NO_PASS set, it is also immune - you can't destroy walls. Note
354 * that weak walls have is_alive set, which prevent objects from
355 * passing over/through them. We don't care what type of movement
356 * the wall blocks - if it blocks any type of movement, can't be
357 * destroyed right now.
358 */
359 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 &&
360 !tmp->move_block) {
361 save_throw_object(tmp,type,op);
362 if (was_destroyed (op, op_tag))
363 break;
364 }
365 } 412 }
413
366 return 0; 414 return 0;
367} 415}
368 416
417void
369void attack_message(int dam, int type, object *op, object *hitter) { 418attack_message (int dam, int type, object *op, object *hitter)
419{
370 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 420 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
371 int i, found=0; 421 int i, found = 0;
372 mapstruct *map; 422 mapstruct *map;
373 object *next, *tmp; 423 object *next, *tmp;
374 424
375 /* put in a few special messages for some of the common attacktypes 425 /* put in a few special messages for some of the common attacktypes
376 * a player might have. For example, fire, electric, cold, etc 426 * a player might have. For example, fire, electric, cold, etc
377 * [garbled 20010919] 427 * [garbled 20010919]
378 */ 428 */
379 429
380 if (dam == 9998 && op->type == DOOR) { 430 if (dam == 9998 && op->type == DOOR)
431 {
381 sprintf(buf1, "unlock %s", &op->name); 432 sprintf (buf1, "unlock %s", &op->name);
382 sprintf(buf2, " unlocks"); 433 sprintf (buf2, " unlocks");
383 found++; 434 found++;
435 }
436 if (dam < 0)
384 } 437 {
385 if(dam<0) {
386 sprintf(buf1, "hit %s", &op->name); 438 sprintf (buf1, "hit %s", &op->name);
387 sprintf(buf2, " hits"); 439 sprintf (buf2, " hits");
388 found++; 440 found++;
441 }
389 } else if(dam==0) { 442 else if (dam == 0)
443 {
390 sprintf(buf1, "missed %s", &op->name); 444 sprintf (buf1, "missed %s", &op->name);
391 sprintf(buf2, " misses"); 445 sprintf (buf2, " misses");
392 found++; 446 found++;
447 }
393 } else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || 448 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM ||
394 hitter->type == POISONING || 449 hitter->type == POISONING || (type & AT_POISON && IS_LIVE (op))) && !found)
395 (type & AT_POISON && IS_LIVE(op))) && !found) { 450 {
396 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; 451 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++)
397 i++) 452 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1)
398 if (dam < attack_mess[ATM_SUFFER][i].level 453 {
399 || attack_mess[ATM_SUFFER][i+1].level == -1) { 454 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2);
400 sprintf(buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1,
401 &op->name, attack_mess[ATM_SUFFER][i].buf2);
402 strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3); 455 strcpy (buf2, attack_mess[ATM_SUFFER][i].buf3);
456 found++;
457 break;
458 }
459 }
460 else if (op->type == DOOR && !found)
461 {
462 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; i++)
463 if (dam < attack_mess[ATM_DOOR][i].level || attack_mess[ATM_DOOR][i + 1].level == -1)
464 {
465 sprintf (buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1, &op->name, attack_mess[ATM_DOOR][i].buf2);
466 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3);
467 found++;
468 break;
469 }
470 }
471 else if (hitter->type == PLAYER && IS_LIVE (op))
472 {
473 if (USING_SKILL (hitter, SK_KARATE))
474 {
475 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++)
476 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1)
477 {
478 sprintf (buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1, &op->name, attack_mess[ATM_KARATE][i].buf2);
479 strcpy (buf2, attack_mess[ATM_KARATE][i].buf3);
403 found++; 480 found++;
404 break; 481 break;
405 } 482 }
406 } else if (op->type == DOOR && !found) { 483 }
484 else if (USING_SKILL (hitter, SK_CLAWING))
485 {
407 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DOOR][i].level != -1; 486 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1; i++)
487 if (dam < attack_mess[ATM_CLAW][i].level || attack_mess[ATM_CLAW][i + 1].level == -1)
408 i++) 488 {
409 if (dam < attack_mess[ATM_DOOR][i].level 489 sprintf (buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1, &op->name, attack_mess[ATM_CLAW][i].buf2);
410 || attack_mess[ATM_DOOR][i+1].level == -1) {
411 sprintf(buf1, "%s %s%s", attack_mess[ATM_DOOR][i].buf1,
412 &op->name, attack_mess[ATM_DOOR][i].buf2);
413 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); 490 strcpy (buf2, attack_mess[ATM_CLAW][i].buf3);
414 found++; 491 found++;
415 break; 492 break;
416 }
417 } else if (hitter->type == PLAYER && IS_LIVE(op)) {
418 if (USING_SKILL(hitter, SK_KARATE)) {
419 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1;
420 i++)
421 if (dam < attack_mess[ATM_KARATE][i].level
422 || attack_mess[ATM_KARATE][i+1].level == -1) {
423 sprintf(buf1, "%s %s%s", attack_mess[ATM_KARATE][i].buf1,
424 &op->name, attack_mess[ATM_KARATE][i].buf2);
425 strcpy (buf2, attack_mess[ATM_KARATE][i].buf3);
426 found++;
427 break;
428 } 493 }
429 } else if (USING_SKILL(hitter, SK_CLAWING)) {
430 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_CLAW][i].level != -1;
431 i++)
432 if (dam < attack_mess[ATM_CLAW][i].level
433 || attack_mess[ATM_CLAW][i+1].level == -1) {
434 sprintf(buf1, "%s %s%s", attack_mess[ATM_CLAW][i].buf1,
435 &op->name, attack_mess[ATM_CLAW][i].buf2);
436 strcpy (buf2, attack_mess[ATM_CLAW][i].buf3);
437 found++;
438 break;
439 } 494 }
440 } else if (USING_SKILL(hitter, SK_PUNCHING)) { 495 else if (USING_SKILL (hitter, SK_PUNCHING))
496 {
441 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; 497 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_PUNCH][i].level != -1; i++)
498 if (dam < attack_mess[ATM_PUNCH][i].level || attack_mess[ATM_PUNCH][i + 1].level == -1)
442 i++) 499 {
443 if (dam < attack_mess[ATM_PUNCH][i].level
444 || attack_mess[ATM_PUNCH][i+1].level == -1) {
445 sprintf(buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, 500 sprintf (buf1, "%s %s%s", attack_mess[ATM_PUNCH][i].buf1, &op->name, attack_mess[ATM_PUNCH][i].buf2);
446 &op->name, attack_mess[ATM_PUNCH][i].buf2);
447 strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3); 501 strcpy (buf2, attack_mess[ATM_PUNCH][i].buf3);
448 found++;
449 break;
450 }
451 }
452 }
453 if (found) {
454 /* done */
455 } else if (IS_ARROW(hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) {
456 sprintf(buf1, "hit"); /* just in case */
457 for (i=0; i < MAXATTACKMESS; i++)
458 if (dam < attack_mess[ATM_ARROW][i].level
459 || attack_mess[ATM_ARROW][i+1].level == -1) {
460 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
461 found++; 502 found++;
462 break; 503 break;
504 }
505 }
506 }
507 if (found)
508 {
509 /* done */
510 }
511 else if (IS_ARROW (hitter) && (type == AT_PHYSICAL || type == AT_MAGIC))
512 {
513 sprintf (buf1, "hit"); /* just in case */
514 for (i = 0; i < MAXATTACKMESS; i++)
515 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1)
516 {
517 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
518 found++;
519 break;
520 }
521 }
522 else if (type & AT_DRAIN && IS_LIVE (op))
523 {
524 /* drain is first, because some items have multiple attypes */
525 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++)
526 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1)
527 {
528 sprintf (buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1, &op->name, attack_mess[ATM_DRAIN][i].buf2);
529 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
530 found++;
531 break;
532 }
533 }
534 else if (type & AT_ELECTRICITY && IS_LIVE (op))
535 {
536 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++)
537 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1)
538 {
539 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2);
540 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
541 found++;
542 break;
543 }
544 }
545 else if (type & AT_COLD && IS_LIVE (op))
546 {
547 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++)
548 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1)
549 {
550 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2);
551 strcpy (buf2, attack_mess[ATM_COLD][i].buf3);
552 found++;
553 break;
554 }
555 }
556 else if (type & AT_FIRE)
557 {
558 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1; i++)
559 if (dam < attack_mess[ATM_FIRE][i].level || attack_mess[ATM_FIRE][i + 1].level == -1)
560 {
561 sprintf (buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1, &op->name, attack_mess[ATM_FIRE][i].buf2);
562 strcpy (buf2, attack_mess[ATM_FIRE][i].buf3);
563 found++;
564 break;
565 }
566 }
567 else if (hitter->current_weapon != NULL)
568 {
569 int mtype;
570
571 switch (hitter->current_weapon->weapontype)
572 {
573 case WEAP_HIT:
574 mtype = ATM_BASIC;
575 break;
576 case WEAP_SLASH:
577 mtype = ATM_SLASH;
578 break;
579 case WEAP_PIERCE:
580 mtype = ATM_PIERCE;
581 break;
582 case WEAP_CLEAVE:
583 mtype = ATM_CLEAVE;
584 break;
585 case WEAP_SLICE:
586 mtype = ATM_SLICE;
587 break;
588 case WEAP_STAB:
589 mtype = ATM_STAB;
590 break;
591 case WEAP_WHIP:
592 mtype = ATM_WHIP;
593 break;
594 case WEAP_CRUSH:
595 mtype = ATM_CRUSH;
596 break;
597 case WEAP_BLUD:
598 mtype = ATM_BLUD;
599 break;
600 default:
601 mtype = ATM_BASIC;
602 break;
603 }
604 for (i = 0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1; i++)
605 if (dam < attack_mess[mtype][i].level || attack_mess[mtype][i + 1].level == -1)
606 {
607 sprintf (buf1, "%s %s%s", attack_mess[mtype][i].buf1, &op->name, attack_mess[mtype][i].buf2);
608 strcpy (buf2, attack_mess[mtype][i].buf3);
609 found++;
610 break;
611 }
612 }
613 else
614 {
615 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1; i++)
616 if (dam < attack_mess[ATM_BASIC][i].level || attack_mess[ATM_BASIC][i + 1].level == -1)
617 {
618 sprintf (buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1, &op->name, attack_mess[ATM_BASIC][i].buf2);
619 strcpy (buf2, attack_mess[ATM_BASIC][i].buf3);
620 found++;
621 break;
622 }
623 }
624
625 if (!found)
626 {
627 strcpy (buf1, "hit");
628 strcpy (buf2, " hits");
629 }
630
631 /* bail out if a monster is casting spells */
632 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER)))
633 return;
634
635 /* scale down magic considerably. */
636 if (type & AT_MAGIC && rndm (0, 5))
637 return;
638
639 /* Did a player hurt another player? Inform both! */
640 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER)
641 {
642 if (get_owner (hitter) != NULL)
643 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
644 else
645 {
646 sprintf (buf, "%s%s you.", &hitter->name, buf2);
647 if (dam != 0)
648 {
649 if (dam < 10)
650 play_sound_player_only (op->contr, SOUND_PLAYER_IS_HIT1, 0, 0);
651 else if (dam < 20)
652 play_sound_player_only (op->contr, SOUND_PLAYER_IS_HIT2, 0, 0);
653 else
654 play_sound_player_only (op->contr, SOUND_PLAYER_IS_HIT3, 0, 0);
463 } 655 }
464 } else if (type & AT_DRAIN && IS_LIVE(op)) {
465 /* drain is first, because some items have multiple attypes */
466 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1;
467 i++)
468 if (dam < attack_mess[ATM_DRAIN][i].level
469 || attack_mess[ATM_DRAIN][i+1].level == -1) {
470 sprintf(buf1, "%s %s%s", attack_mess[ATM_DRAIN][i].buf1,
471 &op->name, attack_mess[ATM_DRAIN][i].buf2);
472 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
473 found++;
474 break;
475 } 656 }
476 } else if (type & AT_ELECTRICITY && IS_LIVE(op)) {
477 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1;
478 i++)
479 if (dam < attack_mess[ATM_ELEC][i].level
480 || attack_mess[ATM_ELEC][i+1].level == -1) {
481 sprintf(buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1,
482 &op->name, attack_mess[ATM_ELEC][i].buf2);
483 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
484 found++;
485 break;
486 }
487 } else if (type & AT_COLD && IS_LIVE(op)) {
488 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1;
489 i++)
490 if (dam < attack_mess[ATM_COLD][i].level
491 || attack_mess[ATM_COLD][i+1].level == -1) {
492 sprintf(buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1,
493 &op->name, attack_mess[ATM_COLD][i].buf2);
494 strcpy (buf2, attack_mess[ATM_COLD][i].buf3);
495 found++;
496 break;
497 }
498 } else if (type & AT_FIRE) {
499 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_FIRE][i].level != -1;
500 i++)
501 if (dam < attack_mess[ATM_FIRE][i].level
502 || attack_mess[ATM_FIRE][i+1].level == -1) {
503 sprintf(buf1, "%s %s%s", attack_mess[ATM_FIRE][i].buf1,
504 &op->name, attack_mess[ATM_FIRE][i].buf2);
505 strcpy (buf2, attack_mess[ATM_FIRE][i].buf3);
506 found++;
507 break;
508 }
509 } else if (hitter->current_weapon != NULL) {
510 int mtype;
511 switch (hitter->current_weapon->weapontype) {
512 case WEAP_HIT: mtype = ATM_BASIC; break;
513 case WEAP_SLASH: mtype = ATM_SLASH; break;
514 case WEAP_PIERCE: mtype = ATM_PIERCE; break;
515 case WEAP_CLEAVE: mtype = ATM_CLEAVE; break;
516 case WEAP_SLICE: mtype = ATM_SLICE; break;
517 case WEAP_STAB: mtype = ATM_STAB; break;
518 case WEAP_WHIP: mtype = ATM_WHIP; break;
519 case WEAP_CRUSH: mtype = ATM_CRUSH; break;
520 case WEAP_BLUD: mtype = ATM_BLUD; break;
521 default: mtype = ATM_BASIC; break;
522 }
523 for (i=0; i < MAXATTACKMESS && attack_mess[mtype][i].level != -1;
524 i++)
525 if (dam < attack_mess[mtype][i].level
526 || attack_mess[mtype][i+1].level == -1) {
527 sprintf(buf1, "%s %s%s", attack_mess[mtype][i].buf1,
528 &op->name, attack_mess[mtype][i].buf2);
529 strcpy (buf2, attack_mess[mtype][i].buf3);
530 found++;
531 break;
532 }
533 } else {
534 for (i=0; i < MAXATTACKMESS && attack_mess[ATM_BASIC][i].level != -1;
535 i++)
536 if (dam < attack_mess[ATM_BASIC][i].level
537 || attack_mess[ATM_BASIC][i+1].level == -1) {
538 sprintf(buf1, "%s %s%s", attack_mess[ATM_BASIC][i].buf1,
539 &op->name, attack_mess[ATM_BASIC][i].buf2);
540 strcpy (buf2, attack_mess[ATM_BASIC][i].buf3);
541 found++;
542 break;
543 }
544 }
545
546 if (!found) {
547 strcpy (buf1, "hit");
548 strcpy (buf2, " hits");
549 }
550
551 /* bail out if a monster is casting spells */
552 if (!(hitter->type == PLAYER ||
553 (get_owner(hitter) != NULL && hitter->owner->type == PLAYER)))
554 return;
555
556 /* scale down magic considerably. */
557 if (type & AT_MAGIC && rndm(0, 5))
558 return;
559
560 /* Did a player hurt another player? Inform both! */
561 if(op->type==PLAYER &&
562 (get_owner(hitter)==NULL?hitter->type:hitter->owner->type)==PLAYER) {
563 if(get_owner(hitter)!=NULL)
564 sprintf(buf,"%s's %s%s you.",
565 &hitter->owner->name, &hitter->name, buf2);
566 else {
567 sprintf(buf,"%s%s you.", &hitter->name, buf2);
568 if (dam != 0) {
569 if (dam < 10)
570 play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT1,0,0);
571 else if (dam < 20)
572 play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT2,0,0);
573 else
574 play_sound_player_only(op->contr, SOUND_PLAYER_IS_HIT3,0,0);
575 }
576 }
577 new_draw_info(NDI_BLACK, 0,op,buf); 657 new_draw_info (NDI_BLACK, 0, op, buf);
578 } /* end of player hitting player */ 658 } /* end of player hitting player */
579 659
580 if(hitter->type==PLAYER) { 660 if (hitter->type == PLAYER)
661 {
581 sprintf(buf,"You %s.",buf1); 662 sprintf (buf, "You %s.", buf1);
582 if (dam != 0) { 663 if (dam != 0)
664 {
583 if (dam < 10) 665 if (dam < 10)
584 play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS1,0,0); 666 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS1, 0, 0);
585 else if (dam < 20) 667 else if (dam < 20)
586 play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS2,0,0); 668 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS2, 0, 0);
587 else 669 else
588 play_sound_player_only(hitter->contr, SOUND_PLAYER_HITS3,0,0); 670 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
589 } 671 }
590 new_draw_info(NDI_BLACK, 0, hitter, buf); 672 new_draw_info (NDI_BLACK, 0, hitter, buf);
673 }
591 } else if(get_owner(hitter)!=NULL&&hitter->owner->type==PLAYER) { 674 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER)
675 {
592 /* look for stacked spells and start reducing the message chances */ 676 /* look for stacked spells and start reducing the message chances */
593 if (hitter->type == SPELL_EFFECT && 677 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
594 (hitter->subtype == SP_EXPLOSION || 678 {
595 hitter->subtype == SP_BULLET ||
596 hitter->subtype == SP_CONE)) {
597 i=4; 679 i = 4;
598 map = hitter->map; 680 map = hitter->map;
599 if (out_of_map(map, hitter->x, hitter->y)) 681 if (out_of_map (map, hitter->x, hitter->y))
600 return;
601 next = get_map_ob(map, hitter->x, hitter->y);
602 if (next)
603 while(next) {
604 if (next->type == SPELL_EFFECT &&
605 (next->subtype == SP_EXPLOSION || next->subtype==SP_BULLET ||
606 next->subtype == SP_CONE))
607 i*=3;
608 tmp = next;
609 next = tmp->above;
610 }
611 if (i < 0)
612 return;
613 if (rndm(0, i) != 0)
614 return;
615 } else if (rndm(0, 5) != 0)
616 return; 682 return;
683 next = get_map_ob (map, hitter->x, hitter->y);
684 if (next)
685 while (next)
686 {
687 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE))
688 i *= 3;
689 tmp = next;
690 next = tmp->above;
691 }
692 if (i < 0)
693 return;
694 if (rndm (0, i) != 0)
695 return;
696 }
697 else if (rndm (0, 5) != 0)
698 return;
617 sprintf(buf,"Your %s%s %s.", &hitter->name, buf2, &op->name); 699 sprintf (buf, "Your %s%s %s.", &hitter->name, buf2, &op->name);
618 play_sound_map(op->map, op->x, op->y, SOUND_PLAYER_HITS4); 700 play_sound_map (op->map, op->x, op->y, SOUND_PLAYER_HITS4);
619 new_draw_info(NDI_BLACK, 0, hitter->owner, buf); 701 new_draw_info (NDI_BLACK, 0, hitter->owner, buf);
620 } 702 }
621} 703}
622 704
623 705
706static int
624static int get_attack_mode (object **target, object **hitter, 707get_attack_mode (object **target, object **hitter, int *simple_attack)
625 int *simple_attack)
626{ 708{
627 if (QUERY_FLAG (*target, FLAG_FREED) || QUERY_FLAG (*hitter, FLAG_FREED)) { 709 if (QUERY_FLAG (*target, FLAG_FREED) || QUERY_FLAG (*hitter, FLAG_FREED))
710 {
628 LOG (llevError, "BUG: get_attack_mode(): freed object\n"); 711 LOG (llevError, "BUG: get_attack_mode(): freed object\n");
629 return 1; 712 return 1;
630 } 713 }
631 if ((*target)->head) 714 if ((*target)->head)
632 *target = (*target)->head; 715 *target = (*target)->head;
633 if ((*hitter)->head) 716 if ((*hitter)->head)
634 *hitter = (*hitter)->head; 717 *hitter = (*hitter)->head;
635 if ((*hitter)->env != NULL || (*target)->env != NULL) { 718 if ((*hitter)->env != NULL || (*target)->env != NULL)
719 {
636 *simple_attack = 1; 720 *simple_attack = 1;
637 return 0; 721 return 0;
638 } 722 }
639 if (QUERY_FLAG (*target, FLAG_REMOVED) 723 if (QUERY_FLAG (*target, FLAG_REMOVED)
640 || QUERY_FLAG (*hitter, FLAG_REMOVED)
641 || (*hitter)->map == NULL || !on_same_map((*hitter), (*target))) 724 || QUERY_FLAG (*hitter, FLAG_REMOVED) || (*hitter)->map == NULL || !on_same_map ((*hitter), (*target)))
642 { 725 {
643 LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to " 726 LOG (llevError, "BUG: hitter (arch %s, name %s) with no relation to " "target\n", &(*hitter)->arch->name, &(*hitter)->name);
644 "target\n", &(*hitter)->arch->name, &(*hitter)->name);
645 return 1; 727 return 1;
646 } 728 }
647 *simple_attack = 0; 729 *simple_attack = 0;
648 return 0; 730 return 0;
649} 731}
650 732
733static int
651static int abort_attack (object *target, object *hitter, int simple_attack) 734abort_attack (object *target, object *hitter, int simple_attack)
652{ 735{
736
653/* Check if target and hitter are still in a relation similar to the one 737/* Check if target and hitter are still in a relation similar to the one
654 * determined by get_attack_mode(). Returns true if the relation has changed. 738 * determined by get_attack_mode(). Returns true if the relation has changed.
655 */ 739 */
656 int new_mode; 740 int new_mode;
657 741
658 if (hitter->env == target || target->env == hitter) 742 if (hitter->env == target || target->env == hitter)
659 new_mode = 1; 743 new_mode = 1;
660 else if (QUERY_FLAG (hitter, FLAG_REMOVED) 744 else if (QUERY_FLAG (hitter, FLAG_REMOVED) || QUERY_FLAG (target, FLAG_REMOVED) || hitter->map == NULL || !on_same_map (hitter, target))
661 || QUERY_FLAG (target, FLAG_REMOVED)
662 || hitter->map == NULL || !on_same_map(hitter, target))
663 return 1; 745 return 1;
664 else 746 else
665 new_mode = 0; 747 new_mode = 0;
666 return new_mode != simple_attack; 748 return new_mode != simple_attack;
667} 749}
668 750
669static void thrown_item_effect (object *, object *); 751static void thrown_item_effect (object *, object *);
670 752
753static int
671static int attack_ob_simple (object *op, object *hitter, int base_dam, 754attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
672 int base_wc)
673{ 755{
674 int simple_attack, roll, dam=0; 756 int simple_attack, roll, dam = 0;
675 uint32 type; 757 uint32 type;
676 shstr op_name; 758 shstr op_name;
677 tag_t op_tag, hitter_tag; 759 tag_t op_tag, hitter_tag;
678 760
679 if (get_attack_mode (&op, &hitter, &simple_attack)) 761 if (get_attack_mode (&op, &hitter, &simple_attack))
762 goto error;
763
764 if (hitter->current_weapon)
765 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
766 return RESULT_INT (0);
767
768 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
769 return RESULT_INT (0);
770
771 op_tag = op->count;
772 hitter_tag = hitter->count;
773
774 /*
775 * A little check to make it more difficult to dance forward and back
776 * to avoid ever being hit by monsters.
777 */
778 if (!simple_attack && QUERY_FLAG (op, FLAG_MONSTER) && op->speed_left > -(FABS (op->speed)) * 0.3)
779 {
780 /* Decrease speed BEFORE calling process_object. Otherwise, an
781 * infinite loop occurs, with process_object calling move_monster,
782 * which then gets here again. By decreasing the speed before
783 * we call process_object, the 'if' statement above will fail.
784 */
785 op->speed_left--;
786 process_object (op);
787 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack))
680 goto error; 788 goto error;
681
682 if (hitter->current_weapon)
683 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
684 return RESULT_INT (0);
685
686 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
687 return RESULT_INT (0);
688
689 op_tag = op->count;
690 hitter_tag = hitter->count;
691
692 /*
693 * A little check to make it more difficult to dance forward and back
694 * to avoid ever being hit by monsters.
695 */
696 if ( ! simple_attack && QUERY_FLAG (op, FLAG_MONSTER)
697 && op->speed_left > -(FABS(op->speed))*0.3)
698 { 789 }
699 /* Decrease speed BEFORE calling process_object. Otherwise, an
700 * infinite loop occurs, with process_object calling move_monster,
701 * which then gets here again. By decreasing the speed before
702 * we call process_object, the 'if' statement above will fail.
703 */
704 op->speed_left--;
705 process_object(op);
706 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag)
707 || abort_attack (op, hitter, simple_attack))
708 goto error;
709 }
710 790
711 op_name = op->name; 791 op_name = op->name;
712 792
713 roll=random_roll(1, 20, hitter, PREFER_HIGH); 793 roll = random_roll (1, 20, hitter, PREFER_HIGH);
714 794
715 /* Adjust roll for various situations. */ 795 /* Adjust roll for various situations. */
716 if ( ! simple_attack) 796 if (!simple_attack)
717 roll += adj_attackroll(hitter,op); 797 roll += adj_attackroll (hitter, op);
718 798
719 /* See if we hit the creature */ 799 /* See if we hit the creature */
720 if(roll==20 || op->stats.ac>=base_wc-roll) { 800 if (roll == 20 || op->stats.ac >= base_wc - roll)
801 {
721 int hitdam = base_dam; 802 int hitdam = base_dam;
803
722 if (settings.casting_time == TRUE) { 804 if (settings.casting_time == TRUE)
805 {
723 if ((hitter->type == PLAYER)&&(hitter->casting_time > -1)){ 806 if ((hitter->type == PLAYER) && (hitter->casting_time > -1))
807 {
724 hitter->casting_time = -1; 808 hitter->casting_time = -1;
725 new_draw_info(NDI_UNIQUE, 0,hitter,"You attacked and lost " 809 new_draw_info (NDI_UNIQUE, 0, hitter, "You attacked and lost " "your spell!");
726 "your spell!");
727 } 810 }
728 if ((op->casting_time > -1)&&(hitdam > 0)){ 811 if ((op->casting_time > -1) && (hitdam > 0))
812 {
729 op->casting_time = -1; 813 op->casting_time = -1;
730 if (op->type == PLAYER) { 814 if (op->type == PLAYER)
815 {
731 new_draw_info(NDI_UNIQUE, 0,op,"You were hit and lost " 816 new_draw_info (NDI_UNIQUE, 0, op, "You were hit and lost " "your spell!");
732 "your spell!"); 817 new_draw_info_format (NDI_ALL | NDI_UNIQUE, 5, NULL, "%s was hit by %s and lost a spell.", &op_name, &hitter->name);
733 new_draw_info_format(NDI_ALL|NDI_UNIQUE,5,NULL,
734 "%s was hit by %s and lost a spell.",
735 &op_name,&hitter->name);
736 } 818 }
737 } 819 }
738 } 820 }
739 if ( ! simple_attack) 821 if (!simple_attack)
740 { 822 {
741 /* If you hit something, the victim should *always* wake up. 823 /* If you hit something, the victim should *always* wake up.
742 * Before, invisible hitters could avoid doing this. 824 * Before, invisible hitters could avoid doing this.
743 * -b.t. */ 825 * -b.t. */
744 if (QUERY_FLAG (op, FLAG_SLEEP)) 826 if (QUERY_FLAG (op, FLAG_SLEEP))
745 CLEAR_FLAG(op,FLAG_SLEEP); 827 CLEAR_FLAG (op, FLAG_SLEEP);
746 828
747 /* If the victim can't see the attacker, it may alert others 829 /* If the victim can't see the attacker, it may alert others
748 * for help. */ 830 * for help. */
749 if (op->type != PLAYER && ! can_see_enemy (op, hitter) 831 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int))
750 && ! get_owner (op) && rndm(0, op->stats.Int))
751 npc_call_help (op); 832 npc_call_help (op);
752 833
753 /* if you were hidden and hit by a creature, you are discovered*/ 834 /* if you were hidden and hit by a creature, you are discovered */
754 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) { 835 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
836 {
755 make_visible (op); 837 make_visible (op);
756 if (op->type == PLAYER) 838 if (op->type == PLAYER)
757 new_draw_info (NDI_UNIQUE, 0, op, 839 new_draw_info (NDI_UNIQUE, 0, op, "You were hit by a wild attack. " "You are no longer hidden!");
758 "You were hit by a wild attack. "
759 "You are no longer hidden!");
760 } 840 }
761 841
762 /* thrown items (hitter) will have various effects 842 /* thrown items (hitter) will have various effects
763 * when they hit the victim. For things like thrown daggers, 843 * when they hit the victim. For things like thrown daggers,
764 * this sets 'hitter' to the actual dagger, and not the 844 * this sets 'hitter' to the actual dagger, and not the
765 * wrapper object. 845 * wrapper object.
766 */ 846 */
767 thrown_item_effect (hitter, op); 847 thrown_item_effect (hitter, op);
768 if (was_destroyed (hitter, hitter_tag) 848 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack))
769 || was_destroyed (op, op_tag)
770 || abort_attack (op, hitter, simple_attack))
771 goto leave;
772 }
773
774 /* Need to do at least 1 damage, otherwise there is no point
775 * to go further and it will cause FPE's below.
776 */
777 if (hitdam<=0) hitdam=1;
778
779 type=hitter->attacktype;
780 if(!type) type=AT_PHYSICAL;
781 /* Handle monsters that hit back */
782 if ( ! simple_attack && QUERY_FLAG (op, FLAG_HITBACK)
783 && QUERY_FLAG (hitter, FLAG_ALIVE))
784 {
785 if (op->attacktype & AT_ACID && hitter->type==PLAYER)
786 new_draw_info(NDI_UNIQUE, 0,hitter,"You are splashed by acid!\n");
787 hit_player(hitter, random_roll(0, (op->stats.dam), hitter,
788 PREFER_LOW),op, op->attacktype, 1);
789 if (was_destroyed (op, op_tag)
790 || was_destroyed (hitter, hitter_tag)
791 || abort_attack (op, hitter, simple_attack))
792 goto leave;
793 }
794
795 /* In the new attack code, it should handle multiple attack
796 * types in its area, so remove it from here.
797 */
798 dam=hit_player(op, random_roll(1, hitdam, hitter, PREFER_HIGH),
799 hitter, type, 1);
800 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag)
801 || abort_attack (op, hitter, simple_attack))
802 goto leave; 849 goto leave;
803 } /* end of if hitter hit op */ 850 }
851
852 /* Need to do at least 1 damage, otherwise there is no point
853 * to go further and it will cause FPE's below.
854 */
855 if (hitdam <= 0)
856 hitdam = 1;
857
858 type = hitter->attacktype;
859 if (!type)
860 type = AT_PHYSICAL;
861 /* Handle monsters that hit back */
862 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
863 {
864 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
865 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
866 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
867 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack))
868 goto leave;
869 }
870
871 /* In the new attack code, it should handle multiple attack
872 * types in its area, so remove it from here.
873 */
874 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
875 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack))
876 goto leave;
877 } /* end of if hitter hit op */
804 /* if we missed, dam=0 */ 878 /* if we missed, dam=0 */
805 879
806 /*attack_message(dam, type, op, hitter);*/ 880 /*attack_message(dam, type, op, hitter); */
807 881
808 goto leave; 882 goto leave;
809 883
810 error: 884error:
811 dam = 1; 885 dam = 1;
812 886
813 leave: 887leave:
814 888
815 return dam; 889 return dam;
816} 890}
817 891
892int
818int attack_ob (object *op, object *hitter) 893attack_ob (object *op, object *hitter)
819{ 894{
820 895
821 if (hitter->head) 896 if (hitter->head)
822 hitter = hitter->head; 897 hitter = hitter->head;
823 return attack_ob_simple (op, hitter, hitter->stats.dam, hitter->stats.wc); 898 return attack_ob_simple (op, hitter, hitter->stats.dam, hitter->stats.wc);
824} 899}
825 900
826/* op is the arrow, tmp is what is stopping the arrow. 901/* op is the arrow, tmp is what is stopping the arrow.
827 * 902 *
828 * Returns 1 if op was inserted into tmp's inventory, 0 otherwise. 903 * Returns 1 if op was inserted into tmp's inventory, 0 otherwise.
829 */ 904 */
905static int
830static int stick_arrow (object *op, object *tmp) 906stick_arrow (object *op, object *tmp)
831{ 907{
832 /* If the missile hit a player, we insert it in their inventory. 908 /* If the missile hit a player, we insert it in their inventory.
833 * However, if the missile is heavy, we don't do so (assume it falls 909 * However, if the missile is heavy, we don't do so (assume it falls
834 * to the ground after a hit). What a good value for this is up to 910 * to the ground after a hit). What a good value for this is up to
835 * debate - 5000 is 5 kg, so arrows, knives, and other light weapons 911 * debate - 5000 is 5 kg, so arrows, knives, and other light weapons
836 * stick around. 912 * stick around.
837 */ 913 */
838 if (op->weight <= 5000 && tmp->stats.hp >= 0) { 914 if (op->weight <= 5000 && tmp->stats.hp >= 0)
915 {
839 if(tmp->head != NULL) 916 if (tmp->head != NULL)
840 tmp = tmp->head; 917 tmp = tmp->head;
918
841 remove_ob (op); 919 remove_ob (op);
842 op = insert_ob_in_ob(op,tmp); 920 op = insert_ob_in_ob (op, tmp);
921
843 if (tmp->type== PLAYER) 922 if (tmp->type == PLAYER)
844 esrv_send_item (tmp, op); 923 esrv_send_item (tmp, op);
924
845 return 1; 925 return 1;
926 }
846 } else 927 else
847 return 0; 928 return 0;
848} 929}
849 930
850/* hit_with_arrow() disassembles the missile, attacks the victim and 931/* hit_with_arrow() disassembles the missile, attacks the victim and
851 * reassembles the missile. 932 * reassembles the missile.
852 * 933 *
853 * It returns a pointer to the reassembled missile, or NULL if the missile 934 * It returns a pointer to the reassembled missile, or NULL if the missile
854 * isn't available anymore. 935 * isn't available anymore.
855 */ 936 */
937object *
856object *hit_with_arrow (object *op, object *victim) 938hit_with_arrow (object *op, object *victim)
857{ 939{
858 object *container, *hitter; 940 object *container, *hitter;
859 int hit_something = 0; 941 int hit_something = 0;
860 tag_t victim_tag, hitter_tag; 942 tag_t victim_tag, hitter_tag;
861 sint16 victim_x, victim_y; 943 sint16 victim_x, victim_y;
862 944
863 /* Disassemble missile */ 945 /* Disassemble missile */
864 if (op->inv) { 946 if (op->inv)
947 {
865 container = op; 948 container = op;
866 hitter = op->inv; 949 hitter = op->inv;
867 remove_ob (hitter); 950 remove_ob (hitter);
868 insert_ob_in_map(hitter, container->map,hitter,INS_NO_MERGE | INS_NO_WALK_ON); 951 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON);
869 /* Note that we now have an empty THROWN_OBJ on the map. Code that 952 /* Note that we now have an empty THROWN_OBJ on the map. Code that
870 * might be called until this THROWN_OBJ is either reassembled or 953 * might be called until this THROWN_OBJ is either reassembled or
871 * removed at the end of this function must be able to deal with empty 954 * removed at the end of this function must be able to deal with empty
872 * THROWN_OBJs. */ 955 * THROWN_OBJs. */
873 } else { 956 }
957 else
958 {
874 container = NULL; 959 container = NULL;
875 hitter = op; 960 hitter = op;
876 } 961 }
877 962
878 /* Try to hit victim */ 963 /* Try to hit victim */
879 victim_x = victim->x; 964 victim_x = victim->x;
880 victim_y = victim->y; 965 victim_y = victim->y;
881 victim_tag = victim->count; 966 victim_tag = victim->count;
882 hitter_tag = hitter->count; 967 hitter_tag = hitter->count;
883 968
884 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 969 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
885 970
886 /* Arrow attacks door, rune of summoning is triggered, demon is put on 971 /* Arrow attacks door, rune of summoning is triggered, demon is put on
887 * arrow, move_apply() calls this function, arrow sticks in demon, 972 * arrow, move_apply() calls this function, arrow sticks in demon,
888 * attack_ob_simple() returns, and we've got an arrow that still exists 973 * attack_ob_simple() returns, and we've got an arrow that still exists
889 * but is no longer on the map. Ugh. (Beware: Such things can happen at 974 * but is no longer on the map. Ugh. (Beware: Such things can happen at
890 * other places as well!) 975 * other places as well!)
891 */ 976 */
892 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) { 977 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL)
978 {
893 if (container) { 979 if (container)
980 {
894 remove_ob (container); 981 remove_ob (container);
895 free_object (container); 982 free_object (container);
983 }
984 return NULL;
985 }
986
987 /* Missile hit victim */
988 /* if the speed is > 10, then this is a fast moving arrow, we go straight
989 * through the target
990 */
991 if (hit_something && op->speed <= 10.0)
992 {
993 /* Stop arrow */
994 if (container == NULL)
896 } 995 {
996 hitter = fix_stopped_arrow (hitter);
997 if (hitter == NULL)
998 return NULL;
999 }
1000 else
1001 {
1002 remove_ob (container);
1003 free_object (container);
1004 }
1005
1006 /* Try to stick arrow into victim */
1007 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim))
897 return NULL; 1008 return NULL;
898 }
899 1009
900 /* Missile hit victim */
901 /* if the speed is > 10, then this is a fast moving arrow, we go straight
902 * through the target
903 */
904 if (hit_something && op->speed <= 10.0)
905 {
906 /* Stop arrow */
907 if (container == NULL) {
908 hitter = fix_stopped_arrow (hitter);
909 if (hitter == NULL)
910 return NULL;
911 } else {
912 remove_ob (container);
913 free_object (container);
914 }
915
916 /* Try to stick arrow into victim */
917 if ( ! was_destroyed (victim, victim_tag)
918 && stick_arrow (hitter, victim))
919 return NULL;
920
921 /* Else try to put arrow on victim's map square 1010 /* Else try to put arrow on victim's map square
922 * remove check for P_WALL here. If the arrow got to this 1011 * remove check for P_WALL here. If the arrow got to this
923 * space, that is good enough - with the new movement code, 1012 * space, that is good enough - with the new movement code,
924 * there is now the potential for lots of spaces where something 1013 * there is now the potential for lots of spaces where something
925 * can fly over but not otherwise move over. What is the correct 1014 * can fly over but not otherwise move over. What is the correct
926 * way to handle those otherwise? 1015 * way to handle those otherwise?
927 */ 1016 */
928 if (victim_x != hitter->x || victim_y != hitter->y) { 1017 if (victim_x != hitter->x || victim_y != hitter->y)
1018 {
929 remove_ob (hitter); 1019 remove_ob (hitter);
930 hitter->x = victim_x; 1020 hitter->x = victim_x;
931 hitter->y = victim_y; 1021 hitter->y = victim_y;
932 insert_ob_in_map (hitter, victim->map, hitter,0); 1022 insert_ob_in_map (hitter, victim->map, hitter, 0);
1023 }
933 } else { 1024 else
1025 {
934 /* Else leave arrow where it is */ 1026 /* Else leave arrow where it is */
935 merge_ob (hitter, NULL); 1027 merge_ob (hitter, NULL);
936 } 1028 }
937 return NULL; 1029 return NULL;
938 } 1030 }
939 1031
940 if (hit_something && op->speed >= 10.0) 1032 if (hit_something && op->speed >= 10.0)
941 op->speed -= 1.0; 1033 op->speed -= 1.0;
942 1034
943 /* Missile missed victim - reassemble missile */ 1035 /* Missile missed victim - reassemble missile */
944 if (container) { 1036 if (container)
1037 {
945 remove_ob (hitter); 1038 remove_ob (hitter);
946 insert_ob_in_ob (hitter, container); 1039 insert_ob_in_ob (hitter, container);
947 } 1040 }
948 return op; 1041 return op;
949} 1042}
950 1043
951 1044
1045void
952void tear_down_wall(object *op) 1046tear_down_wall (object *op)
953{ 1047{
954 int perc=0; 1048 int perc = 0;
955 1049
956 if (!op->stats.maxhp) { 1050 if (!op->stats.maxhp)
1051 {
957 LOG(llevError, "TEAR_DOWN wall %s had no maxhp.\n", &op->name); 1052 LOG (llevError, "TEAR_DOWN wall %s had no maxhp.\n", &op->name);
958 perc = 1; 1053 perc = 1;
1054 }
959 } else if(!GET_ANIM_ID(op)) { 1055 else if (!GET_ANIM_ID (op))
1056 {
960 /* Object has been called - no animations, so remove it */ 1057 /* Object has been called - no animations, so remove it */
961 if(op->stats.hp<0) { 1058 if (op->stats.hp < 0)
1059 {
962 remove_ob(op); /* Should update LOS */ 1060 remove_ob (op); /* Should update LOS */
963 free_object(op); 1061 free_object (op);
964 /* Don't know why this is here - remove_ob should do it for us */ 1062 /* Don't know why this is here - remove_ob should do it for us */
965 /*update_position(m, x, y);*/ 1063 /*update_position(m, x, y); */
966 } 1064 }
967 return; /* no animations, so nothing more to do */ 1065 return; /* no animations, so nothing more to do */
968 } 1066 }
969 perc = NUM_ANIMATIONS(op) 1067 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
970 - ((int)NUM_ANIMATIONS(op)*op->stats.hp)/op->stats.maxhp;
971 if (perc >= (int) NUM_ANIMATIONS(op)) 1068 if (perc >= (int) NUM_ANIMATIONS (op))
972 perc = NUM_ANIMATIONS(op)-1; 1069 perc = NUM_ANIMATIONS (op) - 1;
973 else if (perc < 1) 1070 else if (perc < 1)
974 perc = 1; 1071 perc = 1;
975 SET_ANIMATION(op, perc); 1072 SET_ANIMATION (op, perc);
976 update_object(op,UP_OBJ_FACE); 1073 update_object (op, UP_OBJ_FACE);
977 if(perc==NUM_ANIMATIONS(op)-1) { /* Reached the last animation */ 1074 if (perc == NUM_ANIMATIONS (op) - 1)
1075 { /* Reached the last animation */
978 if(op->face==blank_face) { 1076 if (op->face == blank_face)
1077 {
979 /* If the last face is blank, remove the ob */ 1078 /* If the last face is blank, remove the ob */
980 remove_ob(op); /* Should update LOS */ 1079 remove_ob (op); /* Should update LOS */
981 free_object(op); 1080 free_object (op);
982 1081
983 /* remove_ob should call update_position for us */ 1082 /* remove_ob should call update_position for us */
984 /*update_position(m, x, y);*/ 1083 /*update_position(m, x, y); */
985 1084
1085 }
1086 else
986 } else { /* The last face was not blank, leave an image */ 1087 { /* The last face was not blank, leave an image */
987 CLEAR_FLAG(op, FLAG_BLOCKSVIEW); 1088 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
988 update_all_los(op->map, op->x, op->y); 1089 update_all_los (op->map, op->x, op->y);
989 op->move_block = 0; 1090 op->move_block = 0;
990 CLEAR_FLAG(op, FLAG_ALIVE); 1091 CLEAR_FLAG (op, FLAG_ALIVE);
991 } 1092 }
992 } 1093 }
993} 1094}
994 1095
1096void
995void scare_creature(object *target, object *hitter) 1097scare_creature (object *target, object *hitter)
996{ 1098{
997 object *owner = get_owner(hitter); 1099 object *owner = get_owner (hitter);
998 1100
999 if (!owner) owner=hitter; 1101 if (!owner)
1102 owner = hitter;
1000 1103
1001 SET_FLAG(target, FLAG_SCARED); 1104 SET_FLAG (target, FLAG_SCARED);
1002 if (!target->enemy) target->enemy=owner; 1105 if (!target->enemy)
1106 target->enemy = owner;
1003} 1107}
1004 1108
1005 1109
1006/* This returns the amount of damage hitter does to op with the 1110/* This returns the amount of damage hitter does to op with the
1007 * appropriate attacktype. Only 1 attacktype should be set at a time. 1111 * appropriate attacktype. Only 1 attacktype should be set at a time.
1008 * This doesn't damage the player, but returns how much it should 1112 * This doesn't damage the player, but returns how much it should
1009 * take. However, it will do other effects (paralyzation, slow, etc.) 1113 * take. However, it will do other effects (paralyzation, slow, etc.)
1010 * Note - changed for PR code - we now pass the attack number and not 1114 * Note - changed for PR code - we now pass the attack number and not
1011 * the attacktype. Makes it easier for the PR code. */ 1115 * the attacktype. Makes it easier for the PR code. */
1012 1116
1117int
1013int hit_player_attacktype(object *op, object *hitter, int dam, 1118hit_player_attacktype (object *op, object *hitter, int dam, uint32 attacknum, int magic)
1014 uint32 attacknum, int magic) { 1119{
1015 1120
1016 int doesnt_slay = 1; 1121 int doesnt_slay = 1;
1017 1122
1018 /* Catch anyone that may be trying to send us a bitmask instead of the number */ 1123 /* Catch anyone that may be trying to send us a bitmask instead of the number */
1019 if (attacknum >= NROFATTACKS) { 1124 if (attacknum >= NROFATTACKS)
1125 {
1020 LOG(llevError, "hit_player_attacktype: Invalid attacknumber passed: %u\n", attacknum); 1126 LOG (llevError, "hit_player_attacktype: Invalid attacknumber passed: %u\n", attacknum);
1021 return 0; 1127 return 0;
1022 }
1023 1128 }
1129
1024 if (dam < 0) { 1130 if (dam < 0)
1131 {
1025 LOG(llevError,"hit_player_attacktype called with negative damage: %d\n", dam); 1132 LOG (llevError, "hit_player_attacktype called with negative damage: %d\n", dam);
1026 return 0; 1133 return 0;
1027 }
1028 1134 }
1135
1029 /* AT_INTERNAL is supposed to do exactly dam. Put a case here so 1136 /* AT_INTERNAL is supposed to do exactly dam. Put a case here so
1030 * people can't mess with that or it otherwise get confused. */ 1137 * people can't mess with that or it otherwise get confused. */
1031 if (attacknum == ATNR_INTERNAL) return dam; 1138 if (attacknum == ATNR_INTERNAL)
1032 1139 return dam;
1140
1033 if (hitter->slaying) { 1141 if (hitter->slaying)
1142 {
1034 if(((op->race != NULL) && strstr(hitter->slaying, op->race)) || 1143 if (((op->race != NULL) && strstr (hitter->slaying, op->race)) ||
1035 (op->arch && (op->arch->name != NULL) && 1144 (op->arch && (op->arch->name != NULL) && strstr (op->arch->name, hitter->slaying)))
1036 strstr(op->arch->name, hitter->slaying))
1037 ){ 1145 {
1038 doesnt_slay = 0; 1146 doesnt_slay = 0;
1039 dam *= 3; 1147 dam *= 3;
1040 } 1148 }
1041 } 1149 }
1042 1150
1043 /* Adjust the damage for resistance. Note that neg. values increase damage. */ 1151 /* Adjust the damage for resistance. Note that neg. values increase damage. */
1044 if (op->resist[attacknum]) { 1152 if (op->resist[attacknum])
1153 {
1045 /* basically: dam = dam*(100-op->resist[attacknum])/100; 1154 /* basically: dam = dam*(100-op->resist[attacknum])/100;
1046 * in case 0>dam>1, we try to "simulate" a float value-effect */ 1155 * in case 0>dam>1, we try to "simulate" a float value-effect */
1047 dam *= (100-op->resist[attacknum]); 1156 dam *= (100 - op->resist[attacknum]);
1048 if (dam >= 100) dam /= 100; 1157 if (dam >= 100)
1158 dam /= 100;
1049 else 1159 else
1050 dam = (dam > (random_roll(0, 99, op, PREFER_LOW))) ? 1 : 0; 1160 dam = (dam > (random_roll (0, 99, op, PREFER_LOW))) ? 1 : 0;
1051 } 1161 }
1052 1162
1053 /* Special hack. By default, if immune to something, you 1163 /* Special hack. By default, if immune to something, you
1054 * shouldn't need to worry. However, acid is an exception, since 1164 * shouldn't need to worry. However, acid is an exception, since
1055 * it can still damage your items. Only include attacktypes if 1165 * it can still damage your items. Only include attacktypes if
1056 * special processing is needed */ 1166 * special processing is needed */
1057 1167
1058 if ((op->resist[attacknum] >= 100) && 1168 if ((op->resist[attacknum] >= 100) && doesnt_slay && (attacknum != ATNR_ACID))
1059 doesnt_slay && (attacknum != ATNR_ACID))
1060 return 0; 1169 return 0;
1061 1170
1062 /* Keep this in order - makes things easier to find */ 1171 /* Keep this in order - makes things easier to find */
1172
1173 switch (attacknum)
1063 1174 {
1064 switch(attacknum) {
1065 case ATNR_PHYSICAL: 1175 case ATNR_PHYSICAL:
1066 /* here also check for diseases */ 1176 /* here also check for diseases */
1067 check_physically_infect(op, hitter); 1177 check_physically_infect (op, hitter);
1068 break; 1178 break;
1069 1179
1070 /* Don't need to do anything for: 1180 /* Don't need to do anything for:
1071 magic, 1181 magic,
1072 fire, 1182 fire,
1073 electricity, 1183 electricity,
1074 cold */ 1184 cold */
1075 1185
1076 case ATNR_CONFUSION: 1186 case ATNR_CONFUSION:
1077 case ATNR_POISON: 1187 case ATNR_POISON:
1078 case ATNR_SLOW: 1188 case ATNR_SLOW:
1079 case ATNR_PARALYZE: 1189 case ATNR_PARALYZE:
1080 case ATNR_FEAR: 1190 case ATNR_FEAR:
1081 case ATNR_CANCELLATION: 1191 case ATNR_CANCELLATION:
1082 case ATNR_DEPLETE: 1192 case ATNR_DEPLETE:
1083 case ATNR_BLIND: 1193 case ATNR_BLIND:
1084 { 1194 {
1085 /* chance for inflicting a special attack depends on the 1195 /* chance for inflicting a special attack depends on the
1086 * difference between attacker's and defender's level 1196 * difference between attacker's and defender's level
1087 */ 1197 */
1088 int level_diff = MIN(110, MAX(0, op->level - hitter->level)); 1198 int level_diff = MIN (110, MAX (0, op->level - hitter->level));
1089 1199
1090 /* First, only creatures/players with speed can be affected. 1200 /* First, only creatures/players with speed can be affected.
1091 * Second, just getting hit doesn't mean it always affects 1201 * Second, just getting hit doesn't mean it always affects
1092 * you. Third, you still get a saving through against the 1202 * you. Third, you still get a saving through against the
1093 * effect. 1203 * effect.
1094 */ 1204 */
1095 if (op->speed && 1205 if (op->speed &&
1096 (QUERY_FLAG(op, FLAG_MONSTER) || op->type==PLAYER) && 1206 (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER) &&
1097 !(rndm(0, (attacknum == ATNR_SLOW?6:3)-1)) && 1207 !(rndm (0, (attacknum == ATNR_SLOW ? 6 : 3) - 1)) && !did_make_save (op, level_diff, op->resist[attacknum] / 10))
1098 !did_make_save(op, level_diff, op->resist[attacknum]/10)) { 1208 {
1099 1209
1100 /* Player has been hit by something */ 1210 /* Player has been hit by something */
1101 if (attacknum == ATNR_CONFUSION) confuse_player(op,hitter,dam); 1211 if (attacknum == ATNR_CONFUSION)
1212 confuse_player (op, hitter, dam);
1102 else if (attacknum == ATNR_POISON) poison_player(op,hitter,dam); 1213 else if (attacknum == ATNR_POISON)
1214 poison_player (op, hitter, dam);
1103 else if (attacknum == ATNR_SLOW) slow_player(op,hitter,dam); 1215 else if (attacknum == ATNR_SLOW)
1216 slow_player (op, hitter, dam);
1104 else if (attacknum == ATNR_PARALYZE) paralyze_player(op,hitter,dam); 1217 else if (attacknum == ATNR_PARALYZE)
1218 paralyze_player (op, hitter, dam);
1105 else if (attacknum == ATNR_FEAR) scare_creature(op, hitter); 1219 else if (attacknum == ATNR_FEAR)
1220 scare_creature (op, hitter);
1106 else if (attacknum == ATNR_CANCELLATION) cancellation(op); 1221 else if (attacknum == ATNR_CANCELLATION)
1222 cancellation (op);
1107 else if (attacknum == ATNR_DEPLETE) drain_stat(op); 1223 else if (attacknum == ATNR_DEPLETE)
1224 drain_stat (op);
1108 else if (attacknum == ATNR_BLIND && !QUERY_FLAG(op,FLAG_UNDEAD) && 1225 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR))
1109 !QUERY_FLAG(op,FLAG_GENERATOR)) blind_player(op,hitter,dam); 1226 blind_player (op, hitter, dam);
1110 } 1227 }
1111 dam = 0; /* These are all effects and don't do real damage */ 1228 dam = 0; /* These are all effects and don't do real damage */
1112 } 1229 }
1113 break; 1230 break;
1114 case ATNR_ACID: 1231 case ATNR_ACID:
1115 {
1116 int flag=0;
1117
1118 /* Items only get corroded if you're not on a battleground and
1119 * if your acid resistance is below 50%. */
1120 if (!op_on_battleground(op, NULL, NULL) &&
1121 (op->resist[ATNR_ACID] < 50))
1122 { 1232 {
1233 int flag = 0;
1234
1235 /* Items only get corroded if you're not on a battleground and
1236 * if your acid resistance is below 50%. */
1237 if (!op_on_battleground (op, NULL, NULL) && (op->resist[ATNR_ACID] < 50))
1238 {
1123 object *tmp; 1239 object *tmp;
1240
1124 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 1241 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1242 {
1125 if(tmp->invisible) 1243 if (tmp->invisible)
1126 continue; 1244 continue;
1127 if(!QUERY_FLAG(tmp, FLAG_APPLIED) || 1245 if (!QUERY_FLAG (tmp, FLAG_APPLIED) || (tmp->resist[ATNR_ACID] >= 10))
1128 (tmp->resist[ATNR_ACID] >= 10))
1129 /* >= 10% acid res. on itmes will protect these */ 1246 /* >= 10% acid res. on itmes will protect these */
1130 continue; 1247 continue;
1131 if(!(tmp->material & M_IRON)) 1248 if (!(tmp->material & M_IRON))
1132 continue; 1249 continue;
1133 if(tmp->magic < -4) /* Let's stop at -5 */ 1250 if (tmp->magic < -4) /* Let's stop at -5 */
1134 continue; 1251 continue;
1135 if(tmp->type==RING || 1252 if (tmp->type == RING ||
1136 /* removed boots and gloves from exclusion list in 1253 /* removed boots and gloves from exclusion list in
1137 PR */ 1254 PR */
1138 tmp->type==GIRDLE || 1255 tmp->type == GIRDLE || tmp->type == AMULET || tmp->type == WAND || tmp->type == ROD || tmp->type == HORN)
1139 tmp->type==AMULET ||
1140 tmp->type==WAND ||
1141 tmp->type==ROD ||
1142 tmp->type==HORN)
1143 continue; /* To avoid some strange effects */ 1256 continue; /* To avoid some strange effects */
1144 1257
1145 /* High damage acid has better chance of corroding 1258 /* High damage acid has better chance of corroding
1146 objects */ 1259 objects */
1147 if(rndm(0, dam+4) >
1148 random_roll(0, 39, op, PREFER_HIGH)+2*tmp->magic) { 1260 if (rndm (0, dam + 4) > random_roll (0, 39, op, PREFER_HIGH) + 2 * tmp->magic)
1261 {
1149 if(op->type == PLAYER) 1262 if (op->type == PLAYER)
1150 /* Make this more visible */ 1263 /* Make this more visible */
1151 new_draw_info_format(NDI_UNIQUE|NDI_RED,0, op, 1264 new_draw_info_format (NDI_UNIQUE | NDI_RED, 0, op,
1152 "The %s's acid corrodes your %s!", 1265 "The %s's acid corrodes your %s!", query_name (hitter), query_name (tmp));
1153 query_name(hitter), query_name(tmp));
1154 flag = 1; 1266 flag = 1;
1155 tmp->magic--; 1267 tmp->magic--;
1156 if(op->type == PLAYER) 1268 if (op->type == PLAYER)
1157 esrv_send_item(op, tmp); 1269 esrv_send_item (op, tmp);
1270 }
1158 } 1271 }
1272 if (flag)
1273 fix_player (op); /* Something was corroded */
1159 } 1274 }
1160 if(flag)
1161 fix_player(op); /* Something was corroded */
1162 } 1275 }
1163 }
1164 break; 1276 break;
1165 case ATNR_DRAIN: 1277 case ATNR_DRAIN:
1166 { 1278 {
1167 /* rate is the proportion of exp drained. High rate means 1279 /* rate is the proportion of exp drained. High rate means
1168 * not much is drained, low rate means a lot is drained. 1280 * not much is drained, low rate means a lot is drained.
1169 */
1170 int rate;
1171
1172 if(op->resist[ATNR_DRAIN] >= 0)
1173 rate = 400 + op->resist[ATNR_DRAIN] * 3;
1174 else
1175 rate = 400 * 100 / (100 - op->resist[ATNR_DRAIN]);
1176
1177 if(op->stats.exp <= rate) {
1178 if(op->type == GOLEM)
1179 dam = 999; /* Its force is "sucked" away. 8) */
1180 else
1181 /* If we can't drain, lets try to do physical damage */
1182 dam = hit_player_attacktype(op, hitter, dam, ATNR_PHYSICAL, magic);
1183 } else {
1184 /* Randomly give the hitter some hp */
1185 if(hitter->stats.hp<hitter->stats.maxhp &&
1186 (op->level > hitter->level) &&
1187 random_roll(0, (op->level-hitter->level+2), hitter, PREFER_HIGH)>3)
1188 hitter->stats.hp++;
1189
1190 /* Can't do drains on battleground spaces.
1191 * Move the wiz check up here - before, the hitter wouldn't gain exp
1192 * exp, but the wiz would still lose exp! If drainee is a wiz,
1193 * nothing happens.
1194 * Try to credit the owner. We try to display player -> player drain
1195 * attacks, hence all the != PLAYER checks.
1196 */ 1281 */
1282 int rate;
1283
1284 if (op->resist[ATNR_DRAIN] >= 0)
1285 rate = 400 + op->resist[ATNR_DRAIN] * 3;
1286 else
1287 rate = 400 * 100 / (100 - op->resist[ATNR_DRAIN]);
1288
1289 if (op->stats.exp <= rate)
1290 {
1291 if (op->type == GOLEM)
1292 dam = 999; /* Its force is "sucked" away. 8) */
1293 else
1294 /* If we can't drain, lets try to do physical damage */
1295 dam = hit_player_attacktype (op, hitter, dam, ATNR_PHYSICAL, magic);
1296 }
1297 else
1298 {
1299 /* Randomly give the hitter some hp */
1300 if (hitter->stats.hp < hitter->stats.maxhp &&
1301 (op->level > hitter->level) && random_roll (0, (op->level - hitter->level + 2), hitter, PREFER_HIGH) > 3)
1302 hitter->stats.hp++;
1303
1304 /* Can't do drains on battleground spaces.
1305 * Move the wiz check up here - before, the hitter wouldn't gain exp
1306 * exp, but the wiz would still lose exp! If drainee is a wiz,
1307 * nothing happens.
1308 * Try to credit the owner. We try to display player -> player drain
1309 * attacks, hence all the != PLAYER checks.
1310 */
1197 if (!op_on_battleground(hitter, NULL, NULL) && !QUERY_FLAG(op,FLAG_WAS_WIZ)) { 1311 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1312 {
1198 object *owner = get_owner(hitter); 1313 object *owner = get_owner (hitter);
1199 1314
1200 if (owner && owner != hitter) { 1315 if (owner && owner != hitter)
1316 {
1201 if (op->type != PLAYER || owner->type != PLAYER) 1317 if (op->type != PLAYER || owner->type != PLAYER)
1202 change_exp(owner, op->stats.exp/(rate*2), 1318 change_exp (owner, op->stats.exp / (rate * 2),
1203 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *)0, SK_EXP_TOTAL); 1319 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, SK_EXP_TOTAL);
1320 }
1204 } else if (op->type != PLAYER || hitter->type != PLAYER) { 1321 else if (op->type != PLAYER || hitter->type != PLAYER)
1322 {
1205 change_exp(hitter, op->stats.exp/(rate*2), 1323 change_exp (hitter, op->stats.exp / (rate * 2),
1206 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char*)0, 0); 1324 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, 0);
1325 }
1326 change_exp (op, -op->stats.exp / rate, NULL, 0);
1207 } 1327 }
1208 change_exp(op,-op->stats.exp/rate, NULL, 0);
1209 }
1210 dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure 1328 dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure
1211 * drain attack, you won't know that you are actually sucking out EXP, 1329 * drain attack, you won't know that you are actually sucking out EXP,
1212 * as the messages will say you missed 1330 * as the messages will say you missed
1213 */ 1331 */
1332 }
1214 } 1333 }
1215 }
1216 break; 1334 break;
1217 case ATNR_TURN_UNDEAD: 1335 case ATNR_TURN_UNDEAD:
1218 { 1336 {
1219 if (QUERY_FLAG(op,FLAG_UNDEAD)) { 1337 if (QUERY_FLAG (op, FLAG_UNDEAD))
1220 object *owner = get_owner(hitter) == NULL ? hitter : get_owner(hitter); 1338 {
1339 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1221 object *god = find_god (determine_god (owner)); 1340 object *god = find_god (determine_god (owner));
1222 int div = 1; 1341 int div = 1;
1223 1342
1224 /* if undead are not an enemy of your god, you turn them 1343 /* if undead are not an enemy of your god, you turn them
1225 * at half strength */ 1344 * at half strength */
1226 if (! god || ! god->slaying ||
1227 strstr (god->slaying, undead_name) == NULL) 1345 if (!god || !god->slaying || strstr (god->slaying, undead_name) == NULL)
1228 div = 2; 1346 div = 2;
1229 /* Give a bonus if you resist turn undead */ 1347 /* Give a bonus if you resist turn undead */
1230 if (op->level * div < 1348 if (op->level * div < (turn_bonus[owner->stats.Wis] + owner->level + (op->resist[ATNR_TURN_UNDEAD] / 100)))
1231 (turn_bonus[owner->stats.Wis]+owner->level +
1232 (op->resist[ATNR_TURN_UNDEAD]/100)))
1233 scare_creature(op, owner); 1349 scare_creature (op, owner);
1234 } 1350 }
1235 else 1351 else
1236 dam = 0; /* don't damage non undead - should we damage 1352 dam = 0; /* don't damage non undead - should we damage
1237 undead? */ 1353 undead? */
1354 }
1238 } break; 1355 break;
1239 case ATNR_DEATH: 1356 case ATNR_DEATH:
1240 deathstrike_player(op, hitter, &dam); 1357 deathstrike_player (op, hitter, &dam);
1241 break; 1358 break;
1242 case ATNR_CHAOS: 1359 case ATNR_CHAOS:
1243 LOG(llevError, 1360 LOG (llevError, "%s was hit by %s with non-specific chaos.\n", query_name (op), query_name (hitter));
1244 "%s was hit by %s with non-specific chaos.\n",
1245 query_name(op),
1246 query_name(hitter));
1247 dam = 0; 1361 dam = 0;
1248 break; 1362 break;
1249 case ATNR_COUNTERSPELL: 1363 case ATNR_COUNTERSPELL:
1250 LOG(llevError, 1364 LOG (llevError, "%s was hit by %s with counterspell attack.\n", query_name (op), query_name (hitter));
1251 "%s was hit by %s with counterspell attack.\n",
1252 query_name(op),
1253 query_name(hitter));
1254 dam = 0; 1365 dam = 0;
1255 /* This should never happen. Counterspell is handled 1366 /* This should never happen. Counterspell is handled
1256 * seperately and filtered out. If this does happen, 1367 * seperately and filtered out. If this does happen,
1257 * Counterspell has no effect on anything but spells, so it 1368 * Counterspell has no effect on anything but spells, so it
1258 * does no damage. */ 1369 * does no damage. */
1259 break; 1370 break;
1260 case ATNR_HOLYWORD: 1371 case ATNR_HOLYWORD:
1261 { 1372 {
1262 /* This has already been handled by hit_player, 1373 /* This has already been handled by hit_player,
1263 * no need to check twice -- DAMN */ 1374 * no need to check twice -- DAMN */
1264 1375 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1265 object *owner = get_owner(hitter)==NULL?hitter:get_owner(hitter); 1376
1266
1267 /* As with turn undead above, give a bonus on the saving throw */ 1377 /* As with turn undead above, give a bonus on the saving throw */
1268 if((op->level+(op->resist[ATNR_HOLYWORD]/100)) < 1378 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1269 owner->level+turn_bonus[owner->stats.Wis])
1270 scare_creature(op, owner); 1379 scare_creature (op, owner);
1380 }
1271 } break; 1381 break;
1272 case ATNR_LIFE_STEALING: 1382 case ATNR_LIFE_STEALING:
1273 { 1383 {
1274 int new_hp; 1384 int new_hp;
1385
1275 /* this is replacement to drain for players, instead of taking 1386 /* this is replacement to drain for players, instead of taking
1276 * exp it takes hp. It is geared for players, probably not 1387 * exp it takes hp. It is geared for players, probably not
1277 * much use giving it to monsters 1388 * much use giving it to monsters
1278 * 1389 *
1279 * life stealing doesn't do a lot of damage, but it gives the 1390 * life stealing doesn't do a lot of damage, but it gives the
1280 * damage it does do to the player. Given that, 1391 * damage it does do to the player. Given that,
1281 * it only does 1/10'th normal damage (hence the divide by 1392 * it only does 1/10'th normal damage (hence the divide by
1282 * 1000). 1393 * 1000).
1283 */ 1394 */
1284 /* You can't steal life from something undead */ 1395 /* You can't steal life from something undead */
1285 if ((op->type == GOLEM) || (QUERY_FLAG(op, FLAG_UNDEAD))) return 0; 1396 if ((op->type == GOLEM) || (QUERY_FLAG (op, FLAG_UNDEAD)))
1397 return 0;
1286 /* If drain protection is higher than life stealing, use that */ 1398 /* If drain protection is higher than life stealing, use that */
1287 if (op->resist[ATNR_DRAIN] >= op->resist[ATNR_LIFE_STEALING]) 1399 if (op->resist[ATNR_DRAIN] >= op->resist[ATNR_LIFE_STEALING])
1288 dam = (dam*(100 - op->resist[ATNR_DRAIN])) / 3000; 1400 dam = (dam * (100 - op->resist[ATNR_DRAIN])) / 3000;
1401 else
1289 else dam = (dam*(100 - op->resist[ATNR_LIFE_STEALING])) / 3000; 1402 dam = (dam * (100 - op->resist[ATNR_LIFE_STEALING])) / 3000;
1290 /* You die at -1 hp, not zero. */ 1403 /* You die at -1 hp, not zero. */
1291 if (dam > (op->stats.hp+1)) dam = op->stats.hp+1; 1404 if (dam > (op->stats.hp + 1))
1405 dam = op->stats.hp + 1;
1292 new_hp = hitter->stats.hp + dam; 1406 new_hp = hitter->stats.hp + dam;
1293 if (new_hp > hitter->stats.maxhp) new_hp = hitter->stats.maxhp; 1407 if (new_hp > hitter->stats.maxhp)
1294 if (new_hp > hitter->stats.hp) hitter->stats.hp = new_hp; 1408 new_hp = hitter->stats.maxhp;
1409 if (new_hp > hitter->stats.hp)
1410 hitter->stats.hp = new_hp;
1411 }
1295 } 1412 }
1296 }
1297 return dam; 1413 return dam;
1298} 1414}
1299 1415
1300 1416
1301/* GROS: This code comes from hit_player. It has been made external to 1417/* GROS: This code comes from hit_player. It has been made external to
1302 * allow script procedures to "kill" objects in a combat-like fashion. 1418 * allow script procedures to "kill" objects in a combat-like fashion.
1311 * This function was a bit of a mess with hitter getting changed, 1427 * This function was a bit of a mess with hitter getting changed,
1312 * values being stored away but not used, etc. I've cleaned it up 1428 * values being stored away but not used, etc. I've cleaned it up
1313 * a bit - I think it should be functionally equivalant. 1429 * a bit - I think it should be functionally equivalant.
1314 * MSW 2002-07-17 1430 * MSW 2002-07-17
1315 */ 1431 */
1432int
1316int kill_object(object *op,int dam, object *hitter, int type) 1433kill_object (object *op, int dam, object *hitter, int type)
1317{ 1434{
1318 char buf[MAX_BUF]; 1435 char buf[MAX_BUF];
1319 const char *skill; 1436 const char *skill;
1320 int maxdam=0; 1437 int maxdam = 0;
1321 int battleg=0; /* true if op standing on battleground */ 1438 int battleg = 0; /* true if op standing on battleground */
1322 int pk=0; /* true if op and what controls hitter are both players*/ 1439 int pk = 0; /* true if op and what controls hitter are both players */
1323 object *owner=NULL; 1440 object *owner = NULL;
1324 object *skop=NULL; 1441 object *skop = NULL;
1325 1442
1326 if (op->stats.hp>=0) 1443 if (op->stats.hp >= 0)
1327 return -1; 1444 return -1;
1328 1445
1329 if (INVOKE_OBJECT (KILL, op, ARG_OBJECT (hitter))) 1446 if (INVOKE_OBJECT (KILL, op, ARG_OBJECT (hitter)))
1330 return 0; 1447 return 0;
1331 1448
1332 /* maxdam needs to be the amount of damage it took to kill 1449 /* maxdam needs to be the amount of damage it took to kill
1333 * this creature. The function(s) that call us have already 1450 * this creature. The function(s) that call us have already
1334 * adjusted the creatures HP total, so that is negative. 1451 * adjusted the creatures HP total, so that is negative.
1335 */ 1452 */
1336 maxdam = dam + op->stats.hp + 1; 1453 maxdam = dam + op->stats.hp + 1;
1337 1454
1338 if(QUERY_FLAG(op,FLAG_BLOCKSVIEW)) 1455 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW))
1339 update_all_los(op->map,op->x, op->y); /* makes sure los will be recalculated */ 1456 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */
1340 1457
1341 if(op->type==DOOR) { 1458 if (op->type == DOOR)
1459 {
1342 op->speed = 0.1; 1460 op->speed = 0.1;
1343 update_ob_speed(op); 1461 update_ob_speed (op);
1344 op->speed_left= -0.05; 1462 op->speed_left = -0.05;
1345 return maxdam; 1463 return maxdam;
1346 } 1464 }
1347 if(QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) { 1465 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1466 {
1348 remove_friendly_object(op); 1467 remove_friendly_object (op);
1349 if (get_owner (op) != NULL && op->owner->type == PLAYER && 1468 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1350 op->owner->contr->ranges[range_golem] == op) { 1469 {
1351 op->owner->contr->ranges[range_golem]=NULL; 1470 op->owner->contr->ranges[range_golem] = NULL;
1352 op->owner->contr->golem_count=0; 1471 op->owner->contr->golem_count = 0;
1353 } 1472 }
1354 1473
1355 remove_ob(op); 1474 remove_ob (op);
1356 free_object(op); 1475 free_object (op);
1357 return maxdam; 1476 return maxdam;
1358 } 1477 }
1359 1478
1360 /* Now lets start dealing with experience we get for killing something */ 1479 /* Now lets start dealing with experience we get for killing something */
1361 1480
1362 owner=get_owner(hitter); 1481 owner = get_owner (hitter);
1363 if(owner==NULL) 1482 if (owner == NULL)
1364 owner=hitter; 1483 owner = hitter;
1365 1484
1366 /* is the victim (op) standing on battleground? */ 1485 /* is the victim (op) standing on battleground? */
1367 if (op_on_battleground(op, NULL, NULL)) battleg=1; 1486 if (op_on_battleground (op, NULL, NULL))
1368 1487 battleg = 1;
1488
1369 /* is this player killing?*/ 1489 /* is this player killing? */
1370 if (op->type == PLAYER && owner->type == PLAYER) pk=1; 1490 if (op->type == PLAYER && owner->type == PLAYER)
1491 pk = 1;
1371 1492
1372 /* Player killed something */ 1493 /* Player killed something */
1373 if(owner->type==PLAYER) { 1494 if (owner->type == PLAYER)
1495 {
1374 Log_Kill(owner->name, 1496 Log_Kill (owner->name,
1375 query_name(op),op->type, 1497 query_name (op), op->type, (owner != hitter) ? query_name (hitter) : NULL, (owner != hitter) ? hitter->type : 0);
1376 (owner!=hitter) ? query_name(hitter) : NULL,
1377 (owner!=hitter) ? hitter->type : 0);
1378 1498
1379 /* Log players killing other players - makes it easier to detect 1499 /* Log players killing other players - makes it easier to detect
1380 * and filter out malicious player killers - that is why the 1500 * and filter out malicious player killers - that is why the
1381 * ip address is included. 1501 * ip address is included.
1382 */ 1502 */
1383 if (op->type == PLAYER && !battleg) { 1503 if (op->type == PLAYER && !battleg)
1504 {
1384 time_t t=time(NULL); 1505 time_t t = time (NULL);
1385 struct tm *tmv; 1506 struct tm *tmv;
1386 char buf[256]; 1507 char buf[256];
1387 1508
1388 tmv = localtime(&t); 1509 tmv = localtime (&t);
1389 strftime(buf, 256,"%a %b %d %H:%M:%S %Y", tmv); 1510 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv);
1390 1511
1391 LOG(llevInfo,"%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", 1512 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->socket.host, query_name (op));
1392 buf, &owner->name, owner->contr->socket.host, query_name(op));
1393 } 1513 }
1394 1514
1395 /* try to filter some things out - basically, if you are 1515 /* try to filter some things out - basically, if you are
1396 * killing a level 1 creature and your level 20, you 1516 * killing a level 1 creature and your level 20, you
1397 * probably don't want to see that. 1517 * probably don't want to see that.
1398 */ 1518 */
1399 if ( owner->level < op->level * 2|| op->stats.exp>1000) { 1519 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1520 {
1400 if(owner!=hitter) { 1521 if (owner != hitter)
1401 new_draw_info_format(NDI_BLACK, 0, owner, 1522 {
1402 "You killed %s with %s.",query_name(op), 1523 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1403 query_name(hitter));
1404 } 1524 }
1405 else { 1525 else
1406 new_draw_info_format(NDI_BLACK, 0, owner, 1526 {
1407 "You killed %s.",query_name(op)); 1527 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1408 } 1528 }
1409 /* Only play sounds for melee kills */ 1529 /* Only play sounds for melee kills */
1410 if (hitter->type == PLAYER) 1530 if (hitter->type == PLAYER)
1411 play_sound_map(owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1531 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1412 } 1532 }
1413 1533
1414 /* If a player kills another player, not on 1534 /* If a player kills another player, not on
1415 * battleground, the "killer" looses 1 luck. Since this is 1535 * battleground, the "killer" looses 1 luck. Since this is
1416 * not reversible, it's actually quite a pain IMHO. -AV 1536 * not reversible, it's actually quite a pain IMHO. -AV
1417 * Fix bug in that we were changing the luck of the hitter, not 1537 * Fix bug in that we were changing the luck of the hitter, not
1418 * player that the object belonged to - so if you killed another player 1538 * player that the object belonged to - so if you killed another player
1419 * with spells, pets, whatever, there was no penalty. 1539 * with spells, pets, whatever, there was no penalty.
1420 * Changed to make luck penalty configurable in settings. 1540 * Changed to make luck penalty configurable in settings.
1421 */ 1541 */
1422 if(op->type == PLAYER && owner != op && !battleg) 1542 if (op->type == PLAYER && owner != op && !battleg)
1423 change_luck(owner, -settings.pk_luck_penalty); 1543 change_luck (owner, -settings.pk_luck_penalty);
1424 1544
1425 /* This code below deals with finding the appropriate skill 1545 /* This code below deals with finding the appropriate skill
1426 * to credit exp to. This is a bit problematic - we should 1546 * to credit exp to. This is a bit problematic - we should
1427 * probably never really have to look at current_weapon->skill 1547 * probably never really have to look at current_weapon->skill
1428 */ 1548 */
1429 skill = NULL; 1549 skill = NULL;
1430 if (hitter->skill && hitter->type!=PLAYER) skill = hitter->skill; 1550 if (hitter->skill && hitter->type != PLAYER)
1551 skill = hitter->skill;
1431 else if (owner->chosen_skill) { 1552 else if (owner->chosen_skill)
1553 {
1432 skill = owner->chosen_skill->skill; 1554 skill = owner->chosen_skill->skill;
1433 skop = owner->chosen_skill; 1555 skop = owner->chosen_skill;
1434 } 1556 }
1435 else if (QUERY_FLAG(owner, FLAG_READY_WEAPON)) skill=owner->current_weapon->skill; 1557 else if (QUERY_FLAG (owner, FLAG_READY_WEAPON))
1558 skill = owner->current_weapon->skill;
1436 else 1559 else
1437 LOG(llevError,"kill_object - unable to find skill that killed monster\n"); 1560 LOG (llevError, "kill_object - unable to find skill that killed monster\n");
1438 1561
1439 /* We have the skill we want to credit to - now find the object this goes 1562 /* We have the skill we want to credit to - now find the object this goes
1440 * to. Make sure skop is an actual skill, and not a skill tool! 1563 * to. Make sure skop is an actual skill, and not a skill tool!
1441 */ 1564 */
1442 if ((!skop || skop->type != SKILL) && skill) { 1565 if ((!skop || skop->type != SKILL) && skill)
1566 {
1443 int i; 1567 int i;
1444 1568
1445 for (i=0; i<NUM_SKILLS; i++) 1569 for (i = 0; i < NUM_SKILLS; i++)
1446 if (owner->contr->last_skill_ob[i] && 1570 if (owner->contr->last_skill_ob[i] && !strcmp (owner->contr->last_skill_ob[i]->skill, skill))
1447 !strcmp(owner->contr->last_skill_ob[i]->skill, skill)) { 1571 {
1448 skop = owner->contr->last_skill_ob[i]; 1572 skop = owner->contr->last_skill_ob[i];
1449 break; 1573 break;
1450 } 1574 }
1451 } 1575 }
1452 } /* Was it a player that hit somethign */ 1576 } /* Was it a player that hit somethign */
1453 else { 1577 else
1578 {
1454 skill = NULL; 1579 skill = NULL;
1455 } 1580 }
1456 1581
1457 /* Pet (or spell) killed something. */ 1582 /* Pet (or spell) killed something. */
1458 if(owner != hitter ) { 1583 if (owner != hitter)
1584 {
1459 (void) sprintf(buf,"%s killed %s with %s%s%s.",&owner->name, 1585 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1460 query_name(op),query_name(hitter), battleg? " (duel)":"", pk? " (pk)":""); 1586 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1587 }
1588 else
1461 } 1589 {
1462 else {
1463 (void) sprintf(buf,"%s killed %s%s%s%s.",&hitter->name,&op->name, 1590 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1464 (QUERY_FLAG(hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1591 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1465 " in hand to hand combat":"", battleg? " (duel)":"", pk? " (pk)":""); 1592 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1466 } 1593 }
1467 /* These may have been set in the player code section above */ 1594 /* These may have been set in the player code section above */
1595 if (!skop)
1468 if (!skop) skop = hitter->chosen_skill; 1596 skop = hitter->chosen_skill;
1469 if (!skill && skop) skill=skop->skill; 1597 if (!skill && skop)
1598 skill = skop->skill;
1470 1599
1471 new_draw_info(NDI_ALL, op->type==PLAYER?1:10, NULL, buf); 1600 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1472 1601
1473 1602
1474 /* If you didn't kill yourself, and your not the wizard */ 1603 /* If you didn't kill yourself, and your not the wizard */
1475 if(owner!=op && !QUERY_FLAG(op, FLAG_WAS_WIZ)) { 1604 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1605 {
1476 int exp; 1606 int exp;
1477 1607
1478 /* Really don't give much experience for killing other players */ 1608 /* Really don't give much experience for killing other players */
1479 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1609 // schmorp: temporary? reduce the amount of exp gained for pking enourmously
1480 if (op->type==PLAYER) { 1610 if (op->type == PLAYER)
1611 {
1481 if (battleg) { 1612 if (battleg)
1613 {
1482 new_draw_info(NDI_UNIQUE, 0,owner, "Your foe has fallen!"); 1614 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1483 new_draw_info(NDI_UNIQUE, 0,owner, "VICTORY!!!"); 1615 new_draw_info (NDI_UNIQUE, 0, owner, "VICTORY!!!");
1484 } 1616 }
1485 else 1617 else
1486 exp = op->stats.exp / 1000; 1618 exp = op->stats.exp / 1000;
1487 } 1619 }
1488 else 1620 else
1489 exp = calc_skill_exp(owner, op, skop); 1621 exp = calc_skill_exp (owner, op, skop);
1490 1622
1491 /* if op is standing on "battleground" (arena), no way to gain 1623 /* if op is standing on "battleground" (arena), no way to gain
1492 * exp by killing him 1624 * exp by killing him
1493 */ 1625 */
1494 if (battleg) exp = 0; 1626 if (battleg)
1627 exp = 0;
1495 1628
1496 /* Don't know why this is set this way - doesn't make 1629 /* Don't know why this is set this way - doesn't make
1497 * sense to just divide everything by two for no reason. 1630 * sense to just divide everything by two for no reason.
1498 */ 1631 */
1499 1632
1500 if (!settings.simple_exp) 1633 if (!settings.simple_exp)
1501 exp=exp/2; 1634 exp = exp / 2;
1502 1635
1503 if(owner->type!=PLAYER || owner->contr->party==NULL) { 1636 if (owner->type != PLAYER || owner->contr->party == NULL)
1637 {
1504 change_exp(owner,exp, skill, 0); 1638 change_exp (owner, exp, skill, 0);
1639 }
1640 else
1505 } 1641 {
1506 else {
1507 int shares=0,count=0; 1642 int shares = 0, count = 0;
1508 1643
1509 player *pl; 1644 player *pl;
1510 1645
1511 partylist *party=owner->contr->party; 1646 partylist *party = owner->contr->party;
1647
1512#ifdef PARTY_KILL_LOG 1648#ifdef PARTY_KILL_LOG
1513 add_kill_to_party(party, query_name(owner), query_name(op), exp); 1649 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1514#endif 1650#endif
1515 for(pl=first_player;pl!=NULL;pl=pl->next) { 1651 for (pl = first_player; pl != NULL; pl = pl->next)
1652 {
1516 if(party && pl->ob->contr->party==party && on_same_map(pl->ob, owner)) { 1653 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1654 {
1517 count++; 1655 count++;
1518 shares+=(pl->ob->level+4); 1656 shares += (pl->ob->level + 4);
1519 } 1657 }
1520 } 1658 }
1521 if(count==1 || shares>exp) 1659 if (count == 1 || shares > exp)
1522 change_exp(owner,exp, skill, SK_EXP_TOTAL); 1660 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1523 else { 1661 else
1662 {
1524 int share=exp/shares,given=0,nexp; 1663 int share = exp / shares, given = 0, nexp;
1664
1525 for(pl=first_player;pl!=NULL;pl=pl->next) { 1665 for (pl = first_player; pl != NULL; pl = pl->next)
1666 {
1526 if(party && pl->ob->contr->party==party && on_same_map(pl->ob, owner)) { 1667 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1668 {
1527 nexp=(pl->ob->level+4)*share; 1669 nexp = (pl->ob->level + 4) * share;
1528 change_exp(pl->ob,nexp, skill, SK_EXP_TOTAL); 1670 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1529 given+=nexp; 1671 given += nexp;
1530 } 1672 }
1531 } 1673 }
1532 exp-=given; 1674 exp -= given;
1533 /* give any remainder to the player */ 1675 /* give any remainder to the player */
1534 change_exp(owner,exp, skill, SK_EXP_ADD_SKILL); 1676 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1535 } 1677 }
1536 } /* else part of a party */ 1678 } /* else part of a party */
1537 1679
1538 } /* end if person didn't kill himself */ 1680 } /* end if person didn't kill himself */
1539 1681
1540 if(op->type!=PLAYER) { 1682 if (op->type != PLAYER)
1683 {
1541 if(QUERY_FLAG(op,FLAG_FRIENDLY)) { 1684 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1685 {
1542 object *owner1 = get_owner(op); 1686 object *owner1 = get_owner (op);
1543 1687
1544 if(owner1!= NULL && owner1->type == PLAYER) { 1688 if (owner1 != NULL && owner1->type == PLAYER)
1689 {
1545 play_sound_player_only(owner1->contr, SOUND_PET_IS_KILLED,0,0); 1690 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1546 /* Maybe we should include the owner that killed this, maybe not */ 1691 /* Maybe we should include the owner that killed this, maybe not */
1547 new_draw_info_format(NDI_UNIQUE, 0,owner1,"Your pet, the %s, is killed by %s.", 1692 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1548 &op->name,&hitter->name);
1549 } 1693 }
1694
1550 remove_friendly_object(op); 1695 remove_friendly_object (op);
1551 } 1696 }
1697
1552 remove_ob(op); 1698 remove_ob (op);
1553 free_object(op); 1699 free_object (op);
1554 } 1700 }
1555 /* Player has been killed! */ 1701 /* Player has been killed! */
1556 else { 1702 else
1703 {
1557 if(owner->type==PLAYER) { 1704 if (owner->type == PLAYER)
1705 {
1558 snprintf(op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1706 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title);
1559 } 1707 }
1560 else { 1708 else
1561 strncpy(op->contr->killer,hitter->name,BIG_NAME); 1709 assign (op->contr->killer, hitter->name);
1562 op->contr->killer[BIG_NAME-1]='\0';
1563 }
1564 } 1710 }
1711
1565 /* This was return -1 - that doesn't seem correct - if we return -1, process 1712 /* This was return -1 - that doesn't seem correct - if we return -1, process
1566 * continues in the calling function. 1713 * continues in the calling function.
1567 */ 1714 */
1568 return maxdam; 1715 return maxdam;
1569} 1716}
1570 1717
1571/* Find out if this is friendly fire (PVP and attacker is peaceful) or not 1718/* Find out if this is friendly fire (PVP and attacker is peaceful) or not
1572 * Returns 0 this is not friendly fire 1719 * Returns 0 this is not friendly fire
1573 */ 1720 */
1574 1721
1722int
1575int friendly_fire(object *op, object *hitter){ 1723friendly_fire (object *op, object *hitter)
1724{
1576 object *owner; 1725 object *owner;
1577 int friendlyfire; 1726 int friendlyfire;
1578
1579 if (hitter->head) hitter=hitter->head;
1580 1727
1728 if (hitter->head)
1729 hitter = hitter->head;
1730
1581 friendlyfire = 0; 1731 friendlyfire = 0;
1582 1732
1583 if(op->type == PLAYER) { 1733 if (op->type == PLAYER)
1734 {
1584 if (op_on_battleground (hitter, 0, 0)) 1735 if (op_on_battleground (hitter, 0, 0))
1585 return 0; 1736 return 0;
1586 1737
1587 if(hitter->type == PLAYER && hitter->contr->peaceful == 1) 1738 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1588 return 1; 1739 return 1;
1589 1740
1590 if((owner = get_owner(hitter))!=NULL) { 1741 if ((owner = get_owner (hitter)) != NULL)
1742 {
1591 if(owner->type == PLAYER && owner->contr->peaceful == 1) 1743 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1592 friendlyfire = 2; 1744 friendlyfire = 2;
1593 } 1745 }
1594 1746
1595 if (hitter->type == SPELL || hitter->type == POISONING || 1747 if (hitter->type == SPELL || hitter->type == POISONING || hitter->type == DISEASE || hitter->type == RUNE)
1596 hitter->type == DISEASE || hitter->type == RUNE)
1597 friendlyfire = 0; 1748 friendlyfire = 0;
1598 } 1749 }
1599 return friendlyfire; 1750 return friendlyfire;
1600} 1751}
1601 1752
1602 1753
1603/* This isn't used just for players, but in fact most objects. 1754/* This isn't used just for players, but in fact most objects.
1604 * op is the object to be hit, dam is the amount of damage, hitter 1755 * op is the object to be hit, dam is the amount of damage, hitter
1609 */ 1760 */
1610 1761
1611 /* Oct 95 - altered the following slightly for MULTIPLE_GODS hack 1762 /* Oct 95 - altered the following slightly for MULTIPLE_GODS hack
1612 * which needs new attacktype AT_HOLYWORD to work . b.t. */ 1763 * which needs new attacktype AT_HOLYWORD to work . b.t. */
1613 1764
1765int
1614int hit_player(object *op,int dam, object *hitter, int type, int full_hit) { 1766hit_player (object *op, int dam, object *hitter, int type, int full_hit)
1767{
1615 int maxdam=0, ndam=0, attacktype=1, magic=(type & AT_MAGIC); 1768 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1616 int maxattacktype, attacknum; 1769 int maxattacktype, attacknum;
1617 int body_attack = op && op->head; /* Did we hit op's head? */ 1770 int body_attack = op && op->head; /* Did we hit op's head? */
1618 int simple_attack; 1771 int simple_attack;
1619 tag_t op_tag, hitter_tag; 1772 tag_t op_tag, hitter_tag;
1620 int rtn_kill = 0; 1773 int rtn_kill = 0;
1621 int friendlyfire; 1774 int friendlyfire;
1622 1775
1623 if (get_attack_mode (&op, &hitter, &simple_attack)) 1776 if (get_attack_mode (&op, &hitter, &simple_attack))
1624 return 0; 1777 return 0;
1625 1778
1626 /* very simple: if our target has no_damage 1 set or is wiz, we can't hurt him */ 1779 /* very simple: if our target has no_damage 1 set or is wiz, we can't hurt him */
1627 if (QUERY_FLAG (op, FLAG_WIZ) || QUERY_FLAG (op, FLAG_NO_DAMAGE)) 1780 if (QUERY_FLAG (op, FLAG_WIZ) || QUERY_FLAG (op, FLAG_NO_DAMAGE))
1628 return 0; 1781 return 0;
1629 1782
1630#ifdef PROHIBIT_PLAYERKILL 1783#ifdef PROHIBIT_PLAYERKILL
1631 if (op->type == PLAYER) { 1784 if (op->type == PLAYER)
1785 {
1632 object *owner = get_owner (hitter); 1786 object *owner = get_owner (hitter);
1787
1788 if (!owner)
1633 if (!owner) owner = hitter; 1789 owner = hitter;
1634 if (owner->type == PLAYER
1635 && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) 1790 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1636 && op != owner) { 1791 {
1792 return 0;
1793 }
1794 }
1795#endif
1796
1797 op_tag = op->count;
1798 hitter_tag = hitter->count;
1799
1800 if (body_attack)
1801 {
1802 /* slow and paralyze must hit the head. But we don't want to just
1803 * return - we still need to process other attacks the spell still
1804 * might have. So just remove the paralyze and slow attacktypes,
1805 * and keep on processing if we have other attacktypes.
1806 * return if only magic or nothing is left - under normal code
1807 * we don't attack with pure magic if there is another attacktype.
1808 * Only do processing if the initial attacktype includes one of those
1809 * attack so we don't cancel out things like magic bullet.
1810 */
1811 if (type & (AT_PARALYZE | AT_SLOW))
1812 {
1813 type &= ~(AT_PARALYZE | AT_SLOW);
1814 if (!type || type == AT_MAGIC)
1815 return 0;
1816 }
1817 }
1818
1819 if (!simple_attack && op->type == DOOR)
1820 {
1821 object *tmp;
1822
1823 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1824 if (tmp->type == RUNE || tmp->type == TRAP)
1825 {
1826 spring_trap (tmp, hitter);
1827 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack))
1637 return 0; 1828 return 0;
1829 break;
1638 } 1830 }
1831 }
1832
1833 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1639 } 1834 {
1835 /* FIXME: If a player is killed by a rune in a door, the
1836 * was_destroyed() check above doesn't return, and might get here.
1837 */
1838 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1839 return 0;
1840 }
1841
1842#ifdef ATTACK_DEBUG
1843 LOG (llevDebug, "hit player: attacktype %d, dam %d\n", type, dam);
1640#endif 1844#endif
1641 1845
1642 op_tag = op->count;
1643 hitter_tag = hitter->count;
1644
1645 if (body_attack) {
1646 /* slow and paralyze must hit the head. But we don't want to just
1647 * return - we still need to process other attacks the spell still
1648 * might have. So just remove the paralyze and slow attacktypes,
1649 * and keep on processing if we have other attacktypes.
1650 * return if only magic or nothing is left - under normal code
1651 * we don't attack with pure magic if there is another attacktype.
1652 * Only do processing if the initial attacktype includes one of those
1653 * attack so we don't cancel out things like magic bullet.
1654 */
1655 if (type & (AT_PARALYZE | AT_SLOW)) {
1656 type &= ~(AT_PARALYZE | AT_SLOW);
1657 if (!type || type==AT_MAGIC) return 0;
1658 }
1659 }
1660
1661 if ( ! simple_attack && op->type == DOOR) {
1662 object *tmp;
1663 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1664 if (tmp->type == RUNE || tmp->type == TRAP) {
1665 spring_trap (tmp, hitter);
1666 if (was_destroyed (hitter, hitter_tag)
1667 || was_destroyed (op, op_tag)
1668 || abort_attack (op, hitter, simple_attack))
1669 return 0;
1670 break;
1671 }
1672 }
1673
1674 if ( ! QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) {
1675 /* FIXME: If a player is killed by a rune in a door, the
1676 * was_destroyed() check above doesn't return, and might get here.
1677 */
1678 LOG (llevDebug, "victim (arch %s, name %s) already dead in "
1679 "hit_player()\n", &op->arch->name, &op->name);
1680 return 0;
1681 }
1682
1683#ifdef ATTACK_DEBUG
1684 LOG(llevDebug,"hit player: attacktype %d, dam %d\n", type, dam);
1685#endif
1686
1687 if (magic) { 1846 if (magic)
1847 {
1688 /* basically: dam = dam*(100-op->resist[attacknum])/100; 1848 /* basically: dam = dam*(100-op->resist[attacknum])/100;
1689 * in case 0>dam>1, we try to "simulate" a float value-effect */ 1849 * in case 0>dam>1, we try to "simulate" a float value-effect */
1690 dam = dam*(100-op->resist[ATNR_MAGIC]); 1850 dam = dam * (100 - op->resist[ATNR_MAGIC]);
1691 if (dam >= 100) 1851 if (dam >= 100)
1692 dam /= 100; 1852 dam /= 100;
1693 else 1853 else
1694 dam = (dam > (rndm(0, 99))) ? 1 : 0; 1854 dam = (dam > (rndm (0, 99))) ? 1 : 0;
1695 } 1855 }
1696 1856
1697 /* AT_CHAOS here is a weapon or monster. Spells are handled by hit_map 1857 /* AT_CHAOS here is a weapon or monster. Spells are handled by hit_map
1698 * If the attacktype still has chaos, shuffle it, then clear the Chaos bit 1858 * If the attacktype still has chaos, shuffle it, then clear the Chaos bit
1699 */ 1859 */
1700 if(type & AT_CHAOS){ 1860 if (type & AT_CHAOS)
1861 {
1701 shuffle_attack(op,0); /*0 flag tells it to not change the face */ 1862 shuffle_attack (op, 0); /*0 flag tells it to not change the face */
1702 update_object(op,UP_OBJ_FACE); 1863 update_object (op, UP_OBJ_FACE);
1703 type &= ~AT_CHAOS; 1864 type &= ~AT_CHAOS;
1704 } 1865 }
1705 1866
1706 /* Holyword is really an attacktype modifier (like magic is). If 1867 /* Holyword is really an attacktype modifier (like magic is). If
1707 * holyword is part of an attacktype, then make sure the creature is 1868 * holyword is part of an attacktype, then make sure the creature is
1708 * a proper match, otherwise no damage. 1869 * a proper match, otherwise no damage.
1709 */ 1870 */
1710 if (type & AT_HOLYWORD) { 1871 if (type & AT_HOLYWORD)
1872 {
1711 object *god; 1873 object *god;
1874
1712 if ((!hitter->slaying || 1875 if ((!hitter->slaying ||
1713 (!(op->race && strstr(hitter->slaying,op->race)) && 1876 (!(op->race && strstr (hitter->slaying, op->race)) &&
1714 !(op->name && strstr(hitter->slaying,op->name)))) && 1877 !(op->name && strstr (hitter->slaying, op->name)))) &&
1715 (!QUERY_FLAG(op,FLAG_UNDEAD) || 1878 (!QUERY_FLAG (op, FLAG_UNDEAD) ||
1716 (hitter->title != NULL 1879 (hitter->title != NULL
1717 && (god = find_god(determine_god(hitter))) != NULL 1880 && (god = find_god (determine_god (hitter))) != NULL && god->race != NULL && strstr (god->race, undead_name) != NULL)))
1718 && god->race != NULL
1719 && strstr(god->race,undead_name) != NULL)))
1720 return 0; 1881 return 0;
1721 } 1882 }
1722 1883
1723 maxattacktype = type; /* initialize this to something */ 1884 maxattacktype = type; /* initialize this to something */
1724 for (attacknum=0; attacknum<NROFATTACKS; attacknum++, attacktype=1<<attacknum) { 1885 for (attacknum = 0; attacknum < NROFATTACKS; attacknum++, attacktype = 1 << attacknum)
1886 {
1725 /* Magic isn't really a true attack type - it gets combined with other 1887 /* Magic isn't really a true attack type - it gets combined with other
1726 * attack types. As such, skip it over. However, if magic is 1888 * attack types. As such, skip it over. However, if magic is
1727 * the only attacktype in the group, then still attack with it 1889 * the only attacktype in the group, then still attack with it
1728 */ 1890 */
1729 if ((attacktype==AT_MAGIC) && (type & ~AT_MAGIC)) continue; 1891 if ((attacktype == AT_MAGIC) && (type & ~AT_MAGIC))
1892 continue;
1730 1893
1731 /* Go through and hit the player with each attacktype, one by one. 1894 /* Go through and hit the player with each attacktype, one by one.
1732 * hit_player_attacktype only figures out the damage, doesn't inflict 1895 * hit_player_attacktype only figures out the damage, doesn't inflict
1733 * it. It will do the appropriate action for attacktypes with 1896 * it. It will do the appropriate action for attacktypes with
1734 * effects (slow, paralization, etc. 1897 * effects (slow, paralization, etc.
1735 */ 1898 */
1736 if (type & attacktype) { 1899 if (type & attacktype)
1900 {
1737 ndam=hit_player_attacktype(op,hitter,dam,attacknum,magic); 1901 ndam = hit_player_attacktype (op, hitter, dam, attacknum, magic);
1738 /* the >= causes us to prefer messages from special attacks, if 1902 /* the >= causes us to prefer messages from special attacks, if
1739 * the damage is equal. 1903 * the damage is equal.
1740 */ 1904 */
1741 if (ndam >= maxdam) { 1905 if (ndam >= maxdam)
1906 {
1742 maxdam = ndam; 1907 maxdam = ndam;
1743 maxattacktype = 1<<attacknum; 1908 maxattacktype = 1 << attacknum;
1744 } 1909 }
1745 } 1910 }
1746 } 1911 }
1747 1912
1748 /* if this is friendly fire then do a set % of damage only 1913 /* if this is friendly fire then do a set % of damage only
1749 * Note - put a check in to make sure this attack is actually 1914 * Note - put a check in to make sure this attack is actually
1750 * doing damage - otherwise, the +1 in the code below will make 1915 * doing damage - otherwise, the +1 in the code below will make
1751 * an attack do damage before when it otherwise didn't 1916 * an attack do damage before when it otherwise didn't
1752 */ 1917 */
1753 friendlyfire = friendly_fire(op, hitter); 1918 friendlyfire = friendly_fire (op, hitter);
1754 if (friendlyfire && maxdam){ 1919 if (friendlyfire && maxdam)
1920 {
1755 maxdam = ((dam * settings.set_friendly_fire) / 100); 1921 maxdam = ((dam * settings.set_friendly_fire) / 100);
1756#ifndef COZY_SERVER 1922#ifndef COZY_SERVER
1923 maxdam++;
1924#endif
1925
1926#ifdef ATTACK_DEBUG
1927 LOG (llevDebug, "Friendly fire (type:%d setting: %d%) did %d damage dropped to %d\n",
1928 friendlyfire, settings.set_friendly_fire, dam, maxdam);
1929#endif
1930 }
1931
1932 if (!full_hit)
1933 {
1934 archetype *at;
1935 int area;
1936 int remainder;
1937
1938 area = 0;
1939 for (at = op->arch; at != NULL; at = at->more)
1940 area++;
1941 assert (area > 0);
1942
1943 /* basically: maxdam /= area; we try to "simulate" a float
1944 value-effect */
1945 remainder = 100 * (maxdam % area) / area;
1946 maxdam /= area;
1947 if (RANDOM () % 100 < remainder)
1757 maxdam++; 1948 maxdam++;
1949 }
1950
1951#ifdef ATTACK_DEBUG
1952 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1758#endif 1953#endif
1759
1760#ifdef ATTACK_DEBUG
1761 LOG(llevDebug,"Friendly fire (type:%d setting: %d%) did %d damage dropped to %d\n",
1762 friendlyfire, settings.set_friendly_fire, dam, maxdam);
1763#endif
1764 }
1765 1954
1766 if (!full_hit) {
1767 archetype *at;
1768 int area;
1769 int remainder;
1770
1771 area = 0;
1772 for(at = op->arch; at != NULL; at = at->more)
1773 area++;
1774 assert(area > 0);
1775
1776 /* basically: maxdam /= area; we try to "simulate" a float
1777 value-effect */
1778 remainder = 100*(maxdam%area)/area;
1779 maxdam /= area;
1780 if (RANDOM()%100 < remainder)
1781 maxdam++;
1782 }
1783
1784#ifdef ATTACK_DEBUG
1785 LOG(llevDebug,"Attacktype %d did %d damage\n", type, maxdam);
1786#endif
1787
1788 if(get_owner(hitter)) 1955 if (get_owner (hitter))
1789 op->enemy=hitter->owner; 1956 op->enemy = hitter->owner;
1790 else if (QUERY_FLAG(hitter,FLAG_ALIVE)) 1957 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1791 op->enemy=hitter; 1958 op->enemy = hitter;
1792 1959
1793 if(QUERY_FLAG(op,FLAG_UNAGGRESSIVE) && op->type != PLAYER) { 1960 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1961 {
1794 /* The unaggressives look after themselves 8) */ 1962 /* The unaggressives look after themselves 8) */
1795 CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); 1963 CLEAR_FLAG (op, FLAG_UNAGGRESSIVE);
1796 npc_call_help(op); 1964 npc_call_help (op);
1797 } 1965 }
1798 1966
1799 if (magic && did_make_save(op, op->level, 0)) 1967 if (magic && did_make_save (op, op->level, 0))
1800 maxdam=maxdam/2; 1968 maxdam = maxdam / 2;
1801 1969
1802 attack_message(maxdam, maxattacktype, op, hitter); 1970 attack_message (maxdam, maxattacktype, op, hitter);
1803 1971
1804 op->stats.hp-=maxdam; 1972 op->stats.hp -= maxdam;
1805 1973
1806 /* Eneq(@csd.uu.se): Check to see if monster runs away. */ 1974 /* Eneq(@csd.uu.se): Check to see if monster runs away. */
1807 if ((op->stats.hp>=0) && 1975 if ((op->stats.hp >= 0) &&
1808 (QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) && 1976 (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER) &&
1809 op->stats.hp<(signed short)(((float)op->run_away/(float)100)* 1977 op->stats.hp < (signed short) (((float) op->run_away / (float) 100) * (float) op->stats.maxhp))
1810 (float)op->stats.maxhp)) { 1978 {
1811 1979
1812 if (QUERY_FLAG(op, FLAG_MONSTER)) 1980 if (QUERY_FLAG (op, FLAG_MONSTER))
1813 SET_FLAG(op, FLAG_RUN_AWAY); 1981 SET_FLAG (op, FLAG_RUN_AWAY);
1814 else 1982 else
1815 scare_creature(op, hitter); 1983 scare_creature (op, hitter);
1816 } 1984 }
1817 1985
1818 if(QUERY_FLAG(op,FLAG_TEAR_DOWN)) { 1986 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1987 {
1819 if (maxdam) 1988 if (maxdam)
1820 tear_down_wall(op); 1989 tear_down_wall (op);
1821 return maxdam; /* nothing more to do for wall */ 1990 return maxdam; /* nothing more to do for wall */
1822 } 1991 }
1823 1992
1824 /* See if the creature has been killed */ 1993 /* See if the creature has been killed */
1825 rtn_kill = kill_object(op, maxdam, hitter, type); 1994 rtn_kill = kill_object (op, maxdam, hitter, type);
1826 if (rtn_kill != -1) 1995 if (rtn_kill != -1)
1827 return rtn_kill; 1996 return rtn_kill;
1828 1997
1829 1998
1830 /* Used to be ghosthit removal - we now use the ONE_HIT flag. Note 1999 /* Used to be ghosthit removal - we now use the ONE_HIT flag. Note
1831 * that before if the player was immune to ghosthit, the monster 2000 * that before if the player was immune to ghosthit, the monster
1832 * remained - that is no longer the case. 2001 * remained - that is no longer the case.
1833 */ 2002 */
1834 if(QUERY_FLAG(hitter, FLAG_ONE_HIT)) { 2003 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
2004 {
1835 if(QUERY_FLAG(hitter,FLAG_FRIENDLY)) 2005 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
1836 remove_friendly_object(hitter); 2006 remove_friendly_object (hitter);
1837 remove_ob(hitter); 2007 remove_ob (hitter);
1838 free_object(hitter); 2008 free_object (hitter);
1839 } 2009 }
1840 /* Lets handle creatures that are splitting now */ 2010 /* Lets handle creatures that are splitting now */
1841 else if(type&AT_PHYSICAL&&!QUERY_FLAG(op, FLAG_FREED)&&QUERY_FLAG(op,FLAG_SPLITTING)) { 2011 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
2012 {
1842 int i; 2013 int i;
1843 int friendly = QUERY_FLAG(op,FLAG_FRIENDLY); 2014 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
1844 int unaggressive = QUERY_FLAG(op, FLAG_UNAGGRESSIVE); 2015 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
1845 object *owner = get_owner(op); 2016 object *owner = get_owner (op);
1846 2017
1847 if(!op->other_arch) { 2018 if (!op->other_arch)
2019 {
1848 LOG(llevError,"SPLITTING without other_arch error.\n"); 2020 LOG (llevError, "SPLITTING without other_arch error.\n");
1849 return maxdam; 2021 return maxdam;
1850 } 2022 }
1851 remove_ob(op); 2023 remove_ob (op);
1852 for(i=0;i<NROFNEWOBJS(op);i++) { /* This doesn't handle op->more yet */ 2024 for (i = 0; i < NROFNEWOBJS (op); i++)
2025 { /* This doesn't handle op->more yet */
1853 object *tmp=arch_to_object(op->other_arch); 2026 object *tmp = arch_to_object (op->other_arch);
1854 int j; 2027 int j;
1855 2028
1856 tmp->stats.hp=op->stats.hp; 2029 tmp->stats.hp = op->stats.hp;
1857 if (friendly) { 2030 if (friendly)
2031 {
1858 SET_FLAG(tmp, FLAG_FRIENDLY); 2032 SET_FLAG (tmp, FLAG_FRIENDLY);
1859 add_friendly_object(tmp); 2033 add_friendly_object (tmp);
1860 tmp->attack_movement = PETMOVE; 2034 tmp->attack_movement = PETMOVE;
1861 if (owner!=NULL) 2035 if (owner != NULL)
1862 set_owner(tmp,owner); 2036 set_owner (tmp, owner);
1863 } 2037 }
1864 if (unaggressive) 2038 if (unaggressive)
1865 SET_FLAG(tmp, FLAG_UNAGGRESSIVE); 2039 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1866 j=find_first_free_spot(tmp,op->map,op->x,op->y); 2040 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1867 if (j==-1) /* No spot to put this monster */ 2041 if (j == -1) /* No spot to put this monster */
1868 free_object(tmp); 2042 free_object (tmp);
1869 else { 2043 else
2044 {
1870 tmp->x=op->x+freearr_x[j],tmp->y=op->y+freearr_y[j]; 2045 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
1871 insert_ob_in_map(tmp,op->map,NULL,0); 2046 insert_ob_in_map (tmp, op->map, NULL, 0);
1872 } 2047 }
1873 } 2048 }
1874 if(friendly) 2049 if (friendly)
1875 remove_friendly_object(op); 2050 remove_friendly_object (op);
1876 free_object(op); 2051 free_object (op);
1877 } 2052 }
1878 else if(type & AT_DRAIN && hitter->type==GRIMREAPER&&hitter->value++>10) { 2053 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2054 {
1879 remove_ob(hitter); 2055 remove_ob (hitter);
1880 free_object(hitter); 2056 free_object (hitter);
1881 } 2057 }
1882 return maxdam; 2058 return maxdam;
1883} 2059}
1884 2060
1885 2061
2062void
1886void poison_player(object *op, object *hitter, int dam) 2063poison_player (object *op, object *hitter, int dam)
1887{ 2064{
1888 archetype *at = find_archetype("poisoning"); 2065 archetype *at = archetype::find ("poisoning");
1889 object *tmp=present_arch_in_ob(at,op); 2066 object *tmp = present_arch_in_ob (at, op);
1890 2067
1891 if(tmp==NULL) { 2068 if (tmp == NULL)
2069 {
1892 if((tmp=arch_to_object(at))==NULL) 2070 if ((tmp = arch_to_object (at)) == NULL)
1893 LOG(llevError,"Failed to clone arch poisoning.\n"); 2071 LOG (llevError, "Failed to clone arch poisoning.\n");
1894 else { 2072 else
2073 {
1895 tmp = insert_ob_in_ob(tmp,op); 2074 tmp = insert_ob_in_ob (tmp, op);
1896 /* peterm: give poisoning some teeth. It should 2075 /* peterm: give poisoning some teeth. It should
1897 * be able to kill things better than it does: 2076 * be able to kill things better than it does:
1898 * damage should be dependent something--I choose to 2077 * damage should be dependent something--I choose to
1899 * do this: if it's a monster, the damage from the 2078 * do this: if it's a monster, the damage from the
1900 * poisoning goes as the level of the monster/2. 2079 * poisoning goes as the level of the monster/2.
1901 * If anything else, goes as damage. 2080 * If anything else, goes as damage.
1902 */ 2081 */
1903 2082
1904 if(QUERY_FLAG(hitter,FLAG_ALIVE)) 2083 if (QUERY_FLAG (hitter, FLAG_ALIVE))
1905 tmp->stats.dam += hitter->level/2; 2084 tmp->stats.dam += hitter->level / 2;
1906 else 2085 else
1907 tmp->stats.dam = dam; 2086 tmp->stats.dam = dam;
1908 2087
1909 copy_owner(tmp,hitter); /* so we get credit for poisoning kills */ 2088 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */
1910 if(hitter->skill && hitter->skill != tmp->skill) { 2089 if (hitter->skill && hitter->skill != tmp->skill)
2090 {
1911 tmp->skill = hitter->skill; 2091 tmp->skill = hitter->skill;
1912 } 2092 }
1913 2093
1914 tmp->stats.food+=dam; /* more damage, longer poisoning */ 2094 tmp->stats.food += dam; /* more damage, longer poisoning */
1915 2095
1916 if(op->type==PLAYER) { 2096 if (op->type == PLAYER)
2097 {
1917 /* player looses stats, maximum is -10 of each */ 2098 /* player looses stats, maximum is -10 of each */
1918 tmp->stats.Con= MAX(-(dam/4+1), -10); 2099 tmp->stats.Con = MAX (-(dam / 4 + 1), -10);
1919 tmp->stats.Str= MAX(-(dam/3+2), -10); 2100 tmp->stats.Str = MAX (-(dam / 3 + 2), -10);
1920 tmp->stats.Dex= MAX(-(dam/6+1), -10); 2101 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10);
1921 tmp->stats.Int= MAX(-dam/7, -10); 2102 tmp->stats.Int = MAX (-dam / 7, -10);
1922 SET_FLAG(tmp,FLAG_APPLIED); 2103 SET_FLAG (tmp, FLAG_APPLIED);
1923 fix_player(op); 2104 fix_player (op);
1924 new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very ill."); 2105 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
1925 } 2106 }
1926 if (hitter->type == PLAYER) 2107 if (hitter->type == PLAYER)
1927 new_draw_info_format(NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); 2108 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
1928 else if (get_owner(hitter) != NULL && hitter->owner->type == PLAYER) 2109 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER)
1929 new_draw_info_format(NDI_UNIQUE, 0, hitter->owner, 2110 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
1930 "Your %s poisons %s.", &hitter->name, &op->name);
1931 } 2111 }
1932 tmp->speed_left=0; 2112 tmp->speed_left = 0;
1933 } 2113 }
1934 else 2114 else
1935 tmp->stats.food++; 2115 tmp->stats.food++;
1936} 2116}
1937 2117
2118void
1938void slow_player(object *op,object *hitter,int dam) 2119slow_player (object *op, object *hitter, int dam)
2120{
1939{ archetype *at = find_archetype("slowness"); 2121 archetype *at = archetype::find ("slowness");
1940 object *tmp; 2122 object *tmp;
2123
1941 if(at == NULL) { 2124 if (at == NULL)
2125 {
1942 LOG(llevError,"Can't find slowness archetype.\n"); 2126 LOG (llevError, "Can't find slowness archetype.\n");
1943 } 2127 }
1944 if((tmp=present_arch_in_ob(at,op)) == NULL) { 2128 if ((tmp = present_arch_in_ob (at, op)) == NULL)
2129 {
1945 tmp = arch_to_object(at); 2130 tmp = arch_to_object (at);
1946 tmp = insert_ob_in_ob(tmp,op); 2131 tmp = insert_ob_in_ob (tmp, op);
1947 new_draw_info(NDI_UNIQUE, 0,op,"The world suddenly moves very fast!"); 2132 new_draw_info (NDI_UNIQUE, 0, op, "The world suddenly moves very fast!");
2133 }
1948 } else 2134 else
1949 tmp->stats.food++; 2135 tmp->stats.food++;
1950 SET_FLAG(tmp, FLAG_APPLIED); 2136 SET_FLAG (tmp, FLAG_APPLIED);
1951 tmp->speed_left=0; 2137 tmp->speed_left = 0;
1952 fix_player(op); 2138 fix_player (op);
1953} 2139}
1954 2140
2141void
1955void confuse_player(object *op, object *hitter, int dam) 2142confuse_player (object *op, object *hitter, int dam)
1956{ 2143{
1957 object *tmp; 2144 object *tmp;
1958 int maxduration; 2145 int maxduration;
1959 2146
1960 tmp = present_in_ob_by_name(FORCE,"confusion", op); 2147 tmp = present_in_ob_by_name (FORCE, "confusion", op);
1961 if(!tmp) { 2148 if (!tmp)
2149 {
1962 tmp = get_archetype(FORCE_NAME); 2150 tmp = get_archetype (FORCE_NAME);
1963 tmp = insert_ob_in_ob(tmp,op); 2151 tmp = insert_ob_in_ob (tmp, op);
1964 }
1965 2152 }
2153
1966 /* Duration added per hit and max. duration of confusion both depend 2154 /* Duration added per hit and max. duration of confusion both depend
1967 * on the player's resistance 2155 * on the player's resistance
1968 */ 2156 */
1969 tmp->speed = 0.05; 2157 tmp->speed = 0.05;
1970 tmp->subtype = FORCE_CONFUSION; 2158 tmp->subtype = FORCE_CONFUSION;
1971 tmp->duration = 8 + MAX(1, 5*(100-op->resist[ATNR_CONFUSION])/100); 2159 tmp->duration = 8 + MAX (1, 5 * (100 - op->resist[ATNR_CONFUSION]) / 100);
1972 tmp->name = "confusion"; 2160 tmp->name = "confusion";
1973 maxduration = MAX(2, 30*(100-op->resist[ATNR_CONFUSION])/100); 2161 maxduration = MAX (2, 30 * (100 - op->resist[ATNR_CONFUSION]) / 100);
1974 if( tmp->duration > maxduration) 2162 if (tmp->duration > maxduration)
1975 tmp->duration = maxduration; 2163 tmp->duration = maxduration;
1976 2164
1977 if(op->type == PLAYER && !QUERY_FLAG(op,FLAG_CONFUSED)) 2165 if (op->type == PLAYER && !QUERY_FLAG (op, FLAG_CONFUSED))
1978 new_draw_info(NDI_UNIQUE, 0,op,"You suddenly feel very confused!"); 2166 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very confused!");
1979 SET_FLAG(op, FLAG_CONFUSED); 2167 SET_FLAG (op, FLAG_CONFUSED);
1980} 2168}
1981 2169
2170void
1982void blind_player(object *op, object *hitter, int dam) 2171blind_player (object *op, object *hitter, int dam)
1983{ 2172{
1984 object *tmp,*owner; 2173 object *tmp, *owner;
1985 2174
1986 /* Save some work if we know it isn't going to affect the player */ 2175 /* Save some work if we know it isn't going to affect the player */
1987 if (op->resist[ATNR_BLIND]==100) return; 2176 if (op->resist[ATNR_BLIND] == 100)
2177 return;
1988 2178
1989 tmp = present_in_ob(BLINDNESS,op); 2179 tmp = present_in_ob (BLINDNESS, op);
1990 if(!tmp) { 2180 if (!tmp)
2181 {
1991 tmp = get_archetype("blindness"); 2182 tmp = get_archetype ("blindness");
1992 SET_FLAG(tmp, FLAG_BLIND); 2183 SET_FLAG (tmp, FLAG_BLIND);
1993 SET_FLAG(tmp, FLAG_APPLIED); 2184 SET_FLAG (tmp, FLAG_APPLIED);
1994 /* use floats so we don't lose too much precision due to rounding errors. 2185 /* use floats so we don't lose too much precision due to rounding errors.
1995 * speed is a float anyways. 2186 * speed is a float anyways.
1996 */ 2187 */
1997 tmp->speed = tmp->speed * (100.0 - (float)op->resist[ATNR_BLIND]) / 100; 2188 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100;
1998 2189
1999 tmp = insert_ob_in_ob(tmp,op); 2190 tmp = insert_ob_in_ob (tmp, op);
2000 change_abil(op,tmp); /* Mostly to display any messages */ 2191 change_abil (op, tmp); /* Mostly to display any messages */
2001 fix_player(op); /* This takes care of some other stuff */ 2192 fix_player (op); /* This takes care of some other stuff */
2002 2193
2194 if (hitter->owner)
2003 if(hitter->owner) owner = get_owner(hitter); 2195 owner = get_owner (hitter);
2196 else
2004 else owner = hitter; 2197 owner = hitter;
2005 2198
2006 new_draw_info_format(NDI_UNIQUE,0,owner, 2199 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2007 "Your attack blinds %s!",query_name(op));
2008 } 2200 }
2009 tmp->stats.food += dam; 2201 tmp->stats.food += dam;
2010 if(tmp->stats.food > 10) tmp->stats.food = 10; 2202 if (tmp->stats.food > 10)
2203 tmp->stats.food = 10;
2011} 2204}
2012 2205
2206void
2013void paralyze_player(object *op, object *hitter, int dam) 2207paralyze_player (object *op, object *hitter, int dam)
2014{ 2208{
2015 float effect,max; 2209 float effect, max;
2210
2016 /* object *tmp; */ 2211 /* object *tmp; */
2017 2212
2018 /* This is strange stuff... someone knows for what this is 2213 /* This is strange stuff... someone knows for what this is
2019 * written? Well, i think this can and should be removed 2214 * written? Well, i think this can and should be removed
2020 */ 2215 */
2021 2216
2022 /* 2217 /*
2023 if((tmp=present(PARAIMAGE,op->map,op->x,op->y))==NULL) { 2218 if((tmp=present(PARAIMAGE,op->map,op->x,op->y))==NULL) {
2024 tmp=clone_arch(PARAIMAGE); 2219 tmp=clone_arch(PARAIMAGE);
2025 tmp->x=op->x,tmp->y=op->y; 2220 tmp->x=op->x,tmp->y=op->y;
2026 insert_ob_in_map(tmp,op->map,tmp,INS_NO_MERGE | INS_NO_WALK_ON); 2221 insert_ob_in_map(tmp,op->map,tmp,INS_NO_MERGE | INS_NO_WALK_ON);
2027 } 2222 }
2028 */ 2223 */
2029 2224
2030 /* Do this as a float - otherwise, rounding might very well reduce this to 0 */ 2225 /* Do this as a float - otherwise, rounding might very well reduce this to 0 */
2031 effect = (float)dam * 3.0 * (100.0 - op->resist[ATNR_PARALYZE]) / 100; 2226 effect = (float) dam *3.0 * (100.0 - op->resist[ATNR_PARALYZE]) / 100;
2032 2227
2033 if (effect==0) return; 2228 if (effect == 0)
2229 return;
2034 2230
2035 op->speed_left-=FABS(op->speed)*effect; 2231 op->speed_left -= FABS (op->speed) * effect;
2036 /* tmp->stats.food+=(signed short) effect/op->speed; */ 2232 /* tmp->stats.food+=(signed short) effect/op->speed; */
2037 2233
2038 /* max number of ticks to be affected for. */ 2234 /* max number of ticks to be affected for. */
2039 max = (100 - op->resist[ATNR_PARALYZE])/ 2; 2235 max = (100 - op->resist[ATNR_PARALYZE]) / 2;
2040 if (op->speed_left< -(FABS(op->speed)*max)) 2236 if (op->speed_left < -(FABS (op->speed) * max))
2041 op->speed_left = (float) -(FABS(op->speed)*max); 2237 op->speed_left = (float) -(FABS (op->speed) * max);
2042 2238
2043/* tmp->stats.food = (signed short) (max/FABS(op->speed)); */ 2239/* tmp->stats.food = (signed short) (max/FABS(op->speed)); */
2044} 2240}
2045 2241
2046 2242
2047/* Attempts to kill 'op'. hitter is the attack object, dam is 2243/* Attempts to kill 'op'. hitter is the attack object, dam is
2048 * the computed damaged. 2244 * the computed damaged.
2049 */ 2245 */
2246void
2050void deathstrike_player(object *op, object *hitter, int *dam) 2247deathstrike_player (object *op, object *hitter, int *dam)
2051{ 2248{
2052 /* The intention of a death attack is to kill outright things 2249 /* The intention of a death attack is to kill outright things
2053 ** that are a lot weaker than the attacker, have a chance of killing 2250 ** that are a lot weaker than the attacker, have a chance of killing
2054 ** things somewhat weaker than the caster, and no chance of 2251 ** things somewhat weaker than the caster, and no chance of
2055 ** killing something equal or stronger than the attacker. 2252 ** killing something equal or stronger than the attacker.
2056 ** Also, if a deathstrike attack has a slaying, any monster 2253 ** Also, if a deathstrike attack has a slaying, any monster
2057 ** whose name or race matches a comma-delimited list in the slaying 2254 ** whose name or race matches a comma-delimited list in the slaying
2058 ** field of the deathstriking object */ 2255 ** field of the deathstriking object */
2059 2256
2060 int atk_lev, def_lev, kill_lev; 2257 int atk_lev, def_lev, kill_lev;
2061 2258
2062 if(hitter->slaying) 2259 if (hitter->slaying)
2063 if(!( (QUERY_FLAG(op,FLAG_UNDEAD)&&strstr(hitter->slaying,undead_name)) || 2260 if (!((QUERY_FLAG (op, FLAG_UNDEAD) && strstr (hitter->slaying, undead_name)) || (op->race && strstr (hitter->slaying, op->race))))
2064 (op->race&&strstr(hitter->slaying,op->race)))) return; 2261 return;
2065 2262
2066 def_lev = op->level; 2263 def_lev = op->level;
2067 if (def_lev < 1) { 2264 if (def_lev < 1)
2265 {
2068 LOG (llevError, "BUG: arch %s, name %s with level < 1\n", 2266 LOG (llevError, "BUG: arch %s, name %s with level < 1\n", &op->arch->name, &op->name);
2069 &op->arch->name, &op->name);
2070 def_lev = 1; 2267 def_lev = 1;
2071 } 2268 }
2072 atk_lev = (hitter->chosen_skill?hitter->chosen_skill->level:hitter->level) / 2; 2269 atk_lev = (hitter->chosen_skill ? hitter->chosen_skill->level : hitter->level) / 2;
2073 /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n", 2270 /* LOG(llevDebug,"Deathstrike - attack level %d, defender level %d\n",
2074 atk_lev, def_lev); */ 2271 atk_lev, def_lev); */
2075 2272
2076 if(atk_lev >= def_lev ){ 2273 if (atk_lev >= def_lev)
2274 {
2077 kill_lev = random_roll(0, atk_lev-1, hitter, PREFER_HIGH); 2275 kill_lev = random_roll (0, atk_lev - 1, hitter, PREFER_HIGH);
2078 2276
2079 /* Note that the below effectively means the ratio of the atk vs 2277 /* Note that the below effectively means the ratio of the atk vs
2080 * defener level is important - if level 52 character has very little 2278 * defener level is important - if level 52 character has very little
2081 * chance of killing a level 50 monster. This should probably be 2279 * chance of killing a level 50 monster. This should probably be
2082 * redone. 2280 * redone.
2083 */ 2281 */
2084 if(kill_lev >= def_lev) { 2282 if (kill_lev >= def_lev)
2283 {
2085 *dam = op->stats.hp+10; /* take all hp. they can still save for 1/2 */ 2284 *dam = op->stats.hp + 10; /* take all hp. they can still save for 1/2 */
2086 /* I think this doesn't really do much. Because of 2285 /* I think this doesn't really do much. Because of
2087 * integer rounding, this only makes any difference if the 2286 * integer rounding, this only makes any difference if the
2088 * attack level is double the defender level. 2287 * attack level is double the defender level.
2089 */ 2288 */
2090 *dam *= kill_lev / def_lev; 2289 *dam *= kill_lev / def_lev;
2091 } 2290 }
2092 } else { 2291 }
2292 else
2293 {
2093 *dam = 0; /* no harm done */ 2294 *dam = 0; /* no harm done */
2094 } 2295 }
2095} 2296}
2096 2297
2097/* thrown_item_effect() - handles any special effects of thrown 2298/* thrown_item_effect() - handles any special effects of thrown
2098 * items (like attacking living creatures--a potion thrown at a 2299 * items (like attacking living creatures--a potion thrown at a
2099 * monster). 2300 * monster).
2100 */ 2301 */
2302static void
2101static void thrown_item_effect (object *hitter, object *victim) 2303thrown_item_effect (object *hitter, object *victim)
2102{ 2304{
2103 if(!QUERY_FLAG(hitter,FLAG_ALIVE)) { 2305 if (!QUERY_FLAG (hitter, FLAG_ALIVE))
2306 {
2104 /* May not need a switch for just 2 types, but this makes it 2307 /* May not need a switch for just 2 types, but this makes it
2105 * easier for expansion. 2308 * easier for expansion.
2106 */ 2309 */
2107 switch (hitter->type) { 2310 switch (hitter->type)
2311 {
2108 case POTION: 2312 case POTION:
2109 /* should player get a save throw instead of checking magic protection? */ 2313 /* should player get a save throw instead of checking magic protection? */
2110 if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD) 2314 if (QUERY_FLAG (victim, FLAG_ALIVE) && !QUERY_FLAG (victim, FLAG_UNDEAD) && (victim->resist[ATNR_MAGIC] < 60))
2111 &&(victim->resist[ATNR_MAGIC]<60)) (void) apply_potion(victim,hitter); 2315 (void) apply_potion (victim, hitter);
2112 break; 2316 break;
2113 2317
2114 case POISON: /* poison drinks */ 2318 case POISON: /* poison drinks */
2115 /* As with potions, should monster get a save? */ 2319 /* As with potions, should monster get a save? */
2116 if(QUERY_FLAG(victim,FLAG_ALIVE)&&!QUERY_FLAG(victim,FLAG_UNDEAD) 2320 if (QUERY_FLAG (victim, FLAG_ALIVE) && !QUERY_FLAG (victim, FLAG_UNDEAD) && (victim->resist[ATNR_POISON] < 60))
2117 &&(victim->resist[ATNR_POISON]<60)) apply_poison(victim,hitter); 2321 apply_poison (victim, hitter);
2118 break; 2322 break;
2119 2323
2120 /* Removed case statements that did nothing. 2324 /* Removed case statements that did nothing.
2121 * food may be poisonous, but monster must be willing to eat it, 2325 * food may be poisonous, but monster must be willing to eat it,
2122 * so we don't handle it here. 2326 * so we don't handle it here.
2123 * Containers should perhaps break open, but that code was disabled. 2327 * Containers should perhaps break open, but that code was disabled.
2124 */ 2328 */
2125 } 2329 }
2126 } 2330 }
2127} 2331}
2128 2332
2129/* adj_attackroll() - adjustments to attacks by various conditions */ 2333/* adj_attackroll() - adjustments to attacks by various conditions */
2130 2334
2335int
2131int adj_attackroll (object *hitter, object *target) { 2336adj_attackroll (object *hitter, object *target)
2337{
2132 object *attacker = hitter; 2338 object *attacker = hitter;
2133 int adjust=0; 2339 int adjust = 0;
2134 2340
2135 /* safety */ 2341 /* safety */
2136 if(!target||!hitter||!hitter->map||!target->map||!on_same_map(hitter,target)) { 2342 if (!target || !hitter || !hitter->map || !target->map || !on_same_map (hitter, target))
2343 {
2137 LOG (llevError, "BUG: adj_attackroll(): hitter and target not on same " 2344 LOG (llevError, "BUG: adj_attackroll(): hitter and target not on same " "map\n");
2138 "map\n"); 2345 return 0;
2346 }
2347
2348 /* aimed missiles use the owning object's sight */
2349 if (is_aimed_missile (hitter))
2350 {
2351 if ((attacker = get_owner (hitter)) == NULL)
2352 attacker = hitter;
2353 /* A player who saves but hasn't quit still could have objects
2354 * owned by him - need to handle that case to avoid crashes.
2355 */
2356 if (QUERY_FLAG (attacker, FLAG_REMOVED))
2357 attacker = hitter;
2358 }
2359 else if (!QUERY_FLAG (hitter, FLAG_ALIVE))
2139 return 0; 2360 return 0;
2140 }
2141 2361
2142 /* aimed missiles use the owning object's sight */
2143 if(is_aimed_missile(hitter)) {
2144 if ((attacker = get_owner(hitter))==NULL) attacker = hitter;
2145 /* A player who saves but hasn't quit still could have objects
2146 * owned by him - need to handle that case to avoid crashes.
2147 */
2148 if (QUERY_FLAG(attacker, FLAG_REMOVED)) attacker = hitter;
2149 }
2150 else if(!QUERY_FLAG(hitter,FLAG_ALIVE))
2151 return 0;
2152
2153 /* determine the condtions under which we make an attack. 2362 /* determine the condtions under which we make an attack.
2154 * Add more cases, as the need occurs. */ 2363 * Add more cases, as the need occurs. */
2155 2364
2156 if(!can_see_enemy(attacker,target)) { 2365 if (!can_see_enemy (attacker, target))
2366 {
2157 /* target is unseen */ 2367 /* target is unseen */
2158 if(target->invisible || QUERY_FLAG(attacker,FLAG_BLIND)) 2368 if (target->invisible || QUERY_FLAG (attacker, FLAG_BLIND))
2159 adjust -= 10; 2369 adjust -= 10;
2160 /* dark map penalty for the hitter (lacks infravision if we got here). */ 2370 /* dark map penalty for the hitter (lacks infravision if we got here). */
2161 else if(target->map&&target->map->darkness>0&&!stand_in_light(target)) 2371 else if (target->map && target->map->darkness > 0 && !stand_in_light (target))
2162 adjust -= target->map->darkness; 2372 adjust -= target->map->darkness;
2163 } 2373 }
2164 2374
2165 if(QUERY_FLAG(attacker,FLAG_SCARED)) 2375 if (QUERY_FLAG (attacker, FLAG_SCARED))
2166 adjust -= 3; 2376 adjust -= 3;
2167 2377
2168 if(QUERY_FLAG(target,FLAG_UNAGGRESSIVE)) 2378 if (QUERY_FLAG (target, FLAG_UNAGGRESSIVE))
2169 adjust += 1; 2379 adjust += 1;
2170 2380
2171 if(QUERY_FLAG(target,FLAG_SCARED)) 2381 if (QUERY_FLAG (target, FLAG_SCARED))
2172 adjust += 1; 2382 adjust += 1;
2173 2383
2174 if(QUERY_FLAG(attacker,FLAG_CONFUSED)) 2384 if (QUERY_FLAG (attacker, FLAG_CONFUSED))
2175 adjust -= 3; 2385 adjust -= 3;
2176 2386
2177 /* if we attack at a different 'altitude' its harder */ 2387 /* if we attack at a different 'altitude' its harder */
2178 if((attacker->move_type & target->move_type)==0) 2388 if ((attacker->move_type & target->move_type) == 0)
2179 adjust -= 2; 2389 adjust -= 2;
2180 2390
2181#if 0 2391#if 0
2182 /* slower attacks are less likely to succeed. We should use a 2392 /* slower attacks are less likely to succeed. We should use a
2183 * comparison between attacker/target speeds BUT, players have 2393 * comparison between attacker/target speeds BUT, players have
2184 * a generally faster speed, so this will wind up being a HUGE 2394 * a generally faster speed, so this will wind up being a HUGE
2185 * disadantage for the monsters! Too bad, because missiles which 2395 * disadantage for the monsters! Too bad, because missiles which
2186 * fly fast should have a better chance of hitting a slower target. 2396 * fly fast should have a better chance of hitting a slower target.
2187 */ 2397 */
2188 if(hitter->speed<target->speed) 2398 if (hitter->speed < target->speed)
2189 adjust += ((float) hitter->speed-target->speed); 2399 adjust += ((float) hitter->speed - target->speed);
2190#endif 2400#endif
2191 2401
2192#if 0 2402#if 0
2193 LOG(llevDebug,"adj_attackroll() returns %d (%d)\n",adjust,attacker->count); 2403 LOG (llevDebug, "adj_attackroll() returns %d (%d)\n", adjust, attacker->count);
2194#endif 2404#endif
2195 2405
2196 return adjust; 2406 return adjust;
2197} 2407}
2198 2408
2199 2409
2200/* determine if the object is an 'aimed' missile */ 2410/* determine if the object is an 'aimed' missile */
2411int
2201int is_aimed_missile ( object *op) { 2412is_aimed_missile (object *op)
2413{
2202 2414
2203 /* I broke what used to be one big if into a few nested 2415 /* I broke what used to be one big if into a few nested
2204 * ones so that figuring out the logic is at least possible. 2416 * ones so that figuring out the logic is at least possible.
2205 */ 2417 */
2206 if (op && (op->move_type & MOVE_FLYING)) { 2418 if (op && (op->move_type & MOVE_FLYING))
2419 {
2207 if (op->type==ARROW || op->type==THROWN_OBJ) 2420 if (op->type == ARROW || op->type == THROWN_OBJ)
2208 return 1; 2421 return 1;
2209 else if (op->type==SPELL_EFFECT && (op->subtype == SP_BULLET || 2422 else if (op->type == SPELL_EFFECT && (op->subtype == SP_BULLET || op->subtype == SP_EXPLOSION))
2210 op->subtype == SP_EXPLOSION))
2211 return 1; 2423 return 1;
2212 } 2424 }
2213 return 0; 2425 return 0;
2214} 2426}
2215

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines