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.58 by root, Sat May 17 14:57:23 2008 UTC vs.
Revision 1.83 by root, Mon Mar 2 11:45:19 2009 UTC

148 new_bolt->duration++; 148 new_bolt->duration++;
149 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */ 149 new_bolt->stats.dam /= 2; /* reduce daughter bolt damage */
150 new_bolt->stats.dam++; 150 new_bolt->stats.dam++;
151 tmp->stats.dam /= 2; /* reduce father bolt damage */ 151 tmp->stats.dam /= 2; /* reduce father bolt damage */
152 tmp->stats.dam++; 152 tmp->stats.dam++;
153
153 if ((new_bolt = m->insert (new_bolt, sx, sy, op))) 154 if ((new_bolt = m->insert (new_bolt, sx, sy, op)))
154 update_turn_face (new_bolt); 155 update_turn_face (new_bolt);
155} 156}
156 157
157/* move_bolt: moves bolt 'op'. Basically, it just advances a space, 158/* move_bolt: moves bolt 'op'. Basically, it just advances a space,
164 sint16 x, y; 165 sint16 x, y;
165 maptile *m; 166 maptile *m;
166 167
167 if (--op->duration < 0) 168 if (--op->duration < 0)
168 { 169 {
169 op->destroy (); 170 op->drop_and_destroy ();
170 return; 171 return;
171 } 172 }
172 173
173 hit_map (op, 0, op->attacktype, 1); 174 hit_map (op, 0, op->attacktype, 1);
174 175
306 307
307 maptile *newmap; 308 maptile *newmap;
308 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);
309 if (mflags & P_OUT_OF_MAP) 310 if (mflags & P_OUT_OF_MAP)
310 { 311 {
311 tmp->destroy (); 312 tmp->drop_and_destroy ();
312 return 0; 313 return 0;
313 } 314 }
314 315
315 tmp->map = newmap; 316 tmp->map = newmap;
316 317
317 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)))
318 { 319 {
319 if (!QUERY_FLAG (tmp, FLAG_REFLECTING)) 320 if (!QUERY_FLAG (tmp, FLAG_REFLECTING))
320 { 321 {
321 tmp->destroy (); 322 tmp->drop_and_destroy ();
322 return 0; 323 return 0;
323 } 324 }
324 325
325 tmp->x = op->x; 326 tmp->x = op->x;
326 tmp->y = op->y; 327 tmp->y = op->y;
392void 393void
393explode_bullet (object *op) 394explode_bullet (object *op)
394{ 395{
395 object *tmp, *owner; 396 object *tmp, *owner;
396 397
397 if (op->other_arch == NULL) 398 if (!op->other_arch)
398 { 399 {
399 LOG (llevError, "BUG: explode_bullet(): op without other_arch\n"); 400 LOG (llevError, "BUG: explode_bullet(): op without other_arch\n");
400 op->destroy (); 401 op->destroy ();
401 return; 402 return;
402 } 403 }
444 tmp->set_owner (op); 445 tmp->set_owner (op);
445 tmp->skill = op->skill; 446 tmp->skill = op->skill;
446 447
447 owner = op->owner; 448 owner = op->owner;
448 449
449 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))
450 { 454 {
451 op->destroy (); 455 op->destroy ();
452 return; 456 return;
453 } 457 }
454 458
520 { 524 {
521 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 525 if (QUERY_FLAG (tmp, FLAG_ALIVE))
522 { 526 {
523 dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1); 527 dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1);
524 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 ();
732 } 737 }
733#endif 738#endif
734 739
735 hit_map (op, 0, op->attacktype, 0); 740 hit_map (op, 0, op->attacktype, 0);
736 741
742 if (!op->is_on_map ())
743 return;
744
737 /* Check to see if we should push anything. 745 /* Check to see if we should push anything.
738 * Spell objects with weight push whatever they encounter to some 746 * Spell objects with weight push whatever they encounter to some
739 * degree. 747 * degree.
740 */ 748 */
741 if (op->weight) 749 if (op->weight)
750 {
742 check_spell_knockback (op); 751 check_spell_knockback (op);
743 752
744 if (op->destroyed ()) 753 if (!op->is_on_map ())
745 return; 754 return;
755 }
746 756
747 if ((op->duration--) < 0) 757 if (op->duration-- < 0)
748 { 758 {
749 op->destroy (); 759 op->destroy ();
750 return; 760 return;
751 } 761 }
752 /* Object has hit maximum range, so don't have it move 762 /* Object has hit maximum range, so don't have it move
818 */ 828 */
819 movetype = spell->other_arch->move_type; 829 movetype = spell->other_arch->move_type;
820 830
821 for (i = range_min; i <= range_max; i++) 831 for (i = range_min; i <= range_max; i++)
822 { 832 {
823 sint16 x, y, d; 833 sint16 x, y;
824 834
825 /* We can't use absdir here, because it never returns 835 /* We can't use absdir here, because it never returns
826 * 0. If this is a rune, we want to hit the person on top 836 * 0. If this is a rune, we want to hit the person on top
827 * of the trap (d==0). If it is not a rune, then we don't want 837 * of the trap (d==0). If it is not a rune, then we don't want
828 * to hit that person. 838 * to hit that person.
829 */ 839 */
830 d = dir + i; 840 int d = dir ? absdir (dir + i) : i;
831 while (d < 0)
832 d += 8;
833 while (d > 8)
834 d -= 8;
835 841
836 /* If it's not a rune, we don't want to blast the caster. 842 /* If it's not a rune, we don't want to blast the caster.
837 * In that case, we have to see - if dir is specified, 843 * In that case, we have to see - if dir is specified,
838 * turn this into direction 8. If dir is not specified (all 844 * turn this into direction 8. If dir is not specified (all
839 * direction) skip - otherwise, one line would do more damage 845 * direction) skip - otherwise, one line would do more damage
859 865
860 success = 1; 866 success = 1;
861 tmp = arch_to_object (spell->other_arch); 867 tmp = arch_to_object (spell->other_arch);
862 tmp->set_owner (op); 868 tmp->set_owner (op);
863 set_spell_skill (op, caster, spell, tmp); 869 set_spell_skill (op, caster, spell, tmp);
864 tmp->level = caster_level (caster, spell); 870 tmp->level = casting_level (caster, spell);
865 tmp->attacktype = spell->attacktype; 871 tmp->attacktype = spell->attacktype;
866 872
867 /* holy word stuff */ 873 /* holy word stuff */
868 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) 874 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER))
869 if (!tailor_god_spell (tmp, op)) 875 if (!tailor_god_spell (tmp, op))
998 int mflags; 1004 int mflags;
999 sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir]; 1005 sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir];
1000 maptile *m; 1006 maptile *m;
1001 1007
1002 mflags = get_map_flags (op->map, &m, dx, dy, &dx, &dy); 1008 mflags = get_map_flags (op->map, &m, dx, dy, &dx, &dy);
1009
1010 // when creating a bomb below ourself it should always work, even
1011 // when movement is blocked (somehow we got here, somehow we are here,
1012 // so we should also be able to make a bomb here). (originally added
1013 // to fix create bomb traps in doors, which cast with dir=0).
1014 if (dir)
1015 {
1003 if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, dx, dy) & MOVE_WALK)) 1016 if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, dx, dy) & MOVE_WALK))
1004 { 1017 {
1005 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); 1018 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
1006 return 0; 1019 return 0;
1020 }
1007 } 1021 }
1008 1022
1009 tmp = arch_to_object (spell->other_arch); 1023 tmp = arch_to_object (spell->other_arch);
1010 1024
1011 /* level dependencies for bomb */ 1025 /* level dependencies for bomb */
1097 * interesting spell. 1111 * interesting spell.
1098 * if it is a cleric spell, you need a god, and the creature 1112 * if it is a cleric spell, you need a god, and the creature
1099 * can't be friendly to your god. 1113 * can't be friendly to your god.
1100 */ 1114 */
1101 1115
1102 if (!target || QUERY_FLAG (target, FLAG_REFL_SPELL) 1116 if (!target
1117 || target->flag [FLAG_REFL_SPELL]
1103 || (!god && spell->stats.grace) 1118 || (!god && spell->stats.grace)
1104 || (target->title && god && !strcmp (target->title, god->name)) || (target->race && god && strstr (target->race, god->race))) 1119 || (god && target->title == god->name)
1120 || (god && target->race.contains (god->race)))
1105 { 1121 {
1106 new_draw_info (NDI_UNIQUE, 0, op, "Your request is unheeded."); 1122 new_draw_info (NDI_UNIQUE, 0, op, "Your request is unheeded.");
1107 return 0; 1123 return 0;
1108 } 1124 }
1109 1125
1111 effect = arch_to_object (spell->other_arch); 1127 effect = arch_to_object (spell->other_arch);
1112 else 1128 else
1113 return 0; 1129 return 0;
1114 1130
1115 /* tailor the effect by priest level and worshipped God */ 1131 /* tailor the effect by priest level and worshipped God */
1116 effect->level = caster_level (caster, spell); 1132 effect->level = casting_level (caster, spell);
1117 effect->attacktype = spell->attacktype; 1133 effect->attacktype = spell->attacktype;
1118 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER)) 1134 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER))
1119 { 1135 {
1120 if (tailor_god_spell (effect, op)) 1136 if (tailor_god_spell (effect, op))
1121 new_draw_info_format (NDI_UNIQUE, 0, op, "%s answers your call!", determine_god (op)); 1137 new_draw_info_format (NDI_UNIQUE, 0, op, "%s answers your call!", (const char *)determine_god (op));
1122 else 1138 else
1123 { 1139 {
1124 new_draw_info (NDI_UNIQUE, 0, op, "Your request is ignored."); 1140 new_draw_info (NDI_UNIQUE, 0, op, "Your request is ignored.");
1125 return 0; 1141 return 0;
1126 } 1142 }
1178void 1194void
1179move_missile (object *op) 1195move_missile (object *op)
1180{ 1196{
1181 if (op->range-- <= 0) 1197 if (op->range-- <= 0)
1182 { 1198 {
1183 op->destroy (); 1199 op->drop_and_destroy ();
1184 return; 1200 return;
1185 } 1201 }
1186 1202
1187 mapxy pos (op); 1203 mapxy pos (op);
1188 pos.move (op->direction); 1204 pos.move (op->direction);
1240 1256
1241 object *tmp = get_archetype (FORCE_NAME); 1257 object *tmp = get_archetype (FORCE_NAME);
1242 tmp->speed = 0.01; 1258 tmp->speed = 0.01;
1243 tmp->stats.food = time; 1259 tmp->stats.food = time;
1244 SET_FLAG (tmp, FLAG_IS_USED_UP); 1260 SET_FLAG (tmp, FLAG_IS_USED_UP);
1245 tmp->glow_radius = radius; 1261 tmp->set_glow_radius (min (MAX_LIGHT_RADIUS, radius));
1246 if (tmp->glow_radius > MAX_LIGHT_RADII)
1247 tmp->glow_radius = MAX_LIGHT_RADII;
1248
1249 tmp = insert_ob_in_ob (tmp, op); 1262 tmp = insert_ob_in_ob (tmp, op);
1250 1263
1251 if (tmp->glow_radius > op->glow_radius) 1264 if (tmp->glow_radius > op->glow_radius)
1252 op->glow_radius = tmp->glow_radius; 1265 op->set_glow_radius (tmp->glow_radius);
1253 1266
1254 return 1; 1267 return 1;
1255} 1268}
1256 1269
1257int 1270int
1258cast_destruction (object *op, object *caster, object *spell_ob) 1271cast_destruction (object *op, object *caster, object *spell_ob)
1259{ 1272{
1260 int i, j, range, mflags, friendly = 0, dam, dur;
1261 sint16 sx, sy;
1262 maptile *m;
1263 object *tmp;
1264 const char *skill;
1265
1266 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob); 1273 int range = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
1267 dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob); 1274 int dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
1268 dur = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob); 1275 int dur = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1269 if (QUERY_FLAG (op, FLAG_FRIENDLY) || op->type == PLAYER) 1276
1270 friendly = 1; 1277 bool friendly = op->flag [FLAG_FRIENDLY] || op->is_player ();
1271 1278
1272 /* destruction doesn't use another spell object, so we need 1279 /* destruction doesn't use another spell object, so we need
1273 * update op's skill pointer so that exp is properly awarded. 1280 * update op's skill pointer so that exp is properly awarded.
1274 * We do some shortcuts here - since this is just temporary
1275 * and we'll reset the values back, we don't need to go through
1276 * the full share string/free_string route.
1277 */ 1281 */
1278 skill = op->skill; 1282 const shstr skill = op->skill;
1283
1279 if (caster == op) 1284 if (caster == op)
1280 op->skill = spell_ob->skill; 1285 op->skill = spell_ob->skill;
1281 else if (caster->skill) 1286 else if (caster->skill)
1282 op->skill = caster->skill; 1287 op->skill = caster->skill;
1283 else 1288 else
1284 op->skill = NULL; 1289 op->skill = 0;
1285 1290
1286 op->change_skill (find_skill_by_name (op, op->skill)); 1291 op->change_skill (find_skill_by_name (op, op->skill));
1287 1292
1288 for (i = -range; i <= range; i++) 1293 unordered_mapwalk (op, -range, -range, range, range)
1289 { 1294 {
1290 for (j = -range; j <= range; j++) 1295 mapspace &ms = m->at (nx, ny);
1291 {
1292 m = op->map;
1293 sx = op->x + i;
1294 sy = op->y + j;
1295 1296
1296 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1297 if (mflags & P_OUT_OF_MAP)
1298 continue;
1299
1300 if (mflags & P_IS_ALIVE) 1297 if (ms.flags () & P_IS_ALIVE)
1298 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1299 if (tmp->flag [FLAG_ALIVE] || tmp->is_player ())
1301 { 1300 {
1302 for (tmp = GET_MAP_OB (m, sx, sy); tmp; tmp = tmp->above) 1301 tmp = tmp->head_ ();
1303 if (QUERY_FLAG (tmp, FLAG_ALIVE) || tmp->type == PLAYER)
1304 break;
1305 1302
1306 if (tmp) 1303 if ((friendly && !tmp->flag [FLAG_FRIENDLY] && !tmp->is_player ())
1304 || (!friendly && (tmp->flag [FLAG_FRIENDLY] || tmp->is_player ())))
1307 { 1305 {
1308 if (tmp->head) 1306 if (spell_ob->subtype == SP_DESTRUCTION)
1309 tmp = tmp->head;
1310
1311 if ((friendly && !QUERY_FLAG (tmp, FLAG_FRIENDLY) && tmp->type != PLAYER) ||
1312 (!friendly && (QUERY_FLAG (tmp, FLAG_FRIENDLY) || tmp->type == PLAYER)))
1313 { 1307 {
1314 if (spell_ob->subtype == SP_DESTRUCTION)
1315 {
1316 hit_player (tmp, dam, op, spell_ob->attacktype, 0); 1308 hit_player (tmp, dam, op, spell_ob->attacktype, 0);
1317 1309
1318 if (spell_ob->other_arch) 1310 if (spell_ob->other_arch)
1319 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op); 1311 m->insert (arch_to_object (spell_ob->other_arch), nx, ny, op);
1320 } 1312 }
1321 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100) 1313 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist [ATNR_MAGIC] != 100)
1322 { 1314 {
1323 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch) 1315 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch)
1324 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op); 1316 m->insert (arch_to_object (spell_ob->other_arch), nx, ny, op);
1325 }
1326 } 1317 }
1327 } 1318 }
1328 } 1319 }
1329 }
1330 } 1320 }
1331 1321
1332 op->skill = skill; 1322 op->skill = skill;
1333 return 1; 1323 return 1;
1334} 1324}
1441 */ 1431 */
1442int 1432int
1443mood_change (object *op, object *caster, object *spell) 1433mood_change (object *op, object *caster, object *spell)
1444{ 1434{
1445 object *tmp, *god, *head; 1435 object *tmp, *god, *head;
1446 int done_one, range, mflags, level, at, best_at; 1436 int done_one, range, level, at, best_at;
1447 sint16 x, y, nx, ny;
1448 maptile *m;
1449 const char *race; 1437 const char *race;
1450 1438
1451 /* We precompute some values here so that we don't have to keep 1439 /* We precompute some values here so that we don't have to keep
1452 * doing it over and over again. 1440 * doing it over and over again.
1453 */ 1441 */
1454 god = find_god (determine_god (op)); 1442 god = find_god (determine_god (op));
1455 level = caster_level (caster, spell); 1443 level = casting_level (caster, spell);
1456 range = spell->range + SP_level_range_adjust (caster, spell); 1444 range = spell->range + SP_level_range_adjust (caster, spell);
1457 1445
1458 /* On the bright side, no monster should ever have a race of GOD_... 1446 /* On the bright side, no monster should ever have a race of GOD_...
1459 * so even if the player doesn't worship a god, if race=GOD_.., it 1447 * so even if the player doesn't worship a god, if race=GOD_.., it
1460 * won't ever match anything. 1448 * won't ever match anything.
1461 */ 1449 */
1462 if (!spell->race) 1450 if (!spell->race)
1463 race = NULL; 1451 race = NULL;
1464 else if (god && !strcmp (spell->race, "GOD_SLAYING")) 1452 else if (god && spell->race == shstr_GOD_SLAYING)
1465 race = god->slaying; 1453 race = god->slaying;
1466 else if (god && !strcmp (spell->race, "GOD_FRIEND")) 1454 else if (god && spell->race == shstr_GOD_FRIEND)
1467 race = god->race; 1455 race = god->race;
1468 else 1456 else
1469 race = spell->race; 1457 race = spell->race;
1470 1458
1471 for (x = op->x - range; x <= op->x + range; x++) 1459 unordered_mapwalk (op, -range, -range, range, range)
1472 for (y = op->y - range; y <= op->y + range; y++)
1473 { 1460 {
1474 done_one = 0; 1461 mapspace &ms = m->at (nx, ny);
1475 m = op->map;
1476 nx = x;
1477 ny = y;
1478 mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1479 if (mflags & P_OUT_OF_MAP)
1480 continue;
1481 1462
1482 /* If there is nothing living on this space, no need to go further */ 1463 /* If there is nothing living on this space, no need to go further */
1483 if (!(mflags & P_IS_ALIVE)) 1464 if (!ms.flags () & P_IS_ALIVE)
1484 continue; 1465 continue;
1485 1466
1486 // players can only affect spaces that they can actually see 1467 // players can only affect spaces that they can actually see
1468 if (caster
1487 if (caster && caster->contr 1469 && caster->contr
1488 && caster->contr->visibility_at (m, nx, ny) < 70) 1470 && caster->contr->darkness_at (m, nx, ny) == LOS_BLOCKED)
1489 continue; 1471 continue;
1490 1472
1491 for (tmp = GET_MAP_TOP (m, nx, ny); tmp; tmp = tmp->below) 1473 for (tmp = ms.top; tmp; tmp = tmp->below)
1492 if (QUERY_FLAG (tmp, FLAG_MONSTER)) 1474 if (tmp->flag [FLAG_MONSTER])
1493 break; 1475 break;
1494 1476
1495 /* There can be living objects that are not monsters */ 1477 /* There can be living objects that are not monsters */
1496 if (!tmp || tmp->type == PLAYER) 1478 if (!tmp)
1497 continue; 1479 continue;
1498 1480
1499 /* Only the head has meaningful data, so resolve to that */ 1481 /* Only the head has meaningful data, so resolve to that */
1500 if (tmp->head)
1501 head = tmp->head; 1482 head = tmp->head_ ();
1502 else
1503 head = tmp;
1504 1483
1505 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */ 1484 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */
1506 if (race && head->race && !strstr (race, head->race)) 1485 if (race && head->race && !strstr (race, head->race))
1507 continue; 1486 continue;
1508 1487
1509 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD)) 1488 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD))
1510 continue; 1489 continue;
1511 1490
1512 /* Now do a bunch of stuff related to saving throws */ 1491 /* Now do a bunch of stuff related to saving throws */
1513 best_at = -1; 1492 best_at = -1;
1514 if (spell->attacktype) 1493 if (spell->attacktype)
1515 { 1494 {
1516 for (at = 0; at < NROFATTACKS; at++) 1495 for (at = 0; at < NROFATTACKS; at++)
1517 if (spell->attacktype & (1 << at)) 1496 if (spell->attacktype & (1 << at))
1518 if (best_at == -1 || head->resist[at] > head->resist[best_at]) 1497 if (best_at == -1 || head->resist[at] > head->resist[best_at])
1519 best_at = at; 1498 best_at = at;
1520 1499
1521 if (best_at == -1) 1500 if (best_at == -1)
1522 at = 0; 1501 at = 0;
1523 else 1502 else
1524 { 1503 {
1525 if (head->resist[best_at] == 100) 1504 if (head->resist[best_at] == 100)
1526 continue; 1505 continue;
1527 else 1506 else
1528 at = head->resist[best_at] / 5; 1507 at = head->resist[best_at] / 5;
1529 } 1508 }
1509
1530 at -= level / 5; 1510 at -= level / 5;
1531 if (did_make_save (head, head->level, at)) 1511 if (did_make_save (head, head->level, at))
1532 continue; 1512 continue;
1533 } 1513 }
1534 else /* spell->attacktype */ 1514 else /* spell->attacktype */
1535 { 1515 {
1536 /* 1516 /*
1537 Spell has no attacktype (charm & such), so we'll have a specific saving: 1517 Spell has no attacktype (charm & such), so we'll have a specific saving:
1538 * if spell level < monster level, no go 1518 * if spell level < monster level, no go
1539 * else, chance of effect = 20 + min( 50, 2 * ( spell level - monster level ) ) 1519 * else, chance of effect = 20 + min( 50, 2 * ( spell level - monster level ) )
1540 1520
1541 The chance will then be in the range [20-70] percent, not too bad. 1521 The chance will then be in the range [20-70] percent, not too bad.
1542 1522
1543 This is required to fix the 'charm monster' abuse, where a player level 1 can 1523 This is required to fix the 'charm monster' abuse, where a player level 1 can
1544 charm a level 125 monster... 1524 charm a level 125 monster...
1545 1525
1546 Ryo, august 14th 1526 Ryo, august 14th
1547 */ 1527 */
1548 if (head->level > level) 1528 if (head->level > level)
1549 continue; 1529 continue;
1550 1530
1551 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level)))) 1531 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level))))
1552 /* Failed, no effect */ 1532 /* Failed, no effect */
1553 continue; 1533 continue;
1554 } 1534 }
1555 1535
1556 /* Done with saving throw. Now start affecting the monster */ 1536 /* Done with saving throw. Now start affecting the monster */
1537 done_one = 0;
1557 1538
1558 /* aggravation */ 1539 /* aggravation */
1559 if (QUERY_FLAG (spell, FLAG_MONSTER)) 1540 if (QUERY_FLAG (spell, FLAG_MONSTER))
1560 { 1541 {
1561 CLEAR_FLAG (head, FLAG_SLEEP); 1542 CLEAR_FLAG (head, FLAG_SLEEP);
1562 remove_friendly_object (head); 1543 remove_friendly_object (head);
1563 done_one = 1; 1544 done_one = 1;
1564 head->enemy = op; 1545 head->enemy = op;
1565 } 1546 }
1566 1547
1567 /* calm monsters */ 1548 /* calm monsters */
1568 if (QUERY_FLAG (spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (head, FLAG_UNAGGRESSIVE)) 1549 if (QUERY_FLAG (spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (head, FLAG_UNAGGRESSIVE))
1569 { 1550 {
1570 SET_FLAG (head, FLAG_UNAGGRESSIVE); 1551 SET_FLAG (head, FLAG_UNAGGRESSIVE);
1571 head->enemy = NULL; 1552 head->enemy = NULL;
1572 done_one = 1; 1553 done_one = 1;
1573 } 1554 }
1574 1555
1575 /* berserk monsters */ 1556 /* berserk monsters */
1576 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK)) 1557 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK))
1577 { 1558 {
1578 SET_FLAG (head, FLAG_BERSERK); 1559 SET_FLAG (head, FLAG_BERSERK);
1579 done_one = 1; 1560 done_one = 1;
1580 } 1561 }
1581 1562
1582 /* charm */ 1563 /* charm */
1583 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY)) 1564 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY))
1584 { 1565 {
1585 INVOKE_OBJECT (KILL, head, ARG_OBJECT (caster)); 1566 INVOKE_OBJECT (KILL, head, ARG_OBJECT (caster));
1586 1567
1587 /* Prevent uncontrolled outbreaks of self replicating monsters. 1568 /* Prevent uncontrolled outbreaks of self replicating monsters.
1588 Typical use case is charm, go somwhere, use aggravation to make hostile. 1569 Typical use case is charm, go somwhere, use aggravation to make hostile.
1589 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */ 1570 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1590 CLEAR_FLAG (head, FLAG_GENERATOR); 1571 CLEAR_FLAG (head, FLAG_GENERATOR);
1591 head->set_owner (op); 1572 head->set_owner (op);
1592 set_spell_skill (op, caster, spell, head); 1573 set_spell_skill (op, caster, spell, head);
1593 add_friendly_object (head); 1574 add_friendly_object (head);
1594 head->attack_movement = PETMOVE; 1575 head->attack_movement = PETMOVE;
1595 done_one = 1; 1576 done_one = 1;
1596 change_exp (op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL); 1577 change_exp (op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL);
1597 head->stats.exp = 0; 1578 head->stats.exp = 0;
1598 } 1579 }
1599 1580
1600 /* If a monster was effected, put an effect in */ 1581 /* If a monster was effected, put an effect in */
1601 if (done_one && spell->other_arch) 1582 if (done_one && spell->other_arch)
1602 m->insert (arch_to_object (spell->other_arch), nx, ny, op); 1583 m->insert (arch_to_object (spell->other_arch), nx, ny, op);
1603 } /* for y */ 1584 }
1604 1585
1605 return 1; 1586 return 1;
1606} 1587}
1607
1608 1588
1609/* Move_ball_spell: This handles ball type spells that just sort of wander 1589/* Move_ball_spell: This handles ball type spells that just sort of wander
1610 * about. was called move_ball_lightning, but since more than the ball 1590 * about. was called move_ball_lightning, but since more than the ball
1611 * lightning spell used it, that seemed misnamed. 1591 * lightning spell used it, that seemed misnamed.
1612 * op is the spell effect. 1592 * op is the spell effect.
1613 * note that duration is handled by process_object() in time.c 1593 * note that duration is handled by process_object() in time.c
1614 */ 1594 */
1615
1616void 1595void
1617move_ball_spell (object *op) 1596move_ball_spell (object *op)
1618{ 1597{
1619 int i, j, dam_save, dir, mflags; 1598 int i, j, dam_save, dir, mflags;
1620 sint16 nx, ny, hx, hy; 1599 sint16 nx, ny, hx, hy;
1639 for (i = 1; i < 9; i++) 1618 for (i = 1; i < 9; i++)
1640 { 1619 {
1641 /* i bit 0: alters sign of offset 1620 /* i bit 0: alters sign of offset
1642 * other bits (i / 2): absolute value of offset 1621 * other bits (i / 2): absolute value of offset
1643 */ 1622 */
1644
1645 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2); 1623 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2);
1646 int tmpdir = absdir (op->direction + offset); 1624 int tmpdir = absdir (op->direction + offset);
1647 1625
1648 nx = op->x + freearr_x[tmpdir]; 1626 nx = op->x + freearr_x[tmpdir];
1649 ny = op->y + freearr_y[tmpdir]; 1627 ny = op->y + freearr_y[tmpdir];
1651 { 1629 {
1652 dir = tmpdir; 1630 dir = tmpdir;
1653 break; 1631 break;
1654 } 1632 }
1655 } 1633 }
1634
1656 if (dir == 0) 1635 if (dir == 0)
1657 { 1636 {
1658 nx = op->x; 1637 nx = op->x;
1659 ny = op->y; 1638 ny = op->y;
1660 m = op->map; 1639 m = op->map;
1730 int adjustdir; 1709 int adjustdir;
1731 maptile *m; 1710 maptile *m;
1732#endif 1711#endif
1733 object *owner = op->env; 1712 object *owner = op->env;
1734 1713
1714 if (!owner) // MUST not happen, remove when true TODO
1715 {
1716 LOG (llevError, "swarm spell found outside inventory: %s\n", op->debug_desc ());
1717 op->destroy ();
1718 return;
1719 }
1720
1735 if (!op->duration || !owner->is_on_map ()) 1721 if (!op->duration || !owner->is_on_map ())
1736 { 1722 {
1737 op->destroy (); 1723 op->drop_and_destroy ();
1738 return; 1724 return;
1739 } 1725 }
1740 1726
1741 op->duration--; 1727 op->duration--;
1742 1728
1743 int basedir = op->direction; 1729 int basedir = op->direction;
1744 if (!basedir) 1730 if (!basedir)
1731 {
1745 /* spray in all directions! 8) */ 1732 /* spray in all directions! 8) */
1746 basedir = (op->facing += op->state) % 8 + 1; 1733 op->facing = (op->facing + op->state) & 7;
1734 basedir = op->facing + 1;
1735 }
1747 1736
1748#if 0 1737#if 0
1749 // this is bogus: it causes wrong places to be checked below 1738 // this is bogus: it causes wrong places to be checked below
1750 // (a wall 2 cells away will block the effect...) and 1739 // (a wall 2 cells away will block the effect...) and
1751 // doesn't work for SP_BULLET anyhow, so again tests the wrong 1740 // doesn't work for SP_BULLET anyhow, so again tests the wrong
1833{ 1822{
1834 if (!spell->other_arch) 1823 if (!spell->other_arch)
1835 return 0; 1824 return 0;
1836 1825
1837 object *tmp = archetype::get (SWARM_SPELL); 1826 object *tmp = archetype::get (SWARM_SPELL);
1827
1838 set_spell_skill (op, caster, spell, tmp); 1828 set_spell_skill (op, caster, spell, tmp);
1839 tmp->level = caster_level (caster, spell); /* needed later, to get level dep. right. */ 1829 tmp->level = casting_level (caster, spell); /* needed later, to get level dep. right. */
1840 tmp->spell = spell->other_arch->instance (); 1830 tmp->spell = spell->other_arch->instance ();
1841 tmp->attacktype = tmp->spell->attacktype; 1831 tmp->attacktype = tmp->spell->attacktype;
1842 1832
1843 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) 1833 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER)
1844 if (!tailor_god_spell (tmp, op)) 1834 if (!tailor_god_spell (tmp, op))
1846 1836
1847 tmp->duration = SP_level_duration_adjust (caster, spell); 1837 tmp->duration = SP_level_duration_adjust (caster, spell);
1848 for (int i = 0; i < spell->duration; i++) 1838 for (int i = 0; i < spell->duration; i++)
1849 tmp->duration += die_roll (1, 3, op, PREFER_HIGH); 1839 tmp->duration += die_roll (1, 3, op, PREFER_HIGH);
1850 1840
1841 tmp->invisible = 1;
1842 tmp->flag [FLAG_NO_DROP] = 1; // make sure it stays in inv, or else
1851 tmp->direction = dir; 1843 tmp->direction = dir;
1852 tmp->invisible = 1;
1853 tmp->facing = rndm (1, 8); // initial firing direction 1844 tmp->facing = rndm (1, 8); // initial firing direction
1854 tmp->state = rndm (4) * 2 + 1; // direction increment 1845 tmp->state = rndm (4) * 2 + 1; // direction increment
1855 1846
1856 op->insert (tmp); 1847 op->insert (tmp);
1857 1848
1869 int dam, mflags; 1860 int dam, mflags;
1870 maptile *m; 1861 maptile *m;
1871 1862
1872 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); 1863 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1873 1864
1874 if (!dir) 1865 if (dir)
1875 {
1876 new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
1877 return 0;
1878 } 1866 {
1879
1880 x = op->x + freearr_x[dir]; 1867 x = op->x + freearr_x[dir];
1881 y = op->y + freearr_y[dir]; 1868 y = op->y + freearr_y[dir];
1882 m = op->map; 1869 m = op->map;
1883 1870
1884 mflags = get_map_flags (m, &m, x, y, &x, &y); 1871 mflags = get_map_flags (m, &m, x, y, &x, &y);
1885 1872
1886 if (mflags & P_OUT_OF_MAP) 1873 if (mflags & P_OUT_OF_MAP)
1887 { 1874 {
1888 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there."); 1875 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there.");
1889 return 0; 1876 return 0;
1890 } 1877 }
1891 1878
1892 if (mflags & P_IS_ALIVE && spell->attacktype) 1879 if (mflags & P_IS_ALIVE && spell->attacktype)
1893 { 1880 {
1894 for (target = GET_MAP_OB (m, x, y); target; target = target->above) 1881 for (target = GET_MAP_OB (m, x, y); target; target = target->above)
1895 if (QUERY_FLAG (target, FLAG_MONSTER)) 1882 if (QUERY_FLAG (target, FLAG_MONSTER))
1896 { 1883 {
1897 /* oky doky. got a target monster. Lets make a blinding attack */ 1884 /* oky doky. got a target monster. Lets make a blinding attack */
1898 if (target->head) 1885 if (target->head)
1899 target = target->head; 1886 target = target->head;
1900 1887
1901 hit_player (target, dam, op, spell->attacktype, 1); 1888 hit_player (target, dam, op, spell->attacktype, 1);
1902 return 1; /* one success only! */ 1889 return 1; /* one success only! */
1890 }
1903 } 1891 }
1904 }
1905 1892
1906 /* no live target, perhaps a wall is in the way? */ 1893 /* no live target, perhaps a wall is in the way? */
1907 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y))) 1894 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)))
1908 { 1895 {
1909 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); 1896 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1910 return 0; 1897 return 0;
1898 }
1911 } 1899 }
1912 1900
1913 /* ok, looks groovy to just insert a new light on the map */ 1901 /* ok, looks groovy to just insert a new light on the map */
1914 tmp = arch_to_object (spell->other_arch); 1902 tmp = arch_to_object (spell->other_arch);
1915 if (!tmp) 1903 if (!tmp)
1916 { 1904 {
1917 LOG (llevError, "Error: spell arch for cast_light() missing.\n"); 1905 LOG (llevError, "Error: spell arch for cast_light() missing.\n");
1918 return 0; 1906 return 0;
1919 } 1907 }
1908
1920 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell); 1909 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell);
1910
1921 if (tmp->glow_radius) 1911 if (tmp->glow_radius)
1922 { 1912 tmp->set_glow_radius (
1923 tmp->glow_radius = spell->range + SP_level_range_adjust (caster, spell); 1913 min (MAX_LIGHT_RADIUS, spell->range + SP_level_range_adjust (caster, spell)));
1924 if (tmp->glow_radius > MAX_LIGHT_RADII)
1925 tmp->glow_radius = MAX_LIGHT_RADII;
1926 }
1927 1914
1915 if (dir)
1928 m->insert (tmp, x, y, op); 1916 m->insert (tmp, x, y, op);
1917 else
1918 caster->outer_env ()->insert (tmp);
1919
1929 return 1; 1920 return 1;
1930} 1921}
1931 1922
1932/* cast_cause_disease: this spell looks along <dir> from the 1923/* cast_cause_disease: this spell looks along <dir> from the
1933 * player and infects someone. 1924 * player and infects someone.
1986 object *disease = arch_to_object (spell->other_arch); 1977 object *disease = arch_to_object (spell->other_arch);
1987 1978
1988 disease->set_owner (op); 1979 disease->set_owner (op);
1989 set_spell_skill (op, caster, spell, disease); 1980 set_spell_skill (op, caster, spell, disease);
1990 disease->stats.exp = 0; 1981 disease->stats.exp = 0;
1991 disease->level = caster_level (caster, spell); 1982 disease->level = casting_level (caster, spell);
1992 1983
1993 /* do level adjustments */ 1984 /* do level adjustments */
1994 if (disease->stats.wc) 1985 if (disease->stats.wc)
1995 disease->stats.wc += dur_mod / 2; 1986 disease->stats.wc += dur_mod / 2;
1996 1987

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines