diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 2f013dcc7..52a470d24 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -13,9 +13,12 @@ Include additional headers for multiplayer purposes */ +#include #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; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 2d2f664e2..ea43a8cd7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -16,10 +16,12 @@ Include additional headers for multiplayer purposes */ +#include #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 */ diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 17005f235..e88e5e537 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -4,6 +4,18 @@ #include +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include +#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& 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)); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index da358ad75..f3f732fdb 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -34,10 +34,11 @@ */ #include #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) */ diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index f556d1ab2..dc0e41102 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -9,9 +9,12 @@ Include additional headers for multiplayer purposes */ +#include #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 (localAttack) + { + localAttack->block = false; + } - if ((!isDedicated && Misc::Rng::roll0to99() < x) || - (isDedicated && mwmp::PlayerList::getPlayer(blocker)->attack.block == true)) + mwmp::Attack *dedicatedAttack = mwmp::Main::get().getMechanicsHelper()->getDedicatedAttack(blocker); + + if ((dedicatedAttack && dedicatedAttack->block == true) || + Misc::Rng::roll0to99() < x) { - if (attacker == MWMechanics::getPlayer()) - mwmp::Main::get().getLocalPlayer()->attack.block = true; + if (localAttack) + { + localAttack->block = true; + } /* End of tes3mp change (major) */ diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 072d4ecbf..f20ca14d3 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -13,9 +13,11 @@ Include additional headers for multiplayer purposes */ +#include #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()) { diff --git a/apps/openmw/mwmp/DedicatedPlayer.cpp b/apps/openmw/mwmp/DedicatedPlayer.cpp index 6d0eab962..b17ef3dd9 100644 --- a/apps/openmw/mwmp/DedicatedPlayer.cpp +++ b/apps/openmw/mwmp/DedicatedPlayer.cpp @@ -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; diff --git a/apps/openmw/mwmp/DedicatedPlayer.hpp b/apps/openmw/mwmp/DedicatedPlayer.hpp index 4b746a52b..428f5d597 100644 --- a/apps/openmw/mwmp/DedicatedPlayer.hpp +++ b/apps/openmw/mwmp/DedicatedPlayer.hpp @@ -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(); diff --git a/apps/openmw/mwmp/LocalActor.cpp b/apps/openmw/mwmp/LocalActor.cpp index 68ee70977..db5e2ee0a 100644 --- a/apps/openmw/mwmp/LocalActor.cpp +++ b/apps/openmw/mwmp/LocalActor.cpp @@ -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; diff --git a/apps/openmw/mwmp/LocalActor.hpp b/apps/openmw/mwmp/LocalActor.hpp index 45f23e7a6..f4ec95bca 100644 --- a/apps/openmw/mwmp/LocalActor.hpp +++ b/apps/openmw/mwmp/LocalActor.hpp @@ -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); diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 62c4c0ea9..5bb9cd1e3 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -2,7 +2,6 @@ // Created by koncord on 14.01.16. // -#include #include #include @@ -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(); -} diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 53b0a1e86..da5eb099d 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -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(); diff --git a/apps/openmw/mwmp/MechanicsHelper.cpp b/apps/openmw/mwmp/MechanicsHelper.cpp index 6eec2d3a9..a42f8d230 100644 --- a/apps/openmw/mwmp/MechanicsHelper.cpp +++ b/apps/openmw/mwmp/MechanicsHelper.cpp @@ -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())