/* * This function is used to provide services to mag_groups. This function * is the one you should change to add new group spells. */ void perform_mag_groups(int level, struct char_data *ch, struct char_data *tch, int spellnum, int savetype) { switch (spellnum) { case SPELL_GROUP_HEAL: mag_points(level, ch, tch, SPELL_HEAL, savetype); break; case SPELL_GROUP_ARMOR: mag_affects(level, ch, tch, SPELL_ARMOR, savetype); break; case SPELL_GROUP_RECALL: spell_recall(level, ch, tch, NULL); break; } }
/* This function is the very heart of the entire magic system. All invocations * of all types of magic -- objects, spoken and unspoken PC and NPC spells, the * works -- all come through this function eventually. This is also the entry * point for non-spoken or unrestricted spells. Spellnum 0 is legal but silently * ignored here, to make callers simpler. */ int call_magic(struct char_data *caster, struct char_data *cvict, struct obj_data *ovict, int spellnum, int level, int casttype) { int savetype; if (spellnum < 1 || spellnum > TOP_SPELL_DEFINE) return (0); if (!cast_wtrigger(caster, cvict, ovict, spellnum)) return 0; if (!cast_otrigger(caster, ovict, spellnum)) return 0; if (!cast_mtrigger(caster, cvict, spellnum)) return 0; if (ROOM_FLAGGED(IN_ROOM(caster), ROOM_NOMAGIC)) { send_to_char(caster, "Your magic fizzles out and dies.\r\n"); act("$n's magic fizzles out and dies.", FALSE, caster, 0, 0, TO_ROOM); return (0); } if (ROOM_FLAGGED(IN_ROOM(caster), ROOM_PEACEFUL) && (SINFO.violent || IS_SET(SINFO.routines, MAG_DAMAGE))) { send_to_char(caster, "A flash of white light fills the room, dispelling your violent magic!\r\n"); act("White light from no particular source suddenly fills the room, then vanishes.", FALSE, caster, 0, 0, TO_ROOM); return (0); } if (cvict && MOB_FLAGGED(cvict, MOB_NOKILL)) { send_to_char(caster, "This mob is protected.\r\n"); return (0); } /* determine the type of saving throw */ switch (casttype) { case CAST_STAFF: case CAST_SCROLL: case CAST_POTION: case CAST_WAND: savetype = SAVING_ROD; break; case CAST_SPELL: savetype = SAVING_SPELL; break; default: savetype = SAVING_BREATH; break; } if (IS_SET(SINFO.routines, MAG_DAMAGE)) if (mag_damage(level, caster, cvict, spellnum, savetype) == -1) return (-1); /* Successful and target died, don't cast again. */ if (IS_SET(SINFO.routines, MAG_AFFECTS)) mag_affects(level, caster, cvict, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_UNAFFECTS)) mag_unaffects(level, caster, cvict, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_POINTS)) mag_points(level, caster, cvict, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_ALTER_OBJS)) mag_alter_objs(level, caster, ovict, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_GROUPS)) mag_groups(level, caster, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_MASSES)) mag_masses(level, caster, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_AREAS)) mag_areas(level, caster, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_SUMMONS)) mag_summons(level, caster, ovict, spellnum, savetype); if (IS_SET(SINFO.routines, MAG_CREATIONS)) mag_creations(level, caster, spellnum); if (IS_SET(SINFO.routines, MAG_ROOMS)) mag_rooms(level, caster, spellnum); if (IS_SET(SINFO.routines, MAG_MANUAL)) switch (spellnum) { case SPELL_CHARM: MANUAL_SPELL(spell_charm); break; case SPELL_CREATE_WATER: MANUAL_SPELL(spell_create_water); break; case SPELL_DETECT_POISON: MANUAL_SPELL(spell_detect_poison); break; case SPELL_ENCHANT_WEAPON: MANUAL_SPELL(spell_enchant_weapon); break; case SPELL_IDENTIFY: MANUAL_SPELL(spell_identify); break; case SPELL_LOCATE_OBJECT: MANUAL_SPELL(spell_locate_object); break; case SPELL_SUMMON: MANUAL_SPELL(spell_summon); break; case SPELL_WORD_OF_RECALL: MANUAL_SPELL(spell_recall); break; case SPELL_TELEPORT: MANUAL_SPELL(spell_teleport); break; } return (1); }
/* * Remove an affected_type structure from a char (called when duration * reaches zero). Pointer *af must never be NIL! Frees mem and calls * affect_location_apply */ void affect_remove(struct char_data * ch, struct affected_type * af, int output) { struct affected_type *temp; struct affected_type aff; bool accum_affect = FALSE; int k; if (ch->affected == NULL) { core_dump(); return; } switch (af->type) { case SPELL_CHARM: { struct char_data* victim = ch->master; if (output == 0) break; affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); if (ch->master) { stop_follower(ch); } if (victim) { if(IS_NPC(ch)) { SET_BIT(MOB_FLAGS(ch), MOB_AGGRESSIVE | MOB_MEMORY); } if (mag_savingthrow(victim, SAVING_SPELL)) { hit(victim, ch, TYPE_UNDEFINED); } } return; } case SPELL_LIGHT: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light -= 10; } } break; case SPELL_DARKNESS: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light += 10; } } break; case SPELL_BLACK_PLAGUE: mag_affects(30, ch, ch, SPELL_BREATH_OF_LIFE, SAVING_SPELL); break; case SPELL_CALL_ANIMAL_SPIRIT: case SPELL_ANIMAL_SUMMONING: case SPELL_ANIMAL_SUMMONING_II: case SPELL_ANIMAL_SUMMONING_III: case SPELL_CONJURE_ELEMENTAL: case SPELL_GREATER_ELEMENTAL: case SPELL_DUST_DEVIL: case SPELL_STICKS_TO_SNAKES: case SPELL_SUMMON_INSECTS: case SPELL_AERIAL_SERVANT: case SPELL_SUMMON_GUARD: if (IS_NPC(ch)) { if (GET_POS(ch) > POS_DEAD) { if (output == 1) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); GET_NAME(ch, chname); stop_fighting(ch); /*Fighting Bug Fix Jasrags*/ sprintf(buf, "%s disappears into thin air as the summoning ends.", chname); act(buf, FALSE, world[ch->in_room].people, 0, 0, TO_ROOM); FREE_NAME(chname); extract_char(ch); ch = NULL; return; } } } break; case SPELL_POLYMORPH: if (!PRF_FLAGGED(ch, PRF_NOTSELF)) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); return; } break; case SPELL_DONTUSEME: if(AFF_FLAGGED(ch, AFF_STANCE) && !AFF_FLAGGED(ch, AFF_TIRED)) { aff.type = SKILL_STANCE; aff.duration = 2; aff.location = APPLY_STR; aff.modifier = -2; aff.bitvector = AFF_TIRED; accum_affect = FALSE; affect_to_char(ch, &aff); } break; default: break; } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type != SPELL_POLYMORPH && af->type != SPELL_DONTUSEME) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (*spell_wear_off_msg[af->type]) { send_to_char(spell_wear_off_msg[af->type], ch); send_to_char("\r\n", ch); } } } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type == SPELL_POLYMORPH) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (PLR_FLAGGED(ch, PLR_RABBIT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_RABBIT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing, and your ears shrinking. You no longer feel like a rabbit.\r\n", ch); act("$n's body grows, $s ears shrinking. $n no longer looks like a rabbit.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BIRD)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BIRD); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing and your feathers falling away. You no longer feel like a bird.\r\n", ch); act("$n's body grows, $s feathers falling away as it expands. $n no longer looks like a bird.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_WOLF)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_WOLF); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your your fur shed and your teeth shrink. You no longer feel like a wolf.\r\n", ch); act("$n's teeth shrink, $s fur shedding. $n no longer looks like a wolf.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BEAR)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BEAR); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("Your claws shrink as does the rest of your body. You no longer feel like a bear.\r\n", ch); act("$n's claws shrink as does the rest of $s body. $n no longer looks like a bear.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_CAT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_CAT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your body growing, and your fur shedding. You no longer feel like a cat.\r\n", ch); act("$n's body slowly grows, $s fur shedding. $n no longer looks like a cat.\r\n", 0, ch, 0, 0, TO_ROOM); } for (k = 0; k < NUM_WEARS; k++) if (GET_EQ(ch, k)){ GET_OBJ_DISGUISE(GET_EQ(ch, k)) = 0; } } } affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); }
/* * This function is the very heart of the entire magic system. All * invocations of all types of magic -- objects, spoken and unspoken PC * and NPC spells, the works -- all come through this function eventually. * This is also the entry point for non-spoken or unrestricted spells. * Spellnum 0 is legal but silently ignored here, to make callers simpler. */ int call_magic(struct char_data *caster, struct char_data *cvict, struct obj_data *ovict, struct spell_info_type *sptr, int level, int casttype, char *tar_str) { int savetype; if (!magic_enabled) return (0); if (caster->nr != real_mobile(DG_CASTER_PROXY)) { if (ROOM_FLAGGED(IN_ROOM(caster), ROOM_NOMAGIC)) { send_to_char("Your magic fizzles out and dies.\r\n", caster); act("$n's magic fizzles out and dies.", FALSE, caster, 0, 0, TO_ROOM); return (0); } if (ROOM_FLAGGED(IN_ROOM(caster), ROOM_PEACEFUL) && (sptr->violent || IS_SET(sptr->routines, MAG_DAMAGE))) { send_to_char("A flash of white light fills the room, dispelling your " "violent magic!\r\n", caster); act("White light from no particular source suddenly fills the room, " "then vanishes.", FALSE, caster, 0, 0, TO_ROOM); return (0); } } /* determine the type of saving throw */ switch (casttype) { case CAST_STAFF: case CAST_SCROLL: case CAST_POTION: case CAST_WAND: savetype = SAVING_ROD; break; case CAST_SPELL: savetype = SAVING_SPELL; break; default: savetype = SAVING_BREATH; break; } if (IS_SET(sptr->routines, MAG_DAMAGE)) if (mag_damage(level, caster, cvict, sptr, savetype) == -1) return (-1); /* Successful and target died, don't cast again. */ if (IS_SET(sptr->routines, MAG_AFFECTS)) mag_affects(level, caster, cvict, sptr, savetype); if (IS_SET(sptr->routines, MAG_UNAFFECTS)) mag_unaffects(level, caster, cvict, sptr, savetype); if (IS_SET(sptr->routines, MAG_POINTS)) mag_points(level, caster, cvict, sptr, savetype); if (IS_SET(sptr->routines, MAG_ALTER_OBJS)) mag_alter_objs(level, caster, ovict, sptr, savetype); if (IS_SET(sptr->routines, MAG_GROUPS)) mag_groups(level, caster, sptr, savetype); if (IS_SET(sptr->routines, MAG_MASSES)) mag_masses(level, caster, sptr, savetype); if (IS_SET(sptr->routines, MAG_AREAS)) mag_areas(level, caster, sptr, savetype); if (IS_SET(sptr->routines, MAG_SUMMONS)) mag_summons(level, caster, ovict, sptr, savetype); if (IS_SET(sptr->routines, MAG_CREATIONS)) mag_creations(level, caster, sptr); if (IS_SET(sptr->routines, MAG_MANUAL)) switch (sptr->number) { case SPELL_CHARM: MANUAL_SPELL(spell_charm); break; case SPELL_CREATE_WATER: MANUAL_SPELL(spell_create_water); break; case SPELL_DETECT_POISON: MANUAL_SPELL(spell_detect_poison); break; case SPELL_ENCHANT_WEAPON: MANUAL_SPELL(spell_enchant_weapon); break; case SPELL_IDENTIFY: MANUAL_SPELL(spell_identify); break; case SPELL_LOCATE_OBJECT: MANUAL_SPELL(spell_locate_object); break; case SPELL_SUMMON: MANUAL_SPELL(spell_summon); break; case SPELL_WORD_OF_RECALL: MANUAL_SPELL(spell_recall); break; case SPELL_TELEPORT: MANUAL_SPELL(spell_teleport); break; case SPELL_MINOR_IDENTIFY: MANUAL_SPELL(spell_minor_identify); break; case SPELL_PORTAL: MANUAL_SPELL(spell_portal); break; case SPELL_ARCANE_WORD: MANUAL_SPELL(spell_arcane_word); break; case SPELL_ARCANE_PORTAL: MANUAL_SPELL(spell_arcane_portal); break; } return (1); }