mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 19:19:56 +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 <components/openmw-mp/Log.hpp>
|
||||
#include "../mwmp/Main.hpp"
|
||||
#include "../mwmp/LocalPlayer.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -563,10 +566,12 @@ namespace MWClass
|
|||
/*
|
||||
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;
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -620,15 +625,15 @@ namespace MWClass
|
|||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
If the attacker is a LocalPlayer and the target is a DedicatedPlayer,
|
||||
mark that accordingly in the LocalPlayer data
|
||||
If the attacker is a LocalPlayer or LocalActor, get their Attack and
|
||||
assign data for its target
|
||||
*/
|
||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
{
|
||||
mwmp::Main::get().getLocalPlayer()->attack.success = true;
|
||||
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(ptr);
|
||||
|
||||
if (mwmp::PlayerList::isDedicatedPlayer(victim))
|
||||
mwmp::Main::get().getLocalPlayer()->attack.target.guid = mwmp::PlayerList::getPlayer(victim)->guid;
|
||||
if (localAttack)
|
||||
{
|
||||
localAttack->success = true;
|
||||
mwmp::Main::get().getMechanicsHelper()->assignAttackTarget(localAttack, victim);
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
|
@ -639,13 +644,14 @@ namespace MWClass
|
|||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
If this was a failed attack by the LocalPlayer, send a
|
||||
PlayerAttack packet about it
|
||||
If this was a failed attack by the LocalPlayer or LocalActor, send a
|
||||
packet about it
|
||||
*/
|
||||
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
if (localAttack)
|
||||
{
|
||||
mwmp::Main::get().getLocalPlayer()->attack.success = false;
|
||||
mwmp::Main::get().getLocalPlayer()->sendAttack(mwmp::Attack::MELEE);
|
||||
localAttack->pressed = false;
|
||||
localAttack->success = false;
|
||||
localAttack->shouldSend = true;
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
|
@ -800,10 +806,12 @@ namespace MWClass
|
|||
/*
|
||||
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
|
||||
*/
|
||||
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);
|
||||
else if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
|
||||
/*
|
||||
|
@ -913,24 +921,24 @@ namespace MWClass
|
|||
/*
|
||||
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
|
||||
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;
|
||||
attack->damage = damage;
|
||||
attack->target.guid = victimPlayer->guid;
|
||||
attack->knockdown = getCreatureStats(ptr).getKnockedDown();
|
||||
mwmp::Main::get().getMechanicsHelper()->assignAttackTarget(localAttack, ptr);
|
||||
|
||||
mwmp::Main::get().getLocalPlayer()->sendAttack(mwmp::Attack::MELEE); // todo: make this sensitive to different weapon types
|
||||
localAttack->shouldSend = true;
|
||||
}
|
||||
|
||||
if (ptr == MWMechanics::getPlayer())
|
||||
else if (ptr == MWMechanics::getPlayer())
|
||||
{
|
||||
mwmp::Main::get().getLocalPlayer()->updateStatsDynamic(true);
|
||||
mwmp::Main::get().getLocalPlayer()->updatePosition(true); // fix position after getting damage;
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
|
||||
Include additional headers for multiplayer purposes
|
||||
*/
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
#include "../mwmp/Main.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/LocalPlayer.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -1120,15 +1122,26 @@ namespace MWMechanics
|
|||
Start of tes3mp change (minor)
|
||||
|
||||
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)
|
||||
{
|
||||
bool state = MWBase::Environment::get().getWorld()->getPlayer().getAttackingOrSpell();
|
||||
DrawState_ dstate = player.getClass().getNpcStats(player).getDrawState();
|
||||
iter->second->getCharacterController()->setAttackingOrSpell(state);
|
||||
|
||||
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)
|
||||
|
@ -1137,10 +1150,12 @@ namespace MWMechanics
|
|||
/*
|
||||
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::PlayerList::getPlayer(iter->first)->updateActor(iter->second);
|
||||
mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(iter->first);
|
||||
|
||||
if (dedicatedAttack)
|
||||
iter->second->getCharacterController()->setAttackingOrSpell(dedicatedAttack->pressed);
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,18 @@
|
|||
|
||||
#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/esmstore.hpp"
|
||||
|
||||
|
@ -233,6 +245,25 @@ namespace MWMechanics
|
|||
{
|
||||
storage.stopAttack();
|
||||
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;
|
||||
// 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());
|
||||
|
@ -566,6 +597,24 @@ namespace MWMechanics
|
|||
mAttack = true; // attack starts just now
|
||||
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)
|
||||
characterController.setAIAttackType(chooseBestAttack(weapon));
|
||||
|
||||
|
|
|
@ -34,10 +34,11 @@
|
|||
*/
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
#include "../mwmp/Main.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/LocalPlayer.hpp"
|
||||
#include "../mwmp/LocalActor.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -1258,10 +1259,18 @@ bool CharacterController::updateWeaponState()
|
|||
/*
|
||||
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::Main::get().getLocalPlayer()->prepareAttack(mwmp::Attack::MAGIC, true);
|
||||
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(mPtr);
|
||||
|
||||
if (localAttack)
|
||||
{
|
||||
mwmp::Main::get().getMechanicsHelper()->resetAttack(localAttack);
|
||||
localAttack->type = mwmp::Attack::MAGIC;
|
||||
localAttack->pressed = true;
|
||||
localAttack->shouldSend = true;
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -1349,10 +1358,11 @@ bool CharacterController::updateWeaponState()
|
|||
/*
|
||||
Start of tes3mp change (major)
|
||||
|
||||
We need player-controlled NPCs to not have their attacks
|
||||
cancelled here, so a 2nd condition has been added for them
|
||||
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))
|
||||
if(mPtr == getPlayer() || mwmp::PlayerList::isDedicatedPlayer(mPtr) ||
|
||||
mwmp::Main::get().getCellController()->isDedicatedActor(mPtr))
|
||||
/*
|
||||
End of tes3mp change (major)
|
||||
*/
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
|
||||
Include additional headers for multiplayer purposes
|
||||
*/
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
#include "../mwmp/Main.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/LocalPlayer.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -127,19 +130,25 @@ namespace MWMechanics
|
|||
/*
|
||||
Start of tes3mp change (major)
|
||||
|
||||
Only calculate block chance for blockers who are not DedicatedPlayers
|
||||
and update block state for LocalPlayer
|
||||
Only calculate block chance for LocalPlayers and LocalActors; otherwise,
|
||||
get the block state from the relevant DedicatedPlayer or DedicatedActor
|
||||
*/
|
||||
if (attacker == MWMechanics::getPlayer())
|
||||
mwmp::Main::get().getLocalPlayer()->attack.block = false;
|
||||
mwmp::Attack *localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(attacker);
|
||||
|
||||
bool isDedicated = mwmp::PlayerList::isDedicatedPlayer(blocker);
|
||||
|
||||
if ((!isDedicated && Misc::Rng::roll0to99() < x) ||
|
||||
(isDedicated && mwmp::PlayerList::getPlayer(blocker)->attack.block == true))
|
||||
if (localAttack)
|
||||
{
|
||||
if (attacker == MWMechanics::getPlayer())
|
||||
mwmp::Main::get().getLocalPlayer()->attack.block = true;
|
||||
localAttack->block = false;
|
||||
}
|
||||
|
||||
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)
|
||||
*/
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
|
||||
Include additional headers for multiplayer purposes
|
||||
*/
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
#include "../mwmp/Main.hpp"
|
||||
#include "../mwmp/DedicatedPlayer.hpp"
|
||||
#include "../mwmp/LocalPlayer.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -856,16 +858,17 @@ namespace MWMechanics
|
|||
TODO: See if LocalPlayer being the target and having godmode on
|
||||
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 (isDedicated)
|
||||
dedicatedPlayer->attack.pressed = false;
|
||||
if (dedicatedAttack)
|
||||
dedicatedAttack->pressed = false;
|
||||
else
|
||||
localAttack = mwmp::Main::get().getMechanicsHelper()->getLocalAttack(mCaster);
|
||||
|
||||
// Check success
|
||||
if ((!isDedicated && !mwmp::Main::get().getLocalPlayer()->attack.success) ||
|
||||
(isDedicated && dedicatedPlayer->attack.success == false))
|
||||
if ((localAttack && localAttack->success == false) ||
|
||||
(dedicatedAttack && dedicatedAttack->success == false))
|
||||
{
|
||||
if (mCaster == getPlayer())
|
||||
{
|
||||
|
|
|
@ -235,7 +235,7 @@ DedicatedPlayer *PlayerList::getPlayer(const MWWorld::Ptr &ptr)
|
|||
|
||||
bool PlayerList::isDedicatedPlayer(const MWWorld::Ptr &ptr)
|
||||
{
|
||||
if (ptr.mRef == 0)
|
||||
if (ptr.mRef == NULL)
|
||||
return false;
|
||||
|
||||
return (getPlayer(ptr) != 0);
|
||||
|
@ -420,11 +420,6 @@ void DedicatedPlayer::setMarkerState(bool state)
|
|||
removeMarker();
|
||||
}
|
||||
|
||||
void DedicatedPlayer::updateActor(MWMechanics::Actor *actor)
|
||||
{
|
||||
actor->getCharacterController()->setAttackingOrSpell(attack.pressed);
|
||||
}
|
||||
|
||||
MWWorld::Ptr DedicatedPlayer::getPtr()
|
||||
{
|
||||
return ptr;
|
||||
|
|
|
@ -61,7 +61,6 @@ namespace mwmp
|
|||
void updateMarker();
|
||||
void removeMarker();
|
||||
void setMarkerState(bool state);
|
||||
void updateActor(MWMechanics::Actor *actor);
|
||||
|
||||
MWWorld::Ptr getPtr();
|
||||
MWWorld::Ptr getLiveCellPtr();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Main.hpp"
|
||||
#include "Networking.hpp"
|
||||
#include "ActorList.hpp"
|
||||
#include "MechanicsHelper.hpp"
|
||||
|
||||
using namespace mwmp;
|
||||
using namespace std;
|
||||
|
@ -32,6 +33,9 @@ LocalActor::LocalActor()
|
|||
|
||||
statTimer = 0;
|
||||
|
||||
attack.type = Attack::MELEE;
|
||||
attack.shouldSend = false;
|
||||
|
||||
creatureStats = new ESM::CreatureStats();
|
||||
}
|
||||
|
||||
|
@ -47,6 +51,7 @@ void LocalActor::update(bool forceUpdate)
|
|||
updateAnimPlay();
|
||||
updateSpeech();
|
||||
updateStatsDynamic(forceUpdate);
|
||||
updateAttack();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return ptr;
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace mwmp
|
|||
void updateAnimPlay();
|
||||
void updateSpeech();
|
||||
void updateStatsDynamic(bool forceUpdate);
|
||||
void updateAttack();
|
||||
|
||||
MWWorld::Ptr getPtr();
|
||||
void setPtr(const MWWorld::Ptr& newPtr);
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Created by koncord on 14.01.16.
|
||||
//
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
|
||||
|
@ -22,7 +21,6 @@
|
|||
#include "../mwmechanics/aitravel.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/mechanicsmanagerimp.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
|
||||
#include "../mwscript/scriptmanagerimp.hpp"
|
||||
|
||||
|
@ -36,9 +34,10 @@
|
|||
#include "../mwworld/worldimp.hpp"
|
||||
|
||||
#include "LocalPlayer.hpp"
|
||||
#include "Main.hpp"
|
||||
#include "Networking.hpp"
|
||||
#include "CellController.hpp"
|
||||
#include "Main.hpp"
|
||||
#include "MechanicsHelper.hpp"
|
||||
|
||||
using namespace mwmp;
|
||||
using namespace std;
|
||||
|
@ -49,6 +48,8 @@ LocalPlayer::LocalPlayer()
|
|||
charGenStage.end = 1;
|
||||
consoleAllowed = true;
|
||||
ignorePosPacket = false;
|
||||
|
||||
attack.shouldSend = false;
|
||||
}
|
||||
|
||||
LocalPlayer::~LocalPlayer()
|
||||
|
@ -71,7 +72,7 @@ void LocalPlayer::update()
|
|||
updateCell();
|
||||
updatePosition();
|
||||
updateAnimFlags();
|
||||
updateAttackState();
|
||||
updateAttack();
|
||||
updateDeadState();
|
||||
updateEquipment();
|
||||
updateStatsDynamic();
|
||||
|
@ -514,32 +515,20 @@ void LocalPlayer::updateInventory(bool forceUpdate)
|
|||
sendInventory();
|
||||
}
|
||||
|
||||
void LocalPlayer::updateAttackState(bool forceUpdate)
|
||||
void LocalPlayer::updateAttack()
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
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)
|
||||
if (attack.shouldSend)
|
||||
{
|
||||
MWWorld::Ptr weapon = MWWorld::Ptr(); // hand-to-hand
|
||||
|
||||
if (state == MWMechanics::DrawState_Spell)
|
||||
if (attack.type == Attack::MAGIC)
|
||||
{
|
||||
attack.type = Attack::MAGIC;
|
||||
attack.pressed = true;
|
||||
attack.spellId = MWBase::Environment::get().getWindowManager()->getSelectedSpell();
|
||||
attack.success = mwmp::Main::get().getMechanicsHelper()->getSpellSuccess(attack.spellId, getPlayerPtr());
|
||||
}
|
||||
|
||||
attackPressed = true;
|
||||
}
|
||||
else if (!world->getPlayer().getAttackingOrSpell() && attackPressed)
|
||||
{
|
||||
attackPressed = false;
|
||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->setPlayer(this);
|
||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTACK)->Send();
|
||||
|
||||
attack.shouldSend = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1108,17 +1097,6 @@ void LocalPlayer::sendJournalIndex(const std::string& quest, int index)
|
|||
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()
|
||||
{
|
||||
cellStateChanges.cellStates.clear();
|
||||
|
@ -1161,31 +1139,3 @@ void LocalPlayer::storeCurrentContainer(const MWWorld::Ptr &container, bool loot
|
|||
currentContainer.mpNum = container.getCellRef().getMpNum();
|
||||
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 updateEquipment(bool forceUpdate = false);
|
||||
void updateInventory(bool forceUpdate = false);
|
||||
void updateAttackState(bool forceUpdate = false);
|
||||
void updateAttack();
|
||||
void updateDeadState(bool forceUpdate = false);
|
||||
void updateAnimFlags(bool forceUpdate = false);
|
||||
|
||||
|
@ -66,7 +66,6 @@ namespace mwmp
|
|||
void sendSpellRemoval(const ESM::Spell &spell);
|
||||
void sendJournalEntry(const std::string& id, int index, const MWWorld::Ptr& actor);
|
||||
void sendJournalIndex(const std::string& id, int index);
|
||||
void sendAttack(Attack::TYPE type);
|
||||
|
||||
void clearCellStates();
|
||||
void clearCurrentContainer();
|
||||
|
@ -74,8 +73,6 @@ namespace mwmp
|
|||
void storeCellState(ESM::Cell cell, int stateType);
|
||||
void storeCurrentContainer(const MWWorld::Ptr& container, bool loot);
|
||||
|
||||
void prepareAttack(Attack::TYPE type, bool state);
|
||||
|
||||
private:
|
||||
Networking *getNetworking();
|
||||
MWWorld::Ptr getPlayerPtr();
|
||||
|
|
|
@ -97,21 +97,48 @@ void MechanicsHelper::processAttack(Attack attack, const MWWorld::Ptr& attacker)
|
|||
{
|
||||
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)
|
||||
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);
|
||||
attackerStats.getSpells().setSelectedSpell(attack.spellId);
|
||||
|
||||
MWWorld::Ptr victim;
|
||||
|
||||
if (attack.target.guid == mwmp::Main::get().getLocalPlayer()->guid)
|
||||
victim = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
else if (PlayerList::getPlayer(attack.target.guid) != 0)
|
||||
victim = PlayerList::getPlayer(attack.target.guid)->getPtr();
|
||||
|
||||
if (attack.target.refId.empty())
|
||||
{
|
||||
if (attack.target.guid == mwmp::Main::get().getLocalPlayer()->guid)
|
||||
{
|
||||
victim = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
}
|
||||
else if (PlayerList::getPlayer(attack.target.guid) != NULL)
|
||||
{
|
||||
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())
|
||||
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())
|
||||
weapon = MWWorld::Ptr();
|
||||
|
||||
if (victim.mRef != 0)
|
||||
if (victim.mRef != NULL)
|
||||
{
|
||||
bool healthdmg;
|
||||
if (!weapon.isEmpty())
|
||||
|
|
Loading…
Reference in a new issue