ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
(Generate patch)

Comparing deliantra/server/server/spell_effect.C (file contents):
Revision 1.73 by root, Sat Sep 1 08:03:46 2007 UTC vs.
Revision 1.148 by root, Sat Nov 17 23:40:04 2018 UTC

1/* 1/*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team 4 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
5 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 6 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 7 * Copyright (©) 1992 Frank Tore Johansen
7 * 8 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify 9 * Deliantra is free software: you can redistribute it and/or modify it under
9 * it under the terms of the GNU General Public License as published by 10 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 11 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 12 * option) any later version.
12 * 13 *
13 * This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 17 * GNU General Public License for more details.
17 * 18 *
18 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 * and the GNU General Public License along with this program. If not, see
21 * <http://www.gnu.org/licenses/>.
20 * 22 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de> 23 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 24 */
23 25
24#include <global.h> 26#include <global.h>
25#include <object.h> 27#include <object.h>
26#include <living.h> 28#include <living.h>
57} 59}
58 60
59int 61int
60recharge (object *op, object *caster, object *spell_ob) 62recharge (object *op, object *caster, object *spell_ob)
61{ 63{
62 object *wand, *tmp;
63 int ncharges; 64 int ncharges;
64 65
65 wand = find_marked_object (op); 66 object *wand = op->mark ();
67
66 if (wand == NULL || wand->type != WAND) 68 if (!wand || wand->type != WAND)
67 { 69 {
68 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark the wand you want to recharge."); 70 op->failmsg ("You need to mark the wand you want to recharge.");
69 return 0; 71 return 0;
70 } 72 }
73
71 if (!(random_roll (0, 3, op, PREFER_HIGH))) 74 if (!(random_roll (0, 3, op, PREFER_HIGH)))
72 { 75 {
73 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s vibrates violently, then explodes!", query_name (wand)); 76 op->failmsgf ("The %s vibrates violently, then explodes!", query_name (wand));
74 op->play_sound (sound_find ("ob_explode")); 77 op->play_sound (sound_find ("ob_explode"));
75 esrv_del_item (op->contr, wand->count);
76 wand->destroy (); 78 wand->destroy ();
77 tmp = get_archetype ("fireball"); 79 object *tmp = archetype::get (shstr_fireball);
78 tmp->stats.dam = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob)) / 10; 80 tmp->stats.dam = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob)) / 10;
79 81
80 if (!tmp->stats.dam) 82 if (!tmp->stats.dam)
81 tmp->stats.dam = 1; 83 tmp->stats.dam = 1;
82 84
93 95
94 if (wand->inv && wand->inv->level) 96 if (wand->inv && wand->inv->level)
95 ncharges /= wand->inv->level; 97 ncharges /= wand->inv->level;
96 else 98 else
97 { 99 {
98 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is broken.", query_name (wand)); 100 op->failmsgf ("Your %s is broken.", query_name (wand));
99 return 0; 101 return 0;
100 } 102 }
101 103
102 if (!ncharges) 104 if (!ncharges)
103 ncharges = 1; 105 ncharges = 1;
104 106
105 wand->stats.food += ncharges; 107 wand->stats.food += ncharges;
106 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s glows with power.", query_name (wand)); 108 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s glows with power.", query_name (wand));
107 109
108 if (wand->arch && QUERY_FLAG (wand->arch, FLAG_ANIMATE)) 110 if (wand->arch && wand->arch->flag [FLAG_ANIMATE])
109 { 111 {
110 SET_FLAG (wand, FLAG_ANIMATE); 112 wand->set_flag (FLAG_ANIMATE);
111 wand->set_speed (wand->arch->speed); 113 wand->set_speed (wand->arch->speed);
112 } 114 }
113 115
114 return 1; 116 return 1;
115} 117}
123 * The # of arrows created also goes up with level, so if a 30th level mage 125 * The # of arrows created also goes up with level, so if a 30th level mage
124 * wants LOTS of arrows, and doesn't care what the plus is he could 126 * wants LOTS of arrows, and doesn't care what the plus is he could
125 * create nonnmagic arrows, or even -1, etc... 127 * create nonnmagic arrows, or even -1, etc...
126 */ 128 */
127int 129int
128cast_create_missile (object *op, object *caster, object *spell, int dir, const char *stringarg) 130cast_create_missile (object *op, object *caster, object *spell, int dir, const char *spellparam)
129{ 131{
130 int missile_plus = 0, bonus_plus = 0; 132 int bonus_plus = 0;
131 const char *missile_name; 133 const char *missile_name = "arrow";
132 object *tmp, *missile;
133 134
134 missile_name = "arrow";
135
136 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 135 for (object *tmp = op->inv; tmp; tmp = tmp->below)
137 if (tmp->type == BOW && QUERY_FLAG (tmp, FLAG_APPLIED)) 136 if (tmp->type == BOW && tmp->flag [FLAG_APPLIED])
138 missile_name = tmp->race; 137 missile_name = tmp->race;
139 138
140 missile_plus = spell->stats.dam + SP_level_dam_adjust (caster, spell); 139 int missile_plus = spell->stats.dam + SP_level_dam_adjust (caster, spell);
141 140
142 if (archetype::find (missile_name) == NULL) 141 archetype *missile_arch = archetype::find (missile_name);
142
143 if (!missile_arch)
143 { 144 {
144 LOG (llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name); 145 LOG (llevDebug, "Cast create_missile: could not find archetype %s\n", missile_name);
145 return 0; 146 return 0;
146 } 147 }
147 148
148 missile = get_archetype (missile_name); 149 object *missile = missile_arch->instance ();
149 150
150 if (stringarg) 151 if (spellparam)
151 { 152 {
152 /* If it starts with a letter, presume it is a description */ 153 /* If it starts with a letter, presume it is a description */
153 if (isalpha (*stringarg)) 154 if (isalpha (*spellparam))
154 { 155 {
155 artifact *al = find_artifactlist (missile->type)->items; 156 artifact *al = find_artifactlist (missile->type)->items;
156 157
157 for (; al; al = al->next) 158 for (; al; al = al->next)
158 if (!strcasecmp (al->item->name, stringarg)) 159 if (!strcasecmp (al->item->name, spellparam))
159 break; 160 break;
160 161
161 if (!al) 162 if (!al)
162 { 163 {
163 missile->destroy (); 164 missile->destroy ();
164 new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, stringarg); 165 op->failmsgf ("No such object %ss of %s", missile_name, spellparam);
165 return 0; 166 return 0;
166 } 167 }
167 168
168 if (al->item->slaying) 169 if (al->item->slaying)
169 { 170 {
170 missile->destroy (); 171 missile->destroy ();
171 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, stringarg); 172 op->failmsgf ("You are not allowed to create %ss of %s", missile_name, spellparam);
172 return 0; 173 return 0;
173 } 174 }
174 175
175 give_artifact_abilities (missile, al->item); 176 give_artifact_abilities (missile, al->item);
176 /* These special arrows cost something extra. Don't have them also be magical - 177 /* These special arrows cost something extra. Don't have them also be magical -
177 * otherwise, in most cases, not enough will be created. I don't want to get into 178 * otherwise, in most cases, not enough will be created. I don't want to get into
178 * the parsing of having to do both plus and type. 179 * the parsing of having to do both plus and type.
179 */ 180 */
180 bonus_plus = 1 + (al->item->value / 5); 181 bonus_plus = 1 + (al->item->value / 5);
181 missile_plus = 0; 182 missile_plus = 0;
182 } 183 }
183 else if (atoi (stringarg) < missile_plus) 184 else if (atoi (spellparam) < missile_plus)
184 missile_plus = atoi (stringarg); 185 missile_plus = atoi (spellparam);
185 } 186 }
186 187
187 if (missile_plus > 4) 188 missile_plus = clamp (missile_plus, -4, 4);
188 missile_plus = 4;
189 else if (missile_plus < -4)
190 missile_plus = -4;
191 189
192 missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell); 190 missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell);
193 missile->nrof -= 3 * (missile_plus + bonus_plus); 191 missile->nrof -= 3 * (missile_plus + bonus_plus);
194 192
195 if (missile->nrof < 1) 193 if (missile->nrof < 1)
197 195
198 missile->magic = missile_plus; 196 missile->magic = missile_plus;
199 /* Can't get any money for these objects */ 197 /* Can't get any money for these objects */
200 missile->value = 0; 198 missile->value = 0;
201 199
202 SET_FLAG (missile, FLAG_IDENTIFIED); 200 missile->set_flag (FLAG_IDENTIFIED);
203 201
204 if (!cast_create_obj (op, caster, missile, dir) && op->type == PLAYER && !missile->destroyed ()) 202 cast_create_obj (op, caster, missile, dir);
203
204 if (!dir
205 && op->type == PLAYER
206 && !missile->destroyed ())
205 pick_up (op, missile); 207 pick_up (op, missile);
206 208
207 return 1; 209 return 1;
208} 210}
209 211
210
211/* allows the choice of what sort of food object to make. 212/* allows the choice of what sort of food object to make.
212 * If stringarg is NULL, it will create food dependent on level --PeterM*/ 213 * If spellparam is NULL, it will create food dependent on level --PeterM*/
213int 214int
214cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *stringarg) 215cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *spellparam)
215{ 216{
216 int food_value; 217 int food_value;
217 archetype *at = NULL; 218 archetype *at = NULL;
218 object *new_op; 219 object *new_op;
219 220
220 food_value = spell_ob->stats.food + +50 * SP_level_duration_adjust (caster, spell_ob); 221 food_value = spell_ob->stats.food + 50 * SP_level_duration_adjust (caster, spell_ob);
221 222
222 if (stringarg) 223 if (spellparam)
223 { 224 {
224 at = find_archetype_by_object_type_name (FOOD, stringarg); 225 at = find_archetype_by_object_type_name (FOOD, spellparam);
225 if (at == NULL) 226 if (at == NULL)
226 at = find_archetype_by_object_type_name (DRINK, stringarg); 227 at = find_archetype_by_object_type_name (DRINK, spellparam);
227 if (at == NULL || at->stats.food > food_value) 228 if (at == NULL || at->stats.food > food_value)
228 stringarg = NULL; 229 spellparam = NULL;
229 } 230 }
230 231
231 if (!stringarg) 232 if (!spellparam)
232 { 233 {
233 archetype *at_tmp; 234 archetype *at_tmp;
234 235
235 /* We try to find the archetype with the maximum food value. 236 /* We try to find the archetype with the maximum food value.
236 * This removes the dependancy of hard coded food values in this 237 * This removes the dependancy of hard coded food values in this
261 /* Pretty unlikely (there are some very low food items), but you never 262 /* Pretty unlikely (there are some very low food items), but you never
262 * know 263 * know
263 */ 264 */
264 if (!at) 265 if (!at)
265 { 266 {
266 new_draw_info (NDI_UNIQUE, 0, op, "You don't have enough experience to create any food."); 267 op->failmsgf ("You don't have enough experience to create any food.");
267 return 0; 268 return 0;
268 } 269 }
269 270
270 food_value /= at->stats.food; 271 food_value /= at->stats.food;
271 new_op = arch_to_object (at); 272 new_op = at->instance ();
272 new_op->nrof = food_value; 273 new_op->nrof = food_value;
273 274
274 new_op->value = 0; 275 new_op->value = 0;
275 if (new_op->nrof < 1) 276 if (new_op->nrof < 1)
276 new_op->nrof = 1; 277 new_op->nrof = 1;
284{ 285{
285 int r, mflags, maxrange; 286 int r, mflags, maxrange;
286 object *tmp; 287 object *tmp;
287 maptile *m; 288 maptile *m;
288 289
289
290 if (!dir) 290 if (!dir)
291 { 291 {
292 examine_monster (op, op); 292 examine_monster (op, op);
293 return 1; 293 return 1;
294 } 294 }
295 295
296 maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob); 296 maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
297 for (r = 1; r < maxrange; r++) 297 for (r = 1; r < maxrange; r++)
298 { 298 {
299 sint16 x = op->x + r * freearr_x[dir], y = op->y + r * freearr_y[dir]; 299 sint16 x = op->x + r * DIRX (dir), y = op->y + r * DIRY (dir);
300 300
301 m = op->map; 301 m = op->map;
302 mflags = get_map_flags (m, &m, x, y, &x, &y); 302 mflags = get_map_flags (m, &m, x, y, &x, &y);
303 303
304 if (mflags & P_OUT_OF_MAP) 304 if (mflags & P_OUT_OF_MAP)
305 break; 305 break;
306 306
307 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (mflags & P_NO_MAGIC)) 307 if (!op->flag [FLAG_WIZCAST] && (mflags & P_NO_MAGIC))
308 { 308 {
309 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks your magic."); 309 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks your magic.");
310 return 0; 310 return 0;
311 } 311 }
312
312 if (mflags & P_IS_ALIVE) 313 if (mflags & P_IS_ALIVE)
313 { 314 {
314 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) 315 for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above)
315 if (QUERY_FLAG (tmp, FLAG_ALIVE) && (tmp->type == PLAYER || QUERY_FLAG (tmp, FLAG_MONSTER))) 316 if (tmp->flag [FLAG_ALIVE] && (tmp->type == PLAYER || tmp->flag [FLAG_MONSTER]))
316 { 317 {
317 new_draw_info (NDI_UNIQUE, 0, op, "You detect something."); 318 new_draw_info (NDI_UNIQUE, 0, op, "You detect something.");
318 if (tmp->head != NULL) 319 if (tmp->head != NULL)
319 tmp = tmp->head; 320 tmp = tmp->head;
320 examine_monster (op, tmp); 321 examine_monster (op, tmp);
343 if (pl->type == PLAYER) 344 if (pl->type == PLAYER)
344 { 345 {
345 /* If race isn't set, then invisible unless it is undead */ 346 /* If race isn't set, then invisible unless it is undead */
346 if (!pl->contr->invis_race) 347 if (!pl->contr->invis_race)
347 { 348 {
348 if (QUERY_FLAG (mon, FLAG_UNDEAD)) 349 if (mon->flag [FLAG_UNDEAD])
349 return 0; 350 return 0;
350 351
351 return 1; 352 return 1;
352 } 353 }
353 354
354 /* invis_race is set if we get here */ 355 /* invis_race is set if we get here */
355 if (!strcmp (pl->contr->invis_race, "undead") && is_true_undead (mon)) 356 if (pl->contr->invis_race == shstr_undead && is_true_undead (mon))
356 return 1; 357 return 1;
357 358
358 /* No race, can't be invisible to it */ 359 /* No race, can't be invisible to it */
359 if (!mon->race) 360 if (!mon->race)
360 return 0; 361 return 0;
361 362
362 if (strstr (mon->race, pl->contr->invis_race)) 363 if (mon->race.contains (pl->contr->invis_race))
363 return 1; 364 return 1;
364 365
365 /* Nothing matched above, return 0 */ 366 /* Nothing matched above, return 0 */
366 return 0; 367 return 0;
367 } 368 }
384int 385int
385cast_invisible (object *op, object *caster, object *spell_ob) 386cast_invisible (object *op, object *caster, object *spell_ob)
386{ 387{
387 if (op->invisible > 1000) 388 if (op->invisible > 1000)
388 { 389 {
389 new_draw_info (NDI_UNIQUE, 0, op, "You can not extend the duration of your invisibility any further"); 390 op->failmsg ("You can not extend the duration of your invisibility any further");
390 return 0; 391 return 0;
391 } 392 }
392 393
393 /* Remove the switch with 90% duplicate code - just handle the differences with 394 /* Remove the switch with 90% duplicate code - just handle the differences with
394 * and if statement or two. 395 * and if statement or two.
395 */ 396 */
396 op->invisible += spell_ob->duration + SP_level_duration_adjust (caster, spell_ob); 397 op->invisible += spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
398
397 /* max duration */ 399 /* limit duration */
398 if (op->invisible > 1000) 400 min_it (op->invisible, 1000);
399 op->invisible = 1000;
400 401
401 if (op->type == PLAYER) 402 if (op->type == PLAYER)
402 { 403 {
403 op->contr->invis_race = spell_ob->race; 404 op->contr->invis_race = spell_ob->race;
404 405
405 if (QUERY_FLAG (spell_ob, FLAG_MAKE_INVIS)) 406 if (spell_ob->flag [FLAG_MAKE_INVIS])
406 op->contr->tmp_invis = 0; 407 op->contr->tmp_invis = 0;
407 else 408 else
408 op->contr->tmp_invis = 1; 409 op->contr->tmp_invis = 1;
409
410 op->contr->hidden = 0;
411 } 410 }
412 411
413 if (makes_invisible_to (op, op)) 412 if (makes_invisible_to (op, op))
414 new_draw_info (NDI_UNIQUE, 0, op, "You can't see your hands!"); 413 new_draw_info (NDI_UNIQUE, 0, op, "You can't see your hands!");
415 else 414 else
430/* earth to dust spell. Basically destroys earthwalls in the area. 429/* earth to dust spell. Basically destroys earthwalls in the area.
431 */ 430 */
432int 431int
433cast_earth_to_dust (object *op, object *caster, object *spell_ob) 432cast_earth_to_dust (object *op, object *caster, object *spell_ob)
434{ 433{
435 object *tmp, *next;
436 int range, i, j, mflags; 434 int range, i, j, mflags;
437 sint16 sx, sy; 435 sint16 sx, sy;
438 maptile *m; 436 maptile *m;
439
440 if (op->type != PLAYER)
441 return 0;
442 437
443 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob); 438 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
444 439
445 for (i = -range; i <= range; i++) 440 for (i = -range; i <= range; i++)
446 for (j = -range; j <= range; j++) 441 for (j = -range; j <= range; j++)
451 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); 446 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
452 447
453 if (mflags & P_OUT_OF_MAP) 448 if (mflags & P_OUT_OF_MAP)
454 continue; 449 continue;
455 450
456 // earth to dust tears down everything that can be teared down 451 // earth to dust tears down everything that can be torn down
457 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next) 452 for (object *next, *tmp = m->at (sx, sy).bot; tmp; tmp = next)
458 { 453 {
459 next = tmp->above; 454 next = tmp->above;
460 if (QUERY_FLAG (tmp, FLAG_TEAR_DOWN)) 455
456 if (tmp->flag [FLAG_TEAR_DOWN])
461 hit_player (tmp, 9998, op, AT_PHYSICAL, 0); 457 hit_player (tmp, 9998, op, AT_PHYSICAL, 0);
462 } 458 }
463 } 459 }
464 460
465 return 1; 461 return 1;
467 463
468void 464void
469execute_word_of_recall (object *op) 465execute_word_of_recall (object *op)
470{ 466{
471 if (object *pl = op->in_player ()) 467 if (object *pl = op->in_player ())
472 {
473 if (pl->ms ().flags () & P_NO_CLERIC && !QUERY_FLAG (pl, FLAG_WIZCAST)) 468 if (pl->ms ().flags () & P_NO_CLERIC && !pl->flag [FLAG_WIZCAST])
474 new_draw_info (NDI_UNIQUE, 0, pl, "You feel something fizzle inside you."); 469 new_draw_info (NDI_UNIQUE, 0, pl, "You feel something fizzle inside you.");
475 else 470 else
476 { 471 pl->player_goto (op->slaying, op->stats.hp, op->stats.sp);
477 // remove first so we do not call update_stats
478 op->remove ();
479 pl->enter_exit (op);
480 }
481 }
482 472
483 op->destroy (); 473 op->destroy ();
484} 474}
485 475
486/* Word of recall causes the player to return 'home'. 476/* Word of recall causes the player to return 'home'.
487 * we put a force into the player object, so that there is a 477 * we put a force into the player object, so that there is a
488 * time delay effect. 478 * time delay effect.
489 */ 479 */
490int 480int
491cast_word_of_recall (object *op, object *caster, object *spell_ob) 481cast_word_of_recall (object *op, object *caster, object *spell_ob)
492{ 482{
493 object *dummy; 483 if (!op->is_player ())
494 int time;
495
496 if (op->type != PLAYER)
497 return 0; 484 return 0;
498 485
499 if (find_obj_by_type_subtype (op, SPELL_EFFECT, SP_WORD_OF_RECALL)) 486 if (find_obj_by_type_subtype (op, SPELL_EFFECT, SP_WORD_OF_RECALL))
500 { 487 {
501 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you."); 488 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you.");
502 return 1; 489 return 1;
503 } 490 }
504 491
505 dummy = get_archetype (FORCE_NAME); 492 object *dummy = archetype::get (FORCE_NAME);
506 if (dummy == NULL)
507 {
508 new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
509 LOG (llevError, "cast_word_of_recall: get_archetype(force) failed!\n");
510 return 0;
511 }
512 493
513 time = spell_ob->duration - SP_level_duration_adjust (caster, spell_ob); 494 int time = max (1, spell_ob->duration - SP_level_duration_adjust (caster, spell_ob));
514 if (time < 1)
515 time = 1;
516 495
517 /* value of speed really doesn't make much difference, as long as it is 496 /* value of speed really doesn't make much difference, as long as it is
518 * positive. Lower value may be useful so that the problem doesn't 497 * positive. Lower value may be useful so that the problem doesn't
519 * do anything really odd if it say a -1000 or something. 498 * do anything really odd if it say a -1000 or something.
520 */ 499 */
521 dummy->set_speed (0.002); 500 dummy->set_speed (0.002);
522 dummy->speed_left = -dummy->speed * time; 501 dummy->speed_left = -dummy->speed * time;
523 dummy->type = SPELL_EFFECT; 502 dummy->type = SPELL_EFFECT;
524 dummy->subtype = SP_WORD_OF_RECALL; 503 dummy->subtype = SP_WORD_OF_RECALL;
525 504 dummy->slaying = op->contr->savebed_map;
526 /* If we could take advantage of enter_player_savebed() here, it would be 505 dummy->stats.hp = op->contr->bed_x;
527 * nice, but until the map load fails, we can't. 506 dummy->stats.sp = op->contr->bed_y;
528 */
529 EXIT_PATH (dummy) = op->contr->savebed_map;
530 EXIT_X (dummy) = op->contr->bed_x;
531 EXIT_Y (dummy) = op->contr->bed_y;
532 507
533 op->insert (dummy); 508 op->insert (dummy);
534 509
535 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you."); 510 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you.");
536 511
575 550
576int 551int
577perceive_self (object *op) 552perceive_self (object *op)
578{ 553{
579 const char *cp = describe_item (op, op); 554 const char *cp = describe_item (op, op);
580 archetype *at = archetype::find (ARCH_DEPLETION); 555 archetype *at = archetype::find (shstr_depletion);
581 556
582 dynbuf_text buf; 557 dynbuf_text &buf = msg_dynbuf; buf.clear ();
583 558
584 if (player *pl = op->contr) 559 if (!op->is_player ())
560 return 0;
561
585 if (object *race = archetype::find (op->race)) 562 if (object *race = archetype::find (op->race))
586 buf << "You are a " << (pl->gender ? "female" : "male") << " " << &race->name << ".\n"; 563 buf << " - You are a G<male|female> " << &race->name << ".\n";
587 564
588 if (object *god = find_god (determine_god (op))) 565 if (object *god = find_god (determine_god (op)))
589 buf << "You worship " << &god->name << ".\n"; 566 buf << " - You worship " << &god->name << ".\n";
590 else 567 else
591 buf << "You worship no god.\n"; 568 buf << " - You worship no god.\n";
592 569
593 object *tmp = present_arch_in_ob (at, op); 570 object *tmp = present_arch_in_ob (at, op);
594 571
595 if (*cp == '\0' && tmp == NULL) 572 if (*cp == '\0' && !tmp)
596 buf << "You feel very mundane. "; 573 buf << " - You feel very mundane. ";
597 else 574 else
598 { 575 {
599 buf << "You have: " << cp << ".\n"; 576 buf << " - You have: " << cp << ".\n";
600 577
601 if (tmp) 578 if (tmp)
602 for (int i = 0; i < NUM_STATS; i++) 579 for (int i = 0; i < NUM_STATS; i++)
603 if (tmp->stats.stat (i) < 0) 580 if (tmp->stats.stat (i) < 0)
604 buf.printf ("Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i)); 581 buf.printf (" - Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i));
605 } 582 }
606 583
607 if (is_dragon_pl (op)) 584 if (op->is_dragon ())
608 /* now grab the 'dragon_ability'-force from the player's inventory */ 585 /* now grab the 'dragon_ability'-force from the player's inventory */
609 for (tmp = op->inv; tmp; tmp = tmp->below) 586 for (tmp = op->inv; tmp; tmp = tmp->below)
610 { 587 {
611 if (tmp->type == FORCE && tmp->arch->archname == shstr_dragon_ability_force) 588 if (tmp->type == FORCE && tmp->arch->archname == shstr_dragon_ability_force)
612 { 589 {
613 if (tmp->stats.exp == 0) 590 if (tmp->stats.exp == 0)
614 buf << "Your metabolism isn't focused on anything.\n"; 591 buf << " - Your metabolism isn't focused on anything.\n";
615 else 592 else
616 buf << "Your metabolism is focused on " << change_resist_msg[tmp->stats.exp] << ".\n"; 593 buf << " - Your metabolism is focused on " << change_resist_msg[tmp->stats.exp] << ".\n";
617 594
618 break; 595 break;
619 } 596 }
620 } 597 }
621 598
622 buf << '\0'; // zero-terminate 599 op->contr->infobox (MSG_CHANNEL ("perceiveself"), buf);
623
624 new_draw_info (NDI_UNIQUE, 0, op, buf.linearise ());
625 600
626 return 1; 601 return 1;
627} 602}
628 603
629/* This creates magic walls. Really, it can create most any object, 604/* This creates magic walls. Really, it can create most any object,
645 x = op->x; 620 x = op->x;
646 y = op->y; 621 y = op->y;
647 } 622 }
648 else 623 else
649 { 624 {
650 x = op->x + freearr_x[dir]; 625 x = op->x + DIRX (dir);
651 y = op->y + freearr_y[dir]; 626 y = op->y + DIRY (dir);
652 } 627 }
653 628
654 m = op->map; 629 m = op->map;
655 630
656 if ((spell_ob->move_block || x != op->x || y != op->y) && 631 if ((spell_ob->move_block || x != op->x || y != op->y) &&
657 (get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE) || 632 (get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE) ||
658 ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) == spell_ob->move_block))) 633 ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) == spell_ob->move_block)))
659 { 634 {
660 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); 635 op->failmsg ("Something is in the way.");
661 return 0; 636 return 0;
662 } 637 }
663 638
664 if (spell_ob->other_arch) 639 if (spell_ob->other_arch)
665 tmp = arch_to_object (spell_ob->other_arch); 640 tmp = spell_ob->other_arch->instance ();
666 else if (spell_ob->race) 641 else if (spell_ob->race)
667 { 642 {
668 char buf1[MAX_BUF]; 643 char buf1[MAX_BUF];
669 644
670 sprintf (buf1, spell_ob->race, dir); 645 sprintf (buf1, spell_ob->race, dir);
674 LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1); 649 LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1);
675 new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken."); 650 new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken.");
676 return 0; 651 return 0;
677 } 652 }
678 653
679 tmp = arch_to_object (at); 654 tmp = at->instance ();
680 } 655 }
681 else 656 else
682 { 657 {
683 LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name); 658 LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name);
684 return 0; 659 return 0;
689 tmp->attacktype = spell_ob->attacktype; 664 tmp->attacktype = spell_ob->attacktype;
690 tmp->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob); 665 tmp->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
691 tmp->stats.dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob); 666 tmp->stats.dam = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
692 tmp->range = 0; 667 tmp->range = 0;
693 } 668 }
694 else if (QUERY_FLAG (tmp, FLAG_ALIVE)) 669 else if (tmp->flag [FLAG_ALIVE])
695 { 670 {
696 tmp->stats.hp = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob); 671 tmp->stats.hp = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
697 tmp->stats.maxhp = tmp->stats.hp; 672 tmp->stats.maxhp = tmp->stats.hp;
698 } 673 }
699 674
700 if (QUERY_FLAG (spell_ob, FLAG_IS_USED_UP) || QUERY_FLAG (tmp, FLAG_IS_USED_UP)) 675 if (spell_ob->flag [FLAG_IS_USED_UP] || tmp->flag [FLAG_IS_USED_UP])
701 { 676 {
702 tmp->stats.food = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob); 677 tmp->stats.food = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob);
703 SET_FLAG (tmp, FLAG_IS_USED_UP); 678 tmp->set_flag (FLAG_IS_USED_UP);
704 } 679 }
705 680
706 if (QUERY_FLAG (spell_ob, FLAG_TEAR_DOWN)) 681 if (spell_ob->flag [FLAG_TEAR_DOWN])
707 { 682 {
708 tmp->stats.hp = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob); 683 tmp->stats.hp = spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
709 tmp->stats.maxhp = tmp->stats.hp; 684 tmp->stats.maxhp = tmp->stats.hp;
710 SET_FLAG (tmp, FLAG_TEAR_DOWN); 685 tmp->set_flag (FLAG_TEAR_DOWN);
711 SET_FLAG (tmp, FLAG_ALIVE); 686 tmp->set_flag (FLAG_ALIVE);
712 } 687 }
713 688
714 /* This can't really hurt - if the object doesn't kill anything, 689 /* This can't really hurt - if the object doesn't kill anything,
715 * these fields just won't be used. Do not set the owner for 690 * these fields just won't be used. Do not set the owner for
716 * earthwalls, though, so they survive restarts. 691 * earthwalls, though, so they survive restarts.
717 */ 692 */
718 if (tmp->type != EARTHWALL) //TODO 693 if (tmp->type != EARTHWALL) //TODO
719 tmp->set_owner (op); 694 tmp->set_owner (op);
720 695
721 set_spell_skill (op, caster, spell_ob, tmp); 696 set_spell_skill (op, caster, spell_ob, tmp);
722 tmp->level = caster_level (caster, spell_ob) / 2; 697 tmp->level = casting_level (caster, spell_ob) / 2;
723 698
724 name = tmp->name; 699 name = tmp->name;
725 if (!(tmp = m->insert (tmp, x, y, op))) 700 if (!(tmp = m->insert (tmp, x, y, op)))
726 { 701 {
727 new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name); 702 new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name);
728 return 0; 703 return 0;
729 } 704 }
730 705
731 /* If this is a spellcasting wall, need to insert the spell object */ 706 /* If this is a spellcasting wall, need to insert the spell object */
732 if (tmp->other_arch && tmp->other_arch->type == SPELL) 707 if (tmp->other_arch && tmp->other_arch->type == SPELL)
733 insert_ob_in_ob (arch_to_object (tmp->other_arch), tmp); 708 insert_ob_in_ob (tmp->other_arch->instance (), tmp);
734 709
735 /* This code causes the wall to extend some distance in 710 /* This code causes the wall to extend some distance in
736 * each direction, or until an obstruction is encountered. 711 * each direction, or until an obstruction is encountered.
737 * posblocked and negblocked help determine how far the 712 * posblocked and negblocked help determine how far the
738 * created wall can extend, it won't go extend through 713 * created wall can extend, it won't go extend through
739 * blocked spaces. 714 * blocked spaces.
740 */ 715 */
741 maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob); 716 maxrange = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
746 { 721 {
747 int dir2; 722 int dir2;
748 723
749 dir2 = (dir < 4) ? (dir + 2) : dir - 2; 724 dir2 = (dir < 4) ? (dir + 2) : dir - 2;
750 725
751 x = tmp->x + i * freearr_x[dir2]; 726 x = tmp->x + i * DIRX (dir2);
752 y = tmp->y + i * freearr_y[dir2]; 727 y = tmp->y + i * DIRY (dir2);
753 m = tmp->map; 728 m = tmp->map;
754 729
755 if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) && 730 if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
756 ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !posblocked) 731 ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !posblocked)
757 { 732 {
758 object *tmp2 = tmp->clone (); 733 object *tmp2 = tmp->clone ();
759 m->insert (tmp2, x, y, op); 734 m->insert (tmp2, x, y, op);
760 735
761 /* If this is a spellcasting wall, need to insert the spell object */ 736 /* If this is a spellcasting wall, need to insert the spell object */
762 if (tmp2->other_arch && tmp2->other_arch->type == SPELL) 737 if (tmp2->other_arch && tmp2->other_arch->type == SPELL)
763 tmp2->insert (arch_to_object (tmp2->other_arch)); 738 tmp2->insert (tmp2->other_arch->instance ());
764 739
765 } 740 }
766 else 741 else
767 posblocked = 1; 742 posblocked = 1;
768 743
769 x = tmp->x - i * freearr_x[dir2]; 744 x = tmp->x - i * DIRX (dir2);
770 y = tmp->y - i * freearr_y[dir2]; 745 y = tmp->y - i * DIRY (dir2);
771 m = tmp->map; 746 m = tmp->map;
772 747
773 if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) && 748 if (!(get_map_flags (m, &m, x, y, &x, &y) & (P_OUT_OF_MAP | P_IS_ALIVE)) &&
774 ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !negblocked) 749 ((spell_ob->move_block & GET_MAP_MOVE_BLOCK (m, x, y)) != spell_ob->move_block) && !negblocked)
775 { 750 {
776 object *tmp2 = tmp->clone (); 751 object *tmp2 = tmp->clone ();
777 m->insert (tmp2, x, y, op); 752 m->insert (tmp2, x, y, op);
778 753
779 if (tmp2->other_arch && tmp2->other_arch->type == SPELL) 754 if (tmp2->other_arch && tmp2->other_arch->type == SPELL)
780 tmp2->insert (arch_to_object (tmp2->other_arch)); 755 tmp2->insert (tmp2->other_arch->instance ());
781 } 756 }
782 else 757 else
783 negblocked = 1; 758 negblocked = 1;
784 } 759 }
785 760
786 if (QUERY_FLAG (tmp, FLAG_BLOCKSVIEW)) 761 if (tmp->flag [FLAG_BLOCKSVIEW])
787 update_all_los (op->map, op->x, op->y); 762 update_all_los (op->map, op->x, op->y);
788 763
789 return 1; 764 return 1;
790} 765}
791 766
792int 767int
793dimension_door (object *op, object *caster, object *spob, int dir) 768dimension_door (object *op, object *caster, object *spob, int dir, const char *spellparam)
794{ 769{
795 uint32 dist, maxdist; 770 uint32 dist, maxdist;
796 int mflags; 771 int mflags;
797 maptile *m; 772 maptile *m;
798 sint16 sx, sy; 773 sint16 sx, sy;
800 if (op->type != PLAYER) 775 if (op->type != PLAYER)
801 return 0; 776 return 0;
802 777
803 if (!dir) 778 if (!dir)
804 { 779 {
805 new_draw_info (NDI_UNIQUE, 0, op, "In what direction?"); 780 op->failmsg ("In what direction?");
806 return 0; 781 return 0;
807 } 782 }
808 783
809 /* Given the new outdoor maps, can't let players dimension door for 784 /* Given the new outdoor maps, can't let players dimension door for
810 * ever, so put limits in. 785 * ever, so put limits in.
811 */ 786 */
812 maxdist = spob->range + SP_level_range_adjust (caster, spob); 787 maxdist = spob->range + SP_level_range_adjust (caster, spob);
813 788
814 if (op->contr->count) 789 if (spellparam)
815 { 790 {
791 int count = atoi (spellparam);
792
816 if (op->contr->count > maxdist) 793 if (count > maxdist)
817 { 794 {
818 new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!"); 795 op->failmsg ("You can't dimension door that far!");
819 return 0; 796 return 0;
820 } 797 }
821 798
822 for (dist = 0; dist < op->contr->count; dist++) 799 for (dist = 0; dist < count; dist++)
823 { 800 {
824 mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy); 801 mflags = get_map_flags (op->map, &m, op->x + DIRX (dir) * (dist + 1), op->y + DIRY (dir) * (dist + 1), &sx, &sy);
825 802
826 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP)) 803 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
827 break; 804 break;
828 805
829 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) 806 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
830 break; 807 break;
831 } 808 }
832 809
833 if (dist < op->contr->count) 810 if (dist < count)
834 { 811 {
835 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n"); 812 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n");
836 op->contr->count = 0;
837 return 0; 813 return 0;
838 } 814 }
839
840 op->contr->count = 0;
841 815
842 /* Remove code that puts player on random space on maps. IMO, 816 /* Remove code that puts player on random space on maps. IMO,
843 * a lot of maps probably have areas the player should not get to, 817 * a lot of maps probably have areas the player should not get to,
844 * but may not be marked as NO_MAGIC (as they may be bounded 818 * but may not be marked as NO_MAGIC (as they may be bounded
845 * by such squares). Also, there are probably treasure rooms and 819 * by such squares). Also, there are probably treasure rooms and
846 * lots of other maps that protect areas with no magic, but the 820 * lots of other maps that protect areas with no magic, but the
847 * areas themselves don't contain no magic spaces. 821 * areas themselves don't contain no magic spaces.
848 */ 822 */
849 /* This call here is really just to normalize the coordinates */ 823 /* This call here is really just to normalize the coordinates */
850 mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, &sx, &sy); 824 mflags = get_map_flags (op->map, &m, op->x + DIRX (dir) * dist, op->y + DIRY (dir) * dist, &sx, &sy);
851 if (mflags & P_IS_ALIVE || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) 825 if (mflags & P_IS_ALIVE || OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
852 { 826 {
853 new_draw_info (NDI_UNIQUE, 0, op, "You cast your spell, but nothing happens.\n"); 827 new_draw_info (NDI_UNIQUE, 0, op, "You cast your spell, but nothing happens.\n");
854 return 1; /* Maybe the penalty should be more severe... */ 828 return 1; /* Maybe the penalty should be more severe... */
855 } 829 }
861 * spaces that blocked the players view. 835 * spaces that blocked the players view.
862 */ 836 */
863 837
864 for (dist = 0; dist < maxdist; dist++) 838 for (dist = 0; dist < maxdist; dist++)
865 { 839 {
866 mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy); 840 mflags = get_map_flags (op->map, &m, op->x + DIRX (dir) * (dist + 1), op->y + DIRY (dir) * (dist + 1), &sx, &sy);
867 841
868 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP)) 842 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
869 break; 843 break;
870 844
871 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) 845 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
876 /* If the destination is blocked, keep backing up until we 850 /* If the destination is blocked, keep backing up until we
877 * find a place for the player. 851 * find a place for the player.
878 */ 852 */
879 for (; dist > 0; dist--) 853 for (; dist > 0; dist--)
880 { 854 {
881 if (get_map_flags (op->map, &m, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, 855 if (get_map_flags (op->map, &m, op->x + DIRX (dir) * dist, op->y + DIRY (dir) * dist,
882 &sx, &sy) & (P_OUT_OF_MAP | P_IS_ALIVE)) 856 &sx, &sy) & (P_OUT_OF_MAP | P_IS_ALIVE))
883 continue; 857 continue;
884 858
885 859
886 if (!OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) 860 if (!OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
887 break; 861 break;
888 862
889 } 863 }
890 if (!dist) 864 if (!dist)
891 { 865 {
892 new_draw_info (NDI_UNIQUE, 0, op, "Your spell failed!\n"); 866 op->failmsg ("Your spell failed!\n");
893 return 0; 867 return 0;
894 } 868 }
895 } 869 }
896 870
897 /* Actually move the player now */ 871 /* Actually move the player now */
898 if (!(op = op->map->insert (op, op->x + freearr_x[dir] * dist, op->y + freearr_y[dir] * dist, op))) 872 if (!(op = op->map->insert (op, op->x + DIRX (dir) * dist, op->y + DIRY (dir) * dist, op)))
899 return 1; 873 return 1;
900 874
901 op->speed_left = -FABS (op->speed) * 5; /* Freeze them for a short while */ 875 op->speed_left = -5. * op->speed; /* Freeze them for a short while */
876
902 return 1; 877 return 1;
903} 878}
904 879
905/* cast_heal: Heals something. 880/* cast_heal: Heals something.
906 * op is the caster. 881 * op is the caster.
961 if (cure_disease (tmp, op, spell)) 936 if (cure_disease (tmp, op, spell))
962 success = 1; 937 success = 1;
963 938
964 if (spell->attacktype & AT_POISON) 939 if (spell->attacktype & AT_POISON)
965 { 940 {
966 at = archetype::find ("poisoning"); 941 at = archetype::find (shstr_poisoning);
967 poison = present_arch_in_ob (at, tmp); 942 poison = present_arch_in_ob (at, tmp);
968 if (poison) 943 if (poison)
969 { 944 {
970 success = 1; 945 success = 1;
971 new_draw_info (NDI_UNIQUE, 0, tmp, "Your body feels cleansed"); 946 new_draw_info (NDI_UNIQUE, 0, tmp, "Your body feels cleansed");
973 } 948 }
974 } 949 }
975 950
976 if (spell->attacktype & AT_CONFUSION) 951 if (spell->attacktype & AT_CONFUSION)
977 { 952 {
978 poison = present_in_ob_by_name (FORCE, "confusion", tmp); 953 poison = present_in_ob_by_name (FORCE, shstr_confusion, tmp);
979 if (poison) 954 if (poison)
980 { 955 {
981 success = 1; 956 success = 1;
982 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer"); 957 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
983 poison->duration = 1; 958 poison->duration = 1;
984 } 959 }
985 } 960 }
986 961
987 if (spell->attacktype & AT_BLIND) 962 if (spell->attacktype & AT_BLIND)
988 { 963 {
989 at = archetype::find ("blindness"); 964 at = archetype::find (shstr_blindness);
990 poison = present_arch_in_ob (at, tmp); 965 poison = present_arch_in_ob (at, tmp);
991 if (poison) 966 if (poison)
992 { 967 {
993 success = 1; 968 success = 1;
994 new_draw_info (NDI_UNIQUE, 0, tmp, "Your vision begins to return."); 969 new_draw_info (NDI_UNIQUE, 0, tmp, "Your vision begins to return.");
1012 tmp->stats.grace = tmp->stats.maxgrace; 987 tmp->stats.grace = tmp->stats.maxgrace;
1013 success = 1; 988 success = 1;
1014 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!"); 989 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!");
1015 } 990 }
1016 991
1017 if (spell->stats.food && tmp->stats.food < 999) 992 if (spell->stats.food && tmp->stats.food < MAX_FOOD)
1018 { 993 {
1019 tmp->stats.food += spell->stats.food; 994 tmp->stats.food += spell->stats.food;
1020 995 min_it (tmp->stats.food, MAX_FOOD);
1021 if (tmp->stats.food > 999)
1022 tmp->stats.food = 999;
1023 996
1024 success = 1; 997 success = 1;
1025 /* We could do something a bit better like the messages for healing above */ 998 /* We could do something a bit better like the messages for healing above */
1026 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food"); 999 new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food");
1027 } 1000 }
1042 "You don't feel any more powerful." 1015 "You don't feel any more powerful."
1043 "You are no easier to look at.", 1016 "You are no easier to look at.",
1044}; 1017};
1045 1018
1046int 1019int
1020change_ability_duration (object *spell, object *caster)
1021{
1022 return spell->duration + SP_level_duration_adjust (caster, spell) * 50;
1023}
1024
1025int
1047cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent) 1026cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1048{ 1027{
1049 object *force = NULL; 1028 object *force = 0;
1050 int i; 1029 int i;
1051 1030
1052 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */ 1031 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1053 object *tmp = dir 1032 object *tmp = dir
1054 ? find_target_for_friendly_spell (op, dir) 1033 ? find_target_for_friendly_spell (op, dir)
1055 : op; 1034 : op;
1056 1035
1057 if (!tmp) 1036 if (!tmp)
1058 return 0; 1037 return 0;
1059 1038
1060 /* If we've already got a force of this type, don't add a new one. */ 1039 /* If we've already got a force of this type, don't add a new one. */
1068 break; 1047 break;
1069 } 1048 }
1070 else if (spell_ob->race && spell_ob->race == tmp2->name) 1049 else if (spell_ob->race && spell_ob->race == tmp2->name)
1071 { 1050 {
1072 if (!silent) 1051 if (!silent)
1073 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl); 1052 op->failmsgf ("You can not cast %s while %s is in effect",
1053 &spell_ob->name, &tmp2->name_pl);
1054
1074 return 0; 1055 return 0;
1075 } 1056 }
1076 } 1057 }
1077 } 1058 }
1059
1060 int duration = change_ability_duration (spell_ob, caster);
1061
1078 if (force == NULL) 1062 if (force)
1079 {
1080 force = get_archetype (FORCE_NAME);
1081 force->subtype = FORCE_CHANGE_ABILITY;
1082 if (spell_ob->race)
1083 force->name = spell_ob->race;
1084 else
1085 force->name = spell_ob->name;
1086 force->name_pl = spell_ob->name;
1087 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1088
1089 } 1063 {
1090 else
1091 {
1092 int duration;
1093
1094 duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1095 if (duration > force->duration) 1064 if (duration > force->duration)
1096 { 1065 {
1097 force->duration = duration; 1066 force->duration = duration;
1098 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); 1067 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1099 } 1068 }
1100 else 1069 else
1101 {
1102 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); 1070 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1103 }
1104 1071
1105 return 1; 1072 return 1;
1106 } 1073 }
1107 1074
1108 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50; 1075 new_draw_info_format (NDI_UNIQUE, 0, op,
1076 "You create an aura of magical force. H<The effect will last for about %.10g seconds.>",
1077 TICK2TIME (duration));
1078
1079 force = archetype::get (FORCE_NAME);
1080 force->subtype = FORCE_CHANGE_ABILITY;
1081 force->duration = duration;
1082
1083 if (spell_ob->race)
1084 force->name = spell_ob->race;
1085 else
1086 force->name = spell_ob->name;
1087
1088 force->name_pl = spell_ob->name;
1089
1109 force->speed = 1.0; 1090 force->speed = 1.0;
1110 force->speed_left = -1.0; 1091 force->speed_left = -1.0;
1111 SET_FLAG (force, FLAG_APPLIED); 1092 force->set_flag (FLAG_APPLIED);
1112 1093
1113 /* Now start processing the effects. First, protections */ 1094 /* Now start processing the effects. First, protections */
1114 for (i = 0; i < NROFATTACKS; i++) 1095 for (i = 0; i < NROFATTACKS; i++)
1115 {
1116 if (spell_ob->resist[i]) 1096 if (spell_ob->resist[i])
1117 {
1118 force->resist[i] = spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob); 1097 force->resist[i] = min (100, spell_ob->resist[i] + SP_level_dam_adjust (caster, spell_ob));
1119 if (force->resist[i] > 100)
1120 force->resist[i] = 100;
1121 }
1122 }
1123 1098
1124 if (spell_ob->stats.hp) 1099 if (spell_ob->stats.hp)
1125 force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob); 1100 force->stats.hp = spell_ob->stats.hp + SP_level_dam_adjust (caster, spell_ob);
1126 1101
1127 if (tmp->type == PLAYER) 1102 if (tmp->type == PLAYER)
1146 } 1121 }
1147 } 1122 }
1148 1123
1149 force->move_type = spell_ob->move_type; 1124 force->move_type = spell_ob->move_type;
1150 1125
1151 if (QUERY_FLAG (spell_ob, FLAG_SEE_IN_DARK)) 1126 if (spell_ob->flag [FLAG_SEE_IN_DARK])
1152 SET_FLAG (force, FLAG_SEE_IN_DARK); 1127 force->set_flag (FLAG_SEE_IN_DARK);
1153 1128
1154 if (QUERY_FLAG (spell_ob, FLAG_XRAYS)) 1129 if (spell_ob->flag [FLAG_XRAYS])
1155 SET_FLAG (force, FLAG_XRAYS); 1130 force->set_flag (FLAG_XRAYS);
1156 1131
1157 /* Haste/bonus speed */ 1132 /* Haste/bonus speed */
1158 if (spell_ob->stats.exp) 1133 if (spell_ob->stats.exp)
1159 { 1134 {
1160 if (op->speed > 0.5f) 1135 if (op->speed > 0.5f)
1180 */ 1155 */
1181int 1156int
1182cast_bless (object *op, object *caster, object *spell_ob, int dir) 1157cast_bless (object *op, object *caster, object *spell_ob, int dir)
1183{ 1158{
1184 int i; 1159 int i;
1185 object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp; 1160 object *god = find_god (determine_god (op)), *force = NULL, *tmp;
1186 1161
1187 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */ 1162 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1188 if (dir != 0) 1163 if (dir != 0)
1189 { 1164 {
1190 tmp = find_target_for_friendly_spell (op, dir); 1165 tmp = find_target_for_friendly_spell (op, dir);
1166
1167 if (!tmp)
1168 return 0;
1191 } 1169 }
1192 else 1170 else
1193 {
1194 tmp = op; 1171 tmp = op;
1195 }
1196 1172
1197 /* If we've already got a force of this type, don't add a new one. */ 1173 /* If we've already got a force of this type, don't add a new one. */
1198 for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below) 1174 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1199 { 1175 {
1200 if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) 1176 if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1201 { 1177 {
1202 if (tmp2->name == spell_ob->name) 1178 if (tmp2->name == spell_ob->name)
1203 { 1179 {
1209 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl); 1185 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1210 return 0; 1186 return 0;
1211 } 1187 }
1212 } 1188 }
1213 } 1189 }
1190
1214 if (force == NULL) 1191 if (force == NULL)
1215 { 1192 {
1216 force = get_archetype (FORCE_NAME); 1193 force = archetype::get (FORCE_NAME);
1217 force->subtype = FORCE_CHANGE_ABILITY; 1194 force->subtype = FORCE_CHANGE_ABILITY;
1218 if (spell_ob->race) 1195 if (spell_ob->race)
1219 force->name = spell_ob->race; 1196 force->name = spell_ob->race;
1220 else 1197 else
1221 force->name = spell_ob->name; 1198 force->name = spell_ob->name;
1236 { 1213 {
1237 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); 1214 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1238 } 1215 }
1239 return 0; 1216 return 0;
1240 } 1217 }
1218
1241 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50; 1219 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1242 force->speed = 1.0; 1220 force->speed = 1.0;
1243 force->speed_left = -1.0; 1221 force->speed_left = -1.0;
1244 SET_FLAG (force, FLAG_APPLIED); 1222 force->set_flag (FLAG_APPLIED);
1245 1223
1246 if (!god) 1224 if (!god)
1247 { 1225 {
1248 new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty."); 1226 new_draw_info (NDI_UNIQUE, 0, op, "Your blessing seems empty.");
1249 } 1227 }
1250 else 1228 else
1251 { 1229 {
1252 /* Only give out good benefits, and put a max on it */ 1230 /* Only give out good benefits, and put a max on it */
1253 for (i = 0; i < NROFATTACKS; i++) 1231 for (i = 0; i < NROFATTACKS; i++)
1254 {
1255 if (god->resist[i] > 0) 1232 if (god->resist[i] > 0)
1256 {
1257 force->resist[i] = MIN (god->resist[i], spell_ob->resist[ATNR_GODPOWER]); 1233 force->resist[i] = min (god->resist[i], spell_ob->resist[ATNR_GODPOWER]);
1258 } 1234
1259 }
1260 force->path_attuned |= god->path_attuned; 1235 force->path_attuned |= god->path_attuned;
1261 1236
1262 if (spell_ob->attacktype) 1237 if (spell_ob->attacktype)
1263 force->slaying = god->slaying; 1238 force->slaying = god->slaying;
1264 1239
1284 1259
1285/* Alchemy code by Mark Wedel 1260/* Alchemy code by Mark Wedel
1286 * 1261 *
1287 * This code adds a new spell, called alchemy. Alchemy will turn 1262 * This code adds a new spell, called alchemy. Alchemy will turn
1288 * objects to pyrite ("false gold"), henceforth called gold nuggets. 1263 * objects to pyrite ("false gold"), henceforth called gold nuggets.
1289 * 1264 *
1290 * The value of the gold nuggets being about 90% of that of the item 1265 * The value of the gold nuggets being about 90% of that of the item
1291 * itself. It uses the value of the object before charisma adjustments, 1266 * itself. It uses the value of the object before charisma adjustments,
1292 * because the nuggets themselves will be will be adjusted by charisma 1267 * because the nuggets themselves will be will be adjusted by charisma
1293 * when sold. 1268 * when sold.
1294 * 1269 *
1299static void 1274static void
1300alchemy_object (object *obj, uint64 &total_value, int &total_weight) 1275alchemy_object (object *obj, uint64 &total_value, int &total_weight)
1301{ 1276{
1302 uint64 value = query_cost (obj, NULL, F_TRUE); 1277 uint64 value = query_cost (obj, NULL, F_TRUE);
1303 1278
1304 /* Give third price when we alchemy money (This should hopefully 1279 /* Give third price when we alchemy money (this should hopefully
1305 * make it so that it isn't worth it to alchemy money, sell 1280 * make it so that it isn't worth it to alchemy money, sell
1306 * the nuggets, alchemy the gold from that, etc. 1281 * the nuggets, alchemy the gold from that, etc.
1307 * Otherwise, give 9 silver on the gold for other objects, 1282 * Otherwise, give 9 silver on the gold for other objects,
1308 * so that it would still be more affordable to haul 1283 * so that it would still be more affordable to haul
1309 * the stuff back to town. 1284 * the stuff back to town.
1310 */ 1285 */
1311 if (QUERY_FLAG (obj, FLAG_UNPAID)) 1286 if (obj->flag [FLAG_UNPAID])
1312 value = 0; 1287 value = 0;
1313 else if (obj->type == MONEY || obj->type == GEM) 1288 else if (obj->type == MONEY || obj->type == GEM)
1314 value /= 3; 1289 value /= 3;
1315 else 1290 else
1316 value = value * 9 / 10; 1291 value = value * 9 / 10;
1329 if (op->type != PLAYER) 1304 if (op->type != PLAYER)
1330 return 0; 1305 return 0;
1331 1306
1332 archetype *nugget[3]; 1307 archetype *nugget[3];
1333 1308
1334 nugget[0] = archetype::find ("pyrite3"); 1309 nugget[0] = archetype::find (shstr_pyrite3);
1335 nugget[1] = archetype::find ("pyrite2"); 1310 nugget[1] = archetype::find (shstr_pyrite2);
1336 nugget[2] = archetype::find ("pyrite"); 1311 nugget[2] = archetype::find (shstr_pyrite);
1337 1312
1338 /* Put a maximum weight of items that can be alchemised. Limits the power 1313 /* Put a maximum weight of items that can be alchemised. Limits the power
1339 * some, and also prevents people from alchemising every table/chair/clock 1314 * some, and also prevents people from alchemising every table/chair/clock
1340 * in sight 1315 * in sight
1341 */ 1316 */
1370 1345
1371 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next) 1346 for (object *next, *tmp = mp->at (nx, ny).bot; tmp; tmp = next)
1372 { 1347 {
1373 next = tmp->above; 1348 next = tmp->above;
1374 1349
1375 if (tmp->weight > 0 && !QUERY_FLAG (tmp, FLAG_NO_PICK) && 1350 if (tmp->weight > 0 && !tmp->flag [FLAG_NO_PICK] &&
1376 !QUERY_FLAG (tmp, FLAG_ALIVE) && !QUERY_FLAG (tmp, FLAG_IS_CAULDRON)) 1351 !tmp->flag [FLAG_ALIVE] && !tmp->flag [FLAG_IS_CAULDRON])
1377 { 1352 {
1378 if (tmp->inv) 1353 if (tmp->inv)
1379 { 1354 {
1380 object *next1, *tmp1; 1355 object *next1, *tmp1;
1381 1356
1382 for (tmp1 = tmp->inv; tmp1; tmp1 = next1) 1357 for (tmp1 = tmp->inv; tmp1; tmp1 = next1)
1383 { 1358 {
1384 next1 = tmp1->below; 1359 next1 = tmp1->below;
1385 if (tmp1->weight > 0 && !QUERY_FLAG (tmp1, FLAG_NO_PICK) && 1360 if (tmp1->weight > 0 && !tmp1->flag [FLAG_NO_PICK] &&
1386 !QUERY_FLAG (tmp1, FLAG_ALIVE) && !QUERY_FLAG (tmp1, FLAG_IS_CAULDRON)) 1361 !tmp1->flag [FLAG_ALIVE] && !tmp1->flag [FLAG_IS_CAULDRON])
1387 alchemy_object (tmp1, value, weight); 1362 alchemy_object (tmp1, value, weight);
1388 } 1363 }
1389 } 1364 }
1390 1365
1391 alchemy_object (tmp, value, weight); 1366 alchemy_object (tmp, value, weight);
1396 } 1371 }
1397 1372
1398 value -= rndm (value >> 4); 1373 value -= rndm (value >> 4);
1399 value = min (value, value_max); 1374 value = min (value, value_max);
1400 1375
1401 for (int i = 0; i < sizeof (nugget) / sizeof (nugget [0]); ++i) 1376 for (int i = 0; i < array_length (nugget); ++i)
1402 if (int nrof = value / nugget [i]->value) 1377 if (int nrof = value / nugget [i]->value)
1403 { 1378 {
1404 value -= nrof * nugget[i]->value; 1379 value -= nrof * nugget[i]->value;
1405 1380
1406 object *tmp = arch_to_object (nugget[i]); 1381 object *tmp = nugget[i]->instance ();
1407 tmp->nrof = nrof; 1382 tmp->nrof = nrof;
1408 tmp->flag [FLAG_IDENTIFIED] = true; 1383 tmp->flag [FLAG_IDENTIFIED] = true;
1409 op->map->insert (tmp, x, y, op, 0); 1384 op->map->insert (tmp, x, y, op, 0);
1410 } 1385 }
1411 1386
1416 1391
1417bailout: 1392bailout:
1418 return 1; 1393 return 1;
1419} 1394}
1420 1395
1421
1422/* This function removes the cursed/damned status on equipped 1396/* This function removes the cursed/damned status on equipped
1423 * items. 1397 * items.
1424 */ 1398 */
1425int 1399int
1426remove_curse (object *op, object *caster, object *spell) 1400remove_curse (object *op, object *caster, object *spell)
1427{ 1401{
1428 object *tmp;
1429 int success = 0, was_one = 0; 1402 int success = 0, was_one = 0;
1430 1403
1404 int num_uncurse = max (1, spell->stats.dam + SP_level_dam_adjust (caster, spell));
1405
1406 op->splay_marked ();
1407
1408 int typeflag = spell->last_sp ? FLAG_DAMNED : FLAG_CURSED;
1409
1431 for (tmp = op->inv; tmp; tmp = tmp->below) 1410 for (object *tmp = op->inv; tmp && num_uncurse; tmp = tmp->below)
1432 if (QUERY_FLAG (tmp, FLAG_APPLIED) && 1411 if (!tmp->invisible && tmp->flag [typeflag])
1433 ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1434 (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1435 { 1412 {
1436 was_one++; 1413 ++was_one;
1414
1437 if (tmp->level <= caster_level (caster, spell)) 1415 if (tmp->level <= casting_level (caster, spell))
1438 { 1416 {
1439 success++; 1417 ++success;
1440 if (QUERY_FLAG (spell, FLAG_DAMNED)) 1418 --num_uncurse;
1441 CLEAR_FLAG (tmp, FLAG_DAMNED);
1442 1419
1443 CLEAR_FLAG (tmp, FLAG_CURSED); 1420 tmp->clr_flag (typeflag);
1444 CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED); 1421 tmp->clr_flag (FLAG_CURSED);
1422 tmp->clr_flag (FLAG_KNOWN_CURSED);
1445 tmp->value = 0; /* Still can't sell it */ 1423 tmp->value = 0; /* Still can't sell it */
1446 if (op->type == PLAYER) 1424
1425 if (object *pl = tmp->visible_to ())
1447 esrv_send_item (op, tmp); 1426 esrv_update_item (UPD_FLAGS, pl, tmp);
1448 } 1427 }
1449 } 1428 }
1450 1429
1451 if (op->type == PLAYER) 1430 if (op->type == PLAYER)
1452 { 1431 {
1453 if (success) 1432 if (success)
1454 new_draw_info (NDI_UNIQUE, 0, op, "You feel like some of your items are looser now."); 1433 new_draw_info (NDI_UNIQUE, 0, op, "You realise that some of your items look shinier now. H<You successfully removed some curses.>");
1455 else 1434 else
1456 { 1435 {
1457 if (was_one) 1436 if (was_one)
1458 new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove the curse."); 1437 new_draw_info (NDI_UNIQUE, 0, op, "You failed to remove any curse. H<The spell was not strong enough.>");
1459 else 1438 else
1460 new_draw_info (NDI_UNIQUE, 0, op, "You are not using any cursed items."); 1439 new_draw_info (NDI_UNIQUE, 0, op, "You are not having any cursed items. H<Epic fail.>");
1461 } 1440 }
1462 } 1441 }
1463 1442
1464 return success; 1443 return success;
1465} 1444}
1466 1445
1467/* Identifies objects in the players inventory/on the ground */ 1446/* Identifies objects in the players inventory/on the ground */
1468int 1447int
1469cast_identify (object *op, object *caster, object *spell) 1448cast_identify (object *op, object *caster, object *spell)
1470{ 1449{
1471 dynbuf_text buf; 1450 dynbuf_text &buf = msg_dynbuf; buf.clear ();
1472 object *tmp;
1473 1451
1474 int num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell); 1452 int num_ident = max (1, spell->stats.dam + SP_level_dam_adjust (caster, spell));
1475 1453
1476 if (num_ident < 1) 1454 op->splay_marked ();
1477 num_ident = 1;
1478 1455
1479 for (tmp = op->inv; tmp; tmp = tmp->below) 1456 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1480 { 1457 {
1481 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp)) 1458 if (!tmp->flag [FLAG_IDENTIFIED] && !tmp->invisible && tmp->need_identify ())
1482 { 1459 {
1483 identify (tmp); 1460 identify (tmp);
1484 1461
1485 if (op->type == PLAYER) 1462 if (op->type == PLAYER)
1486 { 1463 {
1487 buf.printf ("You identified: %s.\n\n", long_desc (tmp, op)); 1464 buf.printf ("You identified: %s.\r", long_desc (tmp, op));
1488 1465
1489 if (tmp->msg) 1466 if (tmp->msg)
1490 buf << "The item has a story:\n\n" << tmp->msg << "\n\n"; 1467 buf << "The item has a story:\r" << tmp->msg << "\n\n";
1491 } 1468 }
1492 1469
1493 num_ident--;
1494 if (!num_ident) 1470 if (!--num_ident)
1495 break; 1471 break;
1496 } 1472 }
1497 } 1473 }
1498 1474
1499 /* If all the power of the spell has been used up, don't go and identify 1475 /* If all the power of the spell has been used up, don't go and identify
1500 * stuff on the floor. Only identify stuff on the floor if the spell 1476 * stuff on the floor. Only identify stuff on the floor if the spell
1501 * was not fully used. 1477 * was not fully used.
1502 */ 1478 */
1503 if (num_ident) 1479 if (num_ident)
1504 { 1480 {
1505 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above) 1481 for (object *tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1506 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp)) 1482 if (!tmp->flag [FLAG_IDENTIFIED] && !tmp->invisible && tmp->need_identify ())
1507 { 1483 {
1508 identify (tmp); 1484 identify (tmp);
1509 1485
1510 if (op->type == PLAYER) 1486 if (object *pl = tmp->visible_to ())
1511 { 1487 {
1512 buf.printf ("On the ground you identified: %s.\n\n", long_desc (tmp, op)); 1488 buf.printf ("On the ground you identified: %s.\r", long_desc (tmp, op));
1513 1489
1514 if (tmp->msg) 1490 if (tmp->msg)
1515 buf << "The item has a story:\n\n" << tmp->msg << "\n\n"; 1491 buf << "The item has a story:\r" << tmp->msg << "\n\n";
1516
1517 esrv_send_item (op, tmp);
1518 } 1492 }
1519 1493
1520 num_ident--;
1521 if (!num_ident) 1494 if (!--num_ident)
1522 break; 1495 break;
1523 } 1496 }
1524 } 1497 }
1525 1498
1526 if (buf.empty ()) 1499 if (buf.empty ())
1540 1513
1541int 1514int
1542cast_detection (object *op, object *caster, object *spell, object *skill) 1515cast_detection (object *op, object *caster, object *spell, object *skill)
1543{ 1516{
1544 object *tmp, *last, *god, *detect; 1517 object *tmp, *last, *god, *detect;
1545 int done_one, range, mflags, floor, level; 1518 int done_one, range, floor, level;
1546 sint16 x, y, nx, ny; 1519 sint16 x, y, nx, ny;
1547 maptile *m; 1520 maptile *m;
1548 1521
1549 /* We precompute some values here so that we don't have to keep 1522 /* We precompute some values here so that we don't have to keep
1550 * doing it over and over again. 1523 * doing it over and over again.
1551 */ 1524 */
1552 god = find_god (determine_god (op)); 1525 god = find_god (determine_god (op));
1553 level = caster_level (caster, spell); 1526 level = casting_level (caster, spell);
1554 range = spell->range + SP_level_range_adjust (caster, spell); 1527 range = spell->range + SP_level_range_adjust (caster, spell);
1555 1528
1556 if (!skill) 1529 if (!skill)
1557 skill = caster; 1530 skill = caster;
1558 1531
1559 for (x = op->x - range; x <= op->x + range; x++) 1532 dynbuf buf;
1560 for (y = op->y - range; y <= op->y + range; y++) 1533 unordered_mapwalk (buf, op, -range, -range, range, range)
1561 { 1534 {
1562 m = op->map;
1563 mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1564 if (mflags & P_OUT_OF_MAP)
1565 continue;
1566
1567 /* For most of the detections, we only detect objects above the 1535 /* For most of the detections, we only detect objects above the
1568 * floor. But this is not true for show invisible. 1536 * floor. But this is not true for show invisible.
1569 * Basically, we just go and find the top object and work 1537 * Basically, we just go and find the top object and work
1570 * down - that is easier than working up. 1538 * down - that is easier than working up.
1571 */ 1539 */
1572 1540
1573 for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above) 1541 for (last = 0, tmp = m->at (nx, ny).bot; tmp; tmp = tmp->above)
1574 last = tmp; 1542 last = tmp;
1575 1543
1576 /* Shouldn't happen, but if there are no objects on a space, this 1544 /* Shouldn't happen, but if there are no objects on a space, this
1577 * would happen. 1545 * would happen.
1578 */ 1546 */
1579 if (!last) 1547 if (!last)
1580 continue; 1548 continue;
1581 1549
1582 done_one = 0; 1550 done_one = 0;
1583 floor = 0; 1551 floor = 0;
1584 detect = NULL; 1552 detect = 0;
1585 for (tmp = last; tmp; tmp = tmp->below) 1553 for (tmp = last; tmp; tmp = tmp->below)
1586 { 1554 {
1587 /* show invisible */ 1555 /* show invisible */
1588 if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) && 1556 if (spell->flag [FLAG_MAKE_INVIS]
1589 /* Might there be other objects that we can make visible? */ 1557 /* Might there be other objects that we can make visible? */
1590 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) || 1558 && (tmp->invisible && (tmp->flag [FLAG_MONSTER]
1591 (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) || 1559 || (tmp->type == PLAYER && !tmp->flag [FLAG_WIZ])
1592 tmp->type == CF_HANDLE || 1560 || tmp->type == T_HANDLE
1593 tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE || 1561 || tmp->type == TRAPDOOR
1562 || tmp->type == EXIT
1563 || tmp->type == HOLE
1564 || tmp->type == BUTTON
1594 tmp->type == BUTTON || tmp->type == TELEPORTER || 1565 || tmp->type == TELEPORTER
1566 || tmp->type == GATE
1595 tmp->type == GATE || tmp->type == LOCKED_DOOR || 1567 || tmp->type == LOCKED_DOOR
1596 tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN || 1568 || tmp->type == WEAPON
1569 || tmp->type == ALTAR
1570 || (tmp->type == SIGN && tmp->face != magicmouth_face)
1597 tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY || 1571 || tmp->type == TRIGGER_PEDESTAL
1598 tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR))) 1572 || tmp->type == SPECIAL_KEY
1573 || tmp->type == TREASURE
1574 || tmp->type == BOOK
1575 || tmp->type == HOLY_ALTAR
1576 || tmp->type == CONTAINER)))
1599 { 1577 {
1578 printf ("show inv %s\n", tmp->debug_desc());//D
1600 if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4) 1579 if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4)
1601 { 1580 {
1602 tmp->invisible = 0; 1581 tmp->invisible = 0;
1582 done_one = 1;
1583 }
1584 }
1585
1586 if (tmp->flag [FLAG_IS_FLOOR])
1587 floor = 1;
1588
1589 /* All detections below this point don't descend beneath the floor,
1590 * so just continue on. We could be clever and look at the type of
1591 * detection to completely break out if we don't care about objects beneath
1592 * the floor, but once we get to the floor, not likely a very big issue anyways.
1593 */
1594 if (floor)
1595 continue;
1596
1597 /* I had thought about making detect magic and detect curse
1598 * show the flash the magic item like it does for detect monster.
1599 * however, if the object is within sight, this would then make it
1600 * difficult to see what object is magical/cursed, so the
1601 * effect wouldn't be as apparent.
1602 */
1603
1604 /* detect magic */
1605 if (spell->flag [FLAG_KNOWN_MAGICAL]
1606 && !tmp->flag [FLAG_KNOWN_MAGICAL]
1607 && !tmp->flag [FLAG_IDENTIFIED]
1608 && tmp->need_identify ()
1609 && is_magical (tmp))
1610 {
1611 tmp->set_flag (FLAG_KNOWN_MAGICAL);
1612 /* make runes more visible */
1613 if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1614 tmp->stats.Cha /= 4;
1615
1616 done_one = 1;
1617 }
1618
1619 /* detect monster */
1620 if (spell->flag [FLAG_MONSTER] && (tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER))
1621 {
1622 done_one = 2;
1623
1624 if (!detect)
1625 detect = tmp;
1626 }
1627
1628 /* Basically, if race is set in the spell, then the creatures race must
1629 * match that. if the spell race is set to GOD, then the gods opposing
1630 * race must match.
1631 */
1632 if (spell->race && tmp->flag [FLAG_MONSTER] && tmp->race &&
1633 ((spell->race == shstr_GOD && god && god->slaying.contains (tmp->race)) ||
1634 spell->race.contains (tmp->race)))
1635 {
1636 done_one = 2;
1637
1638 if (!detect)
1639 detect = tmp;
1640 }
1641
1642 if (spell->flag [FLAG_KNOWN_CURSED]
1643 && !tmp->flag [FLAG_KNOWN_CURSED]
1644 && tmp->need_identify ()
1645 && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]))
1646 {
1647 tmp->set_flag (FLAG_KNOWN_CURSED);
1648 done_one = 1;
1649 }
1650
1651 // Do mining detection spell:
1652 if (spell->last_sp == 1) // 1 - detect any vein
1653 {
1654 if (tmp->type == VEIN)
1655 {
1656 if (tmp->other_arch)
1657 {
1658 if (!detect)
1659 detect = tmp->other_arch;
1660 done_one = 2;
1661 }
1662 else
1603 done_one = 1; 1663 done_one = 1;
1604 } 1664 }
1605 } 1665 }
1606
1607 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1608 floor = 1;
1609
1610 /* All detections below this point don't descend beneath the floor,
1611 * so just continue on. We could be clever and look at the type of
1612 * detection to completely break out if we don't care about objects beneath
1613 * the floor, but once we get to the floor, not likely a very big issue anyways.
1614 */
1615 if (floor)
1616 continue;
1617
1618 /* I had thought about making detect magic and detect curse
1619 * show the flash the magic item like it does for detect monster.
1620 * however, if the object is within sight, this would then make it
1621 * difficult to see what object is magical/cursed, so the
1622 * effect wouldn't be as apparant.
1623 */
1624
1625 /* detect magic */
1626 if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) &&
1627 !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp))
1628 {
1629 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1630 /* make runes more visibile */
1631 if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1632 tmp->stats.Cha /= 4;
1633 done_one = 1;
1634 }
1635 /* detect monster */
1636 if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER))
1637 {
1638 done_one = 2;
1639 if (!detect)
1640 detect = tmp;
1641 }
1642 /* Basically, if race is set in the spell, then the creatures race must
1643 * match that. if the spell race is set to GOD, then the gods opposing
1644 * race must match.
1645 */
1646 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race &&
1647 ((!strcmp (spell->race, "GOD") && god && god->slaying && strstr (god->slaying, tmp->race)) ||
1648 (strstr (spell->race, tmp->race))))
1649 {
1650 done_one = 2;
1651 if (!detect)
1652 detect = tmp;
1653 }
1654 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1655 (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1656 {
1657 SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1658 done_one = 1;
1659 }
1660 } /* for stack of objects on this space */ 1666 } /* for stack of objects on this space */
1661 1667
1662 /* Code here puts an effect of the spell on the space, so you can see 1668 /* Code here puts an effect of the spell on the space, so you can see
1663 * where the magic is. 1669 * where the magic is.
1664 */ 1670 */
1665 if (done_one) 1671 if (done_one)
1666 { 1672 {
1667 object *detect_ob = arch_to_object (spell->other_arch); 1673 object *detect_ob = spell->other_arch->instance ();
1668 1674
1669 /* if this is set, we want to copy the face */ 1675 /* if this is set, we want to copy the face */
1670 if (done_one == 2 && detect) 1676 if (done_one == 2 && detect)
1671 { 1677 {
1672 detect_ob->face = detect->face; 1678 detect_ob->face = detect->face;
1673 detect_ob->animation_id = detect->animation_id; 1679 detect_ob->animation_id = detect->animation_id;
1674 detect_ob->anim_speed = detect->anim_speed; 1680 detect_ob->anim_speed = detect->anim_speed;
1675 detect_ob->last_anim = 0; 1681 detect_ob->last_anim = 0;
1676 /* by default, the detect_ob is already animated */ 1682 /* by default, the detect_ob is already animated */
1677 if (!QUERY_FLAG (detect, FLAG_ANIMATE)) 1683 if (!detect->flag [FLAG_ANIMATE])
1678 CLEAR_FLAG (detect_ob, FLAG_ANIMATE); 1684 detect_ob->clr_flag (FLAG_ANIMATE);
1679 } 1685 }
1680 1686
1681 m->insert (detect_ob, nx, ny, op); 1687 m->insert (detect_ob, nx, ny, op, INS_ON_TOP);
1682 } 1688 }
1683 } /* for processing the surrounding spaces */ 1689 } /* for processing the surrounding spaces */
1684 1690
1685 1691
1686 /* Now process objects in the players inventory if detect curse or magic */ 1692 /* Now process objects in the players inventory if detect curse or magic */
1687 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL)) 1693 if (spell->flag [FLAG_KNOWN_CURSED] || spell->flag [FLAG_KNOWN_MAGICAL])
1688 { 1694 {
1689 done_one = 0; 1695 done_one = 0;
1696
1690 for (tmp = op->inv; tmp; tmp = tmp->below) 1697 for (tmp = op->inv; tmp; tmp = tmp->below)
1691 { 1698 {
1692 if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 1699 if (!tmp->invisible && !tmp->flag [FLAG_IDENTIFIED])
1693 { 1700 {
1694 if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL)) 1701 if (spell->flag [FLAG_KNOWN_MAGICAL] && is_magical (tmp) && !tmp->flag [FLAG_KNOWN_MAGICAL])
1695 { 1702 {
1696 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); 1703 tmp->set_flag (FLAG_KNOWN_MAGICAL);
1697 if (op->type == PLAYER) 1704
1705 if (object *pl = tmp->visible_to ())
1698 esrv_send_item (op, tmp); 1706 esrv_update_item (UPD_FLAGS, pl, tmp);
1699 } 1707 }
1700 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) && 1708
1701 (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) 1709 if (spell->flag [FLAG_KNOWN_CURSED] && !tmp->flag [FLAG_KNOWN_CURSED] &&
1710 (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]))
1702 { 1711 {
1703 SET_FLAG (tmp, FLAG_KNOWN_CURSED); 1712 tmp->set_flag (FLAG_KNOWN_CURSED);
1704 if (op->type == PLAYER) 1713
1714 if (object *pl = tmp->visible_to ())
1705 esrv_send_item (op, tmp); 1715 esrv_update_item (UPD_FLAGS, pl, tmp);
1706 } 1716 }
1707 } /* if item is not identified */ 1717 } /* if item is not identified */
1708 } /* for the players inventory */ 1718 } /* for the players inventory */
1709 } /* if detect magic/curse and object is a player */ 1719 } /* if detect magic/curse and object is a player */
1720
1710 return 1; 1721 return 1;
1711} 1722}
1712 1723
1713 1724
1714/** 1725/**
1727 1738
1728 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you."); 1739 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you.");
1729 1740
1730 if (victim->stats.sp >= victim->stats.maxsp * 2) 1741 if (victim->stats.sp >= victim->stats.maxsp * 2)
1731 { 1742 {
1732 object *tmp;
1733
1734 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!"); 1743 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!");
1735
1736 /* Explodes a fireball centered at player */
1737 tmp = get_archetype (EXPLODING_FIREBALL);
1738 tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1;
1739 tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2;
1740
1741 tmp->insert_at (victim);
1742 victim->stats.sp = 2 * victim->stats.maxsp; 1744 victim->stats.sp = 2 * victim->stats.maxsp;
1745 create_exploding_ball_at (victim, caster_level);
1743 } 1746 }
1744 else if (victim->stats.sp >= victim->stats.maxsp * 1.88) 1747 else if (victim->stats.sp >= victim->stats.maxsp * 1.88)
1745 new_draw_info (NDI_UNIQUE, NDI_ORANGE, victim, "You feel like your head is going to explode."); 1748 new_draw_info (NDI_UNIQUE | NDI_ORANGE, 0, victim, "You feel like your head is going to explode.");
1746 else if (victim->stats.sp >= victim->stats.maxsp * 1.66) 1749 else if (victim->stats.sp >= victim->stats.maxsp * 1.66)
1747 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!"); 1750 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!");
1748 else if (victim->stats.sp >= victim->stats.maxsp * 1.5) 1751 else if (victim->stats.sp >= victim->stats.maxsp * 1.5)
1749 { 1752 {
1750 new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world."); 1753 new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world.");
1766 sint16 x, y; 1769 sint16 x, y;
1767 maptile *m; 1770 maptile *m;
1768 int mflags; 1771 int mflags;
1769 1772
1770 m = op->map; 1773 m = op->map;
1771 x = op->x + freearr_x[dir]; 1774 x = op->x + DIRX (dir);
1772 y = op->y + freearr_y[dir]; 1775 y = op->y + DIRY (dir);
1773 1776
1774 mflags = get_map_flags (m, &m, x, y, &x, &y); 1777 mflags = get_map_flags (m, &m, x, y, &x, &y);
1775 1778
1776 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE) 1779 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
1777 { 1780 {
1778 for (plyr = GET_MAP_OB (m, x, y); plyr != NULL; plyr = plyr->above) 1781 for (plyr = GET_MAP_OB (m, x, y); plyr != NULL; plyr = plyr->above)
1779 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE)) 1782 if (plyr != op && plyr->flag [FLAG_ALIVE])
1780 break; 1783 break;
1781 } 1784 }
1782 1785
1783 1786
1784 /* If we did not find a player in the specified direction, transfer 1787 /* If we did not find a player in the specified direction, transfer
1785 * to anyone on top of us. This is used for the rune of transference mostly. 1788 * to anyone on top of us. This is used for the rune of transference mostly.
1786 */ 1789 */
1787 if (plyr == NULL) 1790 if (plyr == NULL)
1788 for (plyr = GET_MAP_OB (op->map, op->x, op->y); plyr != NULL; plyr = plyr->above) 1791 for (plyr = GET_MAP_OB (op->map, op->x, op->y); plyr != NULL; plyr = plyr->above)
1789 if (plyr != op && QUERY_FLAG (plyr, FLAG_ALIVE)) 1792 if (plyr != op && plyr->flag [FLAG_ALIVE])
1790 break; 1793 break;
1791 1794
1792 if (!plyr) 1795 if (!plyr)
1793 { 1796 {
1794 new_draw_info (NDI_BLACK, 0, op, "There is no one there."); 1797 op->failmsg ("There is no one there.");
1795 return 0; 1798 return 0;
1796 } 1799 }
1797 /* give sp */ 1800 /* give sp */
1798 if (spell->stats.dam > 0) 1801 if (spell->stats.dam > 0)
1799 { 1802 {
1800 plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell); 1803 plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell);
1801 charge_mana_effect (plyr, caster_level (caster, spell)); 1804 charge_mana_effect (plyr, casting_level (caster, spell));
1802 return 1; 1805 return 1;
1803 } 1806 }
1804 /* suck sp away. Can't suck sp from yourself */ 1807 /* suck sp away. Can't suck sp from yourself */
1805 else if (op != plyr) 1808 else if (op != plyr)
1806 { 1809 {
1811 if (rate > 95) 1814 if (rate > 95)
1812 rate = 95; 1815 rate = 95;
1813 1816
1814 sucked = (plyr->stats.sp * rate) / 100; 1817 sucked = (plyr->stats.sp * rate) / 100;
1815 plyr->stats.sp -= sucked; 1818 plyr->stats.sp -= sucked;
1816 if (QUERY_FLAG (op, FLAG_ALIVE)) 1819 if (op->flag [FLAG_ALIVE])
1817 { 1820 {
1818 /* Player doesn't get full credit */ 1821 /* Player doesn't get full credit */
1819 sucked = (sucked * rate) / 100; 1822 sucked = (sucked * rate) / 100;
1820 op->stats.sp += sucked; 1823 op->stats.sp += sucked;
1821 if (sucked > 0) 1824 if (sucked > 0)
1822 { 1825 {
1823 charge_mana_effect (op, caster_level (caster, spell)); 1826 charge_mana_effect (op, casting_level (caster, spell));
1824 } 1827 }
1825 } 1828 }
1826 return 1; 1829 return 1;
1827 } 1830 }
1828 return 0; 1831 return 0;
1841 object *tmp, *head, *next; 1844 object *tmp, *head, *next;
1842 int mflags; 1845 int mflags;
1843 maptile *m; 1846 maptile *m;
1844 sint16 sx, sy; 1847 sint16 sx, sy;
1845 1848
1846 sx = op->x + freearr_x[dir]; 1849 sx = op->x + DIRX (dir);
1847 sy = op->y + freearr_y[dir]; 1850 sy = op->y + DIRY (dir);
1848 m = op->map; 1851 m = op->map;
1849 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); 1852 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
1850 if (mflags & P_OUT_OF_MAP) 1853 if (mflags & P_OUT_OF_MAP)
1851 return; 1854 return;
1852 1855
1865 1868
1866 /* don't attack our own spells */ 1869 /* don't attack our own spells */
1867 if (tmp->owner && tmp->owner == op->owner) 1870 if (tmp->owner && tmp->owner == op->owner)
1868 continue; 1871 continue;
1869 1872
1870 /* Basically, if the object is magical and not counterspell, 1873 /* Basically, if the object is magical and not counterspell,
1871 * we will more or less remove the object. Don't counterspell 1874 * we will more or less remove the object. Don't counterspell
1872 * monsters either. 1875 * monsters either.
1873 */ 1876 */
1874 1877
1875 if (head->attacktype & AT_MAGIC 1878 if (head->attacktype & AT_MAGIC
1876 && !(head->attacktype & AT_COUNTERSPELL) 1879 && !(head->attacktype & AT_COUNTERSPELL)
1877 && !QUERY_FLAG (head, FLAG_MONSTER) 1880 && !head->flag [FLAG_MONSTER]
1878 && (op->level > head->level)) 1881 && (op->level > head->level))
1879 head->destroy (); 1882 head->destroy ();
1880 else 1883 else
1881 switch (head->type) 1884 switch (head->type)
1882 { 1885 {
1883 case SPELL_EFFECT: 1886 case SPELL_EFFECT:
1884 // XXX: Don't affect floor spelleffects. See also XXX comment 1887 // XXX: Don't affect floor spelleffects. See also XXX comment
1885 // about sanctuary in spell_util.C 1888 // about sanctuary in spell_util.C
1886 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 1889 if (tmp->flag [FLAG_IS_FLOOR])
1887 continue; 1890 continue;
1888 1891
1889 if (op->level > head->level) 1892 if (op->level > head->level)
1890 head->destroy (); 1893 head->destroy ();
1891 1894
1904 break; 1907 break;
1905 } 1908 }
1906 } 1909 }
1907} 1910}
1908 1911
1909
1910
1911/* cast_consecrate() - a spell to make an altar your god's */ 1912/* cast_consecrate() - a spell to make an altar your god's */
1912int 1913int
1913cast_consecrate (object *op, object *caster, object *spell) 1914cast_consecrate (object *op, object *caster, object *spell)
1914{ 1915{
1915 char buf[MAX_BUF]; 1916 char buf[MAX_BUF];
1916 1917
1917 object *tmp, *god = find_god (determine_god (op)); 1918 object *tmp, *god = find_god (determine_god (op));
1918 1919
1919 if (!god) 1920 if (!god)
1920 { 1921 {
1921 new_draw_info (NDI_UNIQUE, 0, op, "You can't consecrate anything if you don't worship a god!"); 1922 op->failmsg ("You can't consecrate anything if you don't worship a god!");
1922 return 0; 1923 return 0;
1923 } 1924 }
1924 1925
1925 for (tmp = op->below; tmp; tmp = tmp->below) 1926 for (tmp = op->below; tmp; tmp = tmp->below)
1926 { 1927 {
1927 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 1928 if (tmp->flag [FLAG_IS_FLOOR])
1928 break; 1929 break;
1929 if (tmp->type == HOLY_ALTAR) 1930 if (tmp->type == HOLY_ALTAR)
1930 { 1931 {
1931 1932
1932 if (tmp->level > caster_level (caster, spell)) 1933 if (tmp->level > casting_level (caster, spell))
1933 { 1934 {
1934 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name); 1935 op->failmsgf ("You are not powerful enough to reconsecrate the %s", &tmp->name);
1935 return 0; 1936 return 0;
1936 } 1937 }
1937 else 1938 else
1938 { 1939 {
1939 /* If we got here, we are consecrating an altar */ 1940 /* If we got here, we are consecrating an altar */
1940 sprintf (buf, "Altar of %s", &god->name); 1941 sprintf (buf, "Altar of %s", &god->name);
1941 tmp->name = buf; 1942 tmp->name = buf;
1942 tmp->level = caster_level (caster, spell); 1943 tmp->level = casting_level (caster, spell);
1943 tmp->other_arch = god->arch; 1944 tmp->other_arch = god->arch;
1945
1944 if (op->type == PLAYER) 1946 if (op->type == PLAYER)
1945 esrv_update_item (UPD_NAME, op, tmp); 1947 esrv_update_item (UPD_NAME, op, tmp);
1948
1946 new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name); 1949 new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name);
1947 return 1; 1950 return 1;
1948 } 1951 }
1949 } 1952 }
1950 } 1953 }
1951 new_draw_info (NDI_UNIQUE, 0, op, "You are not standing over an altar!"); 1954
1955 op->failmsg ("You are not standing over an altar!");
1952 return 0; 1956 return 0;
1953} 1957}
1954 1958
1955/* animate_weapon - 1959/* animate_weapon -
1956 * Generalization of staff_to_snake. Makes a golem out of the caster's weapon. 1960 * Generalization of staff_to_snake. Makes a golem out of the caster's weapon.
1957 * The golem is based on the archetype specified, modified by the caster's level 1961 * The golem is based on the archetype specified, modified by the caster's level
1958 * and the attributes of the weapon. The weapon is inserted in the golem's 1962 * and the attributes of the weapon. The weapon is inserted in the golem's
1959 * inventory so that it falls to the ground when the golem dies. 1963 * inventory so that it falls to the ground when the golem dies.
1960 * This code was very odd - code early on would only let players use the spell, 1964 * This code was very odd - code early on would only let players use the spell,
1961 * yet the code wass full of player checks. I've presumed that the code 1965 * yet the code wass full of player checks. I've presumed that the code
1962 * that only let players use it was correct, and removed all the other 1966 * that only let players use it was correct, and removed all the other
1963 * player checks. MSW 2003-01-06 1967 * player checks. MSW 2003-01-06
1964 */ 1968 */
1965int 1969int
1966animate_weapon (object *op, object *caster, object *spell, int dir) 1970animate_weapon (object *op, object *caster, object *spell, int dir)
1967{ 1971{
1968 object *weapon, *tmp;
1969 char buf[MAX_BUF]; 1972 char buf[MAX_BUF];
1970 int a, i; 1973 int a, i;
1971 sint16 x, y; 1974 sint16 x, y;
1972 maptile *m; 1975 maptile *m;
1973 1976
1988 return 0; 1991 return 0;
1989 } 1992 }
1990 1993
1991 /* if no direction specified, pick one */ 1994 /* if no direction specified, pick one */
1992 if (!dir) 1995 if (!dir)
1993 dir = find_free_spot (NULL, op->map, op->x, op->y, 1, 9); 1996 dir = find_free_spot (spell->other_arch, op->map, op->x, op->y, 1, 9);
1994 1997
1995 m = op->map; 1998 m = op->map;
1996 x = op->x + freearr_x[dir]; 1999 x = op->x + DIRX (dir);
1997 y = op->y + freearr_y[dir]; 2000 y = op->y + DIRY (dir);
1998 2001
1999 /* if there's no place to put the golem, abort */ 2002 /* if there's no place to put the golem, abort */
2000 if ((dir == -1) || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP) || 2003 if (dir < 0 || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP)
2001 ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type)) 2004 || ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type))
2002 { 2005 {
2003 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); 2006 op->failmsg ("There is something in the way.");
2004 return 0; 2007 return 0;
2005 } 2008 }
2006 2009
2007 /* Use the weapon marked by the player. */ 2010 /* Use the weapon marked by the player. */
2008 weapon = find_marked_object (op); 2011 object *weapon = op->mark ();
2009 2012
2010 if (!weapon) 2013 if (!weapon)
2011 { 2014 {
2012 new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!"); 2015 op->failmsg ("You must mark a weapon to use with this spell!");
2013 return 0; 2016 return 0;
2014 } 2017 }
2018
2015 if (spell->race && strcmp (weapon->arch->archname, spell->race)) 2019 if (spell->race && weapon->arch->archname != spell->race)
2016 { 2020 {
2017 new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon."); 2021 op->failmsg ("The spell fails to transform your weapon.");
2018 return 0; 2022 return 0;
2019 } 2023 }
2024
2020 if (weapon->type != WEAPON) 2025 if (weapon->type != WEAPON)
2021 { 2026 {
2022 new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it."); 2027 op->failmsg ("You need to wield a weapon to animate it.");
2023 return 0; 2028 return 0;
2024 } 2029 }
2025 if (QUERY_FLAG (weapon, FLAG_APPLIED)) 2030
2031 if (weapon->flag [FLAG_APPLIED])
2026 { 2032 {
2027 new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon)); 2033 op->failmsgf ("You need to unequip %s before using it in this spell", query_name (weapon));
2028 return 0; 2034 return 0;
2029 } 2035 }
2030 2036
2031 if (weapon->nrof > 1) 2037 weapon = weapon->split ();
2032 {
2033 tmp = get_split_ob (weapon, 1);
2034 esrv_send_item (op, weapon);
2035 weapon = tmp;
2036 }
2037 2038
2038 /* create the golem object */ 2039 /* create the golem object */
2039 tmp = arch_to_object (spell->other_arch); 2040 object *tmp = spell->other_arch->instance ();
2040 2041
2041 /* if animated by a player, give the player control of the golem */ 2042 /* if animated by a player, give the player control of the golem */
2042 CLEAR_FLAG (tmp, FLAG_MONSTER); 2043 tmp->clr_flag (FLAG_MONSTER);
2043 tmp->stats.exp = 0; 2044 tmp->stats.exp = 0;
2044 add_friendly_object (tmp); 2045 add_friendly_object (tmp);
2045 tmp->type = GOLEM; 2046 tmp->type = GOLEM;
2046 tmp->set_owner (op); 2047 tmp->set_owner (op);
2047 op->contr->golem = tmp; 2048 op->contr->golem = tmp;
2048 set_spell_skill (op, caster, spell, tmp); 2049 set_spell_skill (op, caster, spell, tmp);
2049 2050
2050 /* Give the weapon to the golem now. A bit of a hack to check the 2051 /* Give the weapon to the golem now. A bit of a hack to check the
2051 * removed flag - it should only be set if get_split_object was 2052 * removed flag - it should only be set if weapon->split was
2052 * used above. 2053 * used above.
2053 */ 2054 */
2054 if (!QUERY_FLAG (weapon, FLAG_REMOVED)) 2055 if (!weapon->flag [FLAG_REMOVED])
2055 weapon->remove (); 2056 weapon->remove ();
2056 2057
2057 insert_ob_in_ob (weapon, tmp); 2058 tmp->insert (weapon);
2058 esrv_send_item (op, weapon); 2059
2059 /* To do everything necessary to let a golem use the weapon is a pain, 2060 /* To do everything necessary to let a golem use the weapon is a pain,
2060 * so instead, just set it as equipped (otherwise, we need to update 2061 * so instead, just set it as equipped (otherwise, we need to update
2061 * body_info, skills, etc) 2062 * body_info, skills, etc)
2062 */ 2063 */
2063 SET_FLAG (tmp, FLAG_USE_WEAPON); 2064 tmp->set_flag (FLAG_USE_WEAPON);
2064 SET_FLAG (weapon, FLAG_APPLIED); 2065 weapon->set_flag (FLAG_APPLIED);
2065 tmp->update_stats (); 2066 tmp->update_stats ();
2066 2067
2067 /* There used to be 'odd' code that basically seemed to take the absolute 2068 /* There used to be 'odd' code that basically seemed to take the absolute
2068 * value of the weapon->magic an use that. IMO, that doesn't make sense - 2069 * value of the weapon->magic an use that. IMO, that doesn't make sense -
2069 * if you're using a crappy weapon, it shouldn't be as good. 2070 * if you're using a crappy weapon, it shouldn't be as good.
2089 2090
2090 /* attacktype */ 2091 /* attacktype */
2091 if (!tmp->attacktype) 2092 if (!tmp->attacktype)
2092 tmp->attacktype = AT_PHYSICAL; 2093 tmp->attacktype = AT_PHYSICAL;
2093 2094
2094 if (materialtype_t *mt = name_to_material (op->materialname))
2095 {
2096 for (i = 0; i < NROFATTACKS; i++) 2095 for (i = 0; i < NROFATTACKS; i++)
2097 tmp->resist[i] = 50 - (mt->save[i] * 5); 2096 tmp->resist[i] = 50 - (op->material->save[i] * 5);
2098 a = mt->save[0]; 2097
2099 } 2098 a = op->material->save[0];
2100 else
2101 {
2102 for (i = 0; i < NROFATTACKS; i++)
2103 tmp->resist[i] = 5;
2104 a = 10;
2105 }
2106 2099
2107 /* Set weapon's immunity */ 2100 /* Set weapon's immunity */
2108 tmp->resist[ATNR_CONFUSION] = 100; 2101 tmp->resist[ATNR_CONFUSION] = 100;
2109 tmp->resist[ATNR_POISON] = 100; 2102 tmp->resist[ATNR_POISON] = 100;
2110 tmp->resist[ATNR_SLOW] = 100; 2103 tmp->resist[ATNR_SLOW] = 100;
2118 /* Improve weapon's armour value according to best save vs. physical of its material */ 2111 /* Improve weapon's armour value according to best save vs. physical of its material */
2119 2112
2120 if (a > 14) 2113 if (a > 14)
2121 a = 14; 2114 a = 14;
2122 2115
2123 tmp->resist[ATNR_PHYSICAL] = 100 - (int) ((100.0 - (float) tmp->resist[ATNR_PHYSICAL]) / (30.0 - 2.0 * a)); 2116 tmp->resist[ATNR_PHYSICAL] = 100 - (int) ((100.f - (float) tmp->resist[ATNR_PHYSICAL]) / (30.f - 2.f * a));
2124 2117
2125 /* Determine golem's speed */ 2118 /* Determine golem's speed */
2126 tmp->set_speed (min (3.33, 0.4 + 0.1 * SP_level_range_adjust (caster, spell))); 2119 tmp->set_speed (min (3.33f, 0.4f + 0.1f * SP_level_range_adjust (caster, spell)));
2127 2120
2128 if (!spell->race) 2121 if (!spell->race)
2129 { 2122 {
2130 sprintf (buf, "animated %s", &weapon->name); 2123 sprintf (buf, "animated %s", &weapon->name);
2131 tmp->name = buf; 2124 tmp->name = buf;
2137 tmp->state = weapon->state; 2130 tmp->state = weapon->state;
2138 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE]; 2131 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE];
2139 } 2132 }
2140 2133
2141 /* make experience increase in proportion to the strength of the summoned creature. */ 2134 /* make experience increase in proportion to the strength of the summoned creature. */
2142 tmp->stats.exp *= 1 + (MAX (spell->stats.maxgrace, spell->stats.sp) / caster_level (caster, spell)); 2135 tmp->stats.exp *= 1 + (max (spell->stats.maxgrace, spell->stats.sp) / casting_level (caster, spell));
2143 2136
2144 tmp->speed_left = -1; 2137 tmp->speed_left = -1;
2145 tmp->direction = dir; 2138 tmp->direction = dir;
2146 2139
2147 m->insert (tmp, x, y, op); 2140 m->insert (tmp, x, y, op);
2151/* cast_daylight() - changes the map darkness level *lower* */ 2144/* cast_daylight() - changes the map darkness level *lower* */
2152 2145
2153/* cast_change_map_lightlevel: Was cast_daylight/nightfall. 2146/* cast_change_map_lightlevel: Was cast_daylight/nightfall.
2154 * This changes the light level for the entire map. 2147 * This changes the light level for the entire map.
2155 */ 2148 */
2156
2157int 2149int
2158cast_change_map_lightlevel (object *op, object *caster, object *spell) 2150cast_change_map_lightlevel (object *op, object *caster, object *spell)
2159{ 2151{
2160 int success; 2152 int success;
2161 2153
2165 success = op->map->change_map_light (spell->stats.dam); 2157 success = op->map->change_map_light (spell->stats.dam);
2166 2158
2167 if (!success) 2159 if (!success)
2168 { 2160 {
2169 if (spell->stats.dam < 0) 2161 if (spell->stats.dam < 0)
2170 new_draw_info (NDI_UNIQUE, 0, op, "It can be no brighter here."); 2162 op->failmsg ("It can be no brighter here.");
2171 else 2163 else
2172 new_draw_info (NDI_UNIQUE, 0, op, "It can be no darker here."); 2164 op->failmsg ("It can be no darker here.");
2173 } 2165 }
2166
2174 return success; 2167 return success;
2175} 2168}
2176 2169
2177/* create an aura spell object and put it in the player's inventory. 2170/* create an aura spell object and put it in the player's inventory.
2178 * as usual, op is player, caster is the object casting the spell, 2171 * as usual, op is player, caster is the object casting the spell,
2186 2179
2187 new_aura = present_arch_in_ob (spell->other_arch, op); 2180 new_aura = present_arch_in_ob (spell->other_arch, op);
2188 if (new_aura) 2181 if (new_aura)
2189 refresh = 1; 2182 refresh = 1;
2190 else 2183 else
2191 new_aura = arch_to_object (spell->other_arch); 2184 new_aura = spell->other_arch->instance ();
2192 2185
2193 new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell); 2186 new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell);
2194 2187
2195 new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); 2188 new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
2196 2189
2197 set_spell_skill (op, caster, spell, new_aura); 2190 set_spell_skill (op, caster, spell, new_aura);
2198 new_aura->attacktype = spell->attacktype; 2191 new_aura->attacktype = spell->attacktype;
2199 2192
2200 new_aura->level = caster_level (caster, spell); 2193 new_aura->level = casting_level (caster, spell);
2201 2194
2202 if (refresh) 2195 if (refresh)
2203 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); 2196 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
2204 else 2197 else
2205 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force."); 2198 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
2212 2205
2213/* move aura function. An aura is a part of someone's inventory, 2206/* move aura function. An aura is a part of someone's inventory,
2214 * which he carries with him, but which acts on the map immediately 2207 * which he carries with him, but which acts on the map immediately
2215 * around him. 2208 * around him.
2216 * Aura parameters: 2209 * Aura parameters:
2217 * duration: duration counter. 2210 * duration: duration counter.
2218 * attacktype: aura's attacktype 2211 * attacktype: aura's attacktype
2219 * other_arch: archetype to drop where we attack 2212 * other_arch: archetype to drop where we attack
2220 */ 2213 */
2221void 2214void
2222move_aura (object *aura) 2215move_aura (object *aura)
2223{ 2216{
2224 /* auras belong in inventories */ 2217 /* auras belong in inventories */
2225 object *env = aura->env; 2218 object *env = aura->env;
2226 object *owner = aura->owner; 2219 object *owner = aura->owner;
2227 2220
2228 /* no matter what we've gotta remove the aura... 2221 /* no matter what we've gotta remove the aura...
2229 * we'll put it back if its time isn't up. 2222 * we'll put it back if its time isn't up.
2230 */ 2223 */
2231 aura->remove (); 2224 aura->remove ();
2232 2225
2233 /* exit if we're out of gas */ 2226 /* exit if we're out of gas */
2234 if (aura->duration-- < 0) 2227 if (aura->duration-- < 0)
2243 aura->destroy (); 2236 aura->destroy ();
2244 return; 2237 return;
2245 } 2238 }
2246 2239
2247 /* we need to jump out of the inventory for a bit 2240 /* we need to jump out of the inventory for a bit
2248 * in order to hit the map conveniently. 2241 * in order to hit the map conveniently.
2249 */ 2242 */
2250 aura->insert_at (env, aura); 2243 aura->insert_at (env, aura);
2251 2244
2252 for (int i = 1; i < 9; i++) 2245 for (int i = 1; i < 9; i++)
2253 { 2246 {
2261 if (pos.normalise () && !(OB_TYPE_MOVE_BLOCK (env, pos->move_block))) 2254 if (pos.normalise () && !(OB_TYPE_MOVE_BLOCK (env, pos->move_block)))
2262 { 2255 {
2263 hit_map (aura, i, aura->attacktype, 0); 2256 hit_map (aura, i, aura->attacktype, 0);
2264 2257
2265 if (aura->other_arch) 2258 if (aura->other_arch)
2266 pos.insert (arch_to_object (aura->other_arch), aura); 2259 pos.insert (aura->other_arch->instance (), aura);
2267 } 2260 }
2268 } 2261 }
2269 2262
2270 /* put the aura back in the player's inventory */ 2263 /* put the aura back in the player's inventory */
2271 env->insert (aura); 2264 env->insert (aura);
2276 * op is the piece object. 2269 * op is the piece object.
2277 */ 2270 */
2278void 2271void
2279move_peacemaker (object *op) 2272move_peacemaker (object *op)
2280{ 2273{
2281 object *tmp; 2274 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
2282
2283 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2284 { 2275 {
2285 int atk_lev, def_lev; 2276 int atk_lev, def_lev;
2286 object *victim = tmp; 2277 object *victim = tmp->head_ ();
2287 2278
2288 if (tmp->head) 2279 if (!victim->flag [FLAG_MONSTER])
2289 victim = tmp->head;
2290 if (!QUERY_FLAG (victim, FLAG_MONSTER))
2291 continue; 2280 continue;
2292 if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE)) 2281
2282 if (victim->flag [FLAG_UNAGGRESSIVE])
2293 continue; 2283 continue;
2284
2294 if (victim->stats.exp == 0) 2285 if (victim->stats.exp == 0)
2295 continue; 2286 continue;
2296 2287
2297 def_lev = MAX (1, victim->level); 2288 def_lev = max (1, victim->level);
2298 atk_lev = MAX (1, op->level); 2289 atk_lev = max (1, op->level);
2299 2290
2300 if (rndm (0, atk_lev - 1) > def_lev) 2291 if (rndm (0, atk_lev - 1) > def_lev)
2301 { 2292 {
2302 /* make this sucker peaceful. */ 2293 /* make this sucker peaceful. */
2303 2294
2295 INVOKE_OBJECT (KILL, victim, ARG_OBJECT (op));
2304 change_exp (op->owner, victim->stats.exp, op->skill, 0); 2296 change_exp (op->owner, victim->stats.exp, op->skill, 0);
2305 victim->stats.exp = 0; 2297 victim->stats.exp = 0;
2306#if 0 2298#if 0
2307 /* No idea why these were all set to zero - if something 2299 /* No idea why these were all set to zero - if something
2308 * makes this creature agressive, he should still do damage. 2300 * makes this creature agressive, he should still do damage.
2311 victim->stats.sp = 0; 2303 victim->stats.sp = 0;
2312 victim->stats.grace = 0; 2304 victim->stats.grace = 0;
2313 victim->stats.Pow = 0; 2305 victim->stats.Pow = 0;
2314#endif 2306#endif
2315 victim->attack_movement = RANDO2; 2307 victim->attack_movement = RANDO2;
2316 SET_FLAG (victim, FLAG_UNAGGRESSIVE); 2308 victim->set_flag (FLAG_UNAGGRESSIVE);
2317 SET_FLAG (victim, FLAG_RUN_AWAY); 2309 victim->set_flag (FLAG_RUN_AWAY);
2318 SET_FLAG (victim, FLAG_RANDOM_MOVE); 2310 victim->set_flag (FLAG_RANDOM_MOVE);
2319 CLEAR_FLAG (victim, FLAG_MONSTER); 2311 victim->clr_flag (FLAG_MONSTER);
2312
2320 if (victim->name) 2313 if (victim->name)
2321 {
2322 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name); 2314 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name);
2323 } 2315 }
2324 }
2325 } 2316 }
2326} 2317}
2327
2328 2318
2329/* This writes a rune that contains the appropriate message. 2319/* This writes a rune that contains the appropriate message.
2330 * There really isn't any adjustments we make. 2320 * There really isn't any adjustments we make.
2331 */ 2321 */
2332
2333int 2322int
2334write_mark (object *op, object *spell, const char *msg) 2323write_mark (object *op, object *spell, const char *msg)
2335{ 2324{
2336 char rune[HUGE_BUF];
2337 object *tmp;
2338
2339 if (!msg || msg[0] == 0) 2325 if (!msg || msg[0] == 0)
2340 { 2326 {
2341 new_draw_info (NDI_UNIQUE, 0, op, "Write what?"); 2327 op->failmsg ("Write what?");
2342 return 0; 2328 return 0;
2343 } 2329 }
2344 2330
2345 if (strcasestr_local (msg, "endmsg")) 2331 if (!msg_is_safe (msg))
2346 { 2332 {
2347 new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?"); 2333 op->failmsg ("Trying to cheat are we? H<@-signs are not allowed in marking runes.>");
2348 LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg); 2334 LOG (llevInfo, "write_mark: player %s tried to write bogus rune %s\n", &op->name, msg);
2349 return 0; 2335 return 0;
2350 } 2336 }
2337
2351 if (!spell->other_arch) 2338 if (!spell->other_arch)
2352 return 0; 2339 return 0;
2353 tmp = arch_to_object (spell->other_arch);
2354 2340
2355 snprintf (rune, sizeof (rune), "%s\n", msg); 2341 object *tmp = spell->other_arch->instance ();
2356 2342
2357 tmp->race = op->name; /*Save the owner of the rune */ 2343 tmp->race = op->name; /*Save the owner of the rune */
2358 tmp->msg = rune; 2344 tmp->msg = msg;
2359 2345
2360 tmp->insert_at (op, op, INS_BELOW_ORIGINATOR); 2346 tmp->insert_at (op, op, INS_BELOW_ORIGINATOR);
2347
2361 return 1; 2348 return 1;
2362} 2349}
2350

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines