--- deliantra/server/server/spell_attack.C 2009/09/01 22:40:26 1.85 +++ deliantra/server/server/spell_attack.C 2018/11/18 15:19:48 1.118 @@ -1,23 +1,25 @@ /* * 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 - * - * 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. - * + * + * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team + * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 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 + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * + * + * You should have received a copy of the Affero GNU General Public License + * and the GNU General Public License along with this program. If not, see + * . + * * The authors can be reached via e-mail to */ @@ -38,7 +40,7 @@ * but moved here so it could be applied to bolts too * op is the spell object. */ -void +static void check_spell_knockback (object *op) { int weight_move; @@ -60,7 +62,7 @@ int num_sections = 1; /* don't move DM */ - if (QUERY_FLAG (tmp, FLAG_WIZ)) + if (tmp->flag [FLAG_WIZ]) return; /* don't move parts of objects */ @@ -68,7 +70,7 @@ continue; /* don't move floors or immobile objects */ - if (QUERY_FLAG (tmp, FLAG_IS_FLOOR) || (!QUERY_FLAG (tmp, FLAG_ALIVE) && QUERY_FLAG (tmp, FLAG_NO_PICK))) + if (tmp->flag [FLAG_IS_FLOOR] || (!tmp->flag [FLAG_ALIVE] && tmp->flag [FLAG_NO_PICK])) continue; /* count the object's sections */ @@ -87,14 +89,14 @@ if (rndm (0, weight_move - 1) > ((tmp->weight / num_sections) * frictionmod)) { /* move it. */ - /* move_object is really for monsters, but looking at + /* move_object is really for monsters, but looking at * the move_object function, it appears that it should * also be safe for objects. * This does return if successful or not, but * 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)); } } @@ -109,7 +111,7 @@ /* Causes op to fork. op is the original bolt, tmp * is the first piece of the fork. */ -void +static void forklightning (object *op, object *tmp) { int new_dir = 1; /* direction or -1 for left, +1 for right 0 if no new bolt */ @@ -130,7 +132,7 @@ /* check the new dir for a wall and in the map */ t_dir = absdir (tmp->direction + new_dir); - if (get_map_flags (tmp->map, &m, tmp->x + freearr_x[t_dir], tmp->y + freearr_y[t_dir], &sx, &sy) & P_OUT_OF_MAP) + if (get_map_flags (tmp->map, &m, tmp->x + DIRX (t_dir), tmp->y + DIRY (t_dir), &sx, &sy) & P_OUT_OF_MAP) return; if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (m, sx, sy))) @@ -180,8 +182,8 @@ op->range = 0; else { - x = op->x + DIRX (op); - y = op->y + DIRY (op); + x = op->x + DIRX (op->direction); + y = op->y + DIRY (op->direction); m = op->map; mflags = get_map_flags (m, &m, x, y, &x, &y); @@ -195,7 +197,7 @@ */ if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)) || ((mflags & P_IS_ALIVE) && reflwall (m, x, y, op))) { - if (!QUERY_FLAG (op, FLAG_REFLECTING)) + if (!op->flag [FLAG_REFLECTING]) return; /* Since walls don't run diagonal, if the bolt is in @@ -218,13 +220,13 @@ * op->direction is within an adjacent map but either * op->direction-1 or op->direction+1 does not exist. */ - mflags = get_map_flags (op->map, &m, op->x + freearr_x[absdir (op->direction - 1)], - op->y + freearr_y[absdir (op->direction - 1)], &x, &y); + mflags = get_map_flags (op->map, &m, op->x + DIRX (absdir (op->direction - 1)), + op->y + DIRY (absdir (op->direction - 1)), &x, &y); left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)); - mflags = get_map_flags (op->map, &m, op->x + freearr_x[absdir (op->direction + 1)], - op->y + freearr_y[absdir (op->direction + 1)], &x, &y); + mflags = get_map_flags (op->map, &m, op->x + DIRX (absdir (op->direction + 1)), + op->y + DIRY (absdir (op->direction + 1)), &x, &y); right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)); if (left == right) @@ -248,7 +250,7 @@ tmp->duration++; /* New forking code. Possibly create forks of this object - * going off in other directions. + * going off in other directions. */ if (tmp->stats.Dex && rndm (0, 99) < tmp->stats.Dex) forklightning (op, tmp); /* stats.Dex % of forking */ @@ -278,7 +280,7 @@ if (!spob->other_arch) return 0; - tmp = arch_to_object (spob->other_arch); + tmp = spob->other_arch->instance (); if (tmp == NULL) return 0; @@ -295,14 +297,14 @@ tmp->stats.Con = spob->stats.Con; tmp->direction = dir; - if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE)) - SET_ANIMATION (tmp, dir); + if (tmp->flag [FLAG_IS_TURNABLE]) + tmp->set_anim_frame (dir); tmp->set_owner (op); set_spell_skill (op, caster, spob, tmp); - tmp->x = op->x + DIRX (tmp); - tmp->y = op->y + DIRY (tmp); + tmp->x = op->x + DIRX (tmp->direction); + tmp->y = op->y + DIRY (tmp->direction); tmp->map = op->map; maptile *newmap; @@ -317,7 +319,7 @@ if (OB_TYPE_MOVE_BLOCK (tmp, GET_MAP_MOVE_BLOCK (tmp->map, tmp->x, tmp->y))) { - if (!QUERY_FLAG (tmp, FLAG_REFLECTING)) + if (!tmp->flag [FLAG_REFLECTING]) { tmp->drop_and_destroy (); return 0; @@ -365,10 +367,10 @@ { sint16 dx, dy; - dx = op->x + freearr_x[i]; - dy = op->y + freearr_y[i]; + dx = op->x + DIRX (i); + dy = op->y + DIRY (i); - /* ok_to_put_more already does things like checks for walls, + /* ok_to_put_more already does things like checks for walls, * out of map, etc. */ if (ok_to_put_more (op->map, dx, dy, op, op->attacktype)) @@ -390,7 +392,7 @@ * poison cloud ball, etc. op is the object to * explode. */ -void +static void explode_bullet (object *op) { object *tmp, *owner; @@ -440,7 +442,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; @@ -522,14 +524,14 @@ for (tmp = op->ms ().bot; tmp; tmp = tmp->above) { - if (QUERY_FLAG (tmp, FLAG_ALIVE)) + if (tmp->flag [FLAG_ALIVE]) { dam = hit_player (tmp, op->stats.dam, op, op->attacktype, 1); // TODO: can't understand the following if's if (op->destroyed () || !tmp->destroyed () || (op->stats.dam -= dam) < 0) { - if (!QUERY_FLAG (op, FLAG_REMOVED)) + if (!op->flag [FLAG_REMOVED]) { op->destroy (); return; @@ -547,14 +549,10 @@ void move_bullet (object *op) { - sint16 new_x, new_y; - int mflags; - maptile *m; - #if 0 /* We need a better general purpose way to do this */ - /* peterm: added to make comet leave a trail of burnouts + /* peterm: added to make comet leave a trail of burnouts it's an unadulterated hack, but the effect is cool. */ if (op->stats.sp == SP_METEOR) { @@ -575,18 +573,20 @@ return; } - new_x = op->x + DIRX (op); - new_y = op->y + DIRY (op); - m = op->map; - mflags = get_map_flags (m, &m, new_x, new_y, &new_x, &new_y); + mapxy pos (op); + pos.move (op->direction); - if (mflags & P_OUT_OF_MAP) + if (!pos.normalise ()) { op->destroy (); return; } - if (!op->direction || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, new_x, new_y))) + mapspace &ms = pos.ms (); + + ms.update (); + + if (!op->direction || OB_TYPE_MOVE_BLOCK (op, ms.move_block)) { if (op->other_arch) explode_bullet (op); @@ -596,7 +596,7 @@ return; } - if (!(op = m->insert (op, new_x, new_y, op))) + if (!(op = pos.insert (op, op))) return; if (reflwall (op->map, op->x, op->y, op)) @@ -643,14 +643,14 @@ tmp->dam_modifier = spob->stats.food + SP_level_dam_adjust (caster, spob); tmp->direction = dir; - if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE)) - SET_ANIMATION (tmp, dir); + if (tmp->flag [FLAG_IS_TURNABLE]) + tmp->set_anim_frame (dir); 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 + DIRX (dir); + tmp->y = op->y + DIRY (dir); tmp->map = op->map; maptile *newmap; @@ -663,9 +663,22 @@ 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)) + if (!tmp->flag [FLAG_REFLECTING]) { tmp->destroy (); return 0; @@ -690,10 +703,10 @@ *****************************************************************************/ /* drops an object based on what is in the cone's "other_arch" */ -void +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); @@ -719,7 +732,7 @@ } /* lava saves it's life, but not yours :) */ - if (QUERY_FLAG (op, FLAG_LIFESAVE)) + if (op->flag [FLAG_LIFESAVE]) { hit_map (op, 0, op->attacktype, 0); return; @@ -744,7 +757,7 @@ /* Check to see if we should push anything. * Spell objects with weight push whatever they encounter to some - * degree. + * degree. */ if (op->weight) { @@ -771,7 +784,7 @@ for (int i = -1; i <= 1; i++) { - sint16 x = op->x + freearr_x[absdir (op->stats.sp + i)], y = op->y + freearr_y[absdir (op->stats.sp + i)]; + sint16 x = op->x + DIRX (absdir (op->stats.sp + i)), y = op->y + DIRY (absdir (op->stats.sp + i)); if (ok_to_put_more (op->map, x, y, op, op->attacktype)) { @@ -810,9 +823,9 @@ if (!spell->other_arch) return 0; - if (op->type == PLAYER && QUERY_FLAG (op, FLAG_UNDEAD) && op->attacktype & AT_TURN_UNDEAD) + if (op->type == PLAYER && op->flag [FLAG_UNDEAD] && op->attacktype & AT_TURN_UNDEAD) { - new_draw_info (NDI_UNIQUE, 0, op, "Your undead nature prevents you from turning undead!"); + op->failmsg ("Your undead nature prevents you from turning undead!"); return 0; } @@ -854,8 +867,8 @@ continue; } - x = op->x + freearr_x[d]; - y = op->y + freearr_y[d]; + x = op->x + DIRX (d); + y = op->y + DIRY (d); if (get_map_flags (op->map, &m, x, y, &sx, &sy) & P_OUT_OF_MAP) continue; @@ -864,7 +877,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); @@ -942,7 +955,7 @@ void animate_bomb (object *op) { - if (op->state != NUM_ANIMATIONS (op) - 1) + if (op->state != op->anim_frames () - 1) return; object *env = op->outer_env (); @@ -973,10 +986,10 @@ { for (int i = 1; i < 9; i++) { - if (out_of_map (op->map, op->x + freearr_x[i], op->y + freearr_x[i])) + if (out_of_map (op->map, op->x + DIRX (i), op->y + DIRX (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; @@ -986,10 +999,10 @@ if (op->skill && op->skill != tmp->skill) tmp->skill = op->skill; - if (QUERY_FLAG (tmp, FLAG_IS_TURNABLE)) - SET_ANIMATION (tmp, i); + if (tmp->flag [FLAG_IS_TURNABLE]) + tmp->set_anim_frame (1); - op->map->insert (tmp, op->x + freearr_x[i], op->y + freearr_x[i], op); + op->map->insert (tmp, op->x + DIRX (i), op->y + DIRX (i), op); move_bullet (tmp); } } @@ -1002,7 +1015,7 @@ { object *tmp; int mflags; - sint16 dx = op->x + freearr_x[dir], dy = op->y + freearr_y[dir]; + sint16 dx = op->x + DIRX (dir), dy = op->y + DIRY (dir); maptile *m; mflags = get_map_flags (op->map, &m, dx, dy, &dx, &dy); @@ -1015,12 +1028,12 @@ { if ((mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, dx, dy) & MOVE_WALK)) { - new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); + op->failmsg ("There is something in the way."); return 0; } } - 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); @@ -1050,7 +1063,7 @@ * type is the type of spell - either SPELL_MANA or SPELL_GRACE. * this info is used for blocked magic/unholy spaces. */ -object * +static object * get_pointed_target (object *op, int dir, int range, int type) { object *target; @@ -1063,8 +1076,8 @@ for (dist = 1; dist < range; dist++) { - x = op->x + freearr_x[dir] * dist; - y = op->y + freearr_y[dir] * dist; + x = op->x + DIRX (dir) * dist; + y = op->y + DIRY (dir) * dist; mp = op->map; mflags = get_map_flags (op->map, &mp, x, y, &x, &y); @@ -1079,15 +1092,15 @@ if (mflags & P_IS_ALIVE) for (target = GET_MAP_OB (mp, x, y); target; target = target->above) - if (QUERY_FLAG (target, FLAG_MONSTER)) + if (target->flag [FLAG_MONSTER]) return target; } return NULL; } -/* cast_smite_arch() - the priest points to a creature and causes - * a 'godly curse' to decend. +/* cast_smite_spell() - the priest points to a creature and causes + * a 'godly curse' to decend. * usual params - * op = player * caster = object casting the spell. @@ -1099,12 +1112,10 @@ { object *effect, *target; object *god = find_god (determine_god (op)); - int range; - range = spell->range + SP_level_range_adjust (caster, spell); target = get_pointed_target (op, dir, 50, spell->stats.grace ? SPELL_GRACE : SPELL_MANA); - /* Bunch of conditions for casting this spell. Note that only + /* Bunch of conditions for casting this spell. Note that only * require a god if this is a cleric spell (requires grace). * This makes this spell much more general purpose - it can be used * by wizards also, which is good, because I think this is a very @@ -1119,12 +1130,12 @@ || (god && target->title == god->name) || (god && target->race.contains (god->race))) { - new_draw_info (NDI_UNIQUE, 0, op, "Your request is unheeded."); + op->failmsg ("Your request is unheeded."); return 0; } if (spell->other_arch) - effect = arch_to_object (spell->other_arch); + effect = spell->other_arch->instance (); else return 0; @@ -1137,7 +1148,7 @@ new_draw_info_format (NDI_UNIQUE, 0, op, "%s answers your call!", (const char *)determine_god (op)); else { - new_draw_info (NDI_UNIQUE, 0, op, "Your request is ignored."); + op->failmsg ("Your request is ignored."); return 0; } } @@ -1151,7 +1162,7 @@ effect->level = spell->stats.dam + SP_level_dam_adjust (caster, spell); /* casting death spells at undead isn't a good thing */ - if (QUERY_FLAG (target, FLAG_UNDEAD)) + if (target->flag [FLAG_UNDEAD]) { if (random_roll (0, 2, op, PREFER_LOW)) { @@ -1231,7 +1242,7 @@ if (i > 0 && i != op->direction) { op->direction = i; - SET_ANIMATION (op, op->direction); + op->set_anim_frame (op->direction); } pos.insert (op, op); @@ -1242,22 +1253,22 @@ ****************************************************************************/ /* make_object_glow() - currently only makes living objects glow. - * we do this by creating a force and inserting it in the + * we do this by creating a force and inserting it in the * object. if time is 0, the object glows permanently. To truely - * make this work for non-living objects, we would have to + * make this work for non-living objects, we would have to * give them the capability to have an inventory. b.t. */ -int +static int make_object_glow (object *op, int radius, int time) { /* some things are unaffected... */ if (op->path_denied & PATH_LIGHT) return 0; - object *tmp = get_archetype (FORCE_NAME); - tmp->speed = 0.01; + object *tmp = archetype::get (FORCE_NAME); + tmp->set_speed (0.01); tmp->stats.food = time; - SET_FLAG (tmp, FLAG_IS_USED_UP); + tmp->set_flag (FLAG_IS_USED_UP); tmp->set_glow_radius (min (MAX_LIGHT_RADIUS, radius)); tmp = insert_ob_in_ob (tmp, op); @@ -1276,50 +1287,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; } @@ -1328,7 +1329,6 @@ * CURSE * ***************************************************************************/ - int cast_curse (object *op, object *caster, object *spell_ob, int dir) { @@ -1338,7 +1338,7 @@ tmp = get_pointed_target (op, (dir == 0) ? op->direction : dir, spell_ob->range, SPELL_GRACE); if (!tmp) { - new_draw_info (NDI_UNIQUE, 0, op, "There is no one in that direction to curse."); + op->failmsg ("There is no one in that direction to curse."); return 0; } @@ -1363,7 +1363,7 @@ if (!force) { - force = get_archetype (FORCE_NAME); + force = archetype::get (FORCE_NAME); force->subtype = FORCE_CHANGE_ABILITY; if (spell_ob->race) @@ -1391,9 +1391,9 @@ } force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50; - force->speed = 1.f; force->speed_left = -1.f; - SET_FLAG (force, FLAG_APPLIED); + force->set_speed (1.f); + force->set_flag (FLAG_APPLIED); if (god) { @@ -1416,8 +1416,8 @@ change_abil (tmp, force); /* Mostly to display any messages */ insert_ob_in_ob (force, tmp); tmp->update_stats (); - return 1; + return 1; } /********************************************************************** @@ -1456,12 +1456,13 @@ 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); /* If there is nothing living on this space, no need to go further */ - if (!ms.flags () & P_IS_ALIVE) + if (!(ms.flags () & P_IS_ALIVE)) continue; // players can only affect spaces that they can actually see @@ -1485,7 +1486,7 @@ if (race && head->race && !strstr (race, head->race)) continue; - if (QUERY_FLAG (head, FLAG_UNDEAD) && !QUERY_FLAG (spell, FLAG_UNDEAD)) + if (head->flag [FLAG_UNDEAD] && !spell->flag [FLAG_UNDEAD]) continue; /* Now do a bunch of stuff related to saving throws */ @@ -1528,7 +1529,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; } @@ -1537,38 +1538,38 @@ done_one = 0; /* aggravation */ - if (QUERY_FLAG (spell, FLAG_MONSTER)) + if (spell->flag [FLAG_MONSTER]) { - CLEAR_FLAG (head, FLAG_SLEEP); + head->clr_flag (FLAG_SLEEP); remove_friendly_object (head); done_one = 1; head->enemy = op; } /* calm monsters */ - if (QUERY_FLAG (spell, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (head, FLAG_UNAGGRESSIVE)) + if (spell->flag [FLAG_UNAGGRESSIVE] && !head->flag [FLAG_UNAGGRESSIVE]) { - SET_FLAG (head, FLAG_UNAGGRESSIVE); + head->set_flag (FLAG_UNAGGRESSIVE); head->enemy = NULL; done_one = 1; } /* berserk monsters */ - if (QUERY_FLAG (spell, FLAG_BERSERK) && !QUERY_FLAG (head, FLAG_BERSERK)) + if (spell->flag [FLAG_BERSERK] && !head->flag [FLAG_BERSERK]) { - SET_FLAG (head, FLAG_BERSERK); + head->set_flag (FLAG_BERSERK); done_one = 1; } /* charm */ - if (QUERY_FLAG (spell, FLAG_NO_ATTACK) && !QUERY_FLAG (head, FLAG_FRIENDLY)) + if (spell->flag [FLAG_NO_ATTACK] && !head->flag [FLAG_FRIENDLY]) { 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); + head->clr_flag (FLAG_GENERATOR); head->set_owner (op); set_spell_skill (op, caster, spell, head); add_friendly_object (head); @@ -1580,7 +1581,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; @@ -1623,8 +1624,8 @@ int offset = ((i ^ j) & 1) ? (i / 2) : -(i / 2); int tmpdir = absdir (op->direction + offset); - nx = op->x + freearr_x[tmpdir]; - ny = op->y + freearr_y[tmpdir]; + nx = op->x + DIRX (tmpdir); + ny = op->y + DIRY (tmpdir); if (!(get_map_flags (op->map, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) && !(OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, nx, ny)))) { dir = tmpdir; @@ -1641,7 +1642,7 @@ m->insert (op, nx, ny, op); - dam_save = op->stats.dam; /* save the original dam: we do halfdam on + dam_save = op->stats.dam; /* save the original dam: we do halfdam on surrounding squares */ /* loop over current square and neighbors to hit. @@ -1650,8 +1651,8 @@ */ for (j = 0; j < 9; j++) { - hx = nx + freearr_x[j]; - hy = ny + freearr_y[j]; + hx = nx + DIRX (j); + hy = ny + DIRY (j); m = op->map; mflags = get_map_flags (m, &m, hx, hy, &hx, &hy); @@ -1673,7 +1674,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 */ @@ -1684,7 +1685,7 @@ if (i >= 0) { /* we have a preferred direction! */ /* pick another direction if the preferred dir is blocked. */ - if (get_map_flags (op->map, &m, nx + freearr_x[i], ny + freearr_y[i], &hx, &hy) & P_OUT_OF_MAP || + if (get_map_flags (op->map, &m, nx + DIRX (i), ny + DIRY (i), &hx, &hy) & P_OUT_OF_MAP || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, hx, hy))) i = absdir (i + rndm (0, 2) - 1); /* -1, 0, +1 */ @@ -1692,12 +1693,12 @@ } } -/* 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 * is a special type of object that casts swarms of other types * of spells. Which spell it casts is flexible. It fires the spells - * from a set of squares surrounding the caster, in a given direction. + * from a set of squares surrounding the caster, in a given direction. */ void move_swarm_spell (object *op) @@ -1743,7 +1744,7 @@ // (schmorp) /* new offset calculation to make swarm element distribution - * more uniform + * more uniform */ if (op->duration) { @@ -1761,14 +1762,14 @@ adjustdir = 0; /* fire the last one from forward. */ } - target_x = op->x + freearr_x[absdir (basedir + adjustdir)]; - target_y = op->y + freearr_y[absdir (basedir + adjustdir)]; + target_x = op->x + DIRX (absdir (basedir + adjustdir)); + target_y = op->y + DIRY (absdir (basedir + adjustdir)); /* back up one space so we can hit point-blank targets, but this - * necessitates extra out_of_map check below + * necessitates extra out_of_map check below */ - origin_x = target_x - freearr_x[basedir]; - origin_y = target_y - freearr_y[basedir]; + origin_x = target_x - DIRX (basedir); + origin_y = target_y - DIRY (basedir); /* spell pointer is set up for the spell this casts. Since this @@ -1809,7 +1810,7 @@ /* fire_swarm: * The following routine creates a swarm of objects. It actually * sets up a specific swarm object, which then fires off all - * the parts of the swarm. + * the parts of the swarm. * * op: the owner * caster: the caster (owner, wand, rod, scroll) @@ -1864,22 +1865,22 @@ if (dir) { - x = op->x + freearr_x[dir]; - y = op->y + freearr_y[dir]; + x = op->x + DIRX (dir); + y = op->y + DIRY (dir); m = op->map; mflags = get_map_flags (m, &m, x, y, &x, &y); if (mflags & P_OUT_OF_MAP) { - new_draw_info (NDI_UNIQUE, 0, op, "Nothing is there."); + op->failmsg ("Nothing is there."); return 0; } if (mflags & P_IS_ALIVE && spell->attacktype) { for (target = GET_MAP_OB (m, x, y); target; target = target->above) - if (QUERY_FLAG (target, FLAG_MONSTER)) + if (target->flag [FLAG_MONSTER]) { /* oky doky. got a target monster. Lets make a blinding attack */ if (target->head) @@ -1893,13 +1894,13 @@ /* no live target, perhaps a wall is in the way? */ if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y))) { - new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); + op->failmsg ("Something is in the way."); return 0; } } /* 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"); @@ -1916,13 +1917,13 @@ if (dir) m->insert (tmp, x, y, op); else - caster->outer_env ()->insert (tmp); + caster->outer_env_or_self ()->insert (tmp); return 1; } /* cast_cause_disease: this spell looks along from the - * player and infects someone. + * 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? @@ -1938,7 +1939,7 @@ x = op->x; y = op->y; - /* If casting from a scroll, no direction will be available, so refer to the + /* If casting from a scroll, no direction will be available, so refer to the * direction the player is pointing. */ if (!dir) @@ -1955,8 +1956,8 @@ /* search in a line for a victim */ for (i = 1; i < range; i++) { - x = op->x + i * freearr_x[dir]; - y = op->y + i * freearr_y[dir]; + x = op->x + i * DIRX (dir); + y = op->y + i * DIRY (dir); m = op->map; mflags = get_map_flags (m, &m, x, y, &x, &y); @@ -1973,9 +1974,9 @@ { /* search this square for a victim */ for (walk = GET_MAP_OB (m, x, y); walk; walk = walk->above) - if (QUERY_FLAG (walk, FLAG_MONSTER) || (walk->type == PLAYER)) + if (walk->flag [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); @@ -1983,59 +1984,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 += copysignl (disease->stats.dam , dam_mod); + if (disease->stats.maxsp) disease->stats.maxsp += copysignl (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 (archetype::get (shstr_detect_magic), x, y, op); return 1; }