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.4 by root, Tue Aug 29 07:34:00 2006 UTC vs.
Revision 1.19 by root, Sat Sep 16 22:24:13 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines