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.35 by root, Sun Dec 31 10:28:36 2006 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
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 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
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 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>
28*/ 22*/
29#include <assert.h> 23#include <assert.h>
30#include <global.h> 24#include <global.h>
31#include <living.h> 25#include <living.h>
32#include <material.h> 26#include <material.h>
78 esrv_send_item (op->env, op); 72 esrv_send_item (op->env, op);
79 } 73 }
80 } 74 }
81} 75}
82 76
83
84
85/* did_make_save_item just checks to make sure the item actually 77/* 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 78 * made its saving throw based on the tables. It does not take
87 * any further action (like destroying the item). 79 * any further action (like destroying the item).
88 */ 80 */
89
90int 81int
91did_make_save_item (object *op, int type, object *originator) 82did_make_save_item (object *op, int type, object *originator)
92{ 83{
93 int i, roll, saves = 0, attacks = 0, number; 84 int i, roll, saves = 0, attacks = 0, number;
94 materialtype_t *mt; 85 materialtype_t *mt;
95 86
96 if (op->materialname == NULL) 87 if (op->materialname == NULL)
97 { 88 {
98 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next) 89 for (mt = materialt; mt != NULL && mt->next != NULL; mt = mt->next)
99 {
100 if (op->material & mt->material) 90 if (op->material & mt->material)
101 break; 91 break;
102 }
103 } 92 }
104 else 93 else
105 mt = name_to_material (op->materialname); 94 mt = name_to_material (op->materialname);
106 if (mt == NULL) 95 if (mt == NULL)
107 return TRUE; 96 return TRUE;
158{ 147{
159 if (!did_make_save_item (op, type, originator)) 148 if (!did_make_save_item (op, type, originator))
160 { 149 {
161 object *env = op->env; 150 object *env = op->env;
162 int x = op->x, y = op->y; 151 int x = op->x, y = op->y;
163 mapstruct *m = op->map; 152 maptile *m = op->map;
164 153
165 op = stop_item (op); 154 op = stop_item (op);
166 if (op == NULL) 155 if (op == NULL)
167 return; 156 return;
168 157
218 } 207 }
219 else 208 else
220 { 209 {
221 if (op->env) 210 if (op->env)
222 { 211 {
223 object *tmp = is_player_inv (op->env); 212 object *tmp = op->in_player ();
224 213
225 if (tmp) 214 if (tmp)
226 esrv_del_item (tmp->contr, op->count); 215 esrv_del_item (tmp->contr, op->count);
227 } 216 }
228 217
229 if (!QUERY_FLAG (op, FLAG_REMOVED)) 218 op->destroy ();
230 remove_ob (op);
231
232 free_object (op);
233 } 219 }
234 220
235 if (type & (AT_FIRE | AT_ELECTRICITY)) 221 if (type & (AT_FIRE | AT_ELECTRICITY))
236 if (env) 222 if (env)
237 { 223 {
247 233
248 /* The value of 50 is arbitrary. */ 234 /* The value of 50 is arbitrary. */
249 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2)) 235 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
250 { 236 {
251 object *tmp; 237 object *tmp;
252 archetype *at = find_archetype ("icecube"); 238 archetype *at = archetype::find ("icecube");
253 239
254 if (at == NULL) 240 if (at == NULL)
255 return; 241 return;
256 242
257 op = stop_item (op); 243 op = stop_item (op);
270 tmp->move_slow = 0; 256 tmp->move_slow = 0;
271 insert_ob_in_map (tmp, op->map, originator, 0); 257 insert_ob_in_map (tmp, op->map, originator, 0);
272 } 258 }
273 259
274 if (!QUERY_FLAG (op, FLAG_REMOVED)) 260 if (!QUERY_FLAG (op, FLAG_REMOVED))
275 remove_ob (op); 261 op->remove ();
276 262
277 insert_ob_in_ob (op, tmp); 263 insert_ob_in_ob (op, tmp);
278 return; 264 return;
279 } 265 }
280} 266}
288 274
289int 275int
290hit_map (object *op, int dir, int type, int full_hit) 276hit_map (object *op, int dir, int type, int full_hit)
291{ 277{
292 object *tmp, *next; 278 object *tmp, *next;
293 mapstruct *map; 279 maptile *map;
294 sint16 x, y; 280 sint16 x, y;
295 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ 281 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
296 282
297 tag_t op_tag, next_tag = 0;
298
299 if (QUERY_FLAG (op, FLAG_FREED)) 283 if (QUERY_FLAG (op, FLAG_FREED))
300 { 284 {
301 LOG (llevError, "BUG: hit_map(): free object\n"); 285 LOG (llevError, "BUG: hit_map(): free object\n");
302 return 0; 286 return 0;
303 } 287 }
314 return 0; 298 return 0;
315 } 299 }
316 300
317 if (op->head) 301 if (op->head)
318 op = op->head; 302 op = op->head;
319
320 op_tag = op->count;
321 303
322 map = op->map; 304 map = op->map;
323 x = op->x + freearr_x[dir]; 305 x = op->x + freearr_x[dir];
324 y = op->y + freearr_y[dir]; 306 y = op->y + freearr_y[dir];
325 307
352 shuffle_attack (op, 1); /*1 flag tells it to change the face */ 334 shuffle_attack (op, 1); /*1 flag tells it to change the face */
353 update_object (op, UP_OBJ_FACE); 335 update_object (op, UP_OBJ_FACE);
354 type &= ~AT_CHAOS; 336 type &= ~AT_CHAOS;
355 } 337 }
356 338
357 next = get_map_ob (map, x, y); 339 next = GET_MAP_OB (map, x, y);
358 if (next)
359 next_tag = next->count;
360 340
361 while (next) 341 while (next)
362 { 342 {
363 if (was_destroyed (next, next_tag)) 343 if (next->destroyed ())
364 { 344 {
365 /* There may still be objects that were above 'next', but there is no 345 /* 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 346 * simple way to find out short of copying all object references and
367 * tags into a temporary array before we start processing the first 347 * tags into a temporary array before we start processing the first
368 * object. That's why we just abort. 348 * object. That's why we just abort.
376 } 356 }
377 357
378 tmp = next; 358 tmp = next;
379 next = tmp->above; 359 next = tmp->above;
380 360
381 if (next) 361 if (tmp->destroyed ())
382 next_tag = next->count;
383
384 if (QUERY_FLAG (tmp, FLAG_FREED))
385 { 362 {
386 LOG (llevError, "BUG: hit_map(): found freed object\n"); 363 LOG (llevError, "BUG: hit_map(): found freed object\n");
387 break; 364 break;
388 } 365 }
389 366
396 373
397 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 374 if (QUERY_FLAG (tmp, FLAG_ALIVE))
398 { 375 {
399 hit_player (tmp, op->stats.dam, op, type, full_hit); 376 hit_player (tmp, op->stats.dam, op, type, full_hit);
400 retflag |= 1; 377 retflag |= 1;
401 if (was_destroyed (op, op_tag)) 378 if (op->destroyed ())
402 break; 379 break;
403 } 380 }
404 381
405 /* Here we are potentially destroying an object. If the object has 382 /* 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 383 * NO_PASS set, it is also immune - you can't destroy walls. Note
410 * destroyed right now. 387 * destroyed right now.
411 */ 388 */
412 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block) 389 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
413 { 390 {
414 save_throw_object (tmp, type, op); 391 save_throw_object (tmp, type, op);
415 if (was_destroyed (op, op_tag)) 392 if (op->destroyed ())
416 break; 393 break;
417 } 394 }
418 } 395 }
419 396
420 return 0; 397 return 0;
423void 400void
424attack_message (int dam, int type, object *op, object *hitter) 401attack_message (int dam, int type, object *op, object *hitter)
425{ 402{
426 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 403 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
427 int i, found = 0; 404 int i, found = 0;
428 mapstruct *map; 405 maptile *map;
429 object *next, *tmp; 406 object *next, *tmp;
430 407
431 /* put in a few special messages for some of the common attacktypes 408 /* put in a few special messages for some of the common attacktypes
432 * a player might have. For example, fire, electric, cold, etc 409 * a player might have. For example, fire, electric, cold, etc
433 * [garbled 20010919] 410 * [garbled 20010919]
450 sprintf (buf1, "missed %s", &op->name); 427 sprintf (buf1, "missed %s", &op->name);
451 sprintf (buf2, " misses"); 428 sprintf (buf2, " misses");
452 found++; 429 found++;
453 } 430 }
454 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM || 431 else if ((hitter->type == DISEASE || hitter->type == SYMPTOM ||
455 hitter->type == POISONING || (type & AT_POISON && IS_LIVE (op))) && !found) 432 hitter->type == POISONING || (type & AT_POISON && op->is_alive ())) && !found)
456 { 433 {
457 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_SUFFER][i].level != -1; i++) 434 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) 435 if (dam < attack_mess[ATM_SUFFER][i].level || attack_mess[ATM_SUFFER][i + 1].level == -1)
459 { 436 {
460 sprintf (buf1, "%s %s%s", attack_mess[ATM_SUFFER][i].buf1, &op->name, attack_mess[ATM_SUFFER][i].buf2); 437 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); 449 strcpy (buf2, attack_mess[ATM_DOOR][i].buf3);
473 found++; 450 found++;
474 break; 451 break;
475 } 452 }
476 } 453 }
477 else if (hitter->type == PLAYER && IS_LIVE (op)) 454 else if (hitter->type == PLAYER && op->is_alive ())
478 { 455 {
479 if (USING_SKILL (hitter, SK_KARATE)) 456 if (USING_SKILL (hitter, SK_KARATE))
480 { 457 {
481 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_KARATE][i].level != -1; i++) 458 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) 459 if (dam < attack_mess[ATM_KARATE][i].level || attack_mess[ATM_KARATE][i + 1].level == -1)
508 found++; 485 found++;
509 break; 486 break;
510 } 487 }
511 } 488 }
512 } 489 }
490
513 if (found) 491 if (found)
514 { 492 {
515 /* done */ 493 /* done */
516 } 494 }
517 else if (IS_ARROW (hitter) && (type == AT_PHYSICAL || type == AT_MAGIC)) 495 else if (hitter->is_arrow () && (type == AT_PHYSICAL || type == AT_MAGIC))
518 { 496 {
519 sprintf (buf1, "hit"); /* just in case */ 497 sprintf (buf1, "hit"); /* just in case */
520 for (i = 0; i < MAXATTACKMESS; i++) 498 for (i = 0; i < MAXATTACKMESS; i++)
521 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1) 499 if (dam < attack_mess[ATM_ARROW][i].level || attack_mess[ATM_ARROW][i + 1].level == -1)
522 { 500 {
523 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3); 501 strcpy (buf2, attack_mess[ATM_ARROW][i].buf3);
524 found++; 502 found++;
525 break; 503 break;
526 } 504 }
527 } 505 }
528 else if (type & AT_DRAIN && IS_LIVE (op)) 506 else if (type & AT_DRAIN && op->is_alive ())
529 { 507 {
530 /* drain is first, because some items have multiple attypes */ 508 /* drain is first, because some items have multiple attypes */
531 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_DRAIN][i].level != -1; i++) 509 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) 510 if (dam < attack_mess[ATM_DRAIN][i].level || attack_mess[ATM_DRAIN][i + 1].level == -1)
533 { 511 {
535 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3); 513 strcpy (buf2, attack_mess[ATM_DRAIN][i].buf3);
536 found++; 514 found++;
537 break; 515 break;
538 } 516 }
539 } 517 }
540 else if (type & AT_ELECTRICITY && IS_LIVE (op)) 518 else if (type & AT_ELECTRICITY && op->is_alive ())
541 { 519 {
542 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_ELEC][i].level != -1; i++) 520 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) 521 if (dam < attack_mess[ATM_ELEC][i].level || attack_mess[ATM_ELEC][i + 1].level == -1)
544 { 522 {
545 sprintf (buf1, "%s %s%s", attack_mess[ATM_ELEC][i].buf1, &op->name, attack_mess[ATM_ELEC][i].buf2); 523 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); 524 strcpy (buf2, attack_mess[ATM_ELEC][i].buf3);
547 found++; 525 found++;
548 break; 526 break;
549 } 527 }
550 } 528 }
551 else if (type & AT_COLD && IS_LIVE (op)) 529 else if (type & AT_COLD && op->is_alive ())
552 { 530 {
553 for (i = 0; i < MAXATTACKMESS && attack_mess[ATM_COLD][i].level != -1; i++) 531 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) 532 if (dam < attack_mess[ATM_COLD][i].level || attack_mess[ATM_COLD][i + 1].level == -1)
555 { 533 {
556 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2); 534 sprintf (buf1, "%s %s%s", attack_mess[ATM_COLD][i].buf1, &op->name, attack_mess[ATM_COLD][i].buf2);
633 strcpy (buf1, "hit"); 611 strcpy (buf1, "hit");
634 strcpy (buf2, " hits"); 612 strcpy (buf2, " hits");
635 } 613 }
636 614
637 /* bail out if a monster is casting spells */ 615 /* bail out if a monster is casting spells */
638 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER))) 616 if (!(hitter->type == PLAYER || (hitter->owner != NULL && hitter->owner->type == PLAYER)))
639 return; 617 return;
640 618
641 /* scale down magic considerably. */ 619 /* scale down magic considerably. */
642 if (type & AT_MAGIC && rndm (0, 5)) 620 if (type & AT_MAGIC && rndm (0, 5))
643 return; 621 return;
644 622
645 /* Did a player hurt another player? Inform both! */ 623 /* Did a player hurt another player? Inform both! */
646 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER) 624 if (op->type == PLAYER && (hitter->owner == NULL ? hitter->type : hitter->owner->type) == PLAYER)
647 { 625 {
648 if (get_owner (hitter) != NULL) 626 if (hitter->owner != NULL)
649 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2); 627 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
650 else 628 else
651 { 629 {
652 sprintf (buf, "%s%s you.", &hitter->name, buf2); 630 sprintf (buf, "%s%s you.", &hitter->name, buf2);
653 if (dam != 0) 631 if (dam != 0)
675 else 653 else
676 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0); 654 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
677 } 655 }
678 new_draw_info (NDI_BLACK, 0, hitter, buf); 656 new_draw_info (NDI_BLACK, 0, hitter, buf);
679 } 657 }
680 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 658 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
681 { 659 {
682 /* look for stacked spells and start reducing the message chances */ 660 /* 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)) 661 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
684 { 662 {
685 i = 4; 663 i = 4;
686 map = hitter->map; 664 map = hitter->map;
687 if (out_of_map (map, hitter->x, hitter->y)) 665 if (out_of_map (map, hitter->x, hitter->y))
688 return; 666 return;
689 next = get_map_ob (map, hitter->x, hitter->y); 667 next = GET_MAP_OB (map, hitter->x, hitter->y);
690 if (next) 668 if (next)
691 while (next) 669 while (next)
692 { 670 {
693 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE)) 671 if (next->type == SPELL_EFFECT && (next->subtype == SP_EXPLOSION || next->subtype == SP_BULLET || next->subtype == SP_CONE))
694 i *= 3; 672 i *= 3;
760attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 738attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
761{ 739{
762 int simple_attack, roll, dam = 0; 740 int simple_attack, roll, dam = 0;
763 uint32 type; 741 uint32 type;
764 shstr op_name; 742 shstr op_name;
765 tag_t op_tag, hitter_tag;
766 743
767 if (get_attack_mode (&op, &hitter, &simple_attack)) 744 if (get_attack_mode (&op, &hitter, &simple_attack))
768 goto error; 745 goto error;
769 746
770 if (hitter->current_weapon) 747 if (hitter->current_weapon)
771 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 748 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
772 return RESULT_INT (0); 749 return RESULT_INT (0);
773 750
774 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 751 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
775 return RESULT_INT (0); 752 return RESULT_INT (0);
776
777 op_tag = op->count;
778 hitter_tag = hitter->count;
779 753
780 /* 754 /*
781 * A little check to make it more difficult to dance forward and back 755 * A little check to make it more difficult to dance forward and back
782 * to avoid ever being hit by monsters. 756 * to avoid ever being hit by monsters.
783 */ 757 */
788 * which then gets here again. By decreasing the speed before 762 * which then gets here again. By decreasing the speed before
789 * we call process_object, the 'if' statement above will fail. 763 * we call process_object, the 'if' statement above will fail.
790 */ 764 */
791 op->speed_left--; 765 op->speed_left--;
792 process_object (op); 766 process_object (op);
767
793 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 768 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
794 goto error; 769 goto error;
795 } 770 }
796 771
797 op_name = op->name; 772 op_name = op->name;
798 773
832 if (QUERY_FLAG (op, FLAG_SLEEP)) 807 if (QUERY_FLAG (op, FLAG_SLEEP))
833 CLEAR_FLAG (op, FLAG_SLEEP); 808 CLEAR_FLAG (op, FLAG_SLEEP);
834 809
835 /* If the victim can't see the attacker, it may alert others 810 /* If the victim can't see the attacker, it may alert others
836 * for help. */ 811 * for help. */
837 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int)) 812 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !op->owner && rndm (0, op->stats.Int))
838 npc_call_help (op); 813 npc_call_help (op);
839 814
840 /* if you were hidden and hit by a creature, you are discovered */ 815 /* if you were hidden and hit by a creature, you are discovered */
841 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) 816 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
842 { 817 {
849 * when they hit the victim. For things like thrown daggers, 824 * when they hit the victim. For things like thrown daggers,
850 * this sets 'hitter' to the actual dagger, and not the 825 * this sets 'hitter' to the actual dagger, and not the
851 * wrapper object. 826 * wrapper object.
852 */ 827 */
853 thrown_item_effect (hitter, op); 828 thrown_item_effect (hitter, op);
829
854 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 830 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
855 goto leave; 831 goto leave;
856 } 832 }
857 833
858 /* Need to do at least 1 damage, otherwise there is no point 834 /* Need to do at least 1 damage, otherwise there is no point
859 * to go further and it will cause FPE's below. 835 * to go further and it will cause FPE's below.
860 */ 836 */
861 if (hitdam <= 0) 837 if (hitdam <= 0)
862 hitdam = 1; 838 hitdam = 1;
863 839
864 type = hitter->attacktype; 840 type = hitter->attacktype;
841
865 if (!type) 842 if (!type)
866 type = AT_PHYSICAL; 843 type = AT_PHYSICAL;
844
867 /* Handle monsters that hit back */ 845 /* Handle monsters that hit back */
868 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 846 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
869 { 847 {
870 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 848 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
871 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 849 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
850
872 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 851 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
852
873 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 853 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
874 goto leave; 854 goto leave;
875 } 855 }
876 856
877 /* In the new attack code, it should handle multiple attack 857 /* In the new attack code, it should handle multiple attack
878 * types in its area, so remove it from here. 858 * types in its area, so remove it from here.
879 */ 859 */
880 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 860 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
861
881 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 862 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
882 goto leave; 863 goto leave;
883 } /* end of if hitter hit op */ 864 } /* end of if hitter hit op */
884 /* if we missed, dam=0 */ 865 /* if we missed, dam=0 */
885 866
886 /*attack_message(dam, type, op, hitter); */ 867 /*attack_message(dam, type, op, hitter); */
920 if (op->weight <= 5000 && tmp->stats.hp >= 0) 901 if (op->weight <= 5000 && tmp->stats.hp >= 0)
921 { 902 {
922 if (tmp->head != NULL) 903 if (tmp->head != NULL)
923 tmp = tmp->head; 904 tmp = tmp->head;
924 905
925 remove_ob (op); 906 op->remove ();
926 op = insert_ob_in_ob (op, tmp); 907 op = insert_ob_in_ob (op, tmp);
927 908
928 if (tmp->type == PLAYER) 909 if (tmp->type == PLAYER)
929 esrv_send_item (tmp, op); 910 esrv_send_item (tmp, op);
930 911
943object * 924object *
944hit_with_arrow (object *op, object *victim) 925hit_with_arrow (object *op, object *victim)
945{ 926{
946 object *container, *hitter; 927 object *container, *hitter;
947 int hit_something = 0; 928 int hit_something = 0;
948 tag_t victim_tag, hitter_tag;
949 sint16 victim_x, victim_y;
950 929
951 /* Disassemble missile */ 930 /* Disassemble missile */
952 if (op->inv) 931 if (op->inv)
953 { 932 {
954 container = op; 933 container = op;
955 hitter = op->inv; 934 hitter = op->inv;
956 remove_ob (hitter); 935 hitter->remove ();
957 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON); 936 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 937 /* 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 938 * 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 939 * removed at the end of this function must be able to deal with empty
961 * THROWN_OBJs. */ 940 * THROWN_OBJs. */
962 } 941 }
963 else 942 else
964 { 943 {
965 container = NULL; 944 container = 0;
966 hitter = op; 945 hitter = op;
967 } 946 }
968 947
969 /* Try to hit victim */ 948 /* 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); 949 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
976 950
977 /* Arrow attacks door, rune of summoning is triggered, demon is put on 951 /* Arrow attacks door, rune of summoning is triggered, demon is put on
978 * arrow, move_apply() calls this function, arrow sticks in demon, 952 * arrow, move_apply() calls this function, arrow sticks in demon,
979 * attack_ob_simple() returns, and we've got an arrow that still exists 953 * 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 954 * but is no longer on the map. Ugh. (Beware: Such things can happen at
981 * other places as well!) 955 * other places as well!)
982 */ 956 */
983 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 957 if (hitter->destroyed () || hitter->env != NULL)
984 { 958 {
985 if (container) 959 if (container)
986 { 960 {
987 remove_ob (container); 961 container->remove ();
988 free_object (container); 962 container->destroy ();
989 } 963 }
964
990 return NULL; 965 return 0;
991 } 966 }
992 967
993 /* Missile hit victim */ 968 /* Missile hit victim */
994 /* if the speed is > 10, then this is a fast moving arrow, we go straight 969 /* if the speed is > 10, then this is a fast moving arrow, we go straight
995 * through the target 970 * through the target
996 */ 971 */
997 if (hit_something && op->speed <= 10.0) 972 if (hit_something && op->speed <= 10.0)
998 { 973 {
999 /* Stop arrow */ 974 /* Stop arrow */
1000 if (container == NULL) 975 if (!container)
1001 { 976 {
1002 hitter = fix_stopped_arrow (hitter); 977 hitter = fix_stopped_arrow (hitter);
1003 if (hitter == NULL) 978 if (!hitter)
1004 return NULL; 979 return 0;
1005 } 980 }
1006 else 981 else
1007 { 982 container->destroy ();
1008 remove_ob (container);
1009 free_object (container);
1010 }
1011 983
1012 /* Try to stick arrow into victim */ 984 /* Try to stick arrow into victim */
1013 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 985 if (!victim->destroyed () && stick_arrow (hitter, victim))
1014 return NULL; 986 return 0;
1015 987
1016 /* Else try to put arrow on victim's map square 988 /* Else try to put arrow on victim's map square
1017 * remove check for P_WALL here. If the arrow got to this 989 * remove check for P_WALL here. If the arrow got to this
1018 * space, that is good enough - with the new movement code, 990 * space, that is good enough - with the new movement code,
1019 * there is now the potential for lots of spaces where something 991 * there is now the potential for lots of spaces where something
1020 * can fly over but not otherwise move over. What is the correct 992 * can fly over but not otherwise move over. What is the correct
1021 * way to handle those otherwise? 993 * way to handle those otherwise?
1022 */ 994 */
1023 if (victim_x != hitter->x || victim_y != hitter->y) 995 if (victim->x != hitter->x || victim->y != hitter->y)
1024 { 996 {
1025 remove_ob (hitter); 997 hitter->remove ();
1026 hitter->x = victim_x; 998 hitter->x = victim->x;
1027 hitter->y = victim_y; 999 hitter->y = victim->y;
1028 insert_ob_in_map (hitter, victim->map, hitter, 0); 1000 insert_ob_in_map (hitter, victim->map, hitter, 0);
1029 } 1001 }
1030 else 1002 else
1031 {
1032 /* Else leave arrow where it is */ 1003 /* Else leave arrow where it is */
1033 merge_ob (hitter, NULL); 1004 merge_ob (hitter, NULL);
1034 } 1005
1035 return NULL; 1006 return 0;
1036 } 1007 }
1037 1008
1038 if (hit_something && op->speed >= 10.0) 1009 if (hit_something && op->speed >= 10.0)
1039 op->speed -= 1.0; 1010 op->speed -= 1.0;
1040 1011
1041 /* Missile missed victim - reassemble missile */ 1012 /* Missile missed victim - reassemble missile */
1042 if (container) 1013 if (container)
1043 { 1014 {
1044 remove_ob (hitter); 1015 hitter->remove ();
1045 insert_ob_in_ob (hitter, container); 1016 insert_ob_in_ob (hitter, container);
1046 } 1017 }
1018
1047 return op; 1019 return op;
1048} 1020}
1049 1021
1050 1022
1051void 1023void
1060 } 1032 }
1061 else if (!GET_ANIM_ID (op)) 1033 else if (!GET_ANIM_ID (op))
1062 { 1034 {
1063 /* Object has been called - no animations, so remove it */ 1035 /* Object has been called - no animations, so remove it */
1064 if (op->stats.hp < 0) 1036 if (op->stats.hp < 0)
1037 op->destroy ();
1065 { 1038
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 */ 1039 return; /* no animations, so nothing more to do */
1072 } 1040 }
1041
1073 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp; 1042 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
1043
1074 if (perc >= (int) NUM_ANIMATIONS (op)) 1044 if (perc >= (int) NUM_ANIMATIONS (op))
1075 perc = NUM_ANIMATIONS (op) - 1; 1045 perc = NUM_ANIMATIONS (op) - 1;
1076 else if (perc < 1) 1046 else if (perc < 1)
1077 perc = 1; 1047 perc = 1;
1048
1078 SET_ANIMATION (op, perc); 1049 SET_ANIMATION (op, perc);
1079 update_object (op, UP_OBJ_FACE); 1050 update_object (op, UP_OBJ_FACE);
1051
1080 if (perc == NUM_ANIMATIONS (op) - 1) 1052 if (perc == NUM_ANIMATIONS (op) - 1)
1081 { /* Reached the last animation */ 1053 { /* Reached the last animation */
1082 if (op->face == blank_face) 1054 if (op->face == blank_face)
1083 {
1084 /* If the last face is blank, remove the ob */ 1055 /* If the last face is blank, remove the ob */
1085 remove_ob (op); /* Should update LOS */ 1056 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 1057 else
1093 { /* The last face was not blank, leave an image */ 1058 { /* The last face was not blank, leave an image */
1094 CLEAR_FLAG (op, FLAG_BLOCKSVIEW); 1059 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
1095 update_all_los (op->map, op->x, op->y); 1060 update_all_los (op->map, op->x, op->y);
1096 op->move_block = 0; 1061 op->move_block = 0;
1100} 1065}
1101 1066
1102void 1067void
1103scare_creature (object *target, object *hitter) 1068scare_creature (object *target, object *hitter)
1104{ 1069{
1105 object *owner = get_owner (hitter); 1070 object *owner = hitter->owner;
1106 1071
1107 if (!owner) 1072 if (!owner)
1108 owner = hitter; 1073 owner = hitter;
1109 1074
1110 SET_FLAG (target, FLAG_SCARED); 1075 SET_FLAG (target, FLAG_SCARED);
1225 else if (attacknum == ATNR_FEAR) 1190 else if (attacknum == ATNR_FEAR)
1226 scare_creature (op, hitter); 1191 scare_creature (op, hitter);
1227 else if (attacknum == ATNR_CANCELLATION) 1192 else if (attacknum == ATNR_CANCELLATION)
1228 cancellation (op); 1193 cancellation (op);
1229 else if (attacknum == ATNR_DEPLETE) 1194 else if (attacknum == ATNR_DEPLETE)
1230 drain_stat (op); 1195 op->drain_stat ();
1231 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR)) 1196 else if (attacknum == ATNR_BLIND && !QUERY_FLAG (op, FLAG_UNDEAD) && !QUERY_FLAG (op, FLAG_GENERATOR))
1232 blind_player (op, hitter, dam); 1197 blind_player (op, hitter, dam);
1233 } 1198 }
1234 dam = 0; /* These are all effects and don't do real damage */ 1199 dam = 0; /* These are all effects and don't do real damage */
1235 } 1200 }
1274 if (op->type == PLAYER) 1239 if (op->type == PLAYER)
1275 esrv_send_item (op, tmp); 1240 esrv_send_item (op, tmp);
1276 } 1241 }
1277 } 1242 }
1278 if (flag) 1243 if (flag)
1279 fix_player (op); /* Something was corroded */ 1244 op->update_stats (); /* Something was corroded */
1280 } 1245 }
1281 } 1246 }
1282 break; 1247 break;
1283 case ATNR_DRAIN: 1248 case ATNR_DRAIN:
1284 { 1249 {
1314 * Try to credit the owner. We try to display player -> player drain 1279 * Try to credit the owner. We try to display player -> player drain
1315 * attacks, hence all the != PLAYER checks. 1280 * attacks, hence all the != PLAYER checks.
1316 */ 1281 */
1317 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1282 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1318 { 1283 {
1319 object *owner = get_owner (hitter); 1284 object *owner = hitter->owner;
1320 1285
1321 if (owner && owner != hitter) 1286 if (owner && owner != hitter)
1322 { 1287 {
1323 if (op->type != PLAYER || owner->type != PLAYER) 1288 if (op->type != PLAYER || owner->type != PLAYER)
1324 change_exp (owner, op->stats.exp / (rate * 2), 1289 change_exp (owner, op->stats.exp / (rate * 2),
1461 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW)) 1426 if (QUERY_FLAG (op, FLAG_BLOCKSVIEW))
1462 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */ 1427 update_all_los (op->map, op->x, op->y); /* makes sure los will be recalculated */
1463 1428
1464 if (op->type == DOOR) 1429 if (op->type == DOOR)
1465 { 1430 {
1466 op->speed = 0.1; 1431 op->set_speed (0.1);
1467 update_ob_speed (op);
1468 op->speed_left = -0.05; 1432 op->speed_left = -0.05;
1469 return maxdam; 1433 return maxdam;
1470 } 1434 }
1435
1471 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1436 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1472 { 1437 {
1473 remove_friendly_object (op); 1438 remove_friendly_object (op);
1439
1474 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1440 if (op->owner && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1475 {
1476 op->owner->contr->ranges[range_golem] = NULL; 1441 op->owner->contr->ranges[range_golem] = 0;
1477 op->owner->contr->golem_count = 0;
1478 }
1479 1442
1480 remove_ob (op); 1443 op->destroy ();
1481 free_object (op);
1482 return maxdam; 1444 return maxdam;
1483 } 1445 }
1484 1446
1485 /* Now lets start dealing with experience we get for killing something */ 1447 /* Now lets start dealing with experience we get for killing something */
1486 1448
1487 owner = get_owner (hitter); 1449 owner = hitter->owner;
1488 if (owner == NULL) 1450 if (!owner)
1489 owner = hitter; 1451 owner = hitter;
1490 1452
1491 /* is the victim (op) standing on battleground? */ 1453 /* is the victim (op) standing on battleground? */
1492 if (op_on_battleground (op, NULL, NULL)) 1454 if (op_on_battleground (op, NULL, NULL))
1493 battleg = 1; 1455 battleg = 1;
1513 char buf[256]; 1475 char buf[256];
1514 1476
1515 tmv = localtime (&t); 1477 tmv = localtime (&t);
1516 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv); 1478 strftime (buf, 256, "%a %b %d %H:%M:%S %Y", tmv);
1517 1479
1518 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->socket.host, query_name (op)); 1480 LOG (llevInfo, "%s PLAYER_KILL_PLAYER: %s (%s) killed %s\n", buf, &owner->name, owner->contr->ns->host, query_name (op));
1519 } 1481 }
1520 1482
1521 /* try to filter some things out - basically, if you are 1483 /* try to filter some things out - basically, if you are
1522 * killing a level 1 creature and your level 20, you 1484 * killing a level 1 creature and your level 20, you
1523 * probably don't want to see that. 1485 * probably don't want to see that.
1524 */ 1486 */
1525 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1487 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1526 { 1488 {
1527 if (owner != hitter) 1489 if (owner != hitter)
1528 {
1529 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1490 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1530 }
1531 else 1491 else
1532 {
1533 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1492 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1534 } 1493
1535 /* Only play sounds for melee kills */ 1494 /* Only play sounds for melee kills */
1536 if (hitter->type == PLAYER) 1495 if (hitter->type == PLAYER)
1537 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1496 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1538 } 1497 }
1539 1498
1544 * player that the object belonged to - so if you killed another player 1503 * player that the object belonged to - so if you killed another player
1545 * with spells, pets, whatever, there was no penalty. 1504 * with spells, pets, whatever, there was no penalty.
1546 * Changed to make luck penalty configurable in settings. 1505 * Changed to make luck penalty configurable in settings.
1547 */ 1506 */
1548 if (op->type == PLAYER && owner != op && !battleg) 1507 if (op->type == PLAYER && owner != op && !battleg)
1549 change_luck (owner, -settings.pk_luck_penalty); 1508 owner->change_luck (-settings.pk_luck_penalty);
1550 1509
1551 /* This code below deals with finding the appropriate skill 1510 /* This code below deals with finding the appropriate skill
1552 * to credit exp to. This is a bit problematic - we should 1511 * to credit exp to. This is a bit problematic - we should
1553 * probably never really have to look at current_weapon->skill 1512 * probably never really have to look at current_weapon->skill
1554 */ 1513 */
1555 skill = NULL; 1514 skill = 0;
1515
1556 if (hitter->skill && hitter->type != PLAYER) 1516 if (hitter->skill && hitter->type != PLAYER)
1557 skill = hitter->skill; 1517 skill = hitter->skill;
1558 else if (owner->chosen_skill) 1518 else if (owner->chosen_skill)
1559 { 1519 {
1560 skill = owner->chosen_skill->skill; 1520 skill = owner->chosen_skill->skill;
1579 break; 1539 break;
1580 } 1540 }
1581 } 1541 }
1582 } /* Was it a player that hit somethign */ 1542 } /* Was it a player that hit somethign */
1583 else 1543 else
1584 {
1585 skill = NULL; 1544 skill = 0;
1586 }
1587 1545
1588 /* Pet (or spell) killed something. */ 1546 /* Pet (or spell) killed something. */
1589 if (owner != hitter) 1547 if (owner != hitter)
1590 {
1591 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1548 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1592 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1549 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1593 }
1594 else 1550 else
1595 {
1596 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1551 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1597 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1552 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1598 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1553 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1599 } 1554
1600 /* These may have been set in the player code section above */ 1555 /* These may have been set in the player code section above */
1601 if (!skop) 1556 if (!skop)
1602 skop = hitter->chosen_skill; 1557 skop = hitter->chosen_skill;
1558
1603 if (!skill && skop) 1559 if (!skill && skop)
1604 skill = skop->skill; 1560 skill = skop->skill;
1605 1561
1606 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1562 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1607 1563
1608
1609 /* If you didn't kill yourself, and your not the wizard */ 1564 /* If you didn't kill yourself, and your not the wizard */
1610 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1565 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1611 { 1566 {
1612 int exp; 1567 int exp;
1613 1568
1614 /* Really don't give much experience for killing other players */ 1569 /* Really don't give much experience for killing other players */
1615 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1570 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1616 if (op->type == PLAYER) 1571 if (op->type == PLAYER)
1617 { 1572 {
1618 if (battleg) 1573 if (battleg)
1619 { 1574 {
1620 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1575 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1638 1593
1639 if (!settings.simple_exp) 1594 if (!settings.simple_exp)
1640 exp = exp / 2; 1595 exp = exp / 2;
1641 1596
1642 if (owner->type != PLAYER || owner->contr->party == NULL) 1597 if (owner->type != PLAYER || owner->contr->party == NULL)
1643 {
1644 change_exp (owner, exp, skill, 0); 1598 change_exp (owner, exp, skill, 0);
1645 }
1646 else 1599 else
1647 { 1600 {
1648 int shares = 0, count = 0; 1601 int shares = 0, count = 0;
1649
1650 player *pl; 1602 player *pl;
1651
1652 partylist *party = owner->contr->party; 1603 partylist *party = owner->contr->party;
1653 1604
1654#ifdef PARTY_KILL_LOG
1655 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1605 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1656#endif 1606
1657 for (pl = first_player; pl != NULL; pl = pl->next) 1607 for_all_players (pl)
1658 {
1659 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1608 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1660 { 1609 {
1661 count++; 1610 count++;
1662 shares += (pl->ob->level + 4); 1611 shares += (pl->ob->level + 4);
1663 } 1612 }
1664 } 1613
1665 if (count == 1 || shares > exp) 1614 if (count == 1 || shares > exp || !shares)
1666 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1615 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1667 else 1616 else
1668 { 1617 {
1669 int share = exp / shares, given = 0, nexp; 1618 int share = exp / shares, given = 0, nexp;
1670 1619
1671 for (pl = first_player; pl != NULL; pl = pl->next) 1620 for_all_players (pl)
1672 {
1673 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1621 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1674 { 1622 {
1675 nexp = (pl->ob->level + 4) * share; 1623 nexp = (pl->ob->level + 4) * share;
1676 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1624 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1677 given += nexp; 1625 given += nexp;
1678 } 1626 }
1679 } 1627
1680 exp -= given; 1628 exp -= given;
1681 /* give any remainder to the player */ 1629 /* give any remainder to the player */
1682 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1630 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1683 } 1631 }
1684 } /* else part of a party */ 1632 } /* else part of a party */
1685
1686 } /* end if person didn't kill himself */ 1633 } /* end if person didn't kill himself */
1687 1634
1688 if (op->type != PLAYER) 1635 if (op->type != PLAYER)
1689 { 1636 {
1690 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1637 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1691 { 1638 {
1692 object *owner1 = get_owner (op); 1639 object *owner1 = op->owner;
1693 1640
1694 if (owner1 != NULL && owner1->type == PLAYER) 1641 if (owner1 && owner1->type == PLAYER)
1695 { 1642 {
1696 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1643 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1697 /* Maybe we should include the owner that killed this, maybe not */ 1644 /* 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); 1645 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1699 } 1646 }
1700 1647
1701 remove_friendly_object (op); 1648 remove_friendly_object (op);
1702 } 1649 }
1703 1650
1704 remove_ob (op); 1651 op->destroy ();
1705 free_object (op);
1706 } 1652 }
1707 /* Player has been killed! */
1708 else 1653 else
1709 { 1654 {
1655 /* Player has been killed! */
1710 if (owner->type == PLAYER) 1656 if (owner->type == PLAYER)
1711 {
1712 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1657 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1713 }
1714 else 1658 else
1715 assign (op->contr->killer, hitter->name); 1659 assign (op->contr->killer, hitter->name);
1716 } 1660 }
1717 1661
1718 /* This was return -1 - that doesn't seem correct - if we return -1, process 1662 /* This was return -1 - that doesn't seem correct - if we return -1, process
1742 return 0; 1686 return 0;
1743 1687
1744 if (hitter->type == PLAYER && hitter->contr->peaceful == 1) 1688 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1745 return 1; 1689 return 1;
1746 1690
1747 if ((owner = get_owner (hitter)) != NULL) 1691 if ((owner = hitter->owner) != NULL)
1748 { 1692 {
1749 if (owner->type == PLAYER && owner->contr->peaceful == 1) 1693 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1750 friendlyfire = 2; 1694 friendlyfire = 2;
1751 } 1695 }
1752 1696
1773{ 1717{
1774 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1718 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1775 int maxattacktype, attacknum; 1719 int maxattacktype, attacknum;
1776 int body_attack = op && op->head; /* Did we hit op's head? */ 1720 int body_attack = op && op->head; /* Did we hit op's head? */
1777 int simple_attack; 1721 int simple_attack;
1778 tag_t op_tag, hitter_tag;
1779 int rtn_kill = 0; 1722 int rtn_kill = 0;
1780 int friendlyfire; 1723 int friendlyfire;
1781 1724
1782 if (get_attack_mode (&op, &hitter, &simple_attack)) 1725 if (get_attack_mode (&op, &hitter, &simple_attack))
1783 return 0; 1726 return 0;
1787 return 0; 1730 return 0;
1788 1731
1789#ifdef PROHIBIT_PLAYERKILL 1732#ifdef PROHIBIT_PLAYERKILL
1790 if (op->type == PLAYER) 1733 if (op->type == PLAYER)
1791 { 1734 {
1792 object *owner = get_owner (hitter); 1735 object *owner = hitter->owner;
1793 1736
1794 if (!owner) 1737 if (!owner)
1795 owner = hitter; 1738 owner = hitter;
1739
1796 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1740 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1797 {
1798 return 0; 1741 return 0;
1799 }
1800 } 1742 }
1801#endif 1743#endif
1802
1803 op_tag = op->count;
1804 hitter_tag = hitter->count;
1805 1744
1806 if (body_attack) 1745 if (body_attack)
1807 { 1746 {
1808 /* slow and paralyze must hit the head. But we don't want to just 1747 /* 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 1748 * return - we still need to process other attacks the spell still
1815 * attack so we don't cancel out things like magic bullet. 1754 * attack so we don't cancel out things like magic bullet.
1816 */ 1755 */
1817 if (type & (AT_PARALYZE | AT_SLOW)) 1756 if (type & (AT_PARALYZE | AT_SLOW))
1818 { 1757 {
1819 type &= ~(AT_PARALYZE | AT_SLOW); 1758 type &= ~(AT_PARALYZE | AT_SLOW);
1759
1820 if (!type || type == AT_MAGIC) 1760 if (!type || type == AT_MAGIC)
1821 return 0; 1761 return 0;
1822 } 1762 }
1823 } 1763 }
1824 1764
1828 1768
1829 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1769 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1830 if (tmp->type == RUNE || tmp->type == TRAP) 1770 if (tmp->type == RUNE || tmp->type == TRAP)
1831 { 1771 {
1832 spring_trap (tmp, hitter); 1772 spring_trap (tmp, hitter);
1773
1833 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1774 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1834 return 0; 1775 return 0;
1776
1835 break; 1777 break;
1836 } 1778 }
1837 } 1779 }
1838 1780
1839 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1781 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1840 { 1782 {
1841 /* FIXME: If a player is killed by a rune in a door, the 1783 /* 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. 1784 * destroyed() check above doesn't return, and might get here.
1843 */ 1785 */
1844 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1786 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1845 return 0; 1787 return 0;
1846 } 1788 }
1847 1789
1956 1898
1957#ifdef ATTACK_DEBUG 1899#ifdef ATTACK_DEBUG
1958 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam); 1900 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1959#endif 1901#endif
1960 1902
1961 if (get_owner (hitter)) 1903 if (hitter->owner)
1962 op->enemy = hitter->owner; 1904 op->enemy = hitter->owner;
1963 else if (QUERY_FLAG (hitter, FLAG_ALIVE)) 1905 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1964 op->enemy = hitter; 1906 op->enemy = hitter;
1965 1907
1966 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER) 1908 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1991 1933
1992 if (QUERY_FLAG (op, FLAG_TEAR_DOWN)) 1934 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1993 { 1935 {
1994 if (maxdam) 1936 if (maxdam)
1995 tear_down_wall (op); 1937 tear_down_wall (op);
1938
1996 return maxdam; /* nothing more to do for wall */ 1939 return maxdam; /* nothing more to do for wall */
1997 } 1940 }
1998 1941
1999 /* See if the creature has been killed */ 1942 /* See if the creature has been killed */
2000 rtn_kill = kill_object (op, maxdam, hitter, type); 1943 rtn_kill = kill_object (op, maxdam, hitter, type);
2008 */ 1951 */
2009 if (QUERY_FLAG (hitter, FLAG_ONE_HIT)) 1952 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
2010 { 1953 {
2011 if (QUERY_FLAG (hitter, FLAG_FRIENDLY)) 1954 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
2012 remove_friendly_object (hitter); 1955 remove_friendly_object (hitter);
2013 remove_ob (hitter); 1956
2014 free_object (hitter); 1957 hitter->destroy ();
2015 } 1958 }
2016 /* Lets handle creatures that are splitting now */ 1959 /* Lets handle creatures that are splitting now */
2017 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING)) 1960 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
2018 { 1961 {
2019 int i; 1962 int i;
2020 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY); 1963 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
2021 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE); 1964 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
2022 object *owner = get_owner (op); 1965 object *owner = op->owner;
2023 1966
2024 if (!op->other_arch) 1967 if (!op->other_arch)
2025 { 1968 {
2026 LOG (llevError, "SPLITTING without other_arch error.\n"); 1969 LOG (llevError, "SPLITTING without other_arch error.\n");
2027 return maxdam; 1970 return maxdam;
2028 } 1971 }
1972
2029 remove_ob (op); 1973 op->remove ();
1974
2030 for (i = 0; i < NROFNEWOBJS (op); i++) 1975 for (i = 0; i < NROFNEWOBJS (op); i++)
2031 { /* This doesn't handle op->more yet */ 1976 { /* This doesn't handle op->more yet */
2032 object *tmp = arch_to_object (op->other_arch); 1977 object *tmp = arch_to_object (op->other_arch);
2033 int j; 1978 int j;
2034 1979
2035 tmp->stats.hp = op->stats.hp; 1980 tmp->stats.hp = op->stats.hp;
1981
2036 if (friendly) 1982 if (friendly)
2037 { 1983 {
2038 SET_FLAG (tmp, FLAG_FRIENDLY); 1984 SET_FLAG (tmp, FLAG_FRIENDLY);
2039 add_friendly_object (tmp); 1985 add_friendly_object (tmp);
2040 tmp->attack_movement = PETMOVE; 1986 tmp->attack_movement = PETMOVE;
2041 if (owner != NULL) 1987 if (owner != NULL)
2042 set_owner (tmp, owner); 1988 tmp->set_owner (owner);
2043 } 1989 }
1990
2044 if (unaggressive) 1991 if (unaggressive)
2045 SET_FLAG (tmp, FLAG_UNAGGRESSIVE); 1992 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1993
2046 j = find_first_free_spot (tmp, op->map, op->x, op->y); 1994 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1995
2047 if (j == -1) /* No spot to put this monster */ 1996 if (j == -1) /* No spot to put this monster */
2048 free_object (tmp); 1997 tmp->destroy ();
2049 else 1998 else
2050 { 1999 {
2051 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 2000 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
2052 insert_ob_in_map (tmp, op->map, NULL, 0); 2001 insert_ob_in_map (tmp, op->map, NULL, 0);
2053 } 2002 }
2054 } 2003 }
2055 if (friendly) 2004
2056 remove_friendly_object (op); 2005 op->destroy ();
2057 free_object (op);
2058 } 2006 }
2059 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10) 2007 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2060 { 2008 hitter->destroy ();
2061 remove_ob (hitter); 2009
2062 free_object (hitter);
2063 }
2064 return maxdam; 2010 return maxdam;
2065} 2011}
2066 2012
2067 2013
2068void 2014void
2069poison_player (object *op, object *hitter, int dam) 2015poison_player (object *op, object *hitter, int dam)
2070{ 2016{
2071 archetype *at = find_archetype ("poisoning"); 2017 archetype *at = archetype::find ("poisoning");
2072 object *tmp = present_arch_in_ob (at, op); 2018 object *tmp = present_arch_in_ob (at, op);
2073 2019
2074 if (tmp == NULL) 2020 if (tmp == NULL)
2075 { 2021 {
2076 if ((tmp = arch_to_object (at)) == NULL) 2022 if ((tmp = arch_to_object (at)) == NULL)
2089 if (QUERY_FLAG (hitter, FLAG_ALIVE)) 2035 if (QUERY_FLAG (hitter, FLAG_ALIVE))
2090 tmp->stats.dam += hitter->level / 2; 2036 tmp->stats.dam += hitter->level / 2;
2091 else 2037 else
2092 tmp->stats.dam = dam; 2038 tmp->stats.dam = dam;
2093 2039
2094 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */ 2040 tmp->set_owner (hitter); /* so we get credit for poisoning kills */
2095 if (hitter->skill && hitter->skill != tmp->skill) 2041 if (hitter->skill && hitter->skill != tmp->skill)
2096 { 2042 {
2097 tmp->skill = hitter->skill; 2043 tmp->skill = hitter->skill;
2098 } 2044 }
2099 2045
2105 tmp->stats.Con = MAX (-(dam / 4 + 1), -10); 2051 tmp->stats.Con = MAX (-(dam / 4 + 1), -10);
2106 tmp->stats.Str = MAX (-(dam / 3 + 2), -10); 2052 tmp->stats.Str = MAX (-(dam / 3 + 2), -10);
2107 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10); 2053 tmp->stats.Dex = MAX (-(dam / 6 + 1), -10);
2108 tmp->stats.Int = MAX (-dam / 7, -10); 2054 tmp->stats.Int = MAX (-dam / 7, -10);
2109 SET_FLAG (tmp, FLAG_APPLIED); 2055 SET_FLAG (tmp, FLAG_APPLIED);
2110 fix_player (op); 2056 op->update_stats ();
2111 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill."); 2057 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
2112 } 2058 }
2113 if (hitter->type == PLAYER) 2059 if (hitter->type == PLAYER)
2114 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); 2060 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
2115 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 2061 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); 2062 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
2117 } 2063 }
2118 tmp->speed_left = 0; 2064 tmp->speed_left = 0;
2119 } 2065 }
2120 else 2066 else
2122} 2068}
2123 2069
2124void 2070void
2125slow_player (object *op, object *hitter, int dam) 2071slow_player (object *op, object *hitter, int dam)
2126{ 2072{
2127 archetype *at = find_archetype ("slowness"); 2073 archetype *at = archetype::find ("slowness");
2128 object *tmp; 2074 object *tmp;
2129 2075
2130 if (at == NULL) 2076 if (at == NULL)
2131 { 2077 {
2132 LOG (llevError, "Can't find slowness archetype.\n"); 2078 LOG (llevError, "Can't find slowness archetype.\n");
2139 } 2085 }
2140 else 2086 else
2141 tmp->stats.food++; 2087 tmp->stats.food++;
2142 SET_FLAG (tmp, FLAG_APPLIED); 2088 SET_FLAG (tmp, FLAG_APPLIED);
2143 tmp->speed_left = 0; 2089 tmp->speed_left = 0;
2144 fix_player (op); 2090 op->update_stats ();
2145} 2091}
2146 2092
2147void 2093void
2148confuse_player (object *op, object *hitter, int dam) 2094confuse_player (object *op, object *hitter, int dam)
2149{ 2095{
2193 */ 2139 */
2194 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100; 2140 tmp->speed = tmp->speed * (100.0 - (float) op->resist[ATNR_BLIND]) / 100;
2195 2141
2196 tmp = insert_ob_in_ob (tmp, op); 2142 tmp = insert_ob_in_ob (tmp, op);
2197 change_abil (op, tmp); /* Mostly to display any messages */ 2143 change_abil (op, tmp); /* Mostly to display any messages */
2198 fix_player (op); /* This takes care of some other stuff */ 2144 op->update_stats (); /* This takes care of some other stuff */
2199 2145
2200 if (hitter->owner) 2146 if (hitter->owner)
2201 owner = get_owner (hitter); 2147 owner = hitter->owner;
2202 else 2148 else
2203 owner = hitter; 2149 owner = hitter;
2204 2150
2205 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op)); 2151 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2206 } 2152 }
2352 } 2298 }
2353 2299
2354 /* aimed missiles use the owning object's sight */ 2300 /* aimed missiles use the owning object's sight */
2355 if (is_aimed_missile (hitter)) 2301 if (is_aimed_missile (hitter))
2356 { 2302 {
2357 if ((attacker = get_owner (hitter)) == NULL) 2303 if ((attacker = hitter->owner) == NULL)
2358 attacker = hitter; 2304 attacker = hitter;
2359 /* A player who saves but hasn't quit still could have objects 2305 /* A player who saves but hasn't quit still could have objects
2360 * owned by him - need to handle that case to avoid crashes. 2306 * owned by him - need to handle that case to avoid crashes.
2361 */ 2307 */
2362 if (QUERY_FLAG (attacker, FLAG_REMOVED)) 2308 if (QUERY_FLAG (attacker, FLAG_REMOVED))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines