1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-06 02:45:31 +00:00

[General] Fix problems with the synchronization of ranged attacks

Projectile hits now send Attack packets with RANGED attacks, and their success or failure is now synchronized.

Strike enchantments no longer require a valid victim to be synchronized.

Additional debug messages have been added for attacks.
This commit is contained in:
David Cernat 2018-09-11 11:56:45 +03:00
parent 31a9b77f34
commit fcd31bf4a6
5 changed files with 101 additions and 74 deletions

View file

@ -217,10 +217,18 @@ namespace MWMechanics
/*
Start of tes3mp addition
Ignore projectiles fired by DedicatedPlayers
Ignore projectiles fired by DedicatedPlayers and DedicatedActors
If fired by LocalPlayers and LocalActors, get the associated LocalAttack and set its type
to RANGED
*/
if (mwmp::PlayerList::isDedicatedPlayer(attacker))
if (mwmp::PlayerList::isDedicatedPlayer(attacker) || mwmp::Main::get().getCellController()->isDedicatedActor(attacker))
return;
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
if (localAttack)
localAttack->type = mwmp::Attack::RANGED;
/*
End of tes3mp addition
*/
@ -245,10 +253,10 @@ namespace MWMechanics
/*
Start of tes3mp addition
Mark this as a successful attack for LocalPlayer unless proven otherwise
Mark this as a successful attack for the associated LocalAttack unless proven otherwise
*/
if (attacker == MWBase::Environment::get().getWorld()->getPlayerPtr())
mwmp::Main::get().getLocalPlayer()->attack.success = true;
if (localAttack)
localAttack->success = true;
/*
End of tes3mp addition
*/
@ -258,11 +266,10 @@ namespace MWMechanics
/*
Start of tes3mp addition
Mark this as a failed attack for LocalPlayer now that the hit roll
has failed
Mark this as a failed LocalAttack now that the hit roll has failed
*/
if (attacker == getPlayer())
mwmp::Main::get().getLocalPlayer()->attack.success = false;
if (localAttack)
localAttack->success = false;
/*
End of tes3mp addition
*/
@ -312,8 +319,6 @@ namespace MWMechanics
Track whether the strike enchantment is successful for attacks by the
LocalPlayer or LocalActors for both their weapon and projectile
*/
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
bool appliedEnchantment = applyOnStrikeEnchantment(attacker, victim, weapon, hitPosition, true);
if (localAttack)
@ -342,6 +347,19 @@ namespace MWMechanics
victim.getClass().onHit(victim, damage, true, projectile, attacker, hitPosition, true);
}
/*
Start of tes3mp addition
If this is a local attack that had no victim, send a packet for it here
*/
else if (localAttack)
{
localAttack->hitPosition = MechanicsHelper::getPositionFromVector(hitPosition);
localAttack->shouldSend = true;
}
/*
End of tes3mp addition
*/
}
float getHitChance(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, int skillValue)

View file

@ -204,14 +204,16 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
{
if (!attack.pressed)
{
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Processing attack from %s",
attacker.getCellRef().getRefId().c_str());
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Processing attack from %s of type %i",
attacker.getCellRef().getRefId().c_str(), attack.type);
LOG_APPEND(Log::LOG_VERBOSE, "- success: %s", attack.success ? "true" : "false");
if (attack.success)
LOG_APPEND(Log::LOG_VERBOSE, "- damage: %f", attack.damage);
}
LOG_APPEND(Log::LOG_VERBOSE, "- pressed: %s", attack.pressed ? "true" : "false");
MWMechanics::CreatureStats &attackerStats = attacker.getClass().getCreatureStats(attacker);
MWWorld::Ptr victim;
@ -231,12 +233,14 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
victim = controller->getDedicatedActor(attack.target.refNum, attack.target.mpNum)->getPtr();
}
// Get the weapon used (if hand-to-hand, weapon = inv.end())
if (attack.type == attack.MELEE)
if (attack.type == attack.MELEE || attack.type == attack.RANGED)
{
bool isRanged = attack.type == attack.RANGED;
MWWorld::Ptr weapon;
MWWorld::Ptr projectile;
// Get the weapon used; if using hand-to-hand, the weapon is equal to inv.end()
if (attacker.getClass().hasInventoryStore(attacker))
{
MWWorld::InventoryStore &inventoryStore = attacker.getClass().getInventoryStore(attacker);
@ -253,40 +257,44 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
weapon = MWWorld::Ptr();
}
bool isHealthDamage = true;
if (weapon.isEmpty())
{
if (attacker.getClass().isBipedal(attacker))
{
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
isHealthDamage = otherstats.isParalyzed() || otherstats.getKnockedDown();
}
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "- weapon: %s\n- isRanged: %s\n- applyWeaponEnchantment: %s\n- applyProjectileEnchantment: %s",
weapon.getCellRef().getRefId().c_str(), isRanged ? "true" : "false", attack.applyWeaponEnchantment ? "true" : "false",
attack.applyProjectileEnchantment ? "true" : "false");
if (attack.applyWeaponEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, isRanged);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(weapon, false);
}
if (isRanged && !projectile.isEmpty() && attack.applyProjectileEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, isRanged);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(projectile, false);
}
}
if (victim.mRef != nullptr)
{
bool healthdmg = true;
if (weapon.isEmpty())
{
if (attacker.getClass().isBipedal(attacker))
{
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown();
}
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "- weapon: %s", weapon.getCellRef().getRefId().c_str());
if (!isRanged)
MWMechanics::blockMeleeAttack(attacker, victim, weapon, attack.damage, 1);
if (attack.applyWeaponEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, false);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(weapon, false);
}
if (attack.applyProjectileEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, false);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(projectile, false);
}
}
victim.getClass().onHit(victim, attack.damage, healthdmg, weapon, attacker, attack.hitPosition.asVec3(),
victim.getClass().onHit(victim, attack.damage, isHealthDamage, weapon, attacker, attack.hitPosition.asVec3(),
attack.success);
}
}
@ -300,7 +308,7 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
attack.instant = false;
}
LOG_APPEND(Log::LOG_VERBOSE, "- spellId: %s, success: %s", attack.spellId.c_str(), attack.success ? "true" : "false");
LOG_APPEND(Log::LOG_VERBOSE, "- spellId: %s", attack.spellId.c_str());
}
else if (attack.type == attack.ITEM_MAGIC)
{

View file

@ -69,6 +69,7 @@ namespace mwmp
enum TYPE
{
MELEE = 0,
RANGED,
MAGIC,
ITEM_MAGIC,
THROWABLE

View file

@ -26,19 +26,19 @@ void PacketActorAttack::Actor(BaseActor &actor, bool send)
RW(actor.attack.type, send);
if (actor.attack.type == mwmp::Attack::MELEE || actor.attack.type == mwmp::Attack::MAGIC)
if (actor.attack.type == mwmp::Attack::ITEM_MAGIC)
RW(actor.attack.itemId, send, true);
else
{
RW(actor.attack.pressed, send);
RW(actor.attack.success, send);
if (actor.attack.success)
if (actor.attack.type == mwmp::Attack::MAGIC)
{
RW(actor.attack.hitPosition.pos[0], send);
RW(actor.attack.hitPosition.pos[1], send);
RW(actor.attack.hitPosition.pos[2], send);
RW(actor.attack.instant, send);
RW(actor.attack.spellId, send, true);
}
if (actor.attack.type == mwmp::Attack::MELEE)
else
{
RW(actor.attack.damage, send);
RW(actor.attack.block, send);
@ -46,13 +46,13 @@ void PacketActorAttack::Actor(BaseActor &actor, bool send)
RW(actor.attack.applyWeaponEnchantment, send);
RW(actor.attack.applyProjectileEnchantment, send);
}
else if (actor.attack.type == mwmp::Attack::MAGIC)
{
RW(actor.attack.instant, send);
RW(actor.attack.spellId, send, true);
if (actor.attack.success || actor.attack.applyWeaponEnchantment || actor.attack.applyProjectileEnchantment)
{
RW(actor.attack.hitPosition.pos[0], send);
RW(actor.attack.hitPosition.pos[1], send);
RW(actor.attack.hitPosition.pos[2], send);
}
}
}
else if (actor.attack.type == mwmp::Attack::ITEM_MAGIC)
RW(actor.attack.itemId, send, true);
}

View file

@ -27,19 +27,19 @@ void PacketPlayerAttack::Packet(RakNet::BitStream *bs, bool send)
RW(player->attack.type, send);
if (player->attack.type == mwmp::Attack::MELEE || player->attack.type == mwmp::Attack::MAGIC)
if (player->attack.type == mwmp::Attack::ITEM_MAGIC)
RW(player->attack.itemId, send, true);
else
{
RW(player->attack.pressed, send);
RW(player->attack.success, send);
if (player->attack.success)
if (player->attack.type == mwmp::Attack::MAGIC)
{
RW(player->attack.hitPosition.pos[0], send);
RW(player->attack.hitPosition.pos[1], send);
RW(player->attack.hitPosition.pos[2], send);
RW(player->attack.instant, send);
RW(player->attack.spellId, send, true);
}
if (player->attack.type == mwmp::Attack::MELEE)
else
{
RW(player->attack.damage, send);
RW(player->attack.block, send);
@ -47,13 +47,13 @@ void PacketPlayerAttack::Packet(RakNet::BitStream *bs, bool send)
RW(player->attack.applyWeaponEnchantment, send);
RW(player->attack.applyProjectileEnchantment, send);
}
else if (player->attack.type == mwmp::Attack::MAGIC)
{
RW(player->attack.instant, send);
RW(player->attack.spellId, send, true);
if (player->attack.success || player->attack.applyWeaponEnchantment || player->attack.applyProjectileEnchantment)
{
RW(player->attack.hitPosition.pos[0], send);
RW(player->attack.hitPosition.pos[1], send);
RW(player->attack.hitPosition.pos[2], send);
}
}
}
else if (player->attack.type == mwmp::Attack::ITEM_MAGIC)
RW(player->attack.itemId, send, true);
}