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.10 by root, Mon Sep 11 11:46:52 2006 UTC vs.
Revision 1.27 by root, Wed Dec 13 03:28:42 2006 UTC

1
2/*
3 * static char *rcsid_attack_c =
4 * "$Id: attack.C,v 1.10 2006/09/11 11:46:52 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
177 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE)) 166 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE))
178 { 167 {
179 const char *arch = op->other_arch->name; 168 const char *arch = op->other_arch->name;
180 169
181 op = decrease_ob_nr (op, 1); 170 op = decrease_ob_nr (op, 1);
171
182 if (op) 172 if (op)
183 fix_stopped_item (op, m, originator); 173 fix_stopped_item (op, m, originator);
174
184 if ((op = get_archetype (arch)) != NULL) 175 if ((op = get_archetype (arch)) != NULL)
185 { 176 {
186 if (env) 177 if (env)
187 { 178 {
188 op->x = env->x, op->y = env->y; 179 op->x = env->x, op->y = env->y;
194 { 185 {
195 op->x = x, op->y = y; 186 op->x = x, op->y = y;
196 insert_ob_in_map (op, m, originator, 0); 187 insert_ob_in_map (op, m, originator, 0);
197 } 188 }
198 } 189 }
190
199 return; 191 return;
200 } 192 }
193
201 if (type & AT_CANCELLATION) 194 if (type & AT_CANCELLATION)
202 { /* Cancellation. */ 195 { /* Cancellation. */
203 cancellation (op); 196 cancellation (op);
204 fix_stopped_item (op, m, originator); 197 fix_stopped_item (op, m, originator);
205 return; 198 return;
206 } 199 }
200
207 if (op->nrof > 1) 201 if (op->nrof > 1)
208 { 202 {
209 op = decrease_ob_nr (op, rndm (0, op->nrof - 1)); 203 op = decrease_ob_nr (op, rndm (0, op->nrof - 1));
204
210 if (op) 205 if (op)
211 fix_stopped_item (op, m, originator); 206 fix_stopped_item (op, m, originator);
212 } 207 }
213 else 208 else
214 { 209 {
215 if (op->env) 210 if (op->env)
216 { 211 {
217 object *tmp = is_player_inv (op->env); 212 object *tmp = is_player_inv (op->env);
218 213
219 if (tmp) 214 if (tmp)
220 {
221 esrv_del_item (tmp->contr, op->count); 215 esrv_del_item (tmp->contr, op->count);
222 }
223 } 216 }
224 if (!QUERY_FLAG (op, FLAG_REMOVED)) 217
225 remove_ob (op); 218 op->destroy ();
226 free_object (op);
227 } 219 }
220
228 if (type & (AT_FIRE | AT_ELECTRICITY)) 221 if (type & (AT_FIRE | AT_ELECTRICITY))
229 {
230 if (env) 222 if (env)
231 { 223 {
232 op = get_archetype ("burnout"); 224 op = get_archetype ("burnout");
233 op->x = env->x, op->y = env->y; 225 op->x = env->x, op->y = env->y;
234 insert_ob_in_ob (op, env); 226 insert_ob_in_ob (op, env);
235 } 227 }
236 else 228 else
237 {
238 replace_insert_ob_in_map ("burnout", originator); 229 replace_insert_ob_in_map ("burnout", originator);
239 } 230
240 }
241 return; 231 return;
242 } 232 }
233
243 /* The value of 50 is arbitrary. */ 234 /* The value of 50 is arbitrary. */
244 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))
245 { 236 {
246 object *tmp; 237 object *tmp;
247 archetype *at = find_archetype ("icecube"); 238 archetype *at = archetype::find ("icecube");
248 239
249 if (at == NULL) 240 if (at == NULL)
250 return; 241 return;
242
251 op = stop_item (op); 243 op = stop_item (op);
252 if (op == NULL) 244 if (op == NULL)
253 return; 245 return;
246
254 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL) 247 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL)
255 { 248 {
256 tmp = arch_to_object (at); 249 tmp = arch_to_object (at);
257 tmp->x = op->x, tmp->y = op->y; 250 tmp->x = op->x, tmp->y = op->y;
258 /* This was in the old (pre new movement code) - 251 /* This was in the old (pre new movement code) -
261 */ 254 */
262 tmp->move_slow_penalty = 0; 255 tmp->move_slow_penalty = 0;
263 tmp->move_slow = 0; 256 tmp->move_slow = 0;
264 insert_ob_in_map (tmp, op->map, originator, 0); 257 insert_ob_in_map (tmp, op->map, originator, 0);
265 } 258 }
259
266 if (!QUERY_FLAG (op, FLAG_REMOVED)) 260 if (!QUERY_FLAG (op, FLAG_REMOVED))
267 remove_ob (op); 261 op->remove ();
262
268 (void) insert_ob_in_ob (op, tmp); 263 insert_ob_in_ob (op, tmp);
269 return; 264 return;
270 } 265 }
271} 266}
272 267
273/* Object op is hitting the map. 268/* Object op is hitting the map.
279 274
280int 275int
281hit_map (object *op, int dir, int type, int full_hit) 276hit_map (object *op, int dir, int type, int full_hit)
282{ 277{
283 object *tmp, *next; 278 object *tmp, *next;
284 mapstruct *map; 279 maptile *map;
285 sint16 x, y; 280 sint16 x, y;
286 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 */
287 282
288 tag_t op_tag, next_tag = 0;
289
290 if (QUERY_FLAG (op, FLAG_FREED)) 283 if (QUERY_FLAG (op, FLAG_FREED))
291 { 284 {
292 LOG (llevError, "BUG: hit_map(): free object\n"); 285 LOG (llevError, "BUG: hit_map(): free object\n");
293 return 0; 286 return 0;
294 } 287 }
305 return 0; 298 return 0;
306 } 299 }
307 300
308 if (op->head) 301 if (op->head)
309 op = op->head; 302 op = op->head;
310
311 op_tag = op->count;
312 303
313 map = op->map; 304 map = op->map;
314 x = op->x + freearr_x[dir]; 305 x = op->x + freearr_x[dir];
315 y = op->y + freearr_y[dir]; 306 y = op->y + freearr_y[dir];
316 307
317 int mflags = get_map_flags (map, &map, x, y, &x, &y); 308 int mflags = get_map_flags (map, &map, x, y, &x, &y);
318 309
319 // elmex: a safe map tile can't be hit! 310 // elmex: a safe map tile can't be hit!
320 // this should prevent most harmful effects on items and players there. 311 // this should prevent most harmful effects on items and players there.
321 if ((mflags & P_OUT_OF_MAP) || (mflags & P_SAFE)) 312 if (mflags & (P_OUT_OF_MAP | P_SAFE))
322 return 0; 313 return 0;
323 314
324 /* peterm: a few special cases for special attacktypes --counterspell 315 /* peterm: a few special cases for special attacktypes --counterspell
325 * must be out here because it strikes things which are not alive 316 * must be out here because it strikes things which are not alive
326 */ 317 */
331 322
332 /* If the only attacktype is counterspell or magic, don't need 323 /* If the only attacktype is counterspell or magic, don't need
333 * to do any further processing. 324 * to do any further processing.
334 */ 325 */
335 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC))) 326 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
336 {
337 return 0; 327 return 0;
338 } 328
339 type &= ~AT_COUNTERSPELL; 329 type &= ~AT_COUNTERSPELL;
340 } 330 }
341 331
342 if (type & AT_CHAOS) 332 if (type & AT_CHAOS)
343 { 333 {
345 update_object (op, UP_OBJ_FACE); 335 update_object (op, UP_OBJ_FACE);
346 type &= ~AT_CHAOS; 336 type &= ~AT_CHAOS;
347 } 337 }
348 338
349 next = get_map_ob (map, x, y); 339 next = get_map_ob (map, x, y);
350 if (next)
351 next_tag = next->count;
352 340
353 while (next) 341 while (next)
354 { 342 {
355 if (was_destroyed (next, next_tag)) 343 if (next->destroyed ())
356 { 344 {
357 /* 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
358 * 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
359 * tags into a temporary array before we start processing the first 347 * tags into a temporary array before we start processing the first
360 * object. That's why we just abort. 348 * object. That's why we just abort.
364 * below was spamming the logs for absolutely no reason. 352 * below was spamming the logs for absolutely no reason.
365 */ 353 */
366 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */ 354 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
367 break; 355 break;
368 } 356 }
357
369 tmp = next; 358 tmp = next;
370 next = tmp->above; 359 next = tmp->above;
371 if (next)
372 next_tag = next->count;
373 360
374 if (QUERY_FLAG (tmp, FLAG_FREED)) 361 if (tmp->destroyed ())
375 { 362 {
376 LOG (llevError, "BUG: hit_map(): found freed object\n"); 363 LOG (llevError, "BUG: hit_map(): found freed object\n");
377 break; 364 break;
378 } 365 }
379 366
386 373
387 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 374 if (QUERY_FLAG (tmp, FLAG_ALIVE))
388 { 375 {
389 hit_player (tmp, op->stats.dam, op, type, full_hit); 376 hit_player (tmp, op->stats.dam, op, type, full_hit);
390 retflag |= 1; 377 retflag |= 1;
391 if (was_destroyed (op, op_tag)) 378 if (op->destroyed ())
392 break; 379 break;
393 } 380 }
381
394 /* Here we are potentially destroying an object. If the object has 382 /* Here we are potentially destroying an object. If the object has
395 * 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
396 * that weak walls have is_alive set, which prevent objects from 384 * that weak walls have is_alive set, which prevent objects from
397 * passing over/through them. We don't care what type of movement 385 * passing over/through them. We don't care what type of movement
398 * the wall blocks - if it blocks any type of movement, can't be 386 * the wall blocks - if it blocks any type of movement, can't be
399 * destroyed right now. 387 * destroyed right now.
400 */ 388 */
401 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)
402 { 390 {
403 save_throw_object (tmp, type, op); 391 save_throw_object (tmp, type, op);
404 if (was_destroyed (op, op_tag)) 392 if (op->destroyed ())
405 break; 393 break;
406 } 394 }
407 } 395 }
396
408 return 0; 397 return 0;
409} 398}
410 399
411void 400void
412attack_message (int dam, int type, object *op, object *hitter) 401attack_message (int dam, int type, object *op, object *hitter)
413{ 402{
414 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 403 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
415 int i, found = 0; 404 int i, found = 0;
416 mapstruct *map; 405 maptile *map;
417 object *next, *tmp; 406 object *next, *tmp;
418 407
419 /* 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
420 * a player might have. For example, fire, electric, cold, etc 409 * a player might have. For example, fire, electric, cold, etc
421 * [garbled 20010919] 410 * [garbled 20010919]
621 strcpy (buf1, "hit"); 610 strcpy (buf1, "hit");
622 strcpy (buf2, " hits"); 611 strcpy (buf2, " hits");
623 } 612 }
624 613
625 /* bail out if a monster is casting spells */ 614 /* bail out if a monster is casting spells */
626 if (!(hitter->type == PLAYER || (get_owner (hitter) != NULL && hitter->owner->type == PLAYER))) 615 if (!(hitter->type == PLAYER || (hitter->owner != NULL && hitter->owner->type == PLAYER)))
627 return; 616 return;
628 617
629 /* scale down magic considerably. */ 618 /* scale down magic considerably. */
630 if (type & AT_MAGIC && rndm (0, 5)) 619 if (type & AT_MAGIC && rndm (0, 5))
631 return; 620 return;
632 621
633 /* Did a player hurt another player? Inform both! */ 622 /* Did a player hurt another player? Inform both! */
634 if (op->type == PLAYER && (get_owner (hitter) == NULL ? hitter->type : hitter->owner->type) == PLAYER) 623 if (op->type == PLAYER && (hitter->owner == NULL ? hitter->type : hitter->owner->type) == PLAYER)
635 { 624 {
636 if (get_owner (hitter) != NULL) 625 if (hitter->owner != NULL)
637 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2); 626 sprintf (buf, "%s's %s%s you.", &hitter->owner->name, &hitter->name, buf2);
638 else 627 else
639 { 628 {
640 sprintf (buf, "%s%s you.", &hitter->name, buf2); 629 sprintf (buf, "%s%s you.", &hitter->name, buf2);
641 if (dam != 0) 630 if (dam != 0)
663 else 652 else
664 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0); 653 play_sound_player_only (hitter->contr, SOUND_PLAYER_HITS3, 0, 0);
665 } 654 }
666 new_draw_info (NDI_BLACK, 0, hitter, buf); 655 new_draw_info (NDI_BLACK, 0, hitter, buf);
667 } 656 }
668 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 657 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
669 { 658 {
670 /* look for stacked spells and start reducing the message chances */ 659 /* look for stacked spells and start reducing the message chances */
671 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE)) 660 if (hitter->type == SPELL_EFFECT && (hitter->subtype == SP_EXPLOSION || hitter->subtype == SP_BULLET || hitter->subtype == SP_CONE))
672 { 661 {
673 i = 4; 662 i = 4;
748attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 737attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
749{ 738{
750 int simple_attack, roll, dam = 0; 739 int simple_attack, roll, dam = 0;
751 uint32 type; 740 uint32 type;
752 shstr op_name; 741 shstr op_name;
753 tag_t op_tag, hitter_tag;
754 742
755 if (get_attack_mode (&op, &hitter, &simple_attack)) 743 if (get_attack_mode (&op, &hitter, &simple_attack))
756 goto error; 744 goto error;
757 745
758 if (hitter->current_weapon) 746 if (hitter->current_weapon)
759 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 747 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
760 return RESULT_INT (0); 748 return RESULT_INT (0);
761 749
762 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 750 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
763 return RESULT_INT (0); 751 return RESULT_INT (0);
764
765 op_tag = op->count;
766 hitter_tag = hitter->count;
767 752
768 /* 753 /*
769 * A little check to make it more difficult to dance forward and back 754 * A little check to make it more difficult to dance forward and back
770 * to avoid ever being hit by monsters. 755 * to avoid ever being hit by monsters.
771 */ 756 */
776 * which then gets here again. By decreasing the speed before 761 * which then gets here again. By decreasing the speed before
777 * we call process_object, the 'if' statement above will fail. 762 * we call process_object, the 'if' statement above will fail.
778 */ 763 */
779 op->speed_left--; 764 op->speed_left--;
780 process_object (op); 765 process_object (op);
766
781 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 767 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
782 goto error; 768 goto error;
783 } 769 }
784 770
785 op_name = op->name; 771 op_name = op->name;
786 772
820 if (QUERY_FLAG (op, FLAG_SLEEP)) 806 if (QUERY_FLAG (op, FLAG_SLEEP))
821 CLEAR_FLAG (op, FLAG_SLEEP); 807 CLEAR_FLAG (op, FLAG_SLEEP);
822 808
823 /* If the victim can't see the attacker, it may alert others 809 /* If the victim can't see the attacker, it may alert others
824 * for help. */ 810 * for help. */
825 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !get_owner (op) && rndm (0, op->stats.Int)) 811 if (op->type != PLAYER && !can_see_enemy (op, hitter) && !op->owner && rndm (0, op->stats.Int))
826 npc_call_help (op); 812 npc_call_help (op);
827 813
828 /* if you were hidden and hit by a creature, you are discovered */ 814 /* if you were hidden and hit by a creature, you are discovered */
829 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE)) 815 if (op->hide && QUERY_FLAG (hitter, FLAG_ALIVE))
830 { 816 {
837 * when they hit the victim. For things like thrown daggers, 823 * when they hit the victim. For things like thrown daggers,
838 * this sets 'hitter' to the actual dagger, and not the 824 * this sets 'hitter' to the actual dagger, and not the
839 * wrapper object. 825 * wrapper object.
840 */ 826 */
841 thrown_item_effect (hitter, op); 827 thrown_item_effect (hitter, op);
828
842 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 829 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
843 goto leave; 830 goto leave;
844 } 831 }
845 832
846 /* Need to do at least 1 damage, otherwise there is no point 833 /* Need to do at least 1 damage, otherwise there is no point
847 * to go further and it will cause FPE's below. 834 * to go further and it will cause FPE's below.
848 */ 835 */
849 if (hitdam <= 0) 836 if (hitdam <= 0)
850 hitdam = 1; 837 hitdam = 1;
851 838
852 type = hitter->attacktype; 839 type = hitter->attacktype;
840
853 if (!type) 841 if (!type)
854 type = AT_PHYSICAL; 842 type = AT_PHYSICAL;
843
855 /* Handle monsters that hit back */ 844 /* Handle monsters that hit back */
856 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 845 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
857 { 846 {
858 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 847 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
859 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 848 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
849
860 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 850 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
851
861 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 852 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
862 goto leave; 853 goto leave;
863 } 854 }
864 855
865 /* In the new attack code, it should handle multiple attack 856 /* In the new attack code, it should handle multiple attack
866 * types in its area, so remove it from here. 857 * types in its area, so remove it from here.
867 */ 858 */
868 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 859 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
860
869 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 861 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
870 goto leave; 862 goto leave;
871 } /* end of if hitter hit op */ 863 } /* end of if hitter hit op */
872 /* if we missed, dam=0 */ 864 /* if we missed, dam=0 */
873 865
874 /*attack_message(dam, type, op, hitter); */ 866 /*attack_message(dam, type, op, hitter); */
908 if (op->weight <= 5000 && tmp->stats.hp >= 0) 900 if (op->weight <= 5000 && tmp->stats.hp >= 0)
909 { 901 {
910 if (tmp->head != NULL) 902 if (tmp->head != NULL)
911 tmp = tmp->head; 903 tmp = tmp->head;
912 904
913 remove_ob (op); 905 op->remove ();
914 op = insert_ob_in_ob (op, tmp); 906 op = insert_ob_in_ob (op, tmp);
915 907
916 if (tmp->type == PLAYER) 908 if (tmp->type == PLAYER)
917 esrv_send_item (tmp, op); 909 esrv_send_item (tmp, op);
918 910
931object * 923object *
932hit_with_arrow (object *op, object *victim) 924hit_with_arrow (object *op, object *victim)
933{ 925{
934 object *container, *hitter; 926 object *container, *hitter;
935 int hit_something = 0; 927 int hit_something = 0;
936 tag_t victim_tag, hitter_tag;
937 sint16 victim_x, victim_y;
938 928
939 /* Disassemble missile */ 929 /* Disassemble missile */
940 if (op->inv) 930 if (op->inv)
941 { 931 {
942 container = op; 932 container = op;
943 hitter = op->inv; 933 hitter = op->inv;
944 remove_ob (hitter); 934 hitter->remove ();
945 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON); 935 insert_ob_in_map (hitter, container->map, hitter, INS_NO_MERGE | INS_NO_WALK_ON);
946 /* Note that we now have an empty THROWN_OBJ on the map. Code that 936 /* Note that we now have an empty THROWN_OBJ on the map. Code that
947 * might be called until this THROWN_OBJ is either reassembled or 937 * might be called until this THROWN_OBJ is either reassembled or
948 * removed at the end of this function must be able to deal with empty 938 * removed at the end of this function must be able to deal with empty
949 * THROWN_OBJs. */ 939 * THROWN_OBJs. */
950 } 940 }
951 else 941 else
952 { 942 {
953 container = NULL; 943 container = 0;
954 hitter = op; 944 hitter = op;
955 } 945 }
956 946
957 /* Try to hit victim */ 947 /* Try to hit victim */
958 victim_x = victim->x;
959 victim_y = victim->y;
960 victim_tag = victim->count;
961 hitter_tag = hitter->count;
962
963 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc); 948 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
964 949
965 /* Arrow attacks door, rune of summoning is triggered, demon is put on 950 /* Arrow attacks door, rune of summoning is triggered, demon is put on
966 * arrow, move_apply() calls this function, arrow sticks in demon, 951 * arrow, move_apply() calls this function, arrow sticks in demon,
967 * attack_ob_simple() returns, and we've got an arrow that still exists 952 * attack_ob_simple() returns, and we've got an arrow that still exists
968 * but is no longer on the map. Ugh. (Beware: Such things can happen at 953 * but is no longer on the map. Ugh. (Beware: Such things can happen at
969 * other places as well!) 954 * other places as well!)
970 */ 955 */
971 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 956 if (hitter->destroyed () || hitter->env != NULL)
972 { 957 {
973 if (container) 958 if (container)
974 { 959 {
975 remove_ob (container); 960 container->remove ();
976 free_object (container); 961 container->destroy ();
977 } 962 }
963
978 return NULL; 964 return 0;
979 } 965 }
980 966
981 /* Missile hit victim */ 967 /* Missile hit victim */
982 /* if the speed is > 10, then this is a fast moving arrow, we go straight 968 /* if the speed is > 10, then this is a fast moving arrow, we go straight
983 * through the target 969 * through the target
984 */ 970 */
985 if (hit_something && op->speed <= 10.0) 971 if (hit_something && op->speed <= 10.0)
986 { 972 {
987 /* Stop arrow */ 973 /* Stop arrow */
988 if (container == NULL) 974 if (!container)
989 { 975 {
990 hitter = fix_stopped_arrow (hitter); 976 hitter = fix_stopped_arrow (hitter);
991 if (hitter == NULL) 977 if (!hitter)
992 return NULL; 978 return 0;
993 } 979 }
994 else 980 else
995 { 981 container->destroy ();
996 remove_ob (container);
997 free_object (container);
998 }
999 982
1000 /* Try to stick arrow into victim */ 983 /* Try to stick arrow into victim */
1001 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 984 if (!victim->destroyed () && stick_arrow (hitter, victim))
1002 return NULL; 985 return 0;
1003 986
1004 /* Else try to put arrow on victim's map square 987 /* Else try to put arrow on victim's map square
1005 * remove check for P_WALL here. If the arrow got to this 988 * remove check for P_WALL here. If the arrow got to this
1006 * space, that is good enough - with the new movement code, 989 * space, that is good enough - with the new movement code,
1007 * there is now the potential for lots of spaces where something 990 * there is now the potential for lots of spaces where something
1008 * can fly over but not otherwise move over. What is the correct 991 * can fly over but not otherwise move over. What is the correct
1009 * way to handle those otherwise? 992 * way to handle those otherwise?
1010 */ 993 */
1011 if (victim_x != hitter->x || victim_y != hitter->y) 994 if (victim->x != hitter->x || victim->y != hitter->y)
1012 { 995 {
1013 remove_ob (hitter); 996 hitter->remove ();
1014 hitter->x = victim_x; 997 hitter->x = victim->x;
1015 hitter->y = victim_y; 998 hitter->y = victim->y;
1016 insert_ob_in_map (hitter, victim->map, hitter, 0); 999 insert_ob_in_map (hitter, victim->map, hitter, 0);
1017 } 1000 }
1018 else 1001 else
1019 {
1020 /* Else leave arrow where it is */ 1002 /* Else leave arrow where it is */
1021 merge_ob (hitter, NULL); 1003 merge_ob (hitter, NULL);
1022 } 1004
1023 return NULL; 1005 return 0;
1024 } 1006 }
1025 1007
1026 if (hit_something && op->speed >= 10.0) 1008 if (hit_something && op->speed >= 10.0)
1027 op->speed -= 1.0; 1009 op->speed -= 1.0;
1028 1010
1029 /* Missile missed victim - reassemble missile */ 1011 /* Missile missed victim - reassemble missile */
1030 if (container) 1012 if (container)
1031 { 1013 {
1032 remove_ob (hitter); 1014 hitter->remove ();
1033 insert_ob_in_ob (hitter, container); 1015 insert_ob_in_ob (hitter, container);
1034 } 1016 }
1017
1035 return op; 1018 return op;
1036} 1019}
1037 1020
1038 1021
1039void 1022void
1048 } 1031 }
1049 else if (!GET_ANIM_ID (op)) 1032 else if (!GET_ANIM_ID (op))
1050 { 1033 {
1051 /* Object has been called - no animations, so remove it */ 1034 /* Object has been called - no animations, so remove it */
1052 if (op->stats.hp < 0) 1035 if (op->stats.hp < 0)
1036 op->destroy ();
1053 { 1037
1054 remove_ob (op); /* Should update LOS */
1055 free_object (op);
1056 /* Don't know why this is here - remove_ob should do it for us */
1057 /*update_position(m, x, y); */
1058 }
1059 return; /* no animations, so nothing more to do */ 1038 return; /* no animations, so nothing more to do */
1060 } 1039 }
1040
1061 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp; 1041 perc = NUM_ANIMATIONS (op) - ((int) NUM_ANIMATIONS (op) * op->stats.hp) / op->stats.maxhp;
1042
1062 if (perc >= (int) NUM_ANIMATIONS (op)) 1043 if (perc >= (int) NUM_ANIMATIONS (op))
1063 perc = NUM_ANIMATIONS (op) - 1; 1044 perc = NUM_ANIMATIONS (op) - 1;
1064 else if (perc < 1) 1045 else if (perc < 1)
1065 perc = 1; 1046 perc = 1;
1047
1066 SET_ANIMATION (op, perc); 1048 SET_ANIMATION (op, perc);
1067 update_object (op, UP_OBJ_FACE); 1049 update_object (op, UP_OBJ_FACE);
1050
1068 if (perc == NUM_ANIMATIONS (op) - 1) 1051 if (perc == NUM_ANIMATIONS (op) - 1)
1069 { /* Reached the last animation */ 1052 { /* Reached the last animation */
1070 if (op->face == blank_face) 1053 if (op->face == blank_face)
1071 {
1072 /* If the last face is blank, remove the ob */ 1054 /* If the last face is blank, remove the ob */
1073 remove_ob (op); /* Should update LOS */ 1055 op->destroy ();
1074 free_object (op);
1075
1076 /* remove_ob should call update_position for us */
1077 /*update_position(m, x, y); */
1078
1079 }
1080 else 1056 else
1081 { /* The last face was not blank, leave an image */ 1057 { /* The last face was not blank, leave an image */
1082 CLEAR_FLAG (op, FLAG_BLOCKSVIEW); 1058 CLEAR_FLAG (op, FLAG_BLOCKSVIEW);
1083 update_all_los (op->map, op->x, op->y); 1059 update_all_los (op->map, op->x, op->y);
1084 op->move_block = 0; 1060 op->move_block = 0;
1088} 1064}
1089 1065
1090void 1066void
1091scare_creature (object *target, object *hitter) 1067scare_creature (object *target, object *hitter)
1092{ 1068{
1093 object *owner = get_owner (hitter); 1069 object *owner = hitter->owner;
1094 1070
1095 if (!owner) 1071 if (!owner)
1096 owner = hitter; 1072 owner = hitter;
1097 1073
1098 SET_FLAG (target, FLAG_SCARED); 1074 SET_FLAG (target, FLAG_SCARED);
1302 * Try to credit the owner. We try to display player -> player drain 1278 * Try to credit the owner. We try to display player -> player drain
1303 * attacks, hence all the != PLAYER checks. 1279 * attacks, hence all the != PLAYER checks.
1304 */ 1280 */
1305 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1281 if (!op_on_battleground (hitter, NULL, NULL) && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1306 { 1282 {
1307 object *owner = get_owner (hitter); 1283 object *owner = hitter->owner;
1308 1284
1309 if (owner && owner != hitter) 1285 if (owner && owner != hitter)
1310 { 1286 {
1311 if (op->type != PLAYER || owner->type != PLAYER) 1287 if (op->type != PLAYER || owner->type != PLAYER)
1312 change_exp (owner, op->stats.exp / (rate * 2), 1288 change_exp (owner, op->stats.exp / (rate * 2),
1328 break; 1304 break;
1329 case ATNR_TURN_UNDEAD: 1305 case ATNR_TURN_UNDEAD:
1330 { 1306 {
1331 if (QUERY_FLAG (op, FLAG_UNDEAD)) 1307 if (QUERY_FLAG (op, FLAG_UNDEAD))
1332 { 1308 {
1333 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter); 1309 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1334 object *god = find_god (determine_god (owner)); 1310 object *god = find_god (determine_god (owner));
1335 int div = 1; 1311 int div = 1;
1336 1312
1337 /* if undead are not an enemy of your god, you turn them 1313 /* if undead are not an enemy of your god, you turn them
1338 * at half strength */ 1314 * at half strength */
1364 break; 1340 break;
1365 case ATNR_HOLYWORD: 1341 case ATNR_HOLYWORD:
1366 { 1342 {
1367 /* This has already been handled by hit_player, 1343 /* This has already been handled by hit_player,
1368 * no need to check twice -- DAMN */ 1344 * no need to check twice -- DAMN */
1369 1345 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1370 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter);
1371 1346
1372 /* As with turn undead above, give a bonus on the saving throw */ 1347 /* As with turn undead above, give a bonus on the saving throw */
1373 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis]) 1348 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1374 scare_creature (op, owner); 1349 scare_creature (op, owner);
1375 } 1350 }
1455 op->speed = 0.1; 1430 op->speed = 0.1;
1456 update_ob_speed (op); 1431 update_ob_speed (op);
1457 op->speed_left = -0.05; 1432 op->speed_left = -0.05;
1458 return maxdam; 1433 return maxdam;
1459 } 1434 }
1435
1460 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1436 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1461 { 1437 {
1462 remove_friendly_object (op); 1438 remove_friendly_object (op);
1439
1463 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)
1464 {
1465 op->owner->contr->ranges[range_golem] = NULL; 1441 op->owner->contr->ranges[range_golem] = 0;
1466 op->owner->contr->golem_count = 0;
1467 }
1468 1442
1469 remove_ob (op); 1443 op->destroy ();
1470 free_object (op);
1471 return maxdam; 1444 return maxdam;
1472 } 1445 }
1473 1446
1474 /* Now lets start dealing with experience we get for killing something */ 1447 /* Now lets start dealing with experience we get for killing something */
1475 1448
1476 owner = get_owner (hitter); 1449 owner = hitter->owner;
1477 if (owner == NULL) 1450 if (!owner)
1478 owner = hitter; 1451 owner = hitter;
1479 1452
1480 /* is the victim (op) standing on battleground? */ 1453 /* is the victim (op) standing on battleground? */
1481 if (op_on_battleground (op, NULL, NULL)) 1454 if (op_on_battleground (op, NULL, NULL))
1482 battleg = 1; 1455 battleg = 1;
1512 * probably don't want to see that. 1485 * probably don't want to see that.
1513 */ 1486 */
1514 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1487 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1515 { 1488 {
1516 if (owner != hitter) 1489 if (owner != hitter)
1517 {
1518 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));
1519 }
1520 else 1491 else
1521 {
1522 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));
1523 } 1493
1524 /* Only play sounds for melee kills */ 1494 /* Only play sounds for melee kills */
1525 if (hitter->type == PLAYER) 1495 if (hitter->type == PLAYER)
1526 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);
1527 } 1497 }
1528 1498
1539 1509
1540 /* This code below deals with finding the appropriate skill 1510 /* This code below deals with finding the appropriate skill
1541 * to credit exp to. This is a bit problematic - we should 1511 * to credit exp to. This is a bit problematic - we should
1542 * probably never really have to look at current_weapon->skill 1512 * probably never really have to look at current_weapon->skill
1543 */ 1513 */
1544 skill = NULL; 1514 skill = 0;
1515
1545 if (hitter->skill && hitter->type != PLAYER) 1516 if (hitter->skill && hitter->type != PLAYER)
1546 skill = hitter->skill; 1517 skill = hitter->skill;
1547 else if (owner->chosen_skill) 1518 else if (owner->chosen_skill)
1548 { 1519 {
1549 skill = owner->chosen_skill->skill; 1520 skill = owner->chosen_skill->skill;
1568 break; 1539 break;
1569 } 1540 }
1570 } 1541 }
1571 } /* Was it a player that hit somethign */ 1542 } /* Was it a player that hit somethign */
1572 else 1543 else
1573 {
1574 skill = NULL; 1544 skill = 0;
1575 }
1576 1545
1577 /* Pet (or spell) killed something. */ 1546 /* Pet (or spell) killed something. */
1578 if (owner != hitter) 1547 if (owner != hitter)
1579 {
1580 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1548 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1581 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1549 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1582 }
1583 else 1550 else
1584 {
1585 (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,
1586 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1552 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1587 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1553 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1588 } 1554
1589 /* These may have been set in the player code section above */ 1555 /* These may have been set in the player code section above */
1590 if (!skop) 1556 if (!skop)
1591 skop = hitter->chosen_skill; 1557 skop = hitter->chosen_skill;
1558
1592 if (!skill && skop) 1559 if (!skill && skop)
1593 skill = skop->skill; 1560 skill = skop->skill;
1594 1561
1595 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);
1596 1563
1597
1598 /* If you didn't kill yourself, and your not the wizard */ 1564 /* If you didn't kill yourself, and your not the wizard */
1599 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1565 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1600 { 1566 {
1601 int exp; 1567 int exp;
1602 1568
1603 /* Really don't give much experience for killing other players */ 1569 /* Really don't give much experience for killing other players */
1604 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1570 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1605 if (op->type == PLAYER) 1571 if (op->type == PLAYER)
1606 { 1572 {
1607 if (battleg) 1573 if (battleg)
1608 { 1574 {
1609 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1575 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1627 1593
1628 if (!settings.simple_exp) 1594 if (!settings.simple_exp)
1629 exp = exp / 2; 1595 exp = exp / 2;
1630 1596
1631 if (owner->type != PLAYER || owner->contr->party == NULL) 1597 if (owner->type != PLAYER || owner->contr->party == NULL)
1632 {
1633 change_exp (owner, exp, skill, 0); 1598 change_exp (owner, exp, skill, 0);
1634 }
1635 else 1599 else
1636 { 1600 {
1637 int shares = 0, count = 0; 1601 int shares = 0, count = 0;
1638
1639 player *pl; 1602 player *pl;
1640
1641 partylist *party = owner->contr->party; 1603 partylist *party = owner->contr->party;
1642 1604
1643#ifdef PARTY_KILL_LOG 1605#ifdef PARTY_KILL_LOG
1644 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1606 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1645#endif 1607#endif
1646 for (pl = first_player; pl != NULL; pl = pl->next) 1608 for (pl = first_player; pl != NULL; pl = pl->next)
1647 {
1648 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1609 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1649 { 1610 {
1650 count++; 1611 count++;
1651 shares += (pl->ob->level + 4); 1612 shares += (pl->ob->level + 4);
1652 } 1613 }
1653 } 1614
1654 if (count == 1 || shares > exp) 1615 if (count == 1 || shares > exp || !shares)
1655 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1616 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1656 else 1617 else
1657 { 1618 {
1658 int share = exp / shares, given = 0, nexp; 1619 int share = exp / shares, given = 0, nexp;
1659 1620
1660 for (pl = first_player; pl != NULL; pl = pl->next) 1621 for (pl = first_player; pl != NULL; pl = pl->next)
1661 {
1662 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1622 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1663 { 1623 {
1664 nexp = (pl->ob->level + 4) * share; 1624 nexp = (pl->ob->level + 4) * share;
1665 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1625 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1666 given += nexp; 1626 given += nexp;
1667 } 1627 }
1668 } 1628
1669 exp -= given; 1629 exp -= given;
1670 /* give any remainder to the player */ 1630 /* give any remainder to the player */
1671 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1631 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1672 } 1632 }
1673 } /* else part of a party */ 1633 } /* else part of a party */
1674
1675 } /* end if person didn't kill himself */ 1634 } /* end if person didn't kill himself */
1676 1635
1677 if (op->type != PLAYER) 1636 if (op->type != PLAYER)
1678 { 1637 {
1679 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1638 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1680 { 1639 {
1681 object *owner1 = get_owner (op); 1640 object *owner1 = op->owner;
1682 1641
1683 if (owner1 != NULL && owner1->type == PLAYER) 1642 if (owner1 && owner1->type == PLAYER)
1684 { 1643 {
1685 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1644 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1686 /* Maybe we should include the owner that killed this, maybe not */ 1645 /* Maybe we should include the owner that killed this, maybe not */
1687 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name); 1646 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1688 } 1647 }
1648
1689 remove_friendly_object (op); 1649 remove_friendly_object (op);
1690 } 1650 }
1691 remove_ob (op); 1651
1692 free_object (op); 1652 op->destroy ();
1693 } 1653 }
1694 /* Player has been killed! */
1695 else 1654 else
1696 { 1655 {
1656 /* Player has been killed! */
1697 if (owner->type == PLAYER) 1657 if (owner->type == PLAYER)
1698 {
1699 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1658 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1700 }
1701 else 1659 else
1702 {
1703 strncpy (op->contr->killer, hitter->name, BIG_NAME); 1660 assign (op->contr->killer, hitter->name);
1704 op->contr->killer[BIG_NAME - 1] = '\0';
1705 }
1706 } 1661 }
1662
1707 /* This was return -1 - that doesn't seem correct - if we return -1, process 1663 /* This was return -1 - that doesn't seem correct - if we return -1, process
1708 * continues in the calling function. 1664 * continues in the calling function.
1709 */ 1665 */
1710 return maxdam; 1666 return maxdam;
1711} 1667}
1731 return 0; 1687 return 0;
1732 1688
1733 if (hitter->type == PLAYER && hitter->contr->peaceful == 1) 1689 if (hitter->type == PLAYER && hitter->contr->peaceful == 1)
1734 return 1; 1690 return 1;
1735 1691
1736 if ((owner = get_owner (hitter)) != NULL) 1692 if ((owner = hitter->owner) != NULL)
1737 { 1693 {
1738 if (owner->type == PLAYER && owner->contr->peaceful == 1) 1694 if (owner->type == PLAYER && owner->contr->peaceful == 1)
1739 friendlyfire = 2; 1695 friendlyfire = 2;
1740 } 1696 }
1741 1697
1762{ 1718{
1763 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1719 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1764 int maxattacktype, attacknum; 1720 int maxattacktype, attacknum;
1765 int body_attack = op && op->head; /* Did we hit op's head? */ 1721 int body_attack = op && op->head; /* Did we hit op's head? */
1766 int simple_attack; 1722 int simple_attack;
1767 tag_t op_tag, hitter_tag;
1768 int rtn_kill = 0; 1723 int rtn_kill = 0;
1769 int friendlyfire; 1724 int friendlyfire;
1770 1725
1771 if (get_attack_mode (&op, &hitter, &simple_attack)) 1726 if (get_attack_mode (&op, &hitter, &simple_attack))
1772 return 0; 1727 return 0;
1776 return 0; 1731 return 0;
1777 1732
1778#ifdef PROHIBIT_PLAYERKILL 1733#ifdef PROHIBIT_PLAYERKILL
1779 if (op->type == PLAYER) 1734 if (op->type == PLAYER)
1780 { 1735 {
1781 object *owner = get_owner (hitter); 1736 object *owner = hitter->owner;
1782 1737
1783 if (!owner) 1738 if (!owner)
1784 owner = hitter; 1739 owner = hitter;
1740
1785 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1741 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1786 {
1787 return 0; 1742 return 0;
1788 }
1789 } 1743 }
1790#endif 1744#endif
1791
1792 op_tag = op->count;
1793 hitter_tag = hitter->count;
1794 1745
1795 if (body_attack) 1746 if (body_attack)
1796 { 1747 {
1797 /* slow and paralyze must hit the head. But we don't want to just 1748 /* slow and paralyze must hit the head. But we don't want to just
1798 * return - we still need to process other attacks the spell still 1749 * return - we still need to process other attacks the spell still
1804 * attack so we don't cancel out things like magic bullet. 1755 * attack so we don't cancel out things like magic bullet.
1805 */ 1756 */
1806 if (type & (AT_PARALYZE | AT_SLOW)) 1757 if (type & (AT_PARALYZE | AT_SLOW))
1807 { 1758 {
1808 type &= ~(AT_PARALYZE | AT_SLOW); 1759 type &= ~(AT_PARALYZE | AT_SLOW);
1760
1809 if (!type || type == AT_MAGIC) 1761 if (!type || type == AT_MAGIC)
1810 return 0; 1762 return 0;
1811 } 1763 }
1812 } 1764 }
1813 1765
1817 1769
1818 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1770 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1819 if (tmp->type == RUNE || tmp->type == TRAP) 1771 if (tmp->type == RUNE || tmp->type == TRAP)
1820 { 1772 {
1821 spring_trap (tmp, hitter); 1773 spring_trap (tmp, hitter);
1774
1822 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1775 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1823 return 0; 1776 return 0;
1777
1824 break; 1778 break;
1825 } 1779 }
1826 } 1780 }
1827 1781
1828 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1782 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1829 { 1783 {
1830 /* FIXME: If a player is killed by a rune in a door, the 1784 /* FIXME: If a player is killed by a rune in a door, the
1831 * was_destroyed() check above doesn't return, and might get here. 1785 * destroyed() check above doesn't return, and might get here.
1832 */ 1786 */
1833 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1787 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1834 return 0; 1788 return 0;
1835 } 1789 }
1836 1790
1945 1899
1946#ifdef ATTACK_DEBUG 1900#ifdef ATTACK_DEBUG
1947 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam); 1901 LOG (llevDebug, "Attacktype %d did %d damage\n", type, maxdam);
1948#endif 1902#endif
1949 1903
1950 if (get_owner (hitter)) 1904 if (hitter->owner)
1951 op->enemy = hitter->owner; 1905 op->enemy = hitter->owner;
1952 else if (QUERY_FLAG (hitter, FLAG_ALIVE)) 1906 else if (QUERY_FLAG (hitter, FLAG_ALIVE))
1953 op->enemy = hitter; 1907 op->enemy = hitter;
1954 1908
1955 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER) 1909 if (QUERY_FLAG (op, FLAG_UNAGGRESSIVE) && op->type != PLAYER)
1980 1934
1981 if (QUERY_FLAG (op, FLAG_TEAR_DOWN)) 1935 if (QUERY_FLAG (op, FLAG_TEAR_DOWN))
1982 { 1936 {
1983 if (maxdam) 1937 if (maxdam)
1984 tear_down_wall (op); 1938 tear_down_wall (op);
1939
1985 return maxdam; /* nothing more to do for wall */ 1940 return maxdam; /* nothing more to do for wall */
1986 } 1941 }
1987 1942
1988 /* See if the creature has been killed */ 1943 /* See if the creature has been killed */
1989 rtn_kill = kill_object (op, maxdam, hitter, type); 1944 rtn_kill = kill_object (op, maxdam, hitter, type);
1997 */ 1952 */
1998 if (QUERY_FLAG (hitter, FLAG_ONE_HIT)) 1953 if (QUERY_FLAG (hitter, FLAG_ONE_HIT))
1999 { 1954 {
2000 if (QUERY_FLAG (hitter, FLAG_FRIENDLY)) 1955 if (QUERY_FLAG (hitter, FLAG_FRIENDLY))
2001 remove_friendly_object (hitter); 1956 remove_friendly_object (hitter);
2002 remove_ob (hitter); 1957
2003 free_object (hitter); 1958 hitter->destroy ();
2004 } 1959 }
2005 /* Lets handle creatures that are splitting now */ 1960 /* Lets handle creatures that are splitting now */
2006 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING)) 1961 else if (type & AT_PHYSICAL && !QUERY_FLAG (op, FLAG_FREED) && QUERY_FLAG (op, FLAG_SPLITTING))
2007 { 1962 {
2008 int i; 1963 int i;
2009 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY); 1964 int friendly = QUERY_FLAG (op, FLAG_FRIENDLY);
2010 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE); 1965 int unaggressive = QUERY_FLAG (op, FLAG_UNAGGRESSIVE);
2011 object *owner = get_owner (op); 1966 object *owner = op->owner;
2012 1967
2013 if (!op->other_arch) 1968 if (!op->other_arch)
2014 { 1969 {
2015 LOG (llevError, "SPLITTING without other_arch error.\n"); 1970 LOG (llevError, "SPLITTING without other_arch error.\n");
2016 return maxdam; 1971 return maxdam;
2017 } 1972 }
1973
2018 remove_ob (op); 1974 op->remove ();
1975
2019 for (i = 0; i < NROFNEWOBJS (op); i++) 1976 for (i = 0; i < NROFNEWOBJS (op); i++)
2020 { /* This doesn't handle op->more yet */ 1977 { /* This doesn't handle op->more yet */
2021 object *tmp = arch_to_object (op->other_arch); 1978 object *tmp = arch_to_object (op->other_arch);
2022 int j; 1979 int j;
2023 1980
2024 tmp->stats.hp = op->stats.hp; 1981 tmp->stats.hp = op->stats.hp;
1982
2025 if (friendly) 1983 if (friendly)
2026 { 1984 {
2027 SET_FLAG (tmp, FLAG_FRIENDLY); 1985 SET_FLAG (tmp, FLAG_FRIENDLY);
2028 add_friendly_object (tmp); 1986 add_friendly_object (tmp);
2029 tmp->attack_movement = PETMOVE; 1987 tmp->attack_movement = PETMOVE;
2030 if (owner != NULL) 1988 if (owner != NULL)
2031 set_owner (tmp, owner); 1989 tmp->set_owner (owner);
2032 } 1990 }
1991
2033 if (unaggressive) 1992 if (unaggressive)
2034 SET_FLAG (tmp, FLAG_UNAGGRESSIVE); 1993 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
1994
2035 j = find_first_free_spot (tmp, op->map, op->x, op->y); 1995 j = find_first_free_spot (tmp, op->map, op->x, op->y);
1996
2036 if (j == -1) /* No spot to put this monster */ 1997 if (j == -1) /* No spot to put this monster */
2037 free_object (tmp); 1998 tmp->destroy ();
2038 else 1999 else
2039 { 2000 {
2040 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j]; 2001 tmp->x = op->x + freearr_x[j], tmp->y = op->y + freearr_y[j];
2041 insert_ob_in_map (tmp, op->map, NULL, 0); 2002 insert_ob_in_map (tmp, op->map, NULL, 0);
2042 } 2003 }
2043 } 2004 }
2044 if (friendly) 2005
2045 remove_friendly_object (op); 2006 op->destroy ();
2046 free_object (op);
2047 } 2007 }
2048 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10) 2008 else if (type & AT_DRAIN && hitter->type == GRIMREAPER && hitter->value++ > 10)
2049 { 2009 hitter->destroy ();
2050 remove_ob (hitter); 2010
2051 free_object (hitter);
2052 }
2053 return maxdam; 2011 return maxdam;
2054} 2012}
2055 2013
2056 2014
2057void 2015void
2058poison_player (object *op, object *hitter, int dam) 2016poison_player (object *op, object *hitter, int dam)
2059{ 2017{
2060 archetype *at = find_archetype ("poisoning"); 2018 archetype *at = archetype::find ("poisoning");
2061 object *tmp = present_arch_in_ob (at, op); 2019 object *tmp = present_arch_in_ob (at, op);
2062 2020
2063 if (tmp == NULL) 2021 if (tmp == NULL)
2064 { 2022 {
2065 if ((tmp = arch_to_object (at)) == NULL) 2023 if ((tmp = arch_to_object (at)) == NULL)
2078 if (QUERY_FLAG (hitter, FLAG_ALIVE)) 2036 if (QUERY_FLAG (hitter, FLAG_ALIVE))
2079 tmp->stats.dam += hitter->level / 2; 2037 tmp->stats.dam += hitter->level / 2;
2080 else 2038 else
2081 tmp->stats.dam = dam; 2039 tmp->stats.dam = dam;
2082 2040
2083 copy_owner (tmp, hitter); /* so we get credit for poisoning kills */ 2041 tmp->set_owner (hitter); /* so we get credit for poisoning kills */
2084 if (hitter->skill && hitter->skill != tmp->skill) 2042 if (hitter->skill && hitter->skill != tmp->skill)
2085 { 2043 {
2086 tmp->skill = hitter->skill; 2044 tmp->skill = hitter->skill;
2087 } 2045 }
2088 2046
2099 fix_player (op); 2057 fix_player (op);
2100 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill."); 2058 new_draw_info (NDI_UNIQUE, 0, op, "You suddenly feel very ill.");
2101 } 2059 }
2102 if (hitter->type == PLAYER) 2060 if (hitter->type == PLAYER)
2103 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name); 2061 new_draw_info_format (NDI_UNIQUE, 0, hitter, "You poison %s.", &op->name);
2104 else if (get_owner (hitter) != NULL && hitter->owner->type == PLAYER) 2062 else if (hitter->owner != NULL && hitter->owner->type == PLAYER)
2105 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name); 2063 new_draw_info_format (NDI_UNIQUE, 0, hitter->owner, "Your %s poisons %s.", &hitter->name, &op->name);
2106 } 2064 }
2107 tmp->speed_left = 0; 2065 tmp->speed_left = 0;
2108 } 2066 }
2109 else 2067 else
2111} 2069}
2112 2070
2113void 2071void
2114slow_player (object *op, object *hitter, int dam) 2072slow_player (object *op, object *hitter, int dam)
2115{ 2073{
2116 archetype *at = find_archetype ("slowness"); 2074 archetype *at = archetype::find ("slowness");
2117 object *tmp; 2075 object *tmp;
2118 2076
2119 if (at == NULL) 2077 if (at == NULL)
2120 { 2078 {
2121 LOG (llevError, "Can't find slowness archetype.\n"); 2079 LOG (llevError, "Can't find slowness archetype.\n");
2185 tmp = insert_ob_in_ob (tmp, op); 2143 tmp = insert_ob_in_ob (tmp, op);
2186 change_abil (op, tmp); /* Mostly to display any messages */ 2144 change_abil (op, tmp); /* Mostly to display any messages */
2187 fix_player (op); /* This takes care of some other stuff */ 2145 fix_player (op); /* This takes care of some other stuff */
2188 2146
2189 if (hitter->owner) 2147 if (hitter->owner)
2190 owner = get_owner (hitter); 2148 owner = hitter->owner;
2191 else 2149 else
2192 owner = hitter; 2150 owner = hitter;
2193 2151
2194 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op)); 2152 new_draw_info_format (NDI_UNIQUE, 0, owner, "Your attack blinds %s!", query_name (op));
2195 } 2153 }
2341 } 2299 }
2342 2300
2343 /* aimed missiles use the owning object's sight */ 2301 /* aimed missiles use the owning object's sight */
2344 if (is_aimed_missile (hitter)) 2302 if (is_aimed_missile (hitter))
2345 { 2303 {
2346 if ((attacker = get_owner (hitter)) == NULL) 2304 if ((attacker = hitter->owner) == NULL)
2347 attacker = hitter; 2305 attacker = hitter;
2348 /* A player who saves but hasn't quit still could have objects 2306 /* A player who saves but hasn't quit still could have objects
2349 * owned by him - need to handle that case to avoid crashes. 2307 * owned by him - need to handle that case to avoid crashes.
2350 */ 2308 */
2351 if (QUERY_FLAG (attacker, FLAG_REMOVED)) 2309 if (QUERY_FLAG (attacker, FLAG_REMOVED))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines