ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.34
Committed: Mon Jan 8 01:19:04 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.33: +0 -1 lines
Log Message:
more preperations for player eviction

File Contents

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