--- deliantra/server/server/spell_attack.C 2007/08/01 00:26:03 1.45 +++ deliantra/server/server/spell_attack.C 2008/05/17 00:17:02 1.55 @@ -1,11 +1,11 @@ /* - * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. + * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team + * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2002-2003,2007 Mark Wedel & Crossfire Development Team * Copyright (©) 1992,2007 Frank Tore Johansen * - * Crossfire TRT is free software: you can redistribute it and/or modify + * Deliantra is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * The authors can be reached via e-mail to + * The authors can be reached via e-mail to */ /* This file contains all the spell attack code. Grouping this code @@ -345,7 +345,7 @@ ***************************************************************************/ /* expands an explosion. op is a piece of the - * explosion - this expans it in the different directions. + * explosion - this expands it in the different directions. * At least that is what I think this does. */ void @@ -407,8 +407,9 @@ if (op->env) { - object *env = object_get_env_recursive (op); - if (env->map == NULL || out_of_map (env->map, env->x, env->y)) + object *env = op->outer_env (); + + if (!env->map || out_of_map (env->map, env->x, env->y)) { LOG (llevError, "BUG: explode_bullet(): env out of map\n"); op->destroy (); @@ -621,11 +622,11 @@ if (!spob->other_arch) return 0; - tmp = arch_to_object (spob->other_arch); - if (tmp == NULL) + tmp = spob->other_arch->instance (); + if (!tmp) return 0; - /* peterm: level dependency for bolts */ + /* peterm: level dependency for bolts */ tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob); tmp->attacktype = spob->attacktype; if (spob->slaying) @@ -645,8 +646,8 @@ tmp->set_owner (op); set_spell_skill (op, caster, spob, tmp); - tmp->x = op->x + freearr_x[dir]; - tmp->y = op->y + freearr_y[dir]; + tmp->x = op->x + freearr_x[dir]; + tmp->y = op->y + freearr_y[dir]; tmp->map = op->map; maptile *newmap; @@ -939,22 +940,16 @@ void animate_bomb (object *op) { - int i; - object *env, *tmp; - if (op->state != NUM_ANIMATIONS (op) - 1) return; - env = object_get_env_recursive (op); + object *env = op->outer_env (); if (op->env) { if (env->map == NULL) return; - if (env->type == PLAYER) - esrv_del_item (env->contr, op->count); - if (!(op = op->insert_at (env, op))) return; } @@ -974,12 +969,12 @@ */ if (archetype *at = archetype::find (SPLINT)) { - for (i = 1; i < 9; i++) + for (int i = 1; i < 9; i++) { if (out_of_map (op->map, op->x + freearr_x[i], op->y + freearr_x[i])) continue; - tmp = arch_to_object (at); + object *tmp = arch_to_object (at); tmp->direction = i; tmp->range = op->range; tmp->stats.dam = op->stats.dam; @@ -1003,7 +998,6 @@ int create_bomb (object *op, object *caster, int dir, object *spell) { - object *tmp; int mflags; sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir]; @@ -1015,6 +1009,7 @@ new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); return 0; } + tmp = arch_to_object (spell->other_arch); /* level dependencies for bomb */ @@ -1176,7 +1171,6 @@ return 1; } - /**************************************************************************** * * MAGIC MISSILE code. @@ -1376,8 +1370,10 @@ return 0; } + tmp = tmp->head_ (); + /* If we've already got a force of this type, don't add a new one. */ - for (force = tmp->inv; force != NULL; force = force->below) + for (force = tmp->inv; force; force = force->below) { if (force->type == FORCE && force->subtype == FORCE_CHANGE_ABILITY) { @@ -1393,10 +1389,11 @@ } } - if (force == NULL) + if (!force) { force = get_archetype (FORCE_NAME); force->subtype = FORCE_CHANGE_ABILITY; + if (spell_ob->race) force->name = spell_ob->race; else @@ -1416,11 +1413,11 @@ new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); } else - { - new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); - } + new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); + return 1; } + force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50; force->speed = 1.f; force->speed_left = -1.f; @@ -1603,7 +1600,9 @@ /* charm */ if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY)) { - /* Prevent uncontolled outbreaks of self replicating monsters. + INVOKE_OBJECT (KILL, head, ARG_OBJECT (caster)); + + /* Prevent uncontrolled outbreaks of self replicating monsters. Typical use case is charm, go somwhere, use aggravation to make hostile. This could lead to fun stuff like mice outbreak in bigworld and server crawl. */ CLEAR_FLAG (head, FLAG_GENERATOR); @@ -1732,15 +1731,13 @@ } } - -/* move_swarm_spell: peterm +/* move_swarm_spell: peterm * This is an implementation of the swarm spell. It was written for - * meteor swarm, but it could be used for any swarm. A swarm spell + * meteor swarm, but it could be used for any swarm. A swarm spell * is a special type of object that casts swarms of other types - * of spells. Which spell it casts is flexible. It fires the spells + * of spells. Which spell it casts is flexible. It fires the spells * from a set of squares surrounding the caster, in a given direction. */ - void move_swarm_spell (object *op) { @@ -1751,11 +1748,9 @@ int adjustdir; maptile *m; #endif - int basedir; - object *owner; + object *owner = op->env; - owner = op->owner; - if (op->duration == 0 || owner == NULL) + if (!op->duration || !owner->is_on_map ()) { op->destroy (); return; @@ -1763,12 +1758,10 @@ op->duration--; - basedir = op->direction; - if (basedir == 0) - { - /* spray in all directions! 8) */ - basedir = rndm (1, 8); - } + int basedir = op->direction; + if (!basedir) + /* spray in all directions! 8) */ + basedir = rndm (1, 8); #if 0 // this is bogus: it causes wrong places to be checked below @@ -1842,9 +1835,6 @@ } } - - - /* fire_swarm: * The following routine creates a swarm of objects. It actually * sets up a specific swarm object, which then fires off all @@ -1856,23 +1846,16 @@ * spell - the spell that is this spell. * n: the number to be fired. */ - int fire_swarm (object *op, object *caster, object *spell, int dir) { - object *tmp; - int i; - if (!spell->other_arch) return 0; - tmp = get_archetype (SWARM_SPELL); - tmp->set_owner (op); /* needed so that if swarm elements kill, caster gets xp. */ + object *tmp = archetype::get (SWARM_SPELL); set_spell_skill (op, caster, spell, tmp); - - tmp->level = caster_level (caster, spell); /*needed later, to get level dep. right. */ - tmp->spell = arch_to_object (spell->other_arch); - + tmp->level = caster_level (caster, spell); /* needed later, to get level dep. right. */ + tmp->spell = spell->other_arch->instance (); tmp->attacktype = tmp->spell->attacktype; if (tmp->attacktype & AT_HOLYWORD || tmp->attacktype & AT_GODPOWER) @@ -1880,17 +1863,17 @@ return 1; tmp->duration = SP_level_duration_adjust (caster, spell); - for (i = 0; i < spell->duration; i++) + for (int i = 0; i < spell->duration; i++) tmp->duration += die_roll (1, 3, op, PREFER_HIGH); tmp->direction = dir; tmp->invisible = 1; - tmp->insert_at (op, op); + op->insert (tmp); + return 1; } - /* See the spells documentation file for why this is its own * function. */ @@ -1961,16 +1944,12 @@ return 1; } - - - /* cast_cause_disease: this spell looks along from the * player and infects someone. * op is the player/monster, caster is the object, dir is the direction * to cast, disease_arch is the specific disease, and type is the spell number * perhaps this should actually be in disease.c? */ - int cast_cause_disease (object *op, object *caster, object *spell, int dir) { @@ -1987,6 +1966,7 @@ */ if (!dir) dir = op->facing; + if (!dir) return 0; /* won't find anything if casting on ourself, so just return */ @@ -2030,7 +2010,7 @@ disease->stats.wc += dur_mod / 2; if (disease->magic > 0) - disease->magic += dur_mod / 4; + disease->magic += dur_mod / 8; if (disease->stats.maxhp > 0) disease->stats.maxhp += dur_mod;