--- deliantra/server/server/spell_attack.C 2009/11/07 18:30:06 1.91 +++ deliantra/server/server/spell_attack.C 2010/03/26 00:59:22 1.98 @@ -2,8 +2,8 @@ * This file is part of Deliantra, the Roguelike Realtime MMORPG. * * Copyright (©) 2005,2006,2007,2008,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team - * Copyright (©) 2002-2003,2007 Mark Wedel & Crossfire Development Team - * Copyright (©) 1992,2007 Frank Tore Johansen + * Copyright (©) 2002-2003 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992 Frank Tore Johansen * * Deliantra is free software: you can redistribute it and/or modify it under * the terms of the Affero GNU General Public License as published by the @@ -95,7 +95,7 @@ * I don't see us doing anything useful with that information * right now. */ - move_object (tmp, absdir (op->stats.sp)); + tmp->move (absdir (op->stats.sp)); } } @@ -279,7 +279,7 @@ if (!spob->other_arch) return 0; - tmp = arch_to_object (spob->other_arch); + tmp = spob->other_arch->instance (); if (tmp == NULL) return 0; @@ -441,7 +441,7 @@ } /* other_arch contains what this explodes into */ - tmp = arch_to_object (op->other_arch); + tmp = op->other_arch->instance (); tmp->set_owner (op); tmp->skill = op->skill; @@ -662,6 +662,19 @@ tmp->map = newmap; + // in case the bullet has direction 0 we explode it in place. + // direction 0 is possible for instance when a poison cloud trap springs. + if (tmp->direction == 0) + { + if (tmp->other_arch + && (tmp = tmp->insert_at (tmp, op))) // insert before explode cleanly + explode_bullet (tmp); // explode object will/should remove tmp + else + tmp->destroy (); + + return 0; + } + if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (tmp->map, tmp->x, tmp->y))) { if (!QUERY_FLAG (tmp, FLAG_REFLECTING)) @@ -692,7 +705,7 @@ static void cone_drop (object *op) { - object *new_ob = arch_to_object (op->other_arch); + object *new_ob = op->other_arch->instance (); new_ob->level = op->level; new_ob->set_owner (op->owner); @@ -863,7 +876,7 @@ continue; success = 1; - tmp = arch_to_object (spell->other_arch); + tmp = spell->other_arch->instance (); tmp->set_owner (op); set_spell_skill (op, caster, spell, tmp); tmp->level = casting_level (caster, spell); @@ -975,7 +988,7 @@ if (out_of_map (op->map, op->x + freearr_x[i], op->y + freearr_x[i])) continue; - object *tmp = arch_to_object (at); + object *tmp = at->instance (); tmp->direction = i; tmp->range = op->range; tmp->stats.dam = op->stats.dam; @@ -1019,7 +1032,7 @@ } } - tmp = arch_to_object (spell->other_arch); + tmp = spell->other_arch->instance (); /* level dependencies for bomb */ tmp->range = spell->range + SP_level_range_adjust (caster, spell); @@ -1123,7 +1136,7 @@ } if (spell->other_arch) - effect = arch_to_object (spell->other_arch); + effect = spell->other_arch->instance (); else return 0; @@ -1289,33 +1302,38 @@ op->change_skill (find_skill_by_name (op, op->skill)); - unordered_mapwalk (op, -range, -range, range, range) + dynbuf buf; + unordered_mapwalk (buf, op, -range, -range, range, range) { mapspace &ms = m->at (nx, ny); if (ms.flags () & P_IS_ALIVE) - for (object *tmp = ms.bot; tmp; tmp = tmp->above) - if (tmp->flag [FLAG_ALIVE] || tmp->is_player ()) - { - tmp = tmp->head_ (); + for (object *next, *tmp = ms.bot; tmp; tmp = next) + { + next = tmp->above; - if ((friendly && !tmp->flag [FLAG_FRIENDLY] && !tmp->is_player ()) - || (!friendly && (tmp->flag [FLAG_FRIENDLY] || tmp->is_player ()))) - { - if (spell_ob->subtype == SP_DESTRUCTION) - { - hit_player (tmp, dam, op, spell_ob->attacktype, 0); - - if (spell_ob->other_arch) - m->insert (arch_to_object (spell_ob->other_arch), nx, ny, op); - } - else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist [ATNR_MAGIC] != 100) - { - if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch) - m->insert (arch_to_object (spell_ob->other_arch), nx, ny, op); - } - } - } + if (tmp->flag [FLAG_ALIVE] || tmp->is_player ()) + { + tmp = tmp->head_ (); + + if ((friendly && !tmp->flag [FLAG_FRIENDLY] && !tmp->is_player ()) + || (!friendly && (tmp->flag [FLAG_FRIENDLY] || tmp->is_player ()))) + { + if (spell_ob->subtype == SP_DESTRUCTION) + { + hit_player (tmp, dam, op, spell_ob->attacktype, 0); + + if (spell_ob->other_arch) + m->insert (spell_ob->other_arch->instance (), nx, ny, op); + } + else if (spell_ob->subtype == SP_FAERY_FIRE && tmp->resist [ATNR_MAGIC] != 100) + { + if (make_object_glow (tmp, 1, dur) && spell_ob->other_arch) + m->insert (spell_ob->other_arch->instance (), nx, ny, op); + } + } + } + } } op->skill = skill; @@ -1327,7 +1345,6 @@ * CURSE * ***************************************************************************/ - int cast_curse (object *op, object *caster, object *spell_ob, int dir) { @@ -1415,8 +1432,8 @@ change_abil (tmp, force); /* Mostly to display any messages */ insert_ob_in_ob (force, tmp); tmp->update_stats (); - return 1; + return 1; } /********************************************************************** @@ -1455,7 +1472,8 @@ else race = spell->race; - unordered_mapwalk (op, -range, -range, range, range) + dynbuf buf; + unordered_mapwalk (buf, op, -range, -range, range, range) { mapspace &ms = m->at (nx, ny); @@ -1579,7 +1597,7 @@ /* If a monster was effected, put an effect in */ if (done_one && spell->other_arch) - m->insert (arch_to_object (spell->other_arch), nx, ny, op); + m->insert (spell->other_arch->instance (), nx, ny, op); } return 1; @@ -1672,7 +1690,7 @@ /* insert the other arch */ if (op->other_arch && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy)))) - m->insert (arch_to_object (op->other_arch), hx, hy, op); + m->insert (op->other_arch->instance (), hx, hy, op); } /* restore to the center location and damage */ @@ -1898,7 +1916,7 @@ } /* ok, looks groovy to just insert a new light on the map */ - tmp = arch_to_object (spell->other_arch); + tmp = spell->other_arch->instance (); if (!tmp) { LOG (llevError, "Error: spell arch for cast_light() missing.\n"); @@ -1974,7 +1992,7 @@ for (walk = GET_MAP_OB (m, x, y); walk; walk = walk->above) if (QUERY_FLAG (walk, FLAG_MONSTER) || (walk->type == PLAYER)) { /* found a victim */ - object *disease = arch_to_object (spell->other_arch); + object *disease = spell->other_arch->instance (); disease->set_owner (op); set_spell_skill (op, caster, spell, disease);