[General] Implement ActorDeath packet, part 1

ActorDeath packets are sent for dead actors before their StatsDynamic packets. They contain the actor's deathReason in a manner similar to that of PlayerDeath packets.

A future commit will replace the deathReason with a variable named killer which will be an mwmp::Target.
0.6.3
David Cernat 7 years ago
parent 15bfa30070
commit 7ffdb18bf9

@ -113,10 +113,10 @@ source_group(tes3mp-server FILES ${SERVER} ${SERVER_HEADER})
set(PROCESSORS_ACTOR
processors/actor/ProcessorActorAnimFlags.hpp processors/actor/ProcessorActorAnimPlay.hpp
processors/actor/ProcessorActorAttack.hpp processors/actor/ProcessorActorCellChange.hpp
processors/actor/ProcessorActorEquipment.hpp processors/actor/ProcessorActorInteraction.hpp
processors/actor/ProcessorActorList.hpp processors/actor/ProcessorActorPosition.hpp
processors/actor/ProcessorActorSpeech.hpp processors/actor/ProcessorActorStatsDynamic.hpp
processors/actor/ProcessorActorTest.hpp
processors/actor/ProcessorActorDeath.hpp processors/actor/ProcessorActorEquipment.hpp
processors/actor/ProcessorActorInteraction.hpp processors/actor/ProcessorActorList.hpp
processors/actor/ProcessorActorPosition.hpp processors/actor/ProcessorActorSpeech.hpp
processors/actor/ProcessorActorStatsDynamic.hpp processors/actor/ProcessorActorTest.hpp
)
source_group(tes3mp-server\\processors\\actor FILES ${PROCESSORS_ACTOR})

@ -168,6 +168,11 @@ double ActorFunctions::GetActorEquipmentItemEnchantmentCharge(unsigned int i, un
return readActorList->baseActors.at(i).equipmentItems[slot].enchantmentCharge;
}
const char *ActorFunctions::GetActorDeathReason(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).deathReason.c_str();
}
bool ActorFunctions::DoesActorHavePosition(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).hasPositionData;

@ -36,6 +36,8 @@
{"GetActorEquipmentItemCharge", ActorFunctions::GetActorEquipmentItemCharge},\
{"GetActorEquipmentItemEnchantmentCharge", ActorFunctions::GetActorEquipmentItemEnchantmentCharge},\
\
{"GetActorDeathReason", ActorFunctions::GetActorDeathReason},\
\
{"DoesActorHavePosition", ActorFunctions::DoesActorHavePosition},\
{"DoesActorHaveStatsDynamic", ActorFunctions::DoesActorHaveStatsDynamic},\
\
@ -315,6 +317,14 @@ public:
*/
static double GetActorEquipmentItemEnchantmentCharge(unsigned int i, unsigned short slot) noexcept;
/**
* \brief Get the death reason of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The death reason.
*/
static const char *GetActorDeathReason(unsigned int i) noexcept;
/**
* \brief Check whether there is any positional data for the actor at a certain index in
* the read actor list.

@ -340,6 +340,7 @@ public:
{"OnObjectTrap", Function<void, unsigned short, const char*>()},
{"OnActorList", Function<void, unsigned short, const char*>()},
{"OnActorEquipment", Function<void, unsigned short, const char*>()},
{"OnActorDeath", Function<void, unsigned short, const char*>()},
{"OnActorCellChange", Function<void, unsigned short, const char*>()},
{"OnActorTest", Function<void, unsigned short, const char*>()},
{"OnPlayerSendMessage", Function<bool, unsigned short, const char*>()},

@ -19,7 +19,11 @@ namespace mwmp
Cell *serverCell = CellController::get()->getCell(&actorList.cell);
if (serverCell != nullptr && *serverCell->getAuthority() == actorList.guid)
{
Script::Call<Script::CallbackIdentity("OnActorDeath")>(player.getId(), actorList.cell.getDescription().c_str());
serverCell->sendToLoaded(&packet, &actorList);
}
}
};
}

@ -540,6 +540,8 @@ namespace MWClass
Start of tes3mp addition
If the attacker was the LocalPlayer or LocalActor, record their target and send a packet with it
If the victim was a LocalActor who died, record their attacker as the deathReason
*/
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
@ -553,6 +555,14 @@ namespace MWClass
localAttack->shouldSend = true;
}
if (mwmp::Main::get().getCellController()->isLocalActor(ptr))
{
if (getCreatureStats(ptr).isDead())
{
mwmp::Main::get().getCellController()->getLocalActor(ptr)->deathReason = attacker.getClass().getName(attacker);
}
}
/*
End of tes3mp addition
*/

@ -953,6 +953,8 @@ namespace MWClass
If the victim was the LocalPlayer, check whether packets should be sent about
their new dynamic stats and position
If the victim was a LocalActor who died, record their attacker as the deathReason
*/
mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
@ -978,6 +980,13 @@ namespace MWClass
mwmp::Main::get().getLocalPlayer()->deathReason = attacker.getClass().getName(attacker);
}
}
else if (mwmp::Main::get().getCellController()->isLocalActor(ptr))
{
if (getCreatureStats(ptr).isDead())
{
mwmp::Main::get().getCellController()->getLocalActor(ptr)->deathReason = attacker.getClass().getName(attacker);
}
}
/*
End of tes3mp addition
*/

@ -32,6 +32,7 @@ void ActorList::reset()
animPlayActors.clear();
speechActors.clear();
statsDynamicActors.clear();
deathActors.clear();
equipmentActors.clear();
attackActors.clear();
cellChangeActors.clear();
@ -73,6 +74,11 @@ void ActorList::addStatsDynamicActor(LocalActor localActor)
statsDynamicActors.push_back(localActor);
}
void ActorList::addDeathActor(LocalActor localActor)
{
deathActors.push_back(localActor);
}
void ActorList::addEquipmentActor(LocalActor localActor)
{
equipmentActors.push_back(localActor);
@ -138,6 +144,16 @@ void ActorList::sendStatsDynamicActors()
}
}
void ActorList::sendDeathActors()
{
if (deathActors.size() > 0)
{
baseActors = deathActors;
Main::get().getNetworking()->getActorPacket(ID_ACTOR_DEATH)->setActorList(this);
Main::get().getNetworking()->getActorPacket(ID_ACTOR_DEATH)->Send();
}
}
void ActorList::sendEquipmentActors()
{
if (equipmentActors.size() > 0)

@ -26,6 +26,7 @@ namespace mwmp
void addAnimPlayActor(LocalActor localActor);
void addSpeechActor(LocalActor localActor);
void addStatsDynamicActor(LocalActor localActor);
void addDeathActor(LocalActor localActor);
void addEquipmentActor(LocalActor localActor);
void addAttackActor(LocalActor localActor);
void addCellChangeActor(LocalActor localActor);
@ -35,6 +36,7 @@ namespace mwmp
void sendAnimPlayActors();
void sendSpeechActors();
void sendStatsDynamicActors();
void sendDeathActors();
void sendEquipmentActors();
void sendAttackActors();
void sendCellChangeActors();
@ -49,6 +51,7 @@ namespace mwmp
std::vector<BaseActor> animPlayActors;
std::vector<BaseActor> speechActors;
std::vector<BaseActor> statsDynamicActors;
std::vector<BaseActor> deathActors;
std::vector<BaseActor> equipmentActors;
std::vector<BaseActor> attackActors;
std::vector<BaseActor> cellChangeActors;

@ -93,6 +93,7 @@ void Cell::updateLocal(bool forceUpdate)
actorList->sendAnimFlagsActors();
actorList->sendAnimPlayActors();
actorList->sendSpeechActors();
actorList->sendDeathActors();
actorList->sendStatsDynamicActors();
actorList->sendEquipmentActors();
actorList->sendAttackActors();
@ -370,6 +371,11 @@ 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;
std::string mapIndex = Main::get().getCellController()->generateMapIndex(ptr);
localActors[mapIndex] = actor;

@ -30,6 +30,7 @@ LocalActor::LocalActor()
wasForceJumping = false;
wasForceMoveJumping = false;
wasFlying = false;
wasDead = false;
attack.type = Attack::MELEE;
attack.shouldSend = false;
@ -179,6 +180,22 @@ void LocalActor::updateStatsDynamic(bool forceUpdate)
creatureStats.mDead = ptrCreatureStats->isDead();
mwmp::Main::get().getNetworking()->getActorList()->addStatsDynamicActor(*this);
if (creatureStats.mDead && !wasDead)
{
if (deathReason.empty())
deathReason = "suicide";
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_ACTOR_DEATH about %s-%i-%i to server",
refId.c_str(), refNumIndex, mpNum);
LOG_APPEND(Log::LOG_INFO, "- deathReason was %s", deathReason.c_str());
mwmp::Main::get().getNetworking()->getActorList()->addDeathActor(*this);
deathReason = "";
}
wasDead = creatureStats.mDead;
}
}

@ -28,6 +28,8 @@ namespace mwmp
MWWorld::Ptr getPtr();
void setPtr(const MWWorld::Ptr& newPtr);
bool wasDead;
private:
MWWorld::Ptr ptr;

@ -39,6 +39,8 @@ namespace mwmp
Animation animation;
Attack attack;
std::string deathReason;
bool hasAiTarget;
Target aiTarget;
unsigned int aiAction;

@ -11,5 +11,5 @@ PacketActorDeath::PacketActorDeath(RakNet::RakPeerInterface *peer) : ActorPacket
void PacketActorDeath::Actor(BaseActor &actor, bool send)
{
// Placeholder to be filled in later
RW(actor.deathReason, send);
}

Loading…
Cancel
Save