diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 7c2e05c77..41e14cf2d 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -5,6 +5,21 @@ #include #include +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include +#include "../mwmp/Main.hpp" +#include "../mwmp/LocalPlayer.hpp" +#include "../mwmp/DedicatedPlayer.hpp" +#include "../mwmp/CellController.hpp" +#include "../mwmp/MechanicsHelper.hpp" +/* + End of tes3mp addition +*/ + #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/magiceffects.hpp" #include "../mwmechanics/movement.hpp" @@ -225,6 +240,19 @@ namespace MWClass void Creature::hit(const MWWorld::Ptr& ptr, float attackStrength, int type) const { + /* + Start of tes3mp addition + + Ignore hit calculations on this client from DedicatedPlayers and DedicatedActors + */ + if (mwmp::PlayerList::isDedicatedPlayer(ptr) || mwmp::Main::get().getCellController()->isDedicatedActor(ptr)) + { + return; + } + /* + End of tes3mp addition + */ + MWWorld::LiveCellRef *ref = ptr.get(); const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); @@ -267,8 +295,41 @@ namespace MWClass float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat); + /* + Start of tes3mp addition + + If the attacker is a LocalPlayer or LocalActor, get their Attack and + assign data for its target + */ + mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(ptr); + + if (localAttack) + { + localAttack->success = true; + mwmp::Main::get().getMechanicsHelper()->assignAttackTarget(localAttack, victim); + } + /* + End of tes3mp addition + */ + if(Misc::Rng::roll0to99() >= hitchance) { + /* + Start of tes3mp addition + + If this was a failed attack by the LocalPlayer or LocalActor, send a + packet about it + */ + if (localAttack) + { + localAttack->pressed = false; + localAttack->success = false; + localAttack->shouldSend = true; + } + /* + End of tes3mp addition + */ + victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, osg::Vec3f(), false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); return; @@ -403,7 +464,21 @@ namespace MWClass float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat(); float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().iKnockDownOddsMult->getInt() * 0.01f + getGmst().iKnockDownOddsBase->getInt(); - if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99()) + + /* + Start of tes3mp change (major) + + If the attacker is a DedicatedPlayer or DedicatedActor with a successful knockdown, apply the knockdown; + otherwise, use default probability roll + */ + mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(attacker); + + if (dedicatedAttack && dedicatedAttack->knockdown) + stats.setKnockedDown(true); + else if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99()) + /* + End of tes3mp change (major) + */ stats.setKnockedDown(true); else stats.setHitRecovery(true); // Is this supposed to always occur? @@ -432,6 +507,27 @@ namespace MWClass stats.setFatigue(fatigue); } } + + /* + Start of tes3mp addition + + If the attacker was the LocalPlayer or LocalActor, record their target and send a packet with it + */ + mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(attacker); + + if (localAttack) + { + localAttack->pressed = false; + localAttack->damage = damage; + localAttack->knockdown = getCreatureStats(ptr).getKnockedDown(); + + mwmp::Main::get().getMechanicsHelper()->assignAttackTarget(localAttack, ptr); + + localAttack->shouldSend = true; + } + /* + End of tes3mp addition + */ } boost::shared_ptr Creature::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwmp/DedicatedActor.cpp b/apps/openmw/mwmp/DedicatedActor.cpp index d47d8dc10..4acc54ea6 100644 --- a/apps/openmw/mwmp/DedicatedActor.cpp +++ b/apps/openmw/mwmp/DedicatedActor.cpp @@ -34,6 +34,8 @@ DedicatedActor::DedicatedActor() creatureStats->mDynamic[0].mBase = -1; hasChangedCell = true; + + attack.pressed = false; } DedicatedActor::~DedicatedActor() diff --git a/apps/openmw/mwmp/LocalActor.cpp b/apps/openmw/mwmp/LocalActor.cpp index 11242fec7..76fd84ab4 100644 --- a/apps/openmw/mwmp/LocalActor.cpp +++ b/apps/openmw/mwmp/LocalActor.cpp @@ -2,7 +2,6 @@ #include "../mwbase/environment.hpp" -#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/movement.hpp" #include "../mwrender/animation.hpp" diff --git a/apps/openmw/mwmp/LocalActor.hpp b/apps/openmw/mwmp/LocalActor.hpp index 78aab33e8..477176dbd 100644 --- a/apps/openmw/mwmp/LocalActor.hpp +++ b/apps/openmw/mwmp/LocalActor.hpp @@ -2,7 +2,7 @@ #define OPENMW_LOCALACTOR_HPP #include -#include "../mwmechanics/npcstats.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "../mwworld/manualref.hpp" namespace mwmp diff --git a/apps/openmw/mwmp/MechanicsHelper.cpp b/apps/openmw/mwmp/MechanicsHelper.cpp index a42f8d230..b4477c791 100644 --- a/apps/openmw/mwmp/MechanicsHelper.cpp +++ b/apps/openmw/mwmp/MechanicsHelper.cpp @@ -5,8 +5,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" +#include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/combat.hpp" -#include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/spellcasting.hpp" #include "../mwworld/class.hpp" @@ -107,7 +107,7 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker) } } - MWMechanics::CreatureStats &attackerStats = attacker.getClass().getNpcStats(attacker); + MWMechanics::CreatureStats &attackerStats = attacker.getClass().getCreatureStats(attacker); attackerStats.getSpells().setSelectedSpell(attack.spellId); MWWorld::Ptr victim; @@ -143,29 +143,35 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker) // Get the weapon used (if hand-to-hand, weapon = inv.end()) if (attackerStats.getDrawState() == MWMechanics::DrawState_Weapon) { - MWWorld::InventoryStore &inv = attacker.getClass().getInventoryStore(attacker); - MWWorld::ContainerStoreIterator weaponslot = inv.getSlot( - MWWorld::InventoryStore::Slot_CarriedRight); + MWWorld::Ptr weapon; - MWWorld::Ptr weapon = ((weaponslot != inv.end()) ? *weaponslot : MWWorld::Ptr()); - if (!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name()) - weapon = MWWorld::Ptr(); + 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; - if (!weapon.isEmpty()) - healthdmg = true; - else + bool healthdmg = true; + + if (weapon.isEmpty()) { - MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim); - healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown(); + if (attacker.getClass().isBipedal(attacker)) + { + MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim); + healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown(); + } } - - if (!weapon.isEmpty()) + else MWMechanics::blockMeleeAttack(attacker, victim, weapon, attack.damage, 1); - attacker.getClass().onHit(victim, attack.damage, healthdmg, weapon, attacker, osg::Vec3f(), + victim.getClass().onHit(victim, attack.damage, healthdmg, weapon, attacker, osg::Vec3f(), attack.success); } }