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.57 by root, Sat May 17 14:11:13 2008 UTC vs.
Revision 1.73 by root, Sun Dec 28 06:59:27 2008 UTC

39 * op is the spell object. 39 * op is the spell object.
40 */ 40 */
41void 41void
42check_spell_knockback (object *op) 42check_spell_knockback (object *op)
43{ 43{
44 object *tmp, *tmp2; /* object on the map */
45 int weight_move; 44 int weight_move;
46 int frictionmod = 2; /*poor man's physics - multipy targets weight by this amount */ 45 int frictionmod = 2; /*poor man's physics - multipy targets weight by this amount */
47 46
48 if (!op->weight) 47 if (!op->weight)
49 { /*shouldn't happen but if cone object has no weight drop out */ 48 { /*shouldn't happen but if cone object has no weight drop out */
54 { 53 {
55 weight_move = op->weight + (op->weight * op->level) / 3; 54 weight_move = op->weight + (op->weight * op->level) / 3;
56 /*LOG (llevDebug, "DEBUG: arch weighs %d and masses %d (%s,level %d)\n", op->weight,weight_move,op->name,op->level); */ 55 /*LOG (llevDebug, "DEBUG: arch weighs %d and masses %d (%s,level %d)\n", op->weight,weight_move,op->name,op->level); */
57 } 56 }
58 57
59 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above) 58 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
60 { 59 {
61 int num_sections = 1; 60 int num_sections = 1;
62 61
63 /* don't move DM */ 62 /* don't move DM */
64 if (QUERY_FLAG (tmp, FLAG_WIZ)) 63 if (QUERY_FLAG (tmp, FLAG_WIZ))
71 /* don't move floors or immobile objects */ 70 /* don't move floors or immobile objects */
72 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) || (!QUERY_FLAG (tmp, FLAG_ALIVE) && QUERY_FLAG (tmp, FLAG_NO_PICK))) 71 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) || (!QUERY_FLAG (tmp, FLAG_ALIVE) && QUERY_FLAG (tmp, FLAG_NO_PICK)))
73 continue; 72 continue;
74 73
75 /* count the object's sections */ 74 /* count the object's sections */
76 for (tmp2 = tmp; tmp2 != NULL; tmp2 = tmp2->more) 75 for (object *tmp2 = tmp; tmp2; tmp2 = tmp2->more)
77 num_sections++; 76 num_sections++;
78 77
79 /* I'm not sure if it makes sense to divide by num_sections - bigger 78 /* I'm not sure if it makes sense to divide by num_sections - bigger
80 * objects should be harder to move, and we are moving the entire 79 * objects should be harder to move, and we are moving the entire
81 * object, not just the head, so the total weight should be relevant. 80 * object, not just the head, so the total weight should be relevant.
149 new_bolt->duration++; 148 new_bolt->duration++;
150 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */ 149 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */
151 new_bolt->stats.dam++; 150 new_bolt->stats.dam++;
152 tmp->stats.dam /= 2; /* reduce father bolt damage */ 151 tmp->stats.dam /= 2; /* reduce father bolt damage */
153 tmp->stats.dam++; 152 tmp->stats.dam++;
153
154 if ((new_bolt = m->insert (new_bolt, sx, sy, op))) 154 if ((new_bolt = m->insert (new_bolt, sx, sy, op)))
155 update_turn_face (new_bolt); 155 update_turn_face (new_bolt);
156} 156}
157 157
158/* move_bolt: moves bolt 'op'. Basically, it just advances a space, 158/* move_bolt: moves bolt 'op'. Basically, it just advances a space,
159 * and checks for various things that may stop it. 159 * and checks for various things that may stop it.
160 */ 160 */
161
162void 161void
163move_bolt (object *op) 162move_bolt (object *op)
164{ 163{
165 int mflags; 164 int mflags;
166 sint16 x, y; 165 sint16 x, y;
167 maptile *m; 166 maptile *m;
168 167
169 if (--op->duration < 0) 168 if (--op->duration < 0)
170 { 169 {
171 op->destroy (); 170 op->drop_and_destroy ();
172 return; 171 return;
173 } 172 }
174 173
175 hit_map (op, 0, op->attacktype, 1); 174 hit_map (op, 0, op->attacktype, 1);
176 175
249 tmp->duration++; 248 tmp->duration++;
250 249
251 /* New forking code. Possibly create forks of this object 250 /* New forking code. Possibly create forks of this object
252 * going off in other directions. 251 * going off in other directions.
253 */ 252 */
254 if (rndm (0, 99) < tmp->stats.Dex) 253 if (tmp->stats.Dex && rndm (0, 99) < tmp->stats.Dex)
255 { /* stats.Dex % of forking */ 254 forklightning (op, tmp); /* stats.Dex % of forking */
256 forklightning (op, tmp);
257 }
258 255
259 /* In this way, the object left behind sticks on the space, but 256 /* In this way, the object left behind sticks on the space, but
260 * doesn't create any bolts that continue to move onward. 257 * doesn't create any bolts that continue to move onward.
261 */ 258 */
262 op->range = 0; 259 op->range = 0;
286 return 0; 283 return 0;
287 284
288 /* peterm: level dependency for bolts */ 285 /* peterm: level dependency for bolts */
289 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob); 286 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob);
290 tmp->attacktype = spob->attacktype; 287 tmp->attacktype = spob->attacktype;
288
291 if (spob->slaying) 289 if (spob->slaying)
292 tmp->slaying = spob->slaying; 290 tmp->slaying = spob->slaying;
291
293 tmp->range = spob->range + SP_level_range_adjust (caster, spob); 292 tmp->range = spob->range + SP_level_range_adjust (caster, spob);
294 tmp->duration = spob->duration + SP_level_duration_adjust (caster, spob); 293 tmp->duration = spob->duration + SP_level_duration_adjust (caster, spob);
295 tmp->stats.Dex = spob->stats.Dex; 294 tmp->stats.Dex = spob->stats.Dex;
296 tmp->stats.Con = spob->stats.Con; 295 tmp->stats.Con = spob->stats.Con;
297 296
308 307
309 maptile *newmap; 308 maptile *newmap;
310 mflags = get_map_flags (tmp->map, &newmap, tmp->x, tmp->y, &tmp->x, &tmp->y); 309 mflags = get_map_flags (tmp->map, &newmap, tmp->x, tmp->y, &tmp->x, &tmp->y);
311 if (mflags & P_OUT_OF_MAP) 310 if (mflags & P_OUT_OF_MAP)
312 { 311 {
313 tmp->destroy (); 312 tmp->drop_and_destroy ();
314 return 0; 313 return 0;
315 } 314 }
316 315
317 tmp->map = newmap; 316 tmp->map = newmap;
318 317
319 if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (tmp->map, tmp->x, tmp->y))) 318 if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (tmp->map, tmp->x, tmp->y)))
320 { 319 {
321 if (!QUERY_FLAG (tmp, FLAG_REFLECTING)) 320 if (!QUERY_FLAG (tmp, FLAG_REFLECTING))
322 { 321 {
323 tmp->destroy (); 322 tmp->drop_and_destroy ();
324 return 0; 323 return 0;
325 } 324 }
326 325
327 tmp->x = op->x; 326 tmp->x = op->x;
328 tmp->y = op->y; 327 tmp->y = op->y;
394void 393void
395explode_bullet (object *op) 394explode_bullet (object *op)
396{ 395{
397 object *tmp, *owner; 396 object *tmp, *owner;
398 397
399 if (op->other_arch == NULL) 398 if (!op->other_arch)
400 { 399 {
401 LOG (llevError, "BUG: explode_bullet(): op without other_arch\n"); 400 LOG (llevError, "BUG: explode_bullet(): op without other_arch\n");
402 op->destroy (); 401 op->destroy ();
403 return; 402 return;
404 } 403 }
433 } 432 }
434 433
435 if (op->attacktype) 434 if (op->attacktype)
436 { 435 {
437 hit_map (op, 0, op->attacktype, 1); 436 hit_map (op, 0, op->attacktype, 1);
437
438 if (op->destroyed ()) 438 if (op->destroyed ())
439 return; 439 return;
440 } 440 }
441 441
442 /* other_arch contains what this explodes into */ 442 /* other_arch contains what this explodes into */
445 tmp->set_owner (op); 445 tmp->set_owner (op);
446 tmp->skill = op->skill; 446 tmp->skill = op->skill;
447 447
448 owner = op->owner; 448 owner = op->owner;
449 449
450 if ((tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) && owner && !tailor_god_spell (tmp, owner)) 450 if ((tmp->attacktype & AT_HOLYWORD
451 || tmp->attacktype & AT_GODPOWER)
452 && owner
453 && !tailor_god_spell (tmp, owner))
451 { 454 {
452 op->destroy (); 455 op->destroy ();
453 return; 456 return;
454 } 457 }
455 458
520 for (tmp = op->ms ().bot; tmp; tmp = tmp->above) 523 for (tmp = op->ms ().bot; tmp; tmp = tmp->above)
521 { 524 {
522 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 525 if (QUERY_FLAG (tmp, FLAG_ALIVE))
523 { 526 {
524 dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1); 527 dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1);
528
529 // TODO: can't understand the following if's
525 if (op->destroyed () || !tmp->destroyed () || (op->stats.dam -= dam) < 0) 530 if (op->destroyed () || !tmp->destroyed () || (op->stats.dam -= dam) < 0)
526 { 531 {
527 if (!QUERY_FLAG (op, FLAG_REMOVED)) 532 if (!QUERY_FLAG (op, FLAG_REMOVED))
528 { 533 {
529 op->destroy (); 534 op->destroy ();
703/* move_cone: causes cone object 'op' to move a space/hit creatures */ 708/* move_cone: causes cone object 'op' to move a space/hit creatures */
704 709
705void 710void
706move_cone (object *op) 711move_cone (object *op)
707{ 712{
708 int i;
709
710 /* if no map then hit_map will crash so just ignore object */ 713 /* if no map then hit_map will crash so just ignore object */
711 if (!op->map) 714 if (!op->map)
712 { 715 {
713 LOG (llevError, "Tried to move_cone object %s without a map.\n", op->name ? &op->name : "unknown"); 716 LOG (llevError, "Tried to move_cone object %s without a map.\n", op->name ? &op->name : "unknown");
714 op->set_speed (0); 717 op->set_speed (0);
734 } 737 }
735#endif 738#endif
736 739
737 hit_map (op, 0, op->attacktype, 0); 740 hit_map (op, 0, op->attacktype, 0);
738 741
742 if (!op->is_on_map ())
743 return;
744
739 /* Check to see if we should push anything. 745 /* Check to see if we should push anything.
740 * Spell objects with weight push whatever they encounter to some 746 * Spell objects with weight push whatever they encounter to some
741 * degree. 747 * degree.
742 */ 748 */
743 if (op->weight) 749 if (op->weight)
750 {
744 check_spell_knockback (op); 751 check_spell_knockback (op);
745 752
746 if (op->destroyed ()) 753 if (!op->is_on_map ())
747 return; 754 return;
755 }
748 756
749 if ((op->duration--) < 0) 757 if (op->duration-- < 0)
750 { 758 {
751 op->destroy (); 759 op->destroy ();
752 return; 760 return;
753 } 761 }
754 /* Object has hit maximum range, so don't have it move 762 /* Object has hit maximum range, so don't have it move
759 { 767 {
760 op->range = 0; /* just so it doesn't wrap */ 768 op->range = 0; /* just so it doesn't wrap */
761 return; 769 return;
762 } 770 }
763 771
764 for (i = -1; i < 2; i++) 772 for (int i = -1; i <= 1; i++)
765 { 773 {
766 sint16 x = op->x + freearr_x[absdir (op->stats.sp + i)], y = op->y + freearr_y[absdir (op->stats.sp + i)]; 774 sint16 x = op->x + freearr_x[absdir (op->stats.sp + i)], y = op->y + freearr_y[absdir (op->stats.sp + i)];
767 775
768 if (ok_to_put_more (op->map, x, y, op, op->attacktype)) 776 if (ok_to_put_more (op->map, x, y, op, op->attacktype))
769 { 777 {
861 869
862 success = 1; 870 success = 1;
863 tmp = arch_to_object (spell->other_arch); 871 tmp = arch_to_object (spell->other_arch);
864 tmp->set_owner (op); 872 tmp->set_owner (op);
865 set_spell_skill (op, caster, spell, tmp); 873 set_spell_skill (op, caster, spell, tmp);
866 tmp->level = caster_level (caster, spell); 874 tmp->level = casting_level (caster, spell);
867 tmp->attacktype = spell->attacktype; 875 tmp->attacktype = spell->attacktype;
868 876
869 /* holy word stuff */ 877 /* holy word stuff */
870 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) 878 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER))
871 if (!tailor_god_spell (tmp, op)) 879 if (!tailor_god_spell (tmp, op))
1000 int mflags; 1008 int mflags;
1001 sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir]; 1009 sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir];
1002 maptile *m; 1010 maptile *m;
1003 1011
1004 mflags = get_map_flags (op->map, &m, dx, dy, &dx, &dy); 1012 mflags = get_map_flags (op->map, &m, dx, dy, &dx, &dy);
1013
1014 // when creating a bomb below ourself it should always work, even
1015 // when movement is blocked (somehow we got here, somehow we are here,
1016 // so we should also be able to make a bomb here). (originally added
1017 // to fix create bomb traps in doors, which cast with dir=0).
1018 if (dir)
1019 {
1005 if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, dx, dy) & MOVE_WALK)) 1020 if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, dx, dy) & MOVE_WALK))
1006 { 1021 {
1007 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); 1022 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
1008 return 0; 1023 return 0;
1024 }
1009 } 1025 }
1010 1026
1011 tmp = arch_to_object (spell->other_arch); 1027 tmp = arch_to_object (spell->other_arch);
1012 1028
1013 /* level dependencies for bomb */ 1029 /* level dependencies for bomb */
1113 effect = arch_to_object (spell->other_arch); 1129 effect = arch_to_object (spell->other_arch);
1114 else 1130 else
1115 return 0; 1131 return 0;
1116 1132
1117 /* tailor the effect by priest level and worshipped God */ 1133 /* tailor the effect by priest level and worshipped God */
1118 effect->level = caster_level (caster, spell); 1134 effect->level = casting_level (caster, spell);
1119 effect->attacktype = spell->attacktype; 1135 effect->attacktype = spell->attacktype;
1120 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER)) 1136 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER))
1121 { 1137 {
1122 if (tailor_god_spell (effect, op)) 1138 if (tailor_god_spell (effect, op))
1123 new_draw_info_format (NDI_UNIQUE, 0, op, "%s answers your call!", determine_god (op)); 1139 new_draw_info_format (NDI_UNIQUE, 0, op, "%s answers your call!", determine_god (op));
1178 1194
1179/* op is a missile that needs to be moved */ 1195/* op is a missile that needs to be moved */
1180void 1196void
1181move_missile (object *op) 1197move_missile (object *op)
1182{ 1198{
1183 int i, mflags;
1184 object *owner;
1185 sint16 new_x, new_y;
1186 maptile *m;
1187
1188 if (op->range-- <= 0) 1199 if (op->range-- <= 0)
1189 { 1200 {
1201 op->drop_and_destroy ();
1202 return;
1203 }
1204
1205 mapxy pos (op);
1206 pos.move (op->direction);
1207
1208 if (!pos.normalise ())
1209 {
1190 op->destroy (); 1210 op->destroy ();
1191 return; 1211 return;
1192 } 1212 }
1193 1213
1194 owner = op->owner; 1214 mapspace &ms = pos.ms ();
1195#if 0
1196 /* It'd make things nastier if this wasn't here - spells cast by
1197 * monster that are then killed would continue to survive
1198 */
1199 if (owner == NULL)
1200 {
1201 op->destroy ();
1202 return;
1203 }
1204#endif
1205 1215
1206 new_x = op->x + DIRX (op); 1216 if (ms.flags () & P_IS_ALIVE || ms.blocks (op))
1207 new_y = op->y + DIRY (op);
1208
1209 mflags = get_map_flags (op->map, &m, new_x, new_y, &new_x, &new_y);
1210
1211 if (!(mflags & P_OUT_OF_MAP) && ((mflags & P_IS_ALIVE) || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))))
1212 { 1217 {
1213 hit_map (op, op->direction, AT_MAGIC, 1); 1218 hit_map (op, op->direction, AT_MAGIC, 1);
1214 /* Basically, missile only hits one thing then goes away. 1219 /* Basically, missile only hits one thing then goes away.
1215 * we need to remove it if someone hasn't already done so. 1220 * we need to remove it if someone hasn't already done so.
1216 */ 1221 */
1217 if (!op->destroyed ())
1218 op->destroy ();
1219
1220 return;
1221 }
1222
1223 op->remove ();
1224
1225 if (!op->direction || (mflags & P_OUT_OF_MAP))
1226 {
1227 op->destroy (); 1222 op->destroy ();
1228 return; 1223 return;
1229 } 1224 }
1230 1225
1226 if (!op->direction)
1227 {
1228 op->destroy ();
1229 return;
1230 }
1231
1231 i = spell_find_dir (m, new_x, new_y, op->owner); 1232 int i = spell_find_dir (pos.m, pos.x, pos.y, op->owner);
1232 if (i > 0 && i != op->direction) 1233 if (i > 0 && i != op->direction)
1233 { 1234 {
1234 op->direction = i; 1235 op->direction = i;
1235 SET_ANIMATION (op, op->direction); 1236 SET_ANIMATION (op, op->direction);
1236 } 1237 }
1237 1238
1238 m->insert (op, new_x, new_y, op); 1239 pos.insert (op, op);
1239} 1240}
1240 1241
1241/**************************************************************************** 1242/****************************************************************************
1242 * Destruction 1243 * Destruction
1243 ****************************************************************************/ 1244 ****************************************************************************/
1257 1258
1258 object *tmp = get_archetype (FORCE_NAME); 1259 object *tmp = get_archetype (FORCE_NAME);
1259 tmp->speed = 0.01; 1260 tmp->speed = 0.01;
1260 tmp->stats.food = time; 1261 tmp->stats.food = time;
1261 SET_FLAG (tmp, FLAG_IS_USED_UP); 1262 SET_FLAG (tmp, FLAG_IS_USED_UP);
1262 tmp->glow_radius = radius;
1263 if (tmp->glow_radius > MAX_LIGHT_RADII)
1264 tmp->glow_radius = MAX_LIGHT_RADII; 1263 tmp->glow_radius = min (MAX_LIGHT_RADIUS, radius);
1265
1266 tmp = insert_ob_in_ob (tmp, op); 1264 tmp = insert_ob_in_ob (tmp, op);
1267 1265
1268 if (tmp->glow_radius > op->glow_radius) 1266 if (tmp->glow_radius > op->glow_radius)
1269 op->glow_radius = tmp->glow_radius; 1267 op->glow_radius = tmp->glow_radius;
1270 1268
1300 else 1298 else
1301 op->skill = NULL; 1299 op->skill = NULL;
1302 1300
1303 op->change_skill (find_skill_by_name (op, op->skill)); 1301 op->change_skill (find_skill_by_name (op, op->skill));
1304 1302
1305 for (i = -range; i < range; i++) 1303 for (i = -range; i <= range; i++)
1306 { 1304 {
1307 for (j = -range; j < range; j++) 1305 for (j = -range; j <= range; j++)
1308 { 1306 {
1309 m = op->map; 1307 m = op->map;
1310 sx = op->x + i; 1308 sx = op->x + i;
1311 sy = op->y + j; 1309 sy = op->y + j;
1312 1310
1329 (!friendly && (QUERY_FLAG (tmp, FLAG_FRIENDLY) || tmp->type == PLAYER))) 1327 (!friendly && (QUERY_FLAG (tmp, FLAG_FRIENDLY) || tmp->type == PLAYER)))
1330 { 1328 {
1331 if (spell_ob->subtype == SP_DESTRUCTION) 1329 if (spell_ob->subtype == SP_DESTRUCTION)
1332 { 1330 {
1333 hit_player (tmp, dam, op, spell_ob->attacktype, 0); 1331 hit_player (tmp, dam, op, spell_ob->attacktype, 0);
1332
1334 if (spell_ob->other_arch) 1333 if (spell_ob->other_arch)
1335 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op); 1334 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op);
1336 } 1335 }
1337 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100) 1336 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100)
1338 { 1337 {
1466 1465
1467 /* We precompute some values here so that we don't have to keep 1466 /* We precompute some values here so that we don't have to keep
1468 * doing it over and over again. 1467 * doing it over and over again.
1469 */ 1468 */
1470 god = find_god (determine_god (op)); 1469 god = find_god (determine_god (op));
1471 level = caster_level (caster, spell); 1470 level = casting_level (caster, spell);
1472 range = spell->range + SP_level_range_adjust (caster, spell); 1471 range = spell->range + SP_level_range_adjust (caster, spell);
1473 1472
1474 /* On the bright side, no monster should ever have a race of GOD_... 1473 /* On the bright side, no monster should ever have a race of GOD_...
1475 * so even if the player doesn't worship a god, if race=GOD_.., it 1474 * so even if the player doesn't worship a god, if race=GOD_.., it
1476 * won't ever match anything. 1475 * won't ever match anything.
1498 /* If there is nothing living on this space, no need to go further */ 1497 /* If there is nothing living on this space, no need to go further */
1499 if (!(mflags & P_IS_ALIVE)) 1498 if (!(mflags & P_IS_ALIVE))
1500 continue; 1499 continue;
1501 1500
1502 // players can only affect spaces that they can actually see 1501 // players can only affect spaces that they can actually see
1502 if (caster
1503 if (caster && caster->contr 1503 && caster->contr
1504 && caster->contr->visibility_at (m, nx, ny) < 70) 1504 && caster->contr->darkness_at (m, nx, ny) == LOS_BLOCKED)
1505 continue; 1505 continue;
1506 1506
1507 for (tmp = GET_MAP_TOP (m, nx, ny); tmp; tmp = tmp->below) 1507 for (tmp = GET_MAP_TOP (m, nx, ny); tmp; tmp = tmp->below)
1508 if (QUERY_FLAG (tmp, FLAG_MONSTER)) 1508 if (QUERY_FLAG (tmp, FLAG_MONSTER))
1509 break; 1509 break;
1619 } /* for y */ 1619 } /* for y */
1620 1620
1621 return 1; 1621 return 1;
1622} 1622}
1623 1623
1624
1625/* Move_ball_spell: This handles ball type spells that just sort of wander 1624/* Move_ball_spell: This handles ball type spells that just sort of wander
1626 * about. was called move_ball_lightning, but since more than the ball 1625 * about. was called move_ball_lightning, but since more than the ball
1627 * lightning spell used it, that seemed misnamed. 1626 * lightning spell used it, that seemed misnamed.
1628 * op is the spell effect. 1627 * op is the spell effect.
1629 * note that duration is handled by process_object() in time.c 1628 * note that duration is handled by process_object() in time.c
1630 */ 1629 */
1631
1632void 1630void
1633move_ball_spell (object *op) 1631move_ball_spell (object *op)
1634{ 1632{
1635 int i, j, dam_save, dir, mflags; 1633 int i, j, dam_save, dir, mflags;
1636 sint16 nx, ny, hx, hy; 1634 sint16 nx, ny, hx, hy;
1655 for (i = 1; i < 9; i++) 1653 for (i = 1; i < 9; i++)
1656 { 1654 {
1657 /* i bit 0: alters sign of offset 1655 /* i bit 0: alters sign of offset
1658 * other bits (i / 2): absolute value of offset 1656 * other bits (i / 2): absolute value of offset
1659 */ 1657 */
1660
1661 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2); 1658 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2);
1662 int tmpdir = absdir (op->direction + offset); 1659 int tmpdir = absdir (op->direction + offset);
1663 1660
1664 nx = op->x + freearr_x[tmpdir]; 1661 nx = op->x + freearr_x[tmpdir];
1665 ny = op->y + freearr_y[tmpdir]; 1662 ny = op->y + freearr_y[tmpdir];
1667 { 1664 {
1668 dir = tmpdir; 1665 dir = tmpdir;
1669 break; 1666 break;
1670 } 1667 }
1671 } 1668 }
1669
1672 if (dir == 0) 1670 if (dir == 0)
1673 { 1671 {
1674 nx = op->x; 1672 nx = op->x;
1675 ny = op->y; 1673 ny = op->y;
1676 m = op->map; 1674 m = op->map;
1702 1700
1703 if ((mflags & P_IS_ALIVE) && (!owner || owner->x != hx || owner->y != hy || !on_same_map (owner, op))) 1701 if ((mflags & P_IS_ALIVE) && (!owner || owner->x != hx || owner->y != hy || !on_same_map (owner, op)))
1704 { 1702 {
1705 if (j) 1703 if (j)
1706 op->stats.dam = dam_save / 2; 1704 op->stats.dam = dam_save / 2;
1705
1707 hit_map (op, j, op->attacktype, 1); 1706 hit_map (op, j, op->attacktype, 1);
1708
1709 } 1707 }
1710 1708
1711 /* insert the other arch */ 1709 /* insert the other arch */
1712 if (op->other_arch && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy)))) 1710 if (op->other_arch && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy))))
1713 m->insert (arch_to_object (op->other_arch), hx, hy, op); 1711 m->insert (arch_to_object (op->other_arch), hx, hy, op);
1746 int adjustdir; 1744 int adjustdir;
1747 maptile *m; 1745 maptile *m;
1748#endif 1746#endif
1749 object *owner = op->env; 1747 object *owner = op->env;
1750 1748
1749 if (!owner) // MUST not happen, remove when true TODO
1750 {
1751 LOG (llevError, "swarm spell found outside inventory: %s\n", op->debug_desc ());
1752 op->destroy ();
1753 return;
1754 }
1755
1751 if (!op->duration || !owner->is_on_map ()) 1756 if (!op->duration || !owner->is_on_map ())
1752 { 1757 {
1753 op->destroy (); 1758 op->drop_and_destroy ();
1754 return; 1759 return;
1755 } 1760 }
1756 1761
1757 op->duration--; 1762 op->duration--;
1758 1763
1759 int basedir = op->direction; 1764 int basedir = op->direction;
1760 if (!basedir) 1765 if (!basedir)
1766 {
1761 /* spray in all directions! 8) */ 1767 /* spray in all directions! 8) */
1762 basedir = (op->facing += op->state) % 8 + 1; 1768 op->facing = (op->facing + op->state) & 7;
1769 basedir = op->facing + 1;
1770 }
1763 1771
1764#if 0 1772#if 0
1765 // this is bogus: it causes wrong places to be checked below 1773 // this is bogus: it causes wrong places to be checked below
1766 // (a wall 2 cells away will block the effect...) and 1774 // (a wall 2 cells away will block the effect...) and
1767 // doesn't work for SP_BULLET anyhow, so again tests the wrong 1775 // doesn't work for SP_BULLET anyhow, so again tests the wrong
1849{ 1857{
1850 if (!spell->other_arch) 1858 if (!spell->other_arch)
1851 return 0; 1859 return 0;
1852 1860
1853 object *tmp = archetype::get (SWARM_SPELL); 1861 object *tmp = archetype::get (SWARM_SPELL);
1862
1854 set_spell_skill (op, caster, spell, tmp); 1863 set_spell_skill (op, caster, spell, tmp);
1855 tmp->level = caster_level (caster, spell); /* needed later, to get level dep. right. */ 1864 tmp->level = casting_level (caster, spell); /* needed later, to get level dep. right. */
1856 tmp->spell = spell->other_arch->instance (); 1865 tmp->spell = spell->other_arch->instance ();
1857 tmp->attacktype = tmp->spell->attacktype; 1866 tmp->attacktype = tmp->spell->attacktype;
1858 1867
1859 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) 1868 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER)
1860 if (!tailor_god_spell (tmp, op)) 1869 if (!tailor_god_spell (tmp, op))
1862 1871
1863 tmp->duration = SP_level_duration_adjust (caster, spell); 1872 tmp->duration = SP_level_duration_adjust (caster, spell);
1864 for (int i = 0; i < spell->duration; i++) 1873 for (int i = 0; i < spell->duration; i++)
1865 tmp->duration += die_roll (1, 3, op, PREFER_HIGH); 1874 tmp->duration += die_roll (1, 3, op, PREFER_HIGH);
1866 1875
1876 tmp->invisible = 1;
1877 tmp->flag [FLAG_NO_DROP] = 1; // make sure it stays in inv, or else
1867 tmp->direction = dir; 1878 tmp->direction = dir;
1868 tmp->invisible = 1;
1869 tmp->facing = rndm (1, 8); // initial firing direction 1879 tmp->facing = rndm (1, 8); // initial firing direction
1870 tmp->state = rndm (4) * 2 + 1; // direction increment 1880 tmp->state = rndm (4) * 2 + 1; // direction increment
1871 1881
1872 op->insert (tmp); 1882 op->insert (tmp);
1873 1883
1885 int dam, mflags; 1895 int dam, mflags;
1886 maptile *m; 1896 maptile *m;
1887 1897
1888 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); 1898 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1889 1899
1890 if (!dir) 1900 if (dir)
1891 {
1892 new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
1893 return 0;
1894 } 1901 {
1895
1896 x = op->x + freearr_x[dir]; 1902 x = op->x + freearr_x[dir];
1897 y = op->y + freearr_y[dir]; 1903 y = op->y + freearr_y[dir];
1898 m = op->map; 1904 m = op->map;
1899 1905
1900 mflags = get_map_flags (m, &m, x, y, &x, &y); 1906 mflags = get_map_flags (m, &m, x, y, &x, &y);
1901 1907
1902 if (mflags & P_OUT_OF_MAP) 1908 if (mflags & P_OUT_OF_MAP)
1903 { 1909 {
1904 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there."); 1910 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there.");
1905 return 0; 1911 return 0;
1906 } 1912 }
1907 1913
1908 if (mflags & P_IS_ALIVE && spell->attacktype) 1914 if (mflags & P_IS_ALIVE && spell->attacktype)
1909 { 1915 {
1910 for (target = GET_MAP_OB (m, x, y); target; target = target->above) 1916 for (target = GET_MAP_OB (m, x, y); target; target = target->above)
1911 if (QUERY_FLAG (target, FLAG_MONSTER)) 1917 if (QUERY_FLAG (target, FLAG_MONSTER))
1912 { 1918 {
1913 /* oky doky. got a target monster. Lets make a blinding attack */ 1919 /* oky doky. got a target monster. Lets make a blinding attack */
1914 if (target->head) 1920 if (target->head)
1915 target = target->head; 1921 target = target->head;
1922
1916 (void) hit_player (target, dam, op, spell->attacktype, 1); 1923 hit_player (target, dam, op, spell->attacktype, 1);
1917 return 1; /* one success only! */ 1924 return 1; /* one success only! */
1925 }
1918 } 1926 }
1919 }
1920 1927
1921 /* no live target, perhaps a wall is in the way? */ 1928 /* no live target, perhaps a wall is in the way? */
1922 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y))) 1929 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)))
1923 { 1930 {
1924 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); 1931 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1925 return 0; 1932 return 0;
1933 }
1926 } 1934 }
1927 1935
1928 /* ok, looks groovy to just insert a new light on the map */ 1936 /* ok, looks groovy to just insert a new light on the map */
1929 tmp = arch_to_object (spell->other_arch); 1937 tmp = arch_to_object (spell->other_arch);
1930 if (!tmp) 1938 if (!tmp)
1931 { 1939 {
1932 LOG (llevError, "Error: spell arch for cast_light() missing.\n"); 1940 LOG (llevError, "Error: spell arch for cast_light() missing.\n");
1933 return 0; 1941 return 0;
1934 } 1942 }
1943
1935 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell); 1944 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell);
1945
1936 if (tmp->glow_radius) 1946 if (tmp->glow_radius)
1937 {
1938 tmp->glow_radius = spell->range + SP_level_range_adjust (caster, spell); 1947 tmp->glow_radius = min (MAX_LIGHT_RADIUS, spell->range + SP_level_range_adjust (caster, spell));
1939 if (tmp->glow_radius > MAX_LIGHT_RADII)
1940 tmp->glow_radius = MAX_LIGHT_RADII;
1941 }
1942 1948
1949 if (dir)
1943 m->insert (tmp, x, y, op); 1950 m->insert (tmp, x, y, op);
1951 else
1952 caster->outer_env ()->insert (tmp);
1953
1944 return 1; 1954 return 1;
1945} 1955}
1946 1956
1947/* cast_cause_disease: this spell looks along <dir> from the 1957/* cast_cause_disease: this spell looks along <dir> from the
1948 * player and infects someone. 1958 * player and infects someone.
2001 object *disease = arch_to_object (spell->other_arch); 2011 object *disease = arch_to_object (spell->other_arch);
2002 2012
2003 disease->set_owner (op); 2013 disease->set_owner (op);
2004 set_spell_skill (op, caster, spell, disease); 2014 set_spell_skill (op, caster, spell, disease);
2005 disease->stats.exp = 0; 2015 disease->stats.exp = 0;
2006 disease->level = caster_level (caster, spell); 2016 disease->level = casting_level (caster, spell);
2007 2017
2008 /* do level adjustments */ 2018 /* do level adjustments */
2009 if (disease->stats.wc) 2019 if (disease->stats.wc)
2010 disease->stats.wc += dur_mod / 2; 2020 disease->stats.wc += dur_mod / 2;
2011 2021

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines