mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 21:19:40 +00:00
[Client] Make tes3mp combat code work with Creatures, not just NPCs
This commit is contained in:
parent
a82646a130
commit
ea7c3f2dc7
5 changed files with 124 additions and 21 deletions
|
@ -5,6 +5,21 @@
|
||||||
#include <components/esm/loadcrea.hpp>
|
#include <components/esm/loadcrea.hpp>
|
||||||
#include <components/esm/creaturestate.hpp>
|
#include <components/esm/creaturestate.hpp>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Include additional headers for multiplayer purposes
|
||||||
|
*/
|
||||||
|
#include <components/openmw-mp/Log.hpp>
|
||||||
|
#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/creaturestats.hpp"
|
||||||
#include "../mwmechanics/magiceffects.hpp"
|
#include "../mwmechanics/magiceffects.hpp"
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
@ -225,6 +240,19 @@ namespace MWClass
|
||||||
|
|
||||||
void Creature::hit(const MWWorld::Ptr& ptr, float attackStrength, int type) const
|
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<ESM::Creature> *ref =
|
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||||
ptr.get<ESM::Creature>();
|
ptr.get<ESM::Creature>();
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||||
|
@ -267,8 +295,41 @@ namespace MWClass
|
||||||
|
|
||||||
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);
|
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)
|
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);
|
victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, osg::Vec3f(), false);
|
||||||
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
|
MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr);
|
||||||
return;
|
return;
|
||||||
|
@ -403,7 +464,21 @@ namespace MWClass
|
||||||
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat();
|
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat();
|
||||||
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
|
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
* getGmst().iKnockDownOddsMult->getInt() * 0.01f + getGmst().iKnockDownOddsBase->getInt();
|
* 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);
|
stats.setKnockedDown(true);
|
||||||
else
|
else
|
||||||
stats.setHitRecovery(true); // Is this supposed to always occur?
|
stats.setHitRecovery(true); // Is this supposed to always occur?
|
||||||
|
@ -432,6 +507,27 @@ namespace MWClass
|
||||||
stats.setFatigue(fatigue);
|
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<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr,
|
boost::shared_ptr<MWWorld::Action> Creature::activate (const MWWorld::Ptr& ptr,
|
||||||
|
|
|
@ -34,6 +34,8 @@ DedicatedActor::DedicatedActor()
|
||||||
creatureStats->mDynamic[0].mBase = -1;
|
creatureStats->mDynamic[0].mBase = -1;
|
||||||
|
|
||||||
hasChangedCell = true;
|
hasChangedCell = true;
|
||||||
|
|
||||||
|
attack.pressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DedicatedActor::~DedicatedActor()
|
DedicatedActor::~DedicatedActor()
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
|
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define OPENMW_LOCALACTOR_HPP
|
#define OPENMW_LOCALACTOR_HPP
|
||||||
|
|
||||||
#include <components/openmw-mp/Base/BaseActor.hpp>
|
#include <components/openmw-mp/Base/BaseActor.hpp>
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwworld/manualref.hpp"
|
#include "../mwworld/manualref.hpp"
|
||||||
|
|
||||||
namespace mwmp
|
namespace mwmp
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/combat.hpp"
|
#include "../mwmechanics/combat.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.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);
|
attackerStats.getSpells().setSelectedSpell(attack.spellId);
|
||||||
|
|
||||||
MWWorld::Ptr victim;
|
MWWorld::Ptr victim;
|
||||||
|
@ -142,30 +142,36 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
|
||||||
|
|
||||||
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
||||||
if (attackerStats.getDrawState() == MWMechanics::DrawState_Weapon)
|
if (attackerStats.getDrawState() == MWMechanics::DrawState_Weapon)
|
||||||
|
{
|
||||||
|
MWWorld::Ptr weapon;
|
||||||
|
|
||||||
|
if (attacker.getClass().hasInventoryStore(attacker))
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore &inv = attacker.getClass().getInventoryStore(attacker);
|
MWWorld::InventoryStore &inv = attacker.getClass().getInventoryStore(attacker);
|
||||||
MWWorld::ContainerStoreIterator weaponslot = inv.getSlot(
|
MWWorld::ContainerStoreIterator weaponslot = inv.getSlot(
|
||||||
MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
|
||||||
MWWorld::Ptr weapon = ((weaponslot != inv.end()) ? *weaponslot : MWWorld::Ptr());
|
weapon = ((weaponslot != inv.end()) ? *weaponslot : MWWorld::Ptr());
|
||||||
if (!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
|
if (!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
|
||||||
weapon = MWWorld::Ptr();
|
weapon = MWWorld::Ptr();
|
||||||
|
}
|
||||||
|
|
||||||
if (victim.mRef != NULL)
|
if (victim.mRef != NULL)
|
||||||
{
|
{
|
||||||
bool healthdmg;
|
bool healthdmg = true;
|
||||||
if (!weapon.isEmpty())
|
|
||||||
healthdmg = true;
|
if (weapon.isEmpty())
|
||||||
else
|
{
|
||||||
|
if (attacker.getClass().isBipedal(attacker))
|
||||||
{
|
{
|
||||||
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
|
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
|
||||||
healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown();
|
healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!weapon.isEmpty())
|
else
|
||||||
MWMechanics::blockMeleeAttack(attacker, victim, weapon, attack.damage, 1);
|
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);
|
attack.success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue