ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/spell_effect.C
(Generate patch)

Comparing deliantra/server/server/spell_effect.C (file contents):
Revision 1.76 by root, Sun Oct 21 04:16:22 2007 UTC vs.
Revision 1.107 by elmex, Thu Sep 17 16:53:15 2009 UTC

1/* 1/*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * 20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de> 21 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 22 */
23 23
24#include <global.h> 24#include <global.h>
25#include <object.h> 25#include <object.h>
26#include <living.h> 26#include <living.h>
61{ 61{
62 object *wand, *tmp; 62 object *wand, *tmp;
63 int ncharges; 63 int ncharges;
64 64
65 wand = find_marked_object (op); 65 wand = find_marked_object (op);
66 if (wand == NULL || wand->type != WAND) 66 if (!wand || wand->type != WAND)
67 { 67 {
68 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark the wand you want to recharge."); 68 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark the wand you want to recharge.");
69 return 0; 69 return 0;
70 } 70 }
71 if (!(random_roll (0, 3, op, PREFER_HIGH))) 71 if (!(random_roll (0, 3, op, PREFER_HIGH)))
72 { 72 {
73 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s vibrates violently, then explodes!", query_name (wand)); 73 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s vibrates violently, then explodes!", query_name (wand));
74 op->play_sound (sound_find ("ob_explode")); 74 op->play_sound (sound_find ("ob_explode"));
75 esrv_del_item (op->contr, wand->count);
76 wand->destroy (); 75 wand->destroy ();
77 tmp = get_archetype ("fireball"); 76 tmp = get_archetype ("fireball");
78 tmp->stats.dam = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob)) / 10; 77 tmp->stats.dam = (spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob)) / 10;
79 78
80 if (!tmp->stats.dam) 79 if (!tmp->stats.dam)
123 * The # of arrows created also goes up with level, so if a 30th level mage 122 * The # of arrows created also goes up with level, so if a 30th level mage
124 * wants LOTS of arrows, and doesn't care what the plus is he could 123 * wants LOTS of arrows, and doesn't care what the plus is he could
125 * create nonnmagic arrows, or even -1, etc... 124 * create nonnmagic arrows, or even -1, etc...
126 */ 125 */
127int 126int
128cast_create_missile (object *op, object *caster, object *spell, int dir, const char *stringarg) 127cast_create_missile (object *op, object *caster, object *spell, int dir, const char *spellparam)
129{ 128{
130 int bonus_plus = 0; 129 int bonus_plus = 0;
131 const char *missile_name = "arrow"; 130 const char *missile_name = "arrow";
132 131
133 for (object *tmp = op->inv; tmp; tmp = tmp->below) 132 for (object *tmp = op->inv; tmp; tmp = tmp->below)
144 return 0; 143 return 0;
145 } 144 }
146 145
147 object *missile = missile_arch->instance (); 146 object *missile = missile_arch->instance ();
148 147
149 if (stringarg) 148 if (spellparam)
150 { 149 {
151 /* If it starts with a letter, presume it is a description */ 150 /* If it starts with a letter, presume it is a description */
152 if (isalpha (*stringarg)) 151 if (isalpha (*spellparam))
153 { 152 {
154 artifact *al = find_artifactlist (missile->type)->items; 153 artifact *al = find_artifactlist (missile->type)->items;
155 154
156 for (; al; al = al->next) 155 for (; al; al = al->next)
157 if (!strcasecmp (al->item->name, stringarg)) 156 if (!strcasecmp (al->item->name, spellparam))
158 break; 157 break;
159 158
160 if (!al) 159 if (!al)
161 { 160 {
162 missile->destroy (); 161 missile->destroy ();
163 new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, stringarg); 162 new_draw_info_format (NDI_UNIQUE, 0, op, "No such object %ss of %s", missile_name, spellparam);
164 return 0; 163 return 0;
165 } 164 }
166 165
167 if (al->item->slaying) 166 if (al->item->slaying)
168 { 167 {
169 missile->destroy (); 168 missile->destroy ();
170 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, stringarg); 169 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not allowed to create %ss of %s", missile_name, spellparam);
171 return 0; 170 return 0;
172 } 171 }
173 172
174 give_artifact_abilities (missile, al->item); 173 give_artifact_abilities (missile, al->item);
175 /* These special arrows cost something extra. Don't have them also be magical - 174 /* These special arrows cost something extra. Don't have them also be magical -
177 * the parsing of having to do both plus and type. 176 * the parsing of having to do both plus and type.
178 */ 177 */
179 bonus_plus = 1 + (al->item->value / 5); 178 bonus_plus = 1 + (al->item->value / 5);
180 missile_plus = 0; 179 missile_plus = 0;
181 } 180 }
182 else if (atoi (stringarg) < missile_plus) 181 else if (atoi (spellparam) < missile_plus)
183 missile_plus = atoi (stringarg); 182 missile_plus = atoi (spellparam);
184 } 183 }
185 184
186 missile_plus = clamp (missile_plus, -4, 4); 185 missile_plus = clamp (missile_plus, -4, 4);
187 186
188 missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell); 187 missile->nrof = spell->duration + SP_level_duration_adjust (caster, spell);
203 return 1; 202 return 1;
204} 203}
205 204
206 205
207/* allows the choice of what sort of food object to make. 206/* allows the choice of what sort of food object to make.
208 * If stringarg is NULL, it will create food dependent on level --PeterM*/ 207 * If spellparam is NULL, it will create food dependent on level --PeterM*/
209int 208int
210cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *stringarg) 209cast_create_food (object *op, object *caster, object *spell_ob, int dir, const char *spellparam)
211{ 210{
212 int food_value; 211 int food_value;
213 archetype *at = NULL; 212 archetype *at = NULL;
214 object *new_op; 213 object *new_op;
215 214
216 food_value = spell_ob->stats.food + 50 * SP_level_duration_adjust (caster, spell_ob); 215 food_value = spell_ob->stats.food + 50 * SP_level_duration_adjust (caster, spell_ob);
217 216
218 if (stringarg) 217 if (spellparam)
219 { 218 {
220 at = find_archetype_by_object_type_name (FOOD, stringarg); 219 at = find_archetype_by_object_type_name (FOOD, spellparam);
221 if (at == NULL) 220 if (at == NULL)
222 at = find_archetype_by_object_type_name (DRINK, stringarg); 221 at = find_archetype_by_object_type_name (DRINK, spellparam);
223 if (at == NULL || at->stats.food > food_value) 222 if (at == NULL || at->stats.food > food_value)
224 stringarg = NULL; 223 spellparam = NULL;
225 } 224 }
226 225
227 if (!stringarg) 226 if (!spellparam)
228 { 227 {
229 archetype *at_tmp; 228 archetype *at_tmp;
230 229
231 /* We try to find the archetype with the maximum food value. 230 /* We try to find the archetype with the maximum food value.
232 * This removes the dependancy of hard coded food values in this 231 * This removes the dependancy of hard coded food values in this
280{ 279{
281 int r, mflags, maxrange; 280 int r, mflags, maxrange;
282 object *tmp; 281 object *tmp;
283 maptile *m; 282 maptile *m;
284 283
285
286 if (!dir) 284 if (!dir)
287 { 285 {
288 examine_monster (op, op); 286 examine_monster (op, op);
289 return 1; 287 return 1;
290 } 288 }
303 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (mflags & P_NO_MAGIC)) 301 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (mflags & P_NO_MAGIC))
304 { 302 {
305 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks your magic."); 303 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks your magic.");
306 return 0; 304 return 0;
307 } 305 }
306
308 if (mflags & P_IS_ALIVE) 307 if (mflags & P_IS_ALIVE)
309 { 308 {
310 for (tmp = GET_MAP_OB (m, x, y); tmp != NULL; tmp = tmp->above) 309 for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above)
311 if (QUERY_FLAG (tmp, FLAG_ALIVE) && (tmp->type == PLAYER || QUERY_FLAG (tmp, FLAG_MONSTER))) 310 if (QUERY_FLAG (tmp, FLAG_ALIVE) && (tmp->type == PLAYER || QUERY_FLAG (tmp, FLAG_MONSTER)))
312 { 311 {
313 new_draw_info (NDI_UNIQUE, 0, op, "You detect something."); 312 new_draw_info (NDI_UNIQUE, 0, op, "You detect something.");
314 if (tmp->head != NULL) 313 if (tmp->head != NULL)
315 tmp = tmp->head; 314 tmp = tmp->head;
346 345
347 return 1; 346 return 1;
348 } 347 }
349 348
350 /* invis_race is set if we get here */ 349 /* invis_race is set if we get here */
351 if (!strcmp (pl->contr->invis_race, "undead") && is_true_undead (mon)) 350 if (pl->contr->invis_race == shstr_undead && is_true_undead (mon))
352 return 1; 351 return 1;
353 352
354 /* No race, can't be invisible to it */ 353 /* No race, can't be invisible to it */
355 if (!mon->race) 354 if (!mon->race)
356 return 0; 355 return 0;
357 356
358 if (strstr (mon->race, pl->contr->invis_race)) 357 if (mon->race.contains (pl->contr->invis_race))
359 return 1; 358 return 1;
360 359
361 /* Nothing matched above, return 0 */ 360 /* Nothing matched above, return 0 */
362 return 0; 361 return 0;
363 } 362 }
426/* earth to dust spell. Basically destroys earthwalls in the area. 425/* earth to dust spell. Basically destroys earthwalls in the area.
427 */ 426 */
428int 427int
429cast_earth_to_dust (object *op, object *caster, object *spell_ob) 428cast_earth_to_dust (object *op, object *caster, object *spell_ob)
430{ 429{
431 object *tmp, *next;
432 int range, i, j, mflags; 430 int range, i, j, mflags;
433 sint16 sx, sy; 431 sint16 sx, sy;
434 maptile *m; 432 maptile *m;
435
436 if (op->type != PLAYER)
437 return 0;
438 433
439 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob); 434 range = spell_ob->range + SP_level_range_adjust (caster, spell_ob);
440 435
441 for (i = -range; i <= range; i++) 436 for (i = -range; i <= range; i++)
442 for (j = -range; j <= range; j++) 437 for (j = -range; j <= range; j++)
447 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy); 442 mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
448 443
449 if (mflags & P_OUT_OF_MAP) 444 if (mflags & P_OUT_OF_MAP)
450 continue; 445 continue;
451 446
452 // earth to dust tears down everything that can be teared down 447 // earth to dust tears down everything that can be torn down
453 for (tmp = GET_MAP_OB (m, sx, sy); tmp != NULL; tmp = next) 448 for (object *next, *tmp = m->at (sx, sy).bot; tmp; tmp = next)
454 { 449 {
455 next = tmp->above; 450 next = tmp->above;
451
456 if (QUERY_FLAG (tmp, FLAG_TEAR_DOWN)) 452 if (QUERY_FLAG (tmp, FLAG_TEAR_DOWN))
457 hit_player (tmp, 9998, op, AT_PHYSICAL, 0); 453 hit_player (tmp, 9998, op, AT_PHYSICAL, 0);
458 } 454 }
459 } 455 }
460 456
467 if (object *pl = op->in_player ()) 463 if (object *pl = op->in_player ())
468 { 464 {
469 if (pl->ms ().flags () & P_NO_CLERIC && !QUERY_FLAG (pl, FLAG_WIZCAST)) 465 if (pl->ms ().flags () & P_NO_CLERIC && !QUERY_FLAG (pl, FLAG_WIZCAST))
470 new_draw_info (NDI_UNIQUE, 0, pl, "You feel something fizzle inside you."); 466 new_draw_info (NDI_UNIQUE, 0, pl, "You feel something fizzle inside you.");
471 else 467 else
472 { 468 pl->player_goto (op->slaying, op->stats.hp, op->stats.sp);
473 // remove first so we do not call update_stats
474 op->remove ();
475 pl->enter_exit (op);
476 }
477 } 469 }
478 470
479 op->destroy (); 471 op->destroy ();
480} 472}
481 473
497 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you."); 489 new_draw_info (NDI_UNIQUE, 0, op, "You feel a force starting to build up inside you.");
498 return 1; 490 return 1;
499 } 491 }
500 492
501 dummy = get_archetype (FORCE_NAME); 493 dummy = get_archetype (FORCE_NAME);
502 if (dummy == NULL) 494
495 if (!dummy)
503 { 496 {
504 new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!"); 497 new_draw_info (NDI_UNIQUE, 0, op, "Oops, program error!");
505 LOG (llevError, "cast_word_of_recall: get_archetype(force) failed!\n"); 498 LOG (llevError, "cast_word_of_recall: get_archetype(force) failed!\n");
506 return 0; 499 return 0;
507 } 500 }
573perceive_self (object *op) 566perceive_self (object *op)
574{ 567{
575 const char *cp = describe_item (op, op); 568 const char *cp = describe_item (op, op);
576 archetype *at = archetype::find (ARCH_DEPLETION); 569 archetype *at = archetype::find (ARCH_DEPLETION);
577 570
578 dynbuf_text buf; 571 dynbuf_text &buf = msg_dynbuf; buf.clear ();
579 572
580 if (player *pl = op->contr) 573 if (!op->is_player ())
574 return 0;
575
581 if (object *race = archetype::find (op->race)) 576 if (object *race = archetype::find (op->race))
582 buf << "You are a " << (pl->gender ? "female" : "male") << " " << &race->name << ".\n"; 577 buf << " - You are a G<male|female> " << &race->name << ".\n";
583 578
584 if (object *god = find_god (determine_god (op))) 579 if (object *god = find_god (determine_god (op)))
585 buf << "You worship " << &god->name << ".\n"; 580 buf << " - You worship " << &god->name << ".\n";
586 else 581 else
587 buf << "You worship no god.\n"; 582 buf << " - You worship no god.\n";
588 583
589 object *tmp = present_arch_in_ob (at, op); 584 object *tmp = present_arch_in_ob (at, op);
590 585
591 if (*cp == '\0' && tmp == NULL) 586 if (*cp == '\0' && !tmp)
592 buf << "You feel very mundane. "; 587 buf << " - You feel very mundane. ";
593 else 588 else
594 { 589 {
595 buf << "You have: " << cp << ".\n"; 590 buf << " - You have: " << cp << ".\n";
596 591
597 if (tmp) 592 if (tmp)
598 for (int i = 0; i < NUM_STATS; i++) 593 for (int i = 0; i < NUM_STATS; i++)
599 if (tmp->stats.stat (i) < 0) 594 if (tmp->stats.stat (i) < 0)
600 buf.printf ("Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i)); 595 buf.printf (" - Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i));
601 } 596 }
602 597
603 if (is_dragon_pl (op)) 598 if (is_dragon_pl (op))
604 /* now grab the 'dragon_ability'-force from the player's inventory */ 599 /* now grab the 'dragon_ability'-force from the player's inventory */
605 for (tmp = op->inv; tmp; tmp = tmp->below) 600 for (tmp = op->inv; tmp; tmp = tmp->below)
606 { 601 {
607 if (tmp->type == FORCE && tmp->arch->archname == shstr_dragon_ability_force) 602 if (tmp->type == FORCE && tmp->arch->archname == shstr_dragon_ability_force)
608 { 603 {
609 if (tmp->stats.exp == 0) 604 if (tmp->stats.exp == 0)
610 buf << "Your metabolism isn't focused on anything.\n"; 605 buf << " - Your metabolism isn't focused on anything.\n";
611 else 606 else
612 buf << "Your metabolism is focused on " << change_resist_msg[tmp->stats.exp] << ".\n"; 607 buf << " - Your metabolism is focused on " << change_resist_msg[tmp->stats.exp] << ".\n";
613 608
614 break; 609 break;
615 } 610 }
616 } 611 }
617 612
618 buf << '\0'; // zero-terminate 613 op->contr->infobox (MSG_CHANNEL ("perceiveself"), buf);
619
620 new_draw_info (NDI_UNIQUE, 0, op, buf.linearise ());
621 614
622 return 1; 615 return 1;
623} 616}
624 617
625/* This creates magic walls. Really, it can create most any object, 618/* This creates magic walls. Really, it can create most any object,
713 */ 706 */
714 if (tmp->type != EARTHWALL) //TODO 707 if (tmp->type != EARTHWALL) //TODO
715 tmp->set_owner (op); 708 tmp->set_owner (op);
716 709
717 set_spell_skill (op, caster, spell_ob, tmp); 710 set_spell_skill (op, caster, spell_ob, tmp);
718 tmp->level = caster_level (caster, spell_ob) / 2; 711 tmp->level = casting_level (caster, spell_ob) / 2;
719 712
720 name = tmp->name; 713 name = tmp->name;
721 if (!(tmp = m->insert (tmp, x, y, op))) 714 if (!(tmp = m->insert (tmp, x, y, op)))
722 { 715 {
723 new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name); 716 new_draw_info_format (NDI_UNIQUE, 0, op, "Something destroys your %s", name);
784 777
785 return 1; 778 return 1;
786} 779}
787 780
788int 781int
789dimension_door (object *op, object *caster, object *spob, int dir) 782dimension_door (object *op, object *caster, object *spob, int dir, const char *spellparam)
790{ 783{
791 uint32 dist, maxdist; 784 uint32 dist, maxdist;
792 int mflags; 785 int mflags;
793 maptile *m; 786 maptile *m;
794 sint16 sx, sy; 787 sint16 sx, sy;
805 /* Given the new outdoor maps, can't let players dimension door for 798 /* Given the new outdoor maps, can't let players dimension door for
806 * ever, so put limits in. 799 * ever, so put limits in.
807 */ 800 */
808 maxdist = spob->range + SP_level_range_adjust (caster, spob); 801 maxdist = spob->range + SP_level_range_adjust (caster, spob);
809 802
810 if (op->contr->count) 803 if (spellparam)
811 { 804 {
805 int count = atoi (spellparam);
806
812 if (op->contr->count > maxdist) 807 if (count > maxdist)
813 { 808 {
814 new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!"); 809 new_draw_info (NDI_UNIQUE, 0, op, "You can't dimension door that far!");
815 return 0; 810 return 0;
816 } 811 }
817 812
818 for (dist = 0; dist < op->contr->count; dist++) 813 for (dist = 0; dist < count; dist++)
819 { 814 {
820 mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy); 815 mflags = get_map_flags (op->map, &m, op->x + freearr_x[dir] * (dist + 1), op->y + freearr_y[dir] * (dist + 1), &sx, &sy);
821 816
822 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP)) 817 if (mflags & (P_NO_MAGIC | P_OUT_OF_MAP))
823 break; 818 break;
824 819
825 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy))) 820 if ((mflags & P_BLOCKSVIEW) && OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, sx, sy)))
826 break; 821 break;
827 } 822 }
828 823
829 if (dist < op->contr->count) 824 if (dist < count)
830 { 825 {
831 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n"); 826 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the spell.\n");
832 op->contr->count = 0;
833 return 0; 827 return 0;
834 } 828 }
835
836 op->contr->count = 0;
837 829
838 /* Remove code that puts player on random space on maps. IMO, 830 /* Remove code that puts player on random space on maps. IMO,
839 * a lot of maps probably have areas the player should not get to, 831 * a lot of maps probably have areas the player should not get to,
840 * but may not be marked as NO_MAGIC (as they may be bounded 832 * but may not be marked as NO_MAGIC (as they may be bounded
841 * by such squares). Also, there are probably treasure rooms and 833 * by such squares). Also, there are probably treasure rooms and
1038 "You don't feel any more powerful." 1030 "You don't feel any more powerful."
1039 "You are no easier to look at.", 1031 "You are no easier to look at.",
1040}; 1032};
1041 1033
1042int 1034int
1035change_ability_duration (object *spell, object *caster)
1036{
1037 return spell->duration + SP_level_duration_adjust (caster, spell) * 50;
1038}
1039
1040int
1043cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent) 1041cast_change_ability (object *op, object *caster, object *spell_ob, int dir, int silent)
1044{ 1042{
1045 object *force = NULL; 1043 object *force = 0;
1046 int i; 1044 int i;
1047 1045
1048 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */ 1046 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1049 object *tmp = dir 1047 object *tmp = dir
1050 ? find_target_for_friendly_spell (op, dir) 1048 ? find_target_for_friendly_spell (op, dir)
1051 : op; 1049 : op;
1052 1050
1053 if (!tmp) 1051 if (!tmp)
1054 return 0; 1052 return 0;
1055 1053
1056 /* If we've already got a force of this type, don't add a new one. */ 1054 /* If we've already got a force of this type, don't add a new one. */
1065 } 1063 }
1066 else if (spell_ob->race && spell_ob->race == tmp2->name) 1064 else if (spell_ob->race && spell_ob->race == tmp2->name)
1067 { 1065 {
1068 if (!silent) 1066 if (!silent)
1069 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl); 1067 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1068
1070 return 0; 1069 return 0;
1071 } 1070 }
1072 } 1071 }
1073 } 1072 }
1074 if (force == NULL) 1073
1074 if (!force)
1075 { 1075 {
1076 force = get_archetype (FORCE_NAME); 1076 force = get_archetype (FORCE_NAME);
1077 force->subtype = FORCE_CHANGE_ABILITY; 1077 force->subtype = FORCE_CHANGE_ABILITY;
1078
1078 if (spell_ob->race) 1079 if (spell_ob->race)
1079 force->name = spell_ob->race; 1080 force->name = spell_ob->race;
1080 else 1081 else
1081 force->name = spell_ob->name; 1082 force->name = spell_ob->name;
1083
1082 force->name_pl = spell_ob->name; 1084 force->name_pl = spell_ob->name;
1083 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force."); 1085 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
1084 1086
1085 } 1087 }
1086 else 1088 else
1087 { 1089 {
1088 int duration; 1090 int duration = change_ability_duration (spell_ob, caster);
1089 1091
1090 duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1091 if (duration > force->duration) 1092 if (duration > force->duration)
1092 { 1093 {
1093 force->duration = duration; 1094 force->duration = duration;
1094 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); 1095 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
1095 } 1096 }
1096 else 1097 else
1097 {
1098 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect."); 1098 new_draw_info (NDI_UNIQUE, 0, op, "Recasting the spell had no effect.");
1099 }
1100 1099
1101 return 1; 1100 return 1;
1102 } 1101 }
1103 1102
1104 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50; 1103 force->duration = spell_ob->duration + SP_level_duration_adjust (caster, spell_ob) * 50;
1176 */ 1175 */
1177int 1176int
1178cast_bless (object *op, object *caster, object *spell_ob, int dir) 1177cast_bless (object *op, object *caster, object *spell_ob, int dir)
1179{ 1178{
1180 int i; 1179 int i;
1181 object *god = find_god (determine_god (op)), *tmp2, *force = NULL, *tmp; 1180 object *god = find_god (determine_god (op)), *force = NULL, *tmp;
1182 1181
1183 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */ 1182 /* if dir = 99 op defaults to tmp, eat_special_food() requires this. */
1184 if (dir != 0) 1183 if (dir != 0)
1185 { 1184 {
1186 tmp = find_target_for_friendly_spell (op, dir); 1185 tmp = find_target_for_friendly_spell (op, dir);
1186
1187 if (!tmp)
1188 return 0;
1187 } 1189 }
1188 else 1190 else
1189 {
1190 tmp = op; 1191 tmp = op;
1191 }
1192 1192
1193 /* If we've already got a force of this type, don't add a new one. */ 1193 /* If we've already got a force of this type, don't add a new one. */
1194 for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below) 1194 for (object *tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1195 { 1195 {
1196 if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY) 1196 if (tmp2->type == FORCE && tmp2->subtype == FORCE_CHANGE_ABILITY)
1197 { 1197 {
1198 if (tmp2->name == spell_ob->name) 1198 if (tmp2->name == spell_ob->name)
1199 { 1199 {
1205 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl); 1205 new_draw_info_format (NDI_UNIQUE, 0, op, "You can not cast %s while %s is in effect", &spell_ob->name, &tmp2->name_pl);
1206 return 0; 1206 return 0;
1207 } 1207 }
1208 } 1208 }
1209 } 1209 }
1210
1210 if (force == NULL) 1211 if (force == NULL)
1211 { 1212 {
1212 force = get_archetype (FORCE_NAME); 1213 force = get_archetype (FORCE_NAME);
1213 force->subtype = FORCE_CHANGE_ABILITY; 1214 force->subtype = FORCE_CHANGE_ABILITY;
1214 if (spell_ob->race) 1215 if (spell_ob->race)
1412 1413
1413bailout: 1414bailout:
1414 return 1; 1415 return 1;
1415} 1416}
1416 1417
1417
1418/* This function removes the cursed/damned status on equipped 1418/* This function removes the cursed/damned status on equipped
1419 * items. 1419 * items.
1420 */ 1420 */
1421int 1421int
1422remove_curse (object *op, object *caster, object *spell) 1422remove_curse (object *op, object *caster, object *spell)
1423{ 1423{
1424 object *tmp;
1425 int success = 0, was_one = 0; 1424 int success = 0, was_one = 0;
1426 1425
1427 for (tmp = op->inv; tmp; tmp = tmp->below) 1426 for (object *tmp = op->inv; tmp; tmp = tmp->below)
1428 if (QUERY_FLAG (tmp, FLAG_APPLIED) && 1427 if (QUERY_FLAG (tmp, FLAG_APPLIED) &&
1429 ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) || 1428 ((QUERY_FLAG (tmp, FLAG_CURSED) && QUERY_FLAG (spell, FLAG_CURSED)) ||
1430 (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED)))) 1429 (QUERY_FLAG (tmp, FLAG_DAMNED) && QUERY_FLAG (spell, FLAG_DAMNED))))
1431 { 1430 {
1432 was_one++; 1431 was_one++;
1432
1433 if (tmp->level <= caster_level (caster, spell)) 1433 if (tmp->level <= casting_level (caster, spell))
1434 { 1434 {
1435 success++; 1435 success++;
1436 if (QUERY_FLAG (spell, FLAG_DAMNED)) 1436 if (QUERY_FLAG (spell, FLAG_DAMNED))
1437 CLEAR_FLAG (tmp, FLAG_DAMNED); 1437 CLEAR_FLAG (tmp, FLAG_DAMNED);
1438 1438
1439 CLEAR_FLAG (tmp, FLAG_CURSED); 1439 CLEAR_FLAG (tmp, FLAG_CURSED);
1440 CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED); 1440 CLEAR_FLAG (tmp, FLAG_KNOWN_CURSED);
1441 tmp->value = 0; /* Still can't sell it */ 1441 tmp->value = 0; /* Still can't sell it */
1442 if (op->type == PLAYER) 1442
1443 if (object *pl = tmp->visible_to ())
1443 esrv_send_item (op, tmp); 1444 esrv_update_item (UPD_FLAGS, pl, tmp);
1444 } 1445 }
1445 } 1446 }
1446 1447
1447 if (op->type == PLAYER) 1448 if (op->type == PLAYER)
1448 { 1449 {
1462 1463
1463/* Identifies objects in the players inventory/on the ground */ 1464/* Identifies objects in the players inventory/on the ground */
1464int 1465int
1465cast_identify (object *op, object *caster, object *spell) 1466cast_identify (object *op, object *caster, object *spell)
1466{ 1467{
1467 dynbuf_text buf;
1468 object *tmp; 1468 object *tmp;
1469 dynbuf_text &buf = msg_dynbuf; buf.clear ();
1469 1470
1470 int num_ident = spell->stats.dam + SP_level_dam_adjust (caster, spell); 1471 int num_ident = max (1, spell->stats.dam + SP_level_dam_adjust (caster, spell));
1471
1472 if (num_ident < 1)
1473 num_ident = 1;
1474 1472
1475 for (tmp = op->inv; tmp; tmp = tmp->below) 1473 for (tmp = op->inv; tmp; tmp = tmp->below)
1476 { 1474 {
1477 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp)) 1475 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1478 { 1476 {
1479 identify (tmp); 1477 identify (tmp);
1480 1478
1481 if (op->type == PLAYER) 1479 if (op->type == PLAYER)
1482 { 1480 {
1483 buf.printf ("You identified: %s.\n\n", long_desc (tmp, op)); 1481 buf.printf ("You identified: %s.\r", long_desc (tmp, op));
1484 1482
1485 if (tmp->msg) 1483 if (tmp->msg)
1486 buf << "The item has a story:\n\n" << tmp->msg << "\n\n"; 1484 buf << "The item has a story:\r" << tmp->msg << "\n\n";
1487 } 1485 }
1488 1486
1489 num_ident--;
1490 if (!num_ident) 1487 if (!--num_ident)
1491 break; 1488 break;
1492 } 1489 }
1493 } 1490 }
1494 1491
1495 /* If all the power of the spell has been used up, don't go and identify 1492 /* If all the power of the spell has been used up, don't go and identify
1501 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above) 1498 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
1502 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp)) 1499 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !tmp->invisible && need_identify (tmp))
1503 { 1500 {
1504 identify (tmp); 1501 identify (tmp);
1505 1502
1506 if (op->type == PLAYER) 1503 if (object *pl = tmp->visible_to ())
1507 { 1504 {
1508 buf.printf ("On the ground you identified: %s.\n\n", long_desc (tmp, op)); 1505 buf.printf ("On the ground you identified: %s.\r", long_desc (tmp, op));
1509 1506
1510 if (tmp->msg) 1507 if (tmp->msg)
1511 buf << "The item has a story:\n\n" << tmp->msg << "\n\n"; 1508 buf << "The item has a story:\r" << tmp->msg << "\n\n";
1512
1513 esrv_send_item (op, tmp);
1514 } 1509 }
1515 1510
1516 num_ident--;
1517 if (!num_ident) 1511 if (!--num_ident)
1518 break; 1512 break;
1519 } 1513 }
1520 } 1514 }
1521 1515
1522 if (buf.empty ()) 1516 if (buf.empty ())
1544 1538
1545 /* We precompute some values here so that we don't have to keep 1539 /* We precompute some values here so that we don't have to keep
1546 * doing it over and over again. 1540 * doing it over and over again.
1547 */ 1541 */
1548 god = find_god (determine_god (op)); 1542 god = find_god (determine_god (op));
1549 level = caster_level (caster, spell); 1543 level = casting_level (caster, spell);
1550 range = spell->range + SP_level_range_adjust (caster, spell); 1544 range = spell->range + SP_level_range_adjust (caster, spell);
1551 1545
1552 if (!skill) 1546 if (!skill)
1553 skill = caster; 1547 skill = caster;
1554 1548
1555 for (x = op->x - range; x <= op->x + range; x++) 1549 unordered_mapwalk (op, -range, -range, range, range)
1556 for (y = op->y - range; y <= op->y + range; y++)
1557 { 1550 {
1558 m = op->map;
1559 mflags = get_map_flags (m, &m, x, y, &nx, &ny);
1560 if (mflags & P_OUT_OF_MAP)
1561 continue;
1562
1563 /* For most of the detections, we only detect objects above the 1551 /* For most of the detections, we only detect objects above the
1564 * floor. But this is not true for show invisible. 1552 * floor. But this is not true for show invisible.
1565 * Basically, we just go and find the top object and work 1553 * Basically, we just go and find the top object and work
1566 * down - that is easier than working up. 1554 * down - that is easier than working up.
1567 */ 1555 */
1568 1556
1569 for (last = NULL, tmp = GET_MAP_OB (m, nx, ny); tmp; tmp = tmp->above) 1557 for (last = NULL, tmp = m->at (nx, ny).bot; tmp; tmp = tmp->above)
1570 last = tmp; 1558 last = tmp;
1571 1559
1572 /* Shouldn't happen, but if there are no objects on a space, this 1560 /* Shouldn't happen, but if there are no objects on a space, this
1573 * would happen. 1561 * would happen.
1574 */ 1562 */
1575 if (!last) 1563 if (!last)
1576 continue; 1564 continue;
1577 1565
1578 done_one = 0; 1566 done_one = 0;
1579 floor = 0; 1567 floor = 0;
1580 detect = NULL; 1568 detect = NULL;
1581 for (tmp = last; tmp; tmp = tmp->below) 1569 for (tmp = last; tmp; tmp = tmp->below)
1582 { 1570 {
1583 /* show invisible */ 1571 /* show invisible */
1584 if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) && 1572 if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) &&
1585 /* Might there be other objects that we can make visible? */ 1573 /* Might there be other objects that we can make visible? */
1586 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) || 1574 (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER)
1587 (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) || 1575 || (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ))
1588 tmp->type == CF_HANDLE || 1576 || tmp->type == CF_HANDLE
1589 tmp->type == TRAPDOOR || tmp->type == EXIT || tmp->type == HOLE || 1577 || tmp->type == TRAPDOOR
1578 || tmp->type == EXIT
1579 || tmp->type == HOLE
1580 || tmp->type == BUTTON
1590 tmp->type == BUTTON || tmp->type == TELEPORTER || 1581 || tmp->type == TELEPORTER
1582 || tmp->type == GATE
1591 tmp->type == GATE || tmp->type == LOCKED_DOOR || 1583 || tmp->type == LOCKED_DOOR
1592 tmp->type == WEAPON || tmp->type == ALTAR || tmp->type == SIGN || 1584 || tmp->type == WEAPON
1585 || tmp->type == ALTAR
1586 || tmp->type == SIGN
1593 tmp->type == TRIGGER_PEDESTAL || tmp->type == SPECIAL_KEY || 1587 || tmp->type == TRIGGER_PEDESTAL
1594 tmp->type == TREASURE || tmp->type == BOOK || tmp->type == HOLY_ALTAR))) 1588 || tmp->type == SPECIAL_KEY
1589 || tmp->type == TREASURE
1590 || tmp->type == BOOK
1591 || tmp->type == HOLY_ALTAR
1592 || tmp->type == CONTAINER)))
1595 { 1593 {
1596 if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4) 1594 if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4)
1597 { 1595 {
1598 tmp->invisible = 0; 1596 tmp->invisible = 0;
1599 done_one = 1; 1597 done_one = 1;
1600 } 1598 }
1601 } 1599 }
1602 1600
1603 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 1601 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1604 floor = 1; 1602 floor = 1;
1605 1603
1606 /* All detections below this point don't descend beneath the floor, 1604 /* All detections below this point don't descend beneath the floor,
1607 * so just continue on. We could be clever and look at the type of 1605 * so just continue on. We could be clever and look at the type of
1608 * detection to completely break out if we don't care about objects beneath 1606 * detection to completely break out if we don't care about objects beneath
1609 * the floor, but once we get to the floor, not likely a very big issue anyways. 1607 * the floor, but once we get to the floor, not likely a very big issue anyways.
1610 */ 1608 */
1611 if (floor) 1609 if (floor)
1612 continue; 1610 continue;
1613 1611
1614 /* I had thought about making detect magic and detect curse 1612 /* I had thought about making detect magic and detect curse
1615 * show the flash the magic item like it does for detect monster. 1613 * show the flash the magic item like it does for detect monster.
1616 * however, if the object is within sight, this would then make it 1614 * however, if the object is within sight, this would then make it
1617 * difficult to see what object is magical/cursed, so the 1615 * difficult to see what object is magical/cursed, so the
1618 * effect wouldn't be as apparant. 1616 * effect wouldn't be as apparent.
1619 */ 1617 */
1620 1618
1621 /* detect magic */ 1619 /* detect magic */
1622 if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && 1620 if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) &&
1623 !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp)) 1621 !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp))
1624 { 1622 {
1625 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); 1623 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1626 /* make runes more visibile */ 1624 /* make runes more visibile */
1627 if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC) 1625 if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC)
1628 tmp->stats.Cha /= 4; 1626 tmp->stats.Cha /= 4;
1627
1629 done_one = 1; 1628 done_one = 1;
1630 } 1629 }
1630
1631 /* detect monster */ 1631 /* detect monster */
1632 if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER)) 1632 if (QUERY_FLAG (spell, FLAG_MONSTER) && (QUERY_FLAG (tmp, FLAG_MONSTER) || tmp->type == PLAYER))
1633 { 1633 {
1634 done_one = 2; 1634 done_one = 2;
1635
1635 if (!detect) 1636 if (!detect)
1636 detect = tmp; 1637 detect = tmp;
1637 } 1638 }
1639
1638 /* Basically, if race is set in the spell, then the creatures race must 1640 /* Basically, if race is set in the spell, then the creatures race must
1639 * match that. if the spell race is set to GOD, then the gods opposing 1641 * match that. if the spell race is set to GOD, then the gods opposing
1640 * race must match. 1642 * race must match.
1641 */ 1643 */
1642 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race && 1644 if (spell->race && QUERY_FLAG (tmp, FLAG_MONSTER) && tmp->race &&
1643 ((!strcmp (spell->race, "GOD") && god && god->slaying && strstr (god->slaying, tmp->race)) || 1645 ((spell->race == shstr_GOD && god && god->slaying.contains (tmp->race)) ||
1644 (strstr (spell->race, tmp->race)))) 1646 spell->race.contains (tmp->race)))
1645 { 1647 {
1646 done_one = 2; 1648 done_one = 2;
1649
1647 if (!detect) 1650 if (!detect)
1648 detect = tmp; 1651 detect = tmp;
1649 } 1652 }
1653
1650 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) && 1654 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1651 (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) 1655 (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1652 { 1656 {
1653 SET_FLAG (tmp, FLAG_KNOWN_CURSED); 1657 SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1654 done_one = 1; 1658 done_one = 1;
1655 } 1659 }
1656 } /* for stack of objects on this space */ 1660 } /* for stack of objects on this space */
1657 1661
1658 /* Code here puts an effect of the spell on the space, so you can see 1662 /* Code here puts an effect of the spell on the space, so you can see
1659 * where the magic is. 1663 * where the magic is.
1660 */ 1664 */
1661 if (done_one) 1665 if (done_one)
1662 { 1666 {
1663 object *detect_ob = arch_to_object (spell->other_arch); 1667 object *detect_ob = arch_to_object (spell->other_arch);
1664 1668
1665 /* if this is set, we want to copy the face */ 1669 /* if this is set, we want to copy the face */
1666 if (done_one == 2 && detect) 1670 if (done_one == 2 && detect)
1667 { 1671 {
1668 detect_ob->face = detect->face; 1672 detect_ob->face = detect->face;
1669 detect_ob->animation_id = detect->animation_id; 1673 detect_ob->animation_id = detect->animation_id;
1670 detect_ob->anim_speed = detect->anim_speed; 1674 detect_ob->anim_speed = detect->anim_speed;
1671 detect_ob->last_anim = 0; 1675 detect_ob->last_anim = 0;
1672 /* by default, the detect_ob is already animated */ 1676 /* by default, the detect_ob is already animated */
1673 if (!QUERY_FLAG (detect, FLAG_ANIMATE)) 1677 if (!QUERY_FLAG (detect, FLAG_ANIMATE))
1674 CLEAR_FLAG (detect_ob, FLAG_ANIMATE); 1678 CLEAR_FLAG (detect_ob, FLAG_ANIMATE);
1675 } 1679 }
1676 1680
1677 m->insert (detect_ob, nx, ny, op); 1681 m->insert (detect_ob, nx, ny, op);
1678 } 1682 }
1679 } /* for processing the surrounding spaces */ 1683 } /* for processing the surrounding spaces */
1680 1684
1681 1685
1682 /* Now process objects in the players inventory if detect curse or magic */ 1686 /* Now process objects in the players inventory if detect curse or magic */
1683 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL)) 1687 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) || QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL))
1684 { 1688 {
1685 done_one = 0; 1689 done_one = 0;
1690
1686 for (tmp = op->inv; tmp; tmp = tmp->below) 1691 for (tmp = op->inv; tmp; tmp = tmp->below)
1687 { 1692 {
1688 if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 1693 if (!tmp->invisible && !QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1689 { 1694 {
1690 if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL)) 1695 if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && is_magical (tmp) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL))
1691 { 1696 {
1692 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); 1697 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
1693 if (op->type == PLAYER) 1698
1699 if (object *pl = tmp->visible_to ())
1694 esrv_send_item (op, tmp); 1700 esrv_update_item (UPD_FLAGS, pl, tmp);
1695 } 1701 }
1702
1696 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) && 1703 if (QUERY_FLAG (spell, FLAG_KNOWN_CURSED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) &&
1697 (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) 1704 (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)))
1698 { 1705 {
1699 SET_FLAG (tmp, FLAG_KNOWN_CURSED); 1706 SET_FLAG (tmp, FLAG_KNOWN_CURSED);
1700 if (op->type == PLAYER) 1707
1708 if (object *pl = tmp->visible_to ())
1701 esrv_send_item (op, tmp); 1709 esrv_update_item (UPD_FLAGS, pl, tmp);
1702 } 1710 }
1703 } /* if item is not identified */ 1711 } /* if item is not identified */
1704 } /* for the players inventory */ 1712 } /* for the players inventory */
1705 } /* if detect magic/curse and object is a player */ 1713 } /* if detect magic/curse and object is a player */
1714
1706 return 1; 1715 return 1;
1707} 1716}
1708 1717
1709 1718
1710/** 1719/**
1723 1732
1724 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you."); 1733 new_draw_info (NDI_UNIQUE, 0, victim, "You feel energy course through you.");
1725 1734
1726 if (victim->stats.sp >= victim->stats.maxsp * 2) 1735 if (victim->stats.sp >= victim->stats.maxsp * 2)
1727 { 1736 {
1728 object *tmp;
1729
1730 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!"); 1737 new_draw_info (NDI_UNIQUE, 0, victim, "Your head explodes!");
1731
1732 /* Explodes a fireball centered at player */
1733 tmp = get_archetype (EXPLODING_FIREBALL);
1734 tmp->dam_modifier = random_roll (1, caster_level, victim, PREFER_LOW) / 5 + 1;
1735 tmp->stats.maxhp = random_roll (1, caster_level, victim, PREFER_LOW) / 10 + 2;
1736
1737 tmp->insert_at (victim);
1738 victim->stats.sp = 2 * victim->stats.maxsp; 1738 victim->stats.sp = 2 * victim->stats.maxsp;
1739 create_exploding_ball_at (victim, caster_level);
1739 } 1740 }
1740 else if (victim->stats.sp >= victim->stats.maxsp * 1.88) 1741 else if (victim->stats.sp >= victim->stats.maxsp * 1.88)
1741 new_draw_info (NDI_UNIQUE, NDI_ORANGE, victim, "You feel like your head is going to explode."); 1742 new_draw_info (NDI_UNIQUE | NDI_ORANGE, 0, victim, "You feel like your head is going to explode.");
1742 else if (victim->stats.sp >= victim->stats.maxsp * 1.66) 1743 else if (victim->stats.sp >= victim->stats.maxsp * 1.66)
1743 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!"); 1744 new_draw_info (NDI_UNIQUE, 0, victim, "You get a splitting headache!");
1744 else if (victim->stats.sp >= victim->stats.maxsp * 1.5) 1745 else if (victim->stats.sp >= victim->stats.maxsp * 1.5)
1745 { 1746 {
1746 new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world."); 1747 new_draw_info (NDI_UNIQUE, 0, victim, "Chaos fills your world.");
1792 } 1793 }
1793 /* give sp */ 1794 /* give sp */
1794 if (spell->stats.dam > 0) 1795 if (spell->stats.dam > 0)
1795 { 1796 {
1796 plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell); 1797 plyr->stats.sp += spell->stats.dam + SP_level_dam_adjust (caster, spell);
1797 charge_mana_effect (plyr, caster_level (caster, spell)); 1798 charge_mana_effect (plyr, casting_level (caster, spell));
1798 return 1; 1799 return 1;
1799 } 1800 }
1800 /* suck sp away. Can't suck sp from yourself */ 1801 /* suck sp away. Can't suck sp from yourself */
1801 else if (op != plyr) 1802 else if (op != plyr)
1802 { 1803 {
1814 /* Player doesn't get full credit */ 1815 /* Player doesn't get full credit */
1815 sucked = (sucked * rate) / 100; 1816 sucked = (sucked * rate) / 100;
1816 op->stats.sp += sucked; 1817 op->stats.sp += sucked;
1817 if (sucked > 0) 1818 if (sucked > 0)
1818 { 1819 {
1819 charge_mana_effect (op, caster_level (caster, spell)); 1820 charge_mana_effect (op, casting_level (caster, spell));
1820 } 1821 }
1821 } 1822 }
1822 return 1; 1823 return 1;
1823 } 1824 }
1824 return 0; 1825 return 0;
1900 break; 1901 break;
1901 } 1902 }
1902 } 1903 }
1903} 1904}
1904 1905
1905
1906
1907/* cast_consecrate() - a spell to make an altar your god's */ 1906/* cast_consecrate() - a spell to make an altar your god's */
1908int 1907int
1909cast_consecrate (object *op, object *caster, object *spell) 1908cast_consecrate (object *op, object *caster, object *spell)
1910{ 1909{
1911 char buf[MAX_BUF]; 1910 char buf[MAX_BUF];
1923 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 1922 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
1924 break; 1923 break;
1925 if (tmp->type == HOLY_ALTAR) 1924 if (tmp->type == HOLY_ALTAR)
1926 { 1925 {
1927 1926
1928 if (tmp->level > caster_level (caster, spell)) 1927 if (tmp->level > casting_level (caster, spell))
1929 { 1928 {
1930 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name); 1929 new_draw_info_format (NDI_UNIQUE, 0, op, "You are not powerful enough to reconsecrate the %s", &tmp->name);
1931 return 0; 1930 return 0;
1932 } 1931 }
1933 else 1932 else
1934 { 1933 {
1935 /* If we got here, we are consecrating an altar */ 1934 /* If we got here, we are consecrating an altar */
1936 sprintf (buf, "Altar of %s", &god->name); 1935 sprintf (buf, "Altar of %s", &god->name);
1937 tmp->name = buf; 1936 tmp->name = buf;
1938 tmp->level = caster_level (caster, spell); 1937 tmp->level = casting_level (caster, spell);
1939 tmp->other_arch = god->arch; 1938 tmp->other_arch = god->arch;
1939
1940 if (op->type == PLAYER) 1940 if (op->type == PLAYER)
1941 esrv_update_item (UPD_NAME, op, tmp); 1941 esrv_update_item (UPD_NAME, op, tmp);
1942
1942 new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name); 1943 new_draw_info_format (NDI_UNIQUE, 0, op, "You consecrated the altar to %s!", &god->name);
1943 return 1; 1944 return 1;
1944 } 1945 }
1945 } 1946 }
1946 } 1947 }
1984 return 0; 1985 return 0;
1985 } 1986 }
1986 1987
1987 /* if no direction specified, pick one */ 1988 /* if no direction specified, pick one */
1988 if (!dir) 1989 if (!dir)
1989 dir = find_free_spot (NULL, op->map, op->x, op->y, 1, 9); 1990 dir = find_free_spot (spell->other_arch, op->map, op->x, op->y, 1, 9);
1990 1991
1991 m = op->map; 1992 m = op->map;
1992 x = op->x + freearr_x[dir]; 1993 x = op->x + freearr_x[dir];
1993 y = op->y + freearr_y[dir]; 1994 y = op->y + freearr_y[dir];
1994 1995
1995 /* if there's no place to put the golem, abort */ 1996 /* if there's no place to put the golem, abort */
1996 if ((dir == -1) || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP) || 1997 if (dir < 0 || (get_map_flags (m, &m, x, y, &x, &y) & P_OUT_OF_MAP)
1997 ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type)) 1998 || ((spell->other_arch->move_type & GET_MAP_MOVE_BLOCK (m, x, y)) == spell->other_arch->move_type))
1998 { 1999 {
1999 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way."); 2000 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
2000 return 0; 2001 return 0;
2001 } 2002 }
2002 2003
2006 if (!weapon) 2007 if (!weapon)
2007 { 2008 {
2008 new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!"); 2009 new_draw_info (NDI_BLACK, 0, op, "You must mark a weapon to use with this spell!");
2009 return 0; 2010 return 0;
2010 } 2011 }
2012
2011 if (spell->race && strcmp (weapon->arch->archname, spell->race)) 2013 if (spell->race && weapon->arch->archname != spell->race)
2012 { 2014 {
2013 new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon."); 2015 new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to transform your weapon.");
2014 return 0; 2016 return 0;
2015 } 2017 }
2018
2016 if (weapon->type != WEAPON) 2019 if (weapon->type != WEAPON)
2017 { 2020 {
2018 new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it."); 2021 new_draw_info (NDI_UNIQUE, 0, op, "You need to wield a weapon to animate it.");
2019 return 0; 2022 return 0;
2020 } 2023 }
2024
2021 if (QUERY_FLAG (weapon, FLAG_APPLIED)) 2025 if (QUERY_FLAG (weapon, FLAG_APPLIED))
2022 { 2026 {
2023 new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon)); 2027 new_draw_info_format (NDI_BLACK, 0, op, "You need to unequip %s before using it in this spell", query_name (weapon));
2024 return 0; 2028 return 0;
2025 } 2029 }
2026 2030
2027 if (weapon->nrof > 1) 2031 weapon = weapon->split ();
2028 {
2029 tmp = get_split_ob (weapon, 1);
2030 esrv_send_item (op, weapon);
2031 weapon = tmp;
2032 }
2033 2032
2034 /* create the golem object */ 2033 /* create the golem object */
2035 tmp = arch_to_object (spell->other_arch); 2034 tmp = arch_to_object (spell->other_arch);
2036 2035
2037 /* if animated by a player, give the player control of the golem */ 2036 /* if animated by a player, give the player control of the golem */
2042 tmp->set_owner (op); 2041 tmp->set_owner (op);
2043 op->contr->golem = tmp; 2042 op->contr->golem = tmp;
2044 set_spell_skill (op, caster, spell, tmp); 2043 set_spell_skill (op, caster, spell, tmp);
2045 2044
2046 /* Give the weapon to the golem now. A bit of a hack to check the 2045 /* Give the weapon to the golem now. A bit of a hack to check the
2047 * removed flag - it should only be set if get_split_object was 2046 * removed flag - it should only be set if weapon->split was
2048 * used above. 2047 * used above.
2049 */ 2048 */
2050 if (!QUERY_FLAG (weapon, FLAG_REMOVED)) 2049 if (!QUERY_FLAG (weapon, FLAG_REMOVED))
2051 weapon->remove (); 2050 weapon->remove ();
2052 2051
2053 insert_ob_in_ob (weapon, tmp); 2052 tmp->insert (weapon);
2054 esrv_send_item (op, weapon); 2053
2055 /* To do everything necessary to let a golem use the weapon is a pain, 2054 /* To do everything necessary to let a golem use the weapon is a pain,
2056 * so instead, just set it as equipped (otherwise, we need to update 2055 * so instead, just set it as equipped (otherwise, we need to update
2057 * body_info, skills, etc) 2056 * body_info, skills, etc)
2058 */ 2057 */
2059 SET_FLAG (tmp, FLAG_USE_WEAPON); 2058 SET_FLAG (tmp, FLAG_USE_WEAPON);
2133 tmp->state = weapon->state; 2132 tmp->state = weapon->state;
2134 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE]; 2133 tmp->flag [FLAG_ANIMATE] = weapon->flag [FLAG_ANIMATE];
2135 } 2134 }
2136 2135
2137 /* make experience increase in proportion to the strength of the summoned creature. */ 2136 /* make experience increase in proportion to the strength of the summoned creature. */
2138 tmp->stats.exp *= 1 + (MAX (spell->stats.maxgrace, spell->stats.sp) / caster_level (caster, spell)); 2137 tmp->stats.exp *= 1 + (MAX (spell->stats.maxgrace, spell->stats.sp) / casting_level (caster, spell));
2139 2138
2140 tmp->speed_left = -1; 2139 tmp->speed_left = -1;
2141 tmp->direction = dir; 2140 tmp->direction = dir;
2142 2141
2143 m->insert (tmp, x, y, op); 2142 m->insert (tmp, x, y, op);
2147/* cast_daylight() - changes the map darkness level *lower* */ 2146/* cast_daylight() - changes the map darkness level *lower* */
2148 2147
2149/* cast_change_map_lightlevel: Was cast_daylight/nightfall. 2148/* cast_change_map_lightlevel: Was cast_daylight/nightfall.
2150 * This changes the light level for the entire map. 2149 * This changes the light level for the entire map.
2151 */ 2150 */
2152
2153int 2151int
2154cast_change_map_lightlevel (object *op, object *caster, object *spell) 2152cast_change_map_lightlevel (object *op, object *caster, object *spell)
2155{ 2153{
2156 int success; 2154 int success;
2157 2155
2165 if (spell->stats.dam < 0) 2163 if (spell->stats.dam < 0)
2166 new_draw_info (NDI_UNIQUE, 0, op, "It can be no brighter here."); 2164 new_draw_info (NDI_UNIQUE, 0, op, "It can be no brighter here.");
2167 else 2165 else
2168 new_draw_info (NDI_UNIQUE, 0, op, "It can be no darker here."); 2166 new_draw_info (NDI_UNIQUE, 0, op, "It can be no darker here.");
2169 } 2167 }
2168
2170 return success; 2169 return success;
2171} 2170}
2172 2171
2173/* create an aura spell object and put it in the player's inventory. 2172/* create an aura spell object and put it in the player's inventory.
2174 * as usual, op is player, caster is the object casting the spell, 2173 * as usual, op is player, caster is the object casting the spell,
2191 new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); 2190 new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell);
2192 2191
2193 set_spell_skill (op, caster, spell, new_aura); 2192 set_spell_skill (op, caster, spell, new_aura);
2194 new_aura->attacktype = spell->attacktype; 2193 new_aura->attacktype = spell->attacktype;
2195 2194
2196 new_aura->level = caster_level (caster, spell); 2195 new_aura->level = casting_level (caster, spell);
2197 2196
2198 if (refresh) 2197 if (refresh)
2199 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect."); 2198 new_draw_info (NDI_UNIQUE, 0, op, "You recast the spell while in effect.");
2200 else 2199 else
2201 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force."); 2200 new_draw_info (NDI_UNIQUE, 0, op, "You create an aura of magical force.");
2272 * op is the piece object. 2271 * op is the piece object.
2273 */ 2272 */
2274void 2273void
2275move_peacemaker (object *op) 2274move_peacemaker (object *op)
2276{ 2275{
2277 object *tmp; 2276 for (object *tmp = op->ms ().bot; tmp; tmp = tmp->above)
2278
2279 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = tmp->above)
2280 { 2277 {
2281 int atk_lev, def_lev; 2278 int atk_lev, def_lev;
2282 object *victim = tmp; 2279 object *victim = tmp->head_ ();
2283 2280
2284 if (tmp->head)
2285 victim = tmp->head;
2286 if (!QUERY_FLAG (victim, FLAG_MONSTER)) 2281 if (!QUERY_FLAG (victim, FLAG_MONSTER))
2287 continue; 2282 continue;
2283
2288 if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE)) 2284 if (QUERY_FLAG (victim, FLAG_UNAGGRESSIVE))
2289 continue; 2285 continue;
2286
2290 if (victim->stats.exp == 0) 2287 if (victim->stats.exp == 0)
2291 continue; 2288 continue;
2292 2289
2293 def_lev = MAX (1, victim->level); 2290 def_lev = MAX (1, victim->level);
2294 atk_lev = MAX (1, op->level); 2291 atk_lev = MAX (1, op->level);
2295 2292
2296 if (rndm (0, atk_lev - 1) > def_lev) 2293 if (rndm (0, atk_lev - 1) > def_lev)
2297 { 2294 {
2298 /* make this sucker peaceful. */ 2295 /* make this sucker peaceful. */
2299 2296
2297 INVOKE_OBJECT (KILL, victim, ARG_OBJECT (op));
2300 change_exp (op->owner, victim->stats.exp, op->skill, 0); 2298 change_exp (op->owner, victim->stats.exp, op->skill, 0);
2301 victim->stats.exp = 0; 2299 victim->stats.exp = 0;
2302#if 0 2300#if 0
2303 /* No idea why these were all set to zero - if something 2301 /* No idea why these were all set to zero - if something
2304 * makes this creature agressive, he should still do damage. 2302 * makes this creature agressive, he should still do damage.
2311 victim->attack_movement = RANDO2; 2309 victim->attack_movement = RANDO2;
2312 SET_FLAG (victim, FLAG_UNAGGRESSIVE); 2310 SET_FLAG (victim, FLAG_UNAGGRESSIVE);
2313 SET_FLAG (victim, FLAG_RUN_AWAY); 2311 SET_FLAG (victim, FLAG_RUN_AWAY);
2314 SET_FLAG (victim, FLAG_RANDOM_MOVE); 2312 SET_FLAG (victim, FLAG_RANDOM_MOVE);
2315 CLEAR_FLAG (victim, FLAG_MONSTER); 2313 CLEAR_FLAG (victim, FLAG_MONSTER);
2314
2316 if (victim->name) 2315 if (victim->name)
2317 {
2318 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name); 2316 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s no longer feels like fighting.", &victim->name);
2319 } 2317 }
2320 }
2321 } 2318 }
2322} 2319}
2323
2324 2320
2325/* This writes a rune that contains the appropriate message. 2321/* This writes a rune that contains the appropriate message.
2326 * There really isn't any adjustments we make. 2322 * There really isn't any adjustments we make.
2327 */ 2323 */
2328
2329int 2324int
2330write_mark (object *op, object *spell, const char *msg) 2325write_mark (object *op, object *spell, const char *msg)
2331{ 2326{
2332 char rune[HUGE_BUF];
2333 object *tmp;
2334
2335 if (!msg || msg[0] == 0) 2327 if (!msg || msg[0] == 0)
2336 { 2328 {
2337 new_draw_info (NDI_UNIQUE, 0, op, "Write what?"); 2329 new_draw_info (NDI_UNIQUE, 0, op, "Write what?");
2338 return 0; 2330 return 0;
2339 } 2331 }
2342 { 2334 {
2343 new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?"); 2335 new_draw_info (NDI_UNIQUE, 0, op, "Trying to cheat are we?");
2344 LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg); 2336 LOG (llevInfo, "write_rune: player %s tried to write bogus rune %s\n", &op->name, msg);
2345 return 0; 2337 return 0;
2346 } 2338 }
2339
2347 if (!spell->other_arch) 2340 if (!spell->other_arch)
2348 return 0; 2341 return 0;
2342
2349 tmp = arch_to_object (spell->other_arch); 2343 object *tmp = arch_to_object (spell->other_arch);
2350
2351 snprintf (rune, sizeof (rune), "%s\n", msg);
2352 2344
2353 tmp->race = op->name; /*Save the owner of the rune */ 2345 tmp->race = op->name; /*Save the owner of the rune */
2354 tmp->msg = rune; 2346 tmp->msg = msg;
2355 2347
2356 tmp->insert_at (op, op, INS_BELOW_ORIGINATOR); 2348 tmp->insert_at (op, op, INS_BELOW_ORIGINATOR);
2349
2357 return 1; 2350 return 1;
2358} 2351}
2352

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines