/* * healmagic.cpp * Healing magic routines. * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * Permission to use, modify and distribute is granted via the * Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License * http://creativecommons.org/licenses/by-nc-sa/3.0/ * * Copyright (C) 2007-2009 Jason Mitchell, Randi Mitchell * Contributions by Tim Callahan, Jonathan Hseu * Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman * */ #include "mud.h" #include "magic.h" #include "effects.h" #include "move.h" //********************************************************************* // healCombatCheck //********************************************************************* bool healCombatCheck(Creature* healer, Creature* target, bool print=true) { Monster* mTarget = target->getMonster(); if(!mTarget) return(true); if(mTarget->isPet() && mTarget->following == healer) return(true); if(!mTarget->getMonster()->nearEnemy()) return(true); if(target->getMonster()->isEnmCrt(healer->name)) return(true); // if healer is in group with pet, they can heal ctag* cp = (healer->following ? healer->following : healer)->first_fol; while(cp) { if(cp->crt == healer) return(true); cp = cp->next_tag; } if(print) healer->print("Not while %N is in combat with someone.\n", target); return(false); } //********************************************************************* // getHeal //********************************************************************* int getHeal(Creature *healer, Creature* target, int spell) { Player *pHealer = healer->getPlayer(); int level=0, statBns=0, base=0, mod=0, heal=0, dmg=0; int vigPet=0; ctag *cp=0; if(target) { /* Mobs with intelligence > 12 do not like people vigging their enemies and will attack them. -TC */ if(target != healer && target->isPlayer() && target->inCombat()) { cp = target->getRoom()->first_mon; while(cp) { if(cp->crt->intelligence.getCur() > 120 && cp->crt->getMonster()->isEnmCrt(target->name)) cp->crt->getMonster()->addEnmCrt(healer); cp = cp->next_tag; } } if(target == healer) target = 0; } level = healer->getLevel(); if(pHealer && pHealer->getClass() == CLERIC && (pHealer->getSecondClass() == FIGHTER || pHealer->getSecondClass() == ASSASSIN) ) level /= 2; if(target) vigPet = target->isPet() && target->following == healer; switch(spell) { case S_VIGOR: base = mrand(1,8); //1d8 break; case S_MEND_WOUNDS: base = dice(2,7,0); //2d7 break; case S_REJUVENATE: base = dice(1,6,1); // 1d6+1 break; } switch(healer->getClass()) { case CLERIC: statBns = bonus((int)healer->piety.getCur()); switch(healer->getDeity()) { case CERIS: if(healer->getAdjustedAlignment() == BLOODRED || healer->getAdjustedAlignment() == ROYALBLUE) { healer->print("Your healing is not as effective while so far out of natural balance.\n"); level /= 2; } mod = level / 2 + mrand(1, 1 + level / 2); if(healer->getAdjustedAlignment() == NEUTRAL) { if(spell != S_REJUVENATE) healer->print("Your harmonial balance gains you power with Ceris.\n"); mod += mrand(1,4); } if(spell == S_MEND_WOUNDS) mod += level / 2; if(spell == S_REJUVENATE) mod = level / 3 + mrand(1, 1 + level / 3); break; case ARES: level /= 2; // Ares clerics vig as if 1/2 their level if(healer->getAdjustedAlignment() >= BLUISH || healer->getAdjustedAlignment() <= REDDISH) { healer->print("Your soul is too far out of balance.\n"); level /= 2; } mod = level / 2 + mrand(1, 1 + level / 2); if(spell == S_MEND_WOUNDS) mod += level / 2; break; case KAMIRA: level = (level*3)/4; if(healer->getAdjustedAlignment() < PINKISH) { healer->print("Being evil at heart is distorting your healing magic.\n"); level /= 2; } mod = level / 2 + mrand(1, 1 + level / 2); if(spell == S_MEND_WOUNDS) mod += level / 2; break; case JAKAR: if(healer->getAdjustedAlignment() != NEUTRAL) { healer->print("Your soul is out of balance.\n"); level /= 2; } mod = level / 2 + mrand(1, 1 + level / 2); if(spell == S_MEND_WOUNDS) mod += level / 2; mod = (mod*3)/4; break; }// end deity switch break; case DRUID: statBns = MAX(bonus((int)healer->intelligence.getCur()), bonus((int)healer->constitution.getCur())); mod = level/4 + mrand(1, 1 + level / 5); break; case THIEF: case ASSASSIN: case ROGUE: case FIGHTER: case BERSERKER: case WEREWOLF: statBns = bonus((int)healer->constitution.getCur()); mod = 0; break; case MONK: statBns = bonus((int)healer->constitution.getCur()); mod = mrand(1,6); break; case RANGER: case BARD: case VAMPIRE: statBns = MAX(bonus((int)healer->piety.getCur()), bonus((int)healer->intelligence.getCur())); mod = mrand(1,6); break; case MAGE: statBns = MAX(bonus((int)healer->piety.getCur()), bonus((int)healer->intelligence.getCur())); mod = 0; break; case CARETAKER: case DUNGEONMASTER: statBns = MAX(bonus((int)healer->piety.getCur()), bonus((int)healer->intelligence.getCur())); mod = mrand(level/2, level); break; default: statBns = 0; mod = 0; break; } // end class switch // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // clerics and paladins of Gradius if(healer->getDeity() == GRADIUS) { statBns = bonus((int)healer->piety.getCur()); if(pHealer && !pHealer->alignInOrder()) { healer->print("You are out of balance with the earth. Your healing is weakened.\n"); level /= 2; } if(target && target->isAntiGradius()) { healer->print("%s is very puzzled by your healing beings of vile races.\n", gConfig->getDeity(healer->getDeity())->getName().c_str()); mod /= 2; } if(healer->getClass() == CLERIC) { mod = level / 2 + mrand(1, 1 + level / 2); if(spell == S_MEND_WOUNDS) mod += level / 2; mod = (mod*3)/4; } else { if(spell == S_VIGOR) mod = level / 3 + mrand(1, 1 + level / 4); else mod = level / 2 + mrand(1, 1 + level / 3); } // clerics and paladins of Enoch and Linothan } else if(healer->getDeity() == ENOCH || healer->getDeity() == LINOTHAN) { statBns = bonus((int)healer->piety.getCur()); if(pHealer && !pHealer->alignInOrder()) { healer->print("Your healing magic is weakened from lack of faith in %s.\n", gConfig->getDeity(healer->getDeity())->getName().c_str()); level /= 2; } if(target && target->getAdjustedAlignment() < NEUTRAL && healer != target) { healer->print("It concerns %s that you heal the unrighteous and impure of heart.\n", gConfig->getDeity(healer->getDeity())->getName().c_str()); healer->subAlignment(1); mod /= 2; } if(healer->getClass() == CLERIC) { mod = level / 2 + mrand(1, 1 + level / 2); if(spell == S_MEND_WOUNDS) mod += level / 2; } else { if(spell == S_VIGOR) mod = level / 3 + mrand(1, 1 + level / 4); else mod = level / 2 + mrand(1, 1 + level / 3); } // clerics and deathknights of Aramon and Arachnus } else if(healer->getDeity() == ARAMON || healer->getDeity() == ARACHNUS) { statBns = bonus((int)healer->piety.getCur()); if(pHealer && !pHealer->alignInOrder()) level /= 2; if(healer->getAdjustedAlignment() >= LIGHTBLUE) { healer->print("FOOL! You dare turn from %s's evil ways!\n", gConfig->getDeity(healer->getDeity())->getName().c_str()); dmg = mrand(1,10); healer->print("You are shocked for %d damage by %s's wrath!\n", dmg, gConfig->getDeity(healer->getDeity())->getName().c_str()); broadcast(healer->getSock(), healer->getRoom(), "%M doubles over in pain and wretches.\n", healer); healer->hp.decrease(dmg); mod = 0; } else if(target && healer != target && !vigPet) { if(target->getAdjustedAlignment() > LIGHTBLUE) { healer->print("How DARE you heal the righteous and good of heart!\n"); dmg = mrand(1,10); healer->print("You are shocked for %d damage by %s's wrath!\n", dmg, gConfig->getDeity(healer->getDeity())->getName().c_str()); broadcast(healer->getSock(), healer->getRoom(), "%M doubles over in pain and wretches.\n", healer); healer->hp.decrease(dmg); mod = 0; } else if( healer->getDeity() == ARAMON || ( healer->getDeity() == ARACHNUS && (healer->willIgnoreIllusion() ? target->getRace() : target->getDisplayRace()) != DARKELF )) { if(healer->getDeity() == ARAMON) healer->print("%s disapproves of healing others than yourself.\n", gConfig->getDeity(healer->getDeity())->getName().c_str()); else healer->print("%s disapproves of healing non-dark-elves.\n", gConfig->getDeity(healer->getDeity())->getName().c_str()); mod = mrand(1, (1 + level / 5)); } } else { if(healer->getClass() == CLERIC) { mod = level / 2 + mrand(1, 1 + level / 2); if(spell == S_MEND_WOUNDS) mod += level / 2; } else { mod = level / 4 + mrand(1, 1 + level / 4); } } } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- heal = base + statBns + mod; if(healer->getRoom()->magicBonus()) { if(spell == S_MEND_WOUNDS) heal += mrand(1, 6); else heal += mrand(1, 3); healer->print("The room's magical properties increase the power of your spell.\n"); } if(target && healer != target) { if(target->isPlayer()) { if(target->isEffected("stoneskin")) heal /= 2; if(target->flagIsSet(P_POISONED_BY_PLAYER)) heal = mrand(1,4); if(target->flagIsSet(P_OUTLAW) && target->getRoom()->flagIsSet(R_OUTLAW_SAFE)) heal = mrand(1,3); } } else { if(healer->isEffected("stoneskin")) heal /= 2; if(healer->flagIsSet(P_OUTLAW) && healer->getRoom()->flagIsSet(R_OUTLAW_SAFE)) heal = mrand (1,3); } return(MAX(1, heal)); } void niceExp(Creature *healer, Creature *creature, int heal, int how) { Player *player=0, *target=0; int exp=0; if(how != CAST) return; // only players are allowed to use this function! It's called from creature-spells // though, so we have to cast player = healer->getPlayer(); target = creature->getPlayer(); if(!player || !target || healer == target) return; if(player->getDeity() == CERIS || player->getDeity() == ENOCH || player->getDeity() == LINOTHAN) exp = MAX(1, heal) / 4; else exp = MAX(1, heal) / 3; if(player->getDeity() == ARAMON) exp = 0; // also see getHeal for copy of this if( player->getDeity() == ARACHNUS && ( target->getAdjustedAlignment() > LIGHTBLUE || (player->willIgnoreIllusion() ? target->getRace() : target->getDisplayRace()) != DARKELF) ) exp = 0; if(exp && (target->hp.getCur() < target->hp.getMax())) { if(player->halftolevel()) exp = 0; player->addExperience(exp); healer->print("You %s %d experience for your deed.\n", gConfig->isAprilFools() ? "lose" : "gain", exp); player->checkLevel(); } } //********************************************************************* // canCastHealing //********************************************************************* bool canCastHealing(Creature* player, Creature* target, bool rej=false, bool healSpell=false, bool print=true) { if(!healCombatCheck(player, target, print)) return(false); if(target->isEffected("petrification")) { if(print) player->print("Your %s magic is ineffective.\n", rej ? "healing" : "rejuvinating"); return(false); } // for a lich, a heal spell is offensive magic if(target->getClass() == LICH && healSpell) return(true); if(target->getClass() == LICH) { if(print) player->print("The aura of death around %N nullifies your %s magic.\n", target, rej ? "healing" : "rejuvinating"); return(false); } if(!rej && target->isEffected("stoneskin")) { // don't check this for liches if(print) player->print("%M's stoneskin spell reflects your %s magic.\n", target, rej ? "healing" : "rejuvinating"); return(false); } if(checkRefusingMagic(player, target, true, print)) return(false); if(!rej && target->hp.getCur() >= target->hp.getMax()) { if(print) player->print("%M is at full health right now.\n", target); return(false); } return(true); } //********************************************************************* // splVigor //********************************************************************* // This function will cause the vigor spell to be cast on a player or // another monster. int splVigor(Creature* player, cmd* cmnd, SpellData* spellData) { Creature* target=0; int heal=0; if(player->getClass() == LICH) { player->print("Your class prevents you from casting that spell.\n"); return(0); } // Vigor self if(cmnd->num == 2) { if( player->hp.getCur() >= player->hp.getMax() && !player->checkStaff("You are already at full health right now.\n") ) return(0); if(spellData->how == CAST) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); heal = getHeal(player, 0, S_VIGOR); } else heal = mrand(1, 8); player->hp.increase(heal); if(spellData->how == CAST || spellData->how == SCROLL) { player->print("Vigor spell cast.\n"); broadcast(player->getSock(), player->getRoom(), "%M casts a vigor spell on %sself.", player, player->himHer()); return(1); } else { player->print("You feel better.\n"); return(1); } // Cast vigor on another player or monster } else { if(noPotion(player, spellData)) return(0); cmnd->str[2][0] = up(cmnd->str[2][0]); target = player->getRoom()->findCreature(player, cmnd->str[2], cmnd->val[2], false); if(!target) { player->print("That person is not here.\n"); return(0); } if(!canCastHealing(player, target)) return(0); if(target->inCombat(false)) player->smashInvis(); if(spellData->how == CAST) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); heal = getHeal(player, target, S_VIGOR); } else heal = mrand(1, 8); target->hp.increase(heal); if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) { player->print("Vigor spell cast on %N.\n", target); target->print("%M casts a vigor spell on you.\n", player); broadcast(player->getSock(), target->getSock(), player->getRoom(), "%M casts a vigor spell on %N.", player, target); niceExp(player, target, heal, spellData->how); return(1); } } return(1); } //********************************************************************* // splMendWounds //********************************************************************* // This function will cause the mend spell to be cast on a player or // another monster. It heals 2d7 hit points plus any bonuses for // intelligence. If the player is a cleric then there is an additional // point of healing for each level of the cleric. int splMendWounds(Creature* player, cmd* cmnd, SpellData* spellData) { Creature* target=0; int heal=0; if(player->getClass() == LICH) { player->print("Your class prevents you from casting that spell.\n"); return(0); } // Mend self if(cmnd->num == 2) { if( player->hp.getCur() >= player->hp.getMax() && !player->checkStaff("You are already at full health right now.\n") ) return(0); if(spellData->how == CAST) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); heal = getHeal(player, 0, S_MEND_WOUNDS); } else heal = dice(2, 7, 0); addhp(player, heal); if(spellData->how == CAST || spellData->how == SCROLL) { player->print("Mend-wounds spell cast.\n"); broadcast(player->getSock(), player->getRoom(), "%M casts a mend-wounds spell on %sself.", player, player->himHer()); return(1); } else { player->print("You feel better.\n"); return(1); } // Cast mend on another player or monster } else { if(noPotion(player, spellData)) return(0); cmnd->str[2][0] = up(cmnd->str[2][0]); target = player->getRoom()->findCreature(player, cmnd->str[2], cmnd->val[2], false); if(!target) { player->print("That person is not here.\n"); return(0); } if(!healCombatCheck(player, target)) return(0); if(target->inCombat(false)) player->smashInvis(); if(spellData->how == CAST) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); heal = getHeal(player, target, S_MEND_WOUNDS); } else heal = dice(2, 8, 0); addhp(target, heal); if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) { player->print("Mend-wounds spell cast on %N.\n", target); target->print("%M casts a mend-wounds spell on you.\n", player); broadcast(player->getSock(), target->getSock(), player->getRoom(), "%M casts a mend-wounds spell on %N.", player, target); niceExp(player, target, heal, spellData->how); return(1); } } return(1); } //********************************************************************* // splRejuvenate //********************************************************************* // This function will cause the vigor spell to be cast on a player or // another monster. int splRejuvenate(Creature* player, cmd* cmnd, SpellData* spellData) { Creature* target=0; int heal=0, mpHeal=0; if(!(player->getClass() == CLERIC && player->getDeity() == CERIS) && spellData->how == CAST && !player->isCt()) { player->print("%s does not grant you the power to cast that spell.\n", gConfig->getDeity(player->getDeity())->getName().c_str()); return(0); } if(player->getLevel() < 13 && !player->isCt()) { player->print("You are not high enough in your order to cast that spell.\n"); return(0); } if(player->mp.getCur() < 8 && spellData->how == CAST) { player->print("Not enough magic points.\n"); return(0); } if(player->flagIsSet(P_NO_TICK_MP)) { player->print("You cannot cast that spell right now.\n"); return(0); } // Rejuvenate self if(cmnd->num == 2) { if( player->hp.getCur() >= player->hp.getMax() && player->mp.getCur() >= player->mp.getMax() && !player->checkStaff("You are already at full health and magic right now.\n") ) return(0); if(spellData->how == CAST) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); heal = getHeal(player, 0, S_REJUVENATE); mpHeal = getHeal(player, 0, S_REJUVENATE); if(!player->isCt()) { player->lasttime[LT_SPELL].ltime = time(0); player->lasttime[LT_SPELL].interval = 24L; } player->mp.decrease(8); } else { heal = mrand(1,8); mpHeal = mrand(1,8); } addhp(player, heal); addmp(player, mpHeal); if(spellData->how == CAST || spellData->how == SCROLL) { player->print("Rejuvenate spell cast.\n"); broadcast(player->getSock(), player->getRoom(), "%M casts a rejuvenate spell on %sself.", player, player->himHer()); } else { player->print("You feel revitalized.\n"); } // Cast rejuvenate on another player or monster } else { if(noPotion(player, spellData)) return(0); cmnd->str[2][0] = up(cmnd->str[2][0]); target = player->getRoom()->findCreature(player, cmnd->str[2], cmnd->val[2], false); if(!target) { player->print("That person is not here.\n"); return(0); } if(!canCastHealing(player, target, true)) return(0); if(target->hp.getCur() >= target->hp.getMax() && target->mp.getCur() >= target->mp.getMax()) { player->print("%M is at full health and magic right now.\n", target); return(0); } if(target->flagIsSet(P_NO_TICK_MP) || target->flagIsSet(P_NO_TICK_HP)) { player->print("Your rejuvinating magic is ineffective.\n"); return(0); } if(target->inCombat(false)) player->smashInvis(); if(spellData->how == CAST && !player->isCt()) { player->lasttime[LT_SPELL].ltime = time(0); player->lasttime[LT_SPELL].interval = 24L; } if(spellData->how == CAST) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); player->mp.decrease(8); heal = getHeal(player, target, S_REJUVENATE); mpHeal = getHeal(player, target, S_REJUVENATE); } else { heal = mrand(1,8); mpHeal = mrand(1,8); } addhp(target, heal); addmp(target, mpHeal); if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) { player->print("Rejuvenate spell cast on %N.\n", target); target->print("%M casts a rejuvenate spell on you.\n", player); broadcast(player->getSock(), target->getSock(), player->getRoom(), "%M casts a rejuvenate spell on %N.", player, target); niceExp(player, target, (heal+mpHeal)/2, spellData->how); } } return(1); } //********************************************************************* // splHeal //********************************************************************* // This function will cause the heal spell to be cast on a player or // another monster. It heals all hit points damage but only works 3 // times a day. int splHeal(Creature* player, cmd* cmnd, SpellData* spellData) { Creature* creature=0; if(spellData->how == CAST && !player->isStaff()) { if(player->getClass() != CLERIC && player->getClass() != PALADIN && !player->isCt()) { player->print("Your class prohibits you from casting that spell.\n"); return(0); } switch(player->getDeity()) { case ARACHNUS: case JAKAR: case GRADIUS: case ARES: case ARAMON: case KAMIRA: player->print("%s does not allow you to cast that spell.\n", gConfig->getDeity(player->getDeity())->getName().c_str()); return(0); default: break; } } // Heal self if(cmnd->num == 2) { if(!dec_daily(&player->daily[DL_FHEAL]) && spellData->how == CAST && !player->isCt() && player->isPlayer()) { player->print("You have been granted that spell enough today.\n"); return(0); } //addhp(player, player->hp.getMax()); player->hp.restore(); if(spellData->how == CAST || spellData->how == SCROLL) { if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); player->print("Heal spell cast.\n"); broadcast(player->getSock(), player->getRoom(), "%M casts a heal spell on %sself.", player, player->himHer()); return(1); } else { player->print("You feel incredibly better.\n"); return(1); } // Cast heal on another player or monster } else { if(noPotion(player, spellData)) return(0); creature = player->getRoom()->findCreature(player, cmnd->str[2], cmnd->val[2], false); if(!creature) { player->print("That person is not here.\n"); return(0); } if(!dec_daily(&player->daily[DL_FHEAL]) && spellData->how == CAST && !player->isCt() && player->isPlayer()) { player->print("You have been granted that spell enough times for today.\n"); return(0); } if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) { if(!canCastHealing(player, creature, false, true)) return(0); // addhp(creature, creature->hp.getMax()); if(creature->isPlayer() && creature->getClass() == LICH) { if(!player->canAttack(creature)) return(0); if(player->getRoom()->flagIsSet(R_SAFE_ROOM) && !creature->flagIsSet(P_OUTLAW)) { player->print("Your heal spell will harm a lich.\n"); player->print("No killing is allowed here.\n"); return(0); } if(creature->isEffected("resist-magic")) { player->print("Your spell fizzles.\n"); if(spellData->how == CAST) player->subMp(20); return(0); } } else if(creature->isMonster() && creature->getClass() == LICH) { if(creature->isEffected("resist-magic")) { player->print("Your spell fizzles.\n"); if(spellData->how == CAST) player->subMp(20); return(0); } } if(creature->getClass() == LICH) { if(creature->hp.getCur() >= 4) creature->hp.setCur(mrand(2,4)); else creature->hp.setCur(1); player->print("The heal spell nearly kills %N!\n",creature); if(creature->isPlayer()) creature->print("%M's heal spell sucks away your life force!\n", player); broadcast(player->getSock(), creature->getSock(), player->getRoom(), "%M's heal spell nearly kills %N!", player, creature); player->smashInvis(); if(creature->isMonster()) creature->getMonster()->addEnmCrt(player); return(1); } if(creature->inCombat(false)) player->smashInvis(); if(player->isPlayer()) player->getPlayer()->statistics.healingCast(); creature->hp.setCur(MAX(1, creature->hp.getMax() - mrand(1,4))); player->print("Heal spell cast on %N.\n", creature); creature->print("%M casts a heal spell on you.\n", player); broadcast(player->getSock(), creature->getSock(), player->getRoom(), "%M casts a heal spell on %N.", player, creature); logCast(player, creature, "heal"); return(1); } } return(1); } //********************************************************************* // removeStatEffects //********************************************************************* void Creature::removeStatEffects() { Player* pThis = getPlayer(); if(pThis) { pThis->loseRage(); pThis->loseFrenzy(); pThis->losePray(); } removeEffect("strength"); removeEffect("enfeeblement"); removeEffect("haste"); removeEffect("slow"); removeEffect("fortitude"); removeEffect("weakness"); removeEffect("insight"); removeEffect("feeblemind"); removeEffect("prayer"); removeEffect("damnation"); } //********************************************************************* // doRessLoss //********************************************************************* int doRessLoss(int curr, int prev, bool full) { return(MAX(0, (prev - (full ? 0 : (prev - curr) / 5)))); } //********************************************************************* // doRess //********************************************************************* int doRess(Creature* caster, cmd* cmnd, bool ress) { // if ress=false, it's a bloodfusion Player *player = caster->getPlayer(); int a=0, prevLevel=0; bool full=false; long t=0; Player* playerBackup=0, *target=0; BaseRoom *newRoom=0; char filename[80]; strcpy(filename, ""); if(player && !player->isDm()) { if(player->getNegativeLevels()) { player->print("You cannot do that without your full life essence.\n"); return(0); } if(player->mp.getCur() < player->mp.getMax()) { player->print("You must have full MP to cast that spell.\n"); return(0); } } else { // a DM can set to a 100% restore instead of 80% if(cmnd->num==4 && !strcasecmp(cmnd->str[3], "-full")) full = true; } if(cmnd->num < 2) { caster->print("%s?\n", ress ? "Resurrect whom" : "Fuse whom with new blood"); return(0); } cmnd->str[2][0]=up(cmnd->str[2][0]); target = gServer->findPlayer(cmnd->str[2]); if(!target) { caster->print("That player is not online.\n"); return(0); } if(target->isDm() && target->flagIsSet(P_DM_INVIS) && !caster->isDm()) { caster->print("That player is not online.\n"); return(0); } if(target->isStaff()) { caster->print("Staff characters do not need to be %s.\n", ress ? "resurrected" : "fused with blood"); return(0); } if(checkRefusingMagic(caster, target)) return(0); if(Move::tooFarAway(caster, target, ress ? "resurrect" : "fuse with new blood")) return(0); if(ress) { if(target->isUndead()) { caster->print("Undead players cannot be resurrected.\n"); return(0); } } else { if(!target->isUndead()) { caster->print("Only undead players can be fused with new blood.\n"); return(0); } } if(!caster->isDm()) { if(target->getLocation() != target->getLimboRoom()) { caster->print("%s is not in limbo! How can you %s %s?\n", target->name, ress ? "resurrect" : "bloodfuse", target->himHer()); return(0); } if(target->getLevel() < 7) { caster->print("%s is not yet powerful enough to be %s.\n", target->name, ress ? "resurrected" : "fused with blood"); return(0); } if(!target->flagIsSet(P_KILLED_BY_MOB)) { caster->print("%s does not need to be %s.\n", target->name, ress ? "resurrected" : "fused with new blood"); return(0); } } if(target == caster) { caster->print("You cannot %s.\n", ress ? "resurrect yourself" : "fuse yourself with new blood"); return(0); } sprintf(filename, "%s/%s.bak.xml", BACKUPPATH, target->name); if(!file_exists(filename)) { caster->print("Error loading player backup!\n"); if(caster->isDm()) caster->print("File: %s\n", filename); caster->print("Your %s attempt failed.\n", ress ? "resurrection" : "bloodfusion"); return(0); } if(player && !player->isDm() && !dec_daily(&player->daily[DL_RESURRECT])) { player->print("You have done that enough times for today.\n"); return(0); } if(!caster->isDm() && !dec_daily(&target->daily[DL_RESURRECT])) { caster->print("Players can only be %s once per 24 hours real time.\n", ress ? "resurrected" : "fused with new blood"); return(0); } caster->print("You cast a %s spell on %N.\n", ress ? "resurrection" : "bloodfusion", target); prevLevel = target->getLevel(); // load the backed up player if(!loadPlayer(target->name, &playerBackup, LS_BACKUP)) { caster->print("File load failed.\n"); caster->print("Your %s attempt failed.\n", ress ? "resurrection" : "bloodfusion"); return(0); } if(target->getExperience() == playerBackup->getExperience()) { caster->print("Target and backup have the same experience.\n"); caster->print("Your %s attempt failed.\n", ress ? "resurrection" : "bloodfusion"); free_crt(playerBackup, false); return(0); } // Clear any stat-modifying effects from backed up player //normalizeStats(playerBackup); playerBackup->removeStatEffects(); if(!playerBackup->statsAddUp()) { caster->print("Backup's stats do not add up.\n"); caster->print("Your %s attempt failed.\n", ress ? "resurrection" : "bloodfusion"); free_crt(playerBackup, false); return(0); } target->removeStatEffects(); // set target's characteristics back to what they were before target->setExperience(doRessLoss(target->getExperience(), playerBackup->getExperience(), full)); target->setLevel(playerBackup->getLevel()); target->setActualLevel(playerBackup->getActualLevel()); target->hp.setMax(playerBackup->hp.getMax()); target->mp.setMax(playerBackup->mp.getMax()); //target->pp.max = playerBackup->pp.max; for(Realm r = MIN_REALM; r<MAX_REALM; r = (Realm)((int)r + 1)) { target->setRealm(doRessLoss(target->getRealm(r), playerBackup->getRealm(r), full), r); } for(a=0; a<6; a++) { // don't mess with saves target->saves[a].chance = playerBackup->saves[a].chance; target->saves[a].gained = playerBackup->saves[a].gained; } target->strength.setMax(playerBackup->strength.getMax()); target->strength.setCur(playerBackup->strength.getCur()); target->dexterity.setMax(playerBackup->dexterity.getMax()); target->dexterity.setCur(playerBackup->dexterity.getCur()); target->constitution.setMax(playerBackup->constitution.getMax()); target->constitution.setCur(playerBackup->constitution.getCur()); target->intelligence.setMax(playerBackup->intelligence.getMax()); target->intelligence.setCur(playerBackup->intelligence.getCur()); target->piety.setMax(playerBackup->piety.getMax()); target->piety.setCur(playerBackup->piety.getCur()); EffectInfo *effect = target->getEffect("death-sickness"); if(effect) { if(full) target->removeEffect("death-sickness"); else effect->setDuration(effect->getDuration() / 3); } target->cureDisease(); target->curePoison(); target->removeEffect("hold-person"); target->removeEffect("petrification"); target->removeEffect("confusion"); target->removeEffect("drunkenness"); target->clearFlag(P_KILLED_BY_MOB); target->setTickDamage(0); // Free backed up player pointer from memory free_crt(playerBackup, false); broadcast(caster->getSock(), caster->getRoom(), "%M casts a %s spell on %N.", caster, ress ? "resurrection" : "bloodfusion", target); logn("log.resurrect", "%s(L:%d) %s %s(L%d:%d) %s.\n", caster->name, caster->getLevel(), ress ? "resurrected" : "fused", target->name, prevLevel, target->getLevel(), ress ? "from the dead" : "with new blood"); if(ress) broadcast("^R### %M just resurrected %s from the dead!", caster, target->name); else broadcast("^R### %M just fused %s with new blood!", caster, target->name); if(player && !player->isDm()) { t = time(0); caster->setFlag(P_NO_TICK_MP); // caster cannot tick MP for 20 mins online time caster->lasttime[LT_NOMPTICK].ltime = t; caster->lasttime[LT_NOMPTICK].interval = 1200L; broadcast(caster->getSock(), caster->getRoom(), "%M collapses from exhaustion.", caster); caster->print("You collapse from exhaustion.\n"); caster->knockUnconscious(60); caster->mp.setCur(0); } newRoom = target->getRecallRoom().loadRoom(target); if(newRoom) { target->deleteFromRoom(); target->addToRoom(newRoom); target->doPetFollow(); } target->print("You have been %s!\n", ress ? "resurrected from the dead" : "fused with new blood"); target->hp.restore(); target->mp.restore(); target->pp.restore(); target->computeAttackPower(); target->computeAC(); target->clearAsEnemy(); target->save(true); return(1); } //********************************************************************* // splResurrect //********************************************************************* int splResurrect(Creature* player, cmd* cmnd, SpellData* spellData) { if(spellData->how != CAST) return(0); if(!player->isDm()) { if(player->getClass() != CLERIC && player->getDeity() != CERIS) { player->print("You cannot cast that spell.\n"); return(0); } if(!player->spellIsKnown(S_RESURRECT)) { player->print("You do not know that spell.\n"); return(0); } if(player->getLevel() < 19) { player->print("You are not high enough level to cast that spell.\n"); return(0); } if(player->getAdjustedAlignment() != NEUTRAL) { player->print("You must be neutral in order to cast that spell.\n"); return(0); } } return(doRess(player, cmnd, true)); } //********************************************************************* // splBloodfusion //********************************************************************* int splBloodfusion(Creature* player, cmd* cmnd, SpellData* spellData) { if(spellData->how != CAST) return(0); if(!player->isDm()) { if(player->getClass() != CLERIC && player->getDeity() != ARAMON) { player->print("You cannot cast that spell.\n"); return(0); } if(!player->spellIsKnown(S_BLOODFUSION)) { player->print("You do not know that spell.\n"); return(0); } if(player->getLevel() < 22) { player->print("You are not high enough level to cast that spell.\n"); return(0); } if(player->getAdjustedAlignment() != BLOODRED) { player->print("You are not evil enough to cast that spell.\n"); return(0); } } return(doRess(player, cmnd, false)); } //********************************************************************* // splRestore //********************************************************************* // This function allows a player to cast the restore spell using either // a potion or a wand. Restore should not be a cast-able spell because // it can restore magic points to full. int splRestore(Creature* player, cmd* cmnd, SpellData* spellData) { Creature* target=0; if(spellData->how == CAST && player->isPlayer() && !player->isStaff()) { player->print("You may not cast that spell.\n"); return(0); } // Cast restore on self if(cmnd->num == 2) { target = player; if(spellData->how == CAST || spellData->how == WAND) { player->print("Restore spell cast.\n"); broadcast(player->getSock(), player->getRoom(), "%M casts restore on %sself.", player, player->himHer()); } else if(spellData->how == POTION) player->print("You feel restored.\n"); // Cast restore on another player } else { if(noPotion(player, spellData)) return(0); cmnd->str[2][0] = up(cmnd->str[2][0]); target = player->getRoom()->findCreature(player, cmnd->str[2], cmnd->val[2], false); if(!target) { player->print("That person is not here.\n"); return(0); } player->print("Restore spell cast on %N.\n", target); target->print("%M casts a restore spell on you.\n", player); broadcast(player->getSock(), target->getSock(), player->getRoom(), "%M casts a restore spell on %N.", player, target); logCast(player, target, "restore"); } addhp(target, dice(2, 10, 0)); if(mrand(1, 100) < 34) target->mp.restore(); if(player->isStaff()) { target->mp.restore(); target->hp.restore(); } return(1); } //********************************************************************* // splRoomVigor //********************************************************************* int splRoomVigor(Creature* player, cmd* cmnd, SpellData* spellData) { int heal=0; ctag *cp = player->getRoom()->first_ply, *cp_tmp=0; if(spellData->how == POTION) { player->print("The spell fizzles.\n"); return(0); } if(player->getClass() != CLERIC && !player->isCt()) { player->print("Only clerics may cast that spell.\n"); return(0); } player->print("You cast vigor on everyone in the room.\n"); broadcast(player->getSock(), player->getRoom(), "%M casts vigor on everyone in the room.\n", player); heal = mrand(1, 6) + bonus((int) player->piety.getCur()); if(player->getRoom()->magicBonus()) { heal += mrand(1, 3); player->print("\nThe room's magical properties increase the power of your spell\n"); } while(cp) { cp_tmp = cp->next_tag; if(canCastHealing(player, cp->crt, false, false, false)) { if(cp->crt != player) cp->crt->print("%M casts vigor on you.\n", player); addhp(cp->crt, heal); if(cp->crt->inCombat(false)) player->smashInvis(); } cp = cp_tmp; } return(1); }