ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.29
Committed: Sat Dec 30 22:01:39 2006 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.28: +3 -2 lines
Log Message:
*** empty log message ***

File Contents

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