ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.108
Committed: Fri Sep 18 03:38:29 2009 UTC (14 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.107: +20 -18 lines
Log Message:
*** empty log message ***

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