ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
Revision: 1.26
Committed: Tue Dec 26 08:55:00 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.25: +5 -17 lines
Log Message:
replace update_ob_speed by ->set_speed

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