1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 22:53:50 +00:00

[General] Use hard synchronization for melee attack animations

Previously, each client chose its own attack animations for DedicatedPlayers and DedicatedActors based on the direction they were walking in, which however led to desyncs for players with "Always Use Best Attack" enabled and for creatures which pick their attack animations randomly.
This commit is contained in:
David Cernat 2019-11-29 10:39:57 +02:00
parent a385fcdd87
commit 140c1c9c12
7 changed files with 77 additions and 18 deletions

View file

@ -609,6 +609,9 @@ namespace MWMechanics
mAttack = true; // attack starts just now
characterController.setAttackingOrSpell(true);
if (!distantCombat)
characterController.setAIAttackType(chooseBestAttack(weapon));
/*
Start of tes3mp addition
@ -620,6 +623,7 @@ namespace MWMechanics
{
MechanicsHelper::resetAttack(localAttack);
localAttack->type = distantCombat ? mwmp::Attack::RANGED : mwmp::Attack::MELEE;
localAttack->attackAnimation = characterController.getAttackType();
localAttack->pressed = true;
localAttack->shouldSend = true;
}
@ -627,9 +631,6 @@ namespace MWMechanics
End of tes3mp addition
*/
if (!distantCombat)
characterController.setAIAttackType(chooseBestAttack(weapon));
mStrength = Misc::Rng::rollClosedProbability();
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();

View file

@ -1569,7 +1569,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
/*
Start of tes3mp addition
If this mPtr belongs to a LocalPlayer or LocalActor, get their Attack and prepare
If this mPtr belongs to a LocalPlayer or LocalActor, get their Cast and prepare
it for sending
*/
mwmp::Cast *localCast = MechanicsHelper::getLocalCast(mPtr);
@ -1694,17 +1694,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
}
else
{
/*
Start of tes3mp change (major)
We need DedicatedPlayers and DedicatedActors to not have their attacks
cancelled here, so additional conditions have been added for them
*/
if(mPtr == getPlayer() || mwmp::PlayerList::isDedicatedPlayer(mPtr) ||
mwmp::Main::get().getCellController()->isDedicatedActor(mPtr))
/*
End of tes3mp change (major)
*/
if(mPtr == getPlayer())
{
if (Settings::Manager::getBool("best attack", "Game"))
{
@ -1723,7 +1713,37 @@ bool CharacterController::updateWeaponState(CharacterState& idle)
{
setAttackTypeBasedOnMovement();
}
/*
Start of tes3mp addition
Record the attack animation chosen so we can send it in the next PlayerAttack packet
*/
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(mPtr);
if (localAttack)
localAttack->attackAnimation = mAttackType;
/*
End of tes3mp addition
*/
}
/*
Start of tes3mp addition
If this is a DedicatedPlayer or DedicatedActor, use the attack animation received
in the latest Attack packet about them
*/
else
{
mwmp::Attack *dedicatedAttack = MechanicsHelper::getDedicatedAttack(mPtr);
if (dedicatedAttack)
mAttackType = dedicatedAttack->attackAnimation;
}
/*
End of tes3mp addition
*/
// else if (mPtr != getPlayer()) use mAttackType set by AiCombat
startKey = mAttackType+" start";
stopKey = mAttackType+" min attack";
@ -2935,6 +2955,19 @@ float CharacterController::getAttackStrength() const
return mAttackStrength;
}
/*
Start of tes3mp addition
Make it possible to get the current attack type from elsewhere in the code
*/
std::string CharacterController::getAttackType() const
{
return mAttackType;
}
/*
End of tes3mp addition
*/
void CharacterController::setActive(int active)
{
mAnimation->setActive(active);

View file

@ -295,6 +295,16 @@ public:
float getAttackStrength() const;
/*
Start of tes3mp addition
Make it possible to get the current attack type from elsewhere in the code
*/
std::string getAttackType() const;
/*
End of tes3mp addition
*/
/// @see Animation::setActive
void setActive(int active);

View file

@ -282,6 +282,11 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
if (attack.success)
LOG_APPEND(TimedLog::LOG_VERBOSE, "- damage: %f", attack.damage);
}
else
{
if (attack.type == attack.MELEE)
LOG_APPEND(TimedLog::LOG_VERBOSE, "- animation: %s", attack.attackAnimation.c_str());
}
MWMechanics::CreatureStats &attackerStats = attacker.getClass().getCreatureStats(attacker);
MWWorld::Ptr victim;

View file

@ -65,13 +65,15 @@ namespace mwmp
Target target;
char type; // 0 - melee, 1 - ranged
enum TYPE
{
MELEE = 0,
RANGED
};
char type;
std::string attackAnimation;
std::string rangedWeaponId;
std::string rangedAmmoId;

View file

@ -31,7 +31,11 @@ void PacketActorAttack::Actor(BaseActor &actor, bool send)
RW(actor.attack.isHit, send);
if (actor.attack.type == mwmp::Attack::RANGED)
if (actor.attack.type == mwmp::Attack::MELEE)
{
RW(actor.attack.attackAnimation, send);
}
else if (actor.attack.type == mwmp::Attack::RANGED)
{
RW(actor.attack.attackStrength, send);
RW(actor.attack.rangedWeaponId, send);

View file

@ -32,7 +32,11 @@ void PacketPlayerAttack::Packet(RakNet::BitStream *bs, bool send)
RW(player->attack.isHit, send);
if (player->attack.type == mwmp::Attack::RANGED)
if (player->attack.type == mwmp::Attack::MELEE)
{
RW(player->attack.attackAnimation, send);
}
else if (player->attack.type == mwmp::Attack::RANGED)
{
RW(player->attack.attackStrength, send);
RW(player->attack.rangedWeaponId, send);