// $Id: spells.cc,v 1.13.2.29 2000/07/03 06:20:30 aasen Exp $
// $Revision: 1.13.2.29 $ $Author: aasen $ $Date: 2000/07/03 06:20:30 $
//
//ScryMUD Server Code
//Copyright (C) 1998 Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred)
// greearb@agcs.com
//
/* spells.cc: My first try at coding spells. These are quite messy
code-wise, but served as templates to second generation spells
(see the other files) */
#include "commands.h"
#include "command2.h"
#include "command3.h"
#include <stdio.h>
#include "misc.h"
#include "misc2.h"
#include "battle.h"
#include "classes.h"
#include "spells.h"
#include "skills.h"
#include "ez_spll.h"
#include "spells2.h"
#include "dam_spll.h"
#include "pet_spll.h"
#include "rm_spll.h"
#include "trv_spll.h"
#include <PtrArray.h>
#include "SkillSpell.h"
#include "clients.h"
int get_mana_cost(int spell_num) {
return SSCollection::instance().getSS(spell_num).getManaCost();
}
int get_mana_cost(int spell_num, critter& pc) {
float pl, mana_cost=SSCollection::instance().getSS(spell_num).getManaCost();
if (pc.isPc() && ((pl = (float)get_percent_lrnd(MANA_SKILL_NUM, pc)) > -1))
mana_cost-=mana_cost*(pl/900.0);
return (int)mana_cost;
}
void rem_effects_crit(int spell_num, critter &pc, short do_msg) {
String buf(100);
if (spell_num == ARMOR_SKILL_NUM) {
pc.AC -= ARMOR_EFFECT;
pc.SPEL_RESIS -= ARMOR_EFFECT_M;
if (do_msg)
show("You feel more vulnerable.\n", pc);
}//if
else if (spell_num == MAGIC_SHIELD_SKILL_NUM) {
pc.AC -= MAGIC_SHIELD_AC_EFFECT;
pc.SPEL_RESIS -= MAGIC_SHIELD_SAC_EFFECT;
if (do_msg)
show("Your magical shield dissipates.\n", pc);
}//if
else if (spell_num == FAERIE_FIRE_SKILL_NUM) {
pc.AC -= FAERIE_FIRE_AC_AUGMENTATION;
if (do_msg)
show("You stop glowing with an eerie purplish glow.\n", pc);
}//if
else if (spell_num == POISON_SKILL_NUM) {
pc.HP_REGEN -= POISON_HP_REGEN_AUGMENTATION;
pc.MA_REGEN -= POISON_MA_REGEN_AUGMENTATION;
pc.MV_REGEN -= POISON_MV_REGEN_AUGMENTATION;
if (do_msg)
show("Your bowels no longer scream in pain!", pc);
}//if
else if (spell_num == WEB_SKILL_NUM) {
pc.MV_REGEN -= WEB_MV_REGEN_AUGMENTATION;
pc.DEX -= WEB_DEX_AUGMENTATION;
if (do_msg)
show("You finally work your way out of the web.\n", pc);
}//if
else if (spell_num == SHADOWS_BLESSING_SKILL_NUM) {
pc.AC -= SHADOWS_BLESSING_EFFECT;
if (do_msg)
show("Your protective shadows fade away.\n", pc);
}//if
else if (spell_num == DETECT_MAGIC_SKILL_NUM) {
if (pc.pc) {
pc.PC_FLAGS.turn_off(18);
if (do_msg)
show("You can no longer detect magical auras.\n", pc);
}//if
}//if
else if (spell_num == DETECT_HIDDEN_SKILL_NUM) {
pc.SEE_BIT &= ~(4);
if (do_msg)
show("You no longer detect hidden things.\n", pc);
}//if
else if (spell_num == INFRAVISION_SKILL_NUM) {
pc.SEE_BIT &= ~(1);
if (do_msg)
show("You can no longer see in the dark.\n", pc);
}//if
else if (spell_num == DETECT_INVISIBILITY_SKILL_NUM) {
pc.SEE_BIT &= ~(2);
if (do_msg)
show("You no longer detect invisible things.\n", pc);
}//if
else if (spell_num == WEAKEN_SKILL_NUM) {
pc.STR -= WEAKEN_EFFECT;
if (do_msg)
show("You feel stronger!\n", pc);
}//if
else if (spell_num == SLEEP_SKILL_NUM) {
pc.CRIT_FLAGS.turn_off(15);
wake(pc);
}//if
else if (spell_num == FLESH_TO_STONE_SKILL_NUM) {
pc.CRIT_FLAGS.turn_off(14);
unpetrify(pc, do_msg); //more dire effects??
}//if
else if (spell_num == FLY_SKILL_NUM) {
pc.CRIT_FLAGS.turn_off(3);
lose_fly(pc, do_msg); //more dire effects??
}//if
else if (spell_num == ENTANGLE_SKILL_NUM) {
pc.MV_REGEN -= ENTANGLE_MV_REGEN_AUGMENTATION;
pc.DEX -= ENTANGLE_DEX_AUGMENTATION;
if (do_msg)
show("You finally work your way out of the entanglement.\n", pc);
}//if
else if (spell_num == FIREPROOF_SKILL_NUM) {
pc.HEAT_RESIS -= FIRE_PROOF_EFFECT;
if (do_msg)
show("You feel less protected from heat.\n", pc);
}//if
else if (spell_num == STRENGTH_SKILL_NUM) {
pc.STR -= STRENGTH_EFFECT;
if (do_msg)
show("You feel weaker.\n", pc);
}//if
else if (spell_num == HASTE_SKILL_NUM) {
pc.ATTACKS--;
if (do_msg)
show("You lose a little quickness.\n", pc);
}//if
else if (spell_num == PFE_SKILL_NUM) {
pc.CRIT_FLAGS.turn_off(24);
if (do_msg)
show("You no longer feel so protected.\n", pc);
}//if
else if (spell_num == PFG_SKILL_NUM) {
pc.CRIT_FLAGS.turn_off(25);
if (do_msg)
show("You no longer feel so protected.\n", pc);
}//if
else if (spell_num == DIVINE_PROTECTION_SKILL_NUM) {
pc.AC -= DIVINE_PROTECTION_EFFECT;
if (do_msg)
show("A divine force quits protecting you.\n", pc);
}//if
else if (spell_num == STONE_SKIN_SKILL_NUM) {
pc.DEX -= STONE_SKIN_EFFECT_DEX;
pc.DAM_REC_MOD -= STONE_SKIN_EFFECT_DRM;
if (do_msg)
show("Your skin softens.\n", pc);
}//if
else if (spell_num == BLINDNESS_SKILL_NUM) {
pc.SEE_BIT |= 1024;
if (do_msg)
show("A veil of darkness is lifted from your eyes.\n", pc);
}//if
else if (spell_num == ABSORB_BLOWS_SKILL_NUM) {
if (do_msg)
show("Your interdimensional lattice frays and falls apart.\n", pc);
}//if
else if (spell_num == PRISMATIC_GLOBE_SKILL_NUM) {
pc.AC -= PRISMATIC_GLOBE_EFFECT_AC;
pc.MOV -= PRISMATIC_GLOBE_EFFECT_MOV;
if (do_msg)
show("Your prismatic shield folds in upon itself and dissappears.\n",
pc);
}//if
else if (spell_num == SANCTUARY_SKILL_NUM) {
pc.DAM_REC_MOD -= SANCTUARY_EFFECT_DRM;
if (do_msg)
show("Your protective light fades.\n", pc);
}//if
else if (spell_num == BIND_WOUND_SKILL_NUM) {
pc.HP_REGEN -= BIND_WOUND_EFFECT;
if (do_msg)
show("Your bandage wears away.\n", pc);
}//if
else if (spell_num == BLESS_SKILL_NUM) {
pc.HIT -= BLESS_EFFECTS;
if (do_msg)
show("You feel slightly less blessed in the eyes of your lord.\n", pc);
}//if
else if ((spell_num == CHARM_SKILL_NUM) ||
(spell_num == MASS_CHARM_SKILL_NUM)) {
follow(1, &NULL_STRING, pc, do_msg);
}//if
else if (spell_num == INVISIBILITY_SKILL_NUM) {
pc.show("Your cloak of invisibility fades away.\n");
pc.VIS_BIT &= ~2;
}//if
else {
Sprintf(buf, "ERROR: rem_effects_crit DEFAULT: spll# [%i] %s.\n",
spell_num,
(const char*)(SSCollection::instance().getNameForNum(spell_num)));
mudlog.log(ERROR, buf);
}//switch
}// rem_effects_crit()
void rem_effects_obj(int spell_num, object &obj) {
String buf(100);
if (spell_num == RUNE_EDGE_SKILL_NUM) {
obj.OBJ_DAM_DICE_SIDES -= RUNE_EDGE_EFFECTS;
}//if
else if ((spell_num == FROST_BLADE_SKILL_NUM) ||
(spell_num == FIRE_BLADE_SKILL_NUM)) {
; //do nothing, losing spell is enough
}//if
else if (spell_num == INVISIBILITY_SKILL_NUM) {
obj.OBJ_VIS_BIT &= ~2;
}
else if (spell_num == WIZARD_EYE_SKILL_NUM) {
Sprintf(buf, "%S is no longer sending you visions.\n", obj.getName());
obj.obj_proc->w_eye_owner->show(buf);
obj.obj_proc->w_eye_owner->pc->w_eye_obj = NULL; //pc not looking at it anymore.
obj.obj_proc->w_eye_owner = NULL; //object not owned.
}
else {
Sprintf(buf, "ERROR: rem_effects_obj, not supported, spll# [%i] %s.\n",
spell_num, (const char*)(SSCollection::instance().getNameForNum(spell_num)));
mudlog.log(ERROR, buf);
}//else
}// rem_effects_obj()
void rem_effects_door(int spell_num, door& dr, room& rm1,
room& rm2, short do_msg) {
String buf(100);
if (spell_num == FIREWALL_SKILL_NUM) {
if (do_msg) {
show_all("The flames on the exit die down.\n", rm1);
show_all("The flames on the exit die down.\n", rm2);
}//if
}//if
else if (spell_num == DISTORTION_WALL_SKILL_NUM) {
if (do_msg) {
show_all("The distortion field fades.\n", rm1);
show_all("The distortion field fades.\n", rm2);
}//if
}//if
else {
Sprintf(buf, "ERROR: rem_effects_door, spll# [%i] %s.\n", spell_num,
(const char*)(SSCollection::instance().getNameForNum(spell_num)));
mudlog.log(ERROR, buf);
}//else
}// rem_effects_door()
void rem_effects_room(int spell_num, room &rm, short do_msg) {
String buf(100);
if (spell_num == ILLUMINATE_SKILL_NUM) {
rm.checkLight(do_msg);
}//if
else {
Sprintf(buf,
"ERROR: spell_num(%i) out of range in rem_effects_room.\n",
spell_num);
mudlog.log(ERROR, buf);
}//else
}// rem_effects_room()
void do_firewall_effects(critter& pc, int& is_dead) {
String buf(100);
is_dead = FALSE;
if (pc.isMob()) {
mudlog.log(ERROR, "ERROR: MOB sent to do_firewall_effects.\n");
return;
}//if
exact_raw_damage(d(10,5), FIRE, pc);
if (pc.HP < 0) {
emote("is burned to death!!", pc, ROOM, TRUE);
show("You have been burned to death!\n", pc);
agg_kills_vict(NULL, pc);
is_dead = TRUE;
}//if
else {
is_dead = FALSE;
show("OUCH!! You are singed as you enter.\n", pc);
emote("momentarily catches on fire!", pc, ROOM, TRUE);
}//else
}//do_firewall_effects(critter&
int do_distortion_wall_effects(critter& pc, int& is_dead, int sanity) {
String buf(100);
int retval;
if (pc.isMob()) {
mudlog.log(ERROR, "ERROR: MOB sent to do_distortion_wall_effects.\n");
is_dead = FALSE;
return -1;
}//if
show("**WOW**, as you step into the next room you encounter a strange
silvery curtain of....energy!\n", pc);
emote("blinks out of sight!", pc, ROOM, TRUE);
retval = relocate_within_zone(pc, is_dead, sanity, FALSE);
emote("materializes in front of you!", pc, ROOM, TRUE); //in new room now
return retval;
}//do_distortion_wall_effects
void do_cast_fireball(critter& vict, critter& agg, int is_canned, int lvl) {
String buf(100);
short do_join_in_battle = TRUE;
short do_fatality = FALSE;
int spell_num = FIREBALL_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, agg);
/* Check for: lost concentration, did_hit, !mag room */
/* Do: damage to vict, mana from agg, messages to all involved, */
/* increment pause_count, */
if (room_list[agg.getCurRoomNum()].isHaven()) {
show(NOT_IN_HAVEN_MSG, agg);
return;
}//if
if ((room_list[agg.getCurRoomNum()].isNoPK()) &&
(vict.pc && agg.pc)) {
show(NO_PK_HERE_MSG, agg);
return;
}//if
if (is_canned) {
if (did_spell_hit(vict, FIRE, agg, lvl, TRUE)) {
vict.HP -= d(4, 20) +
lvl - (int)((100.0 / (vict.HEAT_RESIS + 100)) * 20);
agg.PAUSE += 1; // increment pause_count
if (&vict == &agg) {
if (vict.HP < 0) {
show("You burn the flesh from your bones!\n", agg);
Sprintf(buf, "burns the flesh from %s living bones!\n",
get_his_her(agg));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
do_fatality = TRUE;
}//if
else {
show("You give yourself a taste of life after death!\n",
agg);
Sprintf(buf, "blasts %s with %s crimson inferno.\n",
get_himself_herself(vict),
get_his_her(agg));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
}//else
do_join_in_battle = FALSE;
}//if
else {
if (vict.HP < 0) {
Sprintf(buf, "You burn the flesh from %S's living bones!!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf,
"%S burns the flesh from your once living bones!\n",
name_of_crit(agg, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf, "burns the flesh from %S's living bones!\n",
name_of_crit(vict, ~0));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
do_fatality = TRUE;
}//if
else {
Sprintf(buf, "You give %S a taste of life after death!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S gives you a brief taste of hell!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "blasts %S with %s crimson inferno.\n",
name_of_crit(vict, ~0),
get_his_her(agg));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
}//else
}//else
}//if did_hit
else { //missed
agg.PAUSE += 1; // increment pause_count
if (&agg == &vict) {
show("You miss yourself with your sulpherous inferno.\n", agg);
Sprintf(buf, "misses %s with %s fireball.\n",
get_himself_herself(vict),
get_his_her(vict));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
do_join_in_battle = FALSE;
}//if
else {
Sprintf(buf, "You miss %S with your fireball.\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S narrowly misses you with a fireball!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "misses %S with %s fireball!\n",
name_of_crit(vict, ~0),
get_his_her(agg));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
}//else
}//else, missed with canned magic
}//if canned
else { //not canned
if (!lost_concentration(agg, spell_num)) {
if (&agg == &vict) {
show("It would be stupid to try to burn yourself!!\n", agg);
return;
}//if
if (did_spell_hit(agg, FIRE, vict)) {
exact_raw_damage(d(8, agg.LEVEL), FIRE, vict, agg);
if (vict.HP < 0) {
Sprintf(buf, "You burn the flesh from %S's living bones!!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf,
"%S burns the flesh from your once living bones!\n",
name_of_crit(agg, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf, "burns the flesh from %S's living bones!\n",
name_of_crit(vict, ~0));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
do_fatality = TRUE;
}//if
else {
Sprintf(buf, "You give %S a taste of life after death!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S gives you a brief taste of hell!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "blasts %S with %s crimson inferno.\n",
name_of_crit(vict, ~0),
get_his_her(agg));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE);
}//else not fatality
}//if did_hit
else { //missed
exact_raw_damage(d(3, agg.LEVEL) + agg.LEVEL, FIRE, vict, agg);
if (vict.HP < 0) {
Sprintf(buf, "You burn the flesh from %S's living bones!!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf,
"%S burns the flesh from your once living bones!\n",
name_of_crit(agg, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf, "burns the flesh from %S's living bones!\n",
name_of_crit(vict, ~0));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE, &vict);
do_fatality = TRUE;
}//if
else {
Sprintf(buf, "You singe %S with your fireball.\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S singes you with a fireball!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "singes %S with %s fireball!\n",
name_of_crit(vict, ~0),
get_his_her(agg));
emote(buf, agg, room_list[agg.getCurRoomNum()], TRUE, &vict);
}//else no fatality
}//missed
agg.MANA -= spell_mana;
agg.PAUSE += 1; // increment pause_count
}//if !lost concentration
else { //lost concentration
show(LOST_CONCENTRATION_MSG_SELF, agg);
emote("obviously forgot something!\n", agg,
room_list[agg.getCurRoomNum()], TRUE);
agg.MANA -= spell_mana / 2;
agg.PAUSE += 1;
}//else lost concentration
}//else !canned
if (do_join_in_battle && !HaveData(&vict, agg.IS_FIGHTING)) {
join_in_battle(agg, vict);
}//if
if (do_fatality) {
if (vict.mob && vict.MOB_FLAGS.get(16)) {
vict.MOB_FLAGS.turn_off(16);
}
agg_kills_vict(&agg, vict);
}//if
}//do_cast_fireball
void cast_fireball(int i_th, const String* victim, critter& pc) {
critter* vict = NULL;
int spell_num = FIREBALL_SKILL_NUM;
if (victim->Strlen() == 0)
vict = Top(pc.IS_FIGHTING);
else
vict = ROOM.haveCritNamed(i_th, victim, pc);
if (!vict) {
show("Whom do you wish to barbeque??\n", pc);
return;
}//if
if (vict->isMob()) {
vict = mob_to_smob(*vict, pc.getCurRoomNum(), TRUE, i_th,
victim, pc.SEE_BIT);
}//if
if (!ok_to_do_action(vict, "KMSN", spell_num, pc)) {
return;
}//if
if (!(vict = check_for_diversions(*vict, "SGM", pc)))
return;
/* all checks have been passed, lets do it */
do_cast_fireball(*vict, pc, FALSE, 0);
}//cast_fireball
void cast_summon(int i_th, const String* targ, critter& pc) {
int spell_num = SUMMON_SKILL_NUM;
String buf(100);
critter* vict = have_crit_named(pc_list, i_th, targ,
pc.SEE_BIT, ROOM);
if( config.newSummon)
{
int rm_num;
if (!vict) {
vict = have_crit_named(linkdead_list, i_th, targ,
pc.SEE_BIT, ROOM);
}
if (vict) {
rm_num = vict->getCurRoomNum();
}
else {
vict = room::haveCritNamedInWorld(i_th, targ, pc.SEE_BIT, rm_num);
}
}
if (!vict) {
show("You don't see that person!\n", pc);
return;
}//if
if (!ok_to_do_action(vict, "KMSNB", spell_num, pc)) {
return;
}//if
if (vict->isImmort() && (vict->getLevel() > pc.getLevel())) {
pc.show("You wish (and you suddenly feel hungry for your efforts!)!!\n");
if (pc.HUNGER > 0) {
pc.HUNGER = 0; //cause I'm evil!! --Ben
}
return;
}
if (ROOM.isNoMagEntry()) {
pc.show("You can't magically transport someone to this room!\n");
return;
}
/* all checks have been passed, lets do it */
do_cast_summon(*vict, pc, FALSE, 0); //does no error checking
}//cast_summon
void do_cast_summon(critter& vict, critter& pc, int is_canned, int lvl) {
String buf(100);
short do_affects = FALSE;
int spell_num = SUMMON_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, pc);
int lost_con = FALSE;
int did_hit = TRUE;
if (!is_canned)
lvl = pc.LEVEL;
if (is_canned || (!(lost_con = lost_concentration(pc, spell_num)) &&
(did_hit = did_spell_hit(pc, SUMMON, vict)))){
do_affects = TRUE;
if (!is_canned)
pc.MANA -= spell_mana;
}//else !canned
else if (lost_con) {
show(LOST_CONCENTRATION_MSG_SELF, pc);
emote(LOST_CONCENTRATION_MSG_OTHER, pc, ROOM, FALSE);
if (!is_canned)
pc.MANA -= spell_mana / 2;
}//else lost concentration
else {
Sprintf(buf, "You failed to summon %S.\n",
name_of_crit(vict, pc.SEE_BIT));
show(buf, pc);
Sprintf(buf, "%S tried but failed to summon you!\n",
name_of_crit(pc, vict.SEE_BIT));
show(buf, vict);
Sprintf(buf, "fails to summon %S.", name_of_crit(vict, ~0));
emote(buf, pc, ROOM, TRUE, &vict);
if (!is_canned)
pc.MANA -= spell_mana;
}//else
if (do_affects) {
if (!mob_can_enter(vict, ROOM, FALSE)) {
show("That person can't enter this room!\n", pc);
return;
}//if
if (vict.getCurRoom()->isNoMagExit()) {
pc.show("That person's area is impervious to your spell.\n");
return;
}
Sprintf(buf, "%S opens a portal above your head and yanks you through!\n",
name_of_crit(pc, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "is suddenly yanked through a portal that opens over %s head!",
get_his_her(vict));
emote(buf, vict, room_list[vict.getCurRoomNum()], TRUE);
Sprintf(buf, "has been summoned by %S.", name_of_crit(pc, ~0));
emote(buf, vict, ROOM, TRUE);
int is_dead;
vict.doGoToRoom(pc.getCurRoomNum(), NULL, NULL, is_dead,
vict.getCurRoomNum(), 1); //vict is always a PC
}//if do_affects
pc.PAUSE += 1;
// RJY [Trice] attempt to slap on ending tags
if( vict.isPc() && vict.isInBattle() ) {
if (vict.isUsingClient()) {
show(CTAG_END_BATTLE(vict.whichClient()), vict);
}
else if (vict.isUsingColor()) {
show(*(vict.getDefaultColor()), vict);
}
}
}//do_cast_summon
void cast_passdoor(int i_th, const String* drr, critter& pc) {
int spell_num = PASSDOOR_SKILL_NUM;
door* dr = door::findDoor(ROOM.DOORS, i_th, drr, pc.SEE_BIT, ROOM);
if (!dr) {
show("Which door do you wish to pass?\n", pc);
return;
}//if
if (!dr->isClosed()) {
show("It isn't even closed!\n", pc);
return;
}//if
if (dr->isMagLocked()) {
show("You can feel a power emanating from the door which would make", pc);
show("your spell fail horribly!\n", pc);
return;
}//if
if (dr->isNoPassdoor()) {
pc.show("This door is imbued with properties that block your spell!\n");
return;
}
if (!ok_to_do_action(NULL, "KMSNB", spell_num, pc)) {
return;
}//if
if (!(mob_can_enter(pc, room_list[abs(dr->destination)], TRUE)))
return;
do_cast_passdoor(*dr, pc, FALSE, 0); //does no error checking
}//cast_passdoor
void do_cast_passdoor(door& dr, critter& vict, int is_canned, int lvl) {
String buf(100);
short do_affects = FALSE;
int spell_num = PASSDOOR_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, vict);
if (!is_canned)
lvl = vict.LEVEL;
if (vict.isMob()) {
if (mudlog.ofLevel(WRN)) {
mudlog << "WARNING: MOB in do_cast_passdor." << endl;
}
return;
}//if
int lost_con = TRUE;
if (is_canned || !(lost_con = lost_concentration(vict, spell_num))) {
do_affects = TRUE;
if (!is_canned)
vict.MANA -= spell_mana;
}//else !canned
else { //lost con
show(LOST_CONCENTRATION_MSG_SELF, vict);
emote(LOST_CONCENTRATION_MSG_OTHER, vict,
room_list[vict.getCurRoomNum()], FALSE);
if (!is_canned)
vict.MANA -= spell_mana / 2;
}//else lost concentration
if (do_affects) {
show("You briefly step into another dimension!\n", vict);
emote("steps into another dimension.", vict,
room_list[vict.getCurRoomNum()], TRUE);
int is_dead;
vict.doGoToRoom(abs(dr.destination), NULL, NULL, is_dead,
vict.getCurRoomNum(), 1);
if (!is_dead) {
emote("steps back into your dimension.", vict,
room_list[vict.getCurRoomNum()], TRUE);
}
}//if do_affects
vict.PAUSE += 1; // increment pause_count
}//do_cast_passdoor
void cast_tammuz(int i_th, const String* victim, critter& pc) {
int spell_num = TAMMUZ_SKILL_NUM;
critter* vict = NULL;
if (victim->Strlen() == 0)
vict = &pc;
else {
vict = ROOM.haveCritNamed(i_th, victim, pc);
}//else
if (!vict) {
show("Transport who?\n", pc);
return;
}//if
if (!ok_to_do_action(vict, "KMSNB", spell_num, pc)) {
return;
}//if
do_cast_tammuz(*vict, pc, FALSE, 0); //does no error checking
}//cast_tammuz
void do_cast_tammuz(critter& vict, critter& pc, int is_canned, int lvl) {
String buf(100);
short do_affects = FALSE;
int spell_num = TAMMUZ_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, pc);
if (!is_canned)
lvl = pc.LEVEL;
int lost_con = TRUE;
if (pc.isMob()) {
if (mudlog.ofLevel(WRN)) {
mudlog << "WARNING: MOB in do_cast_tammuz." << endl;
}
return;
}//if
if (pc.getCurRoom()->isNoMagExit()) {
vict.show("You cannot leave this place by magical means!\n");
return;
}
if (is_canned || !(lost_con = lost_concentration(pc, spell_num))) {
do_affects = TRUE;
if (!is_canned)
pc.MANA -= spell_mana;
}//else !canned
else { //lost con
show(LOST_CONCENTRATION_MSG_SELF, pc);
emote(LOST_CONCENTRATION_MSG_OTHER, pc, ROOM, FALSE);
if (!is_canned)
pc.MANA -= spell_mana / 2;
}//else lost concentration
if (do_affects) {
show("The world shimmers!\n", vict);
emote("grows plaid and disappears.", vict,
room_list[vict.getCurRoomNum()], TRUE);
int is_dead;
vict.doGoToRoom(config.tammuzRoom, NULL, NULL, is_dead,
vict.getCurRoomNum(), 1);
if (!is_dead) {
emote("blinks into existence.", vict, room_list[vict.getCurRoomNum()],
TRUE);
}//if
}//if do_affects
vict.PAUSE += 1; // increment pause_count
}//do_cast_tammuz
void cast_recall(int i_th, const String* victim, critter& pc) {
int spell_num = RECALL_SKILL_NUM;
critter* vict = NULL;
if (victim->Strlen() == 0)
vict = &pc;
else {
vict = ROOM.haveCritNamed(i_th, victim, pc);
}//else
if (!vict) {
show("Recall who?\n", pc);
return;
}//if
if (!ok_to_do_action(vict, "KMSN", spell_num, pc)) {
return;
}//if
do_cast_recall(*vict, pc, FALSE, 0); //does no error checking
}//cast_recall
void do_cast_recall(critter& vict, critter& pc, int is_canned, int lvl) {
String buf(100);
short do_affects = FALSE;
int spell_num = RECALL_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, pc);
if (!is_canned)
lvl = pc.LEVEL;
int lost_con = TRUE;
if (pc.isMob()) {
if (mudlog.ofLevel(WRN)) {
mudlog << "WARNING: MOB in do_cast_recall." << endl;
}
return;
}//if
if (vict.isNPC()) {
pc.show("You cannot recall NPC players.\n");
return;
}
if (pc.getCurRoom()->isNoMagExit()) {
vict.show("You cannot leave this place by magical means!\n");
return;
}
if (is_canned || !(lost_con = lost_concentration(pc, spell_num))) {
do_affects = TRUE;
if (!is_canned)
pc.MANA -= spell_mana;
}//else !canned
else { //lost con
show(LOST_CONCENTRATION_MSG_SELF, pc);
emote(LOST_CONCENTRATION_MSG_OTHER, pc, ROOM, FALSE);
if (!is_canned)
pc.MANA -= spell_mana / 2;
}//else lost concentration
if (do_affects) {
show("The world shimmers!\n", vict);
emote("grows translucent and disappears.", vict,
room_list[vict.getCurRoomNum()], TRUE);
int is_dead;
vict.doGoToRoom(config.recallRoom, NULL, NULL, is_dead,
vict.getCurRoomNum(), 1);
if (!is_dead) {
emote("blinks into existence.", vict, room_list[vict.getCurRoomNum()],
TRUE);
}//if
}//if do_affects
vict.PAUSE += 1; // increment pause_count
}//do_cast_recall
void cast_teleport(int i_th, const String* targ, critter& pc) {
int spell_num = TELEPORT_SKILL_NUM;
String buf(100);
critter* vict = have_crit_named(pc_list, i_th, targ, pc.SEE_BIT, ROOM);
if( config.newTeleport)
{
int rm_num;
if (!vict) {
vict = have_crit_named(linkdead_list, i_th, targ,
pc.SEE_BIT, ROOM);
}
if (vict) {
rm_num = vict->getCurRoomNum();
}
else {
vict = room::haveCritNamedInWorld(i_th, targ, pc.SEE_BIT, rm_num);
}
if (!vict) {
show("That person is not to be found.\n", pc);
return;
}//if
}
if (!ok_to_do_action(NULL, "KMSN", spell_num, pc)) {
return;
}//if
if( config.newTeleport)
{
do_cast_teleport(*vict, pc, FALSE, 0); //does no error checking
}
else
{
do_cast_teleport(pc, pc, FALSE, 0); //does no error checking
}
}//cast_teleport
void do_cast_teleport(critter& vict, critter& pc, int is_canned, int lvl) {
String buf(100);
int new_room_num = FALSE;
short done = FALSE, do_affects = FALSE;
int spell_num = TELEPORT_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, pc);
//log("in do_cast_teleport\n");
if (!is_canned)
lvl = pc.LEVEL;
int lost_con = TRUE;
if (pc.getCurRoom()->isNoMagExit()) {
vict.show("You cannot leave this place by magic means!\n");
return;
}
if( config.newTeleport )
{
if (vict.getCurRoom()->isNoMagEntry()) {
pc.show("You can't magically transport to that room!\n");
return;
}
}
if (is_canned || !(lost_con = lost_concentration(pc, spell_num))) {
do_affects = TRUE;
if (!is_canned)
pc.MANA -= spell_mana;
}//else !canned
else { //lost con
show(LOST_CONCENTRATION_MSG_SELF, pc);
emote(LOST_CONCENTRATION_MSG_OTHER, pc,
room_list[pc.getCurRoomNum()], FALSE);
if (!is_canned)
pc.MANA -= spell_mana / 2;
}//else lost concentration
if (do_affects) {
show("The world shimmers!\n", vict);
emote("grows translucent and disappears.", vict,
room_list[pc.getCurRoomNum()], TRUE);
int sanity = 0;
while (!done) {
if (sanity++ > 10) {
if (mudlog.ofLevel(DBG)) {
mudlog << "WARNING: Sanity check failed in do_cast_teleport."
<< " vict: " << *(name_of_crit(vict, ~0)) << endl;
}
emote("disappears briefly and then shimmers back into existence.",
vict, room_list[pc.getCurRoomNum()], TRUE);
break;
}
if( config.newTeleport)
{
int is_dead;
new_room_num = vict.getCurRoomNum();
if ((mob_can_enter(pc, room_list[new_room_num], FALSE)) &&
(!room_list[new_room_num].isNoMagEntry())) {
done = TRUE;
emote("shimmers into existence.", vict,
room_list[vict.getCurRoomNum()], TRUE);
pc.doRemoveFromBattle();
pc.doGoToRoom(vict.getCurRoomNum(), NULL, NULL,is_dead, pc.getCurRoomNum(), 1);
if (is_dead)
return;
}//if
}
else
{
int is_dead;
new_room_num = d(1, Cur_Max_Room_Num);
if ((mob_can_enter(pc, room_list[new_room_num], FALSE)) &&
(!room_list[new_room_num].isNoMagEntry())) {
done = TRUE;
emote("shimmers into existence.", vict,
room_list[pc.getCurRoomNum()], TRUE);
pc.doRemoveFromBattle();
pc.doGoToRoom(new_room_num, NULL, NULL, is_dead,
pc.getCurRoomNum(), 1);
if (is_dead)
return;
}//if
}
}//while
vict.doRemoveFromBattle();
}//if do_affects
vict.PAUSE += 1; // increment pause_count
// RJY [Trice] attempt to slap in ending battle TAGS
if( pc.isInBattle() )
{
if (pc.isUsingClient()) {
show(CTAG_END_BATTLE(pc.whichClient()), pc);
}
else if (pc.isUsingColor()) {
show(*(pc.getDefaultColor()), pc);
}
}
}//do_cast_teleport
void cast_poison(int i_th, const String* victim, critter& pc) {
critter* vict = NULL;
int spell_num = POISON_SKILL_NUM;
if (victim->Strlen() == 0)
vict = Top(pc.IS_FIGHTING);
else
vict = ROOM.haveCritNamed(i_th, victim, pc);
if (!vict) {
show("Who do you wish to poison??\n", pc);
return;
}//if
if (vict->isMob()) {
vict = mob_to_smob(*vict, pc.getCurRoomNum(), TRUE, i_th,
victim, pc.SEE_BIT);
}//if
if (!ok_to_do_action(vict, "KMSNV", spell_num, pc)) {
return;
}//if
do_cast_poison(*vict, pc, FALSE, 0); //does no error checking
}//cast_poison
void do_cast_poison(critter& vict, critter& agg, int is_canned, int lvl) {
String buf(100);
short do_effects = FALSE;
short do_join_in_battle = TRUE;
int spell_num = POISON_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, agg);
if (!is_canned)
lvl = agg.LEVEL;
if (is_canned) {
if (did_spell_hit(vict, CRONIC, agg, lvl, TRUE)) {
do_effects = TRUE;
if (&vict == &agg) {
show("You feel sick!\n", vict);
emote("turns green and looks quite sick.", agg,
room_list[agg.getCurRoomNum()], TRUE);
do_join_in_battle = FALSE;
}//if
else {
Sprintf(buf, "You poison %S!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S has poisoned you!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
Sprintf(buf, "%S poisons %S.\n",
name_of_crit(agg, ~0), name_of_crit(vict, ~0));
buf.Cap();
show_all_but_2(agg, vict, buf, room_list[agg.getCurRoomNum()]);
}//else
}//if did_hit
else { //missed
if (&agg == &vict) {
show("You can't even manage to poison yourself.\n", agg);
do_join_in_battle = FALSE;
}//if
else {
Sprintf(buf, "You fail to poison %S.\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S fails to poison you!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
}//else
agg.PAUSE += 1; // increment pause_count
}//else, missed with canned magic
}//if canned
else {//not canned
if (&agg == &vict) {
show("You would feel stupid if you poisoned yourself on purpose.\n",
agg);
return;
}//if
if (!lost_concentration(agg, spell_num)) {
if (did_spell_hit(agg, CRONIC, vict)) {
do_effects = TRUE;
Sprintf(buf, "You poison %S!\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S poisons you!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
}//if did_hit
else { //missed
Sprintf(buf, "You fail to poison %S.\n",
name_of_crit(vict, agg.SEE_BIT));
show(buf, agg);
Sprintf(buf, "%S tries and fails to poison you!\n",
name_of_crit(agg, vict.SEE_BIT));
buf.Cap();
show(buf, vict);
}//missed
agg.MANA -= spell_mana;
agg.PAUSE += 1; // increment pause_count
}//if ! lost concentration
else { //lost concentration
show(LOST_CONCENTRATION_MSG_SELF, agg);
emote(LOST_CONCENTRATION_MSG_OTHER, agg, *(agg.getCurRoom()), TRUE);
agg.MANA -= spell_mana / 2;
agg.PAUSE += 1;
}//else
}//else !canned
if (do_effects) {
stat_spell_cell* sp;
Cell<stat_spell_cell*> cll(vict.affected_by);
while ((sp = cll.next())) {
if (sp->stat_spell == spell_num) {
sp->bonus_duration += (int)((float)(lvl) / 3.0);
return;
}//if
}//while
Put(new stat_spell_cell(spell_num, lvl/3), vict.affected_by);
vict.HP_REGEN += POISON_HP_REGEN_AUGMENTATION;
vict.MV_REGEN += POISON_MV_REGEN_AUGMENTATION;
vict.MA_REGEN += POISON_MA_REGEN_AUGMENTATION;
}//if
if (do_join_in_battle && !HaveData(&vict, agg.IS_FIGHTING)) {
join_in_battle(agg, vict);
}//if
}//do_cast_poison
void cast_illuminate(critter& pc) {
int spell_num = ILLUMINATE_SKILL_NUM;
if (!ok_to_do_action(NULL, "KMSN", spell_num, pc)) {
return;
}//if
do_cast_illuminate(ROOM, pc, FALSE, 0); //does no error checking
}//cast_illuminate
void do_cast_illuminate(room& rm, critter& agg, int is_canned,
int lvl) {
int spell_num = ILLUMINATE_SKILL_NUM;
int spell_mana = get_mana_cost(spell_num, agg);
String buf(100);
short do_effects = FALSE;
if (room_list[agg.getCurRoomNum()].isNoMagic()) {
show(NOT_IN_NOMAG_RM_MSG, agg);
return;
}//if
if (!is_canned)
lvl = agg.LEVEL;
agg.PAUSE += 1;
if (is_canned) {
do_effects = TRUE;
show("You enlighten the room!\n", agg);
emote("enlightens the room.", agg, rm, TRUE);
}//if canned
else {//not canned
if (!lost_concentration(agg, spell_num)) {
do_effects = TRUE;
show("You enlighten the room!\n", agg);
emote("enlightens the room.", agg, rm, TRUE);
agg.MANA -= spell_mana;
}//if ! lost concentration
else { //lost concentration
show(LOST_CONCENTRATION_MSG_SELF, agg);
emote(LOST_CONCENTRATION_MSG_OTHER, agg, rm, TRUE);
agg.MANA -= spell_mana / 2;
}//else
}//else !canned
if (do_effects) {
mudlog.log(DBG, "Doing illuminate effects.\n");
stat_spell_cell* sp;
Cell<stat_spell_cell*> cll(rm.affected_by);
while ((sp = cll.next())) {
if (sp->stat_spell == spell_num) {
sp->bonus_duration += (int)((float)(lvl) / 2.0);
return;
}//if
}//while
obj_ptr_log << "NOTE " << rm.getIdNum() << " " << &rm
<< "Adding to affected_rooms bcause of illuminate." << endl;
affected_rooms.gainData(&rm); //add to global affected list so
//spell can wear off eventually
Put(new stat_spell_cell(spell_num, lvl/2), rm.affected_by);
rm.setVisBit(rm.getVisBit() & ~1); //make it light
}//if
}//do_cast_illuminate
//******************************************************************//
///************** auxillary spell/skill functions *************///
//******************************************************************//
int has_all_prereqs(int skill_num, critter& pc) {
Cell<int> cll(SSCollection::instance().getSS(skill_num).prereqs);
int tmp;
int retval;
while ((tmp = cll.next())) {
if (pc.SKILLS_KNOWN.Find(tmp, retval)) {
if (retval < 50)
return FALSE;
}//if
else
return FALSE;
}//while
return TRUE;
}//has_all_prereqs
void update_skills(critter& pc) {
int key;
if (pc.SKILLS_KNOWN.Min(key)) {
update_skill(key, pc);
while (pc.SKILLS_KNOWN.Next(key)) {
update_skill(key, pc);
}//while
}//if
}//update_skills
void update_skill(int last_learned, critter& pc) {
if (!pc.pc) {
return;
}//if
if (get_percent_lrnd(last_learned, pc) < 50) {
return;
}
if (!check_l_range(last_learned, 0, NUMBER_OF_SKILL_SPELLS, pc, FALSE)) {
mudlog.log(ERROR,
"ERROR: last_learned out of range, gain_spells_skills!!\n");
return;
}//if
Cell<int> cll(SSCollection::instance().getSS(last_learned).enables);
int tmp;
while ((tmp = cll.next())) {
if (has_all_prereqs(tmp, pc) && (get_percent_lrnd(tmp, pc) == -1)) {
pc.SKILLS_KNOWN.Insert(tmp, 1);
if (tmp == WEAPON_MASTERY_SKILL_NUM)
pc.DAM++;
else if (tmp == HONOR_CODE_SKILL_NUM)
pc.WIS++;
else if (tmp == LEADERSHIP_SKILL_NUM)
pc.CHA++;
else if (tmp == QUICKFOOT_SKILL_NUM)
pc.DEX++;
else if (tmp == WRESTLING_SKILL_NUM)
pc.BH_DICE_COUNT++;
// This needs to be done in do_battle(), otherwise +1 attack items only work
// for people with at least 1% in second attack.
// else if (tmp == SECOND_ATTACK_SKILL_NUM)
// pc.ATTACKS++;
else if (tmp == CLIMBING_SKILL_NUM)
pc.CRIT_FLAGS.turn_on(5);
else if (tmp == DUAL_WIELD_SKILL_NUM)
pc.CRIT_FLAGS.turn_on(16);
else if (tmp == LOGIC_SKILL_NUM)
pc.CHA--; //logical people are boring!!
else if (tmp == MARTIAL_ARTS_SKILL_NUM) {
pc.BH_DICE_COUNT++;
pc.BH_DICE_SIDES += 2;
}//martail arts
}//if
}//while
}//gain_spells_skills
short lost_concentration(critter& agg, int spell_num) {
int percent_lrned = 0, i;
// log("In lost_concentration\n");
if (agg.pc) {
agg.SKILLS_KNOWN.Find(spell_num, percent_lrned);
}//if
else { //not a pc
percent_lrned = 50 + (2 * agg.LEVEL);
}// else
i = (int)(((float)percent_lrned / 50.0) *
(float)(agg.WIS + agg.INT + agg.LEVEL + 130));
return (d(1, 100) >= d(1, i));
}//lost_concentration
int relocate_within_zone(critter& pc, int& is_dead, int sanity, int do_msgs) {
if (sanity > 20) {
mudlog << "ERROR: sanity check failed in relocate_within_zone."
<< endl;
is_dead = FALSE;
return FALSE;
}
int zn = ROOM.getZoneNum();
int begin_rm = ZoneCollection::instance().elementAt(zn).getBeginRoomNum();
int end_rm = ZoneCollection::instance().elementAt(zn).getEndRoomNum();
int count = 0;
int new_room_num;
while (TRUE) {
new_room_num = begin_rm + d(1, (end_rm - begin_rm));
if (count++ > 15)
new_room_num = pc.getCurRoomNum();
if (mob_can_enter(pc, room_list[new_room_num], FALSE)) {
pc.doGoToRoom(new_room_num, NULL, NULL, is_dead, pc.getCurRoomNum(),
sanity, do_msgs);
return TRUE;
}//if
if (count++ > 15) {
is_dead = FALSE;
return FALSE; //should never get here I think
}
}//while
}//relocate_within_zone