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.7 by root, Wed Aug 30 06:06:27 2006 UTC vs.
Revision 1.24 by root, Sat Dec 9 16:11:09 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines