[General] Implement ActorSpellsActive packet, part 1

The packet can now set the active spells of DedicatedActors.
pull/593/head
David Cernat 4 years ago
parent f6887559f6
commit bf0a42fdad

@ -84,8 +84,8 @@ set(PROCESSORS_ACTOR
processors/actor/ProcessorActorCast.hpp processors/actor/ProcessorActorCellChange.hpp processors/actor/ProcessorActorCast.hpp processors/actor/ProcessorActorCellChange.hpp
processors/actor/ProcessorActorDeath.hpp processors/actor/ProcessorActorEquipment.hpp processors/actor/ProcessorActorDeath.hpp processors/actor/ProcessorActorEquipment.hpp
processors/actor/ProcessorActorList.hpp processors/actor/ProcessorActorPosition.hpp processors/actor/ProcessorActorList.hpp processors/actor/ProcessorActorPosition.hpp
processors/actor/ProcessorActorSpeech.hpp processors/actor/ProcessorActorStatsDynamic.hpp processors/actor/ProcessorActorSpeech.hpp processors/actor/ProcessorActorSpellsActive.hpp
processors/actor/ProcessorActorTest.hpp processors/actor/ProcessorActorStatsDynamic.hpp processors/actor/ProcessorActorTest.hpp
) )
source_group(tes3mp-server\\processors\\actor FILES ${PROCESSORS_ACTOR}) source_group(tes3mp-server\\processors\\actor FILES ${PROCESSORS_ACTOR})

@ -207,6 +207,7 @@ public:
{"OnActorEquipment", Callback<unsigned short, const char*>()}, {"OnActorEquipment", Callback<unsigned short, const char*>()},
{"OnActorAI", Callback<unsigned short, const char*>()}, {"OnActorAI", Callback<unsigned short, const char*>()},
{"OnActorDeath", Callback<unsigned short, const char*>()}, {"OnActorDeath", Callback<unsigned short, const char*>()},
{"OnActorSpellsActive", Callback<unsigned short, const char*>()},
{"OnActorCellChange", Callback<unsigned short, const char*>()}, {"OnActorCellChange", Callback<unsigned short, const char*>()},
{"OnActorTest", Callback<unsigned short, const char*>()}, {"OnActorTest", Callback<unsigned short, const char*>()},
{"OnPlayerSendMessage", Callback<unsigned short, const char*>()}, {"OnPlayerSendMessage", Callback<unsigned short, const char*>()},

@ -51,9 +51,10 @@
#include "actor/ProcessorActorCellChange.hpp" #include "actor/ProcessorActorCellChange.hpp"
#include "actor/ProcessorActorDeath.hpp" #include "actor/ProcessorActorDeath.hpp"
#include "actor/ProcessorActorEquipment.hpp" #include "actor/ProcessorActorEquipment.hpp"
#include "actor/ProcessorActorStatsDynamic.hpp"
#include "actor/ProcessorActorPosition.hpp" #include "actor/ProcessorActorPosition.hpp"
#include "actor/ProcessorActorSpeech.hpp" #include "actor/ProcessorActorSpeech.hpp"
#include "actor/ProcessorActorSpellsActive.hpp"
#include "actor/ProcessorActorStatsDynamic.hpp"
#include "ObjectProcessor.hpp" #include "ObjectProcessor.hpp"
#include "object/ProcessorConsoleCommand.hpp" #include "object/ProcessorConsoleCommand.hpp"
#include "object/ProcessorContainer.hpp" #include "object/ProcessorContainer.hpp"
@ -137,6 +138,7 @@ void ProcessorInitializer()
ActorProcessor::AddProcessor(new ProcessorActorEquipment()); ActorProcessor::AddProcessor(new ProcessorActorEquipment());
ActorProcessor::AddProcessor(new ProcessorActorPosition()); ActorProcessor::AddProcessor(new ProcessorActorPosition());
ActorProcessor::AddProcessor(new ProcessorActorSpeech()); ActorProcessor::AddProcessor(new ProcessorActorSpeech());
ActorProcessor::AddProcessor(new ProcessorActorSpellsActive());
ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic()); ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic());
ActorProcessor::AddProcessor(new ProcessorActorTest()); 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 add_openmw_dir (mwmp/processors/actor ProcessorActorAI ProcessorActorAnimFlags ProcessorActorAnimPlay ProcessorActorAttack
ProcessorActorAuthority ProcessorActorCast ProcessorActorCellChange ProcessorActorDeath ProcessorActorEquipment 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 add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageBox ProcessorUserDisconnected

@ -15,6 +15,8 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwmp/Main.hpp" #include "../mwmp/Main.hpp"
#include "../mwmp/LocalPlayer.hpp" #include "../mwmp/LocalPlayer.hpp"
#include "../mwmp/CellController.hpp"
#include "../mwmp/MechanicsHelper.hpp"
/* /*
End of tes3mp addition End of tes3mp addition
*/ */
@ -47,6 +49,10 @@ namespace MWMechanics
{ {
mwmp::Main::get().getLocalPlayer()->sendSpellsActiveRemoval(iter->first); 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 End of tes3mp addition
*/ */
@ -205,6 +211,10 @@ namespace MWMechanics
{ {
mwmp::Main::get().getLocalPlayer()->sendSpellsActiveAddition(id, esmParams); 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 End of tes3mp addition
*/ */

@ -2123,6 +2123,16 @@ namespace MWMechanics
End of tes3mp change (major) 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); iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
const Misc::TimerStatus engageCombatTimerStatus = iter->second->updateEngageCombatTimer(duration); const Misc::TimerStatus engageCombatTimerStatus = iter->second->updateEngageCombatTimer(duration);
@ -2528,6 +2538,16 @@ namespace MWMechanics
{ {
if (iter->first.getClass().getCreatureStats(iter->first).isDead()) 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); iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
continue; continue;
} }
@ -2547,6 +2567,17 @@ namespace MWMechanics
if (iter->first.getClass().isNpc()) if (iter->first.getClass().isNpc())
calculateNpcStatModifiers(iter->first, duration); 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); iter->first.getClass().getCreatureStats(iter->first).getActiveSpells().update(duration);
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first); MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first);

@ -286,6 +286,36 @@ void Cell::readSpeech(ActorList& actorList)
uninitializeDedicatedActors(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) void Cell::readAi(ActorList& actorList)
{ {
initializeDedicatedActors(actorList); initializeDedicatedActors(actorList);

@ -25,6 +25,7 @@ namespace mwmp
void readDeath(ActorList& actorList); void readDeath(ActorList& actorList);
void readEquipment(ActorList& actorList); void readEquipment(ActorList& actorList);
void readSpeech(ActorList& actorList); void readSpeech(ActorList& actorList);
void readSpellsActive(ActorList& actorList);
void readAi(ActorList& actorList); void readAi(ActorList& actorList);
void readAttack(ActorList& actorList); void readAttack(ActorList& actorList);
void readCast(ActorList& actorList); void readCast(ActorList& actorList);

@ -211,6 +211,17 @@ void CellController::readSpeech(ActorList& actorList)
cellsInitialized[mapIndex]->readSpeech(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) void CellController::readAi(ActorList& actorList)
{ {
std::string mapIndex = actorList.cell.getDescription(); std::string mapIndex = actorList.cell.getDescription();

@ -30,6 +30,7 @@ namespace mwmp
void readDeath(mwmp::ActorList& actorList); void readDeath(mwmp::ActorList& actorList);
void readEquipment(mwmp::ActorList& actorList); void readEquipment(mwmp::ActorList& actorList);
void readSpeech(mwmp::ActorList& actorList); void readSpeech(mwmp::ActorList& actorList);
void readSpellsActive(mwmp::ActorList& actorList);
void readAi(mwmp::ActorList& actorList); void readAi(mwmp::ActorList& actorList);
void readAttack(mwmp::ActorList& actorList); void readAttack(mwmp::ActorList& actorList);
void readCast(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() MWWorld::Ptr DedicatedActor::getPtr()
{ {
return ptr; return ptr;

@ -29,6 +29,10 @@ namespace mwmp
bool hasItem(std::string itemId, int charge); bool hasItem(std::string itemId, int charge);
void equipItem(std::string itemId, int charge, bool noSound = false); void equipItem(std::string itemId, int charge, bool noSound = false);
void addSpellsActive();
void removeSpellsActive();
void setSpellsActive();
MWWorld::Ptr getPtr(); MWWorld::Ptr getPtr();
void setPtr(const MWWorld::Ptr& newPtr); void setPtr(const MWWorld::Ptr& newPtr);

@ -285,6 +285,49 @@ void LocalActor::sendEquipment()
Main::get().getNetworking()->getActorPacket(ID_ACTOR_EQUIPMENT)->Send(); 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) void LocalActor::sendDeath(char newDeathState)
{ {
deathState = newDeathState; deathState = newDeathState;

@ -26,6 +26,8 @@ namespace mwmp
void updateAttackOrCast(); void updateAttackOrCast();
void sendEquipment(); void sendEquipment();
void sendSpellsActiveAddition(const std::string id, ESM::ActiveSpells::ActiveSpellParams params);
void sendSpellsActiveRemoval(const std::string id);
void sendDeath(char newDeathState); void sendDeath(char newDeathState);
MWWorld::Ptr getPtr(); MWWorld::Ptr getPtr();

@ -589,3 +589,13 @@ MWWorld::Ptr MechanicsHelper::getItemPtrFromStore(const mwmp::Item& item, MWWorl
return closestPtr; 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); 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 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/ProcessorActorList.hpp"
#include "actor/ProcessorActorPosition.hpp" #include "actor/ProcessorActorPosition.hpp"
#include "actor/ProcessorActorSpeech.hpp" #include "actor/ProcessorActorSpeech.hpp"
#include "actor/ProcessorActorSpellsActive.hpp"
#include "actor/ProcessorActorStatsDynamic.hpp" #include "actor/ProcessorActorStatsDynamic.hpp"
#include "actor/ProcessorActorTest.hpp" #include "actor/ProcessorActorTest.hpp"
@ -190,6 +191,7 @@ void ProcessorInitializer()
ActorProcessor::AddProcessor(new ProcessorActorList()); ActorProcessor::AddProcessor(new ProcessorActorList());
ActorProcessor::AddProcessor(new ProcessorActorPosition()); ActorProcessor::AddProcessor(new ProcessorActorPosition());
ActorProcessor::AddProcessor(new ProcessorActorSpeech()); ActorProcessor::AddProcessor(new ProcessorActorSpeech());
ActorProcessor::AddProcessor(new ProcessorActorSpellsActive());
ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic()); ActorProcessor::AddProcessor(new ProcessorActorStatsDynamic());
ActorProcessor::AddProcessor(new ProcessorActorTest()); 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; bool hasStatsDynamicData;
Item equipmentItems[19]; Item equipmentItems[19];
SpellsActiveChanges spellsActiveChanges;
}; };
class BaseActorList class BaseActorList

@ -11,5 +11,51 @@ PacketActorSpellsActive::PacketActorSpellsActive(RakNet::RakPeerInterface *peer)
void PacketActorSpellsActive::Actor(BaseActor &actor, bool send) 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); PacketActorSpellsActive(RakNet::RakPeerInterface *peer);
virtual void Actor(BaseActor &actor, bool send); virtual void Actor(BaseActor &actor, bool send);
protected:
static const int maxEffects = 20;
}; };
} }

Loading…
Cancel
Save