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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines