mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-06 01:49:41 +00:00
[General] Implement ActorSpellsActive packet, part 1
The packet can now set the active spells of DedicatedActors.
This commit is contained in:
parent
f6887559f6
commit
bf0a42fdad
22 changed files with 300 additions and 5 deletions
|
@ -84,8 +84,8 @@ set(PROCESSORS_ACTOR
|
|||
processors/actor/ProcessorActorCast.hpp processors/actor/ProcessorActorCellChange.hpp
|
||||
processors/actor/ProcessorActorDeath.hpp processors/actor/ProcessorActorEquipment.hpp
|
||||
processors/actor/ProcessorActorList.hpp processors/actor/ProcessorActorPosition.hpp
|
||||
processors/actor/ProcessorActorSpeech.hpp processors/actor/ProcessorActorStatsDynamic.hpp
|
||||
processors/actor/ProcessorActorTest.hpp
|
||||
processors/actor/ProcessorActorSpeech.hpp processors/actor/ProcessorActorSpellsActive.hpp
|
||||
processors/actor/ProcessorActorStatsDynamic.hpp processors/actor/ProcessorActorTest.hpp
|
||||
)
|
||||
|
||||
source_group(tes3mp-server\\processors\\actor FILES ${PROCESSORS_ACTOR})
|
||||
|
|
|
@ -207,6 +207,7 @@ public:
|
|||
{"OnActorEquipment", Callback<unsigned short, const char*>()},
|
||||
{"OnActorAI", Callback<unsigned short, const char*>()},
|
||||
{"OnActorDeath", Callback<unsigned short, const char*>()},
|
||||
{"OnActorSpellsActive", Callback<unsigned short, const char*>()},
|
||||
{"OnActorCellChange", Callback<unsigned short, const char*>()},
|
||||
{"OnActorTest", Callback<unsigned short, const char*>()},
|
||||
{"OnPlayerSendMessage", Callback<unsigned short, const char*>()},
|
||||
|
|
|
@ -51,9 +51,10 @@
|
|||
#include "actor/ProcessorActorCellChange.hpp"
|
||||
#include "actor/ProcessorActorDeath.hpp"
|
||||
#include "actor/ProcessorActorEquipment.hpp"
|
||||
#include "actor/ProcessorActorStatsDynamic.hpp"
|
||||
#include "actor/ProcessorActorPosition.hpp"
|
||||
#include "actor/ProcessorActorSpeech.hpp"
|
||||
#include "actor/ProcessorActorSpellsActive.hpp"
|
||||
#include "actor/ProcessorActorStatsDynamic.hpp"
|
||||
#include "ObjectProcessor.hpp"
|
||||
#include "object/ProcessorConsoleCommand.hpp"
|
||||
#include "object/ProcessorContainer.hpp"
|
||||
|
@ -137,6 +138,7 @@ void ProcessorInitializer()
|
|||
ActorProcessor::AddProcessor(new ProcessorActorEquipment());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorPosition());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorSpeech());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorSpellsActive());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorTest());
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef OPENMW_PROCESSORACTORSPELLSACTIVE_HPP
|
||||
#define OPENMW_PROCESSORACTORSPELLSACTIVE_HPP
|
||||
|
||||
#include "../ActorProcessor.hpp"
|
||||
|
||||
namespace mwmp
|
||||
{
|
||||
class ProcessorActorSpellsActive : public ActorProcessor
|
||||
{
|
||||
public:
|
||||
ProcessorActorSpellsActive()
|
||||
{
|
||||
BPP_INIT(ID_ACTOR_SPELLS_ACTIVE)
|
||||
}
|
||||
|
||||
void Do(ActorPacket &packet, Player &player, BaseActorList &actorList) override
|
||||
{
|
||||
// Send only to players who have the cell loaded
|
||||
Cell *serverCell = CellController::get()->getCell(&actorList.cell);
|
||||
|
||||
if (serverCell != nullptr && *serverCell->getAuthority() == actorList.guid)
|
||||
{
|
||||
Script::Call<Script::CallbackIdentity("OnActorSpellsActive")>(player.getId(), actorList.cell.getDescription().c_str());
|
||||
|
||||
serverCell->sendToLoaded(&packet, &actorList);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //OPENMW_PROCESSORACTORSPELLSACTIVE_HPP
|
|
@ -115,7 +115,8 @@ add_openmw_dir (mwmp/processors/system ProcessorSystemHandshake
|
|||
|
||||
add_openmw_dir (mwmp/processors/actor ProcessorActorAI ProcessorActorAnimFlags ProcessorActorAnimPlay ProcessorActorAttack
|
||||
ProcessorActorAuthority ProcessorActorCast ProcessorActorCellChange ProcessorActorDeath ProcessorActorEquipment
|
||||
ProcessorActorList ProcessorActorPosition ProcessorActorSpeech ProcessorActorStatsDynamic ProcessorActorTest
|
||||
ProcessorActorList ProcessorActorPosition ProcessorActorSpeech ProcessorActorSpellsActive ProcessorActorStatsDynamic
|
||||
ProcessorActorTest
|
||||
)
|
||||
|
||||
add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageBox ProcessorUserDisconnected
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwmp/Main.hpp"
|
||||
#include "../mwmp/LocalPlayer.hpp"
|
||||
#include "../mwmp/CellController.hpp"
|
||||
#include "../mwmp/MechanicsHelper.hpp"
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -47,6 +49,10 @@ namespace MWMechanics
|
|||
{
|
||||
mwmp::Main::get().getLocalPlayer()->sendSpellsActiveRemoval(iter->first);
|
||||
}
|
||||
else if (mwmp::Main::get().getCellController()->isLocalActor(MechanicsHelper::getCurrentActor()))
|
||||
{
|
||||
mwmp::Main::get().getCellController()->getLocalActor(MechanicsHelper::getCurrentActor())->sendSpellsActiveRemoval(iter->first);
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
@ -205,6 +211,10 @@ namespace MWMechanics
|
|||
{
|
||||
mwmp::Main::get().getLocalPlayer()->sendSpellsActiveAddition(id, esmParams);
|
||||
}
|
||||
else if (mwmp::Main::get().getCellController()->isLocalActor(MechanicsHelper::getCurrentActor()))
|
||||
{
|
||||
mwmp::Main::get().getCellController()->getLocalActor(MechanicsHelper::getCurrentActor())->sendSpellsActiveAddition(id, esmParams);
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
|
|
@ -2123,6 +2123,16 @@ namespace MWMechanics
|
|||
End of tes3mp change (major)
|
||||
*/
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Store the current actor's Ptr so it can be retrieved from inside ActiveSpells for
|
||||
multiplayer logic purposes
|
||||
*/
|
||||
MechanicsHelper::storeCurrentActor(iter->first);
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
|
||||
|
||||
const Misc::TimerStatus engageCombatTimerStatus = iter->second->updateEngageCombatTimer(duration);
|
||||
|
@ -2528,6 +2538,16 @@ namespace MWMechanics
|
|||
{
|
||||
if (iter->first.getClass().getCreatureStats(iter->first).isDead())
|
||||
{
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Store the current actor's Ptr so it can be retrieved from inside ActiveSpells for
|
||||
multiplayer logic purposes
|
||||
*/
|
||||
MechanicsHelper::storeCurrentActor(iter->first);
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
|
||||
continue;
|
||||
}
|
||||
|
@ -2547,6 +2567,17 @@ namespace MWMechanics
|
|||
if (iter->first.getClass().isNpc())
|
||||
calculateNpcStatModifiers(iter->first, duration);
|
||||
|
||||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Store the current actor's Ptr so it can be retrieved from inside ActiveSpells for
|
||||
multiplayer logic purposes
|
||||
*/
|
||||
MechanicsHelper::storeCurrentActor(iter->first);
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
||||
iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
|
||||
|
||||
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first);
|
||||
|
|
|
@ -286,6 +286,36 @@ void Cell::readSpeech(ActorList& actorList)
|
|||
uninitializeDedicatedActors(actorList);
|
||||
}
|
||||
|
||||
void Cell::readSpellsActive(ActorList& actorList)
|
||||
{
|
||||
initializeDedicatedActors(actorList);
|
||||
|
||||
if (dedicatedActors.empty()) return;
|
||||
|
||||
for (const auto& baseActor : actorList.baseActors)
|
||||
{
|
||||
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
||||
|
||||
if (dedicatedActors.count(mapIndex) > 0)
|
||||
{
|
||||
DedicatedActor* actor = dedicatedActors[mapIndex];
|
||||
actor->spellsActiveChanges = baseActor.spellsActiveChanges;
|
||||
|
||||
int spellsActiveAction = baseActor.spellsActiveChanges.action;
|
||||
|
||||
if (spellsActiveAction == SpellsActiveChanges::ADD)
|
||||
actor->addSpellsActive();
|
||||
else if (spellsActiveAction == SpellsActiveChanges::REMOVE)
|
||||
actor->removeSpellsActive();
|
||||
else
|
||||
actor->setSpellsActive();
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLocalAuthority())
|
||||
uninitializeDedicatedActors(actorList);
|
||||
}
|
||||
|
||||
void Cell::readAi(ActorList& actorList)
|
||||
{
|
||||
initializeDedicatedActors(actorList);
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace mwmp
|
|||
void readDeath(ActorList& actorList);
|
||||
void readEquipment(ActorList& actorList);
|
||||
void readSpeech(ActorList& actorList);
|
||||
void readSpellsActive(ActorList& actorList);
|
||||
void readAi(ActorList& actorList);
|
||||
void readAttack(ActorList& actorList);
|
||||
void readCast(ActorList& actorList);
|
||||
|
|
|
@ -211,6 +211,17 @@ void CellController::readSpeech(ActorList& actorList)
|
|||
cellsInitialized[mapIndex]->readSpeech(actorList);
|
||||
}
|
||||
|
||||
void CellController::readSpellsActive(ActorList& actorList)
|
||||
{
|
||||
std::string mapIndex = actorList.cell.getDescription();
|
||||
|
||||
initializeCell(actorList.cell);
|
||||
|
||||
// If this now exists, send it the data
|
||||
if (cellsInitialized.count(mapIndex) > 0)
|
||||
cellsInitialized[mapIndex]->readSpellsActive(actorList);
|
||||
}
|
||||
|
||||
void CellController::readAi(ActorList& actorList)
|
||||
{
|
||||
std::string mapIndex = actorList.cell.getDescription();
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace mwmp
|
|||
void readDeath(mwmp::ActorList& actorList);
|
||||
void readEquipment(mwmp::ActorList& actorList);
|
||||
void readSpeech(mwmp::ActorList& actorList);
|
||||
void readSpellsActive(mwmp::ActorList& actorList);
|
||||
void readAi(mwmp::ActorList& actorList);
|
||||
void readAttack(mwmp::ActorList& actorList);
|
||||
void readCast(mwmp::ActorList& actorList);
|
||||
|
|
|
@ -359,6 +359,41 @@ void DedicatedActor::equipItem(std::string itemId, int charge, bool noSound)
|
|||
}
|
||||
}
|
||||
|
||||
void DedicatedActor::addSpellsActive()
|
||||
{
|
||||
MWMechanics::ActiveSpells& activeSpells = getPtr().getClass().getCreatureStats(getPtr()).getActiveSpells();
|
||||
|
||||
for (const auto& activeSpell : spellsActiveChanges.activeSpells)
|
||||
{
|
||||
// Only add spells that are ensured to exist
|
||||
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(activeSpell.id))
|
||||
{
|
||||
activeSpells.addSpell(activeSpell.id, false, activeSpell.params.mEffects, activeSpell.params.mDisplayName, 1);
|
||||
}
|
||||
else
|
||||
LOG_APPEND(TimedLog::LOG_INFO, "- Ignored addition of invalid spell %s", activeSpell.id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DedicatedActor::removeSpellsActive()
|
||||
{
|
||||
MWMechanics::ActiveSpells& activeSpells = getPtr().getClass().getCreatureStats(getPtr()).getActiveSpells();
|
||||
|
||||
for (const auto& activeSpell : spellsActiveChanges.activeSpells)
|
||||
{
|
||||
activeSpells.removeEffects(activeSpell.id);
|
||||
}
|
||||
}
|
||||
|
||||
void DedicatedActor::setSpellsActive()
|
||||
{
|
||||
MWMechanics::ActiveSpells& activeSpells = getPtr().getClass().getCreatureStats(getPtr()).getActiveSpells();
|
||||
activeSpells.clear();
|
||||
|
||||
// Proceed by adding spells active
|
||||
addSpellsActive();
|
||||
}
|
||||
|
||||
MWWorld::Ptr DedicatedActor::getPtr()
|
||||
{
|
||||
return ptr;
|
||||
|
|
|
@ -29,6 +29,10 @@ namespace mwmp
|
|||
bool hasItem(std::string itemId, int charge);
|
||||
void equipItem(std::string itemId, int charge, bool noSound = false);
|
||||
|
||||
void addSpellsActive();
|
||||
void removeSpellsActive();
|
||||
void setSpellsActive();
|
||||
|
||||
MWWorld::Ptr getPtr();
|
||||
void setPtr(const MWWorld::Ptr& newPtr);
|
||||
|
||||
|
|
|
@ -285,6 +285,49 @@ void LocalActor::sendEquipment()
|
|||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_EQUIPMENT)->Send();
|
||||
}
|
||||
|
||||
void LocalActor::sendSpellsActiveAddition(const std::string id, ESM::ActiveSpells::ActiveSpellParams params)
|
||||
{
|
||||
// Skip any bugged spells that somehow have clientside-only dynamic IDs
|
||||
if (id.find("$dynamic") != std::string::npos)
|
||||
return;
|
||||
|
||||
spellsActiveChanges.activeSpells.clear();
|
||||
|
||||
mwmp::ActiveSpell spell;
|
||||
spell.id = id;
|
||||
spell.params = params;
|
||||
spellsActiveChanges.activeSpells.push_back(spell);
|
||||
|
||||
spellsActiveChanges.action = mwmp::SpellsActiveChanges::ADD;
|
||||
|
||||
ActorList actorList;
|
||||
actorList.cell = cell;
|
||||
actorList.addActor(*this);
|
||||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_SPELLS_ACTIVE)->setActorList(&actorList);
|
||||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_SPELLS_ACTIVE)->Send();
|
||||
}
|
||||
|
||||
void LocalActor::sendSpellsActiveRemoval(const std::string id)
|
||||
{
|
||||
// Skip any bugged spells that somehow have clientside-only dynamic IDs
|
||||
if (id.find("$dynamic") != std::string::npos)
|
||||
return;
|
||||
|
||||
spellsActiveChanges.activeSpells.clear();
|
||||
|
||||
mwmp::ActiveSpell spell;
|
||||
spell.id = id;
|
||||
spellsActiveChanges.activeSpells.push_back(spell);
|
||||
|
||||
spellsActiveChanges.action = mwmp::SpellsActiveChanges::REMOVE;
|
||||
|
||||
ActorList actorList;
|
||||
actorList.cell = cell;
|
||||
actorList.addActor(*this);
|
||||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_SPELLS_ACTIVE)->setActorList(&actorList);
|
||||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_SPELLS_ACTIVE)->Send();
|
||||
}
|
||||
|
||||
void LocalActor::sendDeath(char newDeathState)
|
||||
{
|
||||
deathState = newDeathState;
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace mwmp
|
|||
void updateAttackOrCast();
|
||||
|
||||
void sendEquipment();
|
||||
void sendSpellsActiveAddition(const std::string id, ESM::ActiveSpells::ActiveSpellParams params);
|
||||
void sendSpellsActiveRemoval(const std::string id);
|
||||
void sendDeath(char newDeathState);
|
||||
|
||||
MWWorld::Ptr getPtr();
|
||||
|
|
|
@ -589,3 +589,13 @@ MWWorld::Ptr MechanicsHelper::getItemPtrFromStore(const mwmp::Item& item, MWWorl
|
|||
|
||||
return closestPtr;
|
||||
}
|
||||
|
||||
MWWorld::Ptr MechanicsHelper::getCurrentActor()
|
||||
{
|
||||
return currentActor;
|
||||
}
|
||||
|
||||
void MechanicsHelper::storeCurrentActor(const MWWorld::Ptr& actor)
|
||||
{
|
||||
currentActor = actor;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,11 @@ namespace MechanicsHelper
|
|||
void unequipItemsByEffect(const MWWorld::Ptr& ptr, short enchantmentType, short effectId, short attributeId = -1, short skillId = -1);
|
||||
|
||||
MWWorld::Ptr getItemPtrFromStore(const mwmp::Item& item, MWWorld::ContainerStore& store);
|
||||
|
||||
MWWorld::Ptr getCurrentActor();
|
||||
void storeCurrentActor(const MWWorld::Ptr& actor);
|
||||
|
||||
static MWWorld::Ptr currentActor;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
#include "actor/ProcessorActorList.hpp"
|
||||
#include "actor/ProcessorActorPosition.hpp"
|
||||
#include "actor/ProcessorActorSpeech.hpp"
|
||||
#include "actor/ProcessorActorSpellsActive.hpp"
|
||||
#include "actor/ProcessorActorStatsDynamic.hpp"
|
||||
#include "actor/ProcessorActorTest.hpp"
|
||||
|
||||
|
@ -190,6 +191,7 @@ void ProcessorInitializer()
|
|||
ActorProcessor::AddProcessor(new ProcessorActorList());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorPosition());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorSpeech());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorSpellsActive());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic());
|
||||
ActorProcessor::AddProcessor(new ProcessorActorTest());
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef OPENMW_PROCESSORACTORSPELLSACTIVE_HPP
|
||||
#define OPENMW_PROCESSORACTORSPELLSACTIVE_HPP
|
||||
|
||||
#include "../ActorProcessor.hpp"
|
||||
#include "apps/openmw/mwmp/Main.hpp"
|
||||
#include "apps/openmw/mwmp/CellController.hpp"
|
||||
|
||||
namespace mwmp
|
||||
{
|
||||
class ProcessorActorSpellsActive final: public ActorProcessor
|
||||
{
|
||||
public:
|
||||
ProcessorActorSpellsActive()
|
||||
{
|
||||
BPP_INIT(ID_ACTOR_SPELLS_ACTIVE);
|
||||
}
|
||||
|
||||
virtual void Do(ActorPacket &packet, ActorList &actorList)
|
||||
{
|
||||
Main::get().getCellController()->readSpellsActive(actorList);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //OPENMW_PROCESSORACTORSPELLSACTIVE_HPP
|
|
@ -58,6 +58,7 @@ namespace mwmp
|
|||
bool hasStatsDynamicData;
|
||||
|
||||
Item equipmentItems[19];
|
||||
SpellsActiveChanges spellsActiveChanges;
|
||||
};
|
||||
|
||||
class BaseActorList
|
||||
|
|
|
@ -11,5 +11,51 @@ PacketActorSpellsActive::PacketActorSpellsActive(RakNet::RakPeerInterface *peer)
|
|||
|
||||
void PacketActorSpellsActive::Actor(BaseActor &actor, bool send)
|
||||
{
|
||||
// Placeholder
|
||||
RW(actor.spellsActiveChanges.action, send);
|
||||
|
||||
uint32_t count;
|
||||
|
||||
if (send)
|
||||
count = static_cast<uint32_t>(actor.spellsActiveChanges.activeSpells.size());
|
||||
|
||||
RW(count, send);
|
||||
|
||||
if (!send)
|
||||
{
|
||||
actor.spellsActiveChanges.activeSpells.clear();
|
||||
actor.spellsActiveChanges.activeSpells.resize(count);
|
||||
}
|
||||
|
||||
for (auto&& activeSpell : actor.spellsActiveChanges.activeSpells)
|
||||
{
|
||||
RW(activeSpell.id, send, true);
|
||||
RW(activeSpell.params.mDisplayName, send, true);
|
||||
|
||||
uint32_t effectCount;
|
||||
|
||||
if (send)
|
||||
effectCount = static_cast<uint32_t>(activeSpell.params.mEffects.size());
|
||||
|
||||
RW(effectCount, send);
|
||||
|
||||
if (effectCount > maxEffects)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!send)
|
||||
{
|
||||
activeSpell.params.mEffects.clear();
|
||||
activeSpell.params.mEffects.resize(effectCount);
|
||||
}
|
||||
|
||||
for (auto&& effect : activeSpell.params.mEffects)
|
||||
{
|
||||
RW(effect.mEffectId, send);
|
||||
RW(effect.mArg, send);
|
||||
RW(effect.mMagnitude, send);
|
||||
RW(effect.mDuration, send);
|
||||
RW(effect.mTimeLeft, send);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ namespace mwmp
|
|||
PacketActorSpellsActive(RakNet::RakPeerInterface *peer);
|
||||
|
||||
virtual void Actor(BaseActor &actor, bool send);
|
||||
|
||||
protected:
|
||||
static const int maxEffects = 20;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue