[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.
fix/skillcap
David Cernat 6 years ago
parent 31a9b77f34
commit fcd31bf4a6

@ -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)

@ -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();
}
if (victim.mRef != nullptr)
{
bool healthdmg = true;
bool isHealthDamage = true;
if (weapon.isEmpty())
if (weapon.isEmpty())
{
if (attacker.getClass().isBipedal(attacker))
{
if (attacker.getClass().isBipedal(attacker))
{
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown();
}
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
isHealthDamage = otherstats.isParalyzed() || otherstats.getKnockedDown();
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "- weapon: %s", weapon.getCellRef().getRefId().c_str());
}
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");
MWMechanics::blockMeleeAttack(attacker, victim, weapon, attack.damage, 1);
if (attack.applyWeaponEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, isRanged);
cast.mHitPosition = attack.hitPosition.asVec3();
if (attack.applyWeaponEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, false);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(weapon, false);
}
cast.cast(weapon, false);
}
if (attack.applyProjectileEnchantment)
{
MWMechanics::CastSpell cast(attacker, victim, false);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(projectile, 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)
{
if (!isRanged)
MWMechanics::blockMeleeAttack(attacker, victim, weapon, attack.damage, 1);
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)
{

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

@ -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);
}

@ -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);
}

Loading…
Cancel
Save