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.22 by root, Fri Sep 29 11:53:09 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>
158{ 152{
159 if (!did_make_save_item (op, type, originator)) 153 if (!did_make_save_item (op, type, originator))
160 { 154 {
161 object *env = op->env; 155 object *env = op->env;
162 int x = op->x, y = op->y; 156 int x = op->x, y = op->y;
163 mapstruct *m = op->map; 157 maptile *m = op->map;
164 158
165 op = stop_item (op); 159 op = stop_item (op);
166 if (op == NULL) 160 if (op == NULL)
167 return; 161 return;
168 162
177 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE)) 171 if (type & (AT_FIRE | AT_ELECTRICITY) && op->other_arch && QUERY_FLAG (op, FLAG_IS_LIGHTABLE))
178 { 172 {
179 const char *arch = op->other_arch->name; 173 const char *arch = op->other_arch->name;
180 174
181 op = decrease_ob_nr (op, 1); 175 op = decrease_ob_nr (op, 1);
176
182 if (op) 177 if (op)
183 fix_stopped_item (op, m, originator); 178 fix_stopped_item (op, m, originator);
179
184 if ((op = get_archetype (arch)) != NULL) 180 if ((op = get_archetype (arch)) != NULL)
185 { 181 {
186 if (env) 182 if (env)
187 { 183 {
188 op->x = env->x, op->y = env->y; 184 op->x = env->x, op->y = env->y;
194 { 190 {
195 op->x = x, op->y = y; 191 op->x = x, op->y = y;
196 insert_ob_in_map (op, m, originator, 0); 192 insert_ob_in_map (op, m, originator, 0);
197 } 193 }
198 } 194 }
195
199 return; 196 return;
200 } 197 }
198
201 if (type & AT_CANCELLATION) 199 if (type & AT_CANCELLATION)
202 { /* Cancellation. */ 200 { /* Cancellation. */
203 cancellation (op); 201 cancellation (op);
204 fix_stopped_item (op, m, originator); 202 fix_stopped_item (op, m, originator);
205 return; 203 return;
206 } 204 }
205
207 if (op->nrof > 1) 206 if (op->nrof > 1)
208 { 207 {
209 op = decrease_ob_nr (op, rndm (0, op->nrof - 1)); 208 op = decrease_ob_nr (op, rndm (0, op->nrof - 1));
209
210 if (op) 210 if (op)
211 fix_stopped_item (op, m, originator); 211 fix_stopped_item (op, m, originator);
212 } 212 }
213 else 213 else
214 { 214 {
215 if (op->env) 215 if (op->env)
216 { 216 {
217 object *tmp = is_player_inv (op->env); 217 object *tmp = is_player_inv (op->env);
218 218
219 if (tmp) 219 if (tmp)
220 {
221 esrv_del_item (tmp->contr, op->count); 220 esrv_del_item (tmp->contr, op->count);
222 }
223 } 221 }
222
224 if (!QUERY_FLAG (op, FLAG_REMOVED)) 223 if (!QUERY_FLAG (op, FLAG_REMOVED))
225 remove_ob (op); 224 remove_ob (op);
225
226 free_object (op); 226 free_object (op);
227 } 227 }
228
228 if (type & (AT_FIRE | AT_ELECTRICITY)) 229 if (type & (AT_FIRE | AT_ELECTRICITY))
229 {
230 if (env) 230 if (env)
231 { 231 {
232 op = get_archetype ("burnout"); 232 op = get_archetype ("burnout");
233 op->x = env->x, op->y = env->y; 233 op->x = env->x, op->y = env->y;
234 insert_ob_in_ob (op, env); 234 insert_ob_in_ob (op, env);
235 } 235 }
236 else 236 else
237 {
238 replace_insert_ob_in_map ("burnout", originator); 237 replace_insert_ob_in_map ("burnout", originator);
239 } 238
240 }
241 return; 239 return;
242 } 240 }
241
243 /* The value of 50 is arbitrary. */ 242 /* The value of 50 is arbitrary. */
244 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2)) 243 if (type & AT_COLD && (op->resist[ATNR_COLD] < 50) && !QUERY_FLAG (op, FLAG_NO_PICK) && (RANDOM () & 2))
245 { 244 {
246 object *tmp; 245 object *tmp;
247 archetype *at = find_archetype ("icecube"); 246 archetype *at = archetype::find ("icecube");
248 247
249 if (at == NULL) 248 if (at == NULL)
250 return; 249 return;
250
251 op = stop_item (op); 251 op = stop_item (op);
252 if (op == NULL) 252 if (op == NULL)
253 return; 253 return;
254
254 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL) 255 if ((tmp = present_arch (at, op->map, op->x, op->y)) == NULL)
255 { 256 {
256 tmp = arch_to_object (at); 257 tmp = arch_to_object (at);
257 tmp->x = op->x, tmp->y = op->y; 258 tmp->x = op->x, tmp->y = op->y;
258 /* This was in the old (pre new movement code) - 259 /* This was in the old (pre new movement code) -
261 */ 262 */
262 tmp->move_slow_penalty = 0; 263 tmp->move_slow_penalty = 0;
263 tmp->move_slow = 0; 264 tmp->move_slow = 0;
264 insert_ob_in_map (tmp, op->map, originator, 0); 265 insert_ob_in_map (tmp, op->map, originator, 0);
265 } 266 }
267
266 if (!QUERY_FLAG (op, FLAG_REMOVED)) 268 if (!QUERY_FLAG (op, FLAG_REMOVED))
267 remove_ob (op); 269 remove_ob (op);
270
268 (void) insert_ob_in_ob (op, tmp); 271 insert_ob_in_ob (op, tmp);
269 return; 272 return;
270 } 273 }
271} 274}
272 275
273/* Object op is hitting the map. 276/* Object op is hitting the map.
279 282
280int 283int
281hit_map (object *op, int dir, int type, int full_hit) 284hit_map (object *op, int dir, int type, int full_hit)
282{ 285{
283 object *tmp, *next; 286 object *tmp, *next;
284 mapstruct *map; 287 maptile *map;
285 sint16 x, y; 288 sint16 x, y;
286 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */ 289 int retflag = 0; /* added this flag.. will return 1 if it hits a monster */
287 290
288 tag_t op_tag, next_tag = 0;
289
290 if (QUERY_FLAG (op, FLAG_FREED)) 291 if (QUERY_FLAG (op, FLAG_FREED))
291 { 292 {
292 LOG (llevError, "BUG: hit_map(): free object\n"); 293 LOG (llevError, "BUG: hit_map(): free object\n");
293 return 0; 294 return 0;
294 } 295 }
305 return 0; 306 return 0;
306 } 307 }
307 308
308 if (op->head) 309 if (op->head)
309 op = op->head; 310 op = op->head;
310
311 op_tag = op->count;
312 311
313 map = op->map; 312 map = op->map;
314 x = op->x + freearr_x[dir]; 313 x = op->x + freearr_x[dir];
315 y = op->y + freearr_y[dir]; 314 y = op->y + freearr_y[dir];
316 315
317 int mflags = get_map_flags (map, &map, x, y, &x, &y); 316 int mflags = get_map_flags (map, &map, x, y, &x, &y);
318 317
319 // elmex: a safe map tile can't be hit! 318 // elmex: a safe map tile can't be hit!
320 // this should prevent most harmful effects on items and players there. 319 // this should prevent most harmful effects on items and players there.
321 if ((mflags & P_OUT_OF_MAP) || (mflags & P_SAFE)) 320 if (mflags & (P_OUT_OF_MAP | P_SAFE))
322 return 0; 321 return 0;
323 322
324 /* peterm: a few special cases for special attacktypes --counterspell 323 /* peterm: a few special cases for special attacktypes --counterspell
325 * must be out here because it strikes things which are not alive 324 * must be out here because it strikes things which are not alive
326 */ 325 */
331 330
332 /* If the only attacktype is counterspell or magic, don't need 331 /* If the only attacktype is counterspell or magic, don't need
333 * to do any further processing. 332 * to do any further processing.
334 */ 333 */
335 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC))) 334 if (!(type & ~(AT_COUNTERSPELL | AT_MAGIC)))
336 {
337 return 0; 335 return 0;
338 } 336
339 type &= ~AT_COUNTERSPELL; 337 type &= ~AT_COUNTERSPELL;
340 } 338 }
341 339
342 if (type & AT_CHAOS) 340 if (type & AT_CHAOS)
343 { 341 {
345 update_object (op, UP_OBJ_FACE); 343 update_object (op, UP_OBJ_FACE);
346 type &= ~AT_CHAOS; 344 type &= ~AT_CHAOS;
347 } 345 }
348 346
349 next = get_map_ob (map, x, y); 347 next = get_map_ob (map, x, y);
350 if (next)
351 next_tag = next->count;
352 348
353 while (next) 349 while (next)
354 { 350 {
355 if (was_destroyed (next, next_tag)) 351 if (next->destroyed ())
356 { 352 {
357 /* There may still be objects that were above 'next', but there is no 353 /* There may still be objects that were above 'next', but there is no
358 * simple way to find out short of copying all object references and 354 * simple way to find out short of copying all object references and
359 * tags into a temporary array before we start processing the first 355 * tags into a temporary array before we start processing the first
360 * object. That's why we just abort. 356 * object. That's why we just abort.
364 * below was spamming the logs for absolutely no reason. 360 * below was spamming the logs for absolutely no reason.
365 */ 361 */
366 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */ 362 /* LOG (llevDebug, "hit_map(): next object destroyed\n"); */
367 break; 363 break;
368 } 364 }
365
369 tmp = next; 366 tmp = next;
370 next = tmp->above; 367 next = tmp->above;
371 if (next)
372 next_tag = next->count;
373 368
374 if (QUERY_FLAG (tmp, FLAG_FREED)) 369 if (tmp->destroyed ())
375 { 370 {
376 LOG (llevError, "BUG: hit_map(): found freed object\n"); 371 LOG (llevError, "BUG: hit_map(): found freed object\n");
377 break; 372 break;
378 } 373 }
379 374
386 381
387 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 382 if (QUERY_FLAG (tmp, FLAG_ALIVE))
388 { 383 {
389 hit_player (tmp, op->stats.dam, op, type, full_hit); 384 hit_player (tmp, op->stats.dam, op, type, full_hit);
390 retflag |= 1; 385 retflag |= 1;
391 if (was_destroyed (op, op_tag)) 386 if (op->destroyed ())
392 break; 387 break;
393 } 388 }
389
394 /* Here we are potentially destroying an object. If the object has 390 /* 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 391 * 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 392 * that weak walls have is_alive set, which prevent objects from
397 * passing over/through them. We don't care what type of movement 393 * 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 394 * the wall blocks - if it blocks any type of movement, can't be
399 * destroyed right now. 395 * destroyed right now.
400 */ 396 */
401 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block) 397 else if ((tmp->material || tmp->materialname) && op->stats.dam > 0 && !tmp->move_block)
402 { 398 {
403 save_throw_object (tmp, type, op); 399 save_throw_object (tmp, type, op);
404 if (was_destroyed (op, op_tag)) 400 if (op->destroyed ())
405 break; 401 break;
406 } 402 }
407 } 403 }
404
408 return 0; 405 return 0;
409} 406}
410 407
411void 408void
412attack_message (int dam, int type, object *op, object *hitter) 409attack_message (int dam, int type, object *op, object *hitter)
413{ 410{
414 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF]; 411 char buf[MAX_BUF], buf1[MAX_BUF], buf2[MAX_BUF];
415 int i, found = 0; 412 int i, found = 0;
416 mapstruct *map; 413 maptile *map;
417 object *next, *tmp; 414 object *next, *tmp;
418 415
419 /* put in a few special messages for some of the common attacktypes 416 /* put in a few special messages for some of the common attacktypes
420 * a player might have. For example, fire, electric, cold, etc 417 * a player might have. For example, fire, electric, cold, etc
421 * [garbled 20010919] 418 * [garbled 20010919]
748attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc) 745attack_ob_simple (object *op, object *hitter, int base_dam, int base_wc)
749{ 746{
750 int simple_attack, roll, dam = 0; 747 int simple_attack, roll, dam = 0;
751 uint32 type; 748 uint32 type;
752 shstr op_name; 749 shstr op_name;
753 tag_t op_tag, hitter_tag;
754 750
755 if (get_attack_mode (&op, &hitter, &simple_attack)) 751 if (get_attack_mode (&op, &hitter, &simple_attack))
756 goto error; 752 goto error;
757 753
758 if (hitter->current_weapon) 754 if (hitter->current_weapon)
759 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op))) 755 if (INVOKE_OBJECT (WEAPON_ATTACK, hitter->current_weapon, ARG_OBJECT (hitter), ARG_OBJECT (op)))
760 return RESULT_INT (0); 756 return RESULT_INT (0);
761 757
762 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter))) 758 if (INVOKE_OBJECT (ATTACK, op, ARG_OBJECT (hitter)))
763 return RESULT_INT (0); 759 return RESULT_INT (0);
764
765 op_tag = op->count;
766 hitter_tag = hitter->count;
767 760
768 /* 761 /*
769 * A little check to make it more difficult to dance forward and back 762 * A little check to make it more difficult to dance forward and back
770 * to avoid ever being hit by monsters. 763 * to avoid ever being hit by monsters.
771 */ 764 */
776 * which then gets here again. By decreasing the speed before 769 * which then gets here again. By decreasing the speed before
777 * we call process_object, the 'if' statement above will fail. 770 * we call process_object, the 'if' statement above will fail.
778 */ 771 */
779 op->speed_left--; 772 op->speed_left--;
780 process_object (op); 773 process_object (op);
781 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 774 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
782 goto error; 775 goto error;
783 } 776 }
784 777
785 op_name = op->name; 778 op_name = op->name;
786 779
837 * when they hit the victim. For things like thrown daggers, 830 * when they hit the victim. For things like thrown daggers,
838 * this sets 'hitter' to the actual dagger, and not the 831 * this sets 'hitter' to the actual dagger, and not the
839 * wrapper object. 832 * wrapper object.
840 */ 833 */
841 thrown_item_effect (hitter, op); 834 thrown_item_effect (hitter, op);
842 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 835 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
843 goto leave; 836 goto leave;
844 } 837 }
845 838
846 /* Need to do at least 1 damage, otherwise there is no point 839 /* Need to do at least 1 damage, otherwise there is no point
847 * to go further and it will cause FPE's below. 840 * to go further and it will cause FPE's below.
848 */ 841 */
849 if (hitdam <= 0) 842 if (hitdam <= 0)
850 hitdam = 1; 843 hitdam = 1;
851 844
852 type = hitter->attacktype; 845 type = hitter->attacktype;
846
853 if (!type) 847 if (!type)
854 type = AT_PHYSICAL; 848 type = AT_PHYSICAL;
849
855 /* Handle monsters that hit back */ 850 /* Handle monsters that hit back */
856 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE)) 851 if (!simple_attack && QUERY_FLAG (op, FLAG_HITBACK) && QUERY_FLAG (hitter, FLAG_ALIVE))
857 { 852 {
858 if (op->attacktype & AT_ACID && hitter->type == PLAYER) 853 if (op->attacktype & AT_ACID && hitter->type == PLAYER)
859 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n"); 854 new_draw_info (NDI_UNIQUE, 0, hitter, "You are splashed by acid!\n");
855
860 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1); 856 hit_player (hitter, random_roll (0, (op->stats.dam), hitter, PREFER_LOW), op, op->attacktype, 1);
857
861 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 858 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
862 goto leave; 859 goto leave;
863 } 860 }
864 861
865 /* In the new attack code, it should handle multiple attack 862 /* In the new attack code, it should handle multiple attack
866 * types in its area, so remove it from here. 863 * types in its area, so remove it from here.
867 */ 864 */
868 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1); 865 dam = hit_player (op, random_roll (1, hitdam, hitter, PREFER_HIGH), hitter, type, 1);
866
869 if (was_destroyed (op, op_tag) || was_destroyed (hitter, hitter_tag) || abort_attack (op, hitter, simple_attack)) 867 if (op->destroyed () || hitter->destroyed () || abort_attack (op, hitter, simple_attack))
870 goto leave; 868 goto leave;
871 } /* end of if hitter hit op */ 869 } /* end of if hitter hit op */
872 /* if we missed, dam=0 */ 870 /* if we missed, dam=0 */
873 871
874 /*attack_message(dam, type, op, hitter); */ 872 /*attack_message(dam, type, op, hitter); */
931object * 929object *
932hit_with_arrow (object *op, object *victim) 930hit_with_arrow (object *op, object *victim)
933{ 931{
934 object *container, *hitter; 932 object *container, *hitter;
935 int hit_something = 0; 933 int hit_something = 0;
936 tag_t victim_tag, hitter_tag;
937 sint16 victim_x, victim_y;
938 934
939 /* Disassemble missile */ 935 /* Disassemble missile */
940 if (op->inv) 936 if (op->inv)
941 { 937 {
942 container = op; 938 container = op;
948 * removed at the end of this function must be able to deal with empty 944 * removed at the end of this function must be able to deal with empty
949 * THROWN_OBJs. */ 945 * THROWN_OBJs. */
950 } 946 }
951 else 947 else
952 { 948 {
953 container = NULL; 949 container = 0;
954 hitter = op; 950 hitter = op;
955 } 951 }
956 952
957 /* Try to hit victim */ 953 /* 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); 954 hit_something = attack_ob_simple (victim, hitter, op->stats.dam, op->stats.wc);
964 955
965 /* Arrow attacks door, rune of summoning is triggered, demon is put on 956 /* Arrow attacks door, rune of summoning is triggered, demon is put on
966 * arrow, move_apply() calls this function, arrow sticks in demon, 957 * arrow, move_apply() calls this function, arrow sticks in demon,
967 * attack_ob_simple() returns, and we've got an arrow that still exists 958 * attack_ob_simple() returns, and we've got an arrow that still exists
968 * but is no longer on the map. Ugh. (Beware: Such things can happen at 959 * but is no longer on the map. Ugh. (Beware: Such things can happen at
969 * other places as well!) 960 * other places as well!)
970 */ 961 */
971 if (was_destroyed (hitter, hitter_tag) || hitter->env != NULL) 962 if (hitter->destroyed () || hitter->env != NULL)
972 { 963 {
973 if (container) 964 if (container)
974 { 965 {
975 remove_ob (container); 966 remove_ob (container);
976 free_object (container); 967 free_object (container);
977 } 968 }
969
978 return NULL; 970 return 0;
979 } 971 }
980 972
981 /* Missile hit victim */ 973 /* Missile hit victim */
982 /* if the speed is > 10, then this is a fast moving arrow, we go straight 974 /* if the speed is > 10, then this is a fast moving arrow, we go straight
983 * through the target 975 * through the target
984 */ 976 */
985 if (hit_something && op->speed <= 10.0) 977 if (hit_something && op->speed <= 10.0)
986 { 978 {
987 /* Stop arrow */ 979 /* Stop arrow */
988 if (container == NULL) 980 if (!container)
989 { 981 {
990 hitter = fix_stopped_arrow (hitter); 982 hitter = fix_stopped_arrow (hitter);
991 if (hitter == NULL) 983 if (!hitter)
992 return NULL; 984 return 0;
993 } 985 }
994 else 986 else
995 { 987 {
996 remove_ob (container); 988 remove_ob (container);
997 free_object (container); 989 free_object (container);
998 } 990 }
999 991
1000 /* Try to stick arrow into victim */ 992 /* Try to stick arrow into victim */
1001 if (!was_destroyed (victim, victim_tag) && stick_arrow (hitter, victim)) 993 if (!victim->destroyed () && stick_arrow (hitter, victim))
1002 return NULL; 994 return 0;
1003 995
1004 /* Else try to put arrow on victim's map square 996 /* Else try to put arrow on victim's map square
1005 * remove check for P_WALL here. If the arrow got to this 997 * remove check for P_WALL here. If the arrow got to this
1006 * space, that is good enough - with the new movement code, 998 * space, that is good enough - with the new movement code,
1007 * there is now the potential for lots of spaces where something 999 * there is now the potential for lots of spaces where something
1008 * can fly over but not otherwise move over. What is the correct 1000 * can fly over but not otherwise move over. What is the correct
1009 * way to handle those otherwise? 1001 * way to handle those otherwise?
1010 */ 1002 */
1011 if (victim_x != hitter->x || victim_y != hitter->y) 1003 if (victim->x != hitter->x || victim->y != hitter->y)
1012 { 1004 {
1013 remove_ob (hitter); 1005 remove_ob (hitter);
1014 hitter->x = victim_x; 1006 hitter->x = victim->x;
1015 hitter->y = victim_y; 1007 hitter->y = victim->y;
1016 insert_ob_in_map (hitter, victim->map, hitter, 0); 1008 insert_ob_in_map (hitter, victim->map, hitter, 0);
1017 } 1009 }
1018 else 1010 else
1019 {
1020 /* Else leave arrow where it is */ 1011 /* Else leave arrow where it is */
1021 merge_ob (hitter, NULL); 1012 merge_ob (hitter, NULL);
1022 } 1013
1023 return NULL; 1014 return 0;
1024 } 1015 }
1025 1016
1026 if (hit_something && op->speed >= 10.0) 1017 if (hit_something && op->speed >= 10.0)
1027 op->speed -= 1.0; 1018 op->speed -= 1.0;
1028 1019
1030 if (container) 1021 if (container)
1031 { 1022 {
1032 remove_ob (hitter); 1023 remove_ob (hitter);
1033 insert_ob_in_ob (hitter, container); 1024 insert_ob_in_ob (hitter, container);
1034 } 1025 }
1026
1035 return op; 1027 return op;
1036} 1028}
1037 1029
1038 1030
1039void 1031void
1328 break; 1320 break;
1329 case ATNR_TURN_UNDEAD: 1321 case ATNR_TURN_UNDEAD:
1330 { 1322 {
1331 if (QUERY_FLAG (op, FLAG_UNDEAD)) 1323 if (QUERY_FLAG (op, FLAG_UNDEAD))
1332 { 1324 {
1333 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter); 1325 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1334 object *god = find_god (determine_god (owner)); 1326 object *god = find_god (determine_god (owner));
1335 int div = 1; 1327 int div = 1;
1336 1328
1337 /* if undead are not an enemy of your god, you turn them 1329 /* if undead are not an enemy of your god, you turn them
1338 * at half strength */ 1330 * at half strength */
1364 break; 1356 break;
1365 case ATNR_HOLYWORD: 1357 case ATNR_HOLYWORD:
1366 { 1358 {
1367 /* This has already been handled by hit_player, 1359 /* This has already been handled by hit_player,
1368 * no need to check twice -- DAMN */ 1360 * no need to check twice -- DAMN */
1369 1361 object *owner = hitter->owner ? (object *)hitter->owner : hitter;
1370 object *owner = get_owner (hitter) == NULL ? hitter : get_owner (hitter);
1371 1362
1372 /* As with turn undead above, give a bonus on the saving throw */ 1363 /* As with turn undead above, give a bonus on the saving throw */
1373 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis]) 1364 if ((op->level + (op->resist[ATNR_HOLYWORD] / 100)) < owner->level + turn_bonus[owner->stats.Wis])
1374 scare_creature (op, owner); 1365 scare_creature (op, owner);
1375 } 1366 }
1455 op->speed = 0.1; 1446 op->speed = 0.1;
1456 update_ob_speed (op); 1447 update_ob_speed (op);
1457 op->speed_left = -0.05; 1448 op->speed_left = -0.05;
1458 return maxdam; 1449 return maxdam;
1459 } 1450 }
1451
1460 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER) 1452 if (QUERY_FLAG (op, FLAG_FRIENDLY) && op->type != PLAYER)
1461 { 1453 {
1462 remove_friendly_object (op); 1454 remove_friendly_object (op);
1463 if (get_owner (op) != NULL && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op) 1455 if (get_owner (op) && op->owner->type == PLAYER && op->owner->contr->ranges[range_golem] == op)
1464 { 1456 {
1465 op->owner->contr->ranges[range_golem] = NULL; 1457 op->owner->contr->ranges[range_golem] = 0;
1466 op->owner->contr->golem_count = 0; 1458 op->owner->contr->golem_count = 0;
1467 } 1459 }
1468 1460
1469 remove_ob (op); 1461 remove_ob (op);
1470 free_object (op); 1462 free_object (op);
1472 } 1464 }
1473 1465
1474 /* Now lets start dealing with experience we get for killing something */ 1466 /* Now lets start dealing with experience we get for killing something */
1475 1467
1476 owner = get_owner (hitter); 1468 owner = get_owner (hitter);
1477 if (owner == NULL) 1469 if (!owner)
1478 owner = hitter; 1470 owner = hitter;
1479 1471
1480 /* is the victim (op) standing on battleground? */ 1472 /* is the victim (op) standing on battleground? */
1481 if (op_on_battleground (op, NULL, NULL)) 1473 if (op_on_battleground (op, NULL, NULL))
1482 battleg = 1; 1474 battleg = 1;
1512 * probably don't want to see that. 1504 * probably don't want to see that.
1513 */ 1505 */
1514 if (owner->level < op->level * 2 || op->stats.exp > 1000) 1506 if (owner->level < op->level * 2 || op->stats.exp > 1000)
1515 { 1507 {
1516 if (owner != hitter) 1508 if (owner != hitter)
1517 {
1518 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter)); 1509 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s with %s.", query_name (op), query_name (hitter));
1519 }
1520 else 1510 else
1521 {
1522 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op)); 1511 new_draw_info_format (NDI_BLACK, 0, owner, "You killed %s.", query_name (op));
1523 } 1512
1524 /* Only play sounds for melee kills */ 1513 /* Only play sounds for melee kills */
1525 if (hitter->type == PLAYER) 1514 if (hitter->type == PLAYER)
1526 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS); 1515 play_sound_map (owner->map, owner->x, owner->y, SOUND_PLAYER_KILLS);
1527 } 1516 }
1528 1517
1539 1528
1540 /* This code below deals with finding the appropriate skill 1529 /* This code below deals with finding the appropriate skill
1541 * to credit exp to. This is a bit problematic - we should 1530 * to credit exp to. This is a bit problematic - we should
1542 * probably never really have to look at current_weapon->skill 1531 * probably never really have to look at current_weapon->skill
1543 */ 1532 */
1544 skill = NULL; 1533 skill = 0;
1534
1545 if (hitter->skill && hitter->type != PLAYER) 1535 if (hitter->skill && hitter->type != PLAYER)
1546 skill = hitter->skill; 1536 skill = hitter->skill;
1547 else if (owner->chosen_skill) 1537 else if (owner->chosen_skill)
1548 { 1538 {
1549 skill = owner->chosen_skill->skill; 1539 skill = owner->chosen_skill->skill;
1568 break; 1558 break;
1569 } 1559 }
1570 } 1560 }
1571 } /* Was it a player that hit somethign */ 1561 } /* Was it a player that hit somethign */
1572 else 1562 else
1573 {
1574 skill = NULL; 1563 skill = 0;
1575 }
1576 1564
1577 /* Pet (or spell) killed something. */ 1565 /* Pet (or spell) killed something. */
1578 if (owner != hitter) 1566 if (owner != hitter)
1579 {
1580 (void) sprintf (buf, "%s killed %s with %s%s%s.", &owner->name, 1567 sprintf (buf, "%s killed %s with %s%s%s.", &owner->name,
1581 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1568 query_name (op), query_name (hitter), battleg ? " (duel)" : "", pk ? " (pk)" : "");
1582 }
1583 else 1569 else
1584 {
1585 (void) sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name, 1570 sprintf (buf, "%s killed %s%s%s%s.", &hitter->name, &op->name,
1586 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ? 1571 (QUERY_FLAG (hitter, FLAG_MONSTER)) || hitter->type == PLAYER ?
1587 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : ""); 1572 " in hand to hand combat" : "", battleg ? " (duel)" : "", pk ? " (pk)" : "");
1588 } 1573
1589 /* These may have been set in the player code section above */ 1574 /* These may have been set in the player code section above */
1590 if (!skop) 1575 if (!skop)
1591 skop = hitter->chosen_skill; 1576 skop = hitter->chosen_skill;
1577
1592 if (!skill && skop) 1578 if (!skill && skop)
1593 skill = skop->skill; 1579 skill = skop->skill;
1594 1580
1595 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf); 1581 new_draw_info (NDI_ALL, op->type == PLAYER ? 1 : 10, NULL, buf);
1596 1582
1597
1598 /* If you didn't kill yourself, and your not the wizard */ 1583 /* If you didn't kill yourself, and your not the wizard */
1599 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ)) 1584 if (owner != op && !QUERY_FLAG (op, FLAG_WAS_WIZ))
1600 { 1585 {
1601 int exp; 1586 int exp;
1602 1587
1603 /* Really don't give much experience for killing other players */ 1588 /* Really don't give much experience for killing other players */
1604 // schmorp: temporary? reduce the amount of exp gained for pking enourmously 1589 // schmorp: temporarily? reduce the amount of exp gained for pking enourmously
1605 if (op->type == PLAYER) 1590 if (op->type == PLAYER)
1606 { 1591 {
1607 if (battleg) 1592 if (battleg)
1608 { 1593 {
1609 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!"); 1594 new_draw_info (NDI_UNIQUE, 0, owner, "Your foe has fallen!");
1633 change_exp (owner, exp, skill, 0); 1618 change_exp (owner, exp, skill, 0);
1634 } 1619 }
1635 else 1620 else
1636 { 1621 {
1637 int shares = 0, count = 0; 1622 int shares = 0, count = 0;
1638
1639 player *pl; 1623 player *pl;
1640
1641 partylist *party = owner->contr->party; 1624 partylist *party = owner->contr->party;
1642 1625
1643#ifdef PARTY_KILL_LOG 1626#ifdef PARTY_KILL_LOG
1644 add_kill_to_party (party, query_name (owner), query_name (op), exp); 1627 add_kill_to_party (party, query_name (owner), query_name (op), exp);
1645#endif 1628#endif
1646 for (pl = first_player; pl != NULL; pl = pl->next) 1629 for (pl = first_player; pl != NULL; pl = pl->next)
1647 {
1648 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1630 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1649 { 1631 {
1650 count++; 1632 count++;
1651 shares += (pl->ob->level + 4); 1633 shares += (pl->ob->level + 4);
1652 } 1634 }
1653 } 1635
1654 if (count == 1 || shares > exp) 1636 if (count == 1 || shares > exp)
1655 change_exp (owner, exp, skill, SK_EXP_TOTAL); 1637 change_exp (owner, exp, skill, SK_EXP_TOTAL);
1656 else 1638 else
1657 { 1639 {
1658 int share = exp / shares, given = 0, nexp; 1640 int share = exp / shares, given = 0, nexp;
1659 1641
1660 for (pl = first_player; pl != NULL; pl = pl->next) 1642 for (pl = first_player; pl != NULL; pl = pl->next)
1661 {
1662 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner)) 1643 if (party && pl->ob->contr->party == party && on_same_map (pl->ob, owner))
1663 { 1644 {
1664 nexp = (pl->ob->level + 4) * share; 1645 nexp = (pl->ob->level + 4) * share;
1665 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL); 1646 change_exp (pl->ob, nexp, skill, SK_EXP_TOTAL);
1666 given += nexp; 1647 given += nexp;
1667 } 1648 }
1668 } 1649
1669 exp -= given; 1650 exp -= given;
1670 /* give any remainder to the player */ 1651 /* give any remainder to the player */
1671 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL); 1652 change_exp (owner, exp, skill, SK_EXP_ADD_SKILL);
1672 } 1653 }
1673 } /* else part of a party */ 1654 } /* else part of a party */
1674
1675 } /* end if person didn't kill himself */ 1655 } /* end if person didn't kill himself */
1676 1656
1677 if (op->type != PLAYER) 1657 if (op->type != PLAYER)
1678 { 1658 {
1679 if (QUERY_FLAG (op, FLAG_FRIENDLY)) 1659 if (QUERY_FLAG (op, FLAG_FRIENDLY))
1680 { 1660 {
1681 object *owner1 = get_owner (op); 1661 object *owner1 = get_owner (op);
1682 1662
1683 if (owner1 != NULL && owner1->type == PLAYER) 1663 if (owner1 && owner1->type == PLAYER)
1684 { 1664 {
1685 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0); 1665 play_sound_player_only (owner1->contr, SOUND_PET_IS_KILLED, 0, 0);
1686 /* Maybe we should include the owner that killed this, maybe not */ 1666 /* 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); 1667 new_draw_info_format (NDI_UNIQUE, 0, owner1, "Your pet, the %s, is killed by %s.", &op->name, &hitter->name);
1688 } 1668 }
1669
1689 remove_friendly_object (op); 1670 remove_friendly_object (op);
1690 } 1671 }
1672
1691 remove_ob (op); 1673 remove_ob (op);
1692 free_object (op); 1674 free_object (op);
1693 } 1675 }
1694 /* Player has been killed! */
1695 else 1676 else
1696 { 1677 {
1678 /* Player has been killed! */
1697 if (owner->type == PLAYER) 1679 if (owner->type == PLAYER)
1698 {
1699 snprintf (op->contr->killer, BIG_NAME, "%s the %s", &owner->name, owner->contr->title); 1680 snprintf (op->contr->killer, sizeof (op->contr->killer), "%s the %s", &owner->name, owner->contr->title);
1700 }
1701 else 1681 else
1702 {
1703 strncpy (op->contr->killer, hitter->name, BIG_NAME); 1682 assign (op->contr->killer, hitter->name);
1704 op->contr->killer[BIG_NAME - 1] = '\0';
1705 }
1706 } 1683 }
1684
1707 /* This was return -1 - that doesn't seem correct - if we return -1, process 1685 /* This was return -1 - that doesn't seem correct - if we return -1, process
1708 * continues in the calling function. 1686 * continues in the calling function.
1709 */ 1687 */
1710 return maxdam; 1688 return maxdam;
1711} 1689}
1762{ 1740{
1763 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC); 1741 int maxdam = 0, ndam = 0, attacktype = 1, magic = (type & AT_MAGIC);
1764 int maxattacktype, attacknum; 1742 int maxattacktype, attacknum;
1765 int body_attack = op && op->head; /* Did we hit op's head? */ 1743 int body_attack = op && op->head; /* Did we hit op's head? */
1766 int simple_attack; 1744 int simple_attack;
1767 tag_t op_tag, hitter_tag;
1768 int rtn_kill = 0; 1745 int rtn_kill = 0;
1769 int friendlyfire; 1746 int friendlyfire;
1770 1747
1771 if (get_attack_mode (&op, &hitter, &simple_attack)) 1748 if (get_attack_mode (&op, &hitter, &simple_attack))
1772 return 0; 1749 return 0;
1780 { 1757 {
1781 object *owner = get_owner (hitter); 1758 object *owner = get_owner (hitter);
1782 1759
1783 if (!owner) 1760 if (!owner)
1784 owner = hitter; 1761 owner = hitter;
1762
1785 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner) 1763 if (owner->type == PLAYER && (!op_on_battleground (op, 0, 0) && (op->contr->peaceful || owner->contr->peaceful)) && op != owner)
1786 {
1787 return 0; 1764 return 0;
1788 }
1789 } 1765 }
1790#endif 1766#endif
1791
1792 op_tag = op->count;
1793 hitter_tag = hitter->count;
1794 1767
1795 if (body_attack) 1768 if (body_attack)
1796 { 1769 {
1797 /* slow and paralyze must hit the head. But we don't want to just 1770 /* 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 1771 * return - we still need to process other attacks the spell still
1804 * attack so we don't cancel out things like magic bullet. 1777 * attack so we don't cancel out things like magic bullet.
1805 */ 1778 */
1806 if (type & (AT_PARALYZE | AT_SLOW)) 1779 if (type & (AT_PARALYZE | AT_SLOW))
1807 { 1780 {
1808 type &= ~(AT_PARALYZE | AT_SLOW); 1781 type &= ~(AT_PARALYZE | AT_SLOW);
1782
1809 if (!type || type == AT_MAGIC) 1783 if (!type || type == AT_MAGIC)
1810 return 0; 1784 return 0;
1811 } 1785 }
1812 } 1786 }
1813 1787
1817 1791
1818 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 1792 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1819 if (tmp->type == RUNE || tmp->type == TRAP) 1793 if (tmp->type == RUNE || tmp->type == TRAP)
1820 { 1794 {
1821 spring_trap (tmp, hitter); 1795 spring_trap (tmp, hitter);
1822 if (was_destroyed (hitter, hitter_tag) || was_destroyed (op, op_tag) || abort_attack (op, hitter, simple_attack)) 1796 if (hitter->destroyed () || op->destroyed () || abort_attack (op, hitter, simple_attack))
1823 return 0; 1797 return 0;
1824 break; 1798 break;
1825 } 1799 }
1826 } 1800 }
1827 1801
1828 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0) 1802 if (!QUERY_FLAG (op, FLAG_ALIVE) || op->stats.hp < 0)
1829 { 1803 {
1830 /* FIXME: If a player is killed by a rune in a door, the 1804 /* 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. 1805 * destroyed() check above doesn't return, and might get here.
1832 */ 1806 */
1833 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name); 1807 LOG (llevDebug, "victim (arch %s, name %s) already dead in " "hit_player()\n", &op->arch->name, &op->name);
1834 return 0; 1808 return 0;
1835 } 1809 }
1836 1810
2055 2029
2056 2030
2057void 2031void
2058poison_player (object *op, object *hitter, int dam) 2032poison_player (object *op, object *hitter, int dam)
2059{ 2033{
2060 archetype *at = find_archetype ("poisoning"); 2034 archetype *at = archetype::find ("poisoning");
2061 object *tmp = present_arch_in_ob (at, op); 2035 object *tmp = present_arch_in_ob (at, op);
2062 2036
2063 if (tmp == NULL) 2037 if (tmp == NULL)
2064 { 2038 {
2065 if ((tmp = arch_to_object (at)) == NULL) 2039 if ((tmp = arch_to_object (at)) == NULL)
2111} 2085}
2112 2086
2113void 2087void
2114slow_player (object *op, object *hitter, int dam) 2088slow_player (object *op, object *hitter, int dam)
2115{ 2089{
2116 archetype *at = find_archetype ("slowness"); 2090 archetype *at = archetype::find ("slowness");
2117 object *tmp; 2091 object *tmp;
2118 2092
2119 if (at == NULL) 2093 if (at == NULL)
2120 { 2094 {
2121 LOG (llevError, "Can't find slowness archetype.\n"); 2095 LOG (llevError, "Can't find slowness archetype.\n");

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines