mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 17:06:43 +00:00
[General] Include death animations in ActorDeath packets
This commit is contained in:
parent
ecf00af548
commit
a383b7b612
12 changed files with 193 additions and 31 deletions
|
@ -212,6 +212,11 @@ const char *ActorFunctions::GetActorKillerName(unsigned int index) noexcept
|
|||
return readActorList->baseActors.at(index).killer.name.c_str();
|
||||
}
|
||||
|
||||
unsigned int ActorFunctions::GetActorDeathState(unsigned int index) noexcept
|
||||
{
|
||||
return readActorList->baseActors.at(index).deathState;
|
||||
}
|
||||
|
||||
bool ActorFunctions::DoesActorHavePosition(unsigned int index) noexcept
|
||||
{
|
||||
return readActorList->baseActors.at(index).hasPositionData;
|
||||
|
@ -316,6 +321,16 @@ void ActorFunctions::SetActorSound(const char* sound) noexcept
|
|||
tempActor.sound = sound;
|
||||
}
|
||||
|
||||
void ActorFunctions::SetActorDeathState(unsigned int deathState) noexcept
|
||||
{
|
||||
tempActor.deathState = deathState;
|
||||
}
|
||||
|
||||
void ActorFunctions::SetActorDeathInstant(bool isInstant) noexcept
|
||||
{
|
||||
tempActor.isInstantDeath = isInstant;
|
||||
}
|
||||
|
||||
void ActorFunctions::SetActorAIAction(unsigned int action) noexcept
|
||||
{
|
||||
tempActor.aiAction = action;
|
||||
|
@ -483,6 +498,25 @@ void ActorFunctions::SendActorSpeech(bool sendToOtherVisitors, bool skipAttached
|
|||
}
|
||||
}
|
||||
|
||||
void ActorFunctions::SendActorDeath(bool sendToOtherVisitors, bool skipAttachedPlayer) noexcept
|
||||
{
|
||||
mwmp::ActorPacket *actorPacket = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_DEATH);
|
||||
actorPacket->setActorList(&writeActorList);
|
||||
|
||||
if (!skipAttachedPlayer)
|
||||
actorPacket->Send(writeActorList.guid);
|
||||
|
||||
if (sendToOtherVisitors)
|
||||
{
|
||||
Cell *serverCell = CellController::get()->getCell(&writeActorList.cell);
|
||||
|
||||
if (serverCell != nullptr)
|
||||
{
|
||||
serverCell->sendToLoaded(actorPacket, &writeActorList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActorFunctions::SendActorAI(bool sendToOtherVisitors, bool skipAttachedPlayer) noexcept
|
||||
{
|
||||
mwmp::ActorPacket *actorPacket = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_AI);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
{"GetActorKillerRefNum", ActorFunctions::GetActorKillerRefNum},\
|
||||
{"GetActorKillerMpNum", ActorFunctions::GetActorKillerMpNum},\
|
||||
{"GetActorKillerName", ActorFunctions::GetActorKillerName},\
|
||||
{"GetActorDeathState", ActorFunctions::GetActorDeathState},\
|
||||
\
|
||||
{"DoesActorHavePosition", ActorFunctions::DoesActorHavePosition},\
|
||||
{"DoesActorHaveStatsDynamic", ActorFunctions::DoesActorHaveStatsDynamic},\
|
||||
|
@ -71,6 +72,8 @@
|
|||
{"SetActorFatigueCurrent", ActorFunctions::SetActorFatigueCurrent},\
|
||||
{"SetActorFatigueModified", ActorFunctions::SetActorFatigueModified},\
|
||||
\
|
||||
{"SetActorDeathState", ActorFunctions::SetActorDeathState},\
|
||||
{"SetActorDeathInstant", ActorFunctions::SetActorDeathInstant},\
|
||||
{"SetActorSound", ActorFunctions::SetActorSound},\
|
||||
\
|
||||
{"SetActorAIAction", ActorFunctions::SetActorAIAction},\
|
||||
|
@ -92,6 +95,7 @@
|
|||
{"SendActorStatsDynamic", ActorFunctions::SendActorStatsDynamic},\
|
||||
{"SendActorEquipment", ActorFunctions::SendActorEquipment},\
|
||||
{"SendActorSpeech", ActorFunctions::SendActorSpeech},\
|
||||
{"SendActorDeath", ActorFunctions::SendActorDeath},\
|
||||
{"SendActorAI", ActorFunctions::SendActorAI},\
|
||||
{"SendActorCellChange", ActorFunctions::SendActorCellChange},\
|
||||
\
|
||||
|
@ -402,6 +406,14 @@ public:
|
|||
*/
|
||||
static const char *GetActorKillerName(unsigned int index) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Get the deathState of the actor at a certain index in the read actor list.
|
||||
*
|
||||
* \param index The index of the actor.
|
||||
* \return The deathState.
|
||||
*/
|
||||
static unsigned int GetActorDeathState(unsigned int index) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Check whether there is any positional data for the actor at a certain index in
|
||||
* the read actor list.
|
||||
|
@ -581,6 +593,23 @@ public:
|
|||
*/
|
||||
static void SetActorSound(const char* sound) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Set the deathState of the temporary actor stored on the server.
|
||||
*
|
||||
* \param deathState The deathState.
|
||||
* \return void
|
||||
*/
|
||||
static void SetActorDeathState(unsigned int deathState) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Set whether the death of the temporary actor stored on the server should
|
||||
* be instant or not.
|
||||
*
|
||||
* \param isInstant Whether the death should be instant.
|
||||
* \return void
|
||||
*/
|
||||
static void SetActorDeathInstant(bool isInstant) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Set the AI action of the temporary actor stored on the server.
|
||||
*
|
||||
|
@ -742,6 +771,17 @@ public:
|
|||
*/
|
||||
static void SendActorSpeech(bool sendToOtherVisitors, bool skipAttachedPlayer) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Send an ActorDeath packet.
|
||||
*
|
||||
* \param sendToOtherVisitors Whether this packet should be sent to cell visitors other
|
||||
* than the player attached to the packet (false by default).
|
||||
* \param skipAttachedPlayer Whether the packet should skip being sent to the player attached
|
||||
* to the packet (false by default).
|
||||
* \return void
|
||||
*/
|
||||
static void SendActorDeath(bool sendToOtherVisitors, bool skipAttachedPlayer) noexcept;
|
||||
|
||||
/**
|
||||
* \brief Send an ActorAI packet.
|
||||
*
|
||||
|
|
|
@ -813,11 +813,18 @@ void CharacterController::playRandomDeath(float startpoint)
|
|||
Start tes3mp change (major)
|
||||
|
||||
If this is a DedicatedPlayer, use the deathState received from their PlayerDeath packet
|
||||
|
||||
If this is a DedicatedActor, use the deathState from their ActorDeath packet
|
||||
*/
|
||||
if (mwmp::PlayerList::isDedicatedPlayer(mPtr))
|
||||
{
|
||||
mDeathState = static_cast<CharacterState>(mwmp::PlayerList::getPlayer(mPtr)->deathState);
|
||||
}
|
||||
else if (mwmp::Main::get().getCellController()->hasQueuedDeathState(mPtr))
|
||||
{
|
||||
mDeathState = static_cast<CharacterState>(mwmp::Main::get().getCellController()->getQueuedDeathState(mPtr));
|
||||
mwmp::Main::get().getCellController()->clearQueuedDeathState(mPtr);
|
||||
}
|
||||
else if(mHitState == CharState_SwimKnockDown && mAnimation->hasAnimation("swimdeathknockdown"))
|
||||
/*
|
||||
End of tes3mp change (major)
|
||||
|
@ -849,12 +856,19 @@ void CharacterController::playRandomDeath(float startpoint)
|
|||
/*
|
||||
Start of tes3mp addition
|
||||
|
||||
Send a PlayerDeath packet with the decided-upon death animation
|
||||
If this is the local player, send a PlayerDeath packet with the decided-upon
|
||||
death animation
|
||||
|
||||
If this is a local actor, send an ActorDeath packet with the animation
|
||||
*/
|
||||
if (mPtr == getPlayer())
|
||||
{
|
||||
mwmp::Main::get().getLocalPlayer()->sendDeath(mDeathState);
|
||||
}
|
||||
else if (!mPtr.getClass().getCreatureStats(mPtr).isDeathAnimationFinished() && mwmp::Main::get().getCellController()->isLocalActor(mPtr))
|
||||
{
|
||||
mwmp::Main::get().getCellController()->getLocalActor(mPtr)->sendDeath(mDeathState);
|
||||
}
|
||||
/*
|
||||
End of tes3mp addition
|
||||
*/
|
||||
|
|
|
@ -203,14 +203,37 @@ void Cell::readStatsDynamic(ActorList& actorList)
|
|||
// That way, if this actor is about to become a LocalActor, initial data about it
|
||||
// received from the server still gets set
|
||||
actor->setStatsDynamic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actors loaded as dead from the server need special handling to skip their death animations
|
||||
// and disable their collision
|
||||
if (actor->creatureStats.mDynamic[0].mCurrent < 1)
|
||||
{
|
||||
actor->getPtr().getClass().getCreatureStats(actor->getPtr()).setDeathAnimationFinished(true);
|
||||
MWBase::Environment::get().getWorld()->enableActorCollision(actor->getPtr(), false);
|
||||
}
|
||||
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);
|
||||
|
||||
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "In Cell::readDeath, deathState is %i and isInstantDeath is %s",
|
||||
baseActor.deathState,
|
||||
baseActor.isInstantDeath ? "true" : "false");
|
||||
|
||||
if (baseActor.isInstantDeath)
|
||||
{
|
||||
actor->getPtr().getClass().getCreatureStats(actor->getPtr()).setDeathAnimationFinished(true);
|
||||
MWBase::Environment::get().getWorld()->enableActorCollision(actor->getPtr(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -419,11 +442,6 @@ void Cell::initializeLocalActor(const MWWorld::Ptr& ptr)
|
|||
actor->cell = *store->getCell();
|
||||
actor->setPtr(ptr);
|
||||
|
||||
// Note that this actor was already dead when we were given control over it,
|
||||
// to avoid sending an ActorDeath packet
|
||||
if (ptr.getClass().getCreatureStats(ptr).isDead())
|
||||
actor->wasDead = true;
|
||||
|
||||
localActors[mapIndex] = actor;
|
||||
|
||||
Main::get().getCellController()->setLocalActorRecord(mapIndex, getDescription());
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace mwmp
|
|||
void readAnimFlags(ActorList& actorList);
|
||||
void readAnimPlay(ActorList& actorList);
|
||||
void readStatsDynamic(ActorList& actorList);
|
||||
void readDeath(ActorList& actorList);
|
||||
void readEquipment(ActorList& actorList);
|
||||
void readSpeech(ActorList& actorList);
|
||||
void readAi(ActorList& actorList);
|
||||
|
|
|
@ -17,6 +17,7 @@ using namespace mwmp;
|
|||
std::map<std::string, mwmp::Cell *> CellController::cellsInitialized;
|
||||
std::map<std::string, std::string> CellController::localActorsToCells;
|
||||
std::map<std::string, std::string> CellController::dedicatedActorsToCells;
|
||||
std::map<std::string, unsigned int> CellController::queuedDeathStates;
|
||||
|
||||
mwmp::CellController::CellController()
|
||||
{
|
||||
|
@ -134,6 +135,17 @@ void CellController::readStatsDynamic(ActorList& actorList)
|
|||
cellsInitialized[mapIndex]->readStatsDynamic(actorList);
|
||||
}
|
||||
|
||||
void CellController::readDeath(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]->readDeath(actorList);
|
||||
}
|
||||
|
||||
void CellController::readEquipment(ActorList& actorList)
|
||||
{
|
||||
std::string mapIndex = actorList.cell.getDescription();
|
||||
|
@ -200,6 +212,34 @@ void CellController::readCellChange(ActorList& actorList)
|
|||
cellsInitialized[mapIndex]->readCellChange(actorList);
|
||||
}
|
||||
|
||||
bool CellController::hasQueuedDeathState(MWWorld::Ptr ptr)
|
||||
{
|
||||
std::string actorIndex = generateMapIndex(ptr);
|
||||
|
||||
return queuedDeathStates.count(actorIndex) > 0;
|
||||
}
|
||||
|
||||
unsigned int CellController::getQueuedDeathState(MWWorld::Ptr ptr)
|
||||
{
|
||||
std::string actorIndex = generateMapIndex(ptr);
|
||||
|
||||
return queuedDeathStates[actorIndex];
|
||||
}
|
||||
|
||||
void CellController::clearQueuedDeathState(MWWorld::Ptr ptr)
|
||||
{
|
||||
std::string actorIndex = generateMapIndex(ptr);
|
||||
|
||||
queuedDeathStates.erase(actorIndex);
|
||||
}
|
||||
|
||||
void CellController::setQueuedDeathState(MWWorld::Ptr ptr, unsigned int deathState)
|
||||
{
|
||||
std::string actorIndex = generateMapIndex(ptr);
|
||||
|
||||
queuedDeathStates[actorIndex] = deathState;
|
||||
}
|
||||
|
||||
void CellController::setLocalActorRecord(std::string actorIndex, std::string cellIndex)
|
||||
{
|
||||
localActorsToCells[actorIndex] = cellIndex;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace mwmp
|
|||
void readAnimFlags(mwmp::ActorList& actorList);
|
||||
void readAnimPlay(mwmp::ActorList& actorList);
|
||||
void readStatsDynamic(mwmp::ActorList& actorList);
|
||||
void readDeath(mwmp::ActorList& actorList);
|
||||
void readEquipment(mwmp::ActorList& actorList);
|
||||
void readSpeech(mwmp::ActorList& actorList);
|
||||
void readAi(mwmp::ActorList& actorList);
|
||||
|
@ -32,6 +33,11 @@ namespace mwmp
|
|||
void readCast(mwmp::ActorList& actorList);
|
||||
void readCellChange(mwmp::ActorList& actorList);
|
||||
|
||||
bool hasQueuedDeathState(MWWorld::Ptr ptr);
|
||||
unsigned int getQueuedDeathState(MWWorld::Ptr ptr);
|
||||
void clearQueuedDeathState(MWWorld::Ptr ptr);
|
||||
void setQueuedDeathState(MWWorld::Ptr ptr, unsigned int deathState);
|
||||
|
||||
void setLocalActorRecord(std::string actorIndex, std::string cellIndex);
|
||||
void removeLocalActorRecord(std::string actorIndex);
|
||||
|
||||
|
@ -68,6 +74,7 @@ namespace mwmp
|
|||
static std::map<std::string, mwmp::Cell *> cellsInitialized;
|
||||
static std::map<std::string, std::string> localActorsToCells;
|
||||
static std::map<std::string, std::string> dedicatedActorsToCells;
|
||||
static std::map<std::string, unsigned int> queuedDeathStates;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ LocalActor::LocalActor()
|
|||
wasForceJumping = false;
|
||||
wasForceMoveJumping = false;
|
||||
wasFlying = false;
|
||||
wasDead = false;
|
||||
|
||||
attack.type = Attack::MELEE;
|
||||
attack.shouldSend = false;
|
||||
|
@ -194,21 +193,6 @@ void LocalActor::updateStatsDynamic(bool forceUpdate)
|
|||
creatureStats.mDead = ptrCreatureStats->isDead();
|
||||
|
||||
mwmp::Main::get().getNetworking()->getActorList()->addStatsDynamicActor(*this);
|
||||
|
||||
if (creatureStats.mDead && !wasDead)
|
||||
{
|
||||
if (MechanicsHelper::isEmptyTarget(killer))
|
||||
killer = MechanicsHelper::getTarget(ptr);
|
||||
|
||||
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Sending ID_ACTOR_DEATH about %s %i-%i in cell %s to server",
|
||||
refId.c_str(), refNum, mpNum, cell.getDescription().c_str());
|
||||
|
||||
mwmp::Main::get().getNetworking()->getActorList()->addDeathActor(*this);
|
||||
|
||||
MechanicsHelper::clearTarget(killer);
|
||||
}
|
||||
|
||||
wasDead = creatureStats.mDead;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,6 +254,25 @@ void LocalActor::updateAttackOrCast()
|
|||
}
|
||||
}
|
||||
|
||||
void LocalActor::sendDeath(char newDeathState)
|
||||
{
|
||||
deathState = newDeathState;
|
||||
|
||||
if (MechanicsHelper::isEmptyTarget(killer))
|
||||
killer = MechanicsHelper::getTarget(ptr);
|
||||
|
||||
LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Sending ID_ACTOR_DEATH about %s %i-%i in cell %s to server\n- deathState: %d",
|
||||
refId.c_str(), refNum, mpNum, cell.getDescription().c_str(), deathState);
|
||||
|
||||
ActorList actorList;
|
||||
actorList.cell = cell;
|
||||
actorList.addActor(*this);
|
||||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_DEATH)->setActorList(&actorList);
|
||||
Main::get().getNetworking()->getActorPacket(ID_ACTOR_DEATH)->Send();
|
||||
|
||||
MechanicsHelper::clearTarget(killer);
|
||||
}
|
||||
|
||||
MWWorld::Ptr LocalActor::getPtr()
|
||||
{
|
||||
return ptr;
|
||||
|
|
|
@ -25,11 +25,12 @@ namespace mwmp
|
|||
void updateEquipment(bool forceUpdate);
|
||||
void updateAttackOrCast();
|
||||
|
||||
void sendDeath(char newDeathState);
|
||||
|
||||
MWWorld::Ptr getPtr();
|
||||
void setPtr(const MWWorld::Ptr& newPtr);
|
||||
|
||||
bool hasSentData;
|
||||
bool wasDead;
|
||||
|
||||
private:
|
||||
MWWorld::Ptr ptr;
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace mwmp
|
|||
|
||||
virtual void Do(ActorPacket &packet, ActorList &actorList)
|
||||
{
|
||||
//Main::get().getCellController()->readDeath(actorList);
|
||||
Main::get().getCellController()->readDeath(actorList);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace mwmp
|
|||
SimpleCreatureStats creatureStats;
|
||||
|
||||
Animation animation;
|
||||
char deathState;
|
||||
bool isInstantDeath = false;
|
||||
Attack attack;
|
||||
Cast cast;
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ void PacketActorDeath::Actor(BaseActor &actor, bool send)
|
|||
{
|
||||
RW(actor.refId, send);
|
||||
|
||||
RW(actor.deathState, send);
|
||||
RW(actor.isInstantDeath, send);
|
||||
RW(actor.killer.isPlayer, send);
|
||||
|
||||
if (actor.killer.isPlayer)
|
||||
|
|
Loading…
Reference in a new issue