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.15 by root, Thu Sep 14 20:46:10 2006 UTC vs.
Revision 1.41 by root, Mon Jan 15 00:40:49 2007 UTC

1
2/*
3 * static char *rcsid_attack_c =
4 * "$Id: attack.C,v 1.15 2006/09/14 20:46:10 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
12 7
13 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by 9 it under the terms of the GNU General Public License as published by
22 17
23 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 21
27 The authors can be reached via e-mail to crossfire-devel@real-time.com 22 The authors can be reached via e-mail to <crossfire@schmorp.de>
28*/ 23*/
29#include <assert.h> 24#include <assert.h>
30#include <global.h> 25#include <global.h>
31#include <living.h> 26#include <living.h>
32#include <material.h> 27#include <material.h>
78 esrv_send_item (op->env, op); 73 esrv_send_item (op->env, op);
79 } 74 }
80 } 75 }
81} 76}
82 77
83
84
85/* did_make_save_item just checks to make sure the item actually 78/* did_make_save_item just checks to make sure the item actually
86 * made its saving throw based on the tables. It does not take 79 * made its saving throw based on the tables. It does not take
87 * any further action (like destroying the item). 80 * any further action (like destroying the item).
88 */ 81 */
89
90int 82int
91did_make_save_item (object *op, int type, object *originator) 83did_make_save_item (object *op, int type, object *originator)
92{ 84{
93 int i, roll, saves = 0, attacks = 0, number; 85 int i, roll, saves = 0, attacks = 0, number;
94 materialtype_t *mt; 86 materialtype_t *mt;
95 87
96 if (op->materialname == NULL) 88 if (op->materialname == NULL)
97 { 89 {
98 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next) 90 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
99 {
100 if (op->material & mt->material) 91 if (op->material & mt->material)
101 break; 92 break;
102 }
103 } 93 }
104 else 94 else
105 mt = name_to_material (op->materialname); 95 mt = name_to_material (op->materialname);
96
106 if (mt == NULL) 97 if (mt == NULL)
107 return TRUE; 98 return TRUE;
99
108 roll = rndm (1, 20); 100 roll = rndm (1, 20);
109 101
110 /* the attacktypes have no meaning for object saves 102 /* the attacktypes have no meaning for object saves
111 * If the type is only magic, don't adjust type - basically, if 103 * If the type is only magic, don't adjust type - basically, if
112 * pure magic is hitting an object, it should save. However, if it 104 * pure magic is hitting an object, it should save. However, if it
158{ 150{
159 if (!did_make_save_item (op, type, originator)) 151 if (!did_make_save_item (op, type, originator))
160 { 152 {
161 object *env = op->env; 153 object *env = op->env;
162 int x = op->x, y = op->y; 154 int x = op->x, y = op->y;
163 mapstruct *m = op->map; 155 maptile *m = op->map;
164 156
165 op = stop_item (op); 157 op = stop_item (op);
166 if (op == NULL) 158 if (op == NULL)
167 return; 159 return;
168 160
218 } 210 }
219 else 211 else
220 { 212 {
221 if (op->env) 213 if (op->env)
222 { 214 {
223 object *tmp = is_player_inv (op->env); 215 object *tmp = op->in_player ();
224 216
225 if (tmp) 217 if (tmp)
226 esrv_del_item (tmp->contr, op->count); 218 esrv_del_item (tmp->contr, op->count);
227 } 219 }
228 220
229 if (!QUERY_FLAG (op, FLAG_REMOVED)) 221 op->destroy ();
230 remove_ob (op);
231
232 free_object (op);
233 } 222 }
234 223
235 if (type & (AT_FIRE | AT_ELECTRICITY)) 224 if (type & (AT_FIRE | AT_ELECTRICITY))
236 if (env) 225 if (env)
237 { 226 {
247 236
248 /* The value of 50 is arbitrary. */ 237 /* The value of 50 is arbitrary. */
249 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2)) 238 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
250 { 239 {
251 object *tmp; 240 object *tmp;
252 archetype *at = find_archetype ("icecube"); 241 archetype *at = archetype::find ("icecube");
253 242
254 if (at == NULL) 243 if (at == NULL)
255 return; 244 return;
256 245
257 op = stop_item (op); 246 op = stop_item (op);
270 tmp->move_slow = 0; 259 tmp->move_slow = 0;
271 insert_ob_in_map (tmp, op->map, originator, 0); 260 insert_ob_in_map (tmp, op->map, originator, 0);
272 } 261 }
273 262
274 if (!QUERY_FLAG (op, FLAG_REMOVED)) 263 if (!QUERY_FLAG (op, FLAG_REMOVED))
275 remove_ob (op); 264 op->remove ();
276 265
277 insert_ob_in_ob (op, tmp); 266 insert_ob_in_ob (op, tmp);
278 return; 267 return;
279 } 268 }
280} 269}
287 */ 276 */
288 277
289int 278int
290hit_map (object *op, int dir, int type, int full_hit) 279hit_map (object *op, int dir, int type, int full_hit)
291{ 280{
292 object *tmp, *next;
293 mapstruct *map; 281 maptile *map;
294 sint16 x, y; 282 sint16 x, y;
295 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ 283 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
296 284
297 tag_t op_tag, next_tag = 0;
298
299 if (QUERY_FLAG (op, FLAG_FREED)) 285 if (QUERY_FLAG (op, FLAG_FREED))
300 { 286 {
301 LOG (llevError, "BUG: hit_map(): free object\n"); 287 LOG (llevError, "BUG: hit_map(): free object\n");
302 return 0; 288 return 0;
303 } 289 }
314 return 0; 300 return 0;
315 } 301 }
316 302
317 if (op->head) 303 if (op->head)
318 op = op->head; 304 op = op->head;
319
320 op_tag = op->count;
321 305
322 map = op->map; 306 map = op->map;
323 x = op->x + freearr_x[dir]; 307 x = op->x + freearr_x[dir];
324 y = op->y + freearr_y[dir]; 308 y = op->y + freearr_y[dir];
325 309
326 int mflags = get_map_flags (map, &map, x, y, &x, &y); 310 if (!xy_normalise (map, x, y))
311 return 0;
327 312
328 // elmex: a safe map tile can't be hit! 313 // elmex: a safe map tile can't be hit!
329 // this should prevent most harmful effects on items and players there. 314 // this should prevent most harmful effects on items and players there.
330 if (mflags & (P_OUT_OF_MAP | P_SAFE)) 315 mapspace &ms = map->at (x, y);
316
317 if (ms.flags () & P_SAFE)
331 return 0; 318 return 0;
332 319
333 /* peterm: a few special cases for special attacktypes --counterspell 320 /* peterm: a few special cases for special attacktypes --counterspell
334 * must be out here because it strikes things which are not alive 321 * must be out here because it strikes things which are not alive
335 */ 322 */
336 323 if (type & (AT_COUNTERSPELL | AT_CHAOS))
324 {
337 if (type & AT_COUNTERSPELL) 325 if (type & AT_COUNTERSPELL)
338 { 326 {
339 counterspell (op, dir); /* see spell_effect.c */ 327 counterspell (op, dir); /* see spell_effect.c */
340 328
341 /* If the only attacktype is counterspell or magic, don't need 329 /* If the only attacktype is counterspell or magic, don't need
342 * to do any further processing. 330 * to do any further processing.
343 */
344 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
345 return 0;
346
347 type &= ~AT_COUNTERSPELL;
348 }
349
350 if (type & AT_CHAOS)
351 {
352 shuffle_attack (op, 1); /*1 flag tells it to change the face */
353 update_object (op, UP_OBJ_FACE);
354 type &= ~AT_CHAOS;
355 }
356
357 next = get_map_ob (map, x, y);
358 if (next)
359 next_tag = next->count;
360
361 while (next)
362 {
363 if (was_destroyed (next, next_tag))
364 {
365 /* There may still be objects that were above 'next', but there is no
366 * simple way to find out short of copying all object references and
367 * tags into a temporary array before we start processing the first
368 * object. That's why we just abort.
369 *
370 * This happens whenever attack spells (like fire) hit a pile
371 * of objects. This is not a bug - nor an error. The errormessage
372 * below was spamming the logs for absolutely no reason.
373 */ 331 */
374 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */ 332 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
375 break; 333 return 0;
334
335 type &= ~AT_COUNTERSPELL;
336 }
337
338 if (type & AT_CHAOS)
376 } 339 {
340 shuffle_attack (op, 1); /* flag tells it to change the face */
341 update_object (op, UP_OBJ_FACE);
342 type &= ~AT_CHAOS;
343 }
344 }
377 345
346 /* There may still be objects that were above 'next', but there is no
347 * simple way to find out short of copying all object references and
348 * tags into a temporary array before we start processing the first
349 * object. That's why we just abort on destroy.
350 *
351 * This happens whenever attack spells (like fire) hit a pile
352 * of objects. This is not a bug - nor an error.
353 */
354 for (object *next = ms.bot; next && !next->destroyed (); )
355 {
378 tmp = next; 356 object *tmp = next;
379 next = tmp->above; 357 next = tmp->above;
380
381 if (next)
382 next_tag = next->count;
383
384 if (QUERY_FLAG (tmp, FLAG_FREED))
385 {
386 LOG (llevError, "BUG: hit_map(): found freed object\n");
387 break;
388 }
389 358
390 /* Something could have happened to 'tmp' while 'tmp->below' was processed. 359 /* Something could have happened to 'tmp' while 'tmp->below' was processed.
391 * For example, 'tmp' was put in an icecube. 360 * For example, 'tmp' was put in an icecube.
392 * This is one of the few cases where on_same_map should not be used. 361 * This is one of the few cases where on_same_map should not be used.
393 */ 362 */
396 365
397 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 366 if (QUERY_FLAG (tmp, FLAG_ALIVE))
398 { 367 {
399 hit_player (tmp, op->stats.dam, op, type, full_hit); 368 hit_player (tmp, op->stats.dam, op, type, full_hit);
400 retflag |= 1; 369 retflag |= 1;
370
401 if (was_destroyed (op, op_tag)) 371 if (op->destroyed ())
402 break; 372 break;
403 } 373 }
404
405 /* Here we are potentially destroying an object. If the object has 374 /* Here we are potentially destroying an object. If the object has
406 * NO_PASS set, it is also immune - you can't destroy walls. Note 375 * NO_PASS set, it is also immune - you can't destroy walls. Note
407 * that weak walls have is_alive set, which prevent objects from 376 * that weak walls have is_alive set, which prevent objects from
408 * passing over/through them. We don't care what type of movement 377 * passing over/through them. We don't care what type of movement
409 * the wall blocks - if it blocks any type of movement, can't be 378 * the wall blocks - if it blocks any type of movement, can't be
410 * destroyed right now. 379 * destroyed right now.
411 */ 380 */
412 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block) 381 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
413 { 382 {
414 save_throw_object (tmp, type, op); 383 save_throw_object (tmp, type, op);
384
415 if (was_destroyed (op, op_tag)) 385 if (op->destroyed ())
416 break; 386 break;
417 } 387 }
418 } 388 }
419 389
420 return 0; 390 return 0;
423void 393void
424attack_message (int dam, int type, object *op, object *hitter) 394attack_message (int dam, int type, object *op, object *hitter)
425{ 395{
426 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 396 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
427 int i, found = 0; 397 int i, found = 0;
428 mapstruct *map; 398 maptile *map;
429 object *next, *tmp; 399 object *next, *tmp;
430 400
431 /* put in a few special messages for some of the common attacktypes 401 /* put in a few special messages for some of the common attacktypes
432 * a player might have. For example, fire, electric, cold, etc 402 * a player might have. For example, fire, electric, cold, etc
433 * [garbled 20010919] 403 * [garbled 20010919]
450 sprintf (buf1, "missed %s", &op->name); 420 sprintf (buf1, "missed %s", &op->name);
451 sprintf (buf2, " misses"); 421 sprintf (buf2, " misses");
452 found++; 422 found++;
453 } 423 }
454 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || 424 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM ||
455 hitter->type == POISONING || (type & AT_POISON && IS_LIVE (op))) && !found) 425 hitter->type == POISONING || (type & AT_POISON && op->is_alive ())) && !found)
456 { 426 {
457 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++) 427 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++)
458 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1) 428 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1)
459 { 429 {
460 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2); 430 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2);
472 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3); 442 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3);
473 found++; 443 found++;
474 break; 444 break;
475 } 445 }
476 } 446 }
477 else if (hitter->type == PLAYER && IS_LIVE (op)) 447 else if (hitter->type == PLAYER && op->is_alive ())
478 { 448 {
479 if (USING_SKILL (hitter, SK_KARATE)) 449 if (USING_SKILL (hitter, SK_KARATE))
480 { 450 {
481 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++) 451 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++)
482 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1) 452 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1)
508 found++; 478 found++;
509 break; 479 break;
510 } 480 }
511 } 481 }
512 } 482 }
483
513 if (found) 484 if (found)
514 { 485 {
515 /* done */ 486 /* done */
516 } 487 }
517 else if (IS_ARROW (hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) 488 else if (hitter->is_arrow () && (type == AT_PHYSICAL || type == AT_MAGIC))
518 { 489 {
519 sprintf (buf1, "hit"); /* just in case */ 490 sprintf (buf1, "hit"); /* just in case */
520 for (i = 0; i < MAXATTACKMESS; i++) 491 for (i = 0; i < MAXATTACKMESS; i++)
521 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1) 492 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1)
522 { 493 {
523 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3); 494 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
524 found++; 495 found++;
525 break; 496 break;
526 } 497 }
527 } 498 }
528 else if (type & AT_DRAIN && IS_LIVE (op)) 499 else if (type & AT_DRAIN && op->is_alive ())
529 { 500 {
530 /* drain is first, because some items have multiple attypes */ 501 /* drain is first, because some items have multiple attypes */
531 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++) 502 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++)
532 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1) 503 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1)
533 { 504 {
535 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); 506 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
536 found++; 507 found++;
537 break; 508 break;
538 } 509 }
539 } 510 }
540 else if (type & AT_ELECTRICITY && IS_LIVE (op)) 511 else if (type & AT_ELECTRICITY && op->is_alive ())
541 { 512 {
542 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++) 513 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++)
543 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1) 514 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1)
544 { 515 {
545 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2); 516 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2);
546 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3); 517 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
547 found++; 518 found++;
548 break; 519 break;
549 } 520 }
550 } 521 }
551 else if (type & AT_COLD && IS_LIVE (op)) 522 else if (type & AT_COLD && op->is_alive ())
552 { 523 {
553 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++) 524 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++)
554 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1) 525 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1)
555 { 526 {
556 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2); 527 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2);
633 strcpy (buf1, "hit"); 604 strcpy (buf1, "hit");
634 strcpy (buf2, " hits"); 605 strcpy (buf2, " hits");
635 } 606 }
636 607
637 /* bail out if a monster is casting spells */ 608 /* bail out if a monster is casting spells */
638 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER))) 609 if (!(hitter->type == PLAYER || (hitter->owner != NULL && hitter->owner->type == PLAYER)))
639 return; 610 return;
640 611
641 /* scale down magic considerably. */ 612 /* scale down magic considerably. */
642 if (type & AT_MAGIC && rndm (0, 5)) 613 if (type & AT_MAGIC && rndm (0, 5))
643 return; 614 return;
644 615
645 /* Did a player hurt another player? Inform both! */ 616 /* Did a player hurt another player? Inform both! */
646 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER) 617 if (op->type == PLAYER && (hitter->owner == NULL ? hitter->type : hitter->owner->type) == PLAYER)
647 { 618 {
648 if (get_owner (hitter) != NULL) 619 if (hitter->owner != NULL)
649 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2); 620 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
650 else 621 else
651 { 622 {
652 sprintf (buf, "%s%s you.", &hitter->name, buf2); 623 sprintf (buf, "%s%s you.", &hitter->name, buf2);
653 if (dam != 0) 624 if (dam != 0)
675 else 646 else
676 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0); 647 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
677 } 648 }
678 new_draw_info (NDI_BLACK, 0, hitter, buf); 649 new_draw_info (NDI_BLACK, 0, hitter, buf);
679 } 650 }
680 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 651 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
681 { 652 {
682 /* look for stacked spells and start reducing the message chances */ 653 /* look for stacked spells and start reducing the message chances */
683 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE)) 654 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
684 { 655 {
685 i = 4; 656 i = 4;
686 map = hitter->map; 657 map = hitter->map;
687 if (out_of_map (map, hitter->x, hitter->y)) 658 if (out_of_map (map, hitter->x, hitter->y))
688 return; 659 return;
689 next = get_map_ob (map, hitter->x, hitter->y); 660 next = GET_MAP_OB (map, hitter->x, hitter->y);
690 if (next) 661 if (next)
691 while (next) 662 while (next)
692 { 663 {
693 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE)) 664 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE))
694 i *= 3; 665 i *= 3;
760attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 731attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
761{ 732{
762 int simple_attack, roll, dam = 0; 733 int simple_attack, roll, dam = 0;
763 uint32 type; 734 uint32 type;
764 shstr op_name; 735 shstr op_name;
765 tag_t op_tag, hitter_tag;
766 736
767 if (get_attack_mode (&op, &hitter, &simple_attack)) 737 if (get_attack_mode (&op, &hitter, &simple_attack))
768 goto error; 738 goto error;
769 739
770 if (hitter->current_weapon) 740 if (hitter->current_weapon)
771 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 741 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
772 return RESULT_INT (0); 742 return RESULT_INT (0);
773 743
774 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 744 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
775 return RESULT_INT (0); 745 return RESULT_INT (0);
776
777 op_tag = op->count;
778 hitter_tag = hitter->count;
779 746
780 /* 747 /*
781 * A little check to make it more difficult to dance forward and back 748 * A little check to make it more difficult to dance forward and back
782 * to avoid ever being hit by monsters. 749 * to avoid ever being hit by monsters.
783 */ 750 */
788 * which then gets here again. By decreasing the speed before 755 * which then gets here again. By decreasing the speed before
789 * we call process_object, the 'if' statement above will fail. 756 * we call process_object, the 'if' statement above will fail.
790 */ 757 */
791 op->speed_left--; 758 op->speed_left--;
792 process_object (op); 759 process_object (op);
760
793 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 761 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
794 goto error; 762 goto error;
795 } 763 }
796 764
797 op_name = op->name; 765 op_name = op->name;
798 766
810 if (settings.casting_time == TRUE) 778 if (settings.casting_time == TRUE)
811 { 779 {
812 if ((hitter->type == PLAYER) && (hitter->casting_time > -1)) 780 if ((hitter->type == PLAYER) && (hitter->casting_time > -1))
813 { 781 {
814 hitter->casting_time = -1; 782 hitter->casting_time = -1;
815 new_draw_info (NDI_UNIQUE, 0, hitter, "You attacked and lost " "your spell!"); 783 new_draw_info (NDI_UNIQUE, 0, hitter, "You attacked and lost your spell!");
816 } 784 }
817 if ((op->casting_time > -1) && (hitdam > 0)) 785 if ((op->casting_time > -1) && (hitdam > 0))
818 { 786 {
819 op->casting_time = -1; 787 op->casting_time = -1;
820 if (op->type == PLAYER) 788 if (op->type == PLAYER)
821 { 789 {
822 new_draw_info (NDI_UNIQUE, 0, op, "You were hit and lost " "your spell!"); 790 new_draw_info (NDI_UNIQUE, 0, op, "You were hit and lost your spell!");
823 new_draw_info_format (NDI_ALL | NDI_UNIQUE, 5, NULL, "%s was hit by %s and lost a spell.", &op_name, &hitter->name); 791 new_draw_info_format (NDI_ALL | NDI_UNIQUE, 5, NULL, "%s was hit by %s and lost a spell.", &op_name, &hitter->name);
824 } 792 }
825 } 793 }
826 } 794 }
827 if (!simple_attack) 795 if (!simple_attack)
832 if (QUERY_FLAG (op, FLAG_SLEEP)) 800 if (QUERY_FLAG (op, FLAG_SLEEP))
833 CLEAR_FLAG (op, FLAG_SLEEP); 801 CLEAR_FLAG (op, FLAG_SLEEP);
834 802
835 /* If the victim can't see the attacker, it may alert others 803 /* If the victim can't see the attacker, it may alert others
836 * for help. */ 804 * for help. */
837 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int)) 805 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !op->owner && rndm (0, op->stats.Int))
838 npc_call_help (op); 806 npc_call_help (op);
839 807
840 /* if you were hidden and hit by a creature, you are discovered */ 808 /* if you were hidden and hit by a creature, you are discovered */
841 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) 809 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
842 { 810 {
849 * when they hit the victim. For things like thrown daggers, 817 * when they hit the victim. For things like thrown daggers,
850 * this sets 'hitter' to the actual dagger, and not the 818 * this sets 'hitter' to the actual dagger, and not the
851 * wrapper object. 819 * wrapper object.
852 */ 820 */
853 thrown_item_effect (hitter, op); 821 thrown_item_effect (hitter, op);
822
854 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 823 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
855 goto leave; 824 goto leave;
856 } 825 }
857 826
858 /* Need to do at least 1 damage, otherwise there is no point 827 /* Need to do at least 1 damage, otherwise there is no point
859 * to go further and it will cause FPE's below. 828 * to go further and it will cause FPE's below.
860 */ 829 */
861 if (hitdam <= 0) 830 if (hitdam <= 0)
862 hitdam = 1; 831 hitdam = 1;
863 832
864 type = hitter->attacktype; 833 type = hitter->attacktype;
834
865 if (!type) 835 if (!type)
866 type = AT_PHYSICAL; 836 type = AT_PHYSICAL;
837
867 /* Handle monsters that hit back */ 838 /* Handle monsters that hit back */
868 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 839 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
869 { 840 {
870 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 841 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
871 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 842 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
843
872 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 844 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
845
873 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 846 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
874 goto leave; 847 goto leave;
875 } 848 }
876 849
877 /* In the new attack code, it should handle multiple attack 850 /* In the new attack code, it should handle multiple attack
878 * types in its area, so remove it from here. 851 * types in its area, so remove it from here.
879 */ 852 */
880 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 853 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
854
881 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 855 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
882 goto leave; 856 goto leave;
883 } /* end of if hitter hit op */ 857 } /* end of if hitter hit op */
884 /* if we missed, dam=0 */ 858 /* if we missed, dam=0 */
885 859
886 /*attack_message(dam, type, op, hitter); */ 860 /*attack_message(dam, type, op, hitter); */
920 if (op->weight <= 5000 && tmp->stats.hp >= 0) 894 if (op->weight <= 5000 && tmp->stats.hp >= 0)
921 { 895 {
922 if (tmp->head != NULL) 896 if (tmp->head != NULL)
923 tmp = tmp->head; 897 tmp = tmp->head;
924 898
925 remove_ob (op); 899 op->remove ();
926 op = insert_ob_in_ob (op, tmp); 900 op = insert_ob_in_ob (op, tmp);
927 901
928 if (tmp->type == PLAYER) 902 if (tmp->type == PLAYER)
929 esrv_send_item (tmp, op); 903 esrv_send_item (tmp, op);
930 904
943object * 917object *
944hit_with_arrow (object *op, object *victim) 918hit_with_arrow (object *op, object *victim)
945{ 919{
946 object *container, *hitter; 920 object *container, *hitter;
947 int hit_something = 0; 921 int hit_something = 0;
948 tag_t victim_tag, hitter_tag;
949 sint16 victim_x, victim_y;
950 922
951 /* Disassemble missile */ 923 /* Disassemble missile */
952 if (op->inv) 924 if (op->inv)
953 { 925 {
954 container = op; 926 container = op;
955 hitter = op->inv; 927 hitter = op->inv;
956 remove_ob (hitter); 928 hitter->remove ();
957 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON); 929 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON);
958 /* Note that we now have an empty THROWN_OBJ on the map. Code that 930 /* Note that we now have an empty THROWN_OBJ on the map. Code that
959 * might be called until this THROWN_OBJ is either reassembled or 931 * might be called until this THROWN_OBJ is either reassembled or
960 * removed at the end of this function must be able to deal with empty 932 * removed at the end of this function must be able to deal with empty
961 * THROWN_OBJs. */ 933 * THROWN_OBJs. */
962 } 934 }
963 else 935 else
964 { 936 {
965 container = NULL; 937 container = 0;
966 hitter = op; 938 hitter = op;
967 } 939 }
968 940
969 /* Try to hit victim */ 941 /* Try to hit victim */
970 victim_x = victim->x;
971 victim_y = victim->y;
972 victim_tag = victim->count;
973 hitter_tag = hitter->count;
974
975 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 942 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
976 943
977 /* Arrow attacks door, rune of summoning is triggered, demon is put on 944 /* Arrow attacks door, rune of summoning is triggered, demon is put on
978 * arrow, move_apply() calls this function, arrow sticks in demon, 945 * arrow, move_apply() calls this function, arrow sticks in demon,
979 * attack_ob_simple() returns, and we've got an arrow that still exists 946 * attack_ob_simple() returns, and we've got an arrow that still exists
980 * but is no longer on the map. Ugh. (Beware: Such things can happen at 947 * but is no longer on the map. Ugh. (Beware: Such things can happen at
981 * other places as well!) 948 * other places as well!)
982 */ 949 */
983 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 950 if (hitter->destroyed () || hitter->env != NULL)
984 { 951 {
985 if (container) 952 if (container)
986 { 953 {
987 remove_ob (container); 954 container->remove ();
988 free_object (container); 955 container->destroy ();
989 } 956 }
957
990 return NULL; 958 return 0;
991 } 959 }
992 960
993 /* Missile hit victim */ 961 /* Missile hit victim */
994 /* if the speed is > 10, then this is a fast moving arrow, we go straight 962 /* if the speed is > 10, then this is a fast moving arrow, we go straight
995 * through the target 963 * through the target
996 */ 964 */
997 if (hit_something && op->speed <= 10.0) 965 if (hit_something && op->speed <= 10.0)
998 { 966 {
999 /* Stop arrow */ 967 /* Stop arrow */
1000 if (container == NULL) 968 if (!container)
1001 { 969 {
1002 hitter = fix_stopped_arrow (hitter); 970 hitter = fix_stopped_arrow (hitter);
1003 if (hitter == NULL) 971 if (!hitter)
1004 return NULL; 972 return 0;
1005 } 973 }
1006 else 974 else
1007 { 975 container->destroy ();
1008 remove_ob (container);
1009 free_object (container);
1010 }
1011 976
1012 /* Try to stick arrow into victim */ 977 /* Try to stick arrow into victim */
1013 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 978 if (!victim->destroyed () && stick_arrow (hitter, victim))
1014 return NULL; 979 return 0;
1015 980
1016 /* Else try to put arrow on victim's map square 981 /* Else try to put arrow on victim's map square
1017 * remove check for P_WALL here. If the arrow got to this 982 * remove check for P_WALL here. If the arrow got to this
1018 * space, that is good enough - with the new movement code, 983 * space, that is good enough - with the new movement code,
1019 * there is now the potential for lots of spaces where something 984 * there is now the potential for lots of spaces where something
1020 * can fly over but not otherwise move over. What is the correct 985 * can fly over but not otherwise move over. What is the correct
1021 * way to handle those otherwise? 986 * way to handle those otherwise?
1022 */ 987 */
1023 if (victim_x != hitter->x || victim_y != hitter->y) 988 if (victim->x != hitter->x || victim->y != hitter->y)
1024 { 989 {
1025 remove_ob (hitter); 990 hitter->remove ();
1026 hitter->x = victim_x; 991 hitter->x = victim->x;
1027 hitter->y = victim_y; 992 hitter->y = victim->y;
1028 insert_ob_in_map (hitter, victim->map, hitter, 0); 993 insert_ob_in_map (hitter, victim->map, hitter, 0);
1029 } 994 }
1030 else 995 else
1031 {
1032 /* Else leave arrow where it is */ 996 /* Else leave arrow where it is */
1033 merge_ob (hitter, NULL); 997 merge_ob (hitter, NULL);
1034 } 998
1035 return NULL; 999 return 0;
1036 } 1000 }
1037 1001
1038 if (hit_something && op->speed >= 10.0) 1002 if (hit_something && op->speed >= 10.0)
1039 op->speed -= 1.0; 1003 op->speed -= 1.0;
1040 1004
1041 /* Missile missed victim - reassemble missile */ 1005 /* Missile missed victim - reassemble missile */
1042 if (container) 1006 if (container)
1043 { 1007 {
1044 remove_ob (hitter); 1008 hitter->remove ();
1045 insert_ob_in_ob (hitter, container); 1009 insert_ob_in_ob (hitter, container);
1046 } 1010 }
1011
1047 return op; 1012 return op;
1048} 1013}
1049 1014
1050 1015
1051void 1016void
1060 } 1025 }
1061 else if (!GET_ANIM_ID (op)) 1026 else if (!GET_ANIM_ID (op))
1062 { 1027 {
1063 /* Object has been called - no animations, so remove it */ 1028 /* Object has been called - no animations, so remove it */
1064 if (op->stats.hp < 0) 1029 if (op->stats.hp < 0)
1030 op->destroy ();
1065 { 1031
1066 remove_ob (op); /* Should update LOS */
1067 free_object (op);
1068 /* Don't know why this is here - remove_ob should do it for us */
1069 /*update_position(m, x, y); */
1070 }
1071 return; /* no animations, so nothing more to do */ 1032 return; /* no animations, so nothing more to do */
1072 } 1033 }
1034
1073 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp; 1035 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
1036
1074 if (perc >= (int) NUM_ANIMATIONS (op)) 1037 if (perc >= (int) NUM_ANIMATIONS (op))
1075 perc = NUM_ANIMATIONS (op) - 1; 1038 perc = NUM_ANIMATIONS (op) - 1;
1076 else if (perc < 1) 1039 else if (perc < 1)
1077 perc = 1; 1040 perc = 1;
1041
1078 SET_ANIMATION (op, perc); 1042 SET_ANIMATION (op, perc);
1079 update_object (op, UP_OBJ_FACE); 1043 update_object (op, UP_OBJ_FACE);
1044
1080 if (perc == NUM_ANIMATIONS (op) - 1) 1045 if (perc == NUM_ANIMATIONS (op) - 1)
1081 { /* Reached the last animation */ 1046 { /* Reached the last animation */
1082 if (op->face == blank_face) 1047 if (op->face == blank_face)
1083 {
1084 /* If the last face is blank, remove the ob */ 1048 /* If the last face is blank, remove the ob */
1085 remove_ob (op); /* Should update LOS */ 1049 op->destroy ();
1086 free_object (op);
1087
1088 /* remove_ob should call update_position for us */
1089 /*update_position(m, x, y); */
1090
1091 }
1092 else 1050 else
1093 { /* The last face was not blank, leave an image */ 1051 { /* The last face was not blank, leave an image */
1094 CLEAR_FLAG (op, FLAG_BLOCKSVIEW); 1052 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
1095 update_all_los (op->map, op->x, op->y); 1053 update_all_los (op->map, op->x, op->y);
1096 op->move_block = 0; 1054 op->move_block = 0;
1100} 1058}
1101 1059
1102void 1060void
1103scare_creature (object *target, object *hitter) 1061scare_creature (object *target, object *hitter)
1104{ 1062{
1105 object *owner = get_owner (hitter); 1063 object *owner = hitter->owner;
1106 1064
1107 if (!owner) 1065 if (!owner)
1108 owner = hitter; 1066 owner = hitter;
1109 1067
1110 SET_FLAG (target, FLAG_SCARED); 1068 SET_FLAG (target, FLAG_SCARED);
1121 * the attacktype. Makes it easier for the PR code. */ 1079 * the attacktype. Makes it easier for the PR code. */
1122 1080
1123int 1081int
1124hit_player_attacktype (object *op, object *hitter, int dam, uint32 attacknum, int magic) 1082hit_player_attacktype (object *op, object *hitter, int dam, uint32 attacknum, int magic)
1125{ 1083{
1126
1127 int doesnt_slay = 1; 1084 int doesnt_slay = 1;
1128 1085
1129 /* Catch anyone that may be trying to send us a bitmask instead of the number */ 1086 /* Catch anyone that may be trying to send us a bitmask instead of the number */
1130 if (attacknum >= NROFATTACKS) 1087 if (attacknum >= NROFATTACKS)
1131 { 1088 {
1176 1133
1177 /* Keep this in order - makes things easier to find */ 1134 /* Keep this in order - makes things easier to find */
1178 1135
1179 switch (attacknum) 1136 switch (attacknum)
1180 { 1137 {
1181 case ATNR_PHYSICAL: 1138 case ATNR_PHYSICAL:
1182 /* here also check for diseases */ 1139 /* here also check for diseases */
1183 check_physically_infect (op, hitter); 1140 check_physically_infect (op, hitter);
1184 break; 1141 break;
1185 1142
1186 /* Don't need to do anything for: 1143 /* Don't need to do anything for:
1187 magic, 1144 magic,
1188 fire, 1145 fire,
1189 electricity, 1146 electricity,
1190 cold */ 1147 cold */
1191 1148
1192 case ATNR_CONFUSION: 1149 case ATNR_CONFUSION:
1193 case ATNR_POISON: 1150 case ATNR_POISON:
1194 case ATNR_SLOW: 1151 case ATNR_SLOW:
1195 case ATNR_PARALYZE: 1152 case ATNR_PARALYZE:
1196 case ATNR_FEAR: 1153 case ATNR_FEAR:
1197 case ATNR_CANCELLATION: 1154 case ATNR_CANCELLATION:
1198 case ATNR_DEPLETE: 1155 case ATNR_DEPLETE:
1199 case ATNR_BLIND: 1156 case ATNR_BLIND:
1200 { 1157 {
1201 /* chance for inflicting a special attack depends on the 1158 /* chance for inflicting a special attack depends on the
1202 * difference between attacker's and defender's level 1159 * difference between attacker's and defender's level
1203 */ 1160 */
1204 int level_diff = MIN (110, MAX (0, op->level - hitter->level)); 1161 int level_diff = MIN (110, MAX (0, op->level - hitter->level));
1205 1162
1206 /* First, only creatures/players with speed can be affected. 1163 /* First, only creatures/players with speed can be affected.
1207 * Second, just getting hit doesn't mean it always affects 1164 * Second, just getting hit doesn't mean it always affects
1208 * you. Third, you still get a saving through against the 1165 * you. Third, you still get a saving through against the
1209 * effect. 1166 * effect.
1210 */ 1167 */
1211 if (op->speed && 1168 if (op->speed &&
1212 (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER) && 1169 (QUERY_FLAG (op, FLAG_MONSTER) || op->type == PLAYER) &&
1213 !(rndm (0, (attacknum == ATNR_SLOW ? 6 : 3) - 1)) && !did_make_save (op, level_diff, op->resist[attacknum] / 10)) 1170 !(rndm (0, (attacknum == ATNR_SLOW ? 6 : 3) - 1)) && !did_make_save (op, level_diff, op->resist[attacknum] / 10))
1214 { 1171 {
1215 1172
1216 /* Player has been hit by something */ 1173 /* Player has been hit by something */
1217 if (attacknum == ATNR_CONFUSION) 1174 if (attacknum == ATNR_CONFUSION)
1218 confuse_player (op, hitter, dam); 1175 confuse_player (op, hitter, dam);
1219 else if (attacknum == ATNR_POISON) 1176 else if (attacknum == ATNR_POISON)
1220 poison_player (op, hitter, dam); 1177 poison_player (op, hitter, dam);
1221 else if (attacknum == ATNR_SLOW) 1178 else if (attacknum == ATNR_SLOW)
1222 slow_player (op, hitter, dam); 1179 slow_player (op, hitter, dam);
1223 else if (attacknum == ATNR_PARALYZE) 1180 else if (attacknum == ATNR_PARALYZE)
1224 paralyze_player (op, hitter, dam); 1181 paralyze_player (op, hitter, dam);
1225 else if (attacknum == ATNR_FEAR) 1182 else if (attacknum == ATNR_FEAR)
1226 scare_creature (op, hitter); 1183 scare_creature (op, hitter);
1227 else if (attacknum == ATNR_CANCELLATION) 1184 else if (attacknum == ATNR_CANCELLATION)
1228 cancellation (op); 1185 cancellation (op);
1229 else if (attacknum == ATNR_DEPLETE) 1186 else if (attacknum == ATNR_DEPLETE)
1230 drain_stat (op); 1187 op->drain_stat ();
1231 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR)) 1188 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR))
1232 blind_player (op, hitter, dam); 1189 blind_player (op, hitter, dam);
1233 } 1190 }
1234 dam = 0; /* These are all effects and don't do real damage */ 1191 dam = 0; /* These are all effects and don't do real damage */
1235 } 1192 }
1236 break; 1193 break;
1237 case ATNR_ACID: 1194 case ATNR_ACID:
1238 { 1195 {
1239 int flag = 0; 1196 int flag = 0;
1240 1197
1241 /* Items only get corroded if you're not on a battleground and 1198 /* Items only get corroded if you're not on a battleground and
1242 * if your acid resistance is below 50%. */ 1199 * if your acid resistance is below 50%. */
1243 if (!op_on_battleground (op, NULL, NULL) && (op->resist[ATNR_ACID] < 50)) 1200 if (!op_on_battleground (op, NULL, NULL) && (op->resist[ATNR_ACID] < 50))
1244 { 1201 {
1245 object *tmp; 1202 object *tmp;
1246 1203
1247 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1204 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1248 { 1205 {
1249 if (tmp->invisible) 1206 if (tmp->invisible)
1250 continue; 1207 continue;
1251 if (!QUERY_FLAG (tmp, FLAG_APPLIED) || (tmp->resist[ATNR_ACID] >= 10)) 1208 if (!QUERY_FLAG (tmp, FLAG_APPLIED) || (tmp->resist[ATNR_ACID] >= 10))
1252 /* >= 10% acid res. on itmes will protect these */ 1209 /* >= 10% acid res. on itmes will protect these */
1253 continue; 1210 continue;
1254 if (!(tmp->material & M_IRON)) 1211 if (!(tmp->material & M_IRON))
1255 continue; 1212 continue;
1256 if (tmp->magic < -4) /* Let's stop at -5 */ 1213 if (tmp->magic < -4) /* Let's stop at -5 */
1257 continue; 1214 continue;
1258 if (tmp->type == RING || 1215 if (tmp->type == RING ||
1259 /* removed boots and gloves from exclusion list in 1216 /* removed boots and gloves from exclusion list in
1260 PR */ 1217 PR */
1261 tmp->type == GIRDLE || tmp->type == AMULET || tmp->type == WAND || tmp->type == ROD || tmp->type == HORN) 1218 tmp->type == GIRDLE || tmp->type == AMULET || tmp->type == WAND || tmp->type == ROD || tmp->type == HORN)
1262 continue; /* To avoid some strange effects */ 1219 continue; /* To avoid some strange effects */
1263 1220
1264 /* High damage acid has better chance of corroding 1221 /* High damage acid has better chance of corroding
1265 objects */ 1222 objects */
1266 if (rndm (0, dam + 4) > random_roll (0, 39, op, PREFER_HIGH) + 2 * tmp->magic) 1223 if (rndm (0, dam + 4) > random_roll (0, 39, op, PREFER_HIGH) + 2 * tmp->magic)
1267 { 1224 {
1268 if (op->type == PLAYER) 1225 if (op->type == PLAYER)
1269 /* Make this more visible */ 1226 /* Make this more visible */
1270 new_draw_info_format (NDI_UNIQUE | NDI_RED, 0, op, 1227 new_draw_info_format (NDI_UNIQUE | NDI_RED, 0, op,
1271 "The %s's acid corrodes your %s!", query_name (hitter), query_name (tmp)); 1228 "The %s's acid corrodes your %s!", query_name (hitter), query_name (tmp));
1272 flag = 1; 1229 flag = 1;
1273 tmp->magic--; 1230 tmp->magic--;
1274 if (op->type == PLAYER) 1231 if (op->type == PLAYER)
1275 esrv_send_item (op, tmp); 1232 esrv_send_item (op, tmp);
1276 } 1233 }
1277 } 1234 }
1278 if (flag) 1235 if (flag)
1279 fix_player (op); /* Something was corroded */ 1236 op->update_stats (); /* Something was corroded */
1280 } 1237 }
1281 } 1238 }
1282 break; 1239 break;
1283 case ATNR_DRAIN: 1240 case ATNR_DRAIN:
1284 { 1241 {
1285 /* rate is the proportion of exp drained. High rate means 1242 /* rate is the proportion of exp drained. High rate means
1286 * not much is drained, low rate means a lot is drained. 1243 * not much is drained, low rate means a lot is drained.
1287 */ 1244 */
1288 int rate; 1245 int rate;
1289 1246
1290 if (op->resist[ATNR_DRAIN] >= 0) 1247 if (op->resist[ATNR_DRAIN] >= 0)
1291 rate = 400 + op->resist[ATNR_DRAIN] * 3; 1248 rate = 400 + op->resist[ATNR_DRAIN] * 3;
1292 else 1249 else
1293 rate = 400 * 100 / (100 - op->resist[ATNR_DRAIN]); 1250 rate = 400 * 100 / (100 - op->resist[ATNR_DRAIN]);
1294 1251
1295 if (op->stats.exp <= rate) 1252 if (op->stats.exp <= rate)
1296 { 1253 {
1297 if (op->type == GOLEM) 1254 if (op->type == GOLEM)
1298 dam = 999; /* Its force is "sucked" away. 8) */ 1255 dam = 999; /* Its force is "sucked" away. 8) */
1299 else 1256 else
1300 /* If we can't drain, lets try to do physical damage */ 1257 /* If we can't drain, lets try to do physical damage */
1301 dam = hit_player_attacktype (op, hitter, dam, ATNR_PHYSICAL, magic); 1258 dam = hit_player_attacktype (op, hitter, dam, ATNR_PHYSICAL, magic);
1302 } 1259 }
1303 else 1260 else
1304 { 1261 {
1305 /* Randomly give the hitter some hp */ 1262 /* Randomly give the hitter some hp */
1306 if (hitter->stats.hp < hitter->stats.maxhp && 1263 if (hitter->stats.hp < hitter->stats.maxhp &&
1307 (op->level > hitter->level) && random_roll (0, (op->level - hitter->level + 2), hitter, PREFER_HIGH) > 3) 1264 (op->level > hitter->level) && random_roll (0, (op->level - hitter->level + 2), hitter, PREFER_HIGH) > 3)
1308 hitter->stats.hp++; 1265 hitter->stats.hp++;
1309 1266
1310 /* Can't do drains on battleground spaces. 1267 /* Can't do drains on battleground spaces.
1311 * Move the wiz check up here - before, the hitter wouldn't gain exp 1268 * Move the wiz check up here - before, the hitter wouldn't gain exp
1312 * exp, but the wiz would still lose exp! If drainee is a wiz, 1269 * exp, but the wiz would still lose exp! If drainee is a wiz,
1313 * nothing happens. 1270 * nothing happens.
1314 * Try to credit the owner. We try to display player -> player drain 1271 * Try to credit the owner. We try to display player -> player drain
1315 * attacks, hence all the != PLAYER checks. 1272 * attacks, hence all the != PLAYER checks.
1316 */ 1273 */
1317 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1274 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1318 { 1275 {
1319 object *owner = get_owner (hitter); 1276 object *owner = hitter->owner;
1320 1277
1321 if (owner && owner != hitter) 1278 if (owner && owner != hitter)
1322 { 1279 {
1323 if (op->type != PLAYER || owner->type != PLAYER) 1280 if (op->type != PLAYER || owner->type != PLAYER)
1324 change_exp (owner, op->stats.exp / (rate * 2), 1281 change_exp (owner, op->stats.exp / (rate * 2),
1325 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, SK_EXP_TOTAL); 1282 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, SK_EXP_TOTAL);
1326 } 1283 }
1327 else if (op->type != PLAYER || hitter->type != PLAYER) 1284 else if (op->type != PLAYER || hitter->type != PLAYER)
1328 { 1285 {
1329 change_exp (hitter, op->stats.exp / (rate * 2), 1286 change_exp (hitter, op->stats.exp / (rate * 2),
1330 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, 0); 1287 hitter->chosen_skill ? hitter->chosen_skill->skill : (const char *) 0, 0);
1331 } 1288 }
1332 change_exp (op, -op->stats.exp / rate, NULL, 0); 1289 change_exp (op, -op->stats.exp / rate, NULL, 0);
1333 } 1290 }
1334 dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure 1291 dam = 1; /* Drain is an effect. Still return 1 - otherwise, if you have pure
1335 * drain attack, you won't know that you are actually sucking out EXP, 1292 * drain attack, you won't know that you are actually sucking out EXP,
1336 * as the messages will say you missed 1293 * as the messages will say you missed
1337 */ 1294 */
1338 } 1295 }
1339 } 1296 }
1340 break; 1297 break;
1341 case ATNR_TURN_UNDEAD: 1298 case ATNR_TURN_UNDEAD:
1342 { 1299 {
1343 if (QUERY_FLAG (op, FLAG_UNDEAD)) 1300 if (QUERY_FLAG (op, FLAG_UNDEAD))
1344 { 1301 {
1345 object *owner = hitter->owner ? (object *)hitter->owner : hitter; 1302 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1346 object *god = find_god (determine_god (owner)); 1303 object *god = find_god (determine_god (owner));
1347 int div = 1; 1304 int div = 1;
1348 1305
1349 /* if undead are not an enemy of your god, you turn them 1306 /* if undead are not an enemy of your god, you turn them
1350 * at half strength */ 1307 * at half strength */
1351 if (!god || !god->slaying || strstr (god->slaying, undead_name) == NULL) 1308 if (!god || !god->slaying || strstr (god->slaying, undead_name) == NULL)
1352 div = 2; 1309 div = 2;
1353 /* Give a bonus if you resist turn undead */ 1310 /* Give a bonus if you resist turn undead */
1354 if (op->level * div < (turn_bonus[owner->stats.Wis] + owner->level + (op->resist[ATNR_TURN_UNDEAD] / 100))) 1311 if (op->level * div < (turn_bonus[owner->stats.Wis] + owner->level + (op->resist[ATNR_TURN_UNDEAD] / 100)))
1355 scare_creature (op, owner); 1312 scare_creature (op, owner);
1356 } 1313 }
1357 else 1314 else
1358 dam = 0; /* don't damage non undead - should we damage 1315 dam = 0; /* don't damage non undead - should we damage
1359 undead? */ 1316 undead? */
1360 } 1317 }
1361 break; 1318 break;
1362 case ATNR_DEATH: 1319 case ATNR_DEATH:
1363 deathstrike_player (op, hitter, &dam); 1320 deathstrike_player (op, hitter, &dam);
1364 break; 1321 break;
1365 case ATNR_CHAOS: 1322 case ATNR_CHAOS:
1366 LOG (llevError, "%s was hit by %s with non-specific chaos.\n", query_name (op), query_name (hitter)); 1323 LOG (llevError, "%s was hit by %s with non-specific chaos.\n", op->debug_desc (), hitter->debug_desc2 ());
1367 dam = 0; 1324 dam = 0;
1368 break; 1325 break;
1369 case ATNR_COUNTERSPELL: 1326 case ATNR_COUNTERSPELL:
1370 LOG (llevError, "%s was hit by %s with counterspell attack.\n", query_name (op), query_name (hitter)); 1327 LOG (llevError, "%s was hit by %s with counterspell attack.\n", op->debug_desc (), hitter->debug_desc2 ());
1371 dam = 0; 1328 dam = 0;
1372 /* This should never happen. Counterspell is handled 1329 /* This should never happen. Counterspell is handled
1373 * seperately and filtered out. If this does happen, 1330 * seperately and filtered out. If this does happen,
1374 * Counterspell has no effect on anything but spells, so it 1331 * Counterspell has no effect on anything but spells, so it
1375 * does no damage. */ 1332 * does no damage. */
1376 break; 1333 break;
1377 case ATNR_HOLYWORD: 1334 case ATNR_HOLYWORD:
1378 { 1335 {
1379 /* This has already been handled by hit_player, 1336 /* This has already been handled by hit_player,
1380 * no need to check twice -- DAMN */ 1337 * no need to check twice -- DAMN */
1381 object *owner = hitter->owner ? (object *)hitter->owner : hitter; 1338 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1382 1339
1383 /* As with turn undead above, give a bonus on the saving throw */ 1340 /* As with turn undead above, give a bonus on the saving throw */
1384 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis]) 1341 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1385 scare_creature (op, owner); 1342 scare_creature (op, owner);
1386 } 1343 }
1387 break; 1344 break;
1388 case ATNR_LIFE_STEALING: 1345 case ATNR_LIFE_STEALING:
1389 { 1346 {
1390 int new_hp; 1347 int new_hp;
1391 1348
1392 /* this is replacement to drain for players, instead of taking 1349 /* this is replacement to drain for players, instead of taking
1393 * exp it takes hp. It is geared for players, probably not 1350 * exp it takes hp. It is geared for players, probably not
1394 * much use giving it to monsters 1351 * much use giving it to monsters
1395 * 1352 *
1396 * life stealing doesn't do a lot of damage, but it gives the 1353 * life stealing doesn't do a lot of damage, but it gives the
1397 * damage it does do to the player. Given that, 1354 * damage it does do to the player. Given that,
1398 * it only does 1/10'th normal damage (hence the divide by 1355 * it only does 1/10'th normal damage (hence the divide by
1399 * 1000). 1356 * 1000).
1400 */ 1357 */
1401 /* You can't steal life from something undead */ 1358 /* You can't steal life from something undead */
1402 if ((op->type == GOLEM) || (QUERY_FLAG (op, FLAG_UNDEAD))) 1359 if ((op->type == GOLEM) || (QUERY_FLAG (op, FLAG_UNDEAD)))
1403 return 0; 1360 return 0;
1404 /* If drain protection is higher than life stealing, use that */ 1361 /* If drain protection is higher than life stealing, use that */
1405 if (op->resist[ATNR_DRAIN] >= op->resist[ATNR_LIFE_STEALING]) 1362 if (op->resist[ATNR_DRAIN] >= op->resist[ATNR_LIFE_STEALING])
1406 dam = (dam * (100 - op->resist[ATNR_DRAIN])) / 3000; 1363 dam = (dam * (100 - op->resist[ATNR_DRAIN])) / 3000;
1407 else 1364 else
1408 dam = (dam * (100 - op->resist[ATNR_LIFE_STEALING])) / 3000; 1365 dam = (dam * (100 - op->resist[ATNR_LIFE_STEALING])) / 3000;
1409 /* You die at -1 hp, not zero. */ 1366 /* You die at -1 hp, not zero. */
1410 if (dam > (op->stats.hp + 1)) 1367 if (dam > (op->stats.hp + 1))
1411 dam = op->stats.hp + 1; 1368 dam = op->stats.hp + 1;
1412 new_hp = hitter->stats.hp + dam; 1369 new_hp = hitter->stats.hp + dam;
1413 if (new_hp > hitter->stats.maxhp) 1370 if (new_hp > hitter->stats.maxhp)
1414 new_hp = hitter->stats.maxhp; 1371 new_hp = hitter->stats.maxhp;
1415 if (new_hp > hitter->stats.hp) 1372 if (new_hp > hitter->stats.hp)
1416 hitter->stats.hp = new_hp; 1373 hitter->stats.hp = new_hp;
1417 } 1374 }
1418 } 1375 }
1376
1419 return dam; 1377 return dam;
1420} 1378}
1421
1422 1379
1423/* GROS: This code comes from hit_player. It has been made external to 1380/* GROS: This code comes from hit_player. It has been made external to
1424 * allow script procedures to "kill" objects in a combat-like fashion. 1381 * allow script procedures to "kill" objects in a combat-like fashion.
1425 * It was initially used by (kill-object) developed for the Collector's 1382 * It was initially used by (kill-object) developed for the Collector's
1426 * Sword. Note that nothing has been changed from the original version 1383 * Sword. Note that nothing has been changed from the original version
1461 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW)) 1418 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW))
1462 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */ 1419 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */
1463 1420
1464 if (op->type == DOOR) 1421 if (op->type == DOOR)
1465 { 1422 {
1466 op->speed = 0.1; 1423 op->set_speed (0.1);
1467 update_ob_speed (op);
1468 op->speed_left = -0.05; 1424 op->speed_left = -0.05;
1469 return maxdam; 1425 return maxdam;
1470 } 1426 }
1427
1471 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1428 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1472 { 1429 {
1473 remove_friendly_object (op); 1430 remove_friendly_object (op);
1431
1474 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1432 if (op->owner && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1475 {
1476 op->owner->contr->ranges[range_golem] = NULL; 1433 op->owner->contr->ranges[range_golem] = 0;
1477 op->owner->contr->golem_count = 0;
1478 }
1479 1434
1480 remove_ob (op); 1435 op->destroy ();
1481 free_object (op);
1482 return maxdam; 1436 return maxdam;
1483 } 1437 }
1484 1438
1485 /* Now lets start dealing with experience we get for killing something */ 1439 /* Now lets start dealing with experience we get for killing something */
1486 1440
1487 owner = get_owner (hitter); 1441 owner = hitter->owner;
1488 if (owner == NULL) 1442 if (!owner)
1489 owner = hitter; 1443 owner = hitter;
1490 1444
1491 /* is the victim (op) standing on battleground? */ 1445 /* is the victim (op) standing on battleground? */
1492 if (op_on_battleground (op, NULL, NULL)) 1446 if (op_on_battleground (op, NULL, NULL))
1493 battleg = 1; 1447 battleg = 1;
1513 char buf[256]; 1467 char buf[256];
1514 1468
1515 tmv = localtime (&t); 1469 tmv = localtime (&t);
1516 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv); 1470 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv);
1517 1471
1518 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->socket.host, query_name (op)); 1472 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->ns->host, query_name (op));
1519 } 1473 }
1520 1474
1521 /* try to filter some things out - basically, if you are 1475 /* try to filter some things out - basically, if you are
1522 * killing a level 1 creature and your level 20, you 1476 * killing a level 1 creature and your level 20, you
1523 * probably don't want to see that. 1477 * probably don't want to see that.
1524 */ 1478 */
1525 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1479 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1526 { 1480 {
1527 if (owner != hitter) 1481 if (owner != hitter)
1528 {
1529 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1482 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1530 }
1531 else 1483 else
1532 {
1533 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1484 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1534 } 1485
1535 /* Only play sounds for melee kills */ 1486 /* Only play sounds for melee kills */
1536 if (hitter->type == PLAYER) 1487 if (hitter->type == PLAYER)
1537 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1488 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1538 } 1489 }
1539 1490
1544 * player that the object belonged to - so if you killed another player 1495 * player that the object belonged to - so if you killed another player
1545 * with spells, pets, whatever, there was no penalty. 1496 * with spells, pets, whatever, there was no penalty.
1546 * Changed to make luck penalty configurable in settings. 1497 * Changed to make luck penalty configurable in settings.
1547 */ 1498 */
1548 if (op->type == PLAYER && owner != op && !battleg) 1499 if (op->type == PLAYER && owner != op && !battleg)
1549 change_luck (owner, -settings.pk_luck_penalty); 1500 owner->change_luck (-settings.pk_luck_penalty);
1550 1501
1551 /* This code below deals with finding the appropriate skill 1502 /* This code below deals with finding the appropriate skill
1552 * to credit exp to. This is a bit problematic - we should 1503 * to credit exp to. This is a bit problematic - we should
1553 * probably never really have to look at current_weapon->skill 1504 * probably never really have to look at current_weapon->skill
1554 */ 1505 */
1555 skill = NULL; 1506 skill = 0;
1507
1556 if (hitter->skill && hitter->type != PLAYER) 1508 if (hitter->skill && hitter->type != PLAYER)
1557 skill = hitter->skill; 1509 skill = hitter->skill;
1558 else if (owner->chosen_skill) 1510 else if (owner->chosen_skill)
1559 { 1511 {
1560 skill = owner->chosen_skill->skill; 1512 skill = owner->chosen_skill->skill;
1579 break; 1531 break;
1580 } 1532 }
1581 } 1533 }
1582 } /* Was it a player that hit somethign */ 1534 } /* Was it a player that hit somethign */
1583 else 1535 else
1584 {
1585 skill = NULL; 1536 skill = 0;
1586 }
1587 1537
1588 /* Pet (or spell) killed something. */ 1538 /* Pet (or spell) killed something. */
1589 if (owner != hitter) 1539 if (owner != hitter)
1590 {
1591 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1540 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1592 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1541 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1593 }
1594 else 1542 else
1595 {
1596 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1543 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1597 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1544 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1598 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1545 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1599 } 1546
1600 /* These may have been set in the player code section above */ 1547 /* These may have been set in the player code section above */
1601 if (!skop) 1548 if (!skop)
1602 skop = hitter->chosen_skill; 1549 skop = hitter->chosen_skill;
1550
1603 if (!skill && skop) 1551 if (!skill && skop)
1604 skill = skop->skill; 1552 skill = skop->skill;
1605 1553
1606 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1554 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1607 1555
1608
1609 /* If you didn't kill yourself, and your not the wizard */ 1556 /* If you didn't kill yourself, and your not the wizard */
1610 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1557 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1611 { 1558 {
1612 int exp; 1559 int exp;
1613 1560
1614 /* Really don't give much experience for killing other players */ 1561 /* Really don't give much experience for killing other players */
1615 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1562 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1616 if (op->type == PLAYER) 1563 if (op->type == PLAYER)
1617 { 1564 {
1618 if (battleg) 1565 if (battleg)
1619 { 1566 {
1620 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1567 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1638 1585
1639 if (!settings.simple_exp) 1586 if (!settings.simple_exp)
1640 exp = exp / 2; 1587 exp = exp / 2;
1641 1588
1642 if (owner->type != PLAYER || owner->contr->party == NULL) 1589 if (owner->type != PLAYER || owner->contr->party == NULL)
1643 {
1644 change_exp (owner, exp, skill, 0); 1590 change_exp (owner, exp, skill, 0);
1645 }
1646 else 1591 else
1647 { 1592 {
1648 int shares = 0, count = 0; 1593 int shares = 0, count = 0;
1649
1650 player *pl; 1594 player *pl;
1651
1652 partylist *party = owner->contr->party; 1595 partylist *party = owner->contr->party;
1653 1596
1654#ifdef PARTY_KILL_LOG
1655 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1597 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1656#endif 1598
1657 for (pl = first_player; pl != NULL; pl = pl->next) 1599 for_all_players (pl)
1658 {
1659 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1600 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1660 { 1601 {
1661 count++; 1602 count++;
1662 shares += (pl->ob->level + 4); 1603 shares += (pl->ob->level + 4);
1663 } 1604 }
1664 } 1605
1665 if (count == 1 || shares > exp) 1606 if (count == 1 || shares > exp || !shares)
1666 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1607 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1667 else 1608 else
1668 { 1609 {
1669 int share = exp / shares, given = 0, nexp; 1610 int share = exp / shares, given = 0, nexp;
1670 1611
1671 for (pl = first_player; pl != NULL; pl = pl->next) 1612 for_all_players (pl)
1672 {
1673 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1613 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1674 { 1614 {
1675 nexp = (pl->ob->level + 4) * share; 1615 nexp = (pl->ob->level + 4) * share;
1676 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1616 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1677 given += nexp; 1617 given += nexp;
1678 } 1618 }
1679 } 1619
1680 exp -= given; 1620 exp -= given;
1681 /* give any remainder to the player */ 1621 /* give any remainder to the player */
1682 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1622 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1683 } 1623 }
1684 } /* else part of a party */ 1624 } /* else part of a party */
1685
1686 } /* end if person didn't kill himself */ 1625 } /* end if person didn't kill himself */
1687 1626
1688 if (op->type != PLAYER) 1627 if (op->type != PLAYER)
1689 { 1628 {
1690 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1629 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1691 { 1630 {
1692 object *owner1 = get_owner (op); 1631 object *owner1 = op->owner;
1693 1632
1694 if (owner1 != NULL && owner1->type == PLAYER) 1633 if (owner1 && owner1->type == PLAYER)
1695 { 1634 {
1696 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1635 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1697 /* Maybe we should include the owner that killed this, maybe not */ 1636 /* Maybe we should include the owner that killed this, maybe not */
1698 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); 1637 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1699 } 1638 }
1700 1639
1701 remove_friendly_object (op); 1640 remove_friendly_object (op);
1702 } 1641 }
1703 1642
1704 remove_ob (op); 1643 op->destroy ();
1705 free_object (op);
1706 } 1644 }
1707 /* Player has been killed! */
1708 else 1645 else
1709 { 1646 {
1647 /* Player has been killed! */
1710 if (owner->type == PLAYER) 1648 if (owner->type == PLAYER)
1711 {
1712 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1649 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1713 }
1714 else 1650 else
1715 assign (op->contr->killer, hitter->name); 1651 assign (op->contr->killer, hitter->name);
1716 } 1652 }
1717 1653
1718 /* This was return -1 - that doesn't seem correct - if we return -1, process 1654 /* This was return -1 - that doesn't seem correct - if we return -1, process
1742 return 0; 1678 return 0;
1743 1679
1744 if (hitter->type == PLAYER && hitter->contr->peaceful == 1) 1680 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1745 return 1; 1681 return 1;
1746 1682
1747 if ((owner = get_owner (hitter)) != NULL) 1683 if ((owner = hitter->owner) != NULL)
1748 { 1684 {
1749 if (owner->type == PLAYER && owner->contr->peaceful == 1) 1685 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1750 friendlyfire = 2; 1686 friendlyfire = 2;
1751 } 1687 }
1752 1688
1762 * is what is hitting the object, type is the attacktype, and 1698 * is what is hitting the object, type is the attacktype, and
1763 * full_hit is set if monster area does not matter. 1699 * full_hit is set if monster area does not matter.
1764 * dam is base damage - protections/vulnerabilities/slaying matches can 1700 * dam is base damage - protections/vulnerabilities/slaying matches can
1765 * modify it. 1701 * modify it.
1766 */ 1702 */
1767
1768 /* Oct 95 - altered the following slightly for MULTIPLE_GODS hack 1703/* Oct 95 - altered the following slightly for MULTIPLE_GODS hack
1769 * which needs new attacktype AT_HOLYWORD to work . b.t. */ 1704 * which needs new attacktype AT_HOLYWORD to work . b.t. */
1770
1771int 1705int
1772hit_player (object *op, int dam, object *hitter, int type, int full_hit) 1706hit_player (object *op, int dam, object *hitter, int type, int full_hit)
1773{ 1707{
1774 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1708 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1775 int maxattacktype, attacknum; 1709 int maxattacktype, attacknum;
1776 int body_attack = op && op->head; /* Did we hit op's head? */ 1710 int body_attack = op && op->head; /* Did we hit op's head? */
1777 int simple_attack; 1711 int simple_attack;
1778 tag_t op_tag, hitter_tag;
1779 int rtn_kill = 0; 1712 int rtn_kill = 0;
1780 int friendlyfire; 1713 int friendlyfire;
1781 1714
1782 if (get_attack_mode (&op, &hitter, &simple_attack)) 1715 if (get_attack_mode (&op, &hitter, &simple_attack))
1783 return 0; 1716 return 0;
1787 return 0; 1720 return 0;
1788 1721
1789#ifdef PROHIBIT_PLAYERKILL 1722#ifdef PROHIBIT_PLAYERKILL
1790 if (op->type == PLAYER) 1723 if (op->type == PLAYER)
1791 { 1724 {
1792 object *owner = get_owner (hitter); 1725 object *owner = hitter->owner;
1793 1726
1794 if (!owner) 1727 if (!owner)
1795 owner = hitter; 1728 owner = hitter;
1729
1796 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1730 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1797 {
1798 return 0; 1731 return 0;
1799 }
1800 } 1732 }
1801#endif 1733#endif
1802
1803 op_tag = op->count;
1804 hitter_tag = hitter->count;
1805 1734
1806 if (body_attack) 1735 if (body_attack)
1807 { 1736 {
1808 /* slow and paralyze must hit the head. But we don't want to just 1737 /* slow and paralyze must hit the head. But we don't want to just
1809 * return - we still need to process other attacks the spell still 1738 * return - we still need to process other attacks the spell still
1815 * attack so we don't cancel out things like magic bullet. 1744 * attack so we don't cancel out things like magic bullet.
1816 */ 1745 */
1817 if (type & (AT_PARALYZE | AT_SLOW)) 1746 if (type & (AT_PARALYZE | AT_SLOW))
1818 { 1747 {
1819 type &= ~(AT_PARALYZE | AT_SLOW); 1748 type &= ~(AT_PARALYZE | AT_SLOW);
1749
1820 if (!type || type == AT_MAGIC) 1750 if (!type || type == AT_MAGIC)
1821 return 0; 1751 return 0;
1822 } 1752 }
1823 } 1753 }
1824 1754
1828 1758
1829 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1759 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1830 if (tmp->type == RUNE || tmp->type == TRAP) 1760 if (tmp->type == RUNE || tmp->type == TRAP)
1831 { 1761 {
1832 spring_trap (tmp, hitter); 1762 spring_trap (tmp, hitter);
1763
1833 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1764 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1834 return 0; 1765 return 0;
1766
1835 break; 1767 break;
1836 } 1768 }
1837 } 1769 }
1838 1770
1839 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1771 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1840 { 1772 {
1841 /* FIXME: If a player is killed by a rune in a door, the 1773 /* FIXME: If a player is killed by a rune in a door, the
1842 * was_destroyed() check above doesn't return, and might get here. 1774 * destroyed() check above doesn't return, and might get here.
1843 */ 1775 */
1844 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1776 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1845 return 0; 1777 return 0;
1846 } 1778 }
1847 1779
1885 (hitter->title != NULL 1817 (hitter->title != NULL
1886 && (god = find_god (determine_god (hitter))) != NULL && god->race != NULL && strstr (god->race, undead_name) != NULL))) 1818 && (god = find_god (determine_god (hitter))) != NULL && god->race != NULL && strstr (god->race, undead_name) != NULL)))
1887 return 0; 1819 return 0;
1888 } 1820 }
1889 1821
1890 maxattacktype = type; /* initialize this to something */ 1822 maxattacktype = type; /* initialise this to something */
1891 for (attacknum = 0; attacknum < NROFATTACKS; attacknum++, attacktype = 1 << attacknum) 1823 for (attacknum = 0; attacknum < NROFATTACKS; attacknum++, attacktype = 1 << attacknum)
1892 { 1824 {
1893 /* Magic isn't really a true attack type - it gets combined with other 1825 /* Magic isn't really a true attack type - it gets combined with other
1894 * attack types. As such, skip it over. However, if magic is 1826 * attack types. As such, skip it over. However, if magic is
1895 * the only attacktype in the group, then still attack with it 1827 * the only attacktype in the group, then still attack with it
1956 1888
1957#ifdef ATTACK_DEBUG 1889#ifdef ATTACK_DEBUG
1958 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam); 1890 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1959#endif 1891#endif
1960 1892
1961 if (get_owner (hitter)) 1893 if (hitter->owner)
1962 op->enemy = hitter->owner; 1894 op->enemy = hitter->owner;
1963 else if (QUERY_FLAG (hitter, FLAG_ALIVE)) 1895 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1964 op->enemy = hitter; 1896 op->enemy = hitter;
1965 1897
1966 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER) 1898 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1991 1923
1992 if (QUERY_FLAG (op, FLAG_TEAR_DOWN)) 1924 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1993 { 1925 {
1994 if (maxdam) 1926 if (maxdam)
1995 tear_down_wall (op); 1927 tear_down_wall (op);
1928
1996 return maxdam; /* nothing more to do for wall */ 1929 return maxdam; /* nothing more to do for wall */
1997 } 1930 }
1998 1931
1999 /* See if the creature has been killed */ 1932 /* See if the creature has been killed */
2000 rtn_kill = kill_object (op, maxdam, hitter, type); 1933 rtn_kill = kill_object (op, maxdam, hitter, type);
2008 */ 1941 */
2009 if (QUERY_FLAG (hitter, FLAG_ONE_HIT)) 1942 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
2010 { 1943 {
2011 if (QUERY_FLAG (hitter, FLAG_FRIENDLY)) 1944 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
2012 remove_friendly_object (hitter); 1945 remove_friendly_object (hitter);
2013 remove_ob (hitter); 1946
2014 free_object (hitter); 1947 hitter->destroy ();
2015 } 1948 }
2016 /* Lets handle creatures that are splitting now */ 1949 /* Lets handle creatures that are splitting now */
2017 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING)) 1950 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
2018 { 1951 {
2019 int i; 1952 int i;
2020 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY); 1953 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
2021 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE); 1954 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
2022 object *owner = get_owner (op); 1955 object *owner = op->owner;
2023 1956
2024 if (!op->other_arch) 1957 if (!op->other_arch)
2025 { 1958 {
2026 LOG (llevError, "SPLITTING without other_arch error.\n"); 1959 LOG (llevError, "SPLITTING without other_arch error.\n");
2027 return maxdam; 1960 return maxdam;
2028 } 1961 }
1962
2029 remove_ob (op); 1963 op->remove ();
1964
2030 for (i = 0; i < NROFNEWOBJS (op); i++) 1965 for (i = 0; i < NROFNEWOBJS (op); i++)
2031 { /* This doesn't handle op->more yet */ 1966 { /* This doesn't handle op->more yet */
2032 object *tmp = arch_to_object (op->other_arch); 1967 object *tmp = arch_to_object (op->other_arch);
2033 int j; 1968 int j;
2034 1969
2035 tmp->stats.hp = op->stats.hp; 1970 tmp->stats.hp = op->stats.hp;
1971
2036 if (friendly) 1972 if (friendly)
2037 { 1973 {
2038 SET_FLAG (tmp, FLAG_FRIENDLY);
2039 add_friendly_object (tmp); 1974 add_friendly_object (tmp);
2040 tmp->attack_movement = PETMOVE; 1975 tmp->attack_movement = PETMOVE;
1976
2041 if (owner != NULL) 1977 if (owner)
2042 set_owner (tmp, owner); 1978 tmp->set_owner (owner);
2043 } 1979 }
1980
2044 if (unaggressive) 1981 if (unaggressive)
2045 SET_FLAG (tmp, FLAG_UNAGGRESSIVE); 1982 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1983
2046 j = find_first_free_spot (tmp, op->map, op->x, op->y); 1984 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1985
2047 if (j == -1) /* No spot to put this monster */ 1986 if (j == -1) /* No spot to put this monster */
2048 free_object (tmp); 1987 tmp->destroy ();
2049 else 1988 else
2050 { 1989 {
2051 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 1990 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
2052 insert_ob_in_map (tmp, op->map, NULL, 0); 1991 insert_ob_in_map (tmp, op->map, NULL, 0);
2053 } 1992 }
2054 } 1993 }
2055 if (friendly) 1994
2056 remove_friendly_object (op); 1995 op->destroy ();
2057 free_object (op);
2058 } 1996 }
2059 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10) 1997 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2060 { 1998 hitter->destroy ();
2061 remove_ob (hitter); 1999
2062 free_object (hitter);
2063 }
2064 return maxdam; 2000 return maxdam;
2065} 2001}
2066 2002
2067 2003
2068void 2004void
2069poison_player (object *op, object *hitter, int dam) 2005poison_player (object *op, object *hitter, int dam)
2070{ 2006{
2071 archetype *at = find_archetype ("poisoning"); 2007 archetype *at = archetype::find ("poisoning");
2072 object *tmp = present_arch_in_ob (at, op); 2008 object *tmp = present_arch_in_ob (at, op);
2073 2009
2074 if (tmp == NULL) 2010 if (tmp == NULL)
2075 { 2011 {
2076 if ((tmp = arch_to_object (at)) == NULL) 2012 if ((tmp = arch_to_object (at)) == NULL)
2089 if (QUERY_FLAG (hitter, FLAG_ALIVE)) 2025 if (QUERY_FLAG (hitter, FLAG_ALIVE))
2090 tmp->stats.dam += hitter->level / 2; 2026 tmp->stats.dam += hitter->level / 2;
2091 else 2027 else
2092 tmp->stats.dam = dam; 2028 tmp->stats.dam = dam;
2093 2029
2094 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */ 2030 tmp->set_owner (hitter); /* so we get credit for poisoning kills */
2095 if (hitter->skill && hitter->skill != tmp->skill) 2031 if (hitter->skill && hitter->skill != tmp->skill)
2096 { 2032 {
2097 tmp->skill = hitter->skill; 2033 tmp->skill = hitter->skill;
2098 } 2034 }
2099 2035
2105 tmp->stats.Con = MAX (-(dam / 4 + 1), -10); 2041 tmp->stats.Con = MAX (-(dam / 4 + 1), -10);
2106 tmp->stats.Str = MAX (-(dam / 3 + 2), -10); 2042 tmp->stats.Str = MAX (-(dam / 3 + 2), -10);
2107 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10); 2043 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10);
2108 tmp->stats.Int = MAX (-dam / 7, -10); 2044 tmp->stats.Int = MAX (-dam / 7, -10);
2109 SET_FLAG (tmp, FLAG_APPLIED); 2045 SET_FLAG (tmp, FLAG_APPLIED);
2110 fix_player (op); 2046 op->update_stats ();
2111 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill."); 2047 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
2112 } 2048 }
2113 if (hitter->type == PLAYER) 2049 if (hitter->type == PLAYER)
2114 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); 2050 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
2115 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 2051 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
2116 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name); 2052 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
2117 } 2053 }
2118 tmp->speed_left = 0; 2054 tmp->speed_left = 0;
2119 } 2055 }
2120 else 2056 else
2122} 2058}
2123 2059
2124void 2060void
2125slow_player (object *op, object *hitter, int dam) 2061slow_player (object *op, object *hitter, int dam)
2126{ 2062{
2127 archetype *at = find_archetype ("slowness"); 2063 archetype *at = archetype::find ("slowness");
2128 object *tmp; 2064 object *tmp;
2129 2065
2130 if (at == NULL) 2066 if (at == NULL)
2131 { 2067 {
2132 LOG (llevError, "Can't find slowness archetype.\n"); 2068 LOG (llevError, "Can't find slowness archetype.\n");
2139 } 2075 }
2140 else 2076 else
2141 tmp->stats.food++; 2077 tmp->stats.food++;
2142 SET_FLAG (tmp, FLAG_APPLIED); 2078 SET_FLAG (tmp, FLAG_APPLIED);
2143 tmp->speed_left = 0; 2079 tmp->speed_left = 0;
2144 fix_player (op); 2080 op->update_stats ();
2145} 2081}
2146 2082
2147void 2083void
2148confuse_player (object *op, object *hitter, int dam) 2084confuse_player (object *op, object *hitter, int dam)
2149{ 2085{
2193 */ 2129 */
2194 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100; 2130 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100;
2195 2131
2196 tmp = insert_ob_in_ob (tmp, op); 2132 tmp = insert_ob_in_ob (tmp, op);
2197 change_abil (op, tmp); /* Mostly to display any messages */ 2133 change_abil (op, tmp); /* Mostly to display any messages */
2198 fix_player (op); /* This takes care of some other stuff */ 2134 op->update_stats (); /* This takes care of some other stuff */
2199 2135
2200 if (hitter->owner) 2136 if (hitter->owner)
2201 owner = get_owner (hitter); 2137 owner = hitter->owner;
2202 else 2138 else
2203 owner = hitter; 2139 owner = hitter;
2204 2140
2205 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op)); 2141 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2206 } 2142 }
2352 } 2288 }
2353 2289
2354 /* aimed missiles use the owning object's sight */ 2290 /* aimed missiles use the owning object's sight */
2355 if (is_aimed_missile (hitter)) 2291 if (is_aimed_missile (hitter))
2356 { 2292 {
2357 if ((attacker = get_owner (hitter)) == NULL) 2293 if ((attacker = hitter->owner) == NULL)
2358 attacker = hitter; 2294 attacker = hitter;
2359 /* A player who saves but hasn't quit still could have objects 2295 /* A player who saves but hasn't quit still could have objects
2360 * owned by him - need to handle that case to avoid crashes. 2296 * owned by him - need to handle that case to avoid crashes.
2361 */ 2297 */
2362 if (QUERY_FLAG (attacker, FLAG_REMOVED)) 2298 if (QUERY_FLAG (attacker, FLAG_REMOVED))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines