/*
* afflictions.cpp
* Functions that handle poison/disease/curse/blind/vampirism/lycanthropy
* ____ _
* | _ \ ___ __ _| |_ __ ___ ___
* | |_) / _ \/ _` | | '_ ` _ \/ __|
* | _ < __/ (_| | | | | | | \__ \
* |_| \_\___|\__,_|_|_| |_| |_|___/
*
* 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-2012 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 "effects.h"
#include "commands.h"
//*********************************************************************
// cmdCreepingDoom
//*********************************************************************
int cmdCreepingDoom(Player* player, cmd* cmnd) {
Creature* creature=0;
Monster *mCreature=0;
long i=0, t=0;
int chance=0, dmg=0;
player->clearFlag(P_AFK);
if(!player->ableToDoCommand())
return(0);
if(!player->isCt()) {
if(!player->knowsSkill("creeping-doom")) {
player->print("You lack the ability to strike someone with creeping doom.\n");
return(0);
}
if(!player->alignInOrder()) {
player->print("%s requires you to be evil to do that.\n", gConfig->getDeity(player->getDeity())->getName().c_str());
return(0);
}
}
if(cmnd->num < 2) {
player->print("Strike whom with creeping doom?\n");
return(0);
}
creature = player->getParent()->findCreature(player, cmnd->str[1], cmnd->val[1], true, true);
if(!creature || creature == player) {
player->print("You don't see that here.\n");
return(0);
}
// pCreature = creature->getPlayer();
mCreature = creature->getAsMonster();
player->smashInvis();
player->interruptDelayedActions();
if(!player->canAttack(creature))
return(0);
if(mCreature && mCreature->getType() == ARACHNID &&
!player->checkStaff("You cannot harm arachnids with creeping-doom.\n")
)
return(0);
if( creature->getDeity() == ARACHNUS &&
!player->checkStaff("You cannot harm followers of Arachnus with creeping-doom.\n")
)
return(0);
double level = player->getSkillLevel("creeping-doom");
i = LT(player, LT_SMOTHER);
t = time(0);
if(i > t && !player->isCt()) {
player->pleaseWait(i-t);
return(0);
}
player->lasttime[LT_SMOTHER].ltime = t;
player->updateAttackTimer();
player->lasttime[LT_SMOTHER].interval = 120L;
chance = ((int)(level - creature->getLevel()) * 20) + bonus((int) player->piety.getCur()) * 5 + 25;
chance = MIN(chance, 80);
dmg = mrand((int)(level*2), (int)(level*3));
if(mCreature)
mCreature->addEnemy(player);
if(!creature->isCt()) {
if(mrand(1, 100) > chance) {
player->print("You failed to strike %N with creeping doom.\n", creature);
broadcast(player->getSock(), creature->getSock(), player->getRoomParent(), "%M tried to strike %N with creeping doom!", player, creature);
creature->print("%M tried to strike you with creeping doom!\n", player);
player->checkImprove("creeping-doom", false);
return(0);
}
if(creature->chkSave(BRE, player, 0)) {
player->printColor("^yYour creeping-doom strike was interrupted!\n");
creature->print("You manage to partially avoid %N's creeping-doom strike.\n", player);
dmg /= 2;
}
}
player->printColor("You struck %N with creeping doom for %s%d^x damage.\n", creature, player->customColorize("*CC:DAMAGE*").c_str(), dmg);
player->checkImprove("creeping-doom", true);
player->statistics.attackDamage(dmg, "creeping-doom");
creature->printColor("%M struck you with creeping doom for %s%d^x damage!\n", player, creature->customColorize("*CC:DAMAGE*").c_str(), dmg);
broadcast(player->getSock(), creature->getSock(), player->getRoomParent(), "%M struck %N with creeping doom!", player, creature);
// if they didn't die from the damage, curse them
if(!player->doDamage(creature, dmg, CHECK_DIE))
creature->addEffect("creeping-doom", 200, (int)level, player, true, player);
return(0);
}
//********************************************************************
// cmdPoison
//********************************************************************
// the Arachnus ability to inflict enemies with poison
int cmdPoison(Player* player, cmd* cmnd) {
Creature* creature=0;
Monster *mCreature=0;
long i=0, t=0;
int chance=0;
unsigned int dur=0;
player->clearFlag(P_AFK);
if(!player->ableToDoCommand())
return(0);
if(!player->isCt()) {
if(!player->knowsSkill("poison")) {
if(player->getClass() == ASSASSIN || player->getSecondClass() == ASSASSIN) {
player->print("Assassins must use envenom to poison people.\n");
} else {
player->print("You lack the ability to poison people.\n");
}
return(0);
}
if(!player->alignInOrder()) {
player->print("%s requires you to be evil to do that.\n", gConfig->getDeity(player->getDeity())->getName().c_str());
return(0);
}
}
if(cmnd->num < 2) {
player->print("Poison whom?\n");
return(0);
}
creature = player->getParent()->findCreature(player, cmnd->str[1], cmnd->val[1], true, true);
if(!creature || creature == player) {
player->print("You don't see that here.\n");
return(0);
}
// pCreature = creature->getPlayer();
mCreature = creature->getAsMonster();
player->smashInvis();
player->interruptDelayedActions();
if(!player->canAttack(creature))
return(0);
if(mCreature && mCreature->getType() == ARACHNID &&
!player->checkStaff("You cannot poison arachnids with this ability.\n")
)
return(0);
if( creature->getDeity() == ARACHNUS &&
!player->checkStaff("You cannot poison followers of Arachnus with this ability.\n")
)
return(0);
double level = player->getSkillLevel("poison");
i = LT(player, LT_DRAIN_LIFE);
t = time(0);
if(i > t && !player->isCt()) {
player->pleaseWait(i-t);
return(0);
}
player->lasttime[LT_DRAIN_LIFE].ltime = t;
player->updateAttackTimer();
player->lasttime[LT_DRAIN_LIFE].interval = 120L;
chance = ((int)(level - creature->getLevel()) * 20) + bonus((int) player->piety.getCur()) * 5 + 25;
chance = MIN(chance, 80);
dur = standardPoisonDuration((short)level, creature->constitution.getCur());
if(mCreature)
mCreature->addEnemy(player);
if(!player->isCt()) {
if(mrand(1, 100) > chance || creature->isPoisoned() || creature->immuneToPoison()) {
player->printColor("^GYou fail to poison %N.\n", creature);
creature->printColor("^G%M tried to poison you!\n", player);
broadcastGroup(false, creature, "%M tried to poison %N.\n", player, creature);
broadcast(player->getSock(), creature->getSock(), player->getRoomParent(), "%M tried to poison %N.", player, creature);
player->checkImprove("poison", false);
return(0);
}
}
player->printColor("^GYou poison %N.\n", creature);
creature->printColor("^G%M poisons you!\n", player);
broadcastGroup(false, creature, "^G%M poisons %N.\n", player, creature);
broadcast(player->getSock(), creature->getSock(), player->getRoomParent(), "^G%M poisons %N.", player, creature);
if(creature->chkSave(POI, player, 0)) {
player->print("%N partially resists your poison.\n", creature);
creature->print("You partially resists %N's poison.\n", player);
level = level * 2 / 3;
dur = dur * 2 / 3;
}
player->checkImprove("poison", true);
creature->poison(player, (unsigned int)level, dur);
return(0);
}
//********************************************************************
// poison
//********************************************************************
// the calling function is responsible for announcing the poisoning
void Creature::poison(Creature *enemy, unsigned int damagePerPulse, unsigned int duration) {
if(immuneToPoison())
return;
setPoisonedBy("");
if(enemy) {
if(isPlayer()) {
if(enemy->isPlayer() || enemy->isPet()) {
setFlag(P_POISONED_BY_PLAYER);
clearFlag(P_POISONED_BY_MONSTER);
} else {
setFlag(P_POISONED_BY_MONSTER);
clearFlag(P_POISONED_BY_PLAYER);
}
if(enemy->isPet())
setPoisonedBy(enemy->getMaster()->getName());
else if(enemy->isMonster() && !enemy->flagIsSet(M_NO_PREFIX))
setPoisonedBy((bstring)"a " + enemy->getName());
else if(this == enemy)
setPoisonedBy((bstring)himHer() + "self");
else
setPoisonedBy(enemy->getName());
} else {
if(enemy->isPlayer())
setPoisonedBy(enemy->getName());
else if(enemy->isPet())
setPoisonedBy(enemy->getMaster()->getName());
else if(enemy->isMonster() && !enemy->flagIsSet(M_NO_PREFIX))
setPoisonedBy((bstring)"a " + enemy->getName());
else
setPoisonedBy(enemy->getName());
}
}
addEffect("poison", duration, damagePerPulse, 0, false, this);
}
//********************************************************************
// immuneToPoison
//********************************************************************
bool Creature::immuneToPoison() const {
if(isUndead() || monType::noLivingVulnerabilities(type))
return(true);
if(deity == ARACHNUS)
return(true);
// check on mobs
if(isMonster()) {
if(flagIsSet(M_NO_POISON))
return(true);
// check on players
} else {
if(isStaff())
return(true);
}
return(false);
}
//*********************************************************************
// isPoisoned
//*********************************************************************
bool Creature::isPoisoned() const {
if(immuneToPoison())
return(false);
return(effects.hasPoison());
}
//*********************************************************************
// hasPoison
//*********************************************************************
bool Effects::hasPoison() const {
EffectList::const_iterator eIt;
for(eIt = effectList.begin() ; eIt != effectList.end() ; eIt++) {
if((*eIt)->isPoison())
return(true);
}
return(false);
}
//*********************************************************************
// curePoison
//*********************************************************************
bool Creature::curePoison() {
pClearFlag(P_POISONED_BY_PLAYER);
pClearFlag(P_POISONED_BY_MONSTER);
removeEffect("slow-poison");
setPoisonedBy("");
return(effects.removePoison());
}
//*********************************************************************
// removePoison
//*********************************************************************
bool Effects::removePoison() {
bool removed=false;
// remove all effects flagged as poison
EffectList::iterator eIt;
EffectInfo *effect=0;
for(eIt = effectList.begin() ; eIt != effectList.end() ;) {
effect = (*eIt);
if(effect->isPoison()) {
removed = true;
effect->remove();
delete effect;
eIt = effectList.erase(eIt);
} else
eIt++;
}
return(removed);
}
//********************************************************************
// standardPoisonDuration
//********************************************************************
unsigned int standardPoisonDuration(short level, short con) {
int dur = 60 * mrand(1,3) - (60*bonus((int)con)) + level*10;
if(con > 120) {
// a spread between 400 (50%) and 120 (0%) resistance
double percent = 1 - (con - 120) / (680 - 120);
percent *= dur;
dur = (int)percent;
}
return(MAX(60,dur));
}
// low con, level 40: 1-3 mins
// high con, level 40: 1 min
//
//********************************************************************
// disease
//********************************************************************
// the calling function is responsible for announcing the diseasing
void Creature::disease(Creature* enemy, unsigned int damagePerPulse) {
if(immuneToDisease())
return;
addPermEffect("disease", damagePerPulse, false);
}
//********************************************************************
// immuneToDisease
//********************************************************************
bool Creature::immuneToDisease() const {
// no need to call noLivingVulnerabilities
if(isMonster())
return(true);
if(isStaff())
return(true);
if(isUndead())
return(true);
return(false);
}
//*********************************************************************
// isDiseased
//*********************************************************************
bool Creature::isDiseased() const {
if(immuneToDisease())
return(false);
return(effects.hasDisease());
}
//*********************************************************************
// hasDisease
//*********************************************************************
bool Effects::hasDisease() const {
EffectList::const_iterator eIt;
for(eIt = effectList.begin() ; eIt != effectList.end() ; eIt++) {
if((*eIt)->isDisease())
return(true);
}
return(false);
}
//*********************************************************************
// cureDisease
//*********************************************************************
bool Creature::cureDisease() {
return(effects.removeDisease());
}
//*********************************************************************
// removeDisease
//*********************************************************************
bool Effects::removeDisease() {
bool removed=false;
// remove all effects flagged as disease
EffectList::iterator eIt;
EffectInfo *effect=0;
for(eIt = effectList.begin() ; eIt != effectList.end() ;) {
effect = (*eIt);
if(effect->isDisease()) {
removed = true;
effect->remove();
delete effect;
eIt = effectList.erase(eIt);
} else
eIt++;
}
return(removed);
}
//*********************************************************************
// removeCurse
//*********************************************************************
// remove curse effects
bool Creature::removeCurse() {
return(effects.removeCurse());
}
bool Effects::removeCurse() {
bool removed=false;
EffectList::iterator eIt;
EffectInfo *effect=0;
for(eIt = effectList.begin() ; eIt != effectList.end() ;) {
effect = (*eIt);
if(effect->isCurse()) {
removed = true;
effect->remove();
delete effect;
eIt = effectList.erase(eIt);
} else
eIt++;
}
return(removed);
}
//********************************************************************
// isBlind
//********************************************************************
bool Creature::isBlind() const {
if(isMonster() || isStaff())
return(false);
return(isEffected("blindness"));
}
//***********************************************************************
// isNew
//***********************************************************************
// these checks distinguish legacy vampires and werewolves from new ones.
// once these legacy classes have been removed, these functions can just
// be replaced with isEffected("vampirism") and isEffected("lycanthropy")
bool Creature::isNewVampire() const {
if(isPlayer() && cClass == PUREBLOOD)
return(false);
return(isEffected("vampirism"));
}
bool Creature::isNewWerewolf() const {
if(isPlayer() && cClass == WEREWOLF)
return(false);
return(isEffected("lycanthropy"));
}
//***********************************************************************
// makeVampire
//***********************************************************************
void Creature::makeVampire() {
addPermEffect("vampirism");
if(isPlayer()) {
setFlag(P_CHAOTIC);
// make sure the master still exists and is still a vampire
Player* player = getAsPlayer();
if(player->getAfflictedBy() != "") {
bool online = true;
Player* master = gServer->findPlayer(player->getAfflictedBy());
if(!master) {
loadPlayer(player->getAfflictedBy().c_str(), &master);
online = false;
}
if(!master || !master->isEffected("vampirism"))
player->setAfflictedBy("");
else {
master->minions.push_back(getName());
master->save(online);
}
if(master && !online)
free_crt(master);
}
}
if(!knowsSkill("mist"))
addSkill("mist", 1);
if(!knowsSkill("bite"))
addSkill("bite", 1);
if(!knowsSkill("hypnotize"))
addSkill("hypnotize", 1);
}
//***********************************************************************
// willBecomeVampire
//***********************************************************************
bool Creature::willBecomeVampire() const {
if(!pFlagIsSet(P_PTESTER))
return(false);
if(level < 7 || cClass == PALADIN || isEffected("lycanthropy") || isUndead())
return(false);
// only evil clerics become vampires
if(cClass == CLERIC && !(deity == ARAMON || deity == ARACHNUS))
return(false);
if(monType::noLivingVulnerabilities(type))
return(false);
return(true);
}
//***********************************************************************
// vampireCharm
//***********************************************************************
// determines if player is a spawn of the master
// if not, it does some cleanup that should have been done elsewhere
// (an extra check to make sure everything is set properly)
bool Creature::vampireCharmed(Player* master) {
if(!isPlayer() || !master)
return(false);
// if they're on their way to becoming a vampire, but arent one yet, don't
// mess with minion or afflictedBy fields
if(isEffected("porphyria"))
return(false);
Player* player = getAsPlayer();
bool charmed = true;
// we need to make sure the minion lists match up;
// this won't be the case if somebody suicides and remakes
if(charmed && (!isEffected("vampirism") || !master->isEffected("vampirism")))
charmed = false;
if(charmed && player->getAfflictedBy() != master->getName())
charmed = false;
if(charmed) {
bool found = false;
std::list<bstring>::iterator mIt;
for(mIt = master->minions.begin() ; mIt != master->minions.end() && !found ; mIt++) {
if(*mIt == player->getName())
found = true;
}
if(!found)
charmed = false;
}
// if they're not charmed, clean up these lists
if(!charmed) {
if(player->getAfflictedBy() == master->getName())
player->setAfflictedBy("");
master->minions.remove(player->getName());
}
return(charmed);
}
//********************************************************************
// clearMinions
//********************************************************************
void Creature::clearMinions() {
if(!isPlayer())
return;
Player* player = getAsPlayer(), *target=0;
bool online = true;
if(player->getAfflictedBy() != "") {
target = gServer->findPlayer(player->getAfflictedBy());
if(!target) {
loadPlayer(player->getAfflictedBy().c_str(), &target);
online = false;
}
if(target) {
target->minions.remove(player->getName());
target->save(online);
}
if(!online)
free_crt(target);
}
std::list<bstring>::iterator mIt;
for(mIt = player->minions.begin() ; mIt != player->minions.end() ; mIt++) {
online = true;
target = gServer->findPlayer(*mIt);
if(!target) {
loadPlayer((*mIt).c_str(), &target);
online = false;
}
if(target) {
if(target->getAfflictedBy() == player->getName()) {
target->setAfflictedBy("");
target->save(online);
}
if(!online)
free_crt(target);
}
}
}
//********************************************************************
// addPorphyria
//********************************************************************
bool Creature::addPorphyria(Creature *killer, int chance) {
const RaceData* rdata = gConfig->getRace(race);
if(rdata)
chance -= rdata->getPorphyriaResistance();
if(mrand(1,100) > chance)
return(false);
if(!willBecomeVampire())
return(false);
if(isEffected("porphyria") || isEffected("undead-ward") || isEffected("drain-shield"))
return(false);
if(!killer || !killer->isNewVampire())
return(false);
addEffect("porphyria", 0, 0, killer, true, this);
// if they become a vampire, they'll be permanently charmed by their master
if(killer->isPlayer()) {
killer->print("You have infected %N with porphyria.\n", this);
if(isPlayer())
getAsPlayer()->setAfflictedBy(killer->getName());
} else if(isPlayer())
getAsPlayer()->setAfflictedBy("");
return(true);
}
//********************************************************************
// sunlightDamage
//********************************************************************
// return true if they died, false if they lived
bool Creature::sunlightDamage() {
if(isStaff() || !isNewVampire())
return(false);
int dmg = hp.getMax() / 5 + mrand(1,10);
unmist();
wake("Terrible nightmares disturb your sleep!");
printColor("^Y^#The searing sunlight burns your flesh!\n");
broadcast(getSock(), getRoomParent(), "^Y%M's flesh is burned by the sunlight!", this);
// lots of damage every 5 seconds
hp.decrease(dmg);
if(hp.getCur() < 1) {
printColor("^YYou have been disintegrated!\n");
if(isPlayer())
getAsPlayer()->die(SUNLIGHT);
else
getAsMonster()->mobDeath();
return(true);
}
return(false);
}
//***********************************************************************
// makeWerewolf
//***********************************************************************
void Creature::makeWerewolf() {
addPermEffect("lycanthropy");
if(!knowsSkill("maul"))
skills["maul"] = new Skill("maul", 1);
if(!knowsSkill("frenzy"))
skills["frenzy"] = new Skill("frenzy", 1);
if(!knowsSkill("howl"))
skills["howl"] = new Skill("howl", 1);
if(!knowsSkill("claw"))
skills["claw"] = new Skill("claw", level * 5);
}
//***********************************************************************
// willBecomeWerewolf
//***********************************************************************
bool Creature::willBecomeWerewolf() const {
if(!pFlagIsSet(P_PTESTER))
return(false);
if(level < 7 || isEffected("lycanthropy") || isUndead())
return(false);
if(monType::noLivingVulnerabilities(type))
return(false);
return(true);
}
//********************************************************************
// addLycanthropy
//********************************************************************
bool Creature::addLycanthropy(Creature *killer, int chance) {
if(mrand(1,100) > chance)
return(false);
if(!willBecomeWerewolf())
return(false);
if(isEffected("lycanthropy"))
return(false);
if(!killer || !killer->isNewWerewolf())
return(false);
addEffect("lycanthropy", 0, 0, killer, true, this);
if(killer->isPlayer()) {
killer->print("You have infected %N with lycanthropy.\n", this);
if(isPlayer())
getAsPlayer()->setAfflictedBy(killer->getName());
} else if(isPlayer())
getAsPlayer()->setAfflictedBy("");
return(true);
}
//*********************************************************************
// splCurePoison
//*********************************************************************
// This function allows a player to cast a curepoison spell on themself,
// another player or a monster. It will remove any poison that is in
// that player's system.
int splCurePoison(Creature* player, cmd* cmnd, SpellData* spellData) {
Creature* target=0;
if( player->isPlayer() &&
player->getClass() != CLERIC &&
player->getClass() != PALADIN &&
!player->isCt() &&
spellData->how == CAST
) {
player->print("Your class may not cast that spell.\n");
return(0);
}
// Curepoison self
if(cmnd->num == 2) {
target = player;
if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
player->print("Cure-poison spell cast on yourself.\n");
player->print("You feel much better.\n");
broadcast(player->getSock(), player->getParent(), "%M casts cure-poison on %sself.",
player, player->himHer());
} else if(spellData->how == POTION && player->isPoisoned())
player->print("You feel the poison subside.\n");
else if(spellData->how == POTION)
player->print("Nothing happens.\n");
// Cure a monster or player
} else {
if(player->noPotion( spellData))
return(0);
cmnd->str[2][0] = up(cmnd->str[2][0]);
target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);
if(!target) {
player->print("That person is not here.\n");
return(0);
}
if(checkRefusingMagic(player, target))
return(0);
if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
player->print("Cure-poison cast on %N.\n", target);
broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts cure-poison on %N.", player, target);
target->print("%M casts cure-poison on you.\nYou feel much better.\n", player);
}
}
if(target->inCombat(false))
player->smashInvis();
target->curePoison();
return(1);
}
//*********************************************************************
// splSlowPoison
//*********************************************************************
int splSlowPoison(Creature* player, cmd* cmnd, SpellData* spellData) {
Creature* target=0;
// slow_poison self
if(cmnd->num == 2) {
target = player;
if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
player->print("Slow-poison spell cast on yourself.\n");
broadcast(player->getSock(), player->getParent(), "%M casts slow-poison on %sself.",
player, player->himHer());
if(!player->isPoisoned()) {
player->print("Nothing happens.\n");
return(0);
}
player->print("You feel the poison subside somewhat.\n");
} else if(spellData->how == POTION && player->isPoisoned())
player->print("You feel the poison subside somewhat.\n");
else if(spellData->how == POTION)
player->print("Nothing happens.\n");
// Cure a monster or player
} else {
if(player->noPotion( spellData))
return(0);
cmnd->str[2][0] = up(cmnd->str[2][0]);
// monsters are now valid targets
target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);
if(!target) {
player->print("That person is not here.\n");
return(0);
}
if(checkRefusingMagic(player, target))
return(0);
player->print("Slow-poison cast on %N.\n", target);
broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts slow-poison on %N.", player, target);
target->print("%M casts slow-poison on you.\n", player);
if(!target->isPoisoned()) {
player->print("Nothing happens.\n");
if(player != target)
target->print("Nothing happens.\n");
return(0);
}
target->print("You feel a little better.\n");
}
if(target->inCombat(false))
player->smashInvis();
target->addPermEffect("slow-poison");
return(1);
}
//*********************************************************************
// splCureDisease
//*********************************************************************
int splCureDisease(Creature* player, cmd* cmnd, SpellData* spellData) {
Creature* target=0;
if(player->getClass() != CLERIC &&
player->getClass() != PALADIN &&
!player->isStaff() &&
spellData->how == CAST)
{
player->print("Only clerics and paladins may cast that spell.\n");
return(0);
}
if(cmnd->num == 2) {
target = player;
if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
player->print("Cure-disease spell cast on yourself.\n");
player->print("Your fever subsides.\n");
broadcast(player->getSock(), player->getParent(), "%M casts cure-disease on %sself.", player, player->himHer());
} else if(spellData->how == POTION && player->isDiseased())
player->print("You feel your fever subside.\n");
else if(spellData->how == POTION)
player->print("Nothing happens.\n");
} else {
if(player->noPotion( spellData))
return(0);
cmnd->str[2][0] = up(cmnd->str[2][0]);
target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);
if(!target) {
player->print("That's not here.\n");
return(0);
}
if(checkRefusingMagic(player, target))
return(0);
player->print("You cure-disease cast on %N.\n", target);
broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts cure-disease on %N.", player, target);
target->print("%M casts cure-disease on you.\nYou feel your fever subside.\n", player);
}
if(target->inCombat(false))
player->smashInvis();
target->cureDisease();
return(1);
}
//*********************************************************************
// splCureBlindness
//*********************************************************************
int splCureBlindness(Creature* player, cmd* cmnd, SpellData* spellData) {
Creature* target=0;
if(cmnd->num == 2) {
target = player;
if(!player->isStaff()) {
if( spellData->how != POTION ||
!player->isEffected("blindness") ||
player->flagIsSet(P_DM_BLINDED)
)
player->print("Nothing happens.\n");
}
} else {
if(player->noPotion( spellData))
return(0);
cmnd->str[2][0] = up(cmnd->str[2][0]);
target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);
if(!target) {
player->print("That's not here.\n");
return(0);
}
if(checkRefusingMagic(player, target))
return(0);
if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
player->print("You cast cure blindess on %N.\n", target);
broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts cure blindness on %N.",
player, target);
if(target->isPlayer()) {
target->print("%M casts cure blindness on you.\n", player);
if( target->isEffected("blindness") &&
(player->isCt() || !target->flagIsSet(P_DM_BLINDED))
) {
//target->print("You can see again.\n");
} else {
target->print("Nothing happens.\n");
}
}
}
}
if(target->inCombat(false))
player->smashInvis();
if(target->isPlayer())
if(player->isCt())
target->clearFlag(P_DM_BLINDED);
target->removeEffect("blindness");
return(1);
}
//*********************************************************************
// isCurse
//*********************************************************************
bool EffectInfo::isCurse() const {
return(myEffect->hasBaseEffect("curse"));
}
//*********************************************************************
// isDisease
//*********************************************************************
bool EffectInfo::isDisease() const {
// lycanthropy is only a disease if it's not permanent - once permanent, it's
// considered an afflication and can't be removed by cure-disease
if(myEffect->getName() == "lycanthropy" && duration == -1)
return(false);
if(myEffect->hasBaseEffect("disease"))
return(true);
return(false);
}
//*********************************************************************
// isPoison
//*********************************************************************
bool EffectInfo::isPoison() const {
return(myEffect->hasBaseEffect("poison"));
}
//*********************************************************************
// splCurse
//*********************************************************************
// This function allows a player to curse a item in their inventory
int splCurse(Creature* player, cmd* cmnd, SpellData* spellData) {
Object *object=0;
if(spellData->how == CAST && player->getClass() != MAGE && player->getClass() != LICH && !player->isStaff()) {
player->print("Only mages and liches can curse.\n");
return(0);
}
if(cmnd->num < 3) {
player->print("Curse what?\n");
return(0);
}
object = player->findObject(player, cmnd, 2);
if(!object) {
player->print("You don't have that in your inventory.\n");
return(0);
}
if(object->flagIsSet(O_CURSED)) {
player->print("That object is already cursed.\n");
return(1);
}
object->setFlag(O_CURSED);
player->printColor("%O glows darkly.\n", object);
broadcast(player->getSock(), player->getParent(), "%M places a curse on %1P.", player, object);
return(1);
}
//*********************************************************************
// splRemoveCurse
//*********************************************************************
// This function allows a player to remove a curse on all the items
// in their inventory or on another player's inventory
int splRemoveCurse(Creature* player, cmd* cmnd, SpellData* spellData) {
Creature* target=0;
int i=0;
bool equipment=true;
// Cast remove-curse on self
if(cmnd->num == 2) {
target = player;
if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
player->print("Remove-curse spell cast.\n");
broadcast(player->getSock(), player->getParent(), "%M casts remove-curse on %sself.", player, player->himHer());
} else if(spellData->how == POTION)
player->print("You feel relieved of burdens.\n");
// Cast remove-curse on another player
} else {
if(player->noPotion( spellData))
return(0);
cmnd->str[2][0] = up(cmnd->str[2][0]);
target = player->getParent()->findPlayer(player, cmnd, 2);
if(!target) {
player->print("That player is not here.\n");
return(0);
}
// this purposely does not check the refuse list
if(target->flagIsSet(P_LINKDEAD) && target->isPlayer()) {
player->print("%M doesn't want that cast on them right now.\n", target);
return(0);
}
player->print("Remove-curse cast on %N.\n", target);
target->print("%M casts a remove-curse spell on you.\n", player);
broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts remove-curse on %N.", player, target);
}
if(target->inCombat(false))
player->smashInvis();
// remove all effects flagged as cursed
if(target->removeCurse())
equipment = false;
// if the remove-curse spell didn't remove a curse on the player,
// it wants to remove a curse on their equipment
if(equipment) {
for(i=0; i<MAXWEAR; i++) {
if(target->ready[i]) {
target->ready[i]->clearFlag(O_CURSED);
target->ready[i]->clearFlag(O_DARKNESS);
}
}
if(target->flagIsSet(P_DARKNESS)) {
for(Object* obj : target->objects) {
obj->clearFlag(O_DARKNESS);
}
player->print("The aura of darkness around you dissipates.\n");
broadcast(player->getSock(), player->getParent(), "The aura of darkness around %N dissipates.", player);
target->clearFlag(P_DARKNESS);
}
}
return(1);
}