ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.22
Committed: Wed Dec 20 09:14:22 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.21: +9 -9 lines
Log Message:
- minor cleanups
- minor optimisations (in_player vs. is_player_inv)
- added P_PLAYER map flag
- some (dead) concept code

File Contents

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