void ActiveSpells::update() const { bool rebuild = false; MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp(); if (mLastUpdate!=now) { TContainer::iterator iter (mSpells.begin()); while (iter!=mSpells.end()) if (!timeToExpire (iter)) { mSpells.erase (iter++); rebuild = true; } else ++iter; mLastUpdate = now; } if (mSpellsChanged) { mSpellsChanged = false; rebuild = true; } if (rebuild) { mEffects = MagicEffects(); for (TIterator iter (begin()); iter!=end(); ++iter) { const ESM::EffectList& effects = getEffectList (iter->first); const MWWorld::TimeStamp& start = iter->second.first; float magnitude = iter->second.second; for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.list.begin()); iter!=effects.list.end(); ++iter) { if (iter->duration) { MWWorld::TimeStamp end = start; end += static_cast<double> (iter->duration)* MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); if (end>now) { EffectParam param; param.mMagnitude = static_cast<int> ( (iter->magnMax-iter->magnMin+1)*magnitude + iter->magnMin); mEffects.add (*iter, param); } } } } } }
void Spells::readState(const ESM::SpellState &state) { for (ESM::SpellState::TContainer::const_iterator it = state.mSpells.begin(); it != state.mSpells.end(); ++it) { // Discard spells that are no longer available due to changed content files const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); if (spell) { mSpells[spell].mEffectRands = it->second.mEffectRands; mSpells[spell].mPurgedEffects = it->second.mPurgedEffects; if (it->first == state.mSelectedSpell) mSelectedSpell = it->first; } } for (std::map<std::string, ESM::TimeStamp>::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it) { const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); if (!spell) continue; mUsedPowers[spell] = MWWorld::TimeStamp(it->second); } for (std::map<std::string, std::vector<ESM::SpellState::PermanentSpellEffectInfo> >::const_iterator it = state.mPermanentSpellEffects.begin(); it != state.mPermanentSpellEffects.end(); ++it) { const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); if (!spell) continue; mPermanentSpellEffects[spell] = MagicEffects(); for (std::vector<ESM::SpellState::PermanentSpellEffectInfo>::const_iterator effectIt = it->second.begin(); effectIt != it->second.end(); ++effectIt) { mPermanentSpellEffects[spell].add(EffectKey(effectIt->mId, effectIt->mArg), effectIt->mMagnitude); } } mCorprusSpells.clear(); for (std::map<std::string, ESM::SpellState::CorprusStats>::const_iterator it = state.mCorprusSpells.begin(); it != state.mCorprusSpells.end(); ++it) { const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); if (!spell) // Discard unavailable corprus spells continue; mCorprusSpells[spell].mWorsenings = state.mCorprusSpells.at(it->first).mWorsenings; mCorprusSpells[spell].mNextWorsening = MWWorld::TimeStamp(state.mCorprusSpells.at(it->first).mNextWorsening); } mSpellsChanged = true; }
void Spells::readState(const ESM::SpellState &state) { for (TContainer::const_iterator it = state.mSpells.begin(); it != state.mSpells.end(); ++it) { // Discard spells that are no longer available due to changed content files const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); if (spell) { mSpells[it->first] = it->second; if (it->first == state.mSelectedSpell) mSelectedSpell = it->first; } } // No need to discard spells here (doesn't really matter if non existent ids are kept) for (std::map<std::string, ESM::TimeStamp>::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it) mUsedPowers[it->first] = MWWorld::TimeStamp(it->second); for (std::map<std::string, std::vector<ESM::SpellState::PermanentSpellEffectInfo> >::const_iterator it = state.mPermanentSpellEffects.begin(); it != state.mPermanentSpellEffects.end(); ++it) { const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first); if (!spell) continue; mPermanentSpellEffects[it->first] = MagicEffects(); for (std::vector<ESM::SpellState::PermanentSpellEffectInfo>::const_iterator effectIt = it->second.begin(); effectIt != it->second.end(); ++effectIt) { mPermanentSpellEffects[it->first].add(EffectKey(effectIt->mId, effectIt->mArg), effectIt->mMagnitude); } } mCorprusSpells.clear(); for (std::map<std::string, ESM::SpellState::CorprusStats>::const_iterator it = state.mCorprusSpells.begin(); it != state.mCorprusSpells.end(); ++it) { if (mSpells.find(it->first) != mSpells.end()) // Discard unavailable corprus spells { mCorprusSpells[it->first].mWorsenings = state.mCorprusSpells.at(it->first).mWorsenings; mCorprusSpells[it->first].mNextWorsening = MWWorld::TimeStamp(state.mCorprusSpells.at(it->first).mNextWorsening); } } }
void Spells::rebuildEffects() const { mEffects = MagicEffects(); mSourcedEffects.clear(); for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) { const ESM::Spell *spell = iter->first; if (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight || spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse) { int i=0; for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) { if (iter->second.mPurgedEffects.find(i) != iter->second.mPurgedEffects.end()) continue; // effect was purged float random = 1.f; if (iter->second.mEffectRands.find(i) != iter->second.mEffectRands.end()) random = iter->second.mEffectRands.at(i); float magnitude = it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random; mEffects.add (*it, magnitude); mSourcedEffects[spell].add(MWMechanics::EffectKey(*it), magnitude); ++i; } } } for (std::map<SpellKey, MagicEffects>::const_iterator it = mPermanentSpellEffects.begin(); it != mPermanentSpellEffects.end(); ++it) { mEffects += it->second; mSourcedEffects[it->first] += it->second; } }
void ActiveSpells::rebuildEffects() const { MWWorld::TimeStamp now = MWBase::Environment::get().getWorld()->getTimeStamp(); mEffects = MagicEffects(); for (TIterator iter (begin()); iter!=end(); ++iter) { const MWWorld::TimeStamp& start = iter->second.mTimeStamp; const std::vector<ActiveEffect>& effects = iter->second.mEffects; for (std::vector<ActiveEffect>::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt) { int duration = effectIt->mDuration; MWWorld::TimeStamp end = start; end += static_cast<double> (duration)* MWBase::Environment::get().getWorld()->getTimeScaleFactor()/(60*60); if (end>now) mEffects.add(MWMechanics::EffectKey(effectIt->mEffectId, effectIt->mArg), MWMechanics::EffectParam(effectIt->mMagnitude)); } } }
void Spells::worsenCorprus(const std::string &corpSpellId) { mCorprusSpells[corpSpellId].mNextWorsening = MWBase::Environment::get().getWorld()->getTimeStamp() + CorprusStats::sWorseningPeriod; mCorprusSpells[corpSpellId].mWorsenings++; // update worsened effects mPermanentSpellEffects[corpSpellId] = MagicEffects(); const ESM::Spell * spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(corpSpellId); int i=0; for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = spell->mEffects.mList.begin(); effectIt != spell->mEffects.mList.end(); ++effectIt, ++i) { const ESM::MagicEffect * magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID); if ((effectIt->mEffectID != ESM::MagicEffect::Corprus) && (magicEffect->mData.mFlags & ESM::MagicEffect::UncappedDamage)) // APPLIED_ONCE { float random = 1.f; if (mSpells[corpSpellId].find(i) != mSpells[corpSpellId].end()) random = mSpells[corpSpellId].at(i); float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random; magnitude *= std::max(1, mCorprusSpells[corpSpellId].mWorsenings); mPermanentSpellEffects[corpSpellId].add(MWMechanics::EffectKey(*effectIt), MWMechanics::EffectParam(magnitude)); } } }
void MechanicsManager::buildPlayer() { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); MWMechanics::NpcStats& npcStats = MWWorld::Class::get (ptr).getNpcStats (ptr); const ESM::NPC *player = ptr.get<ESM::NPC>()->base; // reset creatureStats.mLevel = player->npdt52.level; creatureStats.mSpells.clear(); creatureStats.mMagicEffects = MagicEffects(); for (int i=0; i<27; ++i) npcStats.mSkill[i].setBase (player->npdt52.skills[i]); creatureStats.mAttributes[0].setBase (player->npdt52.strength); creatureStats.mAttributes[1].setBase (player->npdt52.intelligence); creatureStats.mAttributes[2].setBase (player->npdt52.willpower); creatureStats.mAttributes[3].setBase (player->npdt52.agility); creatureStats.mAttributes[4].setBase (player->npdt52.speed); creatureStats.mAttributes[5].setBase (player->npdt52.endurance); creatureStats.mAttributes[6].setBase (player->npdt52.personality); creatureStats.mAttributes[7].setBase (player->npdt52.luck); // race if (mRaceSelected) { const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().races.find ( MWBase::Environment::get().getWorld()->getPlayer().getRace()); bool male = MWBase::Environment::get().getWorld()->getPlayer().isMale(); for (int i=0; i<8; ++i) { const ESM::Race::MaleFemale *attribute = 0; switch (i) { case 0: attribute = &race->data.strength; break; case 1: attribute = &race->data.intelligence; break; case 2: attribute = &race->data.willpower; break; case 3: attribute = &race->data.agility; break; case 4: attribute = &race->data.speed; break; case 5: attribute = &race->data.endurance; break; case 6: attribute = &race->data.personality; break; case 7: attribute = &race->data.luck; break; } creatureStats.mAttributes[i].setBase ( static_cast<int> (male ? attribute->male : attribute->female)); } for (int i=0; i<7; ++i) { int index = race->data.bonus[i].skill; if (index>=0 && index<27) { npcStats.mSkill[index].setBase ( npcStats.mSkill[index].getBase() + race->data.bonus[i].bonus); } } for (std::vector<std::string>::const_iterator iter (race->powers.list.begin()); iter!=race->powers.list.end(); ++iter) { creatureStats.mSpells.add (*iter); } } // birthsign if (!MWBase::Environment::get().getWorld()->getPlayer().getBirthsign().empty()) { const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find ( MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); for (std::vector<std::string>::const_iterator iter (sign->powers.list.begin()); iter!=sign->powers.list.end(); ++iter) { creatureStats.mSpells.add (*iter); } } // class if (mClassSelected) { const ESM::Class& class_ = MWBase::Environment::get().getWorld()->getPlayer().getClass(); for (int i=0; i<2; ++i) { int attribute = class_.data.attribute[i]; if (attribute>=0 && attribute<8) { creatureStats.mAttributes[attribute].setBase ( creatureStats.mAttributes[attribute].getBase() + 10); } } for (int i=0; i<2; ++i) { int bonus = i==0 ? 10 : 25; for (int i2=0; i2<5; ++i2) { int index = class_.data.skills[i2][i]; if (index>=0 && index<27) { npcStats.mSkill[index].setBase ( npcStats.mSkill[index].getBase() + bonus); } } } typedef ESMS::IndexListT<ESM::Skill>::MapType ContainerType; const ContainerType& skills = MWBase::Environment::get().getWorld()->getStore().skills.list; for (ContainerType::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) { if (iter->second.data.specialization==class_.data.specialization) { int index = iter->first; if (index>=0 && index<27) { npcStats.mSkill[index].setBase ( npcStats.mSkill[index].getBase() + 5); } } } } // forced update and current value adjustments mActors.updateActor (ptr, 0); for (int i=0; i<3; ++i) creatureStats.mDynamic[i].setCurrent (creatureStats.mDynamic[i].getModified()); }
void MechanicsManager::buildPlayer() { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr); MWMechanics::NpcStats& npcStats = MWWorld::Class::get (ptr).getNpcStats (ptr); const ESM::NPC *player = ptr.get<ESM::NPC>()->base; // reset creatureStats.setLevel(player->mNpdt52.mLevel); creatureStats.getSpells().clear(); creatureStats.setMagicEffects(MagicEffects()); for (int i=0; i<27; ++i) npcStats.getSkill (i).setBase (player->mNpdt52.mSkills[i]); creatureStats.getAttribute(0).setBase (player->mNpdt52.mStrength); creatureStats.getAttribute(1).setBase (player->mNpdt52.mIntelligence); creatureStats.getAttribute(2).setBase (player->mNpdt52.mWillpower); creatureStats.getAttribute(3).setBase (player->mNpdt52.mAgility); creatureStats.getAttribute(4).setBase (player->mNpdt52.mSpeed); creatureStats.getAttribute(5).setBase (player->mNpdt52.mEndurance); creatureStats.getAttribute(6).setBase (player->mNpdt52.mPersonality); creatureStats.getAttribute(7).setBase (player->mNpdt52.mLuck); // race if (mRaceSelected) { const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().races.find ( MWBase::Environment::get().getWorld()->getPlayer().getRace()); bool male = MWBase::Environment::get().getWorld()->getPlayer().isMale(); for (int i=0; i<8; ++i) { const ESM::Race::MaleFemale *attribute = 0; switch (i) { case 0: attribute = &race->mData.mStrength; break; case 1: attribute = &race->mData.mIntelligence; break; case 2: attribute = &race->mData.mWillpower; break; case 3: attribute = &race->mData.mAgility; break; case 4: attribute = &race->mData.mSpeed; break; case 5: attribute = &race->mData.mEndurance; break; case 6: attribute = &race->mData.mPersonality; break; case 7: attribute = &race->mData.mLuck; break; } creatureStats.getAttribute(i).setBase ( static_cast<int> (male ? attribute->mMale : attribute->mFemale)); } for (int i=0; i<27; ++i) { int bonus = 0; for (int i2=0; i2<7; ++i2) if (race->mData.mBonus[i2].mSkill==i) { bonus = race->mData.mBonus[i2].mBonus; break; } npcStats.getSkill (i).setBase (5 + bonus); } for (std::vector<std::string>::const_iterator iter (race->mPowers.mList.begin()); iter!=race->mPowers.mList.end(); ++iter) { creatureStats.getSpells().add (*iter); } } // birthsign if (!MWBase::Environment::get().getWorld()->getPlayer().getBirthsign().empty()) { const ESM::BirthSign *sign = MWBase::Environment::get().getWorld()->getStore().birthSigns.find ( MWBase::Environment::get().getWorld()->getPlayer().getBirthsign()); for (std::vector<std::string>::const_iterator iter (sign->mPowers.mList.begin()); iter!=sign->mPowers.mList.end(); ++iter) { creatureStats.getSpells().add (*iter); } } // class if (mClassSelected) { const ESM::Class& class_ = MWBase::Environment::get().getWorld()->getPlayer().getClass(); for (int i=0; i<2; ++i) { int attribute = class_.mData.mAttribute[i]; if (attribute>=0 && attribute<8) { creatureStats.getAttribute(attribute).setBase ( creatureStats.getAttribute(attribute).getBase() + 10); } } for (int i=0; i<2; ++i) { int bonus = i==0 ? 10 : 25; for (int i2=0; i2<5; ++i2) { int index = class_.mData.mSkills[i2][i]; if (index>=0 && index<27) { npcStats.getSkill (index).setBase ( npcStats.getSkill (index).getBase() + bonus); } } } typedef ESMS::IndexListT<ESM::Skill>::MapType ContainerType; const ContainerType& skills = MWBase::Environment::get().getWorld()->getStore().skills.list; for (ContainerType::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter) { if (iter->second.mData.mSpecialization==class_.mData.mSpecialization) { int index = iter->first; if (index>=0 && index<27) { npcStats.getSkill (index).setBase ( npcStats.getSkill (index).getBase() + 5); } } } } // forced update and current value adjustments mActors.updateActor (ptr, 0); for (int i=0; i<2; ++i) { DynamicStat<float> stat = creatureStats.getDynamic (i); stat.setCurrent (stat.getModified()); creatureStats.setDynamic (i, stat); } }