Atrinik Server  4.0
spell_effect.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <arch.h>
32 #include <player.h>
33 #include <object.h>
34 #include <disease.h>
35 
45 void cast_magic_storm(object *op, object *tmp, int lvl)
46 {
47  /* Error */
48  if (!tmp) {
49  return;
50  }
51 
52  tmp->level = SK_level(op);
53  tmp->x = op->x;
54  tmp->y = op->y;
55 
56  /* increase the area of destruction */
57  tmp->stats.hp += lvl / 5;
58  /* nasty recoils! */
59  tmp->stats.dam = lvl;
60  tmp->stats.maxhp = tmp->count;
61  object_insert_map(tmp, op->map, op, 0);
62 }
63 
71 int recharge(object *op)
72 {
73  object *wand = find_marked_object(op);
74  int cap;
75 
76  if (wand == NULL || wand->type != WAND) {
77  draw_info(COLOR_RED, op, "You need to mark the wand you want to recharge.");
78  return 0;
79  }
80 
81  char *name = object_get_name_s(wand, op);
82 
83  if (wand->stats.sp < 0 || wand->stats.sp >= NROFREALSPELLS || !spells[wand->stats.sp].charges) {
84  draw_info_format(COLOR_RED, op, "The %s cannot be recharged.", name);
85  efree(name);
86  return 0;
87  }
88 
89  if (rndm_chance(6)) {
90  draw_info_format(COLOR_WHITE, op, "The %s vibrates violently, then "
91  "explodes!", name);
92  play_sound_map(op->map, CMD_SOUND_EFFECT, "explosion.ogg", op->x, op->y, 0, 0);
93  object_remove(wand, 0);
94  object_destroy(wand);
95  efree(name);
96  return 1;
97  }
98 
99  draw_info_format(COLOR_WHITE, op, "The %s glows with power.", name);
100 
101  wand->stats.food += 12 + rndm(1, spells[wand->stats.sp].charges);
102  cap = spells[wand->stats.sp].charges + 12;
103 
104  /* Place a cap on it. */
105  if (wand->stats.food > cap) {
106  wand->stats.food = cap;
107  }
108 
109  if (wand->arch && QUERY_FLAG(&wand->arch->clone, FLAG_ANIMATE)) {
110  SET_FLAG(wand, FLAG_ANIMATE);
111  wand->speed = wand->arch->clone.speed;
112  object_update_speed(wand);
113  }
114 
115  efree(name);
116  return 1;
117 }
118 
138 int cast_create_food(object *op, object *caster, int dir, const char *stringarg)
139 {
140  int food_value = 50 * SP_level_dam_adjust(caster, SP_CREATE_FOOD, false);
141 
142  archetype_t *at = NULL;
143  if (stringarg != NULL) {
144  at = arch_find(stringarg);
145 
146  if (at == NULL || ((at->clone.type != FOOD &&
147  at->clone.type != DRINK) || (at->clone.stats.food >
148  food_value))) {
149  stringarg = NULL;
150  at = NULL;
151  }
152  }
153 
154  if (stringarg == NULL) {
155  archetype_t *at_tmp, *tmp;
156  HASH_ITER(hh, arch_table, at_tmp, tmp) {
157  /* Not food or a drink */
158  if (at_tmp->clone.type != FOOD && at_tmp->clone.type != DRINK) {
159  continue;
160  }
161 
162  /* Food value is higher than what is creatable, skip. */
163  if (at_tmp->clone.stats.food > food_value) {
164  continue;
165  }
166 
167  /* Don't have a food arch yet, or the current one has a higher food
168  * value, so take it instead. */
169  if (at == NULL || at_tmp->clone.stats.food > at->clone.stats.food) {
170  at = at_tmp;
171  }
172  }
173  }
174 
175  /* Pretty unlikely (there are some very low food items), but you
176  * never know */
177  if (!at) {
178  draw_info(COLOR_WHITE, op, "You don't have enough experience to create any food.");
179  return 0;
180  }
181 
182  food_value /= at->clone.stats.food;
183  object *new_op = object_get();
184  object_copy(new_op, &at->clone, false);
185  new_op->nrof = food_value;
186 
187  new_op->value = 0;
188  SET_FLAG(new_op, FLAG_STARTEQUIP);
189  SET_FLAG(new_op, FLAG_IDENTIFIED);
190 
191  if (new_op->nrof < 1) {
192  new_op->nrof = 1;
193  }
194 
195  cast_create_obj(op, new_op, dir);
196  return 1;
197 }
198 
211 int cast_wor(object *op, object *caster)
212 {
213  object *dummy;
214 
215  if (op->type != PLAYER) {
216  return 0;
217  }
218 
219  if (blocks_magic(op->map, op->x, op->y)) {
220  draw_info(COLOR_WHITE, op, "Something blocks your spell.");
221  return 0;
222  }
223 
224  dummy = arch_get("force");
225  SOFT_ASSERT_RC(dummy != NULL, 0, "Failed to find 'force' archetype, "
226  "op: %s, caster: %s", object_get_str(op), object_get_str(caster));
227 
228  /* Better insert the spell in the player */
229  if (op->owner) {
230  op = op->owner;
231  }
232 
233  dummy->speed = 0.002f * ((float) (spells[SP_WOR].bdur + SP_level_strength_adjust(caster, SP_WOR)));
234  object_update_speed(dummy);
235  dummy->speed_left = -1;
236  dummy->type = WORD_OF_RECALL;
237 
238  FREE_AND_COPY_HASH(EXIT_PATH(dummy), CONTR(op)->savebed_map);
239  EXIT_X(dummy) = CONTR(op)->bed_x;
240  EXIT_Y(dummy) = CONTR(op)->bed_y;
241 
242  object_insert_into(dummy, op, 0);
243  draw_info(COLOR_WHITE, op, "You feel a force starting to build up inside you.");
244 
245  return 1;
246 }
247 
259 void cast_destruction(object *op, object *caster, int dam)
260 {
261  int i, j, range, xt, yt;
262  object *tmp, *hitter;
263  mapstruct *m;
264 
265  /* The hitter object. */
266  hitter = arch_to_object(spellarch[SP_DESTRUCTION]);
267  object_owner_set(hitter, op);
268  hitter->level = SK_level(caster);
269 
270  /* Calculate maximum range of the spell */
271  range = MAX(SP_level_strength_adjust(caster, SP_DESTRUCTION), spells[SP_DESTRUCTION].bdur);
272  dam += SP_level_dam_adjust(caster, SP_DESTRUCTION, false);
273 
274  for (i = -range; i < range + 1; i++) {
275  for (j = -range; j < range + 1; j++) {
276  xt = op->x + i;
277  yt = op->y + j;
278 
279  if (!(m = get_map_from_coord(op->map, &xt, &yt))) {
280  continue;
281  }
282 
283  /* Nothing alive here? Move on... */
284  if (!(GET_MAP_FLAGS(m, xt, yt) & (P_IS_MONSTER | P_IS_PLAYER))) {
285  continue;
286  }
287 
288  /* Try to get an object to hit */
289  for (tmp = GET_MAP_OB(m, xt, yt); tmp; tmp = tmp->above) {
290  /* Get head. */
291  if (tmp->head) {
292  tmp = tmp->head;
293  }
294 
295  /* Skip the caster and not alive objects. */
296  if (tmp == caster || !IS_LIVE(tmp)) {
297  continue;
298  }
299 
300  if (!is_friend_of(op, tmp)) {
301  int16_t damage = dam;
302 
303  if (tmp->quick_pos) {
304  damage /= (tmp->quick_pos >> 4) + 1;
305  }
306 
307  attack_hit(tmp, hitter, damage);
308  break;
309  }
310  }
311  }
312  }
313 }
314 
326 int cast_heal_around(object *op, int level, int type)
327 {
328  int success = 0;
329 
330  switch (type) {
331  case SP_RAIN_HEAL:
332  {
333  int i, x, y;
334  mapstruct *m;
335  object *tmp;
336 
337  for (i = 0; i <= SIZEOFFREE1; i++) {
338  x = op->x + freearr_x[i];
339  y = op->y + freearr_y[i];
340 
341  if (!(m = get_map_from_coord(op->map, &x, &y))) {
342  continue;
343  }
344 
345  if (!(GET_MAP_FLAGS(m, x, y) & (P_IS_MONSTER | P_IS_PLAYER))) {
346  continue;
347  }
348 
349  for (tmp = GET_MAP_OB_LAYER(m, x, y, LAYER_LIVING, 0); tmp && tmp->layer == LAYER_LIVING; tmp = tmp->above) {
350  tmp = HEAD(tmp);
351 
352  if (tmp == op || !IS_LIVE(tmp) || !is_friend_of(op, tmp)) {
353  continue;
354  }
355 
356  cast_heal(op, op, level, tmp, SP_MINOR_HEAL);
357  success = 1;
358  }
359  }
360 
361  break;
362  }
363 
364  case SP_PARTY_HEAL:
365  {
366  objectlink *ol;
367 
368  if (op->type != PLAYER) {
369  return 0;
370  } else if (!CONTR(op)->party) {
371  draw_info(COLOR_WHITE, op, "You need to be in a party to cast this spell.");
372  return 0;
373  }
374 
375  for (ol = CONTR(op)->party->members; ol; ol = ol->next) {
376  if (on_same_map(ol->objlink.ob, op)) {
377  cast_heal(op, op, level, ol->objlink.ob, SP_MINOR_HEAL);
378  }
379  }
380 
381  success = 1;
382  break;
383  }
384  }
385 
386  return success;
387 }
388 
403 int
404 cast_heal (object *op,
405  object *caster,
406  int level,
407  object *target,
408  int spell_type)
409 {
410  archetype_t *at;
411  object *temp;
412  int heal = 0, success = 0;
413 
414  if (op == NULL || target == NULL) {
415  log_error("Target or caster is NULL, op: %s, target: %s",
416  object_get_str(op), object_get_str(target));
417  return 0;
418  }
419 
420  switch (spell_type) {
421  case SP_CURE_DISEASE:
422 
423  if (disease_cure(target, caster)) {
424  success = 1;
425  }
426 
427  break;
428 
429  case SP_CURE_POISON:
430  at = arch_find("poisoning");
431 
432  if (op != target && target->type == PLAYER) {
433  draw_info_format(COLOR_WHITE, target, "%s casts cure poison on you!", op->name ? op->name : "Someone");
434  }
435 
436  if (op != target && op->type == PLAYER) {
437  draw_info_format(COLOR_WHITE, op, "You cast cure poison on %s!", target->name ? target->name : "someone");
438  }
439 
440  for (temp = target->inv; temp != NULL; temp = temp->below) {
441  if (temp->arch == at) {
442  success = 1;
443  temp->stats.food = 1;
444  }
445  }
446 
447  if (success) {
448  if (target->type == PLAYER) {
449  draw_info(COLOR_WHITE, target, "Your body feels cleansed.");
450  }
451 
452  if (op != target && op->type == PLAYER) {
453  draw_info_format(COLOR_WHITE, op, "%s's body seems cleansed.", target->name ? target->name : "Someone");
454  }
455  } else {
456  if (target->type == PLAYER) {
457  draw_info(COLOR_WHITE, target, "You are not poisoned.");
458  }
459 
460  if (op != target && op->type == PLAYER) {
461  draw_info_format(COLOR_WHITE, op, "%s is not poisoned.", target->name ? target->name : "Someone");
462  }
463  }
464 
465  break;
466 
467  case SP_CURE_CONFUSION:
468  at = arch_find("confusion");
469 
470  if (op != target && target->type == PLAYER) {
471  draw_info_format(COLOR_WHITE, target, "%s casts cure confusion on you!", op->name ? op->name : "Someone");
472  }
473 
474  if (op != target && op->type == PLAYER) {
475  draw_info_format(COLOR_WHITE, op, "You cast cure confusion on %s!", target->name ? target->name : "someone");
476  }
477 
478  for (temp = target->inv; temp != NULL; temp = temp->below) {
479  if (temp->arch == at) {
480  success = 1;
481  temp->stats.food = 1;
482  }
483  }
484 
485  if (success) {
486  if (target->type == PLAYER) {
487  draw_info(COLOR_WHITE, target, "Your mind feels clearer.");
488  }
489 
490  if (op != target && op->type == PLAYER) {
491  draw_info_format(COLOR_WHITE, op, "%s's mind seems clearer.", target->name ? target->name : "Someone");
492  }
493  } else {
494  if (target->type == PLAYER) {
495  draw_info(COLOR_WHITE, target, "You are not confused.");
496  }
497 
498  if (op != target && op->type == PLAYER) {
499  draw_info_format(COLOR_WHITE, op, "%s is not confused.", target->name ? target->name : "Someone");
500  }
501  }
502 
503  break;
504 
505  case SP_MINOR_HEAL:
506  success = 1;
507  heal = rndm(2, 5 + level) + 6;
508 
509  if (op->type == PLAYER) {
510  if (heal > 0) {
511  draw_info_format(COLOR_WHITE, op, "The spell heals %s for %d hp!", op == target ? "you" : target->name, heal);
512  } else {
513  draw_info(COLOR_WHITE, op, "The healing spell fails!");
514  }
515  }
516 
517  if (op != target && target->type == PLAYER) {
518  if (heal > 0) {
519  draw_info_format(COLOR_WHITE, target, "%s casts minor healing on you healing %d hp!", op->name, heal);
520  } else {
521  draw_info_format(COLOR_WHITE, target, "%s casts minor healing on you but it fails!", op->name);
522  }
523  }
524 
525  break;
526 
527  case SP_GREATER_HEAL:
528  success = 1;
529  heal = rndm(4, 5 + level) + rndm(4, 5 + level) + 12;
530 
531  if (op->type == PLAYER) {
532  if (heal > 0) {
533  draw_info_format(COLOR_WHITE, op, "The spell heals %s for %d hp!", op == target ? "you" : target->name, heal);
534  } else {
535  draw_info(COLOR_WHITE, op, "The healing spell fails!");
536  }
537  }
538 
539  if (op != target && target->type == PLAYER) {
540  if (heal > 0) {
541  draw_info_format(COLOR_WHITE, target, "%s casts greater healing on you healing %d hp!", op->name, heal);
542  } else {
543  draw_info_format(COLOR_WHITE, target, "%s casts greater healing on you but it fails!", op->name);
544  }
545  }
546 
547  break;
548 
549  case SP_RESTORATION:
550 
551  if (cast_heal(op, caster, level, target, SP_CURE_POISON)) {
552  success = 1;
553  }
554 
555  if (cast_heal(op, caster, level, target, SP_CURE_CONFUSION)) {
556  success = 1;
557  }
558 
559  if (cast_heal(op, caster, level, target, SP_CURE_DISEASE)) {
560  success = 1;
561  }
562 
563  if (target->stats.food < 999) {
564  success = 1;
565  target->stats.food = 999;
566  }
567 
568  if (cast_heal(op, caster, level, target, SP_MINOR_HEAL)) {
569  success = 1;
570  }
571 
572  return success;
573  }
574 
575  if (heal > 0) {
576  if (disease_reduce_symptoms(target, heal)) {
577  success = 1;
578  }
579 
580  if (target->stats.hp < target->stats.maxhp) {
581  if (target == op) {
582  if (op->type == PLAYER) {
583  CONTR(op)->stat_damage_healed += MIN(heal, target->stats.maxhp - target->stats.hp);
584  }
585  } else {
586  if (op->type == PLAYER) {
587  CONTR(op)->stat_damage_healed_other += MIN(heal, target->stats.maxhp - target->stats.hp);
588  }
589 
590  if (target->type == PLAYER) {
591  CONTR(target)->stat_damage_heal_received += MIN(heal, target->stats.maxhp - target->stats.hp);
592  }
593  }
594 
595  success = 1;
596  target->stats.hp += heal;
597 
598  if (target->stats.hp > target->stats.maxhp) {
599  target->stats.hp = target->stats.maxhp;
600  }
601  }
602 
603  if (target->damage_round_tag != global_round_tag) {
604  target->last_damage = 0;
605  target->damage_round_tag = global_round_tag;
606  }
607 
608  target->last_damage -= heal;
609  }
610 
611  if (success) {
612  op->speed_left = -FABS(op->speed) * 3;
613  }
614 
615  if (insert_spell_effect(spells[spell_type].archname, target->map,
616  target->x, target->y)) {
617  log_error("Failed to insert spell effect, spell: %d, op: %s, "
618  "target: %s", spell_type, object_get_str(op),
619  object_get_str(target));
620  }
621 
622  return success;
623 }
624 
638 int cast_change_attr(object *op, object *caster, object *target, int spell_type)
639 {
640  object *tmp = target, *tmp2 = NULL, *force = NULL;
641  int is_refresh = 0, i = 0;
642 
643  if (tmp == NULL) {
644  return 0;
645  }
646 
647  /* We ID the buff force with spell_type... if we find one, we have
648  * old effect. If not, we create a fresh force. */
649  for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below) {
650  if (tmp2->type == FORCE) {
651  if (tmp2->value == spell_type) {
652  /* The old effect will be "refreshed" */
653  force = tmp2;
654  is_refresh = 1;
655  draw_info(COLOR_WHITE, op, "You recast the spell while in effect.");
656  }
657  }
658  }
659 
660  if (force == NULL) {
661  force = arch_get("force_effect");
662  }
663 
664  /* Mark this force with the originating spell */
665  force->value = spell_type;
666 
667  switch (spell_type) {
668  case SP_STRENGTH:
669  force->speed_left = -1;
670 
671  if (op->type == PLAYER && op != tmp) {
672  draw_info_format(COLOR_WHITE, tmp, "%s casts strength on you!", op->name ? op->name : "Someone");
673  }
674 
675  if (force->stats.Str < 2) {
676  force->stats.Str++;
677 
678  if (op->type == PLAYER && op != tmp) {
679  draw_info_format(COLOR_WHITE, op, "%s gets stronger.", tmp->name ? tmp->name : "Someone");
680  }
681  } else {
682  draw_info(COLOR_WHITE, tmp, "You don't grow stronger but the spell is refreshed.");
683 
684  if (op->type == PLAYER && op != tmp) {
685  draw_info_format(COLOR_WHITE, op, "%s doesn't grow stronger but the spell is refreshed.", tmp->name ? tmp->name : "Someone");
686  }
687  }
688 
689  if (insert_spell_effect(spells[SP_STRENGTH].archname, target->map,
690  target->x, target->y)) {
691  log_error("Failed to insert spell effect, spell: %d, op: %s, "
692  "caster: %s, target: %s", spell_type, object_get_str(op),
693  object_get_str(caster), object_get_str(target));
694  }
695 
696  break;
697 
698  /* Attacktype protection spells */
699  case SP_PROT_COLD:
700  i = ATNR_COLD;
701  break;
702 
703  case SP_PROT_FIRE:
704  i = ATNR_FIRE;
705  break;
706 
707  case SP_PROT_ELEC:
708  i = ATNR_ELECTRICITY;
709  break;
710 
711  case SP_PROT_POISON:
712  i = ATNR_POISON;
713  break;
714  }
715 
716  if (i) {
717  draw_info_format(COLOR_WHITE, op, "Your protection to %s grows.", attack_name[i]);
718  force->protection[i] = MIN(SP_level_dam_adjust(caster, spell_type,
719  false), 50);
720  }
721 
722  force->speed_left = -1 - SP_level_strength_adjust(caster, spell_type) * 0.1f;
723 
724  if (!is_refresh) {
725  SET_FLAG(force, FLAG_APPLIED);
726  SET_FLAG(force, FLAG_IS_USED_UP);
727  force->face = spells[spell_type].at->clone.face;
728  FREE_AND_COPY_HASH(force->name, spells[spell_type].name);
729 
730  if (spells[spell_type].at->clone.msg) {
731  FREE_AND_COPY_HASH(force->msg, spells[spell_type].at->clone.msg);
732  }
733 
734  force = object_insert_into(force, tmp, 0);
735  if (force == NULL) {
736  log_error("Failed to create force for spell %d, op: %s, "
737  "caster: %s, target: %s", spell_type, object_get_str(op),
738  object_get_str(caster), object_get_str(target));
739  }
740  } else {
741  esrv_update_item(UPD_EXTRA, force);
742  }
743 
744  return 1;
745 }
746 
758 int
759 cast_remove_depletion (object *op, object *target)
760 {
761  HARD_ASSERT(op != NULL);
762  SOFT_ASSERT_RC(target != NULL, 0, "Target is NULL");
763 
764  static archetype_t *at = NULL;
765  if (at == NULL) {
766  at = arch_find("depletion");
767  if (at == NULL) {
768  LOG(ERROR, "Could not find depletion archetype");
769  return 0;
770  }
771  }
772 
773  if (target->type != PLAYER) {
774  char *name = object_get_base_name_s(target, op);
775  draw_info_format(COLOR_WHITE, op, "You cast remove depletion on %s.",
776  name);
777  efree(name);
778  draw_info(COLOR_WHITE, op, "There is no depletion.");
779  return 0;
780  }
781 
782  if (op != target) {
783  if (op->type == PLAYER) {
784  char *name = object_get_base_name_s(target, op);
785  draw_info_format(COLOR_WHITE, op,
786  "You cast remove depletion on %s.", name);
787  efree(name);
788  } else if (target->type == PLAYER) {
789  char *name = object_get_base_name_s(op, target);
790  draw_info_format(COLOR_WHITE, target,
791  "%s casts remove depletion on you.", name);
792  efree(name);
793  }
794  }
795 
796  int success = 0;
797 
798  object *depletion = object_find_arch(target, at);
799  if (depletion != NULL) {
800  for (int i = 0; i < NUM_STATS; i++) {
801  if (get_attr_value(&depletion->stats, i) != 0) {
802  success++;
803  draw_info(COLOR_WHITE, target, restore_msg[i]);
804  }
805  }
806 
807  SET_FLAG(target, FLAG_NO_FIX_PLAYER);
808  object_remove(depletion, 0);
809  object_destroy(depletion);
811  living_update_player(target);
812  }
813 
814  if (op != target && op->type == PLAYER) {
815  if (success != 0) {
816  draw_info(COLOR_WHITE, op, "Your spell removes some depletion.");
817  } else {
818  draw_info(COLOR_WHITE, op, "There is no depletion.");
819  }
820  }
821 
822  if (op != target && target->type == PLAYER && success == 0) {
823  draw_info(COLOR_WHITE, target, "There is no depletion.");
824  }
825 
826  insert_spell_effect(spells[SP_REMOVE_DEPLETION].archname,
827  target->map,
828  target->x,
829  target->y);
830 
831  return success;
832 }
833 
848 int remove_curse(object *op, object *target, int type, int src)
849 {
850  object *tmp;
851  int success = 0;
852 
853  if (!op || !target) {
854  return 0;
855  }
856 
857  if (op != target) {
858  if (op->type == PLAYER) {
859  char *name = object_get_base_name_s(target, op);
860  draw_info_format(COLOR_WHITE, op, "You cast remove %s on %s.",
861  type == SP_REMOVE_CURSE ? "curse" : "damnation", name);
862  efree(name);
863  } else if (target->type == PLAYER) {
864  char *name = object_get_base_name_s(op, target);
865  draw_info_format(COLOR_WHITE, target, "%s casts remove %s on you.",
866  name, type == SP_REMOVE_CURSE ? "curse" : "damnation");
867  efree(name);
868  }
869  }
870 
871  /* Player remove xx only removes applied stuff, npc remove clears ALL */
872  for (tmp = target->inv; tmp; tmp = tmp->below) {
873  if ((src == CAST_NPC || QUERY_FLAG(tmp, FLAG_APPLIED)) && (QUERY_FLAG(tmp, FLAG_CURSED) || (type == SP_REMOVE_DAMNATION && QUERY_FLAG(tmp, FLAG_DAMNED)))) {
874  if (tmp->level <= SK_level(op)) {
875  success++;
876 
877  if (type == SP_REMOVE_DAMNATION) {
878  CLEAR_FLAG(tmp, FLAG_DAMNED);
879  }
880 
881  CLEAR_FLAG(tmp, FLAG_CURSED);
882  esrv_send_item(tmp);
883  } else {
884  /* Level of the items is too high for this remove curse */
885 
886  if (target->type == PLAYER) {
887  char *name = object_get_base_name_s(tmp, target);
888  draw_info_format(COLOR_WHITE, target, "The %s's curse is "
889  "stronger than the spell!", name);
890  efree(name);
891  } else if (op != target && op->type == PLAYER) {
892  char *name = object_get_base_name_s(tmp, op);
893  char *target_name = object_get_base_name_s(target, op);
894  draw_info_format(COLOR_WHITE, op, "The %s's curse of %s is "
895  "stronger than your spell!", name, target_name);
896  efree(name);
897  efree(target_name);
898  }
899  }
900  }
901  }
902 
903  if (op != target && op->type == PLAYER) {
904  if (success) {
905  draw_info(COLOR_WHITE, op, "Your spell removes some curses.");
906  } else {
907  char *name = object_get_base_name_s(target, op);
908  draw_info_format(COLOR_WHITE, op, "%s's items seem uncursed.",
909  name);
910  efree(name);
911  }
912  }
913 
914  if (target->type == PLAYER) {
915  if (success) {
916  draw_info(COLOR_WHITE, target, "You feel like someone is helping you.");
917  } else {
918  if (src == CAST_NORMAL) {
919  draw_info(COLOR_WHITE, target, "You are not using any cursed items.");
920  } else {
921  draw_info(COLOR_WHITE, target, "You hear maniacal laughter in the distance.");
922  }
923  }
924  }
925 
926  insert_spell_effect(spells[SP_REMOVE_CURSE].archname, target->map, target->x, target->y);
927 
928  return success;
929 }
930 
945 int do_cast_identify(object *tmp, object *op, int mode, int *done, int level)
946 {
947  if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) || IS_SYS_INVISIBLE(tmp) || !need_identify(tmp)) {
948  return 1;
949  }
950 
951  if (level < tmp->level) {
952  if (op->type == PLAYER) {
953  char *name = object_get_base_name_s(tmp, op);
954  draw_info_format(COLOR_WHITE, op, "The %s is too powerful for this "
955  "identify!", name);
956  efree(name);
957  }
958  } else {
959  identify(tmp);
960 
961  if (op->type == PLAYER) {
962  char *name = object_get_name_description_s(tmp, op);
963  draw_info_format(COLOR_WHITE, op, "You have %s.", name);
964  efree(name);
965 
966  if (tmp->msg != NULL && tmp->type != BOOK) {
967  draw_info(COLOR_WHITE, op, "The item has a story:");
968  draw_info(COLOR_WHITE, op, tmp->msg);
969  }
970  }
971 
972  *done += 1;
973  }
974 
975  if (mode == IDENTIFY_NORMAL && op->type == PLAYER && *done > CONTR(op)->skill_ptr[SK_LITERACY]->level + op->stats.Int) {
976  return 0;
977  }
978 
979  return 1;
980 }
981 
997 int cast_identify(object *op, int level, object *single_ob, int mode)
998 {
999  int done = 0;
1000 
1001  insert_spell_effect(spells[SP_IDENTIFY].archname, op->map, op->x, op->y);
1002 
1003  if (mode == IDENTIFY_MARKED) {
1004  SOFT_ASSERT_RC(single_ob != NULL, 0, "single_ob is NULL for object: %s",
1005  object_get_str(op));
1006  do_cast_identify(single_ob, op, mode, &done, level);
1007  } else {
1008  object *tmp = op->inv;
1009 
1010  if (single_ob && single_ob->type == CONTAINER) {
1011  tmp = single_ob->inv;
1012  }
1013 
1014  for (; tmp; tmp = tmp->below) {
1015  if (!do_cast_identify(tmp, op, mode, &done, level)) {
1016  break;
1017  }
1018  }
1019  }
1020 
1021  if (op->type == PLAYER && !done) {
1022  draw_info(COLOR_WHITE, op, "You can't reach anything unidentified in your inventory.");
1023  }
1024 
1025  return done;
1026 }
1027 
1035 int cast_consecrate(object *op)
1036 {
1037  object *tmp, *god = find_god(determine_god(op));
1038 
1039  if (!god) {
1040  draw_info(COLOR_WHITE, op, "You can't consecrate anything if you don't worship a god!");
1041  return 0;
1042  }
1043 
1044  for (tmp = op->below; tmp; tmp = tmp->below) {
1045  if (QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
1046  break;
1047  }
1048 
1049  if (tmp->type == HOLY_ALTAR) {
1050  /* We use SK_level here instead of path_level mod because I think
1051  * all the gods should give equal chance of re-consecrating altars
1052  * */
1053  if (tmp->level > SK_level(op)) {
1054  draw_info_format(COLOR_WHITE, op, "You are not powerful enough to reconsecrate the %s.", tmp->name);
1055  return 0;
1056  } else if (tmp->other_arch == god->arch) {
1057  draw_info_format(COLOR_WHITE, op, "That altar is already consecrated to %s.", god->name);
1058  return 0;
1059  } else {
1060  char buf[MAX_BUF], *cp;
1061  object *new_altar;
1062 
1063  snprintf(buf, sizeof(buf), "altar_%s", god->name);
1064 
1065  for (cp = buf; *cp != '\0'; cp++) {
1066  *cp = tolower(*cp);
1067  }
1068 
1069  new_altar = arch_get(buf);
1070  new_altar->level = tmp->level;
1071  new_altar->x = tmp->x;
1072  new_altar->y = tmp->y;
1073  new_altar->direction = tmp->direction;
1074 
1075  if (QUERY_FLAG(new_altar, FLAG_IS_TURNABLE)) {
1076  SET_ANIMATION(new_altar, (NUM_ANIMATIONS(new_altar) / NUM_FACINGS(new_altar)) * new_altar->direction);
1077  }
1078 
1079  if (QUERY_FLAG(tmp, FLAG_IS_BUILDABLE)) {
1080  SET_FLAG(new_altar, FLAG_IS_BUILDABLE);
1081  }
1082 
1083  object_insert_map(new_altar, tmp->map, NULL, 0);
1084  object_remove(tmp, 0);
1085 
1086  draw_info_format(COLOR_WHITE, op, "You consecrated the altar to %s!", god->name);
1087  return 1;
1088  }
1089  }
1090  }
1091 
1092  draw_info(COLOR_WHITE, op, "You are not standing over an altar!");
1093  return 0;
1094 }
1095 
1108 int finger_of_death(object *op, object *target)
1109 {
1110  object *hitter;
1111  int dam;
1112 
1113  if (QUERY_FLAG(target, FLAG_UNDEAD)) {
1114  char *name = object_get_name_s(target, op);
1115  draw_info_format(COLOR_WHITE, op, "The spell seems ineffective against "
1116  "the %s!", name);
1117  efree(name);
1118 
1119  if (!OBJECT_VALID(target->enemy, target->enemy_count)) {
1120  set_npc_enemy(target, op, NULL);
1121  }
1122 
1123  return 1;
1124  }
1125 
1126  /* We create a hitter object -- the spell */
1127  hitter = arch_to_object(spellarch[SP_FINGER_DEATH]);
1128  hitter->level = SK_level(op);
1129  object_owner_set(hitter, op);
1130  hitter->x = target->x;
1131  hitter->y = target->y;
1132  object_insert_map(hitter, target->map, op, 0);
1133 
1134  dam = SP_level_dam_adjust(op, SP_FINGER_DEATH, false);
1135  attack_hit(target, hitter, dam);
1136  object_remove(hitter, 0);
1137 
1138  return 1;
1139 }
1140 
1156 int cast_cause_disease(object *op, object *caster, int dir, struct archetype *disease_arch, int type)
1157 {
1158  int x = op->x, y = op->y, i, xt, yt;
1159  object *walk;
1160  mapstruct *m;
1161 
1162  /* Search in a line for a victim */
1163  for (i = 0; i < 5; i++) {
1164  x += freearr_x[dir];
1165  y += freearr_y[dir];
1166  xt = x;
1167  yt = y;
1168 
1169  if (!(m = get_map_from_coord(op->map, &xt, &yt))) {
1170  continue;
1171  }
1172 
1173  /* Check map flags for alive object */
1174  if (!(GET_MAP_FLAGS(m, xt, yt) & P_IS_MONSTER)) {
1175  continue;
1176  }
1177 
1178  /* Search this square for a victim */
1179  for (walk = GET_MAP_OB(m, xt, yt); walk; walk = walk->above) {
1180  object *disease;
1181  int dam, strength;
1182 
1183  /* Found a victim */
1184  if (!QUERY_FLAG(walk, FLAG_MONSTER) && (walk->type != PLAYER || !pvp_area(op, walk))) {
1185  continue;
1186  }
1187 
1188  disease = arch_to_object(disease_arch);
1189  dam = SP_level_dam_adjust(caster, type, false);
1190  strength = SP_level_strength_adjust(caster, type);
1191 
1192  object_owner_set(disease, op);
1193  disease->stats.exp = 0;
1194  disease->level = SK_level(caster);
1195 
1196  /* Do level adjustments */
1197  if (disease->stats.wc) {
1198  disease->stats.wc += strength / 2;
1199  }
1200 
1201  if (disease->magic > 0) {
1202  disease->magic += strength / 4;
1203  }
1204 
1205  if (disease->stats.maxhp > 0) {
1206  disease->stats.maxhp += strength;
1207  }
1208 
1209  if (disease->stats.dam) {
1210  if (disease->stats.dam > 0) {
1211  disease->stats.dam += dam;
1212  } else {
1213  disease->stats.dam -= dam;
1214  }
1215  }
1216 
1217  if (disease->last_sp) {
1218  disease->last_sp -= 2 * dam;
1219 
1220  if (disease->last_sp < 1) {
1221  disease->last_sp = 1;
1222  }
1223  }
1224 
1225  if (disease->stats.maxsp) {
1226  if (disease->stats.maxsp > 0) {
1227  disease->stats.maxsp += dam;
1228  } else {
1229  disease->stats.maxsp -= dam;
1230  }
1231  }
1232 
1233  if (disease->stats.ac) {
1234  disease->stats.ac += dam;
1235  }
1236 
1237  if (disease->last_eat) {
1238  disease->last_eat -= dam;
1239  }
1240 
1241  if (disease->stats.hp) {
1242  disease->stats.hp -= dam;
1243  }
1244 
1245  if (disease->stats.sp) {
1246  disease->stats.sp -= dam;
1247  }
1248 
1249  if (disease_infect(disease, walk, 1)) {
1250  draw_info_format(COLOR_WHITE, op, "You inflict %s on %s!", disease->name, walk->name);
1251  return 1;
1252  }
1253  }
1254 
1255  /* No more infecting through walls. */
1256  if (wall(m, xt, yt)) {
1257  return 0;
1258  }
1259  }
1260 
1261  draw_info(COLOR_WHITE, op, "No one caught anything!");
1262  return 0;
1263 }
1264 
1272 int cast_transform_wealth(object *op)
1273 {
1274  object *marked;
1275  int64_t val;
1276 
1277  if (op->type != PLAYER) {
1278  return 0;
1279  }
1280 
1281  /* Find the marked wealth. */
1282  marked = find_marked_object(op);
1283 
1284  if (!marked) {
1285  draw_info(COLOR_WHITE, op, "You need to mark an object to cast this spell.");
1286  return 0;
1287  }
1288 
1289  /* Check that it's really money. */
1290  if (marked->type != MONEY) {
1291  draw_info(COLOR_WHITE, op, "You can only cast this spell on wealth objects.");
1292  return 0;
1293  }
1294 
1295  char *name = object_get_name_s(marked, op);
1296 
1297  /* Only allow coppers and silvers to be transformed. */
1298  if (strcmp(marked->arch->name, coins[NUM_COINS - 1]) && strcmp(marked->arch->name, coins[NUM_COINS - 2])) {
1299  draw_info_format(COLOR_WHITE, op, "You don't see a way to transform "
1300  "%s.", name);
1301  efree(name);
1302  return 0;
1303  }
1304 
1305  /* Figure out our value of money to give to player. */
1306  val = (marked->value * (marked->nrof ? marked->nrof : 1)) * TRANSFORM_WEALTH_SACRIFICE;
1307  /* We remove the money. */
1308  object_remove(marked, 0);
1309  /* Now give the player the new money. */
1310  shop_insert_coins(op, val);
1311  draw_info_format(COLOR_WHITE, op, "You transform %s into %s.", name,
1312  shop_get_cost_string(val));
1313  efree(name);
1314  return 1;
1315 }
#define FREE_AND_COPY_HASH(_sv_, _nv_)
Definition: global.h:100
archetype_t * arch_table
Definition: arch.c:41
void object_destroy(object *ob)
Definition: object.c:1441
const char *const attack_name[NROFATTACKS]
Definition: attack.c:57
int16_t ac
Definition: living.h:93
const char * shop_get_cost_string(int64_t cost)
Definition: shop.c:178
uint8_t quick_pos
Definition: object.h:357
int remove_curse(object *op, object *target, int type, int src)
Definition: spell_effect.c:848
Definition: object.h:488
const char *const restore_msg[NUM_STATS]
Definition: living.c:185
int cast_create_food(object *op, object *caster, int dir, const char *stringarg)
Definition: spell_effect.c:138
char * object_get_name_description_s(const object *op, const object *caller)
Definition: item.c:1303
#define FLAG_CURSED
Definition: define.h:1154
void identify(object *op)
Definition: item.c:1364
#define BOOK
Definition: define.h:150
int do_cast_identify(object *tmp, object *op, int mode, int *done, int level)
Definition: spell_effect.c:945
tag_t enemy_count
Definition: object.h:216
void cast_destruction(object *op, object *caster, int dam)
Definition: spell_effect.c:259
#define NUM_FACINGS(ob)
Definition: global.h:300
int recharge(object *op)
Definition: spell_effect.c:71
uint8_t type
One of operation types.
Definition: sound_ambient.c:45
object * object_get(void)
Definition: object.c:993
int cast_heal_around(object *op, int level, int type)
Definition: spell_effect.c:326
#define FLAG_ANIMATE
Definition: define.h:912
int SP_level_strength_adjust(object *caster, int spell_type)
Definition: spell_util.c:1039
#define NROFREALSPELLS
Definition: define.h:664
double speed_left
Definition: object.h:472
#define SIZEOFFREE1
Definition: define.h:654
mapstruct * get_map_from_coord(mapstruct *m, int *x, int *y)
Definition: map.c:1869
int SK_level(object *op)
Definition: skill_util.c:470
#define WAND
Definition: define.h:445
#define SET_ANIMATION(ob, newanim)
Definition: global.h:282
int cast_consecrate(object *op)
void object_copy(object *op, const object *src, bool no_speed)
Definition: object.c:886
int16_t last_sp
Definition: object.h:313
int wall(mapstruct *m, int x, int y)
Definition: map.c:486
#define HOLY_ALTAR
Definition: define.h:288
int cast_transform_wealth(object *op)
object * arch_get(const char *name)
Definition: arch.c:430
int64_t exp
Definition: living.h:69
uint8_t layer
Definition: object.h:405
#define MONEY
Definition: define.h:226
struct obj * above
Definition: object.h:120
int cast_wor(object *op, object *caster)
Definition: spell_effect.c:211
#define IS_LIVE(op)
Definition: define.h:841
#define PLAYER
Definition: define.h:122
bool disease_cure(object *op, object *caster)
Definition: disease.c:507
int8_t get_attr_value(const living *stats, int attr)
Definition: living.c:305
int16_t sp
Definition: living.h:78
#define FLAG_IS_TURNABLE
Definition: define.h:960
object * object_find_arch(object *op, archetype_t *at)
Definition: object.c:2258
#define FLAG_IS_FLOOR
Definition: define.h:1118
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
struct archetype * arch
Definition: object.h:225
struct obj * enemy
Definition: object.h:196
struct archetype * other_arch
Definition: object.h:228
int8_t Int
Definition: living.h:112
#define IS_SYS_INVISIBLE(__ob_)
Definition: define.h:1353
void object_remove(object *op, int flags)
Definition: object.c:1623
#define NUM_COINS
Definition: treasure.h:37
int16_t maxsp
Definition: living.h:81
int32_t hp
Definition: living.h:72
#define FLAG_STARTEQUIP
Definition: define.h:1004
char * object_get_name_s(const object *op, const object *caller)
Definition: item.c:398
object * ob
Definition: object.h:496
#define TRANSFORM_WEALTH_SACRIFICE
Definition: spells.h:294
#define WORD_OF_RECALL
Definition: define.h:405
int cast_remove_depletion(object *op, object *target)
Definition: spell_effect.c:759
#define FLAG_NO_FIX_PLAYER
Definition: define.h:1036
#define FLAG_DAMNED
Definition: define.h:1158
int16_t y
Definition: object.h:276
int32_t maxhp
Definition: living.h:75
#define P_IS_PLAYER
Definition: map.h:256
void set_npc_enemy(object *npc, object *enemy, rv_vector *rv)
Definition: monster.c:85
const char * object_get_str(const object *op)
Definition: object.c:3151
int8_t direction
Definition: object.h:350
Definition: arch.h:40
char * object_get_base_name_s(const object *op, const object *caller)
Definition: item.c:534
int is_friend_of(object *op, object *obj)
Definition: monster.c:1685
#define CAST_NPC
Definition: spells.h:288
#define IDENTIFY_MARKED
Definition: define.h:62
int charges
Definition: spells.h:144
object * object_insert_into(object *op, object *where, int flag)
Definition: object.c:2158
struct mapdef * map
Definition: object.h:139
int16_t last_damage
Definition: object.h:292
int16_t dam
Definition: living.h:87
int cast_create_obj(object *op, object *new_op, int dir)
Definition: spell_util.c:501
const char * name
Definition: object.h:168
#define SET_FLAG(xyz, p)
Definition: define.h:741
#define LAYER_LIVING
Definition: map.h:59
struct archetype * at
Definition: spells.h:198
object * arch_to_object(archetype_t *at)
Definition: arch.c:446
struct obj * below
Definition: object.h:114
#define CONTAINER
Definition: define.h:493
const char * determine_god(object *op)
Definition: gods.c:62
uint32_t nrof
Definition: object.h:264
union oblnk::@3 objlink
uint32_t damage_round_tag
Definition: object.h:149
int cast_change_attr(object *op, object *caster, object *target, int spell_type)
Definition: spell_effect.c:638
int cast_heal(object *op, object *caster, int level, object *target, int spell_type)
Definition: spell_effect.c:404
bool need_identify(const object *op)
Definition: item.c:1315
int insert_spell_effect(const char *archname, mapstruct *m, int x, int y)
Definition: spell_util.c:118
#define FLAG_IS_USED_UP
Definition: define.h:976
#define FLAG_IS_BUILDABLE
Definition: define.h:1162
double speed
Definition: object.h:469
const char * name
Definition: spells.h:132
#define HEAD(op)
Definition: object.h:657
int blocks_magic(mapstruct *m, int x, int y)
Definition: map.c:529
const char *const coins[NUM_COINS+1]
Definition: treasure.c:38
void esrv_send_item(object *op)
Definition: item.c:703
int16_t x
Definition: object.h:273
int pvp_area(object *attacker, object *victim)
Definition: player.c:977
int16_t last_eat
Definition: object.h:319
int16_t wc
Definition: living.h:90
object * find_god(const char *name)
Definition: gods.c:40
object * object_insert_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1741
spell_struct spells[NROFREALSPELLS]
Definition: spellist.h:34
void play_sound_map(mapstruct *map, int type, const char *filename, int x, int y, int loop, int volume)
Definition: sounds.c:159
void shop_insert_coins(object *op, int64_t value)
Definition: shop.c:587
#define FLAG_APPLIED
Definition: define.h:1182
bool disease_reduce_symptoms(object *op, int reduction)
Definition: disease.c:585
void object_owner_set(object *op, object *owner)
Definition: object.c:788
#define NUM_STATS
Definition: living.h:49
int SP_level_dam_adjust(object *caster, int spell_type, bool exact)
Definition: spell_util.c:992
int on_same_map(object *op1, object *op2)
Definition: map.c:2414
struct obj * owner
Definition: object.h:207
#define NUM_ANIMATIONS(ob)
Definition: global.h:298
tag_t count
Definition: object.h:142
living stats
Definition: object.h:481
struct oblnk * next
Definition: object.h:500
void esrv_update_item(int flags, object *op)
Definition: item.c:639
int attack_hit(object *op, object *hitter, int dam)
Definition: attack.c:669
struct archetype * spellarch[NROFREALSPELLS]
Definition: spell_util.c:43
int freearr_x[SIZEOFFREE]
Definition: object.c:84
uint8_t type
Definition: object.h:360
#define CLEAR_FLAG(xyz, p)
Definition: define.h:751
#define IDENTIFY_NORMAL
Definition: define.h:58
shstr * name
More definite name, like "kobold".
Definition: arch.h:46
#define FOOD
Definition: define.h:142
const char * msg
Definition: object.h:183
#define FLAG_MONSTER
Definition: define.h:922
#define OBJECT_VALID(_ob_, _count_)
Definition: object.h:548
int cast_cause_disease(object *op, object *caster, int dir, struct archetype *disease_arch, int type)
struct obj * inv
Definition: object.h:123
struct obj * head
Definition: object.h:136
#define P_IS_MONSTER
Definition: map.h:258
#define FLAG_UNDEAD
Definition: define.h:1012
#define DRINK
Definition: define.h:279
void cast_magic_storm(object *op, object *tmp, int lvl)
Definition: spell_effect.c:45
void object_update_speed(object *op)
Definition: object.c:1043
Definition: map.h:536
New_Face * face
Definition: object.h:234
int finger_of_death(object *op, object *target)
#define CAST_NORMAL
Definition: spells.h:275
int8_t level
Definition: object.h:347
#define FORCE
Definition: define.h:465
int freearr_y[SIZEOFFREE]
Definition: object.c:99
int cast_identify(object *op, int level, object *single_ob, int mode)
Definition: spell_effect.c:997
int64_t value
Definition: object.h:240
int8_t magic
Definition: object.h:341
object clone
An object from which to do object_copy().
Definition: arch.h:47
archetype_t * arch_find(const char *name)
Definition: arch.c:407
#define FLAG_IDENTIFIED
Definition: define.h:980
int16_t food
Definition: living.h:84
object * find_marked_object(object *op)
Definition: player.c:1393
bool disease_infect(object *op, object *victim, bool force)
Definition: disease.c:396
void living_update_player(object *op)
Definition: living.c:614