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.75 by root, Sun Dec 28 08:08:25 2008 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
859 869
860 success = 1; 870 success = 1;
861 tmp = arch_to_object (spell->other_arch); 871 tmp = arch_to_object (spell->other_arch);
862 tmp->set_owner (op); 872 tmp->set_owner (op);
863 set_spell_skill (op, caster, spell, tmp); 873 set_spell_skill (op, caster, spell, tmp);
864 tmp->level = caster_level (caster, spell); 874 tmp->level = casting_level (caster, spell);
865 tmp->attacktype = spell->attacktype; 875 tmp->attacktype = spell->attacktype;
866 876
867 /* holy word stuff */ 877 /* holy word stuff */
868 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER)) 878 if ((tmp->attacktype & AT_HOLYWORD) || (tmp->attacktype & AT_GODPOWER))
869 if (!tailor_god_spell (tmp, op)) 879 if (!tailor_god_spell (tmp, op))
998 int mflags; 1008 int mflags;
999 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];
1000 maptile *m; 1010 maptile *m;
1001 1011
1002 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 {
1003 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))
1004 { 1021 {
1005 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.");
1006 return 0; 1023 return 0;
1024 }
1007 } 1025 }
1008 1026
1009 tmp = arch_to_object (spell->other_arch); 1027 tmp = arch_to_object (spell->other_arch);
1010 1028
1011 /* level dependencies for bomb */ 1029 /* level dependencies for bomb */
1111 effect = arch_to_object (spell->other_arch); 1129 effect = arch_to_object (spell->other_arch);
1112 else 1130 else
1113 return 0; 1131 return 0;
1114 1132
1115 /* tailor the effect by priest level and worshipped God */ 1133 /* tailor the effect by priest level and worshipped God */
1116 effect->level = caster_level (caster, spell); 1134 effect->level = casting_level (caster, spell);
1117 effect->attacktype = spell->attacktype; 1135 effect->attacktype = spell->attacktype;
1118 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER)) 1136 if (effect->attacktype & (AT_HOLYWORD | AT_GODPOWER))
1119 { 1137 {
1120 if (tailor_god_spell (effect, op)) 1138 if (tailor_god_spell (effect, op))
1121 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));
1178void 1196void
1179move_missile (object *op) 1197move_missile (object *op)
1180{ 1198{
1181 if (op->range-- <= 0) 1199 if (op->range-- <= 0)
1182 { 1200 {
1183 op->destroy (); 1201 op->drop_and_destroy ();
1184 return; 1202 return;
1185 } 1203 }
1186 1204
1187 mapxy pos (op); 1205 mapxy pos (op);
1188 pos.move (op->direction); 1206 pos.move (op->direction);
1240 1258
1241 object *tmp = get_archetype (FORCE_NAME); 1259 object *tmp = get_archetype (FORCE_NAME);
1242 tmp->speed = 0.01; 1260 tmp->speed = 0.01;
1243 tmp->stats.food = time; 1261 tmp->stats.food = time;
1244 SET_FLAG (tmp, FLAG_IS_USED_UP); 1262 SET_FLAG (tmp, FLAG_IS_USED_UP);
1245 tmp->glow_radius = radius;
1246 if (tmp->glow_radius > MAX_LIGHT_RADII)
1247 tmp->glow_radius = MAX_LIGHT_RADII; 1263 tmp->glow_radius = min (MAX_LIGHT_RADIUS, radius);
1248
1249 tmp = insert_ob_in_ob (tmp, op); 1264 tmp = insert_ob_in_ob (tmp, op);
1250 1265
1251 if (tmp->glow_radius > op->glow_radius) 1266 if (tmp->glow_radius > op->glow_radius)
1252 op->glow_radius = tmp->glow_radius; 1267 op->glow_radius = tmp->glow_radius;
1253 1268
1255} 1270}
1256 1271
1257int 1272int
1258cast_destruction (object *op, object *caster, object *spell_ob) 1273cast_destruction (object *op, object *caster, object *spell_ob)
1259{ 1274{
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); 1275 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); 1276 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); 1277 int dur = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
1269 if (QUERY_FLAG (op, FLAG_FRIENDLY) || op->type == PLAYER) 1278
1270 friendly = 1; 1279 bool friendly = op->flag [FLAG_FRIENDLY] || op->is_player ();
1271 1280
1272 /* destruction doesn't use another spell object, so we need 1281 /* destruction doesn't use another spell object, so we need
1273 * update op's skill pointer so that exp is properly awarded. 1282 * 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 */ 1283 */
1278 skill = op->skill; 1284 const shstr skill = op->skill;
1285
1279 if (caster == op) 1286 if (caster == op)
1280 op->skill = spell_ob->skill; 1287 op->skill = spell_ob->skill;
1281 else if (caster->skill) 1288 else if (caster->skill)
1282 op->skill = caster->skill; 1289 op->skill = caster->skill;
1283 else 1290 else
1284 op->skill = NULL; 1291 op->skill = 0;
1285 1292
1286 op->change_skill (find_skill_by_name (op, op->skill)); 1293 op->change_skill (find_skill_by_name (op, op->skill));
1287 1294
1288 for (i = -range; i <= range; i++) 1295 unordered_mapwalk (op, -range, -range, range, range)
1289 { 1296 {
1290 for (j = -range; j <= range; j++) 1297 mapspace &ms = m->at (nx, ny);
1291 {
1292 m = op->map;
1293 sx = op->x + i;
1294 sy = op->y + j;
1295 1298
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) 1299 if (ms.flags () & P_IS_ALIVE)
1300 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1301 if (tmp->flag [FLAG_ALIVE] || tmp->is_player ())
1301 { 1302 {
1302 for (tmp = GET_MAP_OB (m, sx, sy); tmp; tmp = tmp->above) 1303 tmp = tmp->head_ ();
1303 if (QUERY_FLAG (tmp, FLAG_ALIVE) || tmp->type == PLAYER)
1304 break;
1305 1304
1306 if (tmp) 1305 if ((friendly && !tmp->flag [FLAG_FRIENDLY] && !tmp->is_player ())
1306 || (!friendly && (tmp->flag [FLAG_FRIENDLY] || tmp->is_player ())))
1307 { 1307 {
1308 if (tmp->head) 1308 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 { 1309 {
1314 if (spell_ob->subtype == SP_DESTRUCTION)
1315 {
1316 hit_player (tmp, dam, op, spell_ob->attacktype, 0); 1310 hit_player (tmp, dam, op, spell_ob->attacktype, 0);
1317 1311
1318 if (spell_ob->other_arch) 1312 if (spell_ob->other_arch)
1319 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op); 1313 m->insert (arch_to_object (spell_ob->other_arch), nx, ny, op);
1320 } 1314 }
1321 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist[ATNR_MAGIC] != 100) 1315 else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist [ATNR_MAGIC] != 100)
1322 { 1316 {
1323 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch) 1317 if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch)
1324 m->insert (arch_to_object (spell_ob->other_arch), sx, sy, op); 1318 m->insert (arch_to_object (spell_ob->other_arch), nx, ny, op);
1325 }
1326 } 1319 }
1327 } 1320 }
1328 } 1321 }
1329 }
1330 } 1322 }
1331 1323
1332 op->skill = skill; 1324 op->skill = skill;
1333 return 1; 1325 return 1;
1334} 1326}
1441 */ 1433 */
1442int 1434int
1443mood_change (object *op, object *caster, object *spell) 1435mood_change (object *op, object *caster, object *spell)
1444{ 1436{
1445 object *tmp, *god, *head; 1437 object *tmp, *god, *head;
1446 int done_one, range, mflags, level, at, best_at; 1438 int done_one, range, level, at, best_at;
1447 sint16 x, y, nx, ny;
1448 maptile *m;
1449 const char *race; 1439 const char *race;
1450 1440
1451 /* We precompute some values here so that we don't have to keep 1441 /* We precompute some values here so that we don't have to keep
1452 * doing it over and over again. 1442 * doing it over and over again.
1453 */ 1443 */
1454 god = find_god (determine_god (op)); 1444 god = find_god (determine_god (op));
1455 level = caster_level (caster, spell); 1445 level = casting_level (caster, spell);
1456 range = spell->range + SP_level_range_adjust (caster, spell); 1446 range = spell->range + SP_level_range_adjust (caster, spell);
1457 1447
1458 /* On the bright side, no monster should ever have a race of GOD_... 1448 /* 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 1449 * so even if the player doesn't worship a god, if race=GOD_.., it
1460 * won't ever match anything. 1450 * won't ever match anything.
1466 else if (god && !strcmp (spell->race, "GOD_FRIEND")) 1456 else if (god && !strcmp (spell->race, "GOD_FRIEND"))
1467 race = god->race; 1457 race = god->race;
1468 else 1458 else
1469 race = spell->race; 1459 race = spell->race;
1470 1460
1471 for (x = op->x - range; x <= op->x + range; x++) 1461 unordered_mapwalk (op, -range, -range, range, range)
1472 for (y = op->y - range; y <= op->y + range; y++)
1473 { 1462 {
1474 done_one = 0; 1463 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 1464
1482 /* If there is nothing living on this space, no need to go further */ 1465 /* If there is nothing living on this space, no need to go further */
1483 if (!(mflags & P_IS_ALIVE)) 1466 if (!ms.flags () & P_IS_ALIVE)
1484 continue; 1467 continue;
1485 1468
1486 // players can only affect spaces that they can actually see 1469 // players can only affect spaces that they can actually see
1470 if (caster
1487 if (caster && caster->contr 1471 && caster->contr
1488 && caster->contr->visibility_at (m, nx, ny) < 70) 1472 && caster->contr->darkness_at (m, nx, ny) == LOS_BLOCKED)
1489 continue; 1473 continue;
1490 1474
1491 for (tmp = GET_MAP_TOP (m, nx, ny); tmp; tmp = tmp->below) 1475 for (tmp = ms.top; tmp; tmp = tmp->below)
1492 if (QUERY_FLAG (tmp, FLAG_MONSTER)) 1476 if (tmp->flag [FLAG_MONSTER])
1493 break; 1477 break;
1494 1478
1495 /* There can be living objects that are not monsters */ 1479 /* There can be living objects that are not monsters */
1496 if (!tmp || tmp->type == PLAYER) 1480 if (!tmp)
1497 continue; 1481 continue;
1498 1482
1499 /* Only the head has meaningful data, so resolve to that */ 1483 /* Only the head has meaningful data, so resolve to that */
1500 if (tmp->head)
1501 head = tmp->head; 1484 head = tmp->head_ ();
1502 else
1503 head = tmp;
1504 1485
1505 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */ 1486 /* Make sure the race is OK. Likewise, only effect undead if spell specifically allows it */
1506 if (race && head->race && !strstr (race, head->race)) 1487 if (race && head->race && !strstr (race, head->race))
1507 continue; 1488 continue;
1508 1489
1509 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD)) 1490 if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD))
1510 continue; 1491 continue;
1511 1492
1512 /* Now do a bunch of stuff related to saving throws */ 1493 /* Now do a bunch of stuff related to saving throws */
1513 best_at = -1; 1494 best_at = -1;
1514 if (spell->attacktype) 1495 if (spell->attacktype)
1515 { 1496 {
1516 for (at = 0; at < NROFATTACKS; at++) 1497 for (at = 0; at < NROFATTACKS; at++)
1517 if (spell->attacktype & (1 << at)) 1498 if (spell->attacktype & (1 << at))
1518 if (best_at == -1 || head->resist[at] > head->resist[best_at]) 1499 if (best_at == -1 || head->resist[at] > head->resist[best_at])
1519 best_at = at; 1500 best_at = at;
1520 1501
1521 if (best_at == -1) 1502 if (best_at == -1)
1522 at = 0; 1503 at = 0;
1523 else 1504 else
1524 { 1505 {
1525 if (head->resist[best_at] == 100) 1506 if (head->resist[best_at] == 100)
1526 continue; 1507 continue;
1527 else 1508 else
1528 at = head->resist[best_at] / 5; 1509 at = head->resist[best_at] / 5;
1529 } 1510 }
1511
1530 at -= level / 5; 1512 at -= level / 5;
1531 if (did_make_save (head, head->level, at)) 1513 if (did_make_save (head, head->level, at))
1532 continue; 1514 continue;
1533 } 1515 }
1534 else /* spell->attacktype */ 1516 else /* spell->attacktype */
1535 { 1517 {
1536 /* 1518 /*
1537 Spell has no attacktype (charm & such), so we'll have a specific saving: 1519 Spell has no attacktype (charm & such), so we'll have a specific saving:
1538 * if spell level < monster level, no go 1520 * if spell level < monster level, no go
1539 * else, chance of effect = 20 + min( 50, 2 * ( spell level - monster level ) ) 1521 * else, chance of effect = 20 + min( 50, 2 * ( spell level - monster level ) )
1540 1522
1541 The chance will then be in the range [20-70] percent, not too bad. 1523 The chance will then be in the range [20-70] percent, not too bad.
1542 1524
1543 This is required to fix the 'charm monster' abuse, where a player level 1 can 1525 This is required to fix the 'charm monster' abuse, where a player level 1 can
1544 charm a level 125 monster... 1526 charm a level 125 monster...
1545 1527
1546 Ryo, august 14th 1528 Ryo, august 14th
1547 */ 1529 */
1548 if (head->level > level) 1530 if (head->level > level)
1549 continue; 1531 continue;
1550 1532
1551 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level)))) 1533 if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level))))
1552 /* Failed, no effect */ 1534 /* Failed, no effect */
1553 continue; 1535 continue;
1554 } 1536 }
1555 1537
1556 /* Done with saving throw. Now start affecting the monster */ 1538 /* Done with saving throw. Now start affecting the monster */
1539 done_one = 0;
1557 1540
1558 /* aggravation */ 1541 /* aggravation */
1559 if (QUERY_FLAG (spell, FLAG_MONSTER)) 1542 if (QUERY_FLAG (spell, FLAG_MONSTER))
1560 { 1543 {
1561 CLEAR_FLAG (head, FLAG_SLEEP); 1544 CLEAR_FLAG (head, FLAG_SLEEP);
1562 remove_friendly_object (head); 1545 remove_friendly_object (head);
1563 done_one = 1; 1546 done_one = 1;
1564 head->enemy = op; 1547 head->enemy = op;
1565 } 1548 }
1566 1549
1567 /* calm monsters */ 1550 /* calm monsters */
1568 if (QUERY_FLAG (spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (head, FLAG_UNAGGRESSIVE)) 1551 if (QUERY_FLAG (spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (head, FLAG_UNAGGRESSIVE))
1569 { 1552 {
1570 SET_FLAG (head, FLAG_UNAGGRESSIVE); 1553 SET_FLAG (head, FLAG_UNAGGRESSIVE);
1571 head->enemy = NULL; 1554 head->enemy = NULL;
1572 done_one = 1; 1555 done_one = 1;
1573 } 1556 }
1574 1557
1575 /* berserk monsters */ 1558 /* berserk monsters */
1576 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK)) 1559 if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK))
1577 { 1560 {
1578 SET_FLAG (head, FLAG_BERSERK); 1561 SET_FLAG (head, FLAG_BERSERK);
1579 done_one = 1; 1562 done_one = 1;
1580 } 1563 }
1581 1564
1582 /* charm */ 1565 /* charm */
1583 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY)) 1566 if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY))
1584 { 1567 {
1585 INVOKE_OBJECT (KILL, head, ARG_OBJECT (caster)); 1568 INVOKE_OBJECT (KILL, head, ARG_OBJECT (caster));
1586 1569
1587 /* Prevent uncontrolled outbreaks of self replicating monsters. 1570 /* Prevent uncontrolled outbreaks of self replicating monsters.
1588 Typical use case is charm, go somwhere, use aggravation to make hostile. 1571 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. */ 1572 This could lead to fun stuff like mice outbreak in bigworld and server crawl. */
1590 CLEAR_FLAG (head, FLAG_GENERATOR); 1573 CLEAR_FLAG (head, FLAG_GENERATOR);
1591 head->set_owner (op); 1574 head->set_owner (op);
1592 set_spell_skill (op, caster, spell, head); 1575 set_spell_skill (op, caster, spell, head);
1593 add_friendly_object (head); 1576 add_friendly_object (head);
1594 head->attack_movement = PETMOVE; 1577 head->attack_movement = PETMOVE;
1595 done_one = 1; 1578 done_one = 1;
1596 change_exp (op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL); 1579 change_exp (op, head->stats.exp / 2, head->skill, SK_EXP_ADD_SKILL);
1597 head->stats.exp = 0; 1580 head->stats.exp = 0;
1598 } 1581 }
1599 1582
1600 /* If a monster was effected, put an effect in */ 1583 /* If a monster was effected, put an effect in */
1601 if (done_one && spell->other_arch) 1584 if (done_one && spell->other_arch)
1602 m->insert (arch_to_object (spell->other_arch), nx, ny, op); 1585 m->insert (arch_to_object (spell->other_arch), nx, ny, op);
1603 } /* for y */ 1586 }
1604 1587
1605 return 1; 1588 return 1;
1606} 1589}
1607
1608 1590
1609/* Move_ball_spell: This handles ball type spells that just sort of wander 1591/* 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 1592 * about. was called move_ball_lightning, but since more than the ball
1611 * lightning spell used it, that seemed misnamed. 1593 * lightning spell used it, that seemed misnamed.
1612 * op is the spell effect. 1594 * op is the spell effect.
1613 * note that duration is handled by process_object() in time.c 1595 * note that duration is handled by process_object() in time.c
1614 */ 1596 */
1615
1616void 1597void
1617move_ball_spell (object *op) 1598move_ball_spell (object *op)
1618{ 1599{
1619 int i, j, dam_save, dir, mflags; 1600 int i, j, dam_save, dir, mflags;
1620 sint16 nx, ny, hx, hy; 1601 sint16 nx, ny, hx, hy;
1639 for (i = 1; i < 9; i++) 1620 for (i = 1; i < 9; i++)
1640 { 1621 {
1641 /* i bit 0: alters sign of offset 1622 /* i bit 0: alters sign of offset
1642 * other bits (i / 2): absolute value of offset 1623 * other bits (i / 2): absolute value of offset
1643 */ 1624 */
1644
1645 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2); 1625 int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2);
1646 int tmpdir = absdir (op->direction + offset); 1626 int tmpdir = absdir (op->direction + offset);
1647 1627
1648 nx = op->x + freearr_x[tmpdir]; 1628 nx = op->x + freearr_x[tmpdir];
1649 ny = op->y + freearr_y[tmpdir]; 1629 ny = op->y + freearr_y[tmpdir];
1651 { 1631 {
1652 dir = tmpdir; 1632 dir = tmpdir;
1653 break; 1633 break;
1654 } 1634 }
1655 } 1635 }
1636
1656 if (dir == 0) 1637 if (dir == 0)
1657 { 1638 {
1658 nx = op->x; 1639 nx = op->x;
1659 ny = op->y; 1640 ny = op->y;
1660 m = op->map; 1641 m = op->map;
1730 int adjustdir; 1711 int adjustdir;
1731 maptile *m; 1712 maptile *m;
1732#endif 1713#endif
1733 object *owner = op->env; 1714 object *owner = op->env;
1734 1715
1716 if (!owner) // MUST not happen, remove when true TODO
1717 {
1718 LOG (llevError, "swarm spell found outside inventory: %s\n", op->debug_desc ());
1719 op->destroy ();
1720 return;
1721 }
1722
1735 if (!op->duration || !owner->is_on_map ()) 1723 if (!op->duration || !owner->is_on_map ())
1736 { 1724 {
1737 op->destroy (); 1725 op->drop_and_destroy ();
1738 return; 1726 return;
1739 } 1727 }
1740 1728
1741 op->duration--; 1729 op->duration--;
1742 1730
1743 int basedir = op->direction; 1731 int basedir = op->direction;
1744 if (!basedir) 1732 if (!basedir)
1733 {
1745 /* spray in all directions! 8) */ 1734 /* spray in all directions! 8) */
1746 basedir = (op->facing += op->state) % 8 + 1; 1735 op->facing = (op->facing + op->state) & 7;
1736 basedir = op->facing + 1;
1737 }
1747 1738
1748#if 0 1739#if 0
1749 // this is bogus: it causes wrong places to be checked below 1740 // this is bogus: it causes wrong places to be checked below
1750 // (a wall 2 cells away will block the effect...) and 1741 // (a wall 2 cells away will block the effect...) and
1751 // doesn't work for SP_BULLET anyhow, so again tests the wrong 1742 // doesn't work for SP_BULLET anyhow, so again tests the wrong
1833{ 1824{
1834 if (!spell->other_arch) 1825 if (!spell->other_arch)
1835 return 0; 1826 return 0;
1836 1827
1837 object *tmp = archetype::get (SWARM_SPELL); 1828 object *tmp = archetype::get (SWARM_SPELL);
1829
1838 set_spell_skill (op, caster, spell, tmp); 1830 set_spell_skill (op, caster, spell, tmp);
1839 tmp->level = caster_level (caster, spell); /* needed later, to get level dep. right. */ 1831 tmp->level = casting_level (caster, spell); /* needed later, to get level dep. right. */
1840 tmp->spell = spell->other_arch->instance (); 1832 tmp->spell = spell->other_arch->instance ();
1841 tmp->attacktype = tmp->spell->attacktype; 1833 tmp->attacktype = tmp->spell->attacktype;
1842 1834
1843 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) 1835 if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER)
1844 if (!tailor_god_spell (tmp, op)) 1836 if (!tailor_god_spell (tmp, op))
1846 1838
1847 tmp->duration = SP_level_duration_adjust (caster, spell); 1839 tmp->duration = SP_level_duration_adjust (caster, spell);
1848 for (int i = 0; i < spell->duration; i++) 1840 for (int i = 0; i < spell->duration; i++)
1849 tmp->duration += die_roll (1, 3, op, PREFER_HIGH); 1841 tmp->duration += die_roll (1, 3, op, PREFER_HIGH);
1850 1842
1843 tmp->invisible = 1;
1844 tmp->flag [FLAG_NO_DROP] = 1; // make sure it stays in inv, or else
1851 tmp->direction = dir; 1845 tmp->direction = dir;
1852 tmp->invisible = 1;
1853 tmp->facing = rndm (1, 8); // initial firing direction 1846 tmp->facing = rndm (1, 8); // initial firing direction
1854 tmp->state = rndm (4) * 2 + 1; // direction increment 1847 tmp->state = rndm (4) * 2 + 1; // direction increment
1855 1848
1856 op->insert (tmp); 1849 op->insert (tmp);
1857 1850
1869 int dam, mflags; 1862 int dam, mflags;
1870 maptile *m; 1863 maptile *m;
1871 1864
1872 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); 1865 dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
1873 1866
1874 if (!dir) 1867 if (dir)
1875 {
1876 new_draw_info (NDI_UNIQUE, 0, op, "In what direction?");
1877 return 0;
1878 } 1868 {
1879
1880 x = op->x + freearr_x[dir]; 1869 x = op->x + freearr_x[dir];
1881 y = op->y + freearr_y[dir]; 1870 y = op->y + freearr_y[dir];
1882 m = op->map; 1871 m = op->map;
1883 1872
1884 mflags = get_map_flags (m, &m, x, y, &x, &y); 1873 mflags = get_map_flags (m, &m, x, y, &x, &y);
1885 1874
1886 if (mflags & P_OUT_OF_MAP) 1875 if (mflags & P_OUT_OF_MAP)
1887 { 1876 {
1888 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there."); 1877 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there.");
1889 return 0; 1878 return 0;
1890 } 1879 }
1891 1880
1892 if (mflags & P_IS_ALIVE && spell->attacktype) 1881 if (mflags & P_IS_ALIVE && spell->attacktype)
1893 { 1882 {
1894 for (target = GET_MAP_OB (m, x, y); target; target = target->above) 1883 for (target = GET_MAP_OB (m, x, y); target; target = target->above)
1895 if (QUERY_FLAG (target, FLAG_MONSTER)) 1884 if (QUERY_FLAG (target, FLAG_MONSTER))
1896 { 1885 {
1897 /* oky doky. got a target monster. Lets make a blinding attack */ 1886 /* oky doky. got a target monster. Lets make a blinding attack */
1898 if (target->head) 1887 if (target->head)
1899 target = target->head; 1888 target = target->head;
1900 1889
1901 hit_player (target, dam, op, spell->attacktype, 1); 1890 hit_player (target, dam, op, spell->attacktype, 1);
1902 return 1; /* one success only! */ 1891 return 1; /* one success only! */
1892 }
1903 } 1893 }
1904 }
1905 1894
1906 /* no live target, perhaps a wall is in the way? */ 1895 /* no live target, perhaps a wall is in the way? */
1907 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y))) 1896 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)))
1908 { 1897 {
1909 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); 1898 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1910 return 0; 1899 return 0;
1900 }
1911 } 1901 }
1912 1902
1913 /* ok, looks groovy to just insert a new light on the map */ 1903 /* ok, looks groovy to just insert a new light on the map */
1914 tmp = arch_to_object (spell->other_arch); 1904 tmp = arch_to_object (spell->other_arch);
1915 if (!tmp) 1905 if (!tmp)
1916 { 1906 {
1917 LOG (llevError, "Error: spell arch for cast_light() missing.\n"); 1907 LOG (llevError, "Error: spell arch for cast_light() missing.\n");
1918 return 0; 1908 return 0;
1919 } 1909 }
1910
1920 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell); 1911 tmp->stats.food = spell->duration + SP_level_duration_adjust (caster, spell);
1912
1921 if (tmp->glow_radius) 1913 if (tmp->glow_radius)
1922 {
1923 tmp->glow_radius = spell->range + SP_level_range_adjust (caster, spell); 1914 tmp->glow_radius = 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 1915
1916 if (dir)
1928 m->insert (tmp, x, y, op); 1917 m->insert (tmp, x, y, op);
1918 else
1919 caster->outer_env ()->insert (tmp);
1920
1929 return 1; 1921 return 1;
1930} 1922}
1931 1923
1932/* cast_cause_disease: this spell looks along <dir> from the 1924/* cast_cause_disease: this spell looks along <dir> from the
1933 * player and infects someone. 1925 * player and infects someone.
1986 object *disease = arch_to_object (spell->other_arch); 1978 object *disease = arch_to_object (spell->other_arch);
1987 1979
1988 disease->set_owner (op); 1980 disease->set_owner (op);
1989 set_spell_skill (op, caster, spell, disease); 1981 set_spell_skill (op, caster, spell, disease);
1990 disease->stats.exp = 0; 1982 disease->stats.exp = 0;
1991 disease->level = caster_level (caster, spell); 1983 disease->level = casting_level (caster, spell);
1992 1984
1993 /* do level adjustments */ 1985 /* do level adjustments */
1994 if (disease->stats.wc) 1986 if (disease->stats.wc)
1995 disease->stats.wc += dur_mod / 2; 1987 disease->stats.wc += dur_mod / 2;
1996 1988

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines