ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_attack.C
(Generate patch)

Comparing deliantra/server/server/spell_attack.C (file contents):
Revision 1.24 by root, Tue Dec 26 08:55:00 2006 UTC vs.
Revision 1.29 by root, Mon Jan 29 16:11:48 2007 UTC

1/* 1/*
2 CrossFire, A Multiplayer game for X-windows 2 * CrossFire, A Multiplayer game for X-windows
3 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
4 Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2002-2003 Mark Wedel & Crossfire Development Team
5 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
6 7 *
7 This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version. 11 * (at your option) any later version.
11 12 *
12 This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details. 16 * GNU General Public License for more details.
16 17 *
17 You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 21 *
21 The authors can be reached via e-mail at <crossfire@schmorp.de> 22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
22*/ 23 */
23 24
24/* This file contains all the spell attack code. Grouping this code 25/* This file contains all the spell attack code. Grouping this code
25 * together should hopefully make it easier to find the relevent bits 26 * together should hopefully make it easier to find the relevent bits
26 * of code 27 * of code
27 */ 28 */
147 tmp->stats.Dex -= 10; /* less forks from main bolt too */ 148 tmp->stats.Dex -= 10; /* less forks from main bolt too */
148 new_bolt->stats.Con += 25 * new_dir; /* adjust the left bias */ 149 new_bolt->stats.Con += 25 * new_dir; /* adjust the left bias */
149 new_bolt->speed_left = -0.1; 150 new_bolt->speed_left = -0.1;
150 new_bolt->direction = t_dir; 151 new_bolt->direction = t_dir;
151 new_bolt->duration++; 152 new_bolt->duration++;
152 new_bolt->x = sx;
153 new_bolt->y = sy;
154 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */ 153 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */
155 new_bolt->stats.dam++; 154 new_bolt->stats.dam++;
156 tmp->stats.dam /= 2; /* reduce father bolt damage */ 155 tmp->stats.dam /= 2; /* reduce father bolt damage */
157 tmp->stats.dam++; 156 tmp->stats.dam++;
158 new_bolt = insert_ob_in_map (new_bolt, m, op, 0); 157 if ((new_bolt = m->insert (new_bolt, sx, sy, op)))
159 update_turn_face (new_bolt); 158 update_turn_face (new_bolt);
160} 159}
161 160
162/* move_bolt: moves bolt 'op'. Basically, it just advances a space, 161/* move_bolt: moves bolt 'op'. Basically, it just advances a space,
163 * and checks for various things that may stop it. 162 * and checks for various things that may stop it.
164 */ 163 */
169 object *tmp; 168 object *tmp;
170 int mflags; 169 int mflags;
171 sint16 x, y; 170 sint16 x, y;
172 maptile *m; 171 maptile *m;
173 172
174 if (--(op->duration) < 0) 173 if (--op->duration < 0)
175 { 174 {
176 op->destroy (); 175 op->destroy ();
177 return; 176 return;
178 } 177 }
179 178
181 180
182 if (!op->direction) 181 if (!op->direction)
183 return; 182 return;
184 183
185 if (--op->range < 0) 184 if (--op->range < 0)
186 {
187 op->range = 0; 185 op->range = 0;
188 }
189 else 186 else
190 { 187 {
191 x = op->x + DIRX (op); 188 x = op->x + DIRX (op);
192 y = op->y + DIRY (op); 189 y = op->y + DIRY (op);
193 m = op->map; 190 m = op->map;
201 * on the space. So only call reflwall if we think the data it returns 198 * on the space. So only call reflwall if we think the data it returns
202 * will be useful. 199 * will be useful.
203 */ 200 */
204 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)) || ((mflags & P_IS_ALIVE) && reflwall (m, x, y, op))) 201 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)) || ((mflags & P_IS_ALIVE) && reflwall (m, x, y, op)))
205 { 202 {
206
207 if (!QUERY_FLAG (op, FLAG_REFLECTING)) 203 if (!QUERY_FLAG (op, FLAG_REFLECTING))
208 return; 204 return;
209 205
210 /* Since walls don't run diagonal, if the bolt is in 206 /* Since walls don't run diagonal, if the bolt is in
211 * one of 4 main directions, it just reflects back in the 207 * one of 4 main directions, it just reflects back in the
241 else if (left) 237 else if (left)
242 op->direction = absdir (op->direction + 2); 238 op->direction = absdir (op->direction + 2);
243 else if (right) 239 else if (right)
244 op->direction = absdir (op->direction - 2); 240 op->direction = absdir (op->direction - 2);
245 } 241 }
242
246 update_turn_face (op); /* A bolt *must* be IS_TURNABLE */ 243 update_turn_face (op); /* A bolt *must* be IS_TURNABLE */
247 return; 244 return;
248 } 245 }
249 else 246 else
250 { /* Create a copy of this object and put it ahead */ 247 { /* Create a copy of this object and put it ahead */
251 tmp = op->clone (); 248 object *tmp = op->clone ();
252 249
250 m->insert (tmp, x, y, op);
253 tmp->speed_left = -0.1; 251 tmp->speed_left = -0.1;
254 tmp->x += DIRX (tmp), tmp->y += DIRY (tmp);
255 tmp = insert_ob_in_map (tmp, op->map, op, 0);
256 /* To make up for the decrease at the top of the function */ 252 /* To make up for the decrease at the top of the function */
257 tmp->duration++; 253 tmp->duration++;
258 254
259 /* New forking code. Possibly create forks of this object 255 /* New forking code. Possibly create forks of this object
260 * going off in other directions. 256 * going off in other directions.
261 */ 257 */
262
263 if (rndm (0, 99) < tmp->stats.Dex) 258 if (rndm (0, 99) < tmp->stats.Dex)
264 { /* stats.Dex % of forking */ 259 { /* stats.Dex % of forking */
265 forklightning (op, tmp); 260 forklightning (op, tmp);
266 } 261 }
262
267 /* In this way, the object left behind sticks on the space, but 263 /* In this way, the object left behind sticks on the space, but
268 * doesn't create any bolts that continue to move onward. 264 * doesn't create any bolts that continue to move onward.
269 */ 265 */
270 op->range = 0; 266 op->range = 0;
271 } /* copy object and move it along */ 267 } /* copy object and move it along */
336 tmp->y = op->y; 332 tmp->y = op->y;
337 tmp->direction = absdir (tmp->direction + 4); 333 tmp->direction = absdir (tmp->direction + 4);
338 tmp->map = op->map; 334 tmp->map = op->map;
339 } 335 }
340 336
341 if ((tmp = insert_ob_in_map (tmp, tmp->map, op, 0)) != NULL) 337 if ((tmp = tmp->insert_at (tmp, op)))
342 move_bolt (tmp); 338 move_bolt (tmp);
343 339
344 return 1; 340 return 1;
345} 341}
346 342
357 * At least that is what I think this does. 353 * At least that is what I think this does.
358 */ 354 */
359void 355void
360explosion (object *op) 356explosion (object *op)
361{ 357{
362 object *tmp;
363 maptile *m = op->map; 358 maptile *m = op->map;
364 int i; 359 int i;
365 360
366 if (--(op->duration) < 0) 361 if (--op->duration < 0)
367 { 362 {
368 op->destroy (); 363 op->destroy ();
369 return; 364 return;
370 } 365 }
371 366
377 { 372 {
378 sint16 dx, dy; 373 sint16 dx, dy;
379 374
380 dx = op->x + freearr_x[i]; 375 dx = op->x + freearr_x[i];
381 dy = op->y + freearr_y[i]; 376 dy = op->y + freearr_y[i];
377
382 /* ok_to_put_more already does things like checks for walls, 378 /* ok_to_put_more already does things like checks for walls,
383 * out of map, etc. 379 * out of map, etc.
384 */ 380 */
385 if (ok_to_put_more (op->map, dx, dy, op, op->attacktype)) 381 if (ok_to_put_more (op->map, dx, dy, op, op->attacktype))
386 { 382 {
387 tmp = op->clone (); 383 object *tmp = op->clone ();
384
388 tmp->state = 0; 385 tmp->state = 0;
389 tmp->speed_left = -0.21; 386 tmp->speed_left = -0.21;
390 tmp->range--; 387 tmp->range--;
391 tmp->value = 0; 388 tmp->value = 0;
392 tmp->x = dx; 389
393 tmp->y = dy; 390 m->insert (tmp, dx, dy, op);
394 insert_ob_in_map (tmp, m, op, 0);
395 } 391 }
396 } 392 }
397 } 393 }
398} 394}
399 395
414 return; 410 return;
415 } 411 }
416 412
417 if (op->env) 413 if (op->env)
418 { 414 {
419 object *env;
420
421 env = object_get_env_recursive (op); 415 object *env = object_get_env_recursive (op);
422 if (env->map == NULL || out_of_map (env->map, env->x, env->y)) 416 if (env->map == NULL || out_of_map (env->map, env->x, env->y))
423 { 417 {
424 LOG (llevError, "BUG: explode_bullet(): env out of map\n"); 418 LOG (llevError, "BUG: explode_bullet(): env out of map\n");
425 op->destroy (); 419 op->destroy ();
426 return; 420 return;
427 } 421 }
428 422
429 op->remove (); 423 op->insert_at (env, op, INS_NO_MERGE | INS_NO_WALK_ON);
430 op->x = env->x;
431 op->y = env->y;
432 insert_ob_in_map (op, env->map, op, INS_NO_MERGE | INS_NO_WALK_ON);
433 } 424 }
434 else if (out_of_map (op->map, op->x, op->y)) 425 else if (out_of_map (op->map, op->x, op->y))
435 { 426 {
436 LOG (llevError, "BUG: explode_bullet(): op out of map\n"); 427 LOG (llevError, "BUG: explode_bullet(): op out of map\n");
437 op->destroy (); 428 op->destroy ();
466 { 457 {
467 op->destroy (); 458 op->destroy ();
468 return; 459 return;
469 } 460 }
470 461
471 tmp->x = op->x;
472 tmp->y = op->y;
473
474 /* special for bombs - it actually has sane values for these */ 462 /* special for bombs - it actually has sane values for these */
475 if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB) 463 if (op->type == SPELL_EFFECT && op->subtype == SP_BOMB)
476 { 464 {
477 tmp->attacktype = op->attacktype; 465 tmp->attacktype = op->attacktype;
478 tmp->range = op->range; 466 tmp->range = op->range;
481 } 469 }
482 else 470 else
483 { 471 {
484 if (op->attacktype & AT_MAGIC) 472 if (op->attacktype & AT_MAGIC)
485 tmp->attacktype |= AT_MAGIC; 473 tmp->attacktype |= AT_MAGIC;
474
486 /* Spell doc describes what is going on here */ 475 /* Spell doc describes what is going on here */
487 tmp->stats.dam = op->dam_modifier; 476 tmp->stats.dam = op->dam_modifier;
488 tmp->range = op->stats.maxhp; 477 tmp->range = op->stats.maxhp;
489 tmp->duration = op->stats.hp; 478 tmp->duration = op->stats.hp;
490 /* Used for spell tracking - just need a unique val for this spell - 479 /* Used for spell tracking - just need a unique val for this spell -
498 tmp->stats.sp = op->direction; 487 tmp->stats.sp = op->direction;
499 488
500 /* Prevent recursion */ 489 /* Prevent recursion */
501 op->move_on = 0; 490 op->move_on = 0;
502 491
503 insert_ob_in_map (tmp, op->map, op, 0); 492 tmp->insert_at (op, op);
504 /* remove the firebullet */ 493 /* remove the firebullet */
505 if (!op->destroyed ())
506 {
507 op->destroy (); 494 op->destroy ();
508 }
509} 495}
510
511
512 496
513/* checks to see what op should do, given the space it is on 497/* checks to see what op should do, given the space it is on
514 * (eg, explode, damage player, etc) 498 * (eg, explode, damage player, etc)
515 */ 499 */
516
517void 500void
518check_bullet (object *op) 501check_bullet (object *op)
519{ 502{
520 object *tmp; 503 object *tmp;
521 int dam, mflags; 504 int dam, mflags;
610 op->destroy (); 593 op->destroy ();
611 594
612 return; 595 return;
613 } 596 }
614 597
615 op->remove (); 598 if (!(op = m->insert (op, new_x, new_y, op)))
616 op->x = new_x;
617 op->y = new_y;
618 if ((op = insert_ob_in_map (op, m, op, 0)) == NULL)
619 return; 599 return;
620 600
621 if (reflwall (op->map, op->x, op->y, op)) 601 if (reflwall (op->map, op->x, op->y, op))
622 { 602 {
623 op->direction = absdir (op->direction + 4); 603 op->direction = absdir (op->direction + 4);
698 tmp->y = op->y; 678 tmp->y = op->y;
699 tmp->direction = absdir (tmp->direction + 4); 679 tmp->direction = absdir (tmp->direction + 4);
700 tmp->map = op->map; 680 tmp->map = op->map;
701 } 681 }
702 682
703 if ((tmp = insert_ob_in_map (tmp, tmp->map, op, 0))) 683 if ((tmp = tmp->insert_at (tmp, op)))
704 check_bullet (tmp); 684 check_bullet (tmp);
705 685
706 return 1; 686 return 1;
707} 687}
708 688
720void 700void
721cone_drop (object *op) 701cone_drop (object *op)
722{ 702{
723 object *new_ob = arch_to_object (op->other_arch); 703 object *new_ob = arch_to_object (op->other_arch);
724 704
725 new_ob->x = op->x;
726 new_ob->y = op->y;
727 new_ob->level = op->level; 705 new_ob->level = op->level;
728 new_ob->set_owner (op->owner); 706 new_ob->set_owner (op->owner);
729 707
730 /* preserve skill ownership */ 708 /* preserve skill ownership */
731 if (op->skill && op->skill != new_ob->skill) 709 if (op->skill && op->skill != new_ob->skill)
732 {
733 new_ob->skill = op->skill; 710 new_ob->skill = op->skill;
734 }
735 insert_ob_in_map (new_ob, op->map, op, 0);
736 711
712 new_ob->insert_at (op, op);
737} 713}
738 714
739/* move_cone: causes cone object 'op' to move a space/hit creatures */ 715/* move_cone: causes cone object 'op' to move a space/hit creatures */
740 716
741void 717void
803 779
804 if (ok_to_put_more (op->map, x, y, op, op->attacktype)) 780 if (ok_to_put_more (op->map, x, y, op, op->attacktype))
805 { 781 {
806 object *tmp = op->clone (); 782 object *tmp = op->clone ();
807 783
808 tmp->x = x;
809 tmp->y = y;
810
811 tmp->duration = op->duration + 1; 784 tmp->duration = op->duration + 1;
812 785
813 /* Use for spell tracking - see ok_to_put_more() */ 786 /* Use for spell tracking - see ok_to_put_more() */
814 tmp->stats.maxhp = op->stats.maxhp; 787 tmp->stats.maxhp = op->stats.maxhp;
815 insert_ob_in_map (tmp, op->map, op, 0); 788
789 op->map->insert (tmp, x, y, op);
790
816 if (tmp->other_arch) 791 if (tmp->other_arch)
817 cone_drop (tmp); 792 cone_drop (tmp);
818 } 793 }
819 } 794 }
820} 795}
899 success = 1; 874 success = 1;
900 tmp = arch_to_object (spell->other_arch); 875 tmp = arch_to_object (spell->other_arch);
901 tmp->set_owner (op); 876 tmp->set_owner (op);
902 set_spell_skill (op, caster, spell, tmp); 877 set_spell_skill (op, caster, spell, tmp);
903 tmp->level = caster_level (caster, spell); 878 tmp->level = caster_level (caster, spell);
904 tmp->x = sx;
905 tmp->y = sy;
906 tmp->attacktype = spell->attacktype; 879 tmp->attacktype = spell->attacktype;
907 880
908 /* holy word stuff */ 881 /* holy word stuff */
909 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) 882 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER))
910 if (!tailor_god_spell (tmp, op)) 883 if (!tailor_god_spell (tmp, op))
947 920
948 if (!(tmp->move_type & MOVE_FLY_LOW)) 921 if (!(tmp->move_type & MOVE_FLY_LOW))
949 LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", &spell->other_arch->name); 922 LOG (llevDebug, "cast_cone(): arch %s doesn't have flying 1\n", &spell->other_arch->name);
950 923
951 if (!tmp->move_on && tmp->stats.dam) 924 if (!tmp->move_on && tmp->stats.dam)
952 {
953 LOG (llevDebug, "cast_cone(): arch %s doesn't have move_on set\n", &spell->other_arch->name); 925 LOG (llevDebug, "cast_cone(): arch %s doesn't have move_on set\n", &spell->other_arch->name);
954 }
955 926
956 insert_ob_in_map (tmp, m, op, 0); 927 m->insert (tmp, sx, sy, op);
957 928
958 /* This is used for tracking spells so that one effect doesn't hit 929 /* This is used for tracking spells so that one effect doesn't hit
959 * a single space too many times. 930 * a single space too many times.
960 */ 931 */
961 tmp->stats.maxhp = tmp->count; 932 tmp->stats.maxhp = tmp->count;
980void 951void
981animate_bomb (object *op) 952animate_bomb (object *op)
982{ 953{
983 int i; 954 int i;
984 object *env, *tmp; 955 object *env, *tmp;
985 archetype *at;
986 956
987 if (op->state != NUM_ANIMATIONS (op) - 1) 957 if (op->state != NUM_ANIMATIONS (op) - 1)
988 return; 958 return;
989 959
990 env = object_get_env_recursive (op); 960 env = object_get_env_recursive (op);
995 return; 965 return;
996 966
997 if (env->type == PLAYER) 967 if (env->type == PLAYER)
998 esrv_del_item (env->contr, op->count); 968 esrv_del_item (env->contr, op->count);
999 969
1000 op->remove (); 970 if (!(op = op->insert_at (env, op)))
1001 op->x = env->x;
1002 op->y = env->y;
1003 if ((op = insert_ob_in_map (op, env->map, op, 0)) == NULL)
1004 return; 971 return;
1005 } 972 }
1006 973
1007 // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent bomb from exploding 974 // elmex Tue Aug 15 17:46:51 CEST 2006: Prevent bomb from exploding
1008 // on a safe map. I don't like this special casing, but it seems to be neccessary 975 // on a safe map. I don't like this special casing, but it seems to be neccessary
1015 982
1016 /* This copies a lot of the code from the fire bullet, 983 /* This copies a lot of the code from the fire bullet,
1017 * but using the cast_bullet isn't really feasible, 984 * but using the cast_bullet isn't really feasible,
1018 * so just set up the appropriate values. 985 * so just set up the appropriate values.
1019 */ 986 */
1020 at = archetype::find (SPLINT); 987 if (archetype *at = archetype::find (SPLINT))
1021 if (at)
1022 { 988 {
1023 for (i = 1; i < 9; i++) 989 for (i = 1; i < 9; i++)
1024 { 990 {
1025 if (out_of_map (op->map, op->x + freearr_x[i], op->y + freearr_x[i])) 991 if (out_of_map (op->map, op->x + freearr_x[i], op->y + freearr_x[i]))
1026 continue; 992 continue;
993
1027 tmp = arch_to_object (at); 994 tmp = arch_to_object (at);
1028 tmp->direction = i; 995 tmp->direction = i;
1029 tmp->range = op->range; 996 tmp->range = op->range;
1030 tmp->stats.dam = op->stats.dam; 997 tmp->stats.dam = op->stats.dam;
1031 tmp->duration = op->duration; 998 tmp->duration = op->duration;
1032 tmp->attacktype = op->attacktype; 999 tmp->attacktype = op->attacktype;
1033 tmp->set_owner (op); 1000 tmp->set_owner (op);
1034 if (op->skill && op->skill != tmp->skill) 1001 if (op->skill && op->skill != tmp->skill)
1035 {
1036 tmp->skill = op->skill; 1002 tmp->skill = op->skill;
1037 } 1003
1038 if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE)) 1004 if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE))
1039 SET_ANIMATION (tmp, i); 1005 SET_ANIMATION (tmp, i);
1040 tmp->x = op->x + freearr_x[i]; 1006
1041 tmp->y = op->y + freearr_x[i]; 1007 op->map->insert (tmp, op->x + freearr_x[i], op->y + freearr_x[i], op);
1042 insert_ob_in_map (tmp, op->map, op, 0);
1043 move_bullet (tmp); 1008 move_bullet (tmp);
1044 } 1009 }
1045 } 1010 }
1046 1011
1047 explode_bullet (op); 1012 explode_bullet (op);
1070 tmp->duration = spell->duration + SP_level_duration_adjust (caster, spell); 1035 tmp->duration = spell->duration + SP_level_duration_adjust (caster, spell);
1071 tmp->attacktype = spell->attacktype; 1036 tmp->attacktype = spell->attacktype;
1072 1037
1073 tmp->set_owner (op); 1038 tmp->set_owner (op);
1074 set_spell_skill (op, caster, spell, tmp); 1039 set_spell_skill (op, caster, spell, tmp);
1075 tmp->x = dx; 1040
1076 tmp->y = dy; 1041 m->insert (tmp, dx, dy, op);
1077 insert_ob_in_map (tmp, m, op, 0);
1078 return 1; 1042 return 1;
1079} 1043}
1080 1044
1081/**************************************************************************** 1045/****************************************************************************
1082 * 1046 *
1225 1189
1226 effect->set_owner (op); 1190 effect->set_owner (op);
1227 set_spell_skill (op, caster, spell, effect); 1191 set_spell_skill (op, caster, spell, effect);
1228 1192
1229 /* ok, tell it where to be, and insert! */ 1193 /* ok, tell it where to be, and insert! */
1230 effect->x = target->x; 1194 effect->insert_at (target, op);
1231 effect->y = target->y;
1232 insert_ob_in_map (effect, target->map, op, 0);
1233 1195
1234 return 1; 1196 return 1;
1235} 1197}
1236 1198
1237 1199
1292 { 1254 {
1293 op->destroy (); 1255 op->destroy ();
1294 return; 1256 return;
1295 } 1257 }
1296 1258
1297 op->x = new_x;
1298 op->y = new_y;
1299 op->map = m;
1300 i = spell_find_dir (op->map, op->x, op->y, op->owner); 1259 i = spell_find_dir (m, new_x, new_y, op->owner);
1301 if (i > 0 && i != op->direction) 1260 if (i > 0 && i != op->direction)
1302 { 1261 {
1303 op->direction = i; 1262 op->direction = i;
1304 SET_ANIMATION (op, op->direction); 1263 SET_ANIMATION (op, op->direction);
1305 } 1264 }
1306 1265
1307 insert_ob_in_map (op, op->map, op, 0); 1266 m->insert (op, new_x, new_y, op);
1308} 1267}
1309 1268
1310/**************************************************************************** 1269/****************************************************************************
1311 * Destruction 1270 * Destruction
1312 ****************************************************************************/ 1271 ****************************************************************************/
1390 for (j = -range; j < range; j++) 1349 for (j = -range; j < range; j++)
1391 { 1350 {
1392 m = op->map; 1351 m = op->map;
1393 sx = op->x + i; 1352 sx = op->x + i;
1394 sy = op->y + j; 1353 sy = op->y + j;
1354
1395 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); 1355 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1396 if (mflags & P_OUT_OF_MAP) 1356 if (mflags & P_OUT_OF_MAP)
1397 continue; 1357 continue;
1358
1398 if (mflags & P_IS_ALIVE) 1359 if (mflags & P_IS_ALIVE)
1399 { 1360 {
1400 for (tmp = GET_MAP_OB (m, sx, sy); tmp; tmp = tmp->above) 1361 for (tmp = GET_MAP_OB (m, sx, sy); tmp; tmp = tmp->above)
1401 {
1402 if (QUERY_FLAG (tmp, FLAG_ALIVE) || tmp->type == PLAYER) 1362 if (QUERY_FLAG (tmp, FLAG_ALIVE) || tmp->type == PLAYER)
1403 break; 1363 break;
1404 } 1364
1405 if (tmp) 1365 if (tmp)
1406 { 1366 {
1407 if (tmp->head) 1367 if (tmp->head)
1408 tmp = tmp->head; 1368 tmp = tmp->head;
1409 1369
1412 { 1372 {
1413 if (spell_ob->subtype == SP_DESTRUCTION) 1373 if (spell_ob->subtype == SP_DESTRUCTION)
1414 { 1374 {
1415 hit_player (tmp, dam, op, spell_ob->attacktype, 0); 1375 hit_player (tmp, dam, op, spell_ob->attacktype, 0);
1416 if (spell_ob->other_arch) 1376 if (spell_ob->other_arch)
1417 {
1418 tmp = arch_to_object (spell_ob->other_arch); 1377 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op);
1419 tmp->x = sx;
1420 tmp->y = sy;
1421 insert_ob_in_map (tmp, m, op, 0);
1422 }
1423 } 1378 }
1424 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100) 1379 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100)
1425 { 1380 {
1426 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch) 1381 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch)
1427 {
1428 object *effect = arch_to_object (spell_ob->other_arch); 1382 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op);
1429
1430 effect->x = sx;
1431 effect->y = sy;
1432 insert_ob_in_map (effect, m, op, 0);
1433 }
1434 } 1383 }
1435 } 1384 }
1436 } 1385 }
1437 } 1386 }
1438 } 1387 }
1439 } 1388 }
1389
1440 op->skill = skill; 1390 op->skill = skill;
1441 return 1; 1391 return 1;
1442} 1392}
1443 1393
1444/*************************************************************************** 1394/***************************************************************************
1532 insert_ob_in_ob (force, tmp); 1482 insert_ob_in_ob (force, tmp);
1533 tmp->update_stats (); 1483 tmp->update_stats ();
1534 return 1; 1484 return 1;
1535 1485
1536} 1486}
1537
1538 1487
1539/********************************************************************** 1488/**********************************************************************
1540 * mood change 1489 * mood change
1541 * Arguably, this may or may not be an attack spell. But since it 1490 * Arguably, this may or may not be an attack spell. But since it
1542 * effects monsters, it seems best to put it into this file 1491 * effects monsters, it seems best to put it into this file
1572 else if (god && !strcmp (spell->race, "GOD_FRIEND")) 1521 else if (god && !strcmp (spell->race, "GOD_FRIEND"))
1573 race = god->race; 1522 race = god->race;
1574 else 1523 else
1575 race = spell->race; 1524 race = spell->race;
1576 1525
1577
1578 for (x = op->x - range; x <= op->x + range; x++) 1526 for (x = op->x - range; x <= op->x + range; x++)
1579 for (y = op->y - range; y <= op->y + range; y++) 1527 for (y = op->y - range; y <= op->y + range; y++)
1580 { 1528 {
1581
1582 done_one = 0; 1529 done_one = 0;
1583 m = op->map; 1530 m = op->map;
1584 nx = x; 1531 nx = x;
1585 ny = y; 1532 ny = y;
1586 mflags = get_map_flags (m, &m, x, y, &nx, &ny); 1533 mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1589 1536
1590 /* If there is nothing living on this space, no need to go further */ 1537 /* If there is nothing living on this space, no need to go further */
1591 if (!(mflags & P_IS_ALIVE)) 1538 if (!(mflags & P_IS_ALIVE))
1592 continue; 1539 continue;
1593 1540
1541 // players can only affect spaces that they can actually see
1542 if (caster && caster->contr
1543 && caster->contr->visibility_at (m, nx, ny) < 70)
1544 continue;
1545
1594 for (tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above) 1546 for (tmp = GET_MAP_TOP (m, nx, ny); tmp; tmp = tmp->below)
1595 if (QUERY_FLAG (tmp, FLAG_MONSTER)) 1547 if (QUERY_FLAG (tmp, FLAG_MONSTER))
1596 break; 1548 break;
1597 1549
1598 /* There can be living objects that are not monsters */ 1550 /* There can be living objects that are not monsters */
1599 if (!tmp || tmp->type == PLAYER) 1551 if (!tmp || tmp->type == PLAYER)
1606 head = tmp; 1558 head = tmp;
1607 1559
1608 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */ 1560 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */
1609 if (race && head->race && !strstr (race, head->race)) 1561 if (race && head->race && !strstr (race, head->race))
1610 continue; 1562 continue;
1563
1611 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD)) 1564 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD))
1612 continue; 1565 continue;
1613 1566
1614 /* Now do a bunch of stuff related to saving throws */ 1567 /* Now do a bunch of stuff related to saving throws */
1615 best_at = -1; 1568 best_at = -1;
1652 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level)))) 1605 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level))))
1653 /* Failed, no effect */ 1606 /* Failed, no effect */
1654 continue; 1607 continue;
1655 } 1608 }
1656 1609
1657 /* Done with saving throw. Now start effecting the monster */ 1610 /* Done with saving throw. Now start affecting the monster */
1658 1611
1659 /* aggravation */ 1612 /* aggravation */
1660 if (QUERY_FLAG (spell, FLAG_MONSTER)) 1613 if (QUERY_FLAG (spell, FLAG_MONSTER))
1661 { 1614 {
1662 CLEAR_FLAG (head, FLAG_SLEEP); 1615 CLEAR_FLAG (head, FLAG_SLEEP);
1679 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK)) 1632 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK))
1680 { 1633 {
1681 SET_FLAG (head, FLAG_BERSERK); 1634 SET_FLAG (head, FLAG_BERSERK);
1682 done_one = 1; 1635 done_one = 1;
1683 } 1636 }
1637
1684 /* charm */ 1638 /* charm */
1685 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY)) 1639 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY))
1686 { 1640 {
1687 SET_FLAG (head, FLAG_FRIENDLY);
1688 /* Prevent uncontolled outbreaks of self replicating monsters. 1641 /* Prevent uncontolled outbreaks of self replicating monsters.
1689 Typical use case is charm, go somwhere, use aggravation to make hostile. 1642 Typical use case is charm, go somwhere, use aggravation to make hostile.
1690 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */ 1643 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1691 CLEAR_FLAG (head, FLAG_GENERATOR); 1644 CLEAR_FLAG (head, FLAG_GENERATOR);
1692 head->set_owner (op); 1645 head->set_owner (op);
1698 head->stats.exp = 0; 1651 head->stats.exp = 0;
1699 } 1652 }
1700 1653
1701 /* If a monster was effected, put an effect in */ 1654 /* If a monster was effected, put an effect in */
1702 if (done_one && spell->other_arch) 1655 if (done_one && spell->other_arch)
1703 {
1704 tmp = arch_to_object (spell->other_arch); 1656 m->insert (arch_to_object (spell->other_arch), nx, ny, op);
1705 tmp->x = nx;
1706 tmp->y = ny;
1707 insert_ob_in_map (tmp, m, op, 0);
1708 }
1709 } /* for y */ 1657 } /* for y */
1710 1658
1711 return 1; 1659 return 1;
1712} 1660}
1713 1661
1764 nx = op->x; 1712 nx = op->x;
1765 ny = op->y; 1713 ny = op->y;
1766 m = op->map; 1714 m = op->map;
1767 } 1715 }
1768 1716
1769 op->remove (); 1717 m->insert (op, nx, ny, op);
1770 op->y = ny;
1771 op->x = nx;
1772 insert_ob_in_map (op, m, op, 0);
1773 1718
1774 dam_save = op->stats.dam; /* save the original dam: we do halfdam on 1719 dam_save = op->stats.dam; /* save the original dam: we do halfdam on
1775 surrounding squares */ 1720 surrounding squares */
1776 1721
1777 /* loop over current square and neighbors to hit. 1722 /* loop over current square and neighbors to hit.
1803 1748
1804 } 1749 }
1805 1750
1806 /* insert the other arch */ 1751 /* insert the other arch */
1807 if (op->other_arch && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy)))) 1752 if (op->other_arch && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy))))
1808 { 1753 m->insert (arch_to_object (op->other_arch), hx, hy, op);
1809 new_ob = arch_to_object (op->other_arch);
1810 new_ob->x = hx;
1811 new_ob->y = hy;
1812 insert_ob_in_map (new_ob, m, op, 0);
1813 }
1814 } 1754 }
1815 1755
1816 /* restore to the center location and damage */ 1756 /* restore to the center location and damage */
1817 op->stats.dam = dam_save; 1757 op->stats.dam = dam_save;
1818 1758
1821 if (i >= 0) 1761 if (i >= 0)
1822 { /* we have a preferred direction! */ 1762 { /* we have a preferred direction! */
1823 /* pick another direction if the preferred dir is blocked. */ 1763 /* pick another direction if the preferred dir is blocked. */
1824 if (get_map_flags (op->map, &m, nx + freearr_x[i], ny + freearr_y[i], &hx, &hy) & P_OUT_OF_MAP || 1764 if (get_map_flags (op->map, &m, nx + freearr_x[i], ny + freearr_y[i], &hx, &hy) & P_OUT_OF_MAP ||
1825 OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy))) 1765 OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy)))
1826 {
1827 i = absdir (i + rndm (0, 2) - 1); /* -1, 0, +1 */ 1766 i = absdir (i + rndm (0, 2) - 1); /* -1, 0, +1 */
1828 } 1767
1829 op->direction = i; 1768 op->direction = i;
1830 } 1769 }
1831} 1770}
1832 1771
1833 1772
1963 1902
1964 if (!spell->other_arch) 1903 if (!spell->other_arch)
1965 return 0; 1904 return 0;
1966 1905
1967 tmp = get_archetype (SWARM_SPELL); 1906 tmp = get_archetype (SWARM_SPELL);
1968 tmp->x = op->x;
1969 tmp->y = op->y;
1970 tmp->set_owner (op); /* needed so that if swarm elements kill, caster gets xp. */ 1907 tmp->set_owner (op); /* needed so that if swarm elements kill, caster gets xp. */
1971 set_spell_skill (op, caster, spell, tmp); 1908 set_spell_skill (op, caster, spell, tmp);
1972 1909
1973 tmp->level = caster_level (caster, spell); /*needed later, to get level dep. right. */ 1910 tmp->level = caster_level (caster, spell); /*needed later, to get level dep. right. */
1974 tmp->spell = arch_to_object (spell->other_arch); 1911 tmp->spell = arch_to_object (spell->other_arch);
1975 1912
1976 tmp->attacktype = tmp->spell->attacktype; 1913 tmp->attacktype = tmp->spell->attacktype;
1977 1914
1978 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) 1915 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER)
1979 {
1980 if (!tailor_god_spell (tmp, op)) 1916 if (!tailor_god_spell (tmp, op))
1981 return 1; 1917 return 1;
1982 } 1918
1983 tmp->duration = SP_level_duration_adjust (caster, spell); 1919 tmp->duration = SP_level_duration_adjust (caster, spell);
1984 for (i = 0; i < spell->duration; i++) 1920 for (i = 0; i < spell->duration; i++)
1985 tmp->duration += die_roll (1, 3, op, PREFER_HIGH); 1921 tmp->duration += die_roll (1, 3, op, PREFER_HIGH);
1986 1922
1987 tmp->direction = dir; 1923 tmp->direction = dir;
1988 tmp->invisible = 1; 1924 tmp->invisible = 1;
1989 insert_ob_in_map (tmp, op->map, op, 0); 1925
1926 tmp->insert_at (op, op);
1990 return 1; 1927 return 1;
1991} 1928}
1992 1929
1993 1930
1994/* See the spells documentation file for why this is its own 1931/* See the spells documentation file for why this is its own
2054 { 1991 {
2055 tmp->glow_radius = spell->range + SP_level_range_adjust (caster, spell); 1992 tmp->glow_radius = spell->range + SP_level_range_adjust (caster, spell);
2056 if (tmp->glow_radius > MAX_LIGHT_RADII) 1993 if (tmp->glow_radius > MAX_LIGHT_RADII)
2057 tmp->glow_radius = MAX_LIGHT_RADII; 1994 tmp->glow_radius = MAX_LIGHT_RADII;
2058 } 1995 }
2059 tmp->x = x; 1996
2060 tmp->y = y; 1997 m->insert (tmp, x, y, op);
2061 insert_ob_in_map (tmp, m, op, 0);
2062 return 1; 1998 return 1;
2063} 1999}
2064 2000
2065 2001
2066 2002
2179 object *flash; /* visual effect for inflicting disease */ 2115 object *flash; /* visual effect for inflicting disease */
2180 2116
2181 new_draw_info_format (NDI_UNIQUE, 0, op, "You inflict %s on %s!", &disease->name, &walk->name); 2117 new_draw_info_format (NDI_UNIQUE, 0, op, "You inflict %s on %s!", &disease->name, &walk->name);
2182 2118
2183 disease->destroy (); /* don't need this one anymore */ 2119 disease->destroy (); /* don't need this one anymore */
2184 flash = get_archetype (ARCH_DETECT_MAGIC); 2120 walk->map->insert (get_archetype (ARCH_DETECT_MAGIC), x, y, op);
2185 flash->x = x;
2186 flash->y = y;
2187 flash->map = walk->map;
2188 insert_ob_in_map (flash, walk->map, op, 0);
2189 return 1; 2121 return 1;
2190 } 2122 }
2191 2123
2192 disease->destroy (); 2124 disease->destroy ();
2193 } 2125 }
2194 } /* if living creature */ 2126 } /* if living creature */
2195 } /* for range of spaces */ 2127 } /* for range of spaces */
2128
2196 new_draw_info (NDI_UNIQUE, 0, op, "No one caught anything!"); 2129 new_draw_info (NDI_UNIQUE, 0, op, "No one caught anything!");
2197 return 1; 2130 return 1;
2198} 2131}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines