2017-04-06 01:00:50 +00:00
|
|
|
#include <components/esm/cellid.hpp>
|
2019-08-19 18:39:33 +00:00
|
|
|
#include <components/openmw-mp/TimedLog.hpp>
|
2017-04-06 01:00:50 +00:00
|
|
|
|
2017-05-31 04:52:45 +00:00
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
|
2017-05-02 00:31:40 +00:00
|
|
|
#include "../mwworld/class.hpp"
|
|
|
|
#include "../mwworld/livecellref.hpp"
|
2017-04-08 09:54:38 +00:00
|
|
|
#include "../mwworld/worldimp.hpp"
|
|
|
|
|
2017-04-06 01:00:50 +00:00
|
|
|
#include "Cell.hpp"
|
|
|
|
#include "Main.hpp"
|
2017-04-06 08:46:56 +00:00
|
|
|
#include "Networking.hpp"
|
2017-05-04 23:46:16 +00:00
|
|
|
#include "LocalPlayer.hpp"
|
2017-04-19 19:10:06 +00:00
|
|
|
#include "CellController.hpp"
|
|
|
|
#include "MechanicsHelper.hpp"
|
|
|
|
|
2017-04-06 01:00:50 +00:00
|
|
|
using namespace mwmp;
|
|
|
|
|
|
|
|
mwmp::Cell::Cell(MWWorld::CellStore* cellStore)
|
|
|
|
{
|
|
|
|
store = cellStore;
|
2017-05-04 23:46:16 +00:00
|
|
|
shouldInitializeActors = false;
|
2017-04-06 01:00:50 +00:00
|
|
|
|
2017-06-10 00:29:51 +00:00
|
|
|
updateTimer = 0;
|
2017-04-06 01:00:50 +00:00
|
|
|
}
|
|
|
|
|
2017-07-03 15:41:16 +00:00
|
|
|
Cell::~Cell()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-04-10 14:10:18 +00:00
|
|
|
void Cell::updateLocal(bool forceUpdate)
|
2017-04-06 01:00:50 +00:00
|
|
|
{
|
2017-06-10 00:29:51 +00:00
|
|
|
if (localActors.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const float timeoutSec = 0.025;
|
|
|
|
|
|
|
|
if (!forceUpdate && (updateTimer += MWBase::Environment::get().getFrameDuration()) < timeoutSec)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
updateTimer = 0;
|
2017-04-06 08:46:56 +00:00
|
|
|
|
2017-05-05 01:58:44 +00:00
|
|
|
CellController *cellController = Main::get().getCellController();
|
2017-04-09 13:32:44 +00:00
|
|
|
ActorList *actorList = mwmp::Main::get().getNetworking()->getActorList();
|
|
|
|
actorList->reset();
|
|
|
|
|
|
|
|
actorList->cell = *store->getCell();
|
2017-04-06 08:46:56 +00:00
|
|
|
|
2017-06-27 13:56:24 +00:00
|
|
|
for (auto it = localActors.begin(); it != localActors.end();)
|
2017-04-06 01:00:50 +00:00
|
|
|
{
|
|
|
|
LocalActor *actor = it->second;
|
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
MWWorld::CellStore *newStore = actor->getPtr().getCell();
|
|
|
|
|
|
|
|
if (newStore != store)
|
2017-04-06 01:00:50 +00:00
|
|
|
{
|
2017-04-23 10:59:15 +00:00
|
|
|
actor->updateCell();
|
2017-05-05 00:52:41 +00:00
|
|
|
std::string mapIndex = it->first;
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2017-05-05 00:52:41 +00:00
|
|
|
// If the cell this actor has moved to is under our authority, move them to it
|
2017-05-05 01:58:44 +00:00
|
|
|
if (cellController->hasLocalAuthority(actor->cell))
|
2017-05-05 00:52:41 +00:00
|
|
|
{
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Moving LocalActor %s to our authority in %s",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), actor->cell.getShortDescription().c_str());
|
2017-05-05 01:58:44 +00:00
|
|
|
Cell *newCell = cellController->getCell(actor->cell);
|
2017-05-05 00:52:41 +00:00
|
|
|
newCell->localActors[mapIndex] = actor;
|
2021-09-17 17:14:55 +00:00
|
|
|
cellController->setLocalActorRecord(mapIndex, newCell->getShortDescription());
|
2017-05-05 00:52:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Deleting LocalActor %s which is no longer under our authority",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), getShortDescription().c_str());
|
2017-05-05 01:58:44 +00:00
|
|
|
cellController->removeLocalActorRecord(mapIndex);
|
2017-05-05 00:52:41 +00:00
|
|
|
delete actor;
|
|
|
|
}
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2017-04-06 01:00:50 +00:00
|
|
|
localActors.erase(it++);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-03-25 09:26:15 +00:00
|
|
|
if (actor->getPtr().getRefData().isEnabled())
|
|
|
|
{
|
|
|
|
if (actor->getPtr().getRefData().isDeleted())
|
|
|
|
{
|
|
|
|
std::string mapIndex = it->first;
|
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Deleting LocalActor %s whose reference has been deleted",
|
|
|
|
mapIndex.c_str(), getShortDescription().c_str());
|
|
|
|
cellController->removeLocalActorRecord(mapIndex);
|
|
|
|
delete actor;
|
|
|
|
localActors.erase(it++);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Forcibly update this local actor if its data has never been sent before;
|
|
|
|
// otherwise, use the current forceUpdate value
|
|
|
|
actor->update(actor->hasSentData ? forceUpdate : true);
|
|
|
|
}
|
|
|
|
}
|
2017-04-13 15:59:22 +00:00
|
|
|
|
2017-04-06 01:00:50 +00:00
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
2017-04-06 08:46:56 +00:00
|
|
|
|
2017-04-10 14:10:18 +00:00
|
|
|
actorList->sendPositionActors();
|
2017-04-15 08:45:20 +00:00
|
|
|
actorList->sendAnimFlagsActors();
|
2017-04-15 10:42:30 +00:00
|
|
|
actorList->sendAnimPlayActors();
|
2017-04-16 15:43:13 +00:00
|
|
|
actorList->sendSpeechActors();
|
2018-06-27 18:47:55 +00:00
|
|
|
actorList->sendDeathActors();
|
2017-04-16 13:42:07 +00:00
|
|
|
actorList->sendStatsDynamicActors();
|
2017-05-26 01:37:49 +00:00
|
|
|
actorList->sendEquipmentActors();
|
2017-04-19 19:10:06 +00:00
|
|
|
actorList->sendAttackActors();
|
2019-08-25 06:35:23 +00:00
|
|
|
actorList->sendCastActors();
|
2017-04-24 07:59:47 +00:00
|
|
|
actorList->sendCellChangeActors();
|
2017-04-06 01:00:50 +00:00
|
|
|
}
|
|
|
|
|
2017-04-07 12:51:34 +00:00
|
|
|
void Cell::updateDedicated(float dt)
|
|
|
|
{
|
|
|
|
if (dedicatedActors.empty()) return;
|
2017-06-27 13:56:24 +00:00
|
|
|
|
2017-06-27 14:27:02 +00:00
|
|
|
for (auto &actor : dedicatedActors)
|
2017-06-27 13:56:24 +00:00
|
|
|
actor.second->update(dt);
|
2017-06-10 12:49:00 +00:00
|
|
|
|
|
|
|
// Are we the authority over this cell? If so, uninitialize DedicatedActors
|
|
|
|
// after the above update
|
|
|
|
if (hasLocalAuthority())
|
|
|
|
uninitializeDedicatedActors();
|
2017-04-07 12:51:34 +00:00
|
|
|
}
|
|
|
|
|
2017-04-10 14:10:18 +00:00
|
|
|
void Cell::readPositions(ActorList& actorList)
|
2017-04-06 08:46:56 +00:00
|
|
|
{
|
2017-04-10 14:10:18 +00:00
|
|
|
initializeDedicatedActors(actorList);
|
2018-09-05 17:03:35 +00:00
|
|
|
|
|
|
|
if (dedicatedActors.empty()) return;
|
2017-04-10 14:10:18 +00:00
|
|
|
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-06 08:46:56 +00:00
|
|
|
{
|
2017-04-09 13:32:44 +00:00
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
2017-04-06 08:46:56 +00:00
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
2017-04-10 04:22:03 +00:00
|
|
|
actor->position = baseActor.position;
|
2017-04-10 14:10:18 +00:00
|
|
|
actor->direction = baseActor.direction;
|
2017-05-01 18:55:50 +00:00
|
|
|
|
|
|
|
if (!actor->hasPositionData)
|
|
|
|
{
|
|
|
|
actor->hasPositionData = true;
|
|
|
|
|
|
|
|
// If this is our first packet about this actor's position, force an update
|
|
|
|
// now instead of waiting for its frame
|
|
|
|
//
|
|
|
|
// That way, if this actor is about to become a LocalActor, initial data about it
|
|
|
|
// received from the server still gets set
|
|
|
|
actor->setPosition();
|
|
|
|
}
|
2017-04-06 08:46:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-15 07:47:53 +00:00
|
|
|
void Cell::readAnimFlags(ActorList& actorList)
|
2017-04-13 12:26:48 +00:00
|
|
|
{
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-13 12:26:48 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->movementFlags = baseActor.movementFlags;
|
|
|
|
actor->drawState = baseActor.drawState;
|
|
|
|
actor->isFlying = baseActor.isFlying;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-15 10:42:30 +00:00
|
|
|
void Cell::readAnimPlay(ActorList& actorList)
|
|
|
|
{
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-15 10:42:30 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->animation.groupname = baseActor.animation.groupname;
|
|
|
|
actor->animation.mode = baseActor.animation.mode;
|
|
|
|
actor->animation.count = baseActor.animation.count;
|
|
|
|
actor->animation.persist = baseActor.animation.persist;
|
2018-08-16 00:50:41 +00:00
|
|
|
actor->playAnimation();
|
2017-04-15 10:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-16 13:42:07 +00:00
|
|
|
void Cell::readStatsDynamic(ActorList& actorList)
|
|
|
|
{
|
2017-04-29 14:43:37 +00:00
|
|
|
initializeDedicatedActors(actorList);
|
|
|
|
|
2018-09-05 17:03:35 +00:00
|
|
|
if (dedicatedActors.empty()) return;
|
|
|
|
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-16 13:42:07 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->creatureStats = baseActor.creatureStats;
|
2017-04-29 14:43:37 +00:00
|
|
|
|
|
|
|
if (!actor->hasStatsDynamicData)
|
|
|
|
{
|
|
|
|
actor->hasStatsDynamicData = true;
|
|
|
|
|
|
|
|
// If this is our first packet about this actor's dynamic stats, force an update
|
|
|
|
// now instead of waiting for its frame
|
|
|
|
//
|
|
|
|
// That way, if this actor is about to become a LocalActor, initial data about it
|
|
|
|
// received from the server still gets set
|
|
|
|
actor->setStatsDynamic();
|
2019-12-05 11:27:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-14 07:27:43 +00:00
|
|
|
|
2019-12-05 11:27:55 +00:00
|
|
|
void Cell::readDeath(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->creatureStats.mDead = true;
|
|
|
|
actor->creatureStats.mDynamic[0].mCurrent = 0;
|
|
|
|
|
|
|
|
Main::get().getCellController()->setQueuedDeathState(actor->getPtr(), baseActor.deathState);
|
|
|
|
|
2019-12-06 10:43:41 +00:00
|
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Received ID_ACTOR_DEATH about %s %i-%i in cell %s\n- deathState: %d\n-isInstantDeath: %s",
|
2021-09-17 17:14:55 +00:00
|
|
|
actor->refId.c_str(), actor->refNum, actor->mpNum, getShortDescription().c_str(),
|
2019-12-06 10:43:41 +00:00
|
|
|
baseActor.deathState, baseActor.isInstantDeath ? "true" : "false");
|
2019-12-05 11:27:55 +00:00
|
|
|
|
|
|
|
if (baseActor.isInstantDeath)
|
|
|
|
{
|
|
|
|
actor->getPtr().getClass().getCreatureStats(actor->getPtr()).setDeathAnimationFinished(true);
|
|
|
|
MWBase::Environment::get().getWorld()->enableActorCollision(actor->getPtr(), false);
|
2017-04-29 14:43:37 +00:00
|
|
|
}
|
2017-04-16 13:42:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-26 01:37:49 +00:00
|
|
|
void Cell::readEquipment(ActorList& actorList)
|
|
|
|
{
|
|
|
|
initializeDedicatedActors(actorList);
|
|
|
|
|
2018-09-05 17:03:35 +00:00
|
|
|
if (dedicatedActors.empty()) return;
|
|
|
|
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-05-26 01:37:49 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
|
|
|
|
for (int slot = 0; slot < 19; ++slot)
|
2018-04-20 19:46:16 +00:00
|
|
|
actor->equipmentItems[slot] = baseActor.equipmentItems[slot];
|
2017-05-26 01:37:49 +00:00
|
|
|
|
|
|
|
actor->setEquipment();
|
|
|
|
}
|
|
|
|
}
|
2018-08-16 00:50:41 +00:00
|
|
|
|
|
|
|
if (hasLocalAuthority())
|
|
|
|
uninitializeDedicatedActors(actorList);
|
2017-05-26 01:37:49 +00:00
|
|
|
}
|
|
|
|
|
2017-04-16 15:43:13 +00:00
|
|
|
void Cell::readSpeech(ActorList& actorList)
|
|
|
|
{
|
2018-08-13 17:39:03 +00:00
|
|
|
initializeDedicatedActors(actorList);
|
|
|
|
|
2018-09-05 17:03:35 +00:00
|
|
|
if (dedicatedActors.empty()) return;
|
|
|
|
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-16 15:43:13 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->sound = baseActor.sound;
|
2018-08-16 00:50:41 +00:00
|
|
|
actor->playSound();
|
2017-04-16 15:43:13 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-16 00:50:41 +00:00
|
|
|
|
|
|
|
if (hasLocalAuthority())
|
|
|
|
uninitializeDedicatedActors(actorList);
|
2017-04-16 15:43:13 +00:00
|
|
|
}
|
|
|
|
|
2021-04-20 01:25:14 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-07-12 17:48:47 +00:00
|
|
|
void Cell::readAi(ActorList& actorList)
|
2018-05-12 03:29:11 +00:00
|
|
|
{
|
|
|
|
initializeDedicatedActors(actorList);
|
|
|
|
|
2018-09-05 17:03:35 +00:00
|
|
|
if (dedicatedActors.empty()) return;
|
|
|
|
|
2018-05-12 03:29:11 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->aiAction = baseActor.aiAction;
|
2018-07-10 02:07:58 +00:00
|
|
|
actor->aiDistance = baseActor.aiDistance;
|
|
|
|
actor->aiDuration = baseActor.aiDuration;
|
2018-07-10 20:18:32 +00:00
|
|
|
actor->aiShouldRepeat = baseActor.aiShouldRepeat;
|
2018-07-10 02:07:58 +00:00
|
|
|
actor->aiCoordinates = baseActor.aiCoordinates;
|
2018-07-09 22:35:38 +00:00
|
|
|
actor->hasAiTarget = baseActor.hasAiTarget;
|
2018-05-12 03:29:11 +00:00
|
|
|
actor->aiTarget = baseActor.aiTarget;
|
2018-07-12 17:48:47 +00:00
|
|
|
actor->setAi();
|
2018-05-12 03:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-16 00:50:41 +00:00
|
|
|
|
|
|
|
if (hasLocalAuthority())
|
|
|
|
uninitializeDedicatedActors(actorList);
|
2018-05-12 03:29:11 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 19:10:06 +00:00
|
|
|
void Cell::readAttack(ActorList& actorList)
|
|
|
|
{
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-19 19:10:06 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Reading ActorAttack about %s", mapIndex.c_str());
|
2019-06-19 05:24:53 +00:00
|
|
|
|
2017-04-19 19:10:06 +00:00
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->attack = baseActor.attack;
|
2017-05-27 01:19:28 +00:00
|
|
|
|
2019-08-25 06:35:23 +00:00
|
|
|
MechanicsHelper::processAttack(actor->attack, actor->getPtr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cell::readCast(ActorList& actorList)
|
|
|
|
{
|
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
|
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Reading ActorCast about %s", mapIndex.c_str());
|
|
|
|
|
|
|
|
DedicatedActor *actor = dedicatedActors[mapIndex];
|
|
|
|
actor->cast = baseActor.cast;
|
|
|
|
|
|
|
|
// Set the correct drawState here if we've somehow we've missed a previous
|
|
|
|
// AnimFlags packet
|
2019-11-28 17:53:34 +00:00
|
|
|
if (actor->drawState != MWMechanics::DrawState_::DrawState_Spell)
|
2017-05-27 01:19:28 +00:00
|
|
|
{
|
2019-06-19 05:24:53 +00:00
|
|
|
actor->drawState = MWMechanics::DrawState_::DrawState_Spell;
|
2017-05-27 01:19:28 +00:00
|
|
|
actor->setAnimFlags();
|
|
|
|
}
|
|
|
|
|
2019-08-25 06:35:23 +00:00
|
|
|
MechanicsHelper::processCast(actor->cast, actor->getPtr());
|
2017-04-19 19:10:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
void Cell::readCellChange(ActorList& actorList)
|
|
|
|
{
|
|
|
|
initializeDedicatedActors(actorList);
|
|
|
|
|
2018-09-05 17:03:35 +00:00
|
|
|
if (dedicatedActors.empty()) return;
|
|
|
|
|
2017-05-05 01:58:44 +00:00
|
|
|
CellController *cellController = Main::get().getCellController();
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-23 10:59:15 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
2018-01-07 23:37:01 +00:00
|
|
|
// Is a packet mistakenly moving the actor to the cell it's already in? If so, ignore it
|
2021-09-17 17:14:55 +00:00
|
|
|
if (Misc::StringUtils::ciEqual(getShortDescription(), baseActor.cell.getShortDescription()))
|
2018-01-07 23:37:01 +00:00
|
|
|
{
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_WARN, "Server says DedicatedActor %s moved to %s, but it was already there",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), getShortDescription().c_str());
|
2018-01-07 23:37:01 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
if (dedicatedActors.count(mapIndex) > 0)
|
|
|
|
{
|
2017-05-05 04:37:09 +00:00
|
|
|
DedicatedActor *dedicatedActor = dedicatedActors[mapIndex];
|
|
|
|
dedicatedActor->cell = baseActor.cell;
|
|
|
|
dedicatedActor->position = baseActor.position;
|
|
|
|
dedicatedActor->direction = baseActor.direction;
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_VERBOSE, "Server says DedicatedActor %s moved to %s",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), dedicatedActor->cell.getShortDescription().c_str());
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2017-05-05 04:37:09 +00:00
|
|
|
MWWorld::CellStore *newStore = cellController->getCellStore(dedicatedActor->cell);
|
|
|
|
dedicatedActor->setCell(newStore);
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2017-05-05 01:58:44 +00:00
|
|
|
// If the cell this actor has moved to is active and not under our authority, move them to it
|
2017-05-05 04:37:09 +00:00
|
|
|
if (cellController->isActiveWorldCell(dedicatedActor->cell) && !cellController->hasLocalAuthority(dedicatedActor->cell))
|
2017-05-05 00:52:41 +00:00
|
|
|
{
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Moving DedicatedActor %s to our active cell %s",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), dedicatedActor->cell.getShortDescription().c_str());
|
2017-05-05 16:54:20 +00:00
|
|
|
cellController->initializeCell(dedicatedActor->cell);
|
2017-05-05 04:37:09 +00:00
|
|
|
Cell *newCell = cellController->getCell(dedicatedActor->cell);
|
|
|
|
newCell->dedicatedActors[mapIndex] = dedicatedActor;
|
2021-09-17 17:14:55 +00:00
|
|
|
cellController->setDedicatedActorRecord(mapIndex, newCell->getShortDescription());
|
2017-05-05 00:52:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-05 04:37:09 +00:00
|
|
|
if (cellController->hasLocalAuthority(dedicatedActor->cell))
|
|
|
|
{
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Creating new LocalActor based on %s in %s",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), dedicatedActor->cell.getShortDescription().c_str());
|
2017-05-05 04:37:09 +00:00
|
|
|
Cell *newCell = cellController->getCell(dedicatedActor->cell);
|
|
|
|
LocalActor *localActor = new LocalActor();
|
|
|
|
localActor->cell = dedicatedActor->cell;
|
|
|
|
localActor->setPtr(dedicatedActor->getPtr());
|
|
|
|
localActor->position = dedicatedActor->position;
|
|
|
|
localActor->direction = dedicatedActor->direction;
|
|
|
|
localActor->movementFlags = dedicatedActor->movementFlags;
|
|
|
|
localActor->drawState = dedicatedActor->drawState;
|
|
|
|
localActor->isFlying = dedicatedActor->isFlying;
|
|
|
|
localActor->creatureStats = dedicatedActor->creatureStats;
|
|
|
|
|
|
|
|
newCell->localActors[mapIndex] = localActor;
|
2021-09-17 17:14:55 +00:00
|
|
|
cellController->setLocalActorRecord(mapIndex, newCell->getShortDescription());
|
2017-05-05 04:37:09 +00:00
|
|
|
}
|
|
|
|
|
2019-08-19 18:39:33 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Deleting DedicatedActor %s which is no longer needed",
|
2021-09-17 17:14:55 +00:00
|
|
|
mapIndex.c_str(), getShortDescription().c_str());
|
2017-05-05 01:58:44 +00:00
|
|
|
cellController->removeDedicatedActorRecord(mapIndex);
|
2017-05-05 04:37:09 +00:00
|
|
|
delete dedicatedActor;
|
2017-05-05 00:52:41 +00:00
|
|
|
}
|
2017-04-23 10:59:15 +00:00
|
|
|
|
|
|
|
dedicatedActors.erase(mapIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cell::initializeLocalActor(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
2019-01-05 21:27:35 +00:00
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(ptr);
|
2021-09-17 17:14:55 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Initializing LocalActor %s in %s", mapIndex.c_str(), getShortDescription().c_str());
|
2019-01-05 21:27:35 +00:00
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
LocalActor *actor = new LocalActor();
|
|
|
|
actor->cell = *store->getCell();
|
|
|
|
actor->setPtr(ptr);
|
|
|
|
|
|
|
|
localActors[mapIndex] = actor;
|
|
|
|
|
2021-09-17 17:14:55 +00:00
|
|
|
Main::get().getCellController()->setLocalActorRecord(mapIndex, getShortDescription());
|
2017-04-23 10:59:15 +00:00
|
|
|
|
2021-09-17 17:14:55 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Successfully initialized LocalActor %s in %s", mapIndex.c_str(), getShortDescription().c_str());
|
2017-04-23 10:59:15 +00:00
|
|
|
}
|
|
|
|
|
2017-04-08 07:58:25 +00:00
|
|
|
void Cell::initializeLocalActors()
|
|
|
|
{
|
2021-09-17 17:14:55 +00:00
|
|
|
LOG_MESSAGE_SIMPLE(TimedLog::LOG_VERBOSE, "Initializing LocalActors in %s", getShortDescription().c_str());
|
2019-01-05 21:27:35 +00:00
|
|
|
|
2017-06-27 13:56:24 +00:00
|
|
|
for (const auto &mergedRef : store->getMergedRefs())
|
2017-04-08 07:58:25 +00:00
|
|
|
{
|
2017-06-27 13:56:24 +00:00
|
|
|
if (mergedRef->mClass->isActor())
|
2017-05-02 00:31:40 +00:00
|
|
|
{
|
2017-06-27 13:56:24 +00:00
|
|
|
MWWorld::Ptr ptr(mergedRef, store);
|
2017-04-24 08:58:39 +00:00
|
|
|
|
2017-05-02 00:31:40 +00:00
|
|
|
// If this Ptr is lacking a unique index, ignore it
|
|
|
|
if (ptr.getCellRef().getRefNum().mIndex == 0 && ptr.getCellRef().getMpNum() == 0) continue;
|
2017-04-28 20:17:23 +00:00
|
|
|
|
2019-12-05 18:27:48 +00:00
|
|
|
// If this Ptr is disabled or deleted, ignore it
|
|
|
|
if (!ptr.getRefData().isEnabled() || ptr.getRefData().isDeleted()) continue;
|
|
|
|
|
2017-05-04 23:46:16 +00:00
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(ptr);
|
|
|
|
|
|
|
|
// Only initialize this actor if it isn't already initialized
|
|
|
|
if (localActors.count(mapIndex) == 0)
|
|
|
|
initializeLocalActor(ptr);
|
2017-05-02 00:31:40 +00:00
|
|
|
}
|
2017-04-24 08:58:39 +00:00
|
|
|
}
|
2019-01-05 21:27:35 +00:00
|
|
|
|
2021-09-17 17:14:55 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Successfully initialized LocalActors in %s", getShortDescription().c_str());
|
2017-04-23 10:59:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Cell::initializeDedicatedActor(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
2019-01-05 21:27:35 +00:00
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(ptr);
|
2021-09-17 17:14:55 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Initializing DedicatedActor %s in %s", mapIndex.c_str(), getShortDescription().c_str());
|
2019-01-05 21:27:35 +00:00
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
DedicatedActor *actor = new DedicatedActor();
|
|
|
|
actor->cell = *store->getCell();
|
|
|
|
actor->setPtr(ptr);
|
2017-04-08 07:58:25 +00:00
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
dedicatedActors[mapIndex] = actor;
|
2017-04-08 07:58:25 +00:00
|
|
|
|
2021-09-17 17:14:55 +00:00
|
|
|
Main::get().getCellController()->setDedicatedActorRecord(mapIndex, getShortDescription());
|
2017-04-08 07:58:25 +00:00
|
|
|
|
2021-09-17 17:14:55 +00:00
|
|
|
LOG_APPEND(TimedLog::LOG_VERBOSE, "- Successfully initialized DedicatedActor %s in %s", mapIndex.c_str(), getShortDescription().c_str());
|
2017-04-10 14:10:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Cell::initializeDedicatedActors(ActorList& actorList)
|
|
|
|
{
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
2017-04-10 14:10:18 +00:00
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
|
|
|
|
// If this key doesn't exist, create it
|
|
|
|
if (dedicatedActors.count(mapIndex) == 0)
|
|
|
|
{
|
2022-03-23 07:51:05 +00:00
|
|
|
MWWorld::Ptr ptrFound = store->searchExact(baseActor.refNum, baseActor.mpNum, baseActor.refId, true);
|
2017-04-10 14:10:18 +00:00
|
|
|
|
2019-10-11 18:29:21 +00:00
|
|
|
if (!ptrFound) continue;
|
2017-04-10 14:10:18 +00:00
|
|
|
|
2017-04-23 10:59:15 +00:00
|
|
|
initializeDedicatedActor(ptrFound);
|
2017-04-10 14:10:18 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-08 07:58:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Cell::uninitializeLocalActors()
|
|
|
|
{
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &actor : localActors)
|
2017-04-08 07:58:25 +00:00
|
|
|
{
|
2017-06-27 13:56:24 +00:00
|
|
|
Main::get().getCellController()->removeLocalActorRecord(actor.first);
|
|
|
|
delete actor.second;
|
2017-04-08 07:58:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
localActors.clear();
|
|
|
|
}
|
|
|
|
|
2018-08-16 00:50:41 +00:00
|
|
|
void Cell::uninitializeDedicatedActors(ActorList& actorList)
|
|
|
|
{
|
|
|
|
for (const auto &baseActor : actorList.baseActors)
|
|
|
|
{
|
|
|
|
std::string mapIndex = Main::get().getCellController()->generateMapIndex(baseActor);
|
|
|
|
Main::get().getCellController()->removeDedicatedActorRecord(mapIndex);
|
|
|
|
delete dedicatedActors.at(mapIndex);
|
|
|
|
dedicatedActors.erase(mapIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-08 07:58:25 +00:00
|
|
|
void Cell::uninitializeDedicatedActors()
|
|
|
|
{
|
2017-06-27 14:27:02 +00:00
|
|
|
for (const auto &actor : dedicatedActors)
|
2017-04-08 07:58:25 +00:00
|
|
|
{
|
2017-06-27 13:56:24 +00:00
|
|
|
Main::get().getCellController()->removeDedicatedActorRecord(actor.first);
|
|
|
|
delete actor.second;
|
2017-04-08 07:58:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dedicatedActors.clear();
|
|
|
|
}
|
|
|
|
|
2017-04-07 07:16:23 +00:00
|
|
|
LocalActor *Cell::getLocalActor(std::string actorIndex)
|
|
|
|
{
|
|
|
|
return localActors.at(actorIndex);
|
|
|
|
}
|
|
|
|
|
2017-04-08 04:46:33 +00:00
|
|
|
DedicatedActor *Cell::getDedicatedActor(std::string actorIndex)
|
|
|
|
{
|
|
|
|
return dedicatedActors.at(actorIndex);
|
|
|
|
}
|
|
|
|
|
2017-05-04 23:46:16 +00:00
|
|
|
bool Cell::hasLocalAuthority()
|
|
|
|
{
|
|
|
|
return authorityGuid == Main::get().getLocalPlayer()->guid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cell::setAuthority(const RakNet::RakNetGUID& guid)
|
|
|
|
{
|
|
|
|
authorityGuid = guid;
|
|
|
|
}
|
|
|
|
|
2017-04-07 05:12:50 +00:00
|
|
|
MWWorld::CellStore *Cell::getCellStore()
|
2017-04-06 01:00:50 +00:00
|
|
|
{
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2021-09-17 17:14:55 +00:00
|
|
|
std::string Cell::getShortDescription()
|
2017-04-06 01:00:50 +00:00
|
|
|
{
|
2021-09-17 17:14:55 +00:00
|
|
|
return store->getCell()->getShortDescription();
|
2017-04-06 01:00:50 +00:00
|
|
|
}
|