#include #include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/combat.hpp" #include "../mwmechanics/spellcasting.hpp" #include "../mwworld/class.hpp" #include "../mwworld/inventorystore.hpp" #include "MechanicsHelper.hpp" #include "Main.hpp" #include "LocalPlayer.hpp" #include "DedicatedPlayer.hpp" #include "CellController.hpp" using namespace mwmp; mwmp::MechanicsHelper::MechanicsHelper() { } mwmp::MechanicsHelper::~MechanicsHelper() { } osg::Vec3f MechanicsHelper::getLinearInterpolation(osg::Vec3f start, osg::Vec3f end, float percent) { osg::Vec3f position(percent, percent, percent); return (start + osg::componentMultiply(position, (end - start))); } Attack *MechanicsHelper::getLocalAttack(const MWWorld::Ptr& ptr) { if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) return &mwmp::Main::get().getLocalPlayer()->attack; else if (mwmp::Main::get().getCellController()->isLocalActor(ptr)) return &mwmp::Main::get().getCellController()->getLocalActor(ptr)->attack; return NULL; } Attack *MechanicsHelper::getDedicatedAttack(const MWWorld::Ptr& ptr) { if (mwmp::PlayerList::isDedicatedPlayer(ptr)) return &mwmp::PlayerList::getPlayer(ptr)->attack; else if (mwmp::Main::get().getCellController()->isDedicatedActor(ptr)) return &mwmp::Main::get().getCellController()->getDedicatedActor(ptr)->attack; return NULL; } void MechanicsHelper::assignAttackTarget(Attack* attack, const MWWorld::Ptr& target) { if (target == MWBase::Environment::get().getWorld()->getPlayerPtr()) { attack->target.guid = mwmp::Main::get().getLocalPlayer()->guid; attack->target.refId.clear(); } else if (mwmp::PlayerList::isDedicatedPlayer(target)) { attack->target.guid = mwmp::PlayerList::getPlayer(target)->guid; attack->target.refId.clear(); } else { MWWorld::CellRef *targetRef = &target.getCellRef(); attack->target.refId = targetRef->getRefId(); attack->target.refNumIndex = targetRef->getRefNum().mIndex; attack->target.mpNum = targetRef->getMpNum(); } } void MechanicsHelper::resetAttack(Attack* attack) { attack->success = false; attack->knockdown = false; attack->block = false; attack->target.guid = RakNet::RakNetGUID(); attack->target.refId.clear(); } bool MechanicsHelper::getSpellSuccess(std::string spellId, const MWWorld::Ptr& caster) { return Misc::Rng::roll0to99() < MWMechanics::getSpellSuccessChance(spellId, caster); } void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker) { if (attack.pressed == false) { LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Processing attack from %s", attacker.getCellRef().getRefId().c_str()); LOG_APPEND(Log::LOG_VERBOSE, "- success: %s", attack.success ? "true" : "false"); if (attack.success == true) { LOG_APPEND(Log::LOG_VERBOSE, "- damage: %f", attack.damage); } } MWMechanics::CreatureStats &attackerStats = attacker.getClass().getCreatureStats(attacker); attackerStats.getSpells().setSelectedSpell(attack.spellId); MWWorld::Ptr victim; if (attack.target.refId.empty()) { if (attack.target.guid == mwmp::Main::get().getLocalPlayer()->guid) { victim = MWBase::Environment::get().getWorld()->getPlayerPtr(); } else if (PlayerList::getPlayer(attack.target.guid) != NULL) { victim = PlayerList::getPlayer(attack.target.guid)->getPtr(); } } else { if (mwmp::Main::get().getCellController()->isLocalActor(attack.target.refId, attack.target.refNumIndex, attack.target.mpNum)) { victim = mwmp::Main::get().getCellController()->getLocalActor(attack.target.refId, attack.target.refNumIndex, attack.target.mpNum)->getPtr(); } else if (mwmp::Main::get().getCellController()->isDedicatedActor(attack.target.refId, attack.target.refNumIndex, attack.target.mpNum)) { victim = mwmp::Main::get().getCellController()->getDedicatedActor(attack.target.refId, attack.target.refNumIndex, attack.target.mpNum)->getPtr(); } } // Get the weapon used (if hand-to-hand, weapon = inv.end()) if (attackerStats.getDrawState() == MWMechanics::DrawState_Weapon) { MWWorld::Ptr weapon; if (attacker.getClass().hasInventoryStore(attacker)) { MWWorld::InventoryStore &inv = attacker.getClass().getInventoryStore(attacker); MWWorld::ContainerStoreIterator weaponslot = inv.getSlot( MWWorld::InventoryStore::Slot_CarriedRight); weapon = ((weaponslot != inv.end()) ? *weaponslot : MWWorld::Ptr()); if (!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name()) weapon = MWWorld::Ptr(); } if (victim.mRef != NULL) { bool healthdmg = true; if (weapon.isEmpty()) { if (attacker.getClass().isBipedal(attacker)) { MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim); healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown(); } } else MWMechanics::blockMeleeAttack(attacker, victim, weapon, attack.damage, 1); victim.getClass().onHit(victim, attack.damage, healthdmg, weapon, attacker, osg::Vec3f(), attack.success); } } else { LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "SpellId: %s", attack.spellId.c_str()); LOG_APPEND(Log::LOG_VERBOSE, " - success: %d", attack.success); } }