/* * effects.cpp * Effects on creatures * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * 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 "effects.h" #include "commands.h" // C++ includes #include <iomanip> #include <locale> //********************************************************************* // getParentType //********************************************************************* EffectParentType Effects::getParentType(Creature* cParent, BaseRoom* rParent, Exit *xParent) { if(xParent) return(EFFECT_EXIT); if(cParent) return(EFFECT_CREATURE); // rParent is also set for Exits, so check this last if(rParent) return(EFFECT_ROOM); return(EFFECT_NO_PARENT); } //********************************************************************* // EffectInfo //********************************************************************* EffectInfo::EffectInfo(bstring pName, time_t pLastMod, long pDuration, int pStrength, Creature* cParent, BaseRoom* rParent, Exit* xParent, const Creature* owner) { myEffect = findEffect(pName, Effects::getParentType(cParent, rParent, xParent)); if(!myEffect) throw bstring("Can't find effect " + pName); name = pName; setOwner(owner); lastMod = pLastMod; duration = pDuration; strength = pStrength; extra = 0; parentCreature = cParent; parentRoom = rParent; parentExit = xParent; } EffectInfo::EffectInfo() { parentCreature = 0; parentRoom = 0; myEffect = 0; lastMod = 0; duration = 0; strength = 0; extra = 0; } EffectInfo::EffectInfo(xmlNodePtr rootNode, EffectParentType type) { xmlNodePtr curNode = rootNode->children; extra = 0; duration = 0; strength = 0; while(curNode) { if(NODE_NAME(curNode, "Name")) xml::copyToBString(name, curNode); else if(NODE_NAME(curNode, "Duration")) xml::copyToNum(duration, curNode); else if(NODE_NAME(curNode, "Strength")) xml::copyToNum(strength, curNode); else if(NODE_NAME(curNode, "Extra")) xml::copyToNum(extra, curNode); curNode = curNode->next; } lastMod = time(0); myEffect = findEffect(name, type); if(!myEffect) { throw bstring("Can't find effect listing " + name); } parentCreature = 0; parentRoom = 0; } EffectInfo::~EffectInfo() { } AlcoholState getAlcoholState(const EffectInfo* effect) { if(!effect || effect->getStrength() < 1) return(ALCOHOL_SOBER); if(effect->getStrength() < 20) return(ALCOHOL_TIPSY); if(effect->getStrength() < 66) return(ALCOHOL_DRUNK); return(ALCOHOL_INEBRIATED); } void EffectInfo::setParentCreature(Creature* parent) { parentCreature = parent; } void EffectInfo::setParentRoom(BaseRoom* parent) { parentRoom = parent; } void EffectInfo::setParentExit(Exit* parent) { parentExit = parent; } effectPtr EffectInfo::getEffect() const { return(myEffect); } const bstring& EffectInfo::getName() const { return(name); } bstring EffectInfo::getDisplayName() const { bstring displayName = myEffect->display; if(myEffect->name != "drunkenness") return(displayName); // drunkenness has a different name based on strength AlcoholState state = getAlcoholState(this); if(state == ALCOHOL_SOBER) displayName += "Sober"; // this state should never happen else if(state == ALCOHOL_TIPSY) displayName += "Tipsy"; else if(state == ALCOHOL_DRUNK) displayName += "Drunk"; else if(state == ALCOHOL_INEBRIATED) displayName += "Inebriated"; displayName += "^x"; return(displayName); } const bstring& EffectInfo::getOwner() const { return(pOwner); } bool EffectInfo::isOwner(const Creature* owner) const { // currently, only players can own effects return(owner && owner->isPlayer() && pOwner == owner->name); } time_t EffectInfo::getLastMod() const { return(lastMod); } long EffectInfo::getDuration() const { return(duration); } int EffectInfo::getStrength() const { return(strength); } int EffectInfo::getExtra() const { return(extra); } bool EffectInfo::isPermanent() const { return(duration == -1); } Creature* EffectInfo::getParentCreature() const { return(parentCreature); } BaseRoom* EffectInfo::getParentRoom() const { return(parentRoom); } Exit* EffectInfo::getParentExit() const { return(parentExit); } void EffectInfo::setOwner(const Creature* owner) { if(owner) pOwner = owner->name; else pOwner = ""; } void EffectInfo::setStrength(int pStrength) { strength = pStrength; } void EffectInfo::setExtra(int pExtra) { extra = pExtra; } void EffectInfo::setDuration(long pDuration) { duration = pDuration; } //********************************************************************* // willOverWrite //********************************************************************* // Will the given effect overwrite the existing effect? bool EffectInfo::willOverWrite(EffectInfo* existingEffect) const { // No effect, it'll overwrite :-P if(!existingEffect) return(true); // Perm effects take presedence if(duration == -1 && existingEffect->duration != -1) return(true); if(strength < existingEffect->strength) return(false); // Don't overwrite perm effects with non perm if(existingEffect->duration == -1 && duration != -1) return(false); return(true); } //********************************************************************* // operator<< //********************************************************************* std::ostream& operator<<(std::ostream& out, const EffectInfo& eff) { out.setf(std::ios::right, std::ios::adjustfield); bstring display = eff.getDisplayName(); short count=0; int len = display.getLength(); for(int i=0; i<len; i++) { if(display.getAt(i) == '^') { count += 2; i++; } } out << std::setw(38+count) << display << " - "; if(eff.duration == -1) out << "Permanent!"; else out << timeStr(eff.duration); return(out); } //********************************************************************* // pulse //********************************************************************* // True on a sucessful pulse // False if it's time to wear off bool EffectInfo::pulse(time_t t) { ASSERTLOG(parentCreature || parentRoom); bool wearOff = updateLastMod(t); if(wearOff) return(false); if(myEffect && (myEffect->effFn)) return((*(myEffect->effFn))(this, parentCreature, EFFECT_PULSE, NULL, FROM_NOWHERE)); return(false); } //********************************************************************* // updateLastMod //********************************************************************* // True if it's time for this effect to wear off bool EffectInfo::updateLastMod(time_t t) { time_t diff = t - lastMod; lastMod = t; diff = MIN(MAX(0, duration), diff); duration -= diff; return(duration == 0); } //********************************************************************* // getRoom //********************************************************************* BaseRoom* EffectInfo::getRoom() const { if(parentCreature) return(parentCreature->getRoom()); return(parentRoom); } //********************************************************************* // remove //********************************************************************* bool EffectInfo::remove(bool show) { ASSERTLOG(parentCreature || parentRoom); if(myEffect && (myEffect->effFn)) { bool success = true; if(show) { if(parentCreature) { if(!myEffect->selfStrDel.empty()) parentCreature->printColor("%s\n", myEffect->selfStrDel.c_str()); if(!myEffect->roomStrDel.empty() && getRoom()) broadcast(parentCreature->getSock(), getRoom(), myEffect->roomStrDel.c_str(), parentCreature); } else if(parentExit) { if(!myEffect->roomStrDel.empty() && getRoom()) broadcast(0, getRoom(), myEffect->roomStrDel.c_str(), parentExit->name); } else { if(!myEffect->roomStrDel.empty() && getRoom()) broadcast(0, getRoom(), myEffect->roomStrDel.c_str()); } } success &= (*(myEffect->effFn))(this, parentCreature, EFFECT_UNAPPLY, NULL, FROM_NOWHERE); return(success); } return(false); } //********************************************************************* // compute //********************************************************************* bool EffectInfo::compute(void* applier, ApplyFrom aFrom) { ASSERTLOG(parentCreature || parentRoom); if(!myEffect || !(myEffect->effFn)) return(false); return((*(myEffect->effFn))(this, parentCreature, EFFECT_COMPUTE, applier, aFrom)); } //********************************************************************* // add //********************************************************************* bool EffectInfo::add() { ASSERTLOG(parentCreature || parentRoom); if(!myEffect || !(myEffect->effFn)) return(false); if(parentCreature) { if(!myEffect->selfStrAdd.empty()) parentCreature->printColor("%s\n", myEffect->selfStrAdd.c_str()); if(!myEffect->roomStrAdd.empty() && getRoom()) broadcast(parentCreature->getSock(), getRoom(), myEffect->roomStrAdd.c_str(), parentCreature); } else if(parentExit) { if(!myEffect->roomStrAdd.empty() && getRoom()) broadcast(0, getRoom(), myEffect->roomStrAdd.c_str(), parentExit->name); } else { if(!myEffect->roomStrAdd.empty() && getRoom()) broadcast(0, getRoom(), myEffect->roomStrAdd.c_str()); } return(true); } //********************************************************************* // apply //********************************************************************* bool EffectInfo::apply() { ASSERTLOG(parentCreature || parentRoom); if(!myEffect || !(myEffect->effFn)) return(false); return((*(myEffect->effFn))(this, parentCreature, EFFECT_APPLY, NULL, FROM_NOWHERE)); } // End - EffectInfo functions //********************************************************************* // addEffect //********************************************************************* bool Creature::addEffect(const bstring& effect, void* applier, ApplyFrom aFrom, bool show, const Creature* owner) { return(effects.addEffect(effect, applier, aFrom, show, this, 0, 0, owner)); } bool BaseRoom::addEffect(const bstring& effect, void* applier, ApplyFrom aFrom, bool show, const Creature* owner) { return(effects.addEffect(effect, applier, aFrom, show, 0, this, 0, owner)); } bool Exit::addEffect(const bstring& effect, void* applier, ApplyFrom aFrom, bool show, BaseRoom* rParent, const Creature* owner) { return(effects.addEffect(effect, applier, aFrom, show, 0, rParent, this, owner)); } bool Effects::addEffect(const bstring& effect, void* applier, ApplyFrom aFrom, bool show, Creature* cParent, BaseRoom* rParent, Exit* xParent, const Creature* owner) { bool success = true; EffectInfo* newEffect = new EffectInfo(effect, time(0), -1, 1, cParent, rParent, xParent, owner); // Compute the effects potency, see if it will overwrite, and then apply & add success = newEffect->compute(applier, aFrom); if(success) return(addEffect(newEffect, show, cParent, rParent, xParent)); return(false); } //********************************************************************* // addEffect //********************************************************************* bool Creature::addEffect(const bstring& effect, long duration, int strength, bool show, const Creature* owner) { return(effects.addEffect(effect, duration, strength, show, this, 0, 0, owner)); } bool BaseRoom::addEffect(const bstring& effect, long duration, int strength, bool show, const Creature* owner) { return(effects.addEffect(effect, duration, strength, show, 0, this, 0, owner)); } bool Exit::addEffect(const bstring& effect, long duration, int strength, bool show, BaseRoom* rParent, const Creature* owner) { return(effects.addEffect(effect, duration, strength, show, 0, rParent, this, owner)); } bool Effects::addEffect(const bstring& effect, long duration, int strength, bool show, Creature* cParent, BaseRoom* rParent, Exit* xParent, const Creature* owner) { if(!findEffect(effect, getParentType(cParent, rParent, xParent))) return(false); EffectInfo* newEffect = new EffectInfo(effect, time(0), duration, strength, cParent, rParent, xParent, owner); return(addEffect(newEffect, show, cParent, rParent, xParent)); } //********************************************************************* // addEffect //********************************************************************* bool Creature::addEffect(EffectInfo* newEffect, bool show) { return(effects.addEffect(newEffect, show, this)); } bool BaseRoom::addEffect(EffectInfo* newEffect, bool show) { return(effects.addEffect(newEffect, show, 0, this)); } bool Exit::addEffect(EffectInfo* newEffect, bool show, BaseRoom* rParent) { return(effects.addEffect(newEffect, show, 0, rParent, this)); } bool Effects::addEffect(EffectInfo* newEffect, bool show, Creature* cParent, BaseRoom* rParent, Exit* xParent) { newEffect->setParentCreature(cParent); newEffect->setParentRoom(rParent); newEffect->setParentExit(xParent); EffectInfo* oldEffect = getEffect(newEffect->getName()); bool success = true; if(oldEffect && !newEffect->willOverWrite(oldEffect)) { // The new effect won't overwrite, so don't add it if(cParent) cParent->print("The effect didn't take hold.\n"); delete newEffect; return(false); } // If no existing effect, or this one will overwrite remove the old one, and add the new one removeEffect(newEffect->getName(), false, true, cParent, rParent, xParent); // Don't show the removal if(show) newEffect->add(); success &= newEffect->apply(); list.push_back(newEffect); if(rParent) rParent->addEffectsIndex(); return(true); } //********************************************************************* // addPermEffect //********************************************************************* bool Creature::addPermEffect(const bstring& effect, int strength, bool show) { return(effects.addEffect(effect, -1, strength, show, this)); } bool BaseRoom::addPermEffect(const bstring& effect, int strength, bool show) { return(effects.addEffect(effect, -1, strength, show, 0, this)); } bool Exit::addPermEffect(const bstring& effect, int strength, bool show, BaseRoom* rParent) { return(effects.addEffect(effect, -1, strength, show, 0, rParent, this)); } //********************************************************************* // removeEffect //********************************************************************* // Remove the effect (Won't remove permanent effects if remPerm is false) bool Creature::removeEffect(const bstring& effect, bool show, bool remPerm) { return(effects.removeEffect(effect, show, remPerm, this)); } bool BaseRoom::removeEffect(const bstring& effect, bool show, bool remPerm) { return(effects.removeEffect(effect, show, remPerm, 0, this)); } bool Exit::removeEffect(const bstring& effect, bool show, bool remPerm, BaseRoom* rParent) { return(effects.removeEffect(effect, show, remPerm, 0, rParent, this)); } bool Effects::removeEffect(const bstring& effect, bool show, bool remPerm, Creature* cParent, BaseRoom* rParent, Exit* xParent) { EffectInfo* toDel = getEffect(effect); if(toDel && (toDel->getDuration() != -1 || (toDel->getDuration() == -1 && remPerm))) return(removeEffect(toDel, show, cParent, rParent, xParent)); return(false); } //********************************************************************* // removeEffect //********************************************************************* bool Creature::removeEffect(EffectInfo* toDel, bool show) { return(effects.removeEffect(toDel, show, this)); } bool BaseRoom::removeEffect(EffectInfo* toDel, bool show) { return(effects.removeEffect(toDel, show, 0, this)); } bool Exit::removeEffect(EffectInfo* toDel, bool show, BaseRoom* rParent) { return(effects.removeEffect(toDel, show, 0, rParent, this)); } bool Effects::removeEffect(EffectInfo* toDel, bool show, Creature* cParent, BaseRoom* rParent, Exit* xParent) { if(!toDel) return(false); ASSERTLOG(toDel->getParentCreature() == cParent); ASSERTLOG(toDel->getParentRoom() == rParent); ASSERTLOG(toDel->getParentExit() == xParent); list.remove(toDel); toDel->remove(show); delete toDel; return(true); } //********************************************************************* // removeOwner //********************************************************************* // on suicide, we remove the owner of the effect void Effects::removeOwner(const Creature* owner) { std::list<EffectInfo*>::iterator it; for(it = list.begin() ; it != list.end() ; it++) { if((*it)->isOwner(owner)) (*it)->setOwner(0); } } //********************************************************************* // isEffected //********************************************************************* bool Creature::isEffected(const bstring& effect) const { return(effects.getEffect(effect) != NULL); } bool BaseRoom::isEffected(const bstring& effect) const { return(effects.getEffect(effect) != NULL); } bool Exit::isEffected(const bstring& effect) const { return(effects.getEffect(effect) != NULL); } //********************************************************************* // hasPermEffect //********************************************************************* bool Creature::hasPermEffect(const bstring& effect) const { EffectInfo* toCheck = effects.getEffect(effect); return(toCheck && toCheck->getDuration() == -1); } bool BaseRoom::hasPermEffect(const bstring& effect) const { EffectInfo* toCheck = effects.getEffect(effect); return(toCheck && toCheck->getDuration() == -1); } bool Exit::hasPermEffect(const bstring& effect) const { EffectInfo* toCheck = effects.getEffect(effect); return(toCheck && toCheck->getDuration() == -1); } //********************************************************************* // getEffect //********************************************************************* EffectInfo* Creature::getEffect(const bstring& effect) const { return(effects.getEffect(effect)); } EffectInfo* BaseRoom::getEffect(const bstring& effect) const { return(effects.getEffect(effect)); } EffectInfo* Exit::getEffect(const bstring& effect) const { return(effects.getEffect(effect)); } EffectInfo* Effects::getEffect(const bstring& effect) const { std::list<EffectInfo*>::const_iterator eIt; for(eIt = list.begin() ; eIt != list.end() ; eIt++) { if((*eIt) && (*eIt)->getName() == effect) return((*eIt)); } return(NULL); } //********************************************************************* // pulseEffects //********************************************************************* // Pulse all effects on this creature // return false if creature died because of this bool Creature::pulseEffects(time_t t) { bool pulsed = true; bool poison = false; EffectInfo* effect=0; std::list<EffectInfo*>::iterator eIt; deathtype = DT_NONE; for(eIt = effects.list.begin() ; eIt != effects.list.end() ;) { effect = (*eIt); // Pulse! ASSERTLOG(effect->getParentCreature() == this); pulsed = effect->pulse(t); // If pulse returns false, purge this effect if(!pulsed) { effect->remove(); if(poison || effect->isPoison()) poison = true; delete effect; eIt = effects.list.erase(eIt); } else eIt++; } // pulse effects might kill them if(deathtype != DT_NONE && hp.getCur() < 1) { if(isPlayer()) getPlayer()->die(deathtype); else getMonster()->mobDeath(); return(false); } // if they're not poisoned anymore, clear poison if(poison && !isPoisoned()) curePoison(); return(true); } //********************************************************************* // pulseEffects //********************************************************************* bool BaseRoom::pulseEffects(time_t t) { effects.pulse(t, this); xtag* xp = first_ext; while(xp) { xp->ext->pulseEffects(t, this); xp = xp->next_tag; } return(true); } //********************************************************************* // pulseEffects //********************************************************************* bool Exit::pulseEffects(time_t t, BaseRoom* rParent) { effects.pulse(t, rParent, this); return(true); } //********************************************************************* // pulse //********************************************************************* // generic pulse function that can be used on rooms and exits (because // they can't die like players can) void Effects::pulse(time_t t, BaseRoom* rParent, Exit* xParent) { std::list<EffectInfo*>::iterator it; EffectInfo* effect=0; bool pulsed=false; for(it = list.begin() ; it != list.end() ;) { effect = (*it); // Pulse! ASSERTLOG(effect->getParentRoom() == rParent); ASSERTLOG(effect->getParentExit() == xParent); pulsed = effect->pulse(t); // If pulse returns false, purge this effect if(!pulsed) { effect->remove(); delete effect; it = list.erase(it); } else it++; } } //********************************************************************* // removeAll //********************************************************************* void Effects::removeAll() { EffectInfo* effect=0; std::list<EffectInfo*>::iterator eIt; for(eIt = list.begin() ; eIt != list.end() ; eIt++) { effect = (*eIt); delete effect; (*eIt) = NULL; } list.clear(); } //********************************************************************* // copy //********************************************************************* void Effects::copy(const Effects* source, Creature* cParent) { EffectInfo* effect; std::list<EffectInfo*>::const_iterator eIt; for(eIt = source->list.begin() ; eIt != source->list.end() ; eIt++) { effect = new EffectInfo(); (*effect) = *(*eIt); effect->setParentCreature(cParent); list.push_back(effect); } } //********************************************************************* // cmdEffects //********************************************************************* int cmdEffects(Creature* creature, cmd* cmnd) { Creature* target = creature; int num=0; if(creature->isCt()) { if(cmnd->num > 1) { target = creature->getRoom()->findCreature(creature, cmnd); cmnd->str[1][0] = up(cmnd->str[1][0]); if(!target) { target = gServer->findPlayer(cmnd->str[1]); if(!target || !creature->canSee(target)) { creature->print("Target not found.\n"); return(0); } } } } num = target->effects.list.size(); creature->print("Current Effects for %s:\n", target->name); creature->printColor("%s", target->effects.getEffectsString(creature).c_str()); creature->print("\n%d effect%s found.\n", num, num != 1 ? "s" : ""); return(0); } //********************************************************************* // getEffectsList //********************************************************************* // Return a list of effects bstring Effects::getEffectsList() const { std::ostringstream effStr; effStr << "Effects: "; int num = 0; const EffectInfo* effect; std::list<EffectInfo*>::const_iterator eIt; for(eIt = list.begin() ; eIt != list.end() ; eIt++) { effect = (*eIt); if(num != 0) effStr << ", "; effStr << effect->getName(); num++; } if(num == 0) effStr << "None"; effStr << ".\n"; bstring toPrint = effStr.str(); return(toPrint); } //********************************************************************* // getEffectsString //********************************************************************* // Used to print out what effects a creature is under bstring Effects::getEffectsString(const Creature* viewer) { std::ostringstream effStr; long t = time(0); EffectInfo* effect=0; std::list<EffectInfo*>::iterator eIt; for(eIt = list.begin() ; eIt != list.end() ; eIt++) { effect = (*eIt); effect->updateLastMod(t); effStr << *effect; if(viewer->isStaff()) { effStr << " ^WStrength: " << effect->getStrength(); if(effect->getExtra()) effStr << " ^WExtra: " << effect->getExtra(); } effStr << "\n"; } return(effStr.str()); } //********************************************************************* // convertOldEffects //********************************************************************* // This function will convert flag/lt combos into effects void Creature::convertOldEffects() { Player* pPlayer = getPlayer(); Monster* mMonster = getMonster(); if(version < "2.40") { if(mMonster) { // mMonster->convertToEffect("stoneskin", OLD_M_STONESKIN, -1); // mMonster->convertToEffect("invisibility", OLD_M_INVISIBLE, OLD_LT_INVISIBILITY); } else if(pPlayer) { } } } //********************************************************************* // convertToEffect //********************************************************************* // Convert the given effect from a flag/lt to an effect bool Creature::convertToEffect(const bstring& effect, int flag, int lt) { if(!flagIsSet(flag)) return(false); clearFlag(flag); long duration = 0; if(lt != -1 && lasttime[lt].interval != 0) duration = lasttime[lt].interval; else duration = -1; EffectInfo* newEffect = new EffectInfo(effect, time(0), duration, 1, this); // if(lt != -1 && (effect == "armor" || effect == "stoneskin")) { // newEffect->setStrength(lasttime[lt].misc); // } // Assuming that they're already properly under the effect, so just add it to the list // and don't actually add it or compute it. // IE: Strength buff -- they already have +str, so don't give them more str!! effects.list.push_back(newEffect); return(true); } //********************************************************************* // removeOppositeEffect //********************************************************************* bool Creature::removeOppositeEffect(const EffectInfo *effect) { return(effects.removeOppositeEffect(effect, this)); } bool BaseRoom::removeOppositeEffect(const EffectInfo *effect) { return(effects.removeOppositeEffect(effect, 0, this)); } bool Exit::removeOppositeEffect(const EffectInfo *effect, BaseRoom* rParent) { return(effects.removeOppositeEffect(effect, 0, rParent, this)); } bool Effects::removeOppositeEffect(const EffectInfo *effect, Creature* cParent, BaseRoom* rParent, Exit* xParent) { effectPtr parentEffect = effect->getEffect(); if(!parentEffect) return(false); if(parentEffect->oppositeEffect.empty()) return(false); return(removeEffect(parentEffect->oppositeEffect, true, true, cParent, rParent, xParent)); } //********************************************************************* // addStatModEffect //********************************************************************* bool Creature::addStatModEffect(EffectInfo* effect) { Stat* stat=0; Player* pThis = getPlayer(); bool good; int hpMod = 0; int mpMod = 0; if(effect->getName() == "strength") { if(pThis) { if(flagIsSet(P_BERSERKED)) pThis->loseRage(); if(cClass == DEATHKNIGHT && flagIsSet(P_PRAYED)) pThis->losePray(); } good = true; stat = &strength; } else if(effect->getName() == "enfeeblement") { good = false; stat = &strength; } else if(effect->getName() == "haste") { if(pThis && flagIsSet(P_FRENZY)) pThis->loseFrenzy(); good = true; stat = &dexterity; } else if(effect->getName() == "slow") { good = false; stat = &dexterity; } else if(effect->getName() == "insight") { if(pThis && isEffected("confusion")) pThis->removeEffect("confusion"); good = true; mpMod = (int)(level * 1.5); stat = &intelligence; } else if(effect->getName() == "feeblemind") { good = false; mpMod = (int)(level * -1.5); stat = &intelligence; } else if(effect->getName() == "prayer") { if(pThis && cClass != DEATHKNIGHT && flagIsSet(P_PRAYED)) pThis->losePray(); good = true; stat = &piety; } else if(effect->getName() == "damnation") { good = false; stat = &piety; } else if(effect->getName() == "fortitude") { good = true; hpMod = (int)(level * 1.5); stat = &constitution; } else if(effect->getName() == "weakness") { good = false; hpMod = (int)(level * -1.5); stat = &constitution; } else { print("Unknown stat effect: %s\n", effect->getName().c_str()); return(false); } int addAmt = effect->getStrength(); if(good == false && addAmt > 0) addAmt *= -1; // print("StatAdd: %s PreAdjust: %d", effect->getName().c_str(), addAmt); if(stat->getCur() + addAmt > MAX_STAT_NUM) addAmt = MAX(0, MAX_STAT_NUM - stat->getCur()); else if(stat->getCur() + addAmt < 1) addAmt = 0 - (stat->getCur() - 1); // print(" PostAdjust: %d\n", addAmt); effect->setStrength(addAmt); stat->addCur(addAmt); if(hpMod) { hpMod = hp.adjustMax(hpMod); effect->setExtra(hpMod); if(hpMod > 0) hp.adjust(hpMod); } else if(mpMod) { mpMod = mp.adjustMax(mpMod); effect->setExtra(mpMod); if(mpMod > 0) mp.adjust(mpMod); } if(pThis) { pThis->computeAttackPower(); pThis->computeAC(); } return(true); } //********************************************************************* // remStatModEffect //********************************************************************* bool Creature::remStatModEffect(EffectInfo* effect) { Stat* stat=0; Player* pThis = getPlayer(); int hpMod = 0; int mpMod = 0; if(effect->getName() == "strength") { stat = &strength; } else if(effect->getName() == "enfeeblement") { stat = &strength; } else if(effect->getName() == "haste") { stat = &dexterity; } else if(effect->getName() == "slow") { stat = &dexterity; } else if(effect->getName() == "insight") { mpMod = -1 * effect->getExtra(); stat = &intelligence; } else if(effect->getName() == "feeblemind") { mpMod = -1 * effect->getExtra(); stat = &intelligence; } else if(effect->getName() == "prayer") { stat = &piety; } else if(effect->getName() == "damnation") { stat = &piety; } else if(effect->getName() == "fortitude") { hpMod = -1 * effect->getExtra(); stat = &constitution; } else if(effect->getName() == "weakness") { hpMod = -1 * effect->getExtra(); stat = &constitution; } else { print("Unknown stat effect: %s\n", effect->getName().c_str()); return(false); } int adjAmt = -1 * effect->getStrength(); // if(good == false && adjAmt > 0) // adjAmt *= -1; if(stat->getCur() - adjAmt > MAX_STAT_NUM) adjAmt = MAX(0, MAX_STAT_NUM - stat->getCur()); else if(stat->getCur() - adjAmt < 1) adjAmt = 0 - (stat->getCur() - 1); effect->setStrength(adjAmt); stat->adjust(adjAmt); if(hpMod) { hp.adjustMax(hpMod); if(hpMod > 0) hp.adjust(hpMod); } else if(mpMod) { mp.adjustMax(mpMod); if(mpMod > 0) mp.adjust(mpMod); } if(pThis) { pThis->computeAttackPower(); pThis->computeAC(); } return(true); } //********************************************************************* // exitEffectDamage //********************************************************************* // Wrapper to actually do the damage to the target // Return: true if they were killed bool exitEffectDamage(EffectInfo *effect, Creature* target, Creature* owner, Realm realm, DeathType dt, const char* crtStr, const char* deathStr, const char* roomStr, const char* killerStr) { Damage damage; if(!effect || effect->getExtra() || effect->isOwner(owner)) return(false); Player* killer=0; bool online = true; if(effect->getOwner() != "") { killer = gServer->findPlayer(effect->getOwner()); if(!killer) { if(loadPlayer(effect->getOwner().c_str(), &killer)) online = false; else killer = 0; } } damage.set(mrand(effect->getStrength() / 2, effect->getStrength() * 3 / 2)); target->modifyDamage(0, MAGICAL, damage, realm); if(killer && target->isMonster()) { target->getMonster()->addEnmCrt(killer); if(online) target->getMonster()->addEnmDmg(killer, damage.get()); } target->printColor(crtStr, target->customColorize("*CC:DAMAGE*"), damage.get()); target->hp.decrease(damage.get()); if(target->hp.getCur() < 1) { target->print(deathStr); broadcast(target->getSock(), target->getRoom(), roomStr, target, target); if(killer) { if(online) killer->print(killerStr, target); target->die(killer); killer->save(online); if(!online) free_crt(killer); } else { if(target->isPlayer()) target->getPlayer()->die(dt); else target->getMonster()->mobDeath(); } return(true); } if(killer && !online) free_crt(killer); return(false); } //********************************************************************* // doEffectDamage //********************************************************************* // Return: true if they were killed bool Exit::doEffectDamage(Creature* target) { Creature *owner = target; if(target->isPet()) owner = target->following; if( exitEffectDamage( getEffect("wall-of-fire"), target, owner, FIRE, BURNED, "The wall of fire burns you for %s%d^x damage.\n", "You are burned to death!\n", "%1M steps through the wall of fire.\n%M burns to death!", "%M steps through your wall of fire and is incinerated!\n" ) ) return(true); if( exitEffectDamage( getEffect("wall-of-thorns"), target, owner, EARTH, THORNS, "The wall of thorns stabs you for %s%d^x damage.\n", "You are stabbed to death!\n", "%1M steps through a wall of thorns.\n%M is stabbed to death!", "%M steps through your wall of thorns and is stabbed to death!\n" ) ) return(true); return(false); }