[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 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; return;
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
if (localAttack)
localAttack->type = mwmp::Attack::RANGED;
/* /*
End of tes3mp addition End of tes3mp addition
*/ */
@ -245,10 +253,10 @@ namespace MWMechanics
/* /*
Start of tes3mp addition 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()) if (localAttack)
mwmp::Main::get().getLocalPlayer()->attack.success = true; localAttack->success = true;
/* /*
End of tes3mp addition End of tes3mp addition
*/ */
@ -258,11 +266,10 @@ namespace MWMechanics
/* /*
Start of tes3mp addition Start of tes3mp addition
Mark this as a failed attack for LocalPlayer now that the hit roll Mark this as a failed LocalAttack now that the hit roll has failed
has failed
*/ */
if (attacker == getPlayer()) if (localAttack)
mwmp::Main::get().getLocalPlayer()->attack.success = false; localAttack->success = false;
/* /*
End of tes3mp addition End of tes3mp addition
*/ */
@ -312,8 +319,6 @@ namespace MWMechanics
Track whether the strike enchantment is successful for attacks by the Track whether the strike enchantment is successful for attacks by the
LocalPlayer or LocalActors for both their weapon and projectile LocalPlayer or LocalActors for both their weapon and projectile
*/ */
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
bool appliedEnchantment = applyOnStrikeEnchantment(attacker, victim, weapon, hitPosition, true); bool appliedEnchantment = applyOnStrikeEnchantment(attacker, victim, weapon, hitPosition, true);
if (localAttack) if (localAttack)
@ -342,6 +347,19 @@ namespace MWMechanics
victim.getClass().onHit(victim, damage, true, projectile, attacker, hitPosition, true); 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) 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) if (!attack.pressed)
{ {
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Processing attack from %s", LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Processing attack from %s of type %i",
attacker.getCellRef().getRefId().c_str()); attacker.getCellRef().getRefId().c_str(), attack.type);
LOG_APPEND(Log::LOG_VERBOSE, "- success: %s", attack.success ? "true" : "false"); LOG_APPEND(Log::LOG_VERBOSE, "- success: %s", attack.success ? "true" : "false");
if (attack.success) if (attack.success)
LOG_APPEND(Log::LOG_VERBOSE, "- damage: %f", attack.damage); 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); MWMechanics::CreatureStats &attackerStats = attacker.getClass().getCreatureStats(attacker);
MWWorld::Ptr victim; 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(); 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 || attack.type == attack.RANGED)
if (attack.type == attack.MELEE)
{ {
bool isRanged = attack.type == attack.RANGED;
MWWorld::Ptr weapon; MWWorld::Ptr weapon;
MWWorld::Ptr projectile; MWWorld::Ptr projectile;
// Get the weapon used; if using hand-to-hand, the weapon is equal to inv.end()
if (attacker.getClass().hasInventoryStore(attacker)) if (attacker.getClass().hasInventoryStore(attacker))
{ {
MWWorld::InventoryStore &inventoryStore = attacker.getClass().getInventoryStore(attacker); MWWorld::InventoryStore &inventoryStore = attacker.getClass().getInventoryStore(attacker);
@ -253,40 +257,44 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
weapon = MWWorld::Ptr(); weapon = MWWorld::Ptr();
} }
if (victim.mRef != nullptr) bool isHealthDamage = true;
{
bool healthdmg = true;
if (weapon.isEmpty()) if (weapon.isEmpty())
{
if (attacker.getClass().isBipedal(attacker))
{ {
if (attacker.getClass().isBipedal(attacker)) MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
{ isHealthDamage = otherstats.isParalyzed() || otherstats.getKnockedDown();
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
healthdmg = otherstats.isParalyzed() || otherstats.getKnockedDown();
}
} }
else }
{ else
LOG_APPEND(Log::LOG_VERBOSE, "- weapon: %s", weapon.getCellRef().getRefId().c_str()); {
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) cast.cast(weapon, false);
{ }
MWMechanics::CastSpell cast(attacker, victim, false);
cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(weapon, false);
}
if (attack.applyProjectileEnchantment) if (isRanged && !projectile.isEmpty() && attack.applyProjectileEnchantment)
{ {
MWMechanics::CastSpell cast(attacker, victim, false); MWMechanics::CastSpell cast(attacker, victim, isRanged);
cast.mHitPosition = attack.hitPosition.asVec3(); cast.mHitPosition = attack.hitPosition.asVec3();
cast.cast(projectile, false); 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); attack.success);
} }
} }
@ -300,7 +308,7 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
attack.instant = false; 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) else if (attack.type == attack.ITEM_MAGIC)
{ {

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

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