--- deliantra/server/server/spell_attack.C 2009/11/06 13:03:34 1.90 +++ deliantra/server/server/spell_attack.C 2010/04/10 05:12:57 1.101 @@ -1,9 +1,9 @@ /* * 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 (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * 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; @@ -1275,50 +1288,40 @@ bool friendly = op->flag [FLAG_FRIENDLY] || op->is_player (); - /* destruction doesn't use another spell object, so we need - * update op's skill pointer so that exp is properly awarded. - */ - const shstr skill = op->skill; - - if (caster == op) - op->skill = spell_ob->skill; - else if (caster->skill) - op->skill = caster->skill; - else - op->skill = 0; - - 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; return 1; } @@ -1327,7 +1330,6 @@ * CURSE * ***************************************************************************/ - int cast_curse (object *op, object *caster, object *spell_ob, int dir) { @@ -1415,8 +1417,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 +1457,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); @@ -1527,7 +1530,7 @@ if (head->level > level) continue; - if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + MIN (50, 2 * (level - head->level)))) + if (random_roll (0, 100, caster, PREFER_LOW) >= (20 + min (50, 2 * (level - head->level)))) /* Failed, no effect */ continue; } @@ -1579,7 +1582,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 +1675,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 +1901,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 +1977,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); @@ -1982,59 +1985,32 @@ disease->level = casting_level (caster, spell); /* do level adjustments */ - if (disease->stats.wc) - disease->stats.wc += dur_mod / 2; - - if (disease->magic > 0) - disease->magic += dur_mod / 8; - - if (disease->stats.maxhp > 0) - disease->stats.maxhp += dur_mod; - - if (disease->stats.maxgrace > 0) - disease->stats.maxgrace += dur_mod; - - if (disease->stats.dam) - { - if (disease->stats.dam > 0) - disease->stats.dam += dam_mod; - else - disease->stats.dam -= dam_mod; - } + if (disease->stats.wc ) disease->stats.wc += dur_mod / 2; + if (disease->magic > 0) disease->magic += dur_mod / 8; + if (disease->stats.maxhp > 0) disease->stats.maxhp += dur_mod; + if (disease->stats.maxgrace > 0) disease->stats.maxgrace += dur_mod; if (disease->last_sp) { disease->last_sp -= 2 * dam_mod; + if (disease->last_sp < 1) disease->last_sp = 1; } - if (disease->stats.maxsp) - { - if (disease->stats.maxsp > 0) - disease->stats.maxsp += dam_mod; - else - disease->stats.maxsp -= dam_mod; - } - - if (disease->stats.ac) - disease->stats.ac += dam_mod; - - if (disease->last_eat) - disease->last_eat -= dam_mod; - - if (disease->stats.hp) - disease->stats.hp -= dam_mod; - - if (disease->stats.sp) - disease->stats.sp -= dam_mod; + if (disease->stats.dam ) disease->stats.dam += copysign (disease->stats.dam , dam_mod); + if (disease->stats.maxsp) disease->stats.maxsp += copysign (disease->stats.maxsp, dam_mod); + if (disease->stats.ac ) disease->stats.ac += dam_mod; + if (disease->last_eat ) disease->last_eat -= dam_mod; + if (disease->stats.hp ) disease->stats.hp -= dam_mod; + if (disease->stats.sp ) disease->stats.sp -= dam_mod; if (infect_object (walk, disease, 1)) { - new_draw_info_format (NDI_UNIQUE, 0, op, "You inflict %s on %s!", &disease->name, &walk->name); + op->statusmsg (format ("You inflict %s on %s!", &disease->name, &walk->name)); disease->destroy (); /* don't need this one anymore */ - walk->map->insert (get_archetype ("detect_magic"), x, y, op); + walk->map->insert (get_archetype (shstr_detect_magic), x, y, op); return 1; }