void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<int>& value) { static const char *ids[] = { "HBar", "MBar", "FBar", 0 }; for (int i=0; ids[i]; ++i) if (ids[i]==id) { switch (i) { case 0: health->setProgressRange (value.getModified()); health->setProgressPosition (value.getCurrent()); break; case 1: magicka->setProgressRange (value.getModified()); magicka->setProgressPosition (value.getCurrent()); break; case 2: stamina->setProgressRange (value.getModified()); stamina->setProgressPosition (value.getCurrent()); break; } } }
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value) { static const char *ids[] = { "HBar", "MBar", "FBar", 0 }; for (int i=0; ids[i]; ++i) if (ids[i]==id) { MyGUI::Widget* w; std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); switch (i) { case 0: mHealth->setProgressRange (value.getModified()); mHealth->setProgressPosition (value.getCurrent()); getWidget(w, "HealthFrame"); w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); break; case 1: mMagicka->setProgressRange (value.getModified()); mMagicka->setProgressPosition (value.getCurrent()); getWidget(w, "MagickaFrame"); w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); break; case 2: mStamina->setProgressRange (value.getModified()); mStamina->setProgressPosition (value.getCurrent()); getWidget(w, "FatigueFrame"); w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); break; } } }
void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat<float>& value) { int current = std::max(0, static_cast<int>(value.getCurrent())); int modified = static_cast<int>(value.getModified()); MyGUI::Widget* w; std::string valStr = MyGUI::utility::toString(current) + "/" + MyGUI::utility::toString(modified); if (id == "HBar") { mHealth->setProgressRange(modified); mHealth->setProgressPosition(current); getWidget(w, "HealthFrame"); w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); } else if (id == "MBar") { mMagicka->setProgressRange (modified); mMagicka->setProgressPosition (current); getWidget(w, "MagickaFrame"); w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); } else if (id == "FBar") { mStamina->setProgressRange (modified); mStamina->setProgressPosition (current); getWidget(w, "FatigueFrame"); w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } }
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) { static const char *ids[] = { "HBar", "MBar", "FBar", 0 }; for (int i=0; ids[i]; ++i) if (ids[i]==id) { std::string id (ids[i]); setBar (id, id + "T", value.getCurrent(), value.getModified()); } }
void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value) { static const char *ids[] = { "HBar", "MBar", "FBar", 0 }; for (int i=0; ids[i]; ++i) { if (ids[i]==id) { std::string id (ids[i]); setBar (id, id + "T", value.getCurrent(), value.getModified()); // health, magicka, fatigue tooltip MyGUI::Widget* w; std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); if (i==0) { getWidget(w, "Health"); w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); } else if (i==1) { getWidget(w, "Magicka"); w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); } else if (i==2) { getWidget(w, "Fatigue"); w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } } } }
void applyFatigueLoss(const MWWorld::Ptr &attacker, const MWWorld::Ptr &weapon, float attackStrength) { // somewhat of a guess, but using the weapon weight makes sense const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat(); const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat(); const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat(); CreatureStats& stats = attacker.getClass().getCreatureStats(attacker); MWMechanics::DynamicStat<float> fatigue = stats.getFatigue(); const float normalizedEncumbrance = attacker.getClass().getNormalizedEncumbrance(attacker); float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult; if (!weapon.isEmpty()) fatigueLoss += weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueMult; fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); stats.setFatigue(fatigue); }
void applyElementalShields(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim) { for (int i=0; i<3; ++i) { float magnitude = victim.getClass().getCreatureStats(victim).getMagicEffects().get(ESM::MagicEffect::FireShield+i).getMagnitude(); if (!magnitude) continue; CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); float saveTerm = attacker.getClass().getSkill(attacker, ESM::Skill::Destruction) + 0.2f * attackerStats.getAttribute(ESM::Attribute::Willpower).getModified() + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); int fatigueMax = attackerStats.getFatigue().getModified(); int fatigueCurrent = attackerStats.getFatigue().getCurrent(); float normalisedFatigue = fatigueMax==0 ? 1 : std::max (0.0f, static_cast<float> (fatigueCurrent)/fatigueMax); saveTerm *= 1.25f * normalisedFatigue; float roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] float x = std::max(0.f, saveTerm - roll); int element = ESM::MagicEffect::FireDamage; if (i == 1) element = ESM::MagicEffect::ShockDamage; if (i == 2) element = ESM::MagicEffect::FrostDamage; float elementResistance = MWMechanics::getEffectResistanceAttribute(element, &attackerStats.getMagicEffects()); x = std::min(100.f, x + elementResistance); static const float fElementalShieldMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fElementalShieldMult")->getFloat(); x = fElementalShieldMult * magnitude * (1.f - 0.01f * x); // Note swapped victim and attacker, since the attacker takes the damage here. x = scaleDamage(x, victim, attacker); MWMechanics::DynamicStat<float> health = attackerStats.getHealth(); health.setCurrent(health.getCurrent() - x); attackerStats.setHealth(health); } }
bool blockMeleeAttack(const MWWorld::Ptr &attacker, const MWWorld::Ptr &blocker, const MWWorld::Ptr &weapon, float damage, float attackStrength) { if (!blocker.getClass().hasInventoryStore(blocker)) return false; MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker); if (blockerStats.getKnockedDown() // Used for both knockout or knockdown || blockerStats.getHitRecovery() || blockerStats.isParalyzed()) return false; if (!MWBase::Environment::get().getMechanicsManager()->isReadyToBlock(blocker)) return false; MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker); MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name()) return false; if (!blocker.getRefData().getBaseNode()) return false; // shouldn't happen float angleDegrees = osg::RadiansToDegrees( signedAngleRadians ( (attacker.getRefData().getPosition().asVec3() - blocker.getRefData().getPosition().asVec3()), blocker.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0), osg::Vec3f(0,0,1))); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); if (angleDegrees < gmst.find("fCombatBlockLeftAngle")->getFloat()) return false; if (angleDegrees > gmst.find("fCombatBlockRightAngle")->getFloat()) return false; MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2f * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1f * blockerStats.getAttribute(ESM::Attribute::Luck).getModified(); float enemySwing = attackStrength; float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat(); float blockerTerm = blockTerm * swingTerm; if (blocker.getClass().getMovementSettings(blocker).mPosition[1] <= 0) blockerTerm *= gmst.find("fBlockStillBonus")->getFloat(); blockerTerm *= blockerStats.getFatigueTerm(); int attackerSkill = 0; if (weapon.isEmpty()) attackerSkill = attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand); else attackerSkill = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); float attackerTerm = attackerSkill + 0.2f * attackerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); attackerTerm *= attackerStats.getFatigueTerm(); int x = int(blockerTerm - attackerTerm); // int iBlockMaxChance = gmst.find("iBlockMaxChance")->getInt(); // int iBlockMinChance = gmst.find("iBlockMinChance")->getInt(); // x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x)); // // if (Misc::Rng::roll0to99() < x) // { // // Reduce shield durability by incoming damage // int shieldhealth = shield->getClass().getItemHealth(*shield); // // shieldhealth -= std::min(shieldhealth, int(damage)); // shield->getCellRef().setCharge(shieldhealth); // if (shieldhealth == 0) // inv.unequipItem(*shield, blocker); // // // Reduce blocker fatigue // const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat(); // const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); // const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); // MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue(); // float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker); // normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); // float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; // if (!weapon.isEmpty()) // fatigueLoss += weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueBlockMult; // fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); // blockerStats.setFatigue(fatigue); // // blockerStats.setBlock(true); // // if (blocker == getPlayer()) // blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); // // return true; // } // manual blocking if (blocker.getClass().getCreatureStats(blocker).getBlockManually()) { // Reduce shield durability by incoming damage int shieldhealth = shield->getClass().getItemHealth(*shield); shieldhealth -= std::min(shieldhealth, int(10 * damage /blockerStats.getAttribute(ESM::Skill::Block).getBase())); shield->getCellRef().setCharge(shieldhealth); if (shieldhealth == 0) inv.unequipItem(*shield, blocker); // Reduce blocker fatigue const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat(); const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue(); float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker); normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; if (!weapon.isEmpty()) fatigueLoss += (weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueBlockMult) - x; fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); blockerStats.setFatigue(fatigue); blockerStats.setBlock(true); if (blocker == getPlayer()) blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); blocker.getClass().getCreatureStats(blocker).setBlockManually(false); return true; } return false; }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value) { mFatigue->setValue(value.getCurrent(), value.getModified()); std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified()); mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); }
bool blockMeleeAttack(const MWWorld::Ptr &attacker, const MWWorld::Ptr &blocker, const MWWorld::Ptr &weapon, float damage) { if (!blocker.getClass().hasInventoryStore(blocker)) return false; if (blocker.getClass().getCreatureStats(blocker).getKnockedDown() || blocker.getClass().getCreatureStats(blocker).getHitRecovery()) return false; MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker); MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name()) return false; Ogre::Degree angle = signedAngle (Ogre::Vector3(attacker.getRefData().getPosition().pos) - Ogre::Vector3(blocker.getRefData().getPosition().pos), blocker.getRefData().getBaseNode()->getOrientation().yAxis(), Ogre::Vector3(0,0,1)); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); if (angle.valueDegrees() < gmst.find("fCombatBlockLeftAngle")->getFloat()) return false; if (angle.valueDegrees() > gmst.find("fCombatBlockRightAngle")->getFloat()) return false; MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker); if (blockerStats.getDrawState() == DrawState_Spell) return false; MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2 * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1 * blockerStats.getAttribute(ESM::Attribute::Luck).getModified(); float enemySwing = attackerStats.getAttackStrength(); float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat(); float blockerTerm = blockTerm * swingTerm; if (blocker.getClass().getMovementSettings(blocker).mPosition[1] <= 0) blockerTerm *= gmst.find("fBlockStillBonus")->getFloat(); blockerTerm *= blockerStats.getFatigueTerm(); float attackerSkill = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); float attackerTerm = attackerSkill + 0.2 * attackerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1 * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); attackerTerm *= attackerStats.getFatigueTerm(); int x = int(blockerTerm - attackerTerm); int iBlockMaxChance = gmst.find("iBlockMaxChance")->getInt(); int iBlockMinChance = gmst.find("iBlockMinChance")->getInt(); x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x)); int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] if (roll < x) { // Reduce shield durability by incoming damage if (shield->getCellRef().mCharge == -1) shield->getCellRef().mCharge = shield->getClass().getItemMaxHealth(*shield); shield->getCellRef().mCharge -= std::min(shield->getCellRef().mCharge, int(damage)); if (!shield->getCellRef().mCharge) inv.unequipItem(*shield, blocker); // Reduce blocker fatigue const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat(); const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue(); float normalizedEncumbrance = blocker.getClass().getEncumbrance(blocker) / blocker.getClass().getCapacity(blocker); normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; fatigueLoss += weapon.getClass().getWeight(weapon) * attackerStats.getAttackStrength() * fWeaponFatigueBlockMult; fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); blockerStats.setFatigue(fatigue); blockerStats.setBlock(true); if (blocker.getClass().isNpc()) blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); return true; } return false; }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<float>& value) { mFatigue->setValue(static_cast<int>(value.getCurrent()), static_cast<int>(value.getModified())); std::string valStr = MyGUI::utility::toString(value.getCurrent()) + "/" + MyGUI::utility::toString(value.getModified()); mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); }
void ReviewDialog::setFatigue(const MWMechanics::DynamicStat<int>& value) { fatigue->setValue(value.getCurrent(), value.getModified()); }
void ReviewDialog::setMagicka(const MWMechanics::DynamicStat<int>& value) { magicka->setValue(value.getCurrent(), value.getModified()); }
void ReviewDialog::setHealth(const MWMechanics::DynamicStat<int>& value) { health->setValue(value.getCurrent(), value.getModified()); }