ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.84
Committed: Tue Jul 8 08:33:27 2008 UTC (15 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_6, rel-2_61
Changes since 1.83: +8 -6 lines
Log Message:
fix crash, bdb 4.7

File Contents

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