mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 15:36:42 +00:00
[Client] Rethink and restructure tes3mp combat code so it works for NPCs
This commit is contained in:
parent
6c2bbd6608
commit
2e8714afaa
13 changed files with 224 additions and 140 deletions
|
@ -13,9 +13,12 @@
|
||||||
|
|
||||||
Include additional headers for multiplayer purposes
|
Include additional headers for multiplayer purposes
|
||||||
*/
|
*/
|
||||||
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include "../mwmp/Main.hpp"
|
#include "../mwmp/Main.hpp"
|
||||||
#include "../mwmp/LocalPlayer.hpp"
|
#include "../mwmp/LocalPlayer.hpp"
|
||||||
#include "../mwmp/DedicatedPlayer.hpp"
|
#include "../mwmp/DedicatedPlayer.hpp"
|
||||||
|
#include "../mwmp/CellController.hpp"
|
||||||
|
#include "../mwmp/MechanicsHelper.hpp"
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -563,10 +566,12 @@ namespace MWClass
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
Ignore hit calculations on this client from DedicatedPlayers
|
Ignore hit calculations on this client from DedicatedPlayers and DedicatedActors
|
||||||
*/
|
*/
|
||||||
if (mwmp::PlayerList::isDedicatedPlayer(ptr))
|
if (mwmp::PlayerList::isDedicatedPlayer(ptr) || mwmp::Main::get().getCellController()->isDedicatedActor(ptr))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -620,15 +625,15 @@ namespace MWClass
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
If the attacker is a LocalPlayer and the target is a DedicatedPlayer,
|
If the attacker is a LocalPlayer or LocalActor, get their Attack and
|
||||||
mark that accordingly in the LocalPlayer data
|
assign data for its target
|
||||||
*/
|
*/
|
||||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(ptr);
|
||||||
{
|
|
||||||
mwmp::Main::get().getLocalPlayer()->attack.success = true;
|
|
||||||
|
|
||||||
if (mwmp::PlayerList::isDedicatedPlayer(victim))
|
if (localAttack)
|
||||||
mwmp::Main::get().getLocalPlayer()->attack.target.guid = mwmp::PlayerList::getPlayer(victim)->guid;
|
{
|
||||||
|
localAttack->success = true;
|
||||||
|
mwmp::Main::get().getMechanicsHelper()->assignAttackTarget(localAttack, victim);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
|
@ -639,13 +644,14 @@ namespace MWClass
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
If this was a failed attack by the LocalPlayer, send a
|
If this was a failed attack by the LocalPlayer or LocalActor, send a
|
||||||
PlayerAttack packet about it
|
packet about it
|
||||||
*/
|
*/
|
||||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
if (localAttack)
|
||||||
{
|
{
|
||||||
mwmp::Main::get().getLocalPlayer()->attack.success = false;
|
localAttack->pressed = false;
|
||||||
mwmp::Main::get().getLocalPlayer()->sendAttack(mwmp::Attack::MELEE);
|
localAttack->success = false;
|
||||||
|
localAttack->shouldSend = true;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
|
@ -800,10 +806,12 @@ namespace MWClass
|
||||||
/*
|
/*
|
||||||
Start of tes3mp change (major)
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
If the attacker is a DedicatedPlayer with a successful knockdown, apply the knockdown;
|
If the attacker is a DedicatedPlayer or DedicatedActor with a successful knockdown, apply the knockdown;
|
||||||
otherwise, use default probability roll
|
otherwise, use default probability roll
|
||||||
*/
|
*/
|
||||||
if (mwmp::PlayerList::isDedicatedPlayer(attacker) && mwmp::PlayerList::getPlayer(attacker)->attack.knockdown)
|
mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(attacker);
|
||||||
|
|
||||||
|
if (dedicatedAttack && dedicatedAttack->knockdown)
|
||||||
stats.setKnockedDown(true);
|
stats.setKnockedDown(true);
|
||||||
else if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
|
else if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
|
||||||
/*
|
/*
|
||||||
|
@ -913,24 +921,24 @@ namespace MWClass
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
If the victim was a DedicatedPlayer, send a PlayerAttack packet from LocalPlayer
|
If the attacker was the LocalPlayer or LocalActor, record their target and send a packet with it
|
||||||
|
|
||||||
If the victim was the LocalPlayer, check whether packets should be sent about
|
If the victim was the LocalPlayer, check whether packets should be sent about
|
||||||
their new dynamic stats and position
|
their new dynamic stats and position
|
||||||
*/
|
*/
|
||||||
if (attacker == MWMechanics::getPlayer() && mwmp::PlayerList::isDedicatedPlayer(ptr))
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(attacker);
|
||||||
|
|
||||||
|
if (localAttack)
|
||||||
{
|
{
|
||||||
mwmp::DedicatedPlayer *victimPlayer = mwmp::PlayerList::getPlayer(ptr);
|
localAttack->pressed = false;
|
||||||
|
localAttack->damage = damage;
|
||||||
|
localAttack->knockdown = getCreatureStats(ptr).getKnockedDown();
|
||||||
|
|
||||||
mwmp::Attack *attack = &mwmp::Main::get().getLocalPlayer()->attack;
|
mwmp::Main::get().getMechanicsHelper()->assignAttackTarget(localAttack, ptr);
|
||||||
attack->damage = damage;
|
|
||||||
attack->target.guid = victimPlayer->guid;
|
|
||||||
attack->knockdown = getCreatureStats(ptr).getKnockedDown();
|
|
||||||
|
|
||||||
mwmp::Main::get().getLocalPlayer()->sendAttack(mwmp::Attack::MELEE); // todo: make this sensitive to different weapon types
|
localAttack->shouldSend = true;
|
||||||
}
|
}
|
||||||
|
else if (ptr == MWMechanics::getPlayer())
|
||||||
if (ptr == MWMechanics::getPlayer())
|
|
||||||
{
|
{
|
||||||
mwmp::Main::get().getLocalPlayer()->updateStatsDynamic(true);
|
mwmp::Main::get().getLocalPlayer()->updateStatsDynamic(true);
|
||||||
mwmp::Main::get().getLocalPlayer()->updatePosition(true); // fix position after getting damage;
|
mwmp::Main::get().getLocalPlayer()->updatePosition(true); // fix position after getting damage;
|
||||||
|
|
|
@ -16,10 +16,12 @@
|
||||||
|
|
||||||
Include additional headers for multiplayer purposes
|
Include additional headers for multiplayer purposes
|
||||||
*/
|
*/
|
||||||
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include "../mwmp/Main.hpp"
|
#include "../mwmp/Main.hpp"
|
||||||
#include "../mwmp/CellController.hpp"
|
|
||||||
#include "../mwmp/DedicatedPlayer.hpp"
|
|
||||||
#include "../mwmp/LocalPlayer.hpp"
|
#include "../mwmp/LocalPlayer.hpp"
|
||||||
|
#include "../mwmp/DedicatedPlayer.hpp"
|
||||||
|
#include "../mwmp/CellController.hpp"
|
||||||
|
#include "../mwmp/MechanicsHelper.hpp"
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -1120,15 +1122,26 @@ namespace MWMechanics
|
||||||
Start of tes3mp change (minor)
|
Start of tes3mp change (minor)
|
||||||
|
|
||||||
Instead of merely updating the player character's mAttackingOrSpell here,
|
Instead of merely updating the player character's mAttackingOrSpell here,
|
||||||
send a PlayerAttack packet from LocalPlayer when applicable
|
prepare an Attack packet for the LocalPlayer
|
||||||
*/
|
*/
|
||||||
if (iter->first == player)
|
if (iter->first == player)
|
||||||
{
|
{
|
||||||
bool state = MWBase::Environment::get().getWorld()->getPlayer().getAttackingOrSpell();
|
bool state = MWBase::Environment::get().getWorld()->getPlayer().getAttackingOrSpell();
|
||||||
DrawState_ dstate = player.getClass().getNpcStats(player).getDrawState();
|
DrawState_ dstate = player.getClass().getNpcStats(player).getDrawState();
|
||||||
iter->second->getCharacterController()->setAttackingOrSpell(state);
|
iter->second->getCharacterController()->setAttackingOrSpell(state);
|
||||||
|
|
||||||
if (dstate == DrawState_Weapon)
|
if (dstate == DrawState_Weapon)
|
||||||
mwmp::Main::get().getLocalPlayer()->prepareAttack(mwmp::Attack::MELEE, state);
|
{
|
||||||
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(iter->first);
|
||||||
|
|
||||||
|
if (localAttack->pressed != state)
|
||||||
|
{
|
||||||
|
mwmp::Main::get().getMechanicsHelper()->resetAttack(localAttack);
|
||||||
|
localAttack->type = mwmp::Attack::MELEE;
|
||||||
|
localAttack->pressed = state;
|
||||||
|
localAttack->shouldSend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp change (minor)
|
End of tes3mp change (minor)
|
||||||
|
@ -1137,10 +1150,12 @@ namespace MWMechanics
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
If this actor is a DedicatedPlayer, update their mAttackingOrSpell
|
If this actor is a DedicatedPlayer or DedicatedActor, update their mAttackingOrSpell
|
||||||
*/
|
*/
|
||||||
if (mwmp::PlayerList::isDedicatedPlayer(iter->first))
|
mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(iter->first);
|
||||||
mwmp::PlayerList::getPlayer(iter->first)->updateActor(iter->second);
|
|
||||||
|
if (dedicatedAttack)
|
||||||
|
iter->second->getCharacterController()->setAttackingOrSpell(dedicatedAttack->pressed);
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,6 +4,18 @@
|
||||||
|
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Include additional headers for multiplayer purposes
|
||||||
|
*/
|
||||||
|
#include <components/openmw-mp/Log.hpp>
|
||||||
|
#include "../mwmp/Main.hpp"
|
||||||
|
#include "../mwmp/MechanicsHelper.hpp"
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
|
@ -233,6 +245,25 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
storage.stopAttack();
|
storage.stopAttack();
|
||||||
characterController.setAttackingOrSpell(false);
|
characterController.setAttackingOrSpell(false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Record that this actor is stopping an attack so that a packet will be sent about it
|
||||||
|
*/
|
||||||
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(actor);
|
||||||
|
|
||||||
|
if (localAttack->pressed != false)
|
||||||
|
{
|
||||||
|
mwmp::Main::get().getMechanicsHelper()->resetAttack(localAttack);
|
||||||
|
localAttack->type = mwmp::Attack::MELEE;
|
||||||
|
localAttack->pressed = false;
|
||||||
|
localAttack->shouldSend = true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
storage.mActionCooldown = 0.f;
|
storage.mActionCooldown = 0.f;
|
||||||
// Continue combat if target is player or player follower/escorter and an attack has been attempted
|
// Continue combat if target is player or player follower/escorter and an attack has been attempted
|
||||||
const std::list<MWWorld::Ptr>& playerFollowersAndEscorters = MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(MWMechanics::getPlayer());
|
const std::list<MWWorld::Ptr>& playerFollowersAndEscorters = MWBase::Environment::get().getMechanicsManager()->getActorsSidingWith(MWMechanics::getPlayer());
|
||||||
|
@ -566,6 +597,24 @@ namespace MWMechanics
|
||||||
mAttack = true; // attack starts just now
|
mAttack = true; // attack starts just now
|
||||||
characterController.setAttackingOrSpell(true);
|
characterController.setAttackingOrSpell(true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start of tes3mp addition
|
||||||
|
|
||||||
|
Record that this actor is starting an attack so that a packet will be sent about it
|
||||||
|
*/
|
||||||
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(actor);
|
||||||
|
|
||||||
|
if (localAttack->pressed != true)
|
||||||
|
{
|
||||||
|
mwmp::Main::get().getMechanicsHelper()->resetAttack(localAttack);
|
||||||
|
localAttack->type = mwmp::Attack::MELEE;
|
||||||
|
localAttack->pressed = true;
|
||||||
|
localAttack->shouldSend = true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
End of tes3mp addition
|
||||||
|
*/
|
||||||
|
|
||||||
if (!distantCombat)
|
if (!distantCombat)
|
||||||
characterController.setAIAttackType(chooseBestAttack(weapon));
|
characterController.setAIAttackType(chooseBestAttack(weapon));
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,11 @@
|
||||||
*/
|
*/
|
||||||
#include <components/openmw-mp/Log.hpp>
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include "../mwmp/Main.hpp"
|
#include "../mwmp/Main.hpp"
|
||||||
#include "../mwmp/CellController.hpp"
|
|
||||||
#include "../mwmp/LocalPlayer.hpp"
|
#include "../mwmp/LocalPlayer.hpp"
|
||||||
#include "../mwmp/LocalActor.hpp"
|
#include "../mwmp/LocalActor.hpp"
|
||||||
#include "../mwmp/DedicatedPlayer.hpp"
|
#include "../mwmp/DedicatedPlayer.hpp"
|
||||||
|
#include "../mwmp/CellController.hpp"
|
||||||
|
#include "../mwmp/MechanicsHelper.hpp"
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -1258,10 +1259,18 @@ bool CharacterController::updateWeaponState()
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
Send PlayerAttack packet for this spell
|
If this mPtr belongs to a LocalPlayer or LocalActor, get their Attack and prepare
|
||||||
|
it for sending
|
||||||
*/
|
*/
|
||||||
if (mPtr == getPlayer())
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(mPtr);
|
||||||
mwmp::Main::get().getLocalPlayer()->prepareAttack(mwmp::Attack::MAGIC, true);
|
|
||||||
|
if (localAttack)
|
||||||
|
{
|
||||||
|
mwmp::Main::get().getMechanicsHelper()->resetAttack(localAttack);
|
||||||
|
localAttack->type = mwmp::Attack::MAGIC;
|
||||||
|
localAttack->pressed = true;
|
||||||
|
localAttack->shouldSend = true;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -1349,10 +1358,11 @@ bool CharacterController::updateWeaponState()
|
||||||
/*
|
/*
|
||||||
Start of tes3mp change (major)
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
We need player-controlled NPCs to not have their attacks
|
We need DedicatedPlayers and DedicatedActors to not have their attacks
|
||||||
cancelled here, so a 2nd condition has been added for them
|
cancelled here, so additional conditions have been added for them
|
||||||
*/
|
*/
|
||||||
if(mPtr == getPlayer() || mwmp::PlayerList::isDedicatedPlayer(mPtr))
|
if(mPtr == getPlayer() || mwmp::PlayerList::isDedicatedPlayer(mPtr) ||
|
||||||
|
mwmp::Main::get().getCellController()->isDedicatedActor(mPtr))
|
||||||
/*
|
/*
|
||||||
End of tes3mp change (major)
|
End of tes3mp change (major)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,9 +9,12 @@
|
||||||
|
|
||||||
Include additional headers for multiplayer purposes
|
Include additional headers for multiplayer purposes
|
||||||
*/
|
*/
|
||||||
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include "../mwmp/Main.hpp"
|
#include "../mwmp/Main.hpp"
|
||||||
#include "../mwmp/DedicatedPlayer.hpp"
|
|
||||||
#include "../mwmp/LocalPlayer.hpp"
|
#include "../mwmp/LocalPlayer.hpp"
|
||||||
|
#include "../mwmp/DedicatedPlayer.hpp"
|
||||||
|
#include "../mwmp/CellController.hpp"
|
||||||
|
#include "../mwmp/MechanicsHelper.hpp"
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -127,19 +130,25 @@ namespace MWMechanics
|
||||||
/*
|
/*
|
||||||
Start of tes3mp change (major)
|
Start of tes3mp change (major)
|
||||||
|
|
||||||
Only calculate block chance for blockers who are not DedicatedPlayers
|
Only calculate block chance for LocalPlayers and LocalActors; otherwise,
|
||||||
and update block state for LocalPlayer
|
get the block state from the relevant DedicatedPlayer or DedicatedActor
|
||||||
*/
|
*/
|
||||||
if (attacker == MWMechanics::getPlayer())
|
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(attacker);
|
||||||
mwmp::Main::get().getLocalPlayer()->attack.block = false;
|
|
||||||
|
|
||||||
bool isDedicated = mwmp::PlayerList::isDedicatedPlayer(blocker);
|
if (localAttack)
|
||||||
|
|
||||||
if ((!isDedicated && Misc::Rng::roll0to99() < x) ||
|
|
||||||
(isDedicated && mwmp::PlayerList::getPlayer(blocker)->attack.block == true))
|
|
||||||
{
|
{
|
||||||
if (attacker == MWMechanics::getPlayer())
|
localAttack->block = false;
|
||||||
mwmp::Main::get().getLocalPlayer()->attack.block = true;
|
}
|
||||||
|
|
||||||
|
mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(blocker);
|
||||||
|
|
||||||
|
if ((dedicatedAttack && dedicatedAttack->block == true) ||
|
||||||
|
Misc::Rng::roll0to99() < x)
|
||||||
|
{
|
||||||
|
if (localAttack)
|
||||||
|
{
|
||||||
|
localAttack->block = true;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
End of tes3mp change (major)
|
End of tes3mp change (major)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
|
|
||||||
Include additional headers for multiplayer purposes
|
Include additional headers for multiplayer purposes
|
||||||
*/
|
*/
|
||||||
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include "../mwmp/Main.hpp"
|
#include "../mwmp/Main.hpp"
|
||||||
#include "../mwmp/DedicatedPlayer.hpp"
|
#include "../mwmp/DedicatedPlayer.hpp"
|
||||||
#include "../mwmp/LocalPlayer.hpp"
|
#include "../mwmp/LocalPlayer.hpp"
|
||||||
|
#include "../mwmp/MechanicsHelper.hpp"
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
@ -856,16 +858,17 @@ namespace MWMechanics
|
||||||
TODO: See if LocalPlayer being the target and having godmode on
|
TODO: See if LocalPlayer being the target and having godmode on
|
||||||
can be accounted for like it is in OpenMW's corresponding code
|
can be accounted for like it is in OpenMW's corresponding code
|
||||||
*/
|
*/
|
||||||
mwmp::DedicatedPlayer *dedicatedPlayer = mwmp::PlayerList::getPlayer(mCaster);
|
mwmp::Attack *localAttack = NULL;
|
||||||
|
mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(mCaster);
|
||||||
|
|
||||||
bool isDedicated = mwmp::PlayerList::isDedicatedPlayer(mCaster);
|
if (dedicatedAttack)
|
||||||
|
dedicatedAttack->pressed = false;
|
||||||
if (isDedicated)
|
else
|
||||||
dedicatedPlayer->attack.pressed = false;
|
localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(mCaster);
|
||||||
|
|
||||||
// Check success
|
// Check success
|
||||||
if ((!isDedicated && !mwmp::Main::get().getLocalPlayer()->attack.success) ||
|
if ((localAttack && localAttack->success == false) ||
|
||||||
(isDedicated && dedicatedPlayer->attack.success == false))
|
(dedicatedAttack && dedicatedAttack->success == false))
|
||||||
{
|
{
|
||||||
if (mCaster == getPlayer())
|
if (mCaster == getPlayer())
|
||||||
{
|
{
|
||||||
|
|
|
@ -235,7 +235,7 @@ DedicatedPlayer *PlayerList::getPlayer(const MWWorld::Ptr &ptr)
|
||||||
|
|
||||||
bool PlayerList::isDedicatedPlayer(const MWWorld::Ptr &ptr)
|
bool PlayerList::isDedicatedPlayer(const MWWorld::Ptr &ptr)
|
||||||
{
|
{
|
||||||
if (ptr.mRef == 0)
|
if (ptr.mRef == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (getPlayer(ptr) != 0);
|
return (getPlayer(ptr) != 0);
|
||||||
|
@ -420,11 +420,6 @@ void DedicatedPlayer::setMarkerState(bool state)
|
||||||
removeMarker();
|
removeMarker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DedicatedPlayer::updateActor(MWMechanics::Actor *actor)
|
|
||||||
{
|
|
||||||
actor->getCharacterController()->setAttackingOrSpell(attack.pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::Ptr DedicatedPlayer::getPtr()
|
MWWorld::Ptr DedicatedPlayer::getPtr()
|
||||||
{
|
{
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
|
@ -61,7 +61,6 @@ namespace mwmp
|
||||||
void updateMarker();
|
void updateMarker();
|
||||||
void removeMarker();
|
void removeMarker();
|
||||||
void setMarkerState(bool state);
|
void setMarkerState(bool state);
|
||||||
void updateActor(MWMechanics::Actor *actor);
|
|
||||||
|
|
||||||
MWWorld::Ptr getPtr();
|
MWWorld::Ptr getPtr();
|
||||||
MWWorld::Ptr getLiveCellPtr();
|
MWWorld::Ptr getLiveCellPtr();
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "Main.hpp"
|
#include "Main.hpp"
|
||||||
#include "Networking.hpp"
|
#include "Networking.hpp"
|
||||||
#include "ActorList.hpp"
|
#include "ActorList.hpp"
|
||||||
|
#include "MechanicsHelper.hpp"
|
||||||
|
|
||||||
using namespace mwmp;
|
using namespace mwmp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -32,6 +33,9 @@ LocalActor::LocalActor()
|
||||||
|
|
||||||
statTimer = 0;
|
statTimer = 0;
|
||||||
|
|
||||||
|
attack.type = Attack::MELEE;
|
||||||
|
attack.shouldSend = false;
|
||||||
|
|
||||||
creatureStats = new ESM::CreatureStats();
|
creatureStats = new ESM::CreatureStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +51,7 @@ void LocalActor::update(bool forceUpdate)
|
||||||
updateAnimPlay();
|
updateAnimPlay();
|
||||||
updateSpeech();
|
updateSpeech();
|
||||||
updateStatsDynamic(forceUpdate);
|
updateStatsDynamic(forceUpdate);
|
||||||
|
updateAttack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalActor::updatePosition(bool forceUpdate)
|
void LocalActor::updatePosition(bool forceUpdate)
|
||||||
|
@ -168,6 +173,22 @@ void LocalActor::updateStatsDynamic(bool forceUpdate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalActor::updateAttack()
|
||||||
|
{
|
||||||
|
if (attack.shouldSend)
|
||||||
|
{
|
||||||
|
if (attack.type == Attack::MAGIC)
|
||||||
|
{
|
||||||
|
MWMechanics::CreatureStats &attackerStats = ptr.getClass().getNpcStats(ptr);
|
||||||
|
attack.spellId = attackerStats.getSpells().getSelectedSpell();
|
||||||
|
attack.success = mwmp::Main::get().getMechanicsHelper()->getSpellSuccess(attack.spellId, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mwmp::Main::get().getNetworking()->getActorList()->addAttackActor(*this);
|
||||||
|
attack.shouldSend = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::Ptr LocalActor::getPtr()
|
MWWorld::Ptr LocalActor::getPtr()
|
||||||
{
|
{
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace mwmp
|
||||||
void updateAnimPlay();
|
void updateAnimPlay();
|
||||||
void updateSpeech();
|
void updateSpeech();
|
||||||
void updateStatsDynamic(bool forceUpdate);
|
void updateStatsDynamic(bool forceUpdate);
|
||||||
|
void updateAttack();
|
||||||
|
|
||||||
MWWorld::Ptr getPtr();
|
MWWorld::Ptr getPtr();
|
||||||
void setPtr(const MWWorld::Ptr& newPtr);
|
void setPtr(const MWWorld::Ptr& newPtr);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// Created by koncord on 14.01.16.
|
// Created by koncord on 14.01.16.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/openmw-mp/Log.hpp>
|
#include <components/openmw-mp/Log.hpp>
|
||||||
|
|
||||||
|
@ -22,7 +21,6 @@
|
||||||
#include "../mwmechanics/aitravel.hpp"
|
#include "../mwmechanics/aitravel.hpp"
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/mechanicsmanagerimp.hpp"
|
#include "../mwmechanics/mechanicsmanagerimp.hpp"
|
||||||
#include "../mwmechanics/spellcasting.hpp"
|
|
||||||
|
|
||||||
#include "../mwscript/scriptmanagerimp.hpp"
|
#include "../mwscript/scriptmanagerimp.hpp"
|
||||||
|
|
||||||
|
@ -36,9 +34,10 @@
|
||||||
#include "../mwworld/worldimp.hpp"
|
#include "../mwworld/worldimp.hpp"
|
||||||
|
|
||||||
#include "LocalPlayer.hpp"
|
#include "LocalPlayer.hpp"
|
||||||
|
#include "Main.hpp"
|
||||||
#include "Networking.hpp"
|
#include "Networking.hpp"
|
||||||
#include "CellController.hpp"
|
#include "CellController.hpp"
|
||||||
#include "Main.hpp"
|
#include "MechanicsHelper.hpp"
|
||||||
|
|
||||||
using namespace mwmp;
|
using namespace mwmp;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -49,6 +48,8 @@ LocalPlayer::LocalPlayer()
|
||||||
charGenStage.end = 1;
|
charGenStage.end = 1;
|
||||||
consoleAllowed = true;
|
consoleAllowed = true;
|
||||||
ignorePosPacket = false;
|
ignorePosPacket = false;
|
||||||
|
|
||||||
|
attack.shouldSend = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPlayer::~LocalPlayer()
|
LocalPlayer::~LocalPlayer()
|
||||||
|
@ -71,7 +72,7 @@ void LocalPlayer::update()
|
||||||
updateCell();
|
updateCell();
|
||||||
updatePosition();
|
updatePosition();
|
||||||
updateAnimFlags();
|
updateAnimFlags();
|
||||||
updateAttackState();
|
updateAttack();
|
||||||
updateDeadState();
|
updateDeadState();
|
||||||
updateEquipment();
|
updateEquipment();
|
||||||
updateStatsDynamic();
|
updateStatsDynamic();
|
||||||
|
@ -514,32 +515,20 @@ void LocalPlayer::updateInventory(bool forceUpdate)
|
||||||
sendInventory();
|
sendInventory();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::updateAttackState(bool forceUpdate)
|
void LocalPlayer::updateAttack()
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
if (attack.shouldSend)
|
||||||
MWWorld::Ptr player = getPlayerPtr();
|
|
||||||
|
|
||||||
using namespace MWMechanics;
|
|
||||||
|
|
||||||
static bool attackPressed = false; // prevent flood
|
|
||||||
MWMechanics::DrawState_ state = player.getClass().getNpcStats(player).getDrawState();
|
|
||||||
|
|
||||||
if (world->getPlayer().getAttackingOrSpell() && !attackPressed)
|
|
||||||
{
|
{
|
||||||
MWWorld::Ptr weapon = MWWorld::Ptr(); // hand-to-hand
|
if (attack.type == Attack::MAGIC)
|
||||||
|
|
||||||
if (state == MWMechanics::DrawState_Spell)
|
|
||||||
{
|
{
|
||||||
attack.type = Attack::MAGIC;
|
|
||||||
attack.pressed = true;
|
|
||||||
attack.spellId = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
attack.spellId = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
||||||
|
attack.success = mwmp::Main::get().getMechanicsHelper()->getSpellSuccess(attack.spellId, getPlayerPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
attackPressed = true;
|
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->setPlayer(this);
|
||||||
}
|
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->Send();
|
||||||
else if (!world->getPlayer().getAttackingOrSpell() && attackPressed)
|
|
||||||
{
|
attack.shouldSend = false;
|
||||||
attackPressed = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1108,17 +1097,6 @@ void LocalPlayer::sendJournalIndex(const std::string& quest, int index)
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_JOURNAL)->Send();
|
getNetworking()->getPlayerPacket(ID_PLAYER_JOURNAL)->Send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::sendAttack(Attack::TYPE type)
|
|
||||||
{
|
|
||||||
MWMechanics::DrawState_ state = getPlayerPtr().getClass().getNpcStats(getPlayerPtr()).getDrawState();
|
|
||||||
|
|
||||||
attack.type = type;
|
|
||||||
attack.pressed = false;
|
|
||||||
|
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->setPlayer(this);
|
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->Send();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalPlayer::clearCellStates()
|
void LocalPlayer::clearCellStates()
|
||||||
{
|
{
|
||||||
cellStateChanges.cellStates.clear();
|
cellStateChanges.cellStates.clear();
|
||||||
|
@ -1161,31 +1139,3 @@ void LocalPlayer::storeCurrentContainer(const MWWorld::Ptr &container, bool loot
|
||||||
currentContainer.mpNum = container.getCellRef().getMpNum();
|
currentContainer.mpNum = container.getCellRef().getMpNum();
|
||||||
currentContainer.loot = loot;
|
currentContainer.loot = loot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::prepareAttack(Attack::TYPE type, bool state)
|
|
||||||
{
|
|
||||||
if (attack.pressed == state && type != Attack::MAGIC)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MWMechanics::DrawState_ dstate = getPlayerPtr().getClass().getNpcStats(getPlayerPtr()).getDrawState();
|
|
||||||
|
|
||||||
if (dstate == MWMechanics::DrawState_Spell)
|
|
||||||
{
|
|
||||||
attack.spellId = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
|
||||||
attack.success = Misc::Rng::roll0to99() < MWMechanics::getSpellSuccessChance(attack.spellId, getPlayerPtr());
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
attack.success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
attack.pressed = state;
|
|
||||||
attack.type = type;
|
|
||||||
attack.knockdown = false;
|
|
||||||
attack.block = false;
|
|
||||||
attack.target.guid = RakNet::RakNetGUID();
|
|
||||||
|
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->setPlayer(this);
|
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->Send();
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace mwmp
|
||||||
void updateChar();
|
void updateChar();
|
||||||
void updateEquipment(bool forceUpdate = false);
|
void updateEquipment(bool forceUpdate = false);
|
||||||
void updateInventory(bool forceUpdate = false);
|
void updateInventory(bool forceUpdate = false);
|
||||||
void updateAttackState(bool forceUpdate = false);
|
void updateAttack();
|
||||||
void updateDeadState(bool forceUpdate = false);
|
void updateDeadState(bool forceUpdate = false);
|
||||||
void updateAnimFlags(bool forceUpdate = false);
|
void updateAnimFlags(bool forceUpdate = false);
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ namespace mwmp
|
||||||
void sendSpellRemoval(const ESM::Spell &spell);
|
void sendSpellRemoval(const ESM::Spell &spell);
|
||||||
void sendJournalEntry(const std::string& id, int index, const MWWorld::Ptr& actor);
|
void sendJournalEntry(const std::string& id, int index, const MWWorld::Ptr& actor);
|
||||||
void sendJournalIndex(const std::string& id, int index);
|
void sendJournalIndex(const std::string& id, int index);
|
||||||
void sendAttack(Attack::TYPE type);
|
|
||||||
|
|
||||||
void clearCellStates();
|
void clearCellStates();
|
||||||
void clearCurrentContainer();
|
void clearCurrentContainer();
|
||||||
|
@ -74,8 +73,6 @@ namespace mwmp
|
||||||
void storeCellState(ESM::Cell cell, int stateType);
|
void storeCellState(ESM::Cell cell, int stateType);
|
||||||
void storeCurrentContainer(const MWWorld::Ptr& container, bool loot);
|
void storeCurrentContainer(const MWWorld::Ptr& container, bool loot);
|
||||||
|
|
||||||
void prepareAttack(Attack::TYPE type, bool state);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Networking *getNetworking();
|
Networking *getNetworking();
|
||||||
MWWorld::Ptr getPlayerPtr();
|
MWWorld::Ptr getPlayerPtr();
|
||||||
|
|
|
@ -97,10 +97,14 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
|
||||||
{
|
{
|
||||||
if (attack.pressed == false)
|
if (attack.pressed == false)
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Attack success: %s", attack.success ? "true" : "false");
|
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Processing attack from %s",
|
||||||
|
attacker.getCellRef().getRefId().c_str());
|
||||||
|
LOG_APPEND(Log::LOG_VERBOSE, "- success: %s", attack.success ? "true" : "false");
|
||||||
|
|
||||||
if (attack.success == true)
|
if (attack.success == true)
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Damage: %f", attack.damage);
|
{
|
||||||
|
LOG_APPEND(Log::LOG_VERBOSE, "- damage: %f", attack.damage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MWMechanics::CreatureStats &attackerStats = attacker.getClass().getNpcStats(attacker);
|
MWMechanics::CreatureStats &attackerStats = attacker.getClass().getNpcStats(attacker);
|
||||||
|
@ -108,10 +112,33 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
|
||||||
|
|
||||||
MWWorld::Ptr victim;
|
MWWorld::Ptr victim;
|
||||||
|
|
||||||
|
if (attack.target.refId.empty())
|
||||||
|
{
|
||||||
if (attack.target.guid == mwmp::Main::get().getLocalPlayer()->guid)
|
if (attack.target.guid == mwmp::Main::get().getLocalPlayer()->guid)
|
||||||
|
{
|
||||||
victim = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
victim = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
else if (PlayerList::getPlayer(attack.target.guid) != 0)
|
}
|
||||||
|
else if (PlayerList::getPlayer(attack.target.guid) != NULL)
|
||||||
|
{
|
||||||
victim = PlayerList::getPlayer(attack.target.guid)->getPtr();
|
victim = PlayerList::getPlayer(attack.target.guid)->getPtr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mwmp::Main::get().getCellController()->isLocalActor(attack.target.refId,
|
||||||
|
attack.target.refNumIndex, attack.target.mpNum))
|
||||||
|
{
|
||||||
|
victim = mwmp::Main::get().getCellController()->getLocalActor(attack.target.refId,
|
||||||
|
attack.target.refNumIndex, attack.target.mpNum)->getPtr();
|
||||||
|
}
|
||||||
|
else if (mwmp::Main::get().getCellController()->isDedicatedActor(attack.target.refId,
|
||||||
|
attack.target.refNumIndex, attack.target.mpNum))
|
||||||
|
{
|
||||||
|
victim = mwmp::Main::get().getCellController()->getDedicatedActor(attack.target.refId,
|
||||||
|
attack.target.refNumIndex, attack.target.mpNum)->getPtr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
// Get the weapon used (if hand-to-hand, weapon = inv.end())
|
||||||
if (attackerStats.getDrawState() == MWMechanics::DrawState_Weapon)
|
if (attackerStats.getDrawState() == MWMechanics::DrawState_Weapon)
|
||||||
|
@ -124,7 +151,7 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
|
||||||
if (!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
|
if (!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
|
||||||
weapon = MWWorld::Ptr();
|
weapon = MWWorld::Ptr();
|
||||||
|
|
||||||
if (victim.mRef != 0)
|
if (victim.mRef != NULL)
|
||||||
{
|
{
|
||||||
bool healthdmg;
|
bool healthdmg;
|
||||||
if (!weapon.isEmpty())
|
if (!weapon.isEmpty())
|
||||||
|
|
Loading…
Reference in a new issue