[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 set(PROCESSORS_ACTOR
processors/actor/ProcessorActorAnimFlags.hpp processors/actor/ProcessorActorAnimPlay.hpp processors/actor/ProcessorActorAnimFlags.hpp processors/actor/ProcessorActorAnimPlay.hpp
processors/actor/ProcessorActorAttack.hpp processors/actor/ProcessorActorCellChange.hpp processors/actor/ProcessorActorAttack.hpp processors/actor/ProcessorActorCellChange.hpp
processors/actor/ProcessorActorEquipment.hpp processors/actor/ProcessorActorInteraction.hpp processors/actor/ProcessorActorDeath.hpp processors/actor/ProcessorActorEquipment.hpp
processors/actor/ProcessorActorList.hpp processors/actor/ProcessorActorPosition.hpp processors/actor/ProcessorActorInteraction.hpp processors/actor/ProcessorActorList.hpp
processors/actor/ProcessorActorSpeech.hpp processors/actor/ProcessorActorStatsDynamic.hpp processors/actor/ProcessorActorPosition.hpp processors/actor/ProcessorActorSpeech.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})

@ -168,6 +168,11 @@ double ActorFunctions::GetActorEquipmentItemEnchantmentCharge(unsigned int i, un
return readActorList->baseActors.at(i).equipmentItems[slot].enchantmentCharge; 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 bool ActorFunctions::DoesActorHavePosition(unsigned int i) noexcept
{ {
return readActorList->baseActors.at(i).hasPositionData; return readActorList->baseActors.at(i).hasPositionData;

@ -36,6 +36,8 @@
{"GetActorEquipmentItemCharge", ActorFunctions::GetActorEquipmentItemCharge},\ {"GetActorEquipmentItemCharge", ActorFunctions::GetActorEquipmentItemCharge},\
{"GetActorEquipmentItemEnchantmentCharge", ActorFunctions::GetActorEquipmentItemEnchantmentCharge},\ {"GetActorEquipmentItemEnchantmentCharge", ActorFunctions::GetActorEquipmentItemEnchantmentCharge},\
\ \
{"GetActorDeathReason", ActorFunctions::GetActorDeathReason},\
\
{"DoesActorHavePosition", ActorFunctions::DoesActorHavePosition},\ {"DoesActorHavePosition", ActorFunctions::DoesActorHavePosition},\
{"DoesActorHaveStatsDynamic", ActorFunctions::DoesActorHaveStatsDynamic},\ {"DoesActorHaveStatsDynamic", ActorFunctions::DoesActorHaveStatsDynamic},\
\ \
@ -315,6 +317,14 @@ public:
*/ */
static double GetActorEquipmentItemEnchantmentCharge(unsigned int i, unsigned short slot) noexcept; 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 * \brief Check whether there is any positional data for the actor at a certain index in
* the read actor list. * the read actor list.

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

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

@ -540,6 +540,8 @@ namespace MWClass
Start of tes3mp addition Start of tes3mp addition
If the attacker was the LocalPlayer or LocalActor, record their target and send a packet with it 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); mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
@ -553,6 +555,14 @@ namespace MWClass
localAttack->shouldSend = true; 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 End of tes3mp addition
*/ */

@ -953,6 +953,8 @@ namespace MWClass
If the victim was the LocalPlayer, check whether packets should be sent about If the victim was the LocalPlayer, check whether packets should be sent about
their new dynamic stats and position 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); mwmp::Attack *localAttack = MechanicsHelper::getLocalAttack(attacker);
@ -978,6 +980,13 @@ namespace MWClass
mwmp::Main::get().getLocalPlayer()->deathReason = attacker.getClass().getName(attacker); 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 End of tes3mp addition
*/ */

@ -32,6 +32,7 @@ void ActorList::reset()
animPlayActors.clear(); animPlayActors.clear();
speechActors.clear(); speechActors.clear();
statsDynamicActors.clear(); statsDynamicActors.clear();
deathActors.clear();
equipmentActors.clear(); equipmentActors.clear();
attackActors.clear(); attackActors.clear();
cellChangeActors.clear(); cellChangeActors.clear();
@ -73,6 +74,11 @@ void ActorList::addStatsDynamicActor(LocalActor localActor)
statsDynamicActors.push_back(localActor); statsDynamicActors.push_back(localActor);
} }
void ActorList::addDeathActor(LocalActor localActor)
{
deathActors.push_back(localActor);
}
void ActorList::addEquipmentActor(LocalActor localActor) void ActorList::addEquipmentActor(LocalActor localActor)
{ {
equipmentActors.push_back(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() void ActorList::sendEquipmentActors()
{ {
if (equipmentActors.size() > 0) if (equipmentActors.size() > 0)

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

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

@ -30,6 +30,7 @@ LocalActor::LocalActor()
wasForceJumping = false; wasForceJumping = false;
wasForceMoveJumping = false; wasForceMoveJumping = false;
wasFlying = false; wasFlying = false;
wasDead = false;
attack.type = Attack::MELEE; attack.type = Attack::MELEE;
attack.shouldSend = false; attack.shouldSend = false;
@ -179,6 +180,22 @@ void LocalActor::updateStatsDynamic(bool forceUpdate)
creatureStats.mDead = ptrCreatureStats->isDead(); creatureStats.mDead = ptrCreatureStats->isDead();
mwmp::Main::get().getNetworking()->getActorList()->addStatsDynamicActor(*this); 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(); MWWorld::Ptr getPtr();
void setPtr(const MWWorld::Ptr& newPtr); void setPtr(const MWWorld::Ptr& newPtr);
bool wasDead;
private: private:
MWWorld::Ptr ptr; MWWorld::Ptr ptr;

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

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

Loading…
Cancel
Save