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:
parent
a385fcdd87
commit
140c1c9c12
7 changed files with 77 additions and 18 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue