/* * creatureAttr.cpp * Creature attribute functions * ____ _ * | _ \ ___ __ _| |_ __ ___ ___ * | |_) / _ \/ _` | | '_ ` _ \/ __| * | _ < __/ (_| | | | | | | \__ \ * |_| \_\___|\__,_|_|_| |_| |_|___/ * * 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 "version.h" #include "calendar.h" #include "specials.h" #include "quests.h" #include "effects.h" //********************************************************************* // getClass //********************************************************************* unsigned short Creature::getClass() const { return(cClass); } //********************************************************************* // getLevel //********************************************************************* unsigned short Creature::getLevel() const { return(level); } //********************************************************************* // getAlignment //********************************************************************* short Creature::getAlignment() const { return(alignment); } //********************************************************************* // getArmor //********************************************************************* unsigned int Creature::getArmor() const { return(armor); } //********************************************************************* // getExperience //********************************************************************* unsigned long Creature::getExperience() const { return(experience); } //********************************************************************* // getCoinDisplay & getBankDisplay //********************************************************************* bstring Player::getCoinDisplay() const { return(coins.str()); } bstring Player::getBankDisplay() const { return(bank.str()); } //********************************************************************* // getClan //********************************************************************* unsigned short Creature::getClan() const { return(clan); } //********************************************************************* // getType //********************************************************************* mType Creature::getType() const { return(type); } //********************************************************************* // getRace //********************************************************************* unsigned short Creature::getRace() const { return(race); } //********************************************************************* // getDeity //********************************************************************* unsigned short Creature::getDeity() const { return(deity); } //********************************************************************* // getSize //********************************************************************* Size Creature::getSize() const { return(size); } //********************************************************************* // getAttackPower //********************************************************************* unsigned int Creature::getAttackPower() const { return(attackPower); } //********************************************************************* // getDescription //********************************************************************* bstring Creature::getDescription() const { return(description); } //********************************************************************* // getVersion //********************************************************************* bstring Creature::getVersion() const { return(version); } //********************************************************************* // getPoisonDuration //********************************************************************* unsigned short Creature::getPoisonDuration() const { return(poison_dur); } //********************************************************************* // getPoisonDamage //********************************************************************* unsigned short Creature::getPoisonDamage() const { return(poison_dmg); } //********************************************************************* // getSex //********************************************************************* Sex Creature::getSex() const { if(isPlayer()) { if(flagIsSet(P_SEXLESS)) return(SEX_NONE); if(flagIsSet(P_MALE)) return(SEX_MALE); return(SEX_FEMALE); } else { if(flagIsSet(M_SEXLESS)) return(SEX_NONE); if(flagIsSet(M_MALE)) return(SEX_MALE); return(SEX_FEMALE); } } //********************************************************************* // getRealm //********************************************************************* unsigned long Creature::getRealm(Realm r) const { return(realm[r-1]); } //********************************************************************* // getPoisonedBy //********************************************************************* bstring Creature::getPoisonedBy() const { return(poisonedBy); } //********************************************************************* // inJail //********************************************************************* bool Creature::inJail() const { if(isStaff()) return(false); if(!inUniqueRoom()) return(false); return(getConstUniqueRoomParent()->flagIsSet(R_JAIL)); } //********************************************************************* // addExperience //********************************************************************* void Creature::addExperience(unsigned long e) { setExperience(experience + e); if(isPlayer()) getAsPlayer()->checkLevel(); } //********************************************************************* // subExperience //********************************************************************* void Creature::subExperience(unsigned long e) { setExperience(e > experience ? 0 : experience - e); int lost = (e > experience ? 0 : e); if(isPlayer()) { getAsPlayer()->checkLevel(); getAsPlayer()->statistics.experienceLost(lost); } } //********************************************************************* // setExperience //********************************************************************* void Creature::setExperience(unsigned long e) { experience = tMIN<unsigned long>(2100000000, e); } //********************************************************************* // setClass //********************************************************************* void Creature::setClass(unsigned short c) { c = tMIN<unsigned short>(CLASS_COUNT-1, c); if(cClass == PUREBLOOD && c != PUREBLOOD) removeEffect("vampirism"); else if(cClass == WEREWOLF && c != WEREWOLF) removeEffect("lycanthropy"); if(cClass != PUREBLOOD && c == PUREBLOOD) { if(!isEffected("vampirism")) { addPermEffect("vampirism"); if(isPlayer()) getAsPlayer()->makeVampire(); } } else if(cClass != WEREWOLF && c == WEREWOLF) { if(!isEffected("lycanthropy")) { addPermEffect("lycanthropy"); if(isPlayer()) getAsPlayer()->makeWerewolf(); } } if(c == LICH) { // Liches don't get hp bonus for con constitution.setInfluences(NULL); hp.setInfluencedBy(NULL); } cClass = c; } //********************************************************************* // setClan //********************************************************************* void Creature::setClan(unsigned short c) { clan = c; } //********************************************************************* // setLevel //********************************************************************* void Creature::setLevel(unsigned short l, bool isDm) { level = tMAX(1, tMIN<int>(l, isDm ? 127 : MAXALVL)); } //********************************************************************* // setAlignment //********************************************************************* void Creature::setAlignment(short a) { alignment = tMAX<short>(-1000, tMIN<short>(1000, a)); } //********************************************************************* // subAlignment //********************************************************************* void Creature::subAlignment(unsigned short a) { setAlignment(alignment - a); } //********************************************************************* // setArmor //********************************************************************* void Creature::setArmor(unsigned int a) { armor = tMAX<unsigned int>(tMIN(a, MAX_ARMOR), 0); } //********************************************************************* // setAttackPower //********************************************************************* void Creature::setAttackPower(unsigned int a) { attackPower = tMIN<unsigned int>(1500, a); } //********************************************************************* // setDeity //********************************************************************* void Creature::setDeity(unsigned short d) { deity = tMIN<unsigned short>(d, DEITY_COUNT-1); } //********************************************************************* // setRace //********************************************************************* void Creature::setRace(unsigned short r) { race = tMIN<unsigned short>(gConfig->raceCount()-1, r); } //********************************************************************* // setSize //********************************************************************* void Creature::setSize(Size s) { size = tMAX(NO_SIZE, tMIN(MAX_SIZE, s)); } //********************************************************************* // setType //********************************************************************* void Creature::setType(unsigned short t) { type = (mType)tMIN<short>(MAX_MOB_TYPES-1, t); } //********************************************************************* // setType //********************************************************************* void Creature::setType(mType t) { type = t; } //********************************************************************* // setDescription //********************************************************************* void Creature::setDescription(const bstring& desc) { description = desc; if(isMonster()) description.Replace("*CR*", "\n"); } //********************************************************************* // setVersion //********************************************************************* void Creature::setVersion(bstring v) { version = v == "" ? VERSION : v; } //********************************************************************* // setVersion //********************************************************************* void Creature::setVersion(xmlNodePtr rootNode) { xml::copyPropToBString(version, rootNode, "Version"); } //********************************************************************* // setPoisonDuration //********************************************************************* void Creature::setPoisonDuration(unsigned short d) { poison_dur = d; } //********************************************************************* // setPoisonDamage //********************************************************************* void Creature::setPoisonDamage(unsigned short d) { poison_dmg = d; } //********************************************************************* // setSex //********************************************************************* void Creature::setSex(Sex sex) { if(isPlayer()) { if(sex == SEX_FEMALE) { clearFlag(P_SEXLESS); clearFlag(P_MALE); } else if(sex == SEX_MALE) { clearFlag(P_SEXLESS); setFlag(P_MALE); } else { setFlag(P_SEXLESS); clearFlag(P_MALE); } } else { if(sex == SEX_FEMALE) { clearFlag(M_SEXLESS); clearFlag(M_MALE); } else if(sex == SEX_MALE) { clearFlag(M_SEXLESS); setFlag(M_MALE); } else { setFlag(M_SEXLESS); clearFlag(M_MALE); } } } //********************************************************************* // getSexName //********************************************************************* bstring getSexName(Sex sex) { if(sex == SEX_FEMALE) return("Female"); if(sex == SEX_MALE) return("Male"); if(sex == SEX_NONE) return("Genderless"); return("Unknown"); } //********************************************************************* // setDeathType //********************************************************************* void Creature::setDeathType(DeathType d) { deathtype = d; } //********************************************************************* // setRealm //********************************************************************* void Creature::setRealm(unsigned long num, Realm r) { realm[r-1] = tMIN<unsigned long>(10000000, num); } //********************************************************************* // addRealm //********************************************************************* void Creature::addRealm(unsigned long num, Realm r) { setRealm(getRealm(r) + num, r); } //********************************************************************* // subRealm //********************************************************************* void Creature::subRealm(unsigned long num, Realm r) { setRealm(num > getRealm(r) ? 0 : getRealm(r) - num, r); } //********************************************************************* // setPoisonedBy //********************************************************************* void Creature::setPoisonedBy(const bstring& p) { poisonedBy = p; } //********************************************************************* // getMobTrade //********************************************************************* unsigned short Monster::getMobTrade() const { return(mobTrade); } //********************************************************************* // getSkillLevel //********************************************************************* int Monster::getSkillLevel() const { return(skillLevel); } //********************************************************************* // getMaxLevel //********************************************************************* unsigned int Monster::getMaxLevel() const { return(maxLevel); } //********************************************************************* // getNumWander //********************************************************************* unsigned short Monster::getNumWander() const { return(numwander); } //********************************************************************* // getLoadAggro //********************************************************************* unsigned short Monster::getLoadAggro() const { return(loadAggro); } //********************************************************************* // getUpdateAggro //********************************************************************* unsigned short Monster::getUpdateAggro() const { return(updateAggro); } //********************************************************************* // getCastChance //********************************************************************* unsigned short Monster::getCastChance() const { return(cast); } //********************************************************************* // getMagicResistance //********************************************************************* unsigned short Monster::getMagicResistance() const { return(magicResistance); } //********************************************************************* // getPrimeFaction //********************************************************************* bstring Monster::getPrimeFaction() const { return(primeFaction); } //********************************************************************* // getTalk //********************************************************************* bstring Monster::getTalk() const { return(talk); } //********************************************************************* // setMaxLevel //********************************************************************* void Monster::setMaxLevel(unsigned short l) { maxLevel = tMAX<unsigned short>(0, tMIN<unsigned short>(l, MAXALVL)); } //********************************************************************* // setCastChance //********************************************************************* void Monster::setCastChance(unsigned short c) { cast = tMAX<unsigned short>(0, tMIN<unsigned short>(c, 100)); } //********************************************************************* // setMagicResistance //********************************************************************* void Monster::setMagicResistance(unsigned short m) { magicResistance = tMAX<unsigned short>(0, tMIN<unsigned short>(100, m)); } //********************************************************************* // setLoadAggro //********************************************************************* void Monster::setLoadAggro(unsigned short a) { loadAggro = tMAX<unsigned short>(0, tMIN<unsigned short>(a, 99)); } //********************************************************************* // setUpdateAggro //********************************************************************* void Monster::setUpdateAggro(unsigned short a) { updateAggro = tMAX<unsigned short>(1, tMIN<unsigned short>(a, 99)); } //********************************************************************* // setNumWander //********************************************************************* void Monster::setNumWander(unsigned short n) { numwander = tMAX<unsigned short>(0, tMIN<unsigned short>(6, n)); } //********************************************************************* // setSkillLevel //********************************************************************* void Monster::setSkillLevel(int l) { skillLevel = tMAX(0, tMIN(100, l)); } //********************************************************************* // setMobTrade //********************************************************************* void Monster::setMobTrade(unsigned short t) { mobTrade = tMAX<unsigned short>(0,tMIN<unsigned short>(MOBTRADE_COUNT-1, t)); } //********************************************************************* // setPrimeFaction //********************************************************************* void Monster::setPrimeFaction(bstring f) { primeFaction = f; } //********************************************************************* // setTalk //********************************************************************* void Monster::setTalk(bstring t) { talk = t; talk.Replace("*CR*", "\n"); } //********************************************************************* // getSecondClass //********************************************************************* unsigned short Player::getSecondClass() const { return(cClass2); } //********************************************************************* // getGuild //********************************************************************* unsigned short Player::getGuild() const { return(guild); } //********************************************************************* // getGuildRank //********************************************************************* unsigned short Player::getGuildRank() const { return(guildRank); } //********************************************************************* // getActualLevel //********************************************************************* unsigned short Player::getActualLevel() const { return(actual_level); } //********************************************************************* // getNegativeLevels //********************************************************************* unsigned short Player::getNegativeLevels() const { return(negativeLevels); } //********************************************************************* // getWimpy //********************************************************************* unsigned short Player::getWimpy() const { return(wimpy); } //********************************************************************* // getTickDamage //********************************************************************* unsigned short Player::getTickDamage() const { return(tickDmg); } //********************************************************************* // getWarnings //********************************************************************* unsigned short Player::getWarnings() const { return(warnings); } //********************************************************************* // getPkin //********************************************************************* unsigned short Player::getPkin() const { return(pkin); } //********************************************************************* // getPkwon //********************************************************************* unsigned short Player::getPkwon() const { return(pkwon); } //********************************************************************* // getWrap //********************************************************************* int Player::getWrap() const { return(wrap); } //********************************************************************* // getLuck //********************************************************************* short Player::getLuck() const { return(luck); } //********************************************************************* // getWeaponTrains //********************************************************************* unsigned short Player::getWeaponTrains() const { return(weaponTrains); } //********************************************************************* // getLastLogin //********************************************************************* long Player::getLastLogin() const { return(lastLogin); } //********************************************************************* // getLastInterest //********************************************************************* long Player::getLastInterest() const { return(lastInterest); } //********************************************************************* // getLastPassword //********************************************************************* bstring Player::getLastPassword() const { return(lastPassword); } //********************************************************************* // getAfflictedBy //********************************************************************* bstring Player::getAfflictedBy() const { return(afflictedBy); } //********************************************************************* // getLastCommunicate //********************************************************************* bstring Player::getLastCommunicate() const { return(lastCommunicate); } //********************************************************************* // getLastCommand //********************************************************************* bstring Player::getLastCommand() const { return(lastCommand); } //********************************************************************* // getSurname //********************************************************************* bstring Player::getSurname() const { return(surname); } //********************************************************************* // getForum //********************************************************************* bstring Player::getForum() const { return(forum); } //********************************************************************* // getCreated //********************************************************************* long Player::getCreated() const { return(created); } //********************************************************************* // getCreatedStr //********************************************************************* bstring Player::getCreatedStr() const { bstring str; if(created) { str = ctime(&created); str.trim(); } else str = oldCreated; return(str); } //********************************************************************* // getAlias //********************************************************************* Monster* Player::getAlias() const { return(alias_crt); } //********************************************************************* // getBirthday //********************************************************************* cDay* Player::getBirthday() const { return(birthday); } //********************************************************************* // getAnchorAlias //********************************************************************* bstring Player::getAnchorAlias(int i) const { return(anchor[i] ? anchor[i]->getAlias() : ""); } //********************************************************************* // getAnchorRoomName //********************************************************************* bstring Player::getAnchorRoomName(int i) const { return(anchor[i] ? anchor[i]->getRoomName() : ""); } //********************************************************************* // getAnchor //********************************************************************* const Anchor* Player::getAnchor(int i) const { return(anchor[i]); } //********************************************************************* // hasAnchor //********************************************************************* bool Player::hasAnchor(int i) const { return(!!anchor[i]); } //********************************************************************* // isAnchor //********************************************************************* bool Player::isAnchor(int i, const BaseRoom* room) const { return(anchor[i]->is(room)); } //********************************************************************* // getThirst //********************************************************************* unsigned short Player::getThirst() const { return(thirst); } //********************************************************************* // numDiscoveredRooms //********************************************************************* int Player::numDiscoveredRooms() const { return(roomExp.size()); } //********************************************************************* // getUniqueObjId //********************************************************************* int Player::getUniqueObjId() const { return(uniqueObjId); } //********************************************************************* // setTickDamage //********************************************************************* void Player::setTickDamage(unsigned short t) { tickDmg = t; } //********************************************************************* // setWarnings //********************************************************************* void Player::setWarnings(unsigned short w) { warnings = w; } //********************************************************************* // addWarnings //********************************************************************* void Player::addWarnings(unsigned short w) { setWarnings(w + warnings); } //********************************************************************* // subWarnings //********************************************************************* void Player::subWarnings(unsigned short w) { setWarnings(w > warnings ? 0 : warnings - w); } //********************************************************************* // setWimpy //********************************************************************* void Player::setWimpy(unsigned short w) { wimpy = w; } //********************************************************************* // setActualLevel //********************************************************************* void Player::setActualLevel(unsigned short l) { actual_level = tMAX<unsigned short>(1, tMIN<unsigned short>(l, MAXALVL)); } //********************************************************************* // setSecondClass //********************************************************************* void Player::setSecondClass(unsigned short c) { cClass2 = tMAX<unsigned short>(0, tMIN<unsigned short>(CLASS_COUNT - 1, c)); } //********************************************************************* // setGuild //********************************************************************* void Player::setGuild(unsigned short g) { guild = g; } //********************************************************************* // setGuildRank //********************************************************************* void Player::setGuildRank(unsigned short g) { guildRank = g; } //********************************************************************* // setNegativeLevels //********************************************************************* void Player::setNegativeLevels(unsigned short l) { negativeLevels = tMAX<unsigned short>(0, tMIN<unsigned short>(exp_to_lev(experience), l)); } //********************************************************************* // setLuck //********************************************************************* void Player::setLuck(int l) { luck = l; } //********************************************************************* // setWeaponTrains //********************************************************************* void Player::setWeaponTrains(unsigned short t) { weaponTrains = t; } //********************************************************************* // subWeaponTrains //********************************************************************* void Player::subWeaponTrains(unsigned short t) { setWeaponTrains(t > weaponTrains ? 0 : weaponTrains - t); } //********************************************************************* // setLastPassword //********************************************************************* void Player::setLastPassword(bstring p) { lastPassword = p; } //********************************************************************* // setAfflictedBy //********************************************************************* void Player::setAfflictedBy(bstring a) { afflictedBy = a; } //********************************************************************* // setLastLogin //********************************************************************* void Player::setLastLogin(long l) { lastLogin = tMAX<long>(0, l); } //********************************************************************* // setLastInterest //********************************************************************* void Player::setLastInterest(long l) { lastInterest = tMAX<long>(0, l); } //********************************************************************* // setLastCommunicate //********************************************************************* void Player::setLastCommunicate(bstring c) { lastCommunicate = c; } //********************************************************************* // setLastCommand //********************************************************************* void Player::setLastCommand(bstring c) { lastCommand = c; lastCommand.trim(); } //********************************************************************* // setCreated //********************************************************************* void Player::setCreated() { created = time(0); } //********************************************************************* // setSurname //********************************************************************* void Player::setSurname(bstring s) { surname = s.left(20); } //********************************************************************* // setForum //********************************************************************* void Player::setForum(bstring f) { forum = f; } //********************************************************************* // setAlias //********************************************************************* void Player::setAlias(Monster* m) { alias_crt = m; } //********************************************************************* // setBirthday //********************************************************************* void Player::setBirthday() { const Calendar* calendar = gConfig->getCalendar(); if(birthday) delete birthday; birthday = new cDay; birthday->setYear(calendar->getCurYear() - gConfig->getRace(getRace())->getStartAge()); birthday->setDay(calendar->getCurDay()); birthday->setMonth(calendar->getCurMonth()); } //********************************************************************* // delAnchor //********************************************************************* void Player::delAnchor(int i) { if(anchor[i]) { delete anchor[i]; anchor[i] = 0; } } //********************************************************************* // setAnchor //********************************************************************* void Player::setAnchor(int i, bstring a) { delAnchor(i); anchor[i] = new Anchor(a, this); } //********************************************************************* // setThirst //********************************************************************* void Player::setThirst(unsigned short t) { thirst = t; } int Player::setWrap(int newWrap) { if(newWrap < -1) newWrap = -1; if(newWrap > 500) newWrap = 500; wrap = newWrap; return(wrap); } //********************************************************************* // setCustomColor //********************************************************************* void Player::setCustomColor(CustomColor i, char c) { customColors[i] = c; } //********************************************************************* // getMaster //********************************************************************* Creature* Creature::getMaster() { return((isMonster() ? getAsMonster()->getMaster() : this)); } //********************************************************************* // getConstMaster //********************************************************************* const Creature* Creature::getConstMaster() const { return((isMonster() ? getAsConstMonster()->getMaster() : this)); } //********************************************************************* // getPlayerMaster //********************************************************************* Player* Creature::getPlayerMaster() { if(!getMaster()) return(NULL); return(getMaster()->getAsPlayer()); } //********************************************************************* // getConstPlayerMaster //********************************************************************* const Player* Creature::getConstPlayerMaster() const { if(!getConstMaster()) return(NULL); return(getConstMaster()->getAsConstPlayer()); } //********************************************************************* // isPlayer //********************************************************************* bool Creature::isPlayer() const { return(type == PLAYER); } //********************************************************************* // isMonster //********************************************************************* bool Creature::isMonster() const { return(type != PLAYER); } //********************************************************************* // crtReset //********************************************************************* // Resets all common structure elements of creature void Creature::crtReset() { // Reset Stream related initStreamable(); // Reset other related moReset(); playing = NULL; myTarget = NULL; for(Creature* targeter : targetingThis) { targeter->clearTarget(false); } // Clear out any skills/factions/etc crtDestroy(); zero(key, sizeof(key)); poisonedBy = description = ""; version = "0.00"; fd = -1; level = cClass = race = alignment = experience = temp_experience = clan = 0; size = NO_SIZE; type = PLAYER; deathtype = DT_NONE; int i; coins.zero(); zero(realm, sizeof(realm)); zero(flags, sizeof(flags)); zero(spells, sizeof(spells)); zero(quests, sizeof(quests)); zero(languages, sizeof(languages)); questnum = 0; strength.setName("Strength"); dexterity.setName("Dexterity"); constitution.setName("Constitution"); intelligence.setName("Intelligence"); piety.setName("Piety"); hp.setName("Hp"); mp.setName("Mp"); if(getAsPlayer()) { getAsPlayer()->focus.setName("Focus"); constitution.setInfluences(&hp); hp.setInfluencedBy(&constitution); intelligence.setInfluences(&mp); mp.setInfluencedBy(&intelligence); } for(i=0; i<MAXWEAR; i++) ready[i] = 0; first_tlk = 0; currentLocation.mapmarker.reset(); currentLocation.room.clear(); group = 0; groupStatus = GROUP_NO_STATUS; current_language = 0; afterProf = 0; memset(movetype, 0, sizeof(movetype)); poison_dur = poison_dmg = 0; for(i=0; i<6; i++) proficiency[i] = 0; deity = 0; memset(spellTimer, 0, sizeof(spellTimer)); armor = 0; for(i=0; i<21; i++) misc[i] = 0; } //********************************************************************* // reset //********************************************************************* void Monster::reset() { // Call Creature::reset first crtReset(); int i; info.clear(); memset(attack, 0, sizeof(attack)); memset(aggroString, 0, sizeof(aggroString)); talk = ""; plural = ""; baseRealm = NO_REALM; defenseSkill = weaponSkill = attackPower = 0; numwander = loadAggro = 0; memset(last_mod, 0, sizeof(last_mod)); mobTrade = 0; skillLevel = 0; maxLevel = 0; memset(ttalk, 0, sizeof(ttalk)); for(i=0; i<NUM_RESCUE; i++) rescue[i].clear(); myMaster = 0; updateAggro = 0; cast = 0; magicResistance = 0; jail.clear(); primeFaction = ""; memset(cClassAggro, 0, sizeof(cClassAggro)); memset(raceAggro, 0, sizeof(raceAggro)); memset(deityAggro, 0, sizeof(deityAggro)); std::list<TalkResponse*>::iterator tIt; for(tIt = responses.begin() ; tIt != responses.end() ; tIt++) { delete (*tIt); } responses.clear(); } //********************************************************************* // reset //********************************************************************* void Player::reset() { // Call Creature::reset first crtReset(); //playing = NULL; wrap = -1; cClass2 = wimpy = 0; barkskin = 0; weaponTrains = 0; bank.zero(); created = 0; oldCreated = surname = lastCommand = lastCommunicate = password = title = tempTitle = ""; lastPassword = afflictedBy = forum = ""; tickDmg = pkwon = pkin = lastLogin = lastInterest = uniqueObjId = 0; memset(songs, 0, sizeof(songs)); guild = guildRank = cClass2 = 0; int i; actual_level = warnings = 0; for(i=0; i<MAX_DIMEN_ANCHORS; i++) anchor[i] = 0; negativeLevels = 0; birthday = NULL; first_charm = 0; luck = 0; ansi = 0; alias_crt = 0; scared_of = 0; for(i=0; i<5; i++) tnum[i] = 0; timeout = 0; thirst = 0; resetCustomColors(); lastPawn = 0; storesRefunded.clear(); roomExp.clear(); objIncrease.clear(); lore.clear(); recipes.clear(); std::map<int, QuestCompletion*>::iterator qIt; for(qIt = questsInProgress.begin() ; qIt != questsInProgress.end() ; qIt++) { delete (*qIt).second; } questsInProgress.clear(); questsCompleted.clear(); } //********************************************************************* // Creature //********************************************************************* Creature::Creature() { hooks.setParent(this); } //********************************************************************* // CopyCommon //********************************************************************* void Creature::CopyCommon(const Creature& cr) { int i=0; moCopy(cr); description = cr.description; for(i=0; i<3; i++) { strcpy(key[i], cr.key[i]); } fd = cr.fd; level = cr.level; type = cr.type; cClass = cr.cClass; race = cr.race; alignment = cr.alignment; experience = cr.experience; temp_experience = cr.temp_experience; poisonedBy = cr.poisonedBy; damage = cr.damage; clan = cr.clan; questnum = cr.questnum; size = cr.size; for(Realm r = MIN_REALM; r<MAX_REALM; r = (Realm)((int)r + 1)) setRealm(cr.getRealm(r), r); for(i=0; i<CRT_FLAG_ARRAY_SIZE; i++) flags[i] = cr.flags[i]; poison_dur = cr.poison_dur; poison_dmg = cr.poison_dmg; strength = cr.strength; dexterity = cr.dexterity; constitution = cr.constitution; intelligence = cr.intelligence; piety = cr.piety; hp = cr.hp; mp = cr.mp; pp = cr.pp; rp = cr.rp; hpTic = cr.hpTic; mpTic = cr.mpTic; ppTic = cr.ppTic; rpTic = cr.rpTic; armor = cr.armor; current_language = cr.current_language; deity = cr.deity; for(i=0; i<MAXWEAR; i++) ready[i] = cr.ready[i]; //following = cr.following; group = cr.group; groupStatus = cr.groupStatus; first_tlk = cr.first_tlk; objects = cr.objects; currentLocation.room = cr.currentLocation.room; currentLocation.mapmarker = cr.currentLocation.mapmarker; parent = cr.parent; for(i=0; i<6; i++) saves[i] = cr.saves[i]; for(i=0; i<16; i++) languages[i] = cr.languages[i]; for(i=0; i<32; i++) { spells[i] = cr.spells[i]; quests[i] = cr.quests[i]; } coins.set(cr.coins); for(i=0; i<6; i++) proficiency[i] = cr.proficiency[i]; for(i=0; i<20; i++) daily[i] = cr.daily[i]; for(i=0; i<128; i++) lasttime[i] = cr.lasttime[i]; for(i=0; i<16; i++) spellTimer[i] = cr.spellTimer[i]; factions = cr.factions; //skills = cr.skills; Skill* skill; Skill* crSkill; std::map<bstring, Skill*>::const_iterator csIt; for(csIt = cr.skills.begin() ; csIt != cr.skills.end() ; csIt++) { crSkill = (*csIt).second; skill = new Skill; (*skill) = (*crSkill); skills[crSkill->getName()] = skill; } effects.copy(&cr.effects, this); std::list<bstring>::const_iterator mIt; for(mIt = cr.minions.begin() ; mIt != cr.minions.end() ; mIt++) { minions.push_back(*mIt); } SpecialAttack* attack; std::list<SpecialAttack*>::const_iterator sIt; for(sIt = cr.specials.begin() ; sIt != cr.specials.end() ; sIt++) { attack = new SpecialAttack(); (*attack) = *(*sIt); specials.push_back(attack); } for(Monster* pet : cr.pets) { pets.push_back(pet); } attackPower = cr.attackPower; previousRoom = cr.previousRoom; } //********************************************************************* // doCopy //********************************************************************* void Player::doCopy(const Player& cr) { // We want a copy of what we're getting, so clear out anything that was here before reset(); // Copy anything in common with the base class CopyCommon(cr); // Players have a unique ID, so copy that id = cr.id; // Now copy player specfic stuff int i=0; created = cr.created; oldCreated = cr.oldCreated; playing = cr.playing; wrap = cr.wrap; title = cr.title; password = cr.getPassword(); surname = cr.surname; forum = cr.forum; bank.set(cr.bank); lastPassword = cr.lastPassword; lastCommand = cr.lastCommand; lastCommunicate = cr.lastCommunicate; afflictedBy = cr.afflictedBy; lastLogin = cr.lastLogin; lastInterest = cr.lastInterest; tempTitle = cr.tempTitle; std::list<CatRef>::const_iterator it; if(!cr.storesRefunded.empty()) { for(it = cr.storesRefunded.begin() ; it != cr.storesRefunded.end() ; it++) { storesRefunded.push_back(*it); } } if(!cr.roomExp.empty()) { for(it = cr.roomExp.begin() ; it != cr.roomExp.end() ; it++) { roomExp.push_back(*it); } } if(!cr.objIncrease.empty()) { for(it = cr.objIncrease.begin() ; it != cr.objIncrease.end() ; it++) { objIncrease.push_back(*it); } } if(!cr.lore.empty()) { for(it = cr.lore.begin() ; it != cr.lore.end() ; it++) { lore.push_back(*it); } } std::list<int>::const_iterator rt; if(!cr.recipes.empty()) { for(rt = cr.recipes.begin() ; rt != cr.recipes.end() ; rt++) { recipes.push_back(*rt); } } cClass2 = cr.cClass2; wimpy = cr.wimpy; tickDmg = cr.tickDmg; pkwon = cr.pkwon; pkin = cr.pkin; bound = cr.bound; statistics = cr.statistics; for(i=0; i<32; i++) songs[i] = cr.songs[i]; guild = cr.guild; guildRank = cr.guildRank; cClass2 = cr.cClass2; focus = cr.focus; negativeLevels = cr.negativeLevels; actual_level = cr.actual_level; warnings = cr.warnings; for(i=0; i<3; i++) strcpy(movetype[i], cr.movetype[i]); for(i=0; i<MAX_DIMEN_ANCHORS; i++) { if(cr.anchor[i]) { anchor[i] = new Anchor; *anchor[i] = *cr.anchor[i]; } } for(i=0; i<MAX_BUILDER_RANGE; i++) { bRange[i] = cr.bRange[i]; } for(i=0; i<21; i++) misc[i] = cr.misc[i]; if(cr.birthday) { birthday = new cDay; *(birthday) = *(cr.birthday); } strcpy(customColors, cr.customColors); thirst = cr.thirst; weaponTrains = cr.weaponTrains; attackTimer = cr.attackTimer; // TODO: Look at this and make sure it's doing what i want it to do QuestCompletion *oldQuest; QuestCompletion *newQuest; for(std::pair<int, QuestCompletion*> p : cr.questsInProgress) { oldQuest = p.second; newQuest = new QuestCompletion(*(oldQuest)); //*(newQuest) = *(oldQuest); questsInProgress[p.first] = newQuest; } for(std::pair<int, int> qc : cr.questsCompleted) { questsCompleted.insert(qc); } } //********************************************************************* // doCopy //********************************************************************* void Monster::doCopy(const Monster& cr) { // We want a copy of what we're getting, so clear out anything that was here before reset(); // Copy anything in common with the base class CopyCommon(cr); // Now do monster specific copies int i; strcpy(aggroString, cr.aggroString); talk = cr.talk; plural = cr.plural; strcpy(last_mod, cr.last_mod); strcpy(ttalk, cr.ttalk); for(i=0; i<3; i++) strcpy(attack[i], cr.attack[i]); for(i=0; i<NUM_RESCUE; i++) rescue[i] = cr.rescue[i]; baseRealm = cr.baseRealm; mobTrade = cr.mobTrade; skillLevel = cr.skillLevel; maxLevel = cr.maxLevel; jail = cr.jail; cast = cr.cast; myMaster = cr.myMaster; loadAggro = cr.loadAggro; info = cr.info; updateAggro = cr.updateAggro; numwander = cr.numwander; for(i=0; i<10; i++) carry[i] = cr.carry[i]; primeFaction = cr.primeFaction; magicResistance = cr.magicResistance; for(i=0; i<NUM_ASSIST_MOB; i++) assist_mob[i] = cr.assist_mob[i]; for(i=0; i<NUM_ENEMY_MOB; i++) enemy_mob[i] = cr.enemy_mob[i]; for(i=0; i<3; i++) { strcpy(movetype[i], cr.movetype[i]); } for(i=0; i<4; i++) { cClassAggro[i] = cr.cClassAggro[i]; raceAggro[i] = cr.raceAggro[i]; deityAggro[i] = cr.deityAggro[i]; } for(i=0; i<21; i++) misc[i] = cr.misc[i]; defenseSkill = cr.defenseSkill; weaponSkill = cr.weaponSkill; for(TalkResponse* response : cr.responses) { responses.push_back(new TalkResponse(*response)); } } //********************************************************************* // getLocation //********************************************************************* Monster::Monster() { reset(); threatTable = new ThreatTable(this); } Monster::Monster(Monster& cr) { doCopy(cr); } Monster::Monster(const Monster& cr) { doCopy(cr); } //********************************************************************* // Monster operators //********************************************************************* Monster& Monster::operator=(const Monster& cr) { doCopy(cr); return(*this); } //********************************************************************* // Player //********************************************************************* Player::Player() { reset(); mySock = NULL; // initial flags for new characters setFlag(P_NO_AUTO_WEAR); } Player::Player(Player& cr) { doCopy(cr); } Player::Player(const Player& cr) { doCopy(cr); } //********************************************************************* // Player operators //********************************************************************* Player& Player::operator=(const Player& cr) { doCopy(cr); return(*this); } //********************************************************************* // crtDestroy //********************************************************************* // Things all subclasses must destroy void Creature::crtDestroy() { for(Creature* targeter : targetingThis) { targeter->clearTarget(false); } clearTarget(); moDestroy(); factions.clear(); Skill* skill; std::map<bstring, Skill*>::iterator csIt; for(csIt = skills.begin() ; csIt != skills.end() ; csIt++) { skill = (*csIt).second; delete skill; } skills.clear(); effects.removeAll(); minions.clear(); SpecialAttack* attack; std::list<SpecialAttack*>::iterator sIt; for(sIt = specials.begin() ; sIt != specials.end() ; sIt++) { attack = (*sIt); delete attack; (*sIt) = NULL; } specials.clear(); } //********************************************************************* // Monster //********************************************************************* Monster::~Monster() { crtDestroy(); if(threatTable) { delete threatTable; threatTable = 0; } } //********************************************************************* // Player //********************************************************************* Player::~Player() { crtDestroy(); int i = 0; if(birthday) { delete birthday; birthday = NULL; } for(i=0; i<MAX_DIMEN_ANCHORS; i++) { if(anchor[i]) { delete anchor[i]; anchor[i] = 0; } } QuestCompletion *quest; for(std::pair<int, QuestCompletion*> p : questsInProgress) { quest = p.second; delete quest; } questsInProgress.clear(); questsCompleted.clear(); setLastPawn(0); } //********************************************************************* // isPublicWatcher //********************************************************************* bool Creature::isPublicWatcher() const { if(isMonster()) return(false); return(flagIsSet(P_WATCHER) && !flagIsSet(P_SECRET_WATCHER)); } //********************************************************************* // isWatcher //********************************************************************* bool Creature::isWatcher() const { if(isMonster()) return(false); return(isCt() || flagIsSet(P_WATCHER)); } //********************************************************************* // isStaff //********************************************************************* bool Creature::isStaff() const { if(!this || isMonster()) return(false); return(cClass >= BUILDER); } //********************************************************************* // isCt //********************************************************************* bool Creature::isCt() const { if(isMonster()) return(false); return(cClass >= CARETAKER); } //********************************************************************* // isDm //********************************************************************* bool Creature::isDm() const { if(isMonster()) return(false); return(cClass == DUNGEONMASTER); } //********************************************************************* // isAdm //********************************************************************* bool Creature::isAdm() const { if(isMonster()) return(false); return(getName() == "Bane" || getName() == "Dominus" || getName() == "Ocelot"); } //********************************************************************* // flagIsSet //********************************************************************* bool Creature::flagIsSet(int flag) const { return(flags[flag/8] & 1<<(flag%8)); } bool Creature::pFlagIsSet(int flag) const { return(isPlayer() && flagIsSet(flag)); } bool Creature::mFlagIsSet(int flag) const { return(isMonster() && flagIsSet(flag)); } //********************************************************************* // setFlag //********************************************************************* void Creature::setFlag(int flag) { flags[flag/8] |= 1<<(flag%8); if(flag == P_NO_TRACK_STATS && isPlayer()) getAsPlayer()->statistics.track = false; } void Creature::pSetFlag(int flag) { if(!isPlayer()) return; setFlag(flag); } void Creature::mSetFlag(int flag) { if(!isMonster()) return; setFlag(flag); } //********************************************************************* // clearFlag //********************************************************************* void Creature::clearFlag(int flag) { flags[flag/8] &= ~(1<<(flag%8)); if(flag == P_NO_TRACK_STATS && isPlayer()) getAsPlayer()->statistics.track = true; } void Creature::pClearFlag(int flag) { if(!isPlayer()) return; clearFlag(flag); } void Creature::mClearFlag(int flag) { if(!isMonster()) return; clearFlag(flag); } //********************************************************************* // toggleFlag //********************************************************************* bool Creature::toggleFlag(int flag) { if(flagIsSet(flag)) clearFlag(flag); else setFlag(flag); return(flagIsSet(flag)); } //********************************************************************* // languageIsKnown //********************************************************************* bool Creature::languageIsKnown(int lang) const { return(languages[lang/8] & 1<<(lang%8)); } //********************************************************************* // learnLanguage //********************************************************************* void Creature::learnLanguage(int lang) { languages[lang/8] |= 1<<(lang%8); } //********************************************************************* // forgetLanguage //********************************************************************* void Creature::forgetLanguage(int lang) { languages[lang/8] &= ~(1<<(lang%8)); } //********************************************************************* // spellIsKnown //********************************************************************* bool Creature::spellIsKnown(int spell) const { return(spells[spell/8] & 1<<(spell%8)); } //********************************************************************* // learnSpell //********************************************************************* extern int spllist_size; void Creature::learnSpell(int spell) { if(spell > spllist_size) { broadcast(::isDm, "^G*** Trying to set invalid spell %d on %s. Spell List Size: %d\n", spell, getCName(), spllist_size); return; } spells[spell/8] |= 1<<(spell%8); } //********************************************************************* // forgetSpell //********************************************************************* void Creature::forgetSpell(int spell) { spells[spell/8] &= ~(1<<(spell%8)); } //********************************************************************* // questIsSet //********************************************************************* bool Player::questIsSet(int quest) const { return(quests[quest/8] & 1<<(quest%8)); } //********************************************************************* // setQuest //********************************************************************* void Player::setQuest(int quest) { quests[quest/8] |= 1<<(quest%8); } //********************************************************************* // clearQuest //********************************************************************* void Player::clearQuest(int quest) { quests[quest/8] &= ~(1<<(quest%8)); } //********************************************************************* // songIsKnown //********************************************************************* bool Player::songIsKnown(int song) const { return(songs[song/8] & 1<<(song%8)); } //********************************************************************* // learnSong //********************************************************************* void Player::learnSong(int song) { songs[song/8] |= 1<<(song%8); } //********************************************************************* // forgetSong //********************************************************************* void Player::forgetSong(int song) { songs[song/8] &= ~(1<<(song%8)); } //********************************************************************* // getDisplayRace //********************************************************************* unsigned short Creature::getDisplayRace() const { if(isMonster() || !isEffected("illusion")) return(race); return(getEffect("illusion")->getExtra()); } //********************************************************************* // isRace //********************************************************************* // lets us determine race equality with the presence of subraces bool isRace(int subRace, int mainRace) { return(mainRace == subRace || (mainRace != 0 && gConfig->getRace(subRace)->getParentRace() == mainRace)); } bool Creature::isRace(int r) const { return(::isRace(race, r)); } //********************************************************************* // hisHer //********************************************************************* const char *Creature::hisHer() const { Sex sex = getSex(); if(sex == SEX_FEMALE) return("her"); else if(sex == SEX_MALE) return("his"); return("its"); } //********************************************************************* // himHer //********************************************************************* const char *Creature::himHer() const { Sex sex = getSex(); if(sex == SEX_FEMALE) return("her"); else if(sex == SEX_MALE) return("him"); return("it"); } //********************************************************************* // heShe //********************************************************************* const char *Creature::heShe() const { Sex sex = getSex(); if(sex == SEX_FEMALE) return("she"); else if(sex == SEX_MALE) return("he"); return("it"); } //********************************************************************* // upHisHer //********************************************************************* const char *Creature::upHisHer() const { Sex sex = getSex(); if(sex == SEX_FEMALE) return("Her"); else if(sex == SEX_MALE) return("His"); return("Its"); } //********************************************************************* // upHeShe //********************************************************************* const char *Creature::upHeShe() const { Sex sex = getSex(); if(sex == SEX_FEMALE) return("She"); else if(sex == SEX_MALE) return("He"); return("It"); } //******************************************************************** // getClassString //******************************************************************** bstring Player::getClassString() const { std::ostringstream cStr; cStr << get_class_string(cClass); if(cClass2) cStr << "/" << get_class_string(cClass2); return(cStr.str()); } //******************************************************************** // isBrittle //******************************************************************** bool Creature::isBrittle() const { return(isPlayer() && cClass == LICH); } //******************************************************************** // isUndead //******************************************************************** bool Creature::isUndead() const { if(cClass == LICH) return(true); if(isEffected("vampirism")) return(true); if(isMonster()) { if(monType::isUndead(type)) return(true); if(flagIsSet(M_UNDEAD)) return(true); } return(false); } //********************************************************************* // isUnconscious //********************************************************************* // unconsciousness provides some special protection in combat for which // sleeping people do not qualify. use this function when being unconscious // will help bool Creature::isUnconscious() const { if(isMonster()) return(false); return(flagIsSet(P_UNCONSCIOUS) && !flagIsSet(P_SLEEPING)); } //********************************************************************* // knockUnconscious //********************************************************************* void Creature::knockUnconscious(long duration) { if(isMonster()) return; setFlag(P_UNCONSCIOUS); clearFlag(P_SLEEPING); lasttime[LT_UNCONSCIOUS].ltime = time(0); lasttime[LT_UNCONSCIOUS].interval = duration; } //********************************************************************* // isBraindead //********************************************************************* bool Creature::isBraindead() const { if(isMonster()) return(false); return(flagIsSet(P_BRAINDEAD)); } //********************************************************************* // fullName //********************************************************************* bstring Creature::fullName() const { const Player *player = getAsConstPlayer(); bstring str = getName(); if(player && !player->getProxyName().empty()) str += "(" + player->getProxyName() + ")"; if(player && player->flagIsSet(P_CHOSEN_SURNAME) && player->getSurname() != "") { str += " "; str += player->getSurname(); } return(str); } //********************************************************************* // unmist //********************************************************************* void Creature::unmist() { if(isMonster()) return; if(!isEffected("mist")) return; removeEffect("mist"); clearFlag(P_SNEAK_WHILE_MISTED); unhide(); printColor("^mYou return to your natural form.\n"); if(getRoomParent()) broadcast(getSock(), getRoomParent(), "%M reforms.", this); } //********************************************************************* // unhide //********************************************************************* bool Creature::unhide(bool show) { if(isMonster()) { if(!flagIsSet(M_HIDDEN)) return(false); clearFlag(M_HIDDEN); setFlag(M_WAS_HIDDEN); } else { if(!flagIsSet(P_HIDDEN)) return(false); clearFlag(P_HIDDEN); if(show) printColor("^cYou have become unhidden.\n"); } return(true); } //********************************************************************* // getBaseRealm //********************************************************************* Realm Monster::getBaseRealm() const { return(baseRealm); } //********************************************************************* // setBaseRealm //********************************************************************* void Monster::setBaseRealm(Realm toSet) { baseRealm = toSet; } //********************************************************************* // hasMp //********************************************************************* bool Creature::hasMp() { return(mp.getMax() != 0 && cClass != BERSERKER && cClass != LICH); } //********************************************************************* // doesntBreathe //********************************************************************* bool Creature::doesntBreathe() const { return( (monType::noLivingVulnerabilities(type) || isUndead()) && !isEffected("vampirism") // vampires breathe (and can drown) ); } //********************************************************************* // immuneCriticals //********************************************************************* bool Creature::immuneCriticals() const { return(monType::immuneCriticals(type)); } //********************************************************************* // getSock //********************************************************************* Socket* Creature::getSock() const { return(NULL); } //********************************************************************* // getSock //********************************************************************* Socket* Player::getSock() const { if(!this) return(null); return(mySock); } //********************************************************************* // setSock //********************************************************************* void Player::setSock(Socket* pSock) { mySock = pSock; } //********************************************************************* // canSpeak //********************************************************************* bool Creature::canSpeak() const { if(isStaff()) return(true); if(isEffected("silence")) return(false); if(getParent()->isEffected("globe-of-silence")) return(false); return(true); } //********************************************************************* // unBlind //********************************************************************* void Creature::unBlind() { if(getAsPlayer()) clearFlag(P_DM_BLINDED); } //********************************************************************* // unSilence //********************************************************************* void Creature::unSilence() { if(getAsPlayer()) clearFlag(P_DM_SILENCED); } //********************************************************************* // poisonedByMonster //********************************************************************* bool Creature::poisonedByMonster() const { return(pFlagIsSet(P_POISONED_BY_MONSTER)); } //********************************************************************* // poisonedByPlayer //********************************************************************* bool Creature::poisonedByPlayer() const { return(pFlagIsSet(P_POISONED_BY_PLAYER)); } //********************************************************************* // getLocation //********************************************************************* Location Creature::getLocation() { return(currentLocation); }