mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-18 03:37:23 -06:00
Compare commits
16 Commits
fix-empty-
...
v3.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3890c0a86c | ||
|
|
c083f21e44 | ||
|
|
c9e95839ee | ||
|
|
dd957ed0c7 | ||
|
|
12296ce553 | ||
|
|
24f4c9d413 | ||
|
|
ba964932b7 | ||
|
|
4c42eea819 | ||
|
|
6b52cf67a0 | ||
|
|
71f708f1b5 | ||
|
|
49aa632d42 | ||
|
|
5ec4142ca1 | ||
|
|
5e9fe40bec | ||
|
|
9524198044 | ||
|
|
a5d0788488 | ||
|
|
a1ba5b8f12 |
@@ -187,7 +187,8 @@ Now that you are logged in, run the following commands.
|
|||||||
```bash
|
```bash
|
||||||
# Creates a user for this computer which uses a password and grant said user all privileges.
|
# Creates a user for this computer which uses a password and grant said user all privileges.
|
||||||
# Change mydarkflameuser to a custom username and password to a custom password.
|
# Change mydarkflameuser to a custom username and password to a custom password.
|
||||||
GRANT ALL ON *.* TO 'mydarkflameuser'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
|
CREATE USER 'mydarkflameuser'@'localhost' IDENTIFIED BY 'password';
|
||||||
|
GRANT ALL ON *.* TO 'mydarkflameuser'@'localhost' WITH GRANT OPTION;
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
|
|
||||||
# Then create a database for Darkflame Universe to use.
|
# Then create a database for Darkflame Universe to use.
|
||||||
|
|||||||
@@ -237,6 +237,57 @@ bool GeneralUtils::ReplaceInString(std::string& str, const std::string_view from
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::wstring> GeneralUtils::SplitString(const std::wstring_view str, const wchar_t delimiter) {
|
||||||
|
std::vector<std::wstring> vector = std::vector<std::wstring>();
|
||||||
|
std::wstring current;
|
||||||
|
|
||||||
|
for (const wchar_t c : str) {
|
||||||
|
if (c == delimiter) {
|
||||||
|
vector.push_back(current);
|
||||||
|
current = L"";
|
||||||
|
} else {
|
||||||
|
current += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector.push_back(std::move(current));
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view str, const char16_t delimiter) {
|
||||||
|
std::vector<std::u16string> vector = std::vector<std::u16string>();
|
||||||
|
std::u16string current;
|
||||||
|
|
||||||
|
for (const char16_t c : str) {
|
||||||
|
if (c == delimiter) {
|
||||||
|
vector.push_back(current);
|
||||||
|
current = u"";
|
||||||
|
} else {
|
||||||
|
current += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector.push_back(std::move(current));
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, const char delimiter) {
|
||||||
|
std::vector<std::string> vector = std::vector<std::string>();
|
||||||
|
std::string current = "";
|
||||||
|
|
||||||
|
for (const char c : str) {
|
||||||
|
if (c == delimiter) {
|
||||||
|
vector.push_back(current);
|
||||||
|
current = "";
|
||||||
|
} else {
|
||||||
|
current += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector.push_back(std::move(current));
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
|
std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
inStream.Read<uint32_t>(length);
|
inStream.Read<uint32_t>(length);
|
||||||
|
|||||||
@@ -130,23 +130,11 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
std::u16string ReadWString(RakNet::BitStream& inStream);
|
std::u16string ReadWString(RakNet::BitStream& inStream);
|
||||||
|
|
||||||
template<typename StringType, typename CharType = typename StringType::value_type>
|
std::vector<std::wstring> SplitString(const std::wstring_view str, const wchar_t delimiter);
|
||||||
std::vector<std::basic_string<CharType>> SplitString(const StringType& str, const typename StringType::value_type delimiter) {
|
|
||||||
std::vector<std::basic_string<CharType>> toReturn{};
|
|
||||||
|
|
||||||
toReturn.emplace_back();
|
std::vector<std::u16string> SplitString(const std::u16string_view str, const char16_t delimiter);
|
||||||
auto itr = toReturn.rbegin();
|
|
||||||
for (const auto c : str) {
|
|
||||||
if (c == delimiter) {
|
|
||||||
toReturn.emplace_back();
|
|
||||||
itr = toReturn.rbegin();
|
|
||||||
} else {
|
|
||||||
(*itr).push_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
std::vector<std::string> SplitString(const std::string_view str, const char delimiter);
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
|
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
|
||||||
|
|
||||||
@@ -312,6 +300,12 @@ namespace GeneralUtils {
|
|||||||
return T();
|
return T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Container>
|
||||||
|
inline Container::value_type GetRandomElement(const Container& container) {
|
||||||
|
DluAssert(!container.empty());
|
||||||
|
return container[GenerateRandomNumber<typename Container::value_type>(0, container.size() - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Casts the value of an enum entry to its underlying type
|
* Casts the value of an enum entry to its underlying type
|
||||||
* @param entry Enum entry to cast
|
* @param entry Enum entry to cast
|
||||||
|
|||||||
@@ -97,6 +97,8 @@
|
|||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
#include "CDZoneTableTable.h"
|
#include "CDZoneTableTable.h"
|
||||||
|
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;
|
Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;
|
||||||
@@ -187,6 +189,7 @@ Entity::~Entity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entity::Initialize() {
|
void Entity::Initialize() {
|
||||||
|
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &Entity::MsgRequestServerObjectInfo);
|
||||||
/**
|
/**
|
||||||
* Setup trigger
|
* Setup trigger
|
||||||
*/
|
*/
|
||||||
@@ -920,7 +923,7 @@ void Entity::WriteLDFData(const std::vector<LDFBaseData*>& ldf, RakNet::BitStrea
|
|||||||
numberOfValidKeys--;
|
numberOfValidKeys--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now write it to the main bitstream
|
// Now write it to the main bitstream
|
||||||
outBitStream.Write<uint32_t>(settingStream.GetNumberOfBytesUsed() + 1 + sizeof(uint32_t));
|
outBitStream.Write<uint32_t>(settingStream.GetNumberOfBytesUsed() + 1 + sizeof(uint32_t));
|
||||||
outBitStream.Write<uint8_t>(0); //no compression used
|
outBitStream.Write<uint8_t>(0); //no compression used
|
||||||
@@ -1662,11 +1665,9 @@ void Entity::PickupItem(const LWOOBJID& objectID) const {
|
|||||||
auto* const skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
|
auto* const skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
|
||||||
const auto skills = skillsTable->Query([&info](CDObjectSkills entry) {return (entry.objectTemplate == info.lot); });
|
const auto skills = skillsTable->Query([&info](CDObjectSkills entry) {return (entry.objectTemplate == info.lot); });
|
||||||
for (const auto& skill : skills) {
|
for (const auto& skill : skills) {
|
||||||
auto* skillComponent = GetComponent<SkillComponent>();
|
const auto [skillComponent, missionComponent] = GetComponentsMut<SkillComponent, MissionComponent>();
|
||||||
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
|
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
|
||||||
|
|
||||||
auto* missionComponent = GetComponent<MissionComponent>();
|
|
||||||
|
|
||||||
if (missionComponent != nullptr) {
|
if (missionComponent != nullptr) {
|
||||||
missionComponent->Progress(eMissionTaskType::POWERUP, skill.skillID);
|
missionComponent->Progress(eMissionTaskType::POWERUP, skill.skillID);
|
||||||
}
|
}
|
||||||
@@ -2211,3 +2212,38 @@ bool Entity::HandleMsg(GameMessages::GameMsg& msg) const {
|
|||||||
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
|
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
|
||||||
m_MsgHandlers.emplace(msgId, handler);
|
m_MsgHandlers.emplace(msgId, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
||||||
|
auto& requestInfo = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
|
||||||
|
AMFArrayValue response;
|
||||||
|
response.Insert("visible", true);
|
||||||
|
response.Insert("objectID", std::to_string(m_ObjectID));
|
||||||
|
response.Insert("serverInfo", true);
|
||||||
|
GameMessages::GetObjectReportInfo info{};
|
||||||
|
info.info = response.InsertArray("data");
|
||||||
|
auto& objectInfo = info.info->PushDebug("Object Details");
|
||||||
|
auto* table = CDClientManager::GetTable<CDObjectsTable>();
|
||||||
|
|
||||||
|
const auto& objTableInfo = table->GetByID(GetLOT());
|
||||||
|
|
||||||
|
objectInfo.PushDebug<AMFStringValue>("Name") = objTableInfo.name;
|
||||||
|
objectInfo.PushDebug<AMFIntValue>("Template ID(LOT)") = GetLOT();
|
||||||
|
objectInfo.PushDebug<AMFStringValue>("Object ID") = std::to_string(GetObjectID());
|
||||||
|
objectInfo.PushDebug<AMFStringValue>("Spawner's Object ID") = std::to_string(GetSpawnerID());
|
||||||
|
|
||||||
|
auto& componentDetails = objectInfo.PushDebug("Component Information");
|
||||||
|
for (const auto [id, component] : m_Components) {
|
||||||
|
componentDetails.PushDebug<AMFStringValue>(StringifiedEnum::ToString(id)) = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& configData = objectInfo.PushDebug("Config Data");
|
||||||
|
for (const auto config : m_Settings) {
|
||||||
|
configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString();
|
||||||
|
|
||||||
|
}
|
||||||
|
HandleMsg(info);
|
||||||
|
|
||||||
|
auto* client = Game::entityManager->GetEntity(requestInfo.clientId);
|
||||||
|
if (client) GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, client->GetSystemAddress());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <tuple>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -161,6 +162,12 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T* GetComponent() const;
|
T* GetComponent() const;
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
auto GetComponents() const;
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
auto GetComponentsMut() const;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool TryGetComponent(eReplicaComponentType componentId, T*& component) const;
|
bool TryGetComponent(eReplicaComponentType componentId, T*& component) const;
|
||||||
|
|
||||||
@@ -168,6 +175,8 @@ public:
|
|||||||
|
|
||||||
void AddComponent(eReplicaComponentType componentId, Component* component);
|
void AddComponent(eReplicaComponentType componentId, Component* component);
|
||||||
|
|
||||||
|
bool MsgRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
// This is expceted to never return nullptr, an assert checks this.
|
// This is expceted to never return nullptr, an assert checks this.
|
||||||
CppScripts::Script* const GetScript() const;
|
CppScripts::Script* const GetScript() const;
|
||||||
|
|
||||||
@@ -329,6 +338,10 @@ public:
|
|||||||
|
|
||||||
bool HandleMsg(GameMessages::GameMsg& msg) const;
|
bool HandleMsg(GameMessages::GameMsg& msg) const;
|
||||||
|
|
||||||
|
void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
|
||||||
|
RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The observable for player entity position updates.
|
* @brief The observable for player entity position updates.
|
||||||
*/
|
*/
|
||||||
@@ -579,3 +592,13 @@ inline ComponentType* Entity::AddComponent(VaArgs... args) {
|
|||||||
// To allow a static cast here instead of a dynamic one.
|
// To allow a static cast here instead of a dynamic one.
|
||||||
return dynamic_cast<ComponentType*>(componentToReturn);
|
return dynamic_cast<ComponentType*>(componentToReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
auto Entity::GetComponents() const {
|
||||||
|
return GetComponentsMut<const T...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
auto Entity::GetComponentsMut() const {
|
||||||
|
return std::tuple{GetComponent<T>()...};
|
||||||
|
}
|
||||||
|
|||||||
@@ -129,6 +129,8 @@ Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentE
|
|||||||
// Set the zone control entity if the entity is a zone control object, this should only happen once
|
// Set the zone control entity if the entity is a zone control object, this should only happen once
|
||||||
if (controller) {
|
if (controller) {
|
||||||
m_ZoneControlEntity = entity;
|
m_ZoneControlEntity = entity;
|
||||||
|
// Proooooobably shouldn't ghost zoneControl
|
||||||
|
m_ZoneControlEntity->SetIsGhostingCandidate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this entity is a respawn point, if so add it to the registry
|
// Check if this entity is a respawn point, if so add it to the registry
|
||||||
@@ -279,6 +281,8 @@ std::vector<Entity*> EntityManager::GetEntitiesByComponent(const eReplicaCompone
|
|||||||
|
|
||||||
withComp.push_back(entity);
|
withComp.push_back(entity);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (auto* const entity : m_Entities | std::views::values) withComp.push_back(entity);
|
||||||
}
|
}
|
||||||
return withComp;
|
return withComp;
|
||||||
}
|
}
|
||||||
@@ -394,7 +398,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateGhosting(PlayerManager::GetPlayer(sysAddr), true);
|
UpdateGhosting(PlayerManager::GetPlayer(sysAddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
||||||
@@ -463,7 +467,7 @@ void EntityManager::UpdateGhosting() {
|
|||||||
m_PlayersToUpdateGhosting.clear();
|
m_PlayersToUpdateGhosting.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::UpdateGhosting(Entity* player, const bool constructAll) {
|
void EntityManager::UpdateGhosting(Entity* player) {
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|
||||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||||
@@ -513,9 +517,6 @@ void EntityManager::UpdateGhosting(Entity* player, const bool constructAll) {
|
|||||||
|
|
||||||
entity->SetObservers(entity->GetObservers() + 1);
|
entity->SetObservers(entity->GetObservers() + 1);
|
||||||
|
|
||||||
// TODO: figure out if zone control should be ghosted at all
|
|
||||||
if (constructAll && entity->GetObjectID() == GetZoneControlEntity()->GetObjectID()) continue;
|
|
||||||
|
|
||||||
ConstructEntity(entity, player->GetSystemAddress());
|
ConstructEntity(entity, player->GetSystemAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public:
|
|||||||
void SetGhostDistanceMin(float value);
|
void SetGhostDistanceMin(float value);
|
||||||
void QueueGhostUpdate(LWOOBJID playerID);
|
void QueueGhostUpdate(LWOOBJID playerID);
|
||||||
void UpdateGhosting();
|
void UpdateGhosting();
|
||||||
void UpdateGhosting(Entity* player, const bool constructAll = false);
|
void UpdateGhosting(Entity* player);
|
||||||
void CheckGhosting(Entity* entity);
|
void CheckGhosting(Entity* entity);
|
||||||
Entity* GetGhostCandidate(LWOOBJID id) const;
|
Entity* GetGhostCandidate(LWOOBJID id) const;
|
||||||
bool GetGhostingEnabled() const;
|
bool GetGhostingEnabled() const;
|
||||||
|
|||||||
@@ -28,8 +28,11 @@
|
|||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
#include "LeaderboardManager.h"
|
#include "LeaderboardManager.h"
|
||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) {
|
ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) {
|
||||||
|
using namespace GameMessages;
|
||||||
|
RegisterMsg<GetObjectReportInfo>(this, &ActivityComponent::OnGetObjectReportInfo);
|
||||||
/*
|
/*
|
||||||
* This is precisely what the client does functionally
|
* This is precisely what the client does functionally
|
||||||
* Use the component id as the default activity id and load its data from the database
|
* Use the component id as the default activity id and load its data from the database
|
||||||
@@ -348,14 +351,13 @@ bool ActivityComponent::CheckCost(Entity* player) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ActivityComponent::TakeCost(Entity* player) const{
|
bool ActivityComponent::TakeCost(Entity* player) const {
|
||||||
|
|
||||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||||
if (CheckCost(player)) {
|
if (CheckCost(player)) {
|
||||||
inventoryComponent->RemoveItem(m_ActivityInfo.optionalCostLOT, m_ActivityInfo.optionalCostCount);
|
inventoryComponent->RemoveItem(m_ActivityInfo.optionalCostLOT, m_ActivityInfo.optionalCostCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
} else return false;
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActivityComponent::PlayerReady(Entity* player, bool bReady) {
|
void ActivityComponent::PlayerReady(Entity* player, bool bReady) {
|
||||||
@@ -618,3 +620,91 @@ void ActivityInstance::SetScore(uint32_t score) {
|
|||||||
Entity* LobbyPlayer::GetEntity() const {
|
Entity* LobbyPlayer::GetEntity() const {
|
||||||
return Game::entityManager->GetEntity(entityID);
|
return Game::entityManager->GetEntity(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
|
||||||
|
auto& activityInfo = reportInfo.info->PushDebug("Activity");
|
||||||
|
|
||||||
|
auto& instances = activityInfo.PushDebug("Instances: " + std::to_string(m_Instances.size()));
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto& activityInstance : m_Instances) {
|
||||||
|
if (!activityInstance) continue;
|
||||||
|
auto& instance = instances.PushDebug("Instance " + std::to_string(i++));
|
||||||
|
instance.PushDebug<AMFIntValue>("Score") = activityInstance->GetScore();
|
||||||
|
instance.PushDebug<AMFIntValue>("Next Zone Clone ID") = activityInstance->GetNextZoneCloneID();
|
||||||
|
|
||||||
|
{
|
||||||
|
auto& activityInfo = instance.PushDebug("Activity Info");
|
||||||
|
const auto& instanceActInfo = activityInstance->GetActivityInfo();
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("ActivityID") = instanceActInfo.ActivityID;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("locStatus") = instanceActInfo.locStatus;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("instanceMapID") = instanceActInfo.instanceMapID;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("minTeams") = instanceActInfo.minTeams;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("maxTeams") = instanceActInfo.maxTeams;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("minTeamSize") = instanceActInfo.minTeamSize;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("maxTeamSize") = instanceActInfo.maxTeamSize;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("waitTime") = instanceActInfo.waitTime;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("startDelay") = instanceActInfo.startDelay;
|
||||||
|
activityInfo.PushDebug<AMFBoolValue>("requiresUniqueData") = instanceActInfo.requiresUniqueData;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("leaderboardType") = instanceActInfo.leaderboardType;
|
||||||
|
activityInfo.PushDebug<AMFBoolValue>("localize") = instanceActInfo.localize;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("optionalCostLOT") = instanceActInfo.optionalCostLOT;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("optionalCostCount") = instanceActInfo.optionalCostCount;
|
||||||
|
activityInfo.PushDebug<AMFBoolValue>("showUIRewards") = instanceActInfo.showUIRewards;
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("CommunityActivityFlagID") = instanceActInfo.CommunityActivityFlagID;
|
||||||
|
activityInfo.PushDebug<AMFStringValue>("gate_version") = instanceActInfo.gate_version;
|
||||||
|
activityInfo.PushDebug<AMFBoolValue>("noTeamLootOnDeath") = instanceActInfo.noTeamLootOnDeath;
|
||||||
|
activityInfo.PushDebug<AMFDoubleValue>("optionalPercentage") = instanceActInfo.optionalPercentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& participants = instance.PushDebug("Participants");
|
||||||
|
for (const auto* participant : activityInstance->GetParticipants()) {
|
||||||
|
if (!participant) continue;
|
||||||
|
auto* character = participant->GetCharacter();
|
||||||
|
if (!character) continue;
|
||||||
|
participants.PushDebug<AMFStringValue>(std::to_string(participant->GetObjectID()) + ": " + character->GetName()) = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& queue = activityInfo.PushDebug("Queue");
|
||||||
|
i = 0;
|
||||||
|
for (const auto& lobbyQueue : m_Queue) {
|
||||||
|
auto& lobby = queue.PushDebug("Lobby " + std::to_string(i++));
|
||||||
|
lobby.PushDebug<AMFDoubleValue>("Timer") = lobbyQueue->timer;
|
||||||
|
|
||||||
|
auto& players = lobby.PushDebug("Players");
|
||||||
|
for (const auto* player : lobbyQueue->players) {
|
||||||
|
if (!player) continue;
|
||||||
|
auto* playerEntity = player->GetEntity();
|
||||||
|
if (!playerEntity) continue;
|
||||||
|
auto* character = playerEntity->GetCharacter();
|
||||||
|
if (!character) continue;
|
||||||
|
|
||||||
|
players.PushDebug<AMFStringValue>(std::to_string(playerEntity->GetObjectID()) + ": " + character->GetName()) = player->ready ? "Ready" : "Not Ready";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& activityPlayers = activityInfo.PushDebug("Activity Players");
|
||||||
|
for (const auto* activityPlayer : m_ActivityPlayers) {
|
||||||
|
if (!activityPlayer) continue;
|
||||||
|
auto* const activityPlayerEntity = Game::entityManager->GetEntity(activityPlayer->playerID);
|
||||||
|
if (!activityPlayerEntity) continue;
|
||||||
|
auto* character = activityPlayerEntity->GetCharacter();
|
||||||
|
if (!character) continue;
|
||||||
|
|
||||||
|
auto& playerData = activityPlayers.PushDebug(std::to_string(activityPlayer->playerID) + " " + character->GetName());
|
||||||
|
|
||||||
|
auto& scores = playerData.PushDebug("Scores");
|
||||||
|
for (size_t i = 0; i < 10; ++i) {
|
||||||
|
scores.PushDebug<AMFDoubleValue>(std::to_string(i)) = activityPlayer->values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& lootMatrices = activityInfo.PushDebug("Loot Matrices");
|
||||||
|
for (const auto& [activityRating, lootMatrixID] : m_ActivityLootMatrices) {
|
||||||
|
lootMatrices.PushDebug<AMFIntValue>("Loot Matrix " + std::to_string(activityRating)) = lootMatrixID;
|
||||||
|
}
|
||||||
|
activityInfo.PushDebug<AMFIntValue>("ActivityID") = m_ActivityID;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
|
|
||||||
|
namespace GameMessages {
|
||||||
|
class GameMsg;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an instance of an activity, having participants and score
|
* Represents an instance of an activity, having participants and score
|
||||||
*/
|
*/
|
||||||
@@ -60,6 +64,10 @@ public:
|
|||||||
* Currently unused
|
* Currently unused
|
||||||
*/
|
*/
|
||||||
void SetScore(uint32_t score);
|
void SetScore(uint32_t score);
|
||||||
|
|
||||||
|
[[nodiscard]] uint32_t GetNextZoneCloneID() const noexcept { return m_NextZoneCloneID; }
|
||||||
|
|
||||||
|
const CDActivities& GetActivityInfo() const noexcept { return m_ActivityInfo; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -75,12 +83,12 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The database information for this activity
|
* The database information for this activity
|
||||||
*/
|
*/
|
||||||
CDActivities m_ActivityInfo;
|
CDActivities m_ActivityInfo{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity that owns this activity (the entity that has the ScriptedActivityComponent)
|
* The entity that owns this activity (the entity that has the ScriptedActivityComponent)
|
||||||
*/
|
*/
|
||||||
Entity* m_Parent;
|
Entity* m_Parent{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the participants of this activity
|
* All the participants of this activity
|
||||||
@@ -341,6 +349,7 @@ public:
|
|||||||
uint32_t GetLootMatrixForTeamSize(uint32_t teamSize) { return m_ActivityLootMatrices[teamSize]; }
|
uint32_t GetLootMatrixForTeamSize(uint32_t teamSize) { return m_ActivityLootMatrices[teamSize]; }
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
/**
|
/**
|
||||||
* The database information for this activity
|
* The database information for this activity
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -49,19 +49,13 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character, con
|
|||||||
m_LastUpdateTimestamp = std::time(nullptr);
|
m_LastUpdateTimestamp = std::time(nullptr);
|
||||||
m_SystemAddress = systemAddress;
|
m_SystemAddress = systemAddress;
|
||||||
|
|
||||||
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &CharacterComponent::OnRequestServerObjectInfo);
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &CharacterComponent::OnGetObjectReportInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
auto& request = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
AMFArrayValue response;
|
|
||||||
|
|
||||||
response.Insert("visible", true);
|
auto& cmptType = reportInfo.info->PushDebug("Character");
|
||||||
response.Insert("objectID", std::to_string(request.targetForReport));
|
|
||||||
response.Insert("serverInfo", true);
|
|
||||||
|
|
||||||
auto& data = *response.InsertArray("data");
|
|
||||||
auto& cmptType = data.PushDebug("Character");
|
|
||||||
|
|
||||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GeneralUtils::ToUnderlying(ComponentType);
|
cmptType.PushDebug<AMFIntValue>("Component ID") = GeneralUtils::ToUnderlying(ComponentType);
|
||||||
cmptType.PushDebug<AMFIntValue>("Character's account ID") = m_Character->GetParentUser()->GetAccountID();
|
cmptType.PushDebug<AMFIntValue>("Character's account ID") = m_Character->GetParentUser()->GetAccountID();
|
||||||
@@ -72,6 +66,13 @@ bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|||||||
cmptType.PushDebug<AMFStringValue>("Total currency") = std::to_string(m_Character->GetCoins());
|
cmptType.PushDebug<AMFStringValue>("Total currency") = std::to_string(m_Character->GetCoins());
|
||||||
cmptType.PushDebug<AMFStringValue>("Currency able to be picked up") = std::to_string(m_DroppedCoins);
|
cmptType.PushDebug<AMFStringValue>("Currency able to be picked up") = std::to_string(m_DroppedCoins);
|
||||||
cmptType.PushDebug<AMFStringValue>("Tooltip flags value") = "0";
|
cmptType.PushDebug<AMFStringValue>("Tooltip flags value") = "0";
|
||||||
|
auto& vl = cmptType.PushDebug("Visited Levels");
|
||||||
|
for (const auto zoneID : m_VisitedLevels) {
|
||||||
|
std::stringstream sstream;
|
||||||
|
sstream << "MapID: " << zoneID.GetMapID() << " CloneID: " << zoneID.GetCloneID();
|
||||||
|
vl.PushDebug<AMFStringValue>(sstream.str()) = "";
|
||||||
|
}
|
||||||
|
|
||||||
// visited locations
|
// visited locations
|
||||||
cmptType.PushDebug<AMFBoolValue>("is a GM") = m_GMLevel > eGameMasterLevel::CIVILIAN;
|
cmptType.PushDebug<AMFBoolValue>("is a GM") = m_GMLevel > eGameMasterLevel::CIVILIAN;
|
||||||
cmptType.PushDebug<AMFBoolValue>("Has PVP flag turned on") = m_PvpEnabled;
|
cmptType.PushDebug<AMFBoolValue>("Has PVP flag turned on") = m_PvpEnabled;
|
||||||
@@ -83,9 +84,6 @@ bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|||||||
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
||||||
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, m_Parent->GetSystemAddress());
|
|
||||||
|
|
||||||
LOG("Handled!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ public:
|
|||||||
void LoadVisitedLevelsXml(const tinyxml2::XMLElement& doc);
|
void LoadVisitedLevelsXml(const tinyxml2::XMLElement& doc);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool OnRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map of active venture vision effects
|
* The map of active venture vision effects
|
||||||
|
|||||||
@@ -56,10 +56,16 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
|
inline void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
|
||||||
m_Parent->RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
m_Parent->RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void RegisterMsg(auto* self, const auto handler) {
|
||||||
|
T msg;
|
||||||
|
RegisterMsg(msg.msgId, self, handler);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity that owns this component
|
* The entity that owns this component
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,8 +14,12 @@
|
|||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
#include "LevelProgressionComponent.h"
|
#include "LevelProgressionComponent.h"
|
||||||
#include "eStateChangeType.h"
|
#include "eStateChangeType.h"
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, int32_t componentId) : PhysicsComponent(entity, componentId) {
|
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, int32_t componentId) : PhysicsComponent(entity, componentId) {
|
||||||
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &ControllablePhysicsComponent::OnGetObjectReportInfo);
|
||||||
|
|
||||||
m_Velocity = {};
|
m_Velocity = {};
|
||||||
m_AngularVelocity = {};
|
m_AngularVelocity = {};
|
||||||
m_InJetpackMode = false;
|
m_InJetpackMode = false;
|
||||||
@@ -354,3 +358,58 @@ void ControllablePhysicsComponent::SetStunImmunity(
|
|||||||
bImmuneToStunUseItem
|
bImmuneToStunUseItem
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ControllablePhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
PhysicsComponent::OnGetObjectReportInfo(msg);
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
auto& info = reportInfo.subCategory->PushDebug("Controllable Info");
|
||||||
|
|
||||||
|
auto& vel = info.PushDebug("Velocity");
|
||||||
|
vel.PushDebug<AMFDoubleValue>("x") = m_Velocity.x;
|
||||||
|
vel.PushDebug<AMFDoubleValue>("y") = m_Velocity.y;
|
||||||
|
vel.PushDebug<AMFDoubleValue>("z") = m_Velocity.z;
|
||||||
|
|
||||||
|
auto& angularVelocity = info.PushDebug("Angular Velocity");
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("x") = m_AngularVelocity.x;
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("y") = m_AngularVelocity.y;
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("z") = m_AngularVelocity.z;
|
||||||
|
|
||||||
|
info.PushDebug<AMFBoolValue>("Is On Ground") = m_IsOnGround;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is On Rail") = m_IsOnRail;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is In Jetpack Mode") = m_InJetpackMode;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is Jetpack Flying") = m_JetpackFlying;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is Bypassing Jetpack Checks") = m_JetpackBypassChecks;
|
||||||
|
info.PushDebug<AMFIntValue>("Jetpack Effect ID") = m_JetpackEffectID;
|
||||||
|
info.PushDebug<AMFDoubleValue>("Speed Multiplier") = m_SpeedMultiplier;
|
||||||
|
info.PushDebug<AMFDoubleValue>("Gravity Scale") = m_GravityScale;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is Static") = m_Static;
|
||||||
|
|
||||||
|
auto& pickupRadii = info.PushDebug("Active Pickup Radius Scales");
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto& scale : m_ActivePickupRadiusScales) {
|
||||||
|
pickupRadii.PushDebug<AMFStringValue>(std::to_string(i++) + " " + std::to_string(scale)) = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
info.PushDebug<AMFDoubleValue>("Largest Pickup Radius") = m_PickupRadius;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is Teleporting") = m_IsTeleporting;
|
||||||
|
|
||||||
|
auto& activeSpeedBoosts = info.PushDebug("Active Speed Boosts");
|
||||||
|
i = 0;
|
||||||
|
for (const auto& boost : m_ActiveSpeedBoosts) {
|
||||||
|
activeSpeedBoosts.PushDebug<AMFStringValue>(std::to_string(i++) + " " + std::to_string(boost)) = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
info.PushDebug<AMFDoubleValue>("Speed Boost") = m_SpeedBoost;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is In Bubble") = m_IsInBubble;
|
||||||
|
info.PushDebug<AMFStringValue>("Bubble Type") = StringifiedEnum::ToString(m_BubbleType).data();
|
||||||
|
info.PushDebug<AMFBoolValue>("Special Anims") = m_SpecialAnims;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun Attack Count") = m_ImmuneToStunAttackCount;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun Equip Count") = m_ImmuneToStunEquipCount;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun Interact Count") = m_ImmuneToStunInteractCount;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun Jump Count") = m_ImmuneToStunJumpCount;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun Move Count") = m_ImmuneToStunMoveCount;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun Turn Count") = m_ImmuneToStunTurnCount;
|
||||||
|
info.PushDebug<AMFIntValue>("Immune To Stun UseItem Count") = m_ImmuneToStunUseItemCount;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
#ifndef CONTROLLABLEPHYSICSCOMPONENT_H
|
#ifndef CONTROLLABLEPHYSICSCOMPONENT_H
|
||||||
#define CONTROLLABLEPHYSICSCOMPONENT_H
|
#define CONTROLLABLEPHYSICSCOMPONENT_H
|
||||||
|
|
||||||
|
#include "PhysicsComponent.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "RakNetTypes.h"
|
#include "RakNetTypes.h"
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
#include "NiQuaternion.h"
|
#include "NiQuaternion.h"
|
||||||
#include "tinyxml2.h"
|
|
||||||
#include "PhysicsComponent.h"
|
|
||||||
#include "dpCollisionChecks.h"
|
#include "dpCollisionChecks.h"
|
||||||
#include "PhantomPhysicsComponent.h"
|
|
||||||
#include "eBubbleType.h"
|
#include "eBubbleType.h"
|
||||||
#include "eReplicaComponentType.h"
|
|
||||||
|
namespace tinyxml2 {
|
||||||
|
class XMLDocument;
|
||||||
|
}
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
class dpEntity;
|
class dpEntity;
|
||||||
@@ -281,6 +283,8 @@ public:
|
|||||||
const bool GetImmuneToStunUseItem() { return m_ImmuneToStunUseItemCount > 0;};
|
const bool GetImmuneToStunUseItem() { return m_ImmuneToStunUseItemCount > 0;};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
/**
|
/**
|
||||||
* The entity that owns this component
|
* The entity that owns this component
|
||||||
*/
|
*/
|
||||||
@@ -374,7 +378,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The active speed boost for this entity
|
* The active speed boost for this entity
|
||||||
*/
|
*/
|
||||||
float m_SpeedBoost;
|
float m_SpeedBoost = 500.0f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If Bubble info is dirty
|
* If Bubble info is dirty
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "BuffComponent.h"
|
#include "BuffComponent.h"
|
||||||
#include "SkillComponent.h"
|
#include "SkillComponent.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
|
#include "ModelComponent.h"
|
||||||
#include "InventoryComponent.h"
|
#include "InventoryComponent.h"
|
||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
#include "WorldConfig.h"
|
#include "WorldConfig.h"
|
||||||
@@ -42,6 +44,7 @@ Implementation<bool, const Entity*> DestroyableComponent::IsEnemyImplentation;
|
|||||||
Implementation<bool, const Entity*> DestroyableComponent::IsFriendImplentation;
|
Implementation<bool, const Entity*> DestroyableComponent::IsFriendImplentation;
|
||||||
|
|
||||||
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
||||||
|
using namespace GameMessages;
|
||||||
m_iArmor = 0;
|
m_iArmor = 0;
|
||||||
m_fMaxArmor = 0.0f;
|
m_fMaxArmor = 0.0f;
|
||||||
m_iImagination = 0;
|
m_iImagination = 0;
|
||||||
@@ -78,6 +81,9 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
|||||||
m_DeathBehavior = -1;
|
m_DeathBehavior = -1;
|
||||||
|
|
||||||
m_DamageCooldownTimer = 0.0f;
|
m_DamageCooldownTimer = 0.0f;
|
||||||
|
|
||||||
|
RegisterMsg<GetObjectReportInfo>(this, &DestroyableComponent::OnGetObjectReportInfo);
|
||||||
|
RegisterMsg<GameMessages::SetFaction>(this, &DestroyableComponent::OnSetFaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
DestroyableComponent::~DestroyableComponent() {
|
DestroyableComponent::~DestroyableComponent() {
|
||||||
@@ -575,6 +581,14 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Client does the same check, so we're doing it too
|
||||||
|
auto* const modelComponent = m_Parent->GetComponent<ModelComponent>();
|
||||||
|
if (modelComponent) {
|
||||||
|
modelComponent->OnHit();
|
||||||
|
// Don't actually deal the damage so the model doesn't die
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If this entity has damage reduction, reduce the damage to a minimum of 1
|
// If this entity has damage reduction, reduce the damage to a minimum of 1
|
||||||
if (m_DamageReduction > 0 && damage > 0) {
|
if (m_DamageReduction > 0 && damage > 0) {
|
||||||
if (damage > m_DamageReduction) {
|
if (damage > m_DamageReduction) {
|
||||||
@@ -1031,3 +1045,65 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DestroyableComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
|
||||||
|
auto& destroyableInfo = reportInfo.info->PushDebug("Destroyable");
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Health") = m_iHealth;
|
||||||
|
destroyableInfo.PushDebug<AMFDoubleValue>("Max Health") = m_fMaxHealth;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Armor") = m_iArmor;
|
||||||
|
destroyableInfo.PushDebug<AMFDoubleValue>("Max Armor") = m_fMaxArmor;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Imagination") = m_iImagination;
|
||||||
|
destroyableInfo.PushDebug<AMFDoubleValue>("Max Imagination") = m_fMaxImagination;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Damage To Absorb") = m_DamageToAbsorb;
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Is GM Immune") = m_IsGMImmune;
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Is Shielded") = m_IsShielded;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Attacks To Block") = m_AttacksToBlock;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Damage Reduction") = m_DamageReduction;
|
||||||
|
auto& factions = destroyableInfo.PushDebug("Factions");
|
||||||
|
size_t i = 0;
|
||||||
|
for (const auto factionID : m_FactionIDs) {
|
||||||
|
factions.PushDebug<AMFStringValue>(std::to_string(i++) + " " + std::to_string(factionID)) = "";
|
||||||
|
}
|
||||||
|
auto& enemyFactions = destroyableInfo.PushDebug("Enemy Factions");
|
||||||
|
i = 0;
|
||||||
|
for (const auto enemyFactionID : m_EnemyFactionIDs) {
|
||||||
|
enemyFactions.PushDebug<AMFStringValue>(std::to_string(i++) + " " + std::to_string(enemyFactionID)) = "";
|
||||||
|
}
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Is Smashable") = m_IsSmashable;
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Is Dead") = m_IsDead;
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Is Smashed") = m_IsSmashed;
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Is Module Assembly") = m_IsModuleAssembly;
|
||||||
|
destroyableInfo.PushDebug<AMFDoubleValue>("Explode Factor") = m_ExplodeFactor;
|
||||||
|
destroyableInfo.PushDebug<AMFBoolValue>("Has Threats") = m_HasThreats;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Loot Matrix ID") = m_LootMatrixID;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Min Coins") = m_MinCoins;
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Max Coins") = m_MaxCoins;
|
||||||
|
destroyableInfo.PushDebug<AMFStringValue>("Killer ID") = std::to_string(m_KillerID);
|
||||||
|
|
||||||
|
// "Scripts"; idk what to do about scripts yet
|
||||||
|
auto& immuneCounts = destroyableInfo.PushDebug("Immune Counts");
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Basic Attack") = m_ImmuneToBasicAttackCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Damage Over Time") = m_ImmuneToDamageOverTimeCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Knockback") = m_ImmuneToKnockbackCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Interrupt") = m_ImmuneToInterruptCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Speed") = m_ImmuneToSpeedCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Imagination Gain") = m_ImmuneToImaginationGainCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Imagination Loss") = m_ImmuneToImaginationLossCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Quickbuild Interrupt") = m_ImmuneToQuickbuildInterruptCount;
|
||||||
|
immuneCounts.PushDebug<AMFIntValue>("Pull To Point") = m_ImmuneToPullToPointCount;
|
||||||
|
|
||||||
|
destroyableInfo.PushDebug<AMFIntValue>("Death Behavior") = m_DeathBehavior;
|
||||||
|
destroyableInfo.PushDebug<AMFDoubleValue>("Damage Cooldown Timer") = m_DamageCooldownTimer;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DestroyableComponent::OnSetFaction(GameMessages::GameMsg& msg) {
|
||||||
|
auto& modifyFaction = static_cast<GameMessages::SetFaction&>(msg);
|
||||||
|
m_DirtyHealth = true;
|
||||||
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
SetFaction(modifyFaction.factionID, modifyFaction.bIgnoreChecks);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
#include "Implementation.h"
|
#include "Implementation.h"
|
||||||
|
|
||||||
|
namespace GameMessages {
|
||||||
|
struct GetObjectReportInfo;
|
||||||
|
};
|
||||||
|
|
||||||
namespace CppScripts {
|
namespace CppScripts {
|
||||||
class Script;
|
class Script;
|
||||||
}; //! namespace CppScripts
|
}; //! namespace CppScripts
|
||||||
@@ -464,6 +468,9 @@ public:
|
|||||||
// handle hardcode mode drops
|
// handle hardcode mode drops
|
||||||
void DoHardcoreModeDrops(const LWOOBJID source);
|
void DoHardcoreModeDrops(const LWOOBJID source);
|
||||||
|
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
bool OnSetFaction(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
static Implementation<bool, const Entity*> IsEnemyImplentation;
|
static Implementation<bool, const Entity*> IsEnemyImplentation;
|
||||||
static Implementation<bool, const Entity*> IsFriendImplentation;
|
static Implementation<bool, const Entity*> IsFriendImplentation;
|
||||||
|
|
||||||
@@ -591,7 +598,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The ID of the entity that smashed this entity, if any
|
* The ID of the entity that smashed this entity, if any
|
||||||
*/
|
*/
|
||||||
LWOOBJID m_KillerID;
|
LWOOBJID m_KillerID{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of callbacks that will be called when this entity gets hit
|
* The list of callbacks that will be called when this entity gets hit
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include "HavokVehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
||||||
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &HavokVehiclePhysicsComponent::OnGetObjectReportInfo);
|
||||||
|
|
||||||
m_Velocity = NiPoint3Constant::ZERO;
|
m_Velocity = NiPoint3Constant::ZERO;
|
||||||
m_AngularVelocity = NiPoint3Constant::ZERO;
|
m_AngularVelocity = NiPoint3Constant::ZERO;
|
||||||
m_IsOnGround = true;
|
m_IsOnGround = true;
|
||||||
@@ -98,3 +101,34 @@ void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
|
|||||||
|
|
||||||
outBitStream.Write0();
|
outBitStream.Write0();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HavokVehiclePhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
PhysicsComponent::OnGetObjectReportInfo(msg);
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
if (!reportInfo.subCategory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& info = reportInfo.subCategory->PushDebug("Havok Vehicle Physics Info");
|
||||||
|
|
||||||
|
auto& velocity = info.PushDebug("Velocity");
|
||||||
|
velocity.PushDebug<AMFDoubleValue>("x") = m_Velocity.x;
|
||||||
|
velocity.PushDebug<AMFDoubleValue>("y") = m_Velocity.y;
|
||||||
|
velocity.PushDebug<AMFDoubleValue>("z") = m_Velocity.z;
|
||||||
|
|
||||||
|
auto& angularVelocity = info.PushDebug("Angular Velocity");
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("x") = m_AngularVelocity.x;
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("y") = m_AngularVelocity.y;
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("z") = m_AngularVelocity.z;
|
||||||
|
|
||||||
|
info.PushDebug<AMFBoolValue>("Is On Ground") = m_IsOnGround;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is On Rail") = m_IsOnRail;
|
||||||
|
info.PushDebug<AMFIntValue>("End Behavior") = m_EndBehavior;
|
||||||
|
|
||||||
|
auto& remoteInputInfo = info.PushDebug("Remote Input Info");
|
||||||
|
remoteInputInfo.PushDebug<AMFDoubleValue>("Remote Input X") = m_RemoteInputInfo.m_RemoteInputX;
|
||||||
|
remoteInputInfo.PushDebug<AMFDoubleValue>("Remote Input Y") = m_RemoteInputInfo.m_RemoteInputY;
|
||||||
|
remoteInputInfo.PushDebug<AMFBoolValue>("Is Powersliding") = m_RemoteInputInfo.m_IsPowersliding;
|
||||||
|
remoteInputInfo.PushDebug<AMFBoolValue>("Is Modified") = m_RemoteInputInfo.m_IsModified;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ public:
|
|||||||
void SetRemoteInputInfo(const RemoteInputInfo&);
|
void SetRemoteInputInfo(const RemoteInputInfo&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
NiPoint3 m_Velocity;
|
NiPoint3 m_Velocity;
|
||||||
NiPoint3 m_AngularVelocity;
|
NiPoint3 m_AngularVelocity;
|
||||||
|
|
||||||
|
|||||||
@@ -1777,7 +1777,7 @@ void InventoryComponent::LoadGroupXml(const tinyxml2::XMLElement& groups) {
|
|||||||
group.groupId = groupId;
|
group.groupId = groupId;
|
||||||
group.groupName = groupName;
|
group.groupName = groupName;
|
||||||
|
|
||||||
for (const auto& lotStr : GeneralUtils::SplitString(std::string_view(lots), ' ')) {
|
for (const auto& lotStr : GeneralUtils::SplitString(lots, ' ')) {
|
||||||
auto lot = GeneralUtils::TryParse<LOT>(lotStr);
|
auto lot = GeneralUtils::TryParse<LOT>(lotStr);
|
||||||
if (lot) group.lots.insert(*lot);
|
if (lot) group.lots.insert(*lot);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,15 @@
|
|||||||
#include "DluAssert.h"
|
#include "DluAssert.h"
|
||||||
|
|
||||||
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||||
|
using namespace GameMessages;
|
||||||
m_OriginalPosition = m_Parent->GetDefaultPosition();
|
m_OriginalPosition = m_Parent->GetDefaultPosition();
|
||||||
m_OriginalRotation = m_Parent->GetDefaultRotation();
|
m_OriginalRotation = m_Parent->GetDefaultRotation();
|
||||||
m_IsPaused = false;
|
m_IsPaused = false;
|
||||||
m_NumListeningInteract = 0;
|
m_NumListeningInteract = 0;
|
||||||
|
|
||||||
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
||||||
RegisterMsg(MessageType::Game::REQUEST_USE, this, &ModelComponent::OnRequestUse);
|
RegisterMsg<RequestUse>(this, &ModelComponent::OnRequestUse);
|
||||||
RegisterMsg(MessageType::Game::RESET_MODEL_TO_DEFAULTS, this, &ModelComponent::OnResetModelToDefaults);
|
RegisterMsg<ResetModelToDefaults>(this, &ModelComponent::OnResetModelToDefaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
|
bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
|
||||||
@@ -40,6 +41,14 @@ bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
|
|||||||
m_Speed = 3.0f;
|
m_Speed = 3.0f;
|
||||||
m_NumListeningInteract = 0;
|
m_NumListeningInteract = 0;
|
||||||
m_NumActiveUnSmash = 0;
|
m_NumActiveUnSmash = 0;
|
||||||
|
|
||||||
|
m_NumActiveAttack = 0;
|
||||||
|
GameMessages::SetFaction set{};
|
||||||
|
set.target = m_Parent->GetObjectID();
|
||||||
|
set.factionID = -1; // Default faction for smashables
|
||||||
|
set.bIgnoreChecks = true; // Remove the attack faction
|
||||||
|
set.Send();
|
||||||
|
|
||||||
m_Dirty = true;
|
m_Dirty = true;
|
||||||
Game::entityManager->SerializeEntity(GetParent());
|
Game::entityManager->SerializeEntity(GetParent());
|
||||||
|
|
||||||
@@ -297,3 +306,35 @@ void ModelComponent::SetVelocity(const NiPoint3& velocity) const {
|
|||||||
void ModelComponent::OnChatMessageReceived(const std::string& sMessage) {
|
void ModelComponent::OnChatMessageReceived(const std::string& sMessage) {
|
||||||
for (auto& behavior : m_Behaviors) behavior.OnChatMessageReceived(sMessage);
|
for (auto& behavior : m_Behaviors) behavior.OnChatMessageReceived(sMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModelComponent::OnHit() {
|
||||||
|
for (auto& behavior : m_Behaviors) {
|
||||||
|
behavior.OnHit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelComponent::AddAttack() {
|
||||||
|
LOG_DEBUG("Adding attack %i", m_NumActiveAttack);
|
||||||
|
m_Dirty = true;
|
||||||
|
if (m_NumActiveAttack == 0) {
|
||||||
|
GameMessages::SetFaction set{};
|
||||||
|
set.target = m_Parent->GetObjectID();
|
||||||
|
set.factionID = 6; // Default faction for smashables
|
||||||
|
set.Send();
|
||||||
|
}
|
||||||
|
m_NumActiveAttack++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModelComponent::RemoveAttack() {
|
||||||
|
LOG_DEBUG("Removing attack %i", m_NumActiveAttack);
|
||||||
|
DluAssert(m_NumActiveAttack > 0);
|
||||||
|
m_Dirty = true;
|
||||||
|
m_NumActiveAttack--;
|
||||||
|
if (m_NumActiveAttack == 0) {
|
||||||
|
GameMessages::SetFaction set{};
|
||||||
|
set.target = m_Parent->GetObjectID();
|
||||||
|
set.factionID = -1; // Default faction for smashables
|
||||||
|
set.bIgnoreChecks = true; // Remove the attack faction
|
||||||
|
set.Send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -146,11 +146,21 @@ public:
|
|||||||
|
|
||||||
void OnChatMessageReceived(const std::string& sMessage);
|
void OnChatMessageReceived(const std::string& sMessage);
|
||||||
|
|
||||||
|
void OnHit();
|
||||||
|
|
||||||
// Sets the speed of the model
|
// Sets the speed of the model
|
||||||
void SetSpeed(const float newSpeed) { m_Speed = newSpeed; }
|
void SetSpeed(const float newSpeed) { m_Speed = newSpeed; }
|
||||||
|
|
||||||
// Whether or not to restart at the end of the frame
|
// Whether or not to restart at the end of the frame
|
||||||
void RestartAtEndOfFrame() { m_RestartAtEndOfFrame = true; }
|
void RestartAtEndOfFrame() { m_RestartAtEndOfFrame = true; }
|
||||||
|
|
||||||
|
// Increments the number of strips listening for an attack.
|
||||||
|
// If this is the first strip adding an attack, it will set the factions to the correct values.
|
||||||
|
void AddAttack();
|
||||||
|
|
||||||
|
// Decrements the number of strips listening for an attack.
|
||||||
|
// If this is the last strip removing an attack, it will reset the factions to the default of -1.
|
||||||
|
void RemoveAttack();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Loads a behavior from the database.
|
// Loads a behavior from the database.
|
||||||
@@ -168,6 +178,9 @@ private:
|
|||||||
// The number of strips listening for a RequestUse GM to come in.
|
// The number of strips listening for a RequestUse GM to come in.
|
||||||
uint32_t m_NumListeningInteract{};
|
uint32_t m_NumListeningInteract{};
|
||||||
|
|
||||||
|
// The number of strips listening for an attack.
|
||||||
|
uint32_t m_NumActiveAttack{};
|
||||||
|
|
||||||
// Whether or not the model is paused and should reject all interactions regarding behaviors.
|
// Whether or not the model is paused and should reject all interactions regarding behaviors.
|
||||||
bool m_IsPaused{};
|
bool m_IsPaused{};
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
#include "QuickBuildComponent.h"
|
||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
|
||||||
#include "dNavMesh.h"
|
#include "dNavMesh.h"
|
||||||
@@ -89,6 +90,9 @@ void MovementAIComponent::Resume() {
|
|||||||
void MovementAIComponent::Update(const float deltaTime) {
|
void MovementAIComponent::Update(const float deltaTime) {
|
||||||
if (m_Paused) return;
|
if (m_Paused) return;
|
||||||
|
|
||||||
|
auto* const quickBuildComponent = m_Parent->GetComponent<QuickBuildComponent>();
|
||||||
|
if (quickBuildComponent && quickBuildComponent->GetState() != eQuickBuildState::COMPLETED) return;
|
||||||
|
|
||||||
if (m_PullingToPoint) {
|
if (m_PullingToPoint) {
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentWaypoint();
|
||||||
|
|
||||||
@@ -154,6 +158,7 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
||||||
|
const auto waypointNum = m_IsBounced ? m_CurrentPath.size() : m_CurrentPathWaypointCount - m_CurrentPath.size() - 1;
|
||||||
if (m_CurrentPath.empty()) {
|
if (m_CurrentPath.empty()) {
|
||||||
if (m_Path) {
|
if (m_Path) {
|
||||||
if (m_Path->pathBehavior == PathBehavior::Loop) {
|
if (m_Path->pathBehavior == PathBehavior::Loop) {
|
||||||
@@ -161,20 +166,24 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
||||||
m_IsBounced = !m_IsBounced;
|
m_IsBounced = !m_IsBounced;
|
||||||
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
|
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
|
||||||
if (m_IsBounced) std::reverse(waypoints.begin(), waypoints.end());
|
if (m_IsBounced) std::ranges::reverse(waypoints);
|
||||||
SetPath(waypoints);
|
SetPath(waypoints);
|
||||||
} else if (m_Path->pathBehavior == PathBehavior::Once) {
|
} else if (m_Path->pathBehavior == PathBehavior::Once) {
|
||||||
|
m_Parent->GetScript()->OnWaypointReached(m_Parent, waypointNum);
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
m_Parent->GetScript()->OnWaypointReached(m_Parent, waypointNum);
|
||||||
Stop();
|
Stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
SetDestination(m_CurrentPath.top().position);
|
m_Parent->GetScript()->OnWaypointReached(m_Parent, waypointNum);
|
||||||
|
SetDestination(m_CurrentPath.top().position);
|
||||||
|
|
||||||
m_CurrentPath.pop();
|
m_CurrentPath.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
@@ -250,6 +259,7 @@ void MovementAIComponent::Stop() {
|
|||||||
|
|
||||||
m_InterpolatedWaypoints.clear();
|
m_InterpolatedWaypoints.clear();
|
||||||
while (!m_CurrentPath.empty()) m_CurrentPath.pop();
|
while (!m_CurrentPath.empty()) m_CurrentPath.pop();
|
||||||
|
m_CurrentPathWaypointCount = 0;
|
||||||
|
|
||||||
m_PathIndex = 0;
|
m_PathIndex = 0;
|
||||||
|
|
||||||
@@ -272,6 +282,7 @@ void MovementAIComponent::SetPath(std::vector<PathWaypoint> path) {
|
|||||||
this->m_CurrentPath.push(point);
|
this->m_CurrentPath.push(point);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m_CurrentPathWaypointCount = path.size();
|
||||||
SetDestination(path.front().position);
|
SetDestination(path.front().position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
static float GetBaseSpeed(LOT lot);
|
static float GetBaseSpeed(LOT lot);
|
||||||
|
|
||||||
|
bool IsPaused() const { return m_Paused; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,6 +325,9 @@ private:
|
|||||||
NiPoint3 m_SavedVelocity;
|
NiPoint3 m_SavedVelocity;
|
||||||
|
|
||||||
bool m_IsBounced{};
|
bool m_IsBounced{};
|
||||||
|
|
||||||
|
// The number of waypoints that were on the path in the call to SetPath
|
||||||
|
uint32_t m_CurrentPathWaypointCount{ 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOVEMENTAICOMPONENT_H
|
#endif // MOVEMENTAICOMPONENT_H
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "EntityInfo.h"
|
#include "EntityInfo.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
#include "dpWorld.h"
|
#include "dpWorld.h"
|
||||||
#include "dpEntity.h"
|
#include "dpEntity.h"
|
||||||
@@ -28,6 +29,8 @@
|
|||||||
#include "dpShapeSphere.h"
|
#include "dpShapeSphere.h"
|
||||||
|
|
||||||
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
||||||
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &PhantomPhysicsComponent::OnGetObjectReportInfo);
|
||||||
|
|
||||||
m_Position = m_Parent->GetDefaultPosition();
|
m_Position = m_Parent->GetDefaultPosition();
|
||||||
m_Rotation = m_Parent->GetDefaultRotation();
|
m_Rotation = m_Parent->GetDefaultRotation();
|
||||||
m_Scale = m_Parent->GetDefaultScale();
|
m_Scale = m_Parent->GetDefaultScale();
|
||||||
@@ -238,3 +241,43 @@ void PhantomPhysicsComponent::SetRotation(const NiQuaternion& rot) {
|
|||||||
PhysicsComponent::SetRotation(rot);
|
PhysicsComponent::SetRotation(rot);
|
||||||
if (m_dpEntity) m_dpEntity->SetRotation(rot);
|
if (m_dpEntity) m_dpEntity->SetRotation(rot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PhantomPhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
PhysicsComponent::OnGetObjectReportInfo(msg);
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
if (!reportInfo.subCategory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto& info = reportInfo.subCategory->PushDebug("Phantom Physics Info");
|
||||||
|
info.PushDebug<AMFDoubleValue>("Scale") = m_Scale;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is Physics Effect Active") = m_IsPhysicsEffectActive;
|
||||||
|
info.PushDebug<AMFIntValue>("Effect Type") = static_cast<int>(m_EffectType);
|
||||||
|
info.PushDebug<AMFDoubleValue>("Directional Multiplier") = m_DirectionalMultiplier;
|
||||||
|
info.PushDebug<AMFBoolValue>("Is Directional") = m_IsDirectional;
|
||||||
|
auto& direction = info.PushDebug("Direction");
|
||||||
|
direction.PushDebug<AMFDoubleValue>("x") = m_Direction.x;
|
||||||
|
direction.PushDebug<AMFDoubleValue>("y") = m_Direction.y;
|
||||||
|
direction.PushDebug<AMFDoubleValue>("z") = m_Direction.z;
|
||||||
|
|
||||||
|
if (m_MinMax) {
|
||||||
|
auto& minMaxInfo = info.PushDebug("Min Max Info");
|
||||||
|
minMaxInfo.PushDebug<AMFIntValue>("Min") = m_Min;
|
||||||
|
minMaxInfo.PushDebug<AMFIntValue>("Max") = m_Max;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_IsRespawnVolume) {
|
||||||
|
auto& respawnInfo = info.PushDebug("Respawn Info");
|
||||||
|
respawnInfo.PushDebug<AMFBoolValue>("Is Respawn Volume") = m_IsRespawnVolume;
|
||||||
|
auto& respawnPos = respawnInfo.PushDebug("Respawn Position");
|
||||||
|
respawnPos.PushDebug<AMFDoubleValue>("x") = m_RespawnPos.x;
|
||||||
|
respawnPos.PushDebug<AMFDoubleValue>("y") = m_RespawnPos.y;
|
||||||
|
respawnPos.PushDebug<AMFDoubleValue>("z") = m_RespawnPos.z;
|
||||||
|
auto& respawnRot = respawnInfo.PushDebug("Respawn Rotation");
|
||||||
|
respawnRot.PushDebug<AMFDoubleValue>("w") = m_RespawnRot.w;
|
||||||
|
respawnRot.PushDebug<AMFDoubleValue>("x") = m_RespawnRot.x;
|
||||||
|
respawnRot.PushDebug<AMFDoubleValue>("y") = m_RespawnRot.y;
|
||||||
|
respawnRot.PushDebug<AMFDoubleValue>("z") = m_RespawnRot.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
#include "NiQuaternion.h"
|
#include "NiQuaternion.h"
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "CppScripts.h"
|
|
||||||
#include "InvalidScript.h"
|
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
#include "PhysicsComponent.h"
|
#include "PhysicsComponent.h"
|
||||||
|
|
||||||
@@ -118,6 +116,8 @@ public:
|
|||||||
void SetMax(uint32_t max);
|
void SetMax(uint32_t max);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scale to apply to the size of the physics object
|
* A scale to apply to the size of the physics object
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "dpShapeSphere.h"
|
#include "dpShapeSphere.h"
|
||||||
|
|
||||||
#include "EntityInfo.h"
|
#include "EntityInfo.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Component(parent) {
|
PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Component(parent) {
|
||||||
m_Position = NiPoint3Constant::ZERO;
|
m_Position = NiPoint3Constant::ZERO;
|
||||||
@@ -97,9 +98,9 @@ dpEntity* PhysicsComponent::CreatePhysicsEntity(eReplicaComponentType type) {
|
|||||||
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume2_RoadGaps.hkx") {
|
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume2_RoadGaps.hkx") {
|
||||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 48.386536f, 50.363434f, 259.361755f);
|
toReturn = new dpEntity(m_Parent->GetObjectID(), 48.386536f, 50.363434f, 259.361755f);
|
||||||
} */ else {
|
} */ else {
|
||||||
// LOG_DEBUG("This one is supposed to have %s", info->physicsAsset.c_str());
|
// LOG_DEBUG("This one is supposed to have %s", info->physicsAsset.c_str());
|
||||||
|
|
||||||
//add fallback cube:
|
//add fallback cube:
|
||||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 2.0f, 2.0f, 2.0f);
|
toReturn = new dpEntity(m_Parent->GetObjectID(), 2.0f, 2.0f, 2.0f);
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
@@ -243,3 +244,24 @@ void PhysicsComponent::SpawnVertices(dpEntity* entity) const {
|
|||||||
Game::entityManager->ConstructEntity(newEntity);
|
Game::entityManager->ConstructEntity(newEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
auto& info = reportInfo.info->PushDebug("Physics");
|
||||||
|
reportInfo.subCategory = &info;
|
||||||
|
|
||||||
|
auto& pos = info.PushDebug("Position");
|
||||||
|
pos.PushDebug<AMFDoubleValue>("x") = m_Position.x;
|
||||||
|
pos.PushDebug<AMFDoubleValue>("y") = m_Position.y;
|
||||||
|
pos.PushDebug<AMFDoubleValue>("z") = m_Position.z;
|
||||||
|
|
||||||
|
auto& rot = info.PushDebug("Rotation");
|
||||||
|
rot.PushDebug<AMFDoubleValue>("w") = m_Rotation.w;
|
||||||
|
rot.PushDebug<AMFDoubleValue>("x") = m_Rotation.x;
|
||||||
|
rot.PushDebug<AMFDoubleValue>("y") = m_Rotation.y;
|
||||||
|
rot.PushDebug<AMFDoubleValue>("z") = m_Rotation.z;
|
||||||
|
|
||||||
|
info.PushDebug<AMFIntValue>("CollisionGroup") = m_CollisionGroup;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
#include "NiQuaternion.h"
|
#include "NiQuaternion.h"
|
||||||
|
|
||||||
|
namespace GameMessages {
|
||||||
|
struct GetObjectReportInfo;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Raknet {
|
namespace Raknet {
|
||||||
class BitStream;
|
class BitStream;
|
||||||
};
|
};
|
||||||
@@ -29,6 +33,8 @@ public:
|
|||||||
int32_t GetCollisionGroup() const noexcept { return m_CollisionGroup; }
|
int32_t GetCollisionGroup() const noexcept { return m_CollisionGroup; }
|
||||||
void SetCollisionGroup(int32_t group) noexcept { m_CollisionGroup = group; }
|
void SetCollisionGroup(int32_t group) noexcept { m_CollisionGroup = group; }
|
||||||
protected:
|
protected:
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
dpEntity* CreatePhysicsEntity(eReplicaComponentType type);
|
dpEntity* CreatePhysicsEntity(eReplicaComponentType type);
|
||||||
|
|
||||||
dpEntity* CreatePhysicsLnv(const float scale, const eReplicaComponentType type) const;
|
dpEntity* CreatePhysicsLnv(const float scale, const eReplicaComponentType type) const;
|
||||||
|
|||||||
@@ -10,9 +10,12 @@
|
|||||||
#include "dpWorld.h"
|
#include "dpWorld.h"
|
||||||
#include "dpShapeBox.h"
|
#include "dpShapeBox.h"
|
||||||
#include "dpShapeSphere.h"
|
#include "dpShapeSphere.h"
|
||||||
#include"EntityInfo.h"
|
#include "EntityInfo.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
||||||
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo);
|
||||||
|
|
||||||
m_Position = m_Parent->GetDefaultPosition();
|
m_Position = m_Parent->GetDefaultPosition();
|
||||||
m_Rotation = m_Parent->GetDefaultRotation();
|
m_Rotation = m_Parent->GetDefaultRotation();
|
||||||
m_Scale = m_Parent->GetDefaultScale();
|
m_Scale = m_Parent->GetDefaultScale();
|
||||||
@@ -55,3 +58,11 @@ void RigidbodyPhantomPhysicsComponent::SpawnVertices() const {
|
|||||||
}
|
}
|
||||||
PhysicsComponent::SpawnVertices(m_dpEntity);
|
PhysicsComponent::SpawnVertices(m_dpEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
PhysicsComponent::OnGetObjectReportInfo(msg);
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
auto& info = reportInfo.subCategory->PushDebug("Rigidbody Phantom Info");
|
||||||
|
info.PushDebug<AMFDoubleValue>("Scale") = m_Scale;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ public:
|
|||||||
|
|
||||||
void SpawnVertices() const;
|
void SpawnVertices() const;
|
||||||
private:
|
private:
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
float m_Scale{};
|
float m_Scale{};
|
||||||
|
|
||||||
dpEntity* m_dpEntity{};
|
dpEntity* m_dpEntity{};
|
||||||
|
|||||||
@@ -12,8 +12,12 @@
|
|||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, int32_t componentID) : PhysicsComponent(parent, componentID) {
|
SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, int32_t componentID) : PhysicsComponent(parent, componentID) {
|
||||||
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &SimplePhysicsComponent::OnGetObjectReportInfo);
|
||||||
|
|
||||||
m_Position = m_Parent->GetDefaultPosition();
|
m_Position = m_Parent->GetDefaultPosition();
|
||||||
m_Rotation = m_Parent->GetDefaultRotation();
|
m_Rotation = m_Parent->GetDefaultRotation();
|
||||||
|
|
||||||
@@ -71,3 +75,20 @@ void SimplePhysicsComponent::SetPhysicsMotionState(uint32_t value) {
|
|||||||
m_DirtyPhysicsMotionState = m_PhysicsMotionState != value;
|
m_DirtyPhysicsMotionState = m_PhysicsMotionState != value;
|
||||||
m_PhysicsMotionState = value;
|
m_PhysicsMotionState = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SimplePhysicsComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
|
PhysicsComponent::OnGetObjectReportInfo(msg);
|
||||||
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
|
auto& info = reportInfo.subCategory->PushDebug("Simple Physics Info");
|
||||||
|
auto& velocity = info.PushDebug("Velocity");
|
||||||
|
velocity.PushDebug<AMFDoubleValue>("x") = m_Velocity.x;
|
||||||
|
velocity.PushDebug<AMFDoubleValue>("y") = m_Velocity.y;
|
||||||
|
velocity.PushDebug<AMFDoubleValue>("z") = m_Velocity.z;
|
||||||
|
auto& angularVelocity = info.PushDebug("Angular Velocity");
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("x") = m_AngularVelocity.x;
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("y") = m_AngularVelocity.y;
|
||||||
|
angularVelocity.PushDebug<AMFDoubleValue>("z") = m_AngularVelocity.z;
|
||||||
|
info.PushDebug<AMFIntValue>("Physics Motion State") = m_PhysicsMotionState;
|
||||||
|
info.PushDebug<AMFStringValue>("Climbable Type") = StringifiedEnum::ToString(m_ClimbableType).data();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ public:
|
|||||||
void SetClimbableType(const eClimbableType& value) { m_ClimbableType = value; }
|
void SetClimbableType(const eClimbableType& value) { m_ClimbableType = value; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current velocity of the entity
|
* The current velocity of the entity
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6165,12 +6165,9 @@ void GameMessages::HandleRemoveDonationItem(RakNet::BitStream& inStream, Entity*
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameMessages::HandleConfirmDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity) {
|
void GameMessages::HandleConfirmDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity) {
|
||||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
const auto [inventoryComponent, missionComponent, characterComponent] = entity->GetComponentsMut<InventoryComponent, MissionComponent, CharacterComponent>();
|
||||||
if (!inventoryComponent) return;
|
if (!inventoryComponent || !missionComponent || !characterComponent || !characterComponent->GetCurrentInteracting()) return;
|
||||||
auto* missionComponent = entity->GetComponent<MissionComponent>();
|
|
||||||
if (!missionComponent) return;
|
|
||||||
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
|
||||||
if (!characterComponent || !characterComponent->GetCurrentInteracting()) return;
|
|
||||||
auto* donationEntity = Game::entityManager->GetEntity(characterComponent->GetCurrentInteracting());
|
auto* donationEntity = Game::entityManager->GetEntity(characterComponent->GetCurrentInteracting());
|
||||||
if (!donationEntity) return;
|
if (!donationEntity) return;
|
||||||
auto* donationVendorComponent = donationEntity->GetComponent<DonationVendorComponent>();
|
auto* donationVendorComponent = donationEntity->GetComponent<DonationVendorComponent>();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
|
||||||
class AMFBaseValue;
|
class AMFBaseValue;
|
||||||
|
class AMFArrayValue;
|
||||||
class Entity;
|
class Entity;
|
||||||
class Item;
|
class Item;
|
||||||
class NiQuaternion;
|
class NiQuaternion;
|
||||||
@@ -788,6 +789,14 @@ namespace GameMessages {
|
|||||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GetObjectReportInfo : public GameMsg {
|
||||||
|
AMFArrayValue* info{};
|
||||||
|
AMFArrayValue* subCategory{};
|
||||||
|
bool bVerbose{};
|
||||||
|
|
||||||
|
GetObjectReportInfo() : GameMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, eGameMasterLevel::DEVELOPER) {}
|
||||||
|
};
|
||||||
|
|
||||||
struct RequestUse : public GameMsg {
|
struct RequestUse : public GameMsg {
|
||||||
RequestUse() : GameMsg(MessageType::Game::REQUEST_USE) {}
|
RequestUse() : GameMsg(MessageType::Game::REQUEST_USE) {}
|
||||||
|
|
||||||
@@ -854,5 +863,13 @@ namespace GameMessages {
|
|||||||
|
|
||||||
NiPoint3 pos{};
|
NiPoint3 pos{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SetFaction : public GameMsg {
|
||||||
|
SetFaction() : GameMsg(MessageType::Game::SET_FACTION) {}
|
||||||
|
|
||||||
|
int32_t factionID{};
|
||||||
|
|
||||||
|
bool bIgnoreChecks{ false };
|
||||||
|
};
|
||||||
};
|
};
|
||||||
#endif // GAMEMESSAGES_H
|
#endif // GAMEMESSAGES_H
|
||||||
|
|||||||
@@ -96,20 +96,18 @@ void Mission::LoadFromXmlCur(const tinyxml2::XMLElement& element) {
|
|||||||
if (index >= m_Tasks.size()) {
|
if (index >= m_Tasks.size()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
auto* const curTask = m_Tasks[index];
|
||||||
|
|
||||||
const auto type = m_Tasks[index]->GetType();
|
const auto type = curTask->GetType();
|
||||||
|
|
||||||
if (type == eMissionTaskType::COLLECTION ||
|
auto value = std::stoul(task->Attribute("v"));
|
||||||
type == eMissionTaskType::VISIT_PROPERTY) {
|
curTask->SetProgress(value, false);
|
||||||
|
task = task->NextSiblingElement();
|
||||||
|
|
||||||
|
// Collection tasks and visit property tasks store each of the collected/visited targets after the progress value
|
||||||
|
if (type == eMissionTaskType::COLLECTION || type == eMissionTaskType::VISIT_PROPERTY) {
|
||||||
std::vector<uint32_t> uniques;
|
std::vector<uint32_t> uniques;
|
||||||
|
while (task != nullptr && value > 0) {
|
||||||
const auto value = std::stoul(task->Attribute("v"));
|
|
||||||
|
|
||||||
m_Tasks[index]->SetProgress(value, false);
|
|
||||||
|
|
||||||
task = task->NextSiblingElement();
|
|
||||||
|
|
||||||
while (task != nullptr) {
|
|
||||||
const auto unique = std::stoul(task->Attribute("v"));
|
const auto unique = std::stoul(task->Attribute("v"));
|
||||||
|
|
||||||
uniques.push_back(unique);
|
uniques.push_back(unique);
|
||||||
@@ -119,19 +117,10 @@ void Mission::LoadFromXmlCur(const tinyxml2::XMLElement& element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task = task->NextSiblingElement();
|
task = task->NextSiblingElement();
|
||||||
|
value--;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Tasks[index]->SetUnique(uniques);
|
curTask->SetUnique(uniques);
|
||||||
|
|
||||||
m_Tasks[index]->SetProgress(uniques.size(), false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
const auto value = std::stoul(task->Attribute("v"));
|
|
||||||
|
|
||||||
m_Tasks[index]->SetProgress(value, false);
|
|
||||||
|
|
||||||
task = task->NextSiblingElement();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
@@ -163,31 +152,19 @@ void Mission::UpdateXmlCur(tinyxml2::XMLElement& element) {
|
|||||||
|
|
||||||
if (IsComplete()) return;
|
if (IsComplete()) return;
|
||||||
|
|
||||||
for (auto* task : m_Tasks) {
|
for (const auto* const task : m_Tasks) {
|
||||||
if (task->GetType() == eMissionTaskType::COLLECTION ||
|
auto* const child = element.InsertNewChildElement("sv");
|
||||||
task->GetType() == eMissionTaskType::VISIT_PROPERTY) {
|
|
||||||
|
|
||||||
auto* child = element.GetDocument()->NewElement("sv");
|
|
||||||
|
|
||||||
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
|
|
||||||
|
|
||||||
element.LinkEndChild(child);
|
|
||||||
|
|
||||||
for (auto unique : task->GetUnique()) {
|
|
||||||
auto* uniqueElement = element.GetDocument()->NewElement("sv");
|
|
||||||
|
|
||||||
uniqueElement->SetAttribute("v", static_cast<unsigned int>(unique));
|
|
||||||
|
|
||||||
element.LinkEndChild(uniqueElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
auto* child = element.GetDocument()->NewElement("sv");
|
|
||||||
|
|
||||||
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
|
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
|
||||||
|
|
||||||
element.LinkEndChild(child);
|
// Collection and visit property tasks then need to store the collected/visited items after the progress
|
||||||
|
const auto taskType = task->GetType();
|
||||||
|
if (taskType == eMissionTaskType::COLLECTION || taskType == eMissionTaskType::VISIT_PROPERTY) {
|
||||||
|
for (const auto unique : task->GetUnique()) {
|
||||||
|
auto* uniqueElement = element.InsertNewChildElement("sv");
|
||||||
|
|
||||||
|
uniqueElement->SetAttribute("v", static_cast<unsigned int>(unique));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,11 +484,6 @@ void Mission::YieldRewards() {
|
|||||||
// If a mission rewards zero of an item, make it reward 1.
|
// If a mission rewards zero of an item, make it reward 1.
|
||||||
auto count = pair.second > 0 ? pair.second : 1;
|
auto count = pair.second > 0 ? pair.second : 1;
|
||||||
|
|
||||||
// Sanity check, 6 is the max any mission yields
|
|
||||||
if (count > 6) {
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT);
|
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,11 +512,6 @@ void Mission::YieldRewards() {
|
|||||||
// If a mission rewards zero of an item, make it reward 1.
|
// If a mission rewards zero of an item, make it reward 1.
|
||||||
auto count = pair.second > 0 ? pair.second : 1;
|
auto count = pair.second > 0 ? pair.second : 1;
|
||||||
|
|
||||||
// Sanity check, 6 is the max any mission yields
|
|
||||||
if (count > 6) {
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT);
|
inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::MISSION : eLootSourceType::ACHIEVEMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -184,3 +184,7 @@ void PropertyBehavior::Update(float deltaTime, ModelComponent& modelComponent) {
|
|||||||
void PropertyBehavior::OnChatMessageReceived(const std::string& sMessage) {
|
void PropertyBehavior::OnChatMessageReceived(const std::string& sMessage) {
|
||||||
for (auto& state : m_States | std::views::values) state.OnChatMessageReceived(sMessage);
|
for (auto& state : m_States | std::views::values) state.OnChatMessageReceived(sMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyBehavior::OnHit() {
|
||||||
|
for (auto& state : m_States | std::views::values) state.OnHit();
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public:
|
|||||||
|
|
||||||
void Update(float deltaTime, ModelComponent& modelComponent);
|
void Update(float deltaTime, ModelComponent& modelComponent);
|
||||||
void OnChatMessageReceived(const std::string& sMessage);
|
void OnChatMessageReceived(const std::string& sMessage);
|
||||||
|
void OnHit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The current active behavior state. Behaviors can only be in ONE state at a time.
|
// The current active behavior state. Behaviors can only be in ONE state at a time.
|
||||||
|
|||||||
@@ -170,3 +170,7 @@ void State::Update(float deltaTime, ModelComponent& modelComponent) {
|
|||||||
void State::OnChatMessageReceived(const std::string& sMessage) {
|
void State::OnChatMessageReceived(const std::string& sMessage) {
|
||||||
for (auto& strip : m_Strips) strip.OnChatMessageReceived(sMessage);
|
for (auto& strip : m_Strips) strip.OnChatMessageReceived(sMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void State::OnHit() {
|
||||||
|
for (auto& strip : m_Strips) strip.OnHit();
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public:
|
|||||||
void Update(float deltaTime, ModelComponent& modelComponent);
|
void Update(float deltaTime, ModelComponent& modelComponent);
|
||||||
|
|
||||||
void OnChatMessageReceived(const std::string& sMessage);
|
void OnChatMessageReceived(const std::string& sMessage);
|
||||||
|
void OnHit();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// The strips contained within this state.
|
// The strips contained within this state.
|
||||||
|
|||||||
@@ -118,6 +118,16 @@ void Strip::OnChatMessageReceived(const std::string& sMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Strip::OnHit() {
|
||||||
|
if (m_PausedTime > 0.0f || !HasMinimumActions()) return;
|
||||||
|
|
||||||
|
const auto& nextAction = GetNextAction();
|
||||||
|
if (nextAction.GetType() == "OnAttack") {
|
||||||
|
IncrementAction();
|
||||||
|
m_WaitingForAction = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Strip::IncrementAction() {
|
void Strip::IncrementAction() {
|
||||||
if (m_Actions.empty()) return;
|
if (m_Actions.empty()) return;
|
||||||
m_NextActionIndex++;
|
m_NextActionIndex++;
|
||||||
@@ -259,6 +269,8 @@ void Strip::RemoveStates(ModelComponent& modelComponent) const {
|
|||||||
if (prevActionType == "OnInteract") {
|
if (prevActionType == "OnInteract") {
|
||||||
modelComponent.RemoveInteract();
|
modelComponent.RemoveInteract();
|
||||||
Game::entityManager->SerializeEntity(modelComponent.GetParent());
|
Game::entityManager->SerializeEntity(modelComponent.GetParent());
|
||||||
|
} else if (prevActionType == "OnAttack") {
|
||||||
|
modelComponent.RemoveAttack();
|
||||||
} else if (prevActionType == "UnSmash") {
|
} else if (prevActionType == "UnSmash") {
|
||||||
modelComponent.RemoveUnSmash();
|
modelComponent.RemoveUnSmash();
|
||||||
}
|
}
|
||||||
@@ -336,13 +348,14 @@ void Strip::Update(float deltaTime, ModelComponent& modelComponent) {
|
|||||||
if (m_NextActionIndex == 0) {
|
if (m_NextActionIndex == 0) {
|
||||||
if (nextAction.GetType() == "OnInteract") {
|
if (nextAction.GetType() == "OnInteract") {
|
||||||
modelComponent.AddInteract();
|
modelComponent.AddInteract();
|
||||||
Game::entityManager->SerializeEntity(entity);
|
|
||||||
m_WaitingForAction = true;
|
|
||||||
|
|
||||||
} else if (nextAction.GetType() == "OnChat") {
|
} else if (nextAction.GetType() == "OnChat") {
|
||||||
Game::entityManager->SerializeEntity(entity);
|
// logic here if needed
|
||||||
m_WaitingForAction = true;
|
} else if (nextAction.GetType() == "OnAttack") {
|
||||||
|
modelComponent.AddAttack();
|
||||||
}
|
}
|
||||||
|
Game::entityManager->SerializeEntity(entity);
|
||||||
|
m_WaitingForAction = true;
|
||||||
} else { // should be a normal block
|
} else { // should be a normal block
|
||||||
ProcNormalAction(deltaTime, modelComponent);
|
ProcNormalAction(deltaTime, modelComponent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public:
|
|||||||
bool HasMinimumActions() const { return m_Actions.size() >= 2; }
|
bool HasMinimumActions() const { return m_Actions.size() >= 2; }
|
||||||
|
|
||||||
void OnChatMessageReceived(const std::string& sMessage);
|
void OnChatMessageReceived(const std::string& sMessage);
|
||||||
|
void OnHit();
|
||||||
private:
|
private:
|
||||||
// Indicates this Strip is waiting for an action to be taken upon it to progress to its actions
|
// Indicates this Strip is waiting for an action to be taken upon it to progress to its actions
|
||||||
bool m_WaitingForAction{ false };
|
bool m_WaitingForAction{ false };
|
||||||
|
|||||||
@@ -1445,12 +1445,28 @@ void SlashCommandHandler::Startup() {
|
|||||||
};
|
};
|
||||||
RegisterCommand(removeIgnoreCommand);
|
RegisterCommand(removeIgnoreCommand);
|
||||||
|
|
||||||
Command shutdownCommand{
|
Command command{
|
||||||
.help = "Shuts this world down",
|
.help = "Shuts this world down",
|
||||||
.info = "Shuts this world down",
|
.info = "Shuts this world down",
|
||||||
.aliases = {"shutdown"},
|
.aliases = {"shutdown"},
|
||||||
.handle = DEVGMCommands::Shutdown,
|
.handle = DEVGMCommands::Shutdown,
|
||||||
.requiredLevel = eGameMasterLevel::DEVELOPER
|
.requiredLevel = eGameMasterLevel::DEVELOPER
|
||||||
};
|
};
|
||||||
RegisterCommand(shutdownCommand);
|
RegisterCommand(command);
|
||||||
|
|
||||||
|
RegisterCommand({
|
||||||
|
.help = "Turns all players' pvp mode on",
|
||||||
|
.info = "Turns all players' pvp mode on",
|
||||||
|
.aliases = {"barfight"},
|
||||||
|
.handle = DEVGMCommands::Barfight,
|
||||||
|
.requiredLevel = eGameMasterLevel::DEVELOPER
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterCommand({
|
||||||
|
.help = "Despawns an object by id",
|
||||||
|
.info = "Despawns an object by id",
|
||||||
|
.aliases = {"despawn"},
|
||||||
|
.handle = DEVGMCommands::Despawn,
|
||||||
|
.requiredLevel = eGameMasterLevel::DEVELOPER
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "DEVGMCommands.h"
|
#include "DEVGMCommands.h"
|
||||||
|
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
// Classes
|
// Classes
|
||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
#include "Character.h"
|
#include "Character.h"
|
||||||
@@ -42,12 +44,14 @@
|
|||||||
#include "SkillComponent.h"
|
#include "SkillComponent.h"
|
||||||
#include "TriggerComponent.h"
|
#include "TriggerComponent.h"
|
||||||
#include "RigidbodyPhantomPhysicsComponent.h"
|
#include "RigidbodyPhantomPhysicsComponent.h"
|
||||||
|
#include "PhantomPhysicsComponent.h"
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "MessageType/Master.h"
|
#include "MessageType/Master.h"
|
||||||
#include "eInventoryType.h"
|
#include "eInventoryType.h"
|
||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
|
|
||||||
namespace DEVGMCommands {
|
namespace DEVGMCommands {
|
||||||
@@ -759,6 +763,7 @@ namespace DEVGMCommands {
|
|||||||
info.spawner = nullptr;
|
info.spawner = nullptr;
|
||||||
info.spawnerID = entity->GetObjectID();
|
info.spawnerID = entity->GetObjectID();
|
||||||
info.spawnerNodeID = 0;
|
info.spawnerNodeID = 0;
|
||||||
|
info.settings = { new LDFData<bool>(u"SpawnedFromSlashCommand", true) };
|
||||||
|
|
||||||
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
|
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
|
||||||
|
|
||||||
@@ -800,6 +805,7 @@ namespace DEVGMCommands {
|
|||||||
info.spawner = nullptr;
|
info.spawner = nullptr;
|
||||||
info.spawnerID = entity->GetObjectID();
|
info.spawnerID = entity->GetObjectID();
|
||||||
info.spawnerNodeID = 0;
|
info.spawnerNodeID = 0;
|
||||||
|
info.settings = { new LDFData<bool>(u"SpawnedFromSlashCommand", true) };
|
||||||
|
|
||||||
auto playerPosition = entity->GetPosition();
|
auto playerPosition = entity->GetPosition();
|
||||||
while (numberToSpawn > 0) {
|
while (numberToSpawn > 0) {
|
||||||
@@ -1514,7 +1520,13 @@ namespace DEVGMCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!closest) return;
|
if (!closest) return;
|
||||||
LOG("%llu", closest->GetObjectID());
|
|
||||||
|
GameMessages::RequestServerObjectInfo objectInfo;
|
||||||
|
objectInfo.bVerbose = true;
|
||||||
|
objectInfo.target = closest->GetObjectID();
|
||||||
|
objectInfo.targetForReport = closest->GetObjectID();
|
||||||
|
objectInfo.clientId = entity->GetObjectID();
|
||||||
|
closest->HandleMsg(objectInfo);
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(closest);
|
Game::entityManager->SerializeEntity(closest);
|
||||||
|
|
||||||
@@ -1528,16 +1540,6 @@ namespace DEVGMCommands {
|
|||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(header.str()));
|
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(header.str()));
|
||||||
|
|
||||||
for (const auto& pair : closest->GetComponents()) {
|
|
||||||
auto id = pair.first;
|
|
||||||
|
|
||||||
std::stringstream stream;
|
|
||||||
|
|
||||||
stream << "Component [" << std::to_string(static_cast<uint32_t>(id)) << "]";
|
|
||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(stream.str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitArgs.size() >= 2) {
|
if (splitArgs.size() >= 2) {
|
||||||
if (splitArgs[1] == "-m" && splitArgs.size() >= 3) {
|
if (splitArgs[1] == "-m" && splitArgs.size() >= 3) {
|
||||||
auto* const movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
|
auto* const movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
|
||||||
@@ -1557,13 +1559,6 @@ namespace DEVGMCommands {
|
|||||||
Game::entityManager->SerializeEntity(closest);
|
Game::entityManager->SerializeEntity(closest);
|
||||||
} else if (splitArgs[1] == "-a" && splitArgs.size() >= 3) {
|
} else if (splitArgs[1] == "-a" && splitArgs.size() >= 3) {
|
||||||
RenderComponent::PlayAnimation(closest, splitArgs.at(2));
|
RenderComponent::PlayAnimation(closest, splitArgs.at(2));
|
||||||
} else if (splitArgs[1] == "-s") {
|
|
||||||
for (auto* entry : closest->GetSettings()) {
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::UTF8ToUTF16(entry->GetString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"------");
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"Spawner ID: " + GeneralUtils::to_u16string(closest->GetSpawnerID()));
|
|
||||||
} else if (splitArgs[1] == "-p") {
|
} else if (splitArgs[1] == "-p") {
|
||||||
const auto postion = closest->GetPosition();
|
const auto postion = closest->GetPosition();
|
||||||
|
|
||||||
@@ -1633,4 +1628,40 @@ namespace DEVGMCommands {
|
|||||||
if (character) LOG("Mythran (%s) has shutdown the world", character->GetName().c_str());
|
if (character) LOG("Mythran (%s) has shutdown the world", character->GetName().c_str());
|
||||||
Game::OnSignal(-1);
|
Game::OnSignal(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Barfight(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||||
|
auto* const characterComponent = entity->GetComponent<CharacterComponent>();
|
||||||
|
if (!characterComponent) return;
|
||||||
|
|
||||||
|
for (auto* const player : PlayerManager::GetAllPlayers()) {
|
||||||
|
auto* const pCharacterComponent = player->GetComponent<CharacterComponent>();
|
||||||
|
if (pCharacterComponent) pCharacterComponent->SetPvpEnabled(true);
|
||||||
|
Game::entityManager->SerializeEntity(player);
|
||||||
|
}
|
||||||
|
const auto msg = u"Pvp has been turned on for all players by " + GeneralUtils::ASCIIToUTF16(characterComponent->GetName());
|
||||||
|
ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, msg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Despawn(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||||
|
if (args.empty()) return;
|
||||||
|
|
||||||
|
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
||||||
|
const auto objId = GeneralUtils::TryParse<LWOOBJID>(splitArgs[0]);
|
||||||
|
if (!objId) return;
|
||||||
|
|
||||||
|
auto* const target = Game::entityManager->GetEntity(*objId);
|
||||||
|
if (!target) {
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, u"Entity not found: " + GeneralUtils::UTF8ToUTF16(splitArgs[0]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target->GetVar<bool>(u"SpawnedFromSlashCommand")) {
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, u"You cannot despawn this entity as it was not despawned from a slash command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
||||||
|
LOG("Despawned entity (%llu)", target->GetObjectID());
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, u"Despawned entity: " + GeneralUtils::to_u16string(target->GetObjectID()));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ namespace DEVGMCommands {
|
|||||||
void CastSkill(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
void CastSkill(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||||
void DeleteInven(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
void DeleteInven(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||||
void Shutdown(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
void Shutdown(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||||
|
void Barfight(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||||
|
void Despawn(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //!DEVGMCOMMANDS_H
|
#endif //!DEVGMCOMMANDS_H
|
||||||
|
|||||||
@@ -14,24 +14,21 @@
|
|||||||
|
|
||||||
#include "Start.h"
|
#include "Start.h"
|
||||||
|
|
||||||
InstanceManager::InstanceManager(Logger* logger, const std::string& externalIP) {
|
using std::make_unique;
|
||||||
mLogger = logger;
|
|
||||||
mExternalIP = externalIP;
|
namespace {
|
||||||
|
const InstancePtr g_Empty{ nullptr };
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceManager::InstanceManager(const std::string& externalIP) : mExternalIP{ externalIP } {
|
||||||
m_LastPort =
|
m_LastPort =
|
||||||
GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("world_port_start")).value_or(m_LastPort);
|
GeneralUtils::TryParse<uint16_t>(Game::config->GetValue("world_port_start")).value_or(m_LastPort);
|
||||||
m_LastInstanceID = LWOINSTANCEID_INVALID;
|
m_LastInstanceID = LWOINSTANCEID_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceManager::~InstanceManager() {
|
const InstancePtr& InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID) {
|
||||||
for (Instance* i : m_Instances) {
|
|
||||||
delete i;
|
|
||||||
i = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID) {
|
|
||||||
LOG("Searching for an instance for mapID %i/%i", mapID, cloneID);
|
LOG("Searching for an instance for mapID %i/%i", mapID, cloneID);
|
||||||
Instance* instance = FindInstance(mapID, isFriendTransfer, cloneID);
|
auto& instance = FindInstance(mapID, isFriendTransfer, cloneID);
|
||||||
if (instance) return instance;
|
if (instance) return instance;
|
||||||
|
|
||||||
// If we are shutting down, return a nullptr so a new instance is not created.
|
// If we are shutting down, return a nullptr so a new instance is not created.
|
||||||
@@ -40,7 +37,7 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW
|
|||||||
mapID,
|
mapID,
|
||||||
m_LastInstanceID + 1,
|
m_LastInstanceID + 1,
|
||||||
cloneID);
|
cloneID);
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
//TODO: Update this so that the IP is read from a configuration file instead
|
//TODO: Update this so that the IP is read from a configuration file instead
|
||||||
|
|
||||||
@@ -56,23 +53,23 @@ Instance* InstanceManager::GetInstance(LWOMAPID mapID, bool isFriendTransfer, LW
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t port = GetFreePort();
|
uint32_t port = GetFreePort();
|
||||||
instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, softCap, maxPlayers);
|
auto newInstance = make_unique<Instance>(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, softCap, maxPlayers);
|
||||||
|
|
||||||
//Start the actual process:
|
//Start the actual process:
|
||||||
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
|
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
|
||||||
|
|
||||||
m_Instances.push_back(instance);
|
m_Instances.push_back(std::move(newInstance));
|
||||||
|
|
||||||
if (instance) {
|
if (m_Instances.back()) {
|
||||||
LOG("Created new instance: %i/%i/%i with min/max %i/%i", mapID, m_LastInstanceID, cloneID, softCap, maxPlayers);
|
LOG("Created new instance: %i/%i/%i with min/max %i/%i", mapID, m_LastInstanceID, cloneID, softCap, maxPlayers);
|
||||||
return instance;
|
return m_Instances.back();
|
||||||
} else LOG("Failed to create a new instance!");
|
} else LOG("Failed to create a new instance!");
|
||||||
|
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceManager::IsPortInUse(uint32_t port) {
|
bool InstanceManager::IsPortInUse(uint32_t port) {
|
||||||
for (Instance* i : m_Instances) {
|
for (const auto& i : m_Instances) {
|
||||||
if (i && i->GetPort() == port) {
|
if (i && i->GetPort() == port) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -84,7 +81,7 @@ bool InstanceManager::IsPortInUse(uint32_t port) {
|
|||||||
uint32_t InstanceManager::GetFreePort() {
|
uint32_t InstanceManager::GetFreePort() {
|
||||||
uint32_t port = m_LastPort;
|
uint32_t port = m_LastPort;
|
||||||
std::vector<uint32_t> usedPorts;
|
std::vector<uint32_t> usedPorts;
|
||||||
for (Instance* i : m_Instances) {
|
for (const auto& i : m_Instances) {
|
||||||
usedPorts.push_back(i->GetPort());
|
usedPorts.push_back(i->GetPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +98,7 @@ uint32_t InstanceManager::GetFreePort() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
void InstanceManager::AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
||||||
Instance* inst = FindInstance(mapID, instanceID);
|
const auto& inst = FindInstance(mapID, instanceID);
|
||||||
if (inst) {
|
if (inst) {
|
||||||
Player player;
|
Player player;
|
||||||
player.addr = systemAddr;
|
player.addr = systemAddr;
|
||||||
@@ -111,7 +108,7 @@ void InstanceManager::AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINS
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
void InstanceManager::RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
||||||
Instance* inst = FindInstance(mapID, instanceID);
|
const auto& inst = FindInstance(mapID, instanceID);
|
||||||
if (inst) {
|
if (inst) {
|
||||||
Player player;
|
Player player;
|
||||||
player.addr = systemAddr;
|
player.addr = systemAddr;
|
||||||
@@ -120,25 +117,23 @@ void InstanceManager::RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Instance*> InstanceManager::GetInstances() const {
|
const std::vector<InstancePtr>& InstanceManager::GetInstances() const {
|
||||||
return m_Instances;
|
return m_Instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::AddInstance(Instance* instance) {
|
void InstanceManager::AddInstance(InstancePtr& instance) {
|
||||||
if (instance == nullptr) return;
|
if (instance == nullptr) return;
|
||||||
|
|
||||||
m_Instances.push_back(instance);
|
m_Instances.push_back(std::move(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::RemoveInstance(Instance* instance) {
|
void InstanceManager::RemoveInstance(const InstancePtr& instance) {
|
||||||
for (uint32_t i = 0; i < m_Instances.size(); ++i) {
|
for (uint32_t i = 0; i < m_Instances.size(); ++i) {
|
||||||
if (m_Instances[i] == instance) {
|
if (m_Instances[i] == instance) {
|
||||||
instance->SetShutdownComplete(true);
|
instance->SetShutdownComplete(true);
|
||||||
|
|
||||||
if (!Game::ShouldShutdown()) RedirectPendingRequests(instance);
|
if (!Game::ShouldShutdown()) RedirectPendingRequests(instance);
|
||||||
|
|
||||||
delete m_Instances[i];
|
|
||||||
|
|
||||||
m_Instances.erase(m_Instances.begin() + i);
|
m_Instances.erase(m_Instances.begin() + i);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -146,7 +141,7 @@ void InstanceManager::RemoveInstance(Instance* instance) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::ReadyInstance(Instance* instance) {
|
void InstanceManager::ReadyInstance(const InstancePtr& instance) {
|
||||||
instance->SetIsReady(true);
|
instance->SetIsReady(true);
|
||||||
|
|
||||||
auto& pending = instance->GetPendingRequests();
|
auto& pending = instance->GetPendingRequests();
|
||||||
@@ -172,7 +167,7 @@ void InstanceManager::ReadyInstance(Instance* instance) {
|
|||||||
pending.clear();
|
pending.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstanceRequest& request) {
|
void InstanceManager::RequestAffirmation(const InstancePtr& instance, const PendingInstanceRequest& request) {
|
||||||
instance->GetPendingAffirmations().push_back(request);
|
instance->GetPendingAffirmations().push_back(request);
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
@@ -189,7 +184,7 @@ void InstanceManager::RequestAffirmation(Instance* instance, const PendingInstan
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::AffirmTransfer(Instance* instance, const uint64_t transferID) {
|
void InstanceManager::AffirmTransfer(const InstancePtr& instance, const uint64_t transferID) {
|
||||||
auto& pending = instance->GetPendingAffirmations();
|
auto& pending = instance->GetPendingAffirmations();
|
||||||
|
|
||||||
for (auto i = 0u; i < pending.size(); ++i) {
|
for (auto i = 0u; i < pending.size(); ++i) {
|
||||||
@@ -217,11 +212,11 @@ void InstanceManager::AffirmTransfer(Instance* instance, const uint64_t transfer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceManager::RedirectPendingRequests(Instance* instance) {
|
void InstanceManager::RedirectPendingRequests(const InstancePtr& instance) {
|
||||||
const auto& zoneId = instance->GetZoneID();
|
const auto& zoneId = instance->GetZoneID();
|
||||||
|
|
||||||
for (const auto& request : instance->GetPendingAffirmations()) {
|
for (const auto& request : instance->GetPendingAffirmations()) {
|
||||||
auto* in = Game::im->GetInstance(zoneId.GetMapID(), false, zoneId.GetCloneID());
|
const auto& in = Game::im->GetInstance(zoneId.GetMapID(), false, zoneId.GetCloneID());
|
||||||
|
|
||||||
if (in && !in->GetIsReady()) // Instance not ready, make a pending request
|
if (in && !in->GetIsReady()) // Instance not ready, make a pending request
|
||||||
{
|
{
|
||||||
@@ -234,57 +229,48 @@ void InstanceManager::RedirectPendingRequests(Instance* instance) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance* InstanceManager::GetInstanceBySysAddr(SystemAddress& sysAddr) {
|
const InstancePtr& InstanceManager::GetInstanceBySysAddr(SystemAddress& sysAddr) {
|
||||||
for (uint32_t i = 0; i < m_Instances.size(); ++i) {
|
for (const auto& instance : m_Instances) {
|
||||||
if (m_Instances[i] && m_Instances[i]->GetSysAddr() == sysAddr) {
|
if (instance && instance->GetSysAddr() == sysAddr) {
|
||||||
return m_Instances[i];
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceManager::IsInstanceFull(Instance* instance, bool isFriendTransfer) {
|
const InstancePtr& InstanceManager::FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId) {
|
||||||
if (!isFriendTransfer && instance->GetSoftCap() > instance->GetCurrentClientCount())
|
for (const auto& i : m_Instances) {
|
||||||
return false;
|
if (i && i->GetMapID() == mapID && i->GetCloneID() == cloneId && !i->IsFull(isFriendTransfer) && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
||||||
else if (isFriendTransfer && instance->GetHardCap() > instance->GetCurrentClientCount())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Instance* InstanceManager::FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId) {
|
|
||||||
for (Instance* i : m_Instances) {
|
|
||||||
if (i && i->GetMapID() == mapID && i->GetCloneID() == cloneId && !IsInstanceFull(i, isFriendTransfer) && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance* InstanceManager::FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
const InstancePtr& InstanceManager::FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
||||||
for (Instance* i : m_Instances) {
|
for (const auto& i : m_Instances) {
|
||||||
if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetIsPrivate() && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance* InstanceManager::FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
const InstancePtr& InstanceManager::FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
||||||
for (Instance* i : m_Instances) {
|
for (const auto& i : m_Instances) {
|
||||||
if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password) {
|
const InstancePtr& InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password) {
|
||||||
auto* instance = FindPrivateInstance(password);
|
const auto& instance = FindPrivateInstance(password);
|
||||||
|
|
||||||
if (instance != nullptr) {
|
if (instance != nullptr) {
|
||||||
return instance;
|
return instance;
|
||||||
@@ -295,27 +281,27 @@ Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID clon
|
|||||||
mapID,
|
mapID,
|
||||||
m_LastInstanceID + 1,
|
m_LastInstanceID + 1,
|
||||||
cloneID);
|
cloneID);
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxPlayers = 999;
|
int maxPlayers = 999;
|
||||||
|
|
||||||
uint32_t port = GetFreePort();
|
uint32_t port = GetFreePort();
|
||||||
instance = new Instance(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password);
|
auto newInstance = make_unique<Instance>(mExternalIP, port, mapID, ++m_LastInstanceID, cloneID, maxPlayers, maxPlayers, true, password);
|
||||||
|
|
||||||
//Start the actual process:
|
//Start the actual process:
|
||||||
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
|
StartWorldServer(mapID, port, m_LastInstanceID, maxPlayers, cloneID);
|
||||||
|
|
||||||
m_Instances.push_back(instance);
|
m_Instances.push_back(std::move(newInstance));
|
||||||
|
|
||||||
if (instance) return instance;
|
if (m_Instances.back()) return m_Instances.back();
|
||||||
else LOG("Failed to create a new instance!");
|
else LOG("Failed to create a new instance!");
|
||||||
|
|
||||||
return instance;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance* InstanceManager::FindPrivateInstance(const std::string& password) {
|
const InstancePtr& InstanceManager::FindPrivateInstance(const std::string& password) {
|
||||||
for (auto* instance : m_Instances) {
|
for (const auto& instance : m_Instances) {
|
||||||
if (!instance) continue;
|
if (!instance) continue;
|
||||||
|
|
||||||
if (!instance->GetIsPrivate()) {
|
if (!instance->GetIsPrivate()) {
|
||||||
@@ -329,7 +315,7 @@ Instance* InstanceManager::FindPrivateInstance(const std::string& password) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return g_Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceManager::GetSoftCap(LWOMAPID mapID) {
|
int InstanceManager::GetSoftCap(LWOMAPID mapID) {
|
||||||
@@ -363,3 +349,14 @@ void Instance::Shutdown() {
|
|||||||
|
|
||||||
LOG("Triggered world shutdown for zone/clone/instance %i/%i/%i", GetMapID(), GetCloneID(), GetInstanceID());
|
LOG("Triggered world shutdown for zone/clone/instance %i/%i/%i", GetMapID(), GetCloneID(), GetInstanceID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Instance::IsFull(bool isFriendTransfer) const {
|
||||||
|
if (!isFriendTransfer && GetSoftCap() > GetCurrentClientCount())
|
||||||
|
return false;
|
||||||
|
else if (isFriendTransfer && GetHardCap() > GetCurrentClientCount())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ public:
|
|||||||
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
bool IsFull(bool isFriendTransfer) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_IP{};
|
std::string m_IP{};
|
||||||
uint32_t m_Port{};
|
uint32_t m_Port{};
|
||||||
@@ -99,42 +101,42 @@ private:
|
|||||||
//Private functions:
|
//Private functions:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using InstancePtr = std::unique_ptr<Instance>;
|
||||||
|
|
||||||
class InstanceManager {
|
class InstanceManager {
|
||||||
public:
|
public:
|
||||||
InstanceManager(Logger* logger, const std::string& externalIP);
|
InstanceManager(const std::string& externalIP);
|
||||||
~InstanceManager();
|
|
||||||
|
|
||||||
Instance* GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID); //Creates an instance if none found
|
const InstancePtr& GetInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneID); //Creates an instance if none found
|
||||||
bool IsPortInUse(uint32_t port);
|
bool IsPortInUse(uint32_t port);
|
||||||
uint32_t GetFreePort();
|
uint32_t GetFreePort();
|
||||||
|
|
||||||
void AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID);
|
void AddPlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID);
|
||||||
void RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID);
|
void RemovePlayer(SystemAddress systemAddr, LWOMAPID mapID, LWOINSTANCEID instanceID);
|
||||||
|
|
||||||
std::vector<Instance*> GetInstances() const;
|
const std::vector<InstancePtr>& GetInstances() const;
|
||||||
void AddInstance(Instance* instance);
|
void AddInstance(InstancePtr& instance);
|
||||||
void RemoveInstance(Instance* instance);
|
void RemoveInstance(const InstancePtr& instance);
|
||||||
|
|
||||||
void ReadyInstance(Instance* instance);
|
void ReadyInstance(const InstancePtr& instance);
|
||||||
void RequestAffirmation(Instance* instance, const PendingInstanceRequest& request);
|
void RequestAffirmation(const InstancePtr& instance, const PendingInstanceRequest& request);
|
||||||
void AffirmTransfer(Instance* instance, uint64_t transferID);
|
void AffirmTransfer(const InstancePtr& instance, uint64_t transferID);
|
||||||
|
|
||||||
void RedirectPendingRequests(Instance* instance);
|
void RedirectPendingRequests(const InstancePtr& instance);
|
||||||
|
|
||||||
Instance* GetInstanceBySysAddr(SystemAddress& sysAddr);
|
const InstancePtr& GetInstanceBySysAddr(SystemAddress& sysAddr);
|
||||||
|
|
||||||
Instance* FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId = 0);
|
const InstancePtr& FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId = 0);
|
||||||
Instance* FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID);
|
const InstancePtr& FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID);
|
||||||
Instance* FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID);
|
const InstancePtr& FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID);
|
||||||
|
|
||||||
Instance* CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password);
|
const InstancePtr& CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password);
|
||||||
Instance* FindPrivateInstance(const std::string& password);
|
const InstancePtr& FindPrivateInstance(const std::string& password);
|
||||||
void SetIsShuttingDown(bool value) { this->m_IsShuttingDown = value; };
|
void SetIsShuttingDown(bool value) { this->m_IsShuttingDown = value; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger* mLogger;
|
|
||||||
std::string mExternalIP;
|
std::string mExternalIP;
|
||||||
std::vector<Instance*> m_Instances;
|
std::vector<std::unique_ptr<Instance>> m_Instances;
|
||||||
uint16_t m_LastPort = 3000;
|
uint16_t m_LastPort = 3000;
|
||||||
LWOINSTANCEID m_LastInstanceID;
|
LWOINSTANCEID m_LastInstanceID;
|
||||||
|
|
||||||
@@ -144,7 +146,6 @@ private:
|
|||||||
bool m_IsShuttingDown = false;
|
bool m_IsShuttingDown = false;
|
||||||
|
|
||||||
//Private functions:
|
//Private functions:
|
||||||
bool IsInstanceFull(Instance* instance, bool isFriendTransfer);
|
|
||||||
int GetSoftCap(LWOMAPID mapID);
|
int GetSoftCap(LWOMAPID mapID);
|
||||||
int GetHardCap(LWOMAPID mapID);
|
int GetHardCap(LWOMAPID mapID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//Create additional objects here:
|
//Create additional objects here:
|
||||||
PersistentIDManager::Initialize();
|
PersistentIDManager::Initialize();
|
||||||
Game::im = new InstanceManager(Game::logger, Game::server->GetIP());
|
Game::im = new InstanceManager(Game::server->GetIP());
|
||||||
|
|
||||||
//Get CDClient initial information
|
//Get CDClient initial information
|
||||||
try {
|
try {
|
||||||
@@ -434,9 +434,9 @@ int main(int argc, char** argv) {
|
|||||||
framesSinceKillUniverseCommand++;
|
framesSinceKillUniverseCommand++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto instances = Game::im->GetInstances();
|
const auto& instances = Game::im->GetInstances();
|
||||||
|
|
||||||
for (auto* instance : instances) {
|
for (const auto& instance : instances) {
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Remove dead instances
|
//Remove dead instances
|
||||||
for (auto* instance : instances) {
|
for (const auto& instance : instances) {
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -489,7 +489,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
//Since this disconnection is intentional, we'll just delete it as
|
//Since this disconnection is intentional, we'll just delete it as
|
||||||
//we'll start a new one anyway if needed:
|
//we'll start a new one anyway if needed:
|
||||||
Instance* instance =
|
const auto& instance =
|
||||||
Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
||||||
if (instance) {
|
if (instance) {
|
||||||
LOG("Actually disconnected from zone %i clone %i instance %i port %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance->GetPort());
|
LOG("Actually disconnected from zone %i clone %i instance %i port %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance->GetPort());
|
||||||
@@ -510,7 +510,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
if (packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
LOG("A server has lost the connection");
|
LOG("A server has lost the connection");
|
||||||
|
|
||||||
Instance* instance =
|
const auto& instance =
|
||||||
Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
||||||
if (instance) {
|
if (instance) {
|
||||||
LWOZONEID zoneID = instance->GetZoneID(); //Get the zoneID so we can recreate a server
|
LWOZONEID zoneID = instance->GetZoneID(); //Get the zoneID so we can recreate a server
|
||||||
@@ -561,9 +561,9 @@ void HandlePacket(Packet* packet) {
|
|||||||
LOG("Shutdown sequence has been started. Not creating a new zone.");
|
LOG("Shutdown sequence has been started. Not creating a new zone.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Instance* in = Game::im->GetInstance(zoneID, false, zoneClone);
|
const auto& in = Game::im->GetInstance(zoneID, false, zoneClone);
|
||||||
|
|
||||||
for (auto* instance : Game::im->GetInstances()) {
|
for (const auto& instance : Game::im->GetInstances()) {
|
||||||
LOG("Instance: %i/%i/%i -> %i %s", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in, instance->GetSysAddr().ToString());
|
LOG("Instance: %i/%i/%i -> %i %s", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in, instance->GetSysAddr().ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,12 +603,12 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
if (theirServerType == ServerType::World) {
|
if (theirServerType == ServerType::World) {
|
||||||
if (!Game::im->IsPortInUse(theirPort)) {
|
if (!Game::im->IsPortInUse(theirPort)) {
|
||||||
Instance* in = new Instance(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12);
|
auto in = std::make_unique<Instance>(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12);
|
||||||
|
|
||||||
in->SetSysAddr(packet->systemAddress);
|
in->SetSysAddr(packet->systemAddress);
|
||||||
Game::im->AddInstance(in);
|
Game::im->AddInstance(in);
|
||||||
} else {
|
} else {
|
||||||
auto* instance = Game::im->FindInstanceWithPrivate(theirZoneID, static_cast<LWOINSTANCEID>(theirInstanceID));
|
const auto& instance = Game::im->FindInstanceWithPrivate(theirZoneID, static_cast<LWOINSTANCEID>(theirInstanceID));
|
||||||
if (instance) {
|
if (instance) {
|
||||||
instance->SetSysAddr(packet->systemAddress);
|
instance->SetSysAddr(packet->systemAddress);
|
||||||
}
|
}
|
||||||
@@ -682,7 +682,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.Read(theirZoneID);
|
inStream.Read(theirZoneID);
|
||||||
inStream.Read(theirInstanceID);
|
inStream.Read(theirInstanceID);
|
||||||
|
|
||||||
auto instance =
|
const auto& instance =
|
||||||
Game::im->FindInstance(theirZoneID, theirInstanceID);
|
Game::im->FindInstance(theirZoneID, theirInstanceID);
|
||||||
if (instance) {
|
if (instance) {
|
||||||
instance->AddPlayer(Player());
|
instance->AddPlayer(Player());
|
||||||
@@ -702,7 +702,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.Read(theirZoneID);
|
inStream.Read(theirZoneID);
|
||||||
inStream.Read(theirInstanceID);
|
inStream.Read(theirInstanceID);
|
||||||
|
|
||||||
auto instance =
|
const auto& instance =
|
||||||
Game::im->FindInstance(theirZoneID, theirInstanceID);
|
Game::im->FindInstance(theirZoneID, theirInstanceID);
|
||||||
if (instance) {
|
if (instance) {
|
||||||
instance->RemovePlayer(Player());
|
instance->RemovePlayer(Player());
|
||||||
@@ -728,7 +728,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
inStream.Read<char>(character);
|
inStream.Read<char>(character);
|
||||||
password += character;
|
password += character;
|
||||||
}
|
}
|
||||||
auto* newInst = Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str());
|
const auto& newInst = Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str());
|
||||||
LOG("Creating private zone %i/%i/%i with password %s", newInst->GetMapID(), newInst->GetCloneID(), newInst->GetInstanceID(), password.c_str());
|
LOG("Creating private zone %i/%i/%i with password %s", newInst->GetMapID(), newInst->GetCloneID(), newInst->GetInstanceID(), password.c_str());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -754,9 +754,9 @@ void HandlePacket(Packet* packet) {
|
|||||||
password += character;
|
password += character;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* instance = Game::im->FindPrivateInstance(password.c_str());
|
const auto& instance = Game::im->FindPrivateInstance(password.c_str());
|
||||||
|
|
||||||
LOG("Join private zone: %llu %d %s %p", requestID, mythranShift, password.c_str(), instance);
|
LOG("Join private zone: %llu %d %s %p", requestID, mythranShift, password.c_str(), instance.get());
|
||||||
|
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
return;
|
return;
|
||||||
@@ -781,7 +781,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
LOG("Got world ready %i %i", zoneID, instanceID);
|
LOG("Got world ready %i %i", zoneID, instanceID);
|
||||||
|
|
||||||
auto* instance = Game::im->FindInstance(zoneID, instanceID);
|
const auto& instance = Game::im->FindInstance(zoneID, instanceID);
|
||||||
|
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
LOG("Failed to find zone to ready");
|
LOG("Failed to find zone to ready");
|
||||||
@@ -819,7 +819,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
LOG("Got affirmation of transfer %llu", requestID);
|
LOG("Got affirmation of transfer %llu", requestID);
|
||||||
|
|
||||||
auto* instance = Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
const auto& instance = Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
||||||
|
|
||||||
if (instance == nullptr)
|
if (instance == nullptr)
|
||||||
return;
|
return;
|
||||||
@@ -832,7 +832,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
case MessageType::Master::SHUTDOWN_RESPONSE: {
|
case MessageType::Master::SHUTDOWN_RESPONSE: {
|
||||||
CINSTREAM_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
|
||||||
auto* instance = Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
const auto& instance = Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
||||||
LOG("Got shutdown response from %s", packet->systemAddress.ToString());
|
LOG("Got shutdown response from %s", packet->systemAddress.ToString());
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
return;
|
return;
|
||||||
@@ -882,13 +882,13 @@ int ShutdownSequence(int32_t signal) {
|
|||||||
LOG("Saved ObjectIDTracker to DB");
|
LOG("Saved ObjectIDTracker to DB");
|
||||||
|
|
||||||
// A server might not be finished spinning up yet, remove all of those here.
|
// A server might not be finished spinning up yet, remove all of those here.
|
||||||
for (auto* instance : Game::im->GetInstances()) {
|
for (const auto& instance : Game::im->GetInstances()) {
|
||||||
|
if (!instance) continue;
|
||||||
|
|
||||||
if (!instance->GetIsReady()) {
|
if (!instance->GetIsReady()) {
|
||||||
Game::im->RemoveInstance(instance);
|
Game::im->RemoveInstance(instance);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* instance : Game::im->GetInstances()) {
|
|
||||||
instance->SetIsShuttingDown(true);
|
instance->SetIsShuttingDown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,7 +909,7 @@ int ShutdownSequence(int32_t signal) {
|
|||||||
|
|
||||||
allInstancesShutdown = true;
|
allInstancesShutdown = true;
|
||||||
|
|
||||||
for (auto* instance : Game::im->GetInstances()) {
|
for (const auto& instance : Game::im->GetInstances()) {
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
void HTTPMonitorInfo::Serialize(RakNet::BitStream &bitStream) const {
|
void HTTPMonitorInfo::Serialize(RakNet::BitStream& bitStream) const {
|
||||||
bitStream.Write(port);
|
bitStream.Write(port);
|
||||||
bitStream.Write<uint8_t>(openWeb);
|
bitStream.Write<uint8_t>(openWeb);
|
||||||
bitStream.Write<uint8_t>(supportsSum);
|
bitStream.Write<uint8_t>(supportsSum);
|
||||||
@@ -81,32 +81,29 @@ void WorldPackets::SendServerState(const SystemAddress& sysAddr) {
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm) {
|
void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm, const LWOCLONEID cloneID) {
|
||||||
|
using namespace std;
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::CREATE_CHARACTER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::CREATE_CHARACTER);
|
||||||
|
|
||||||
RakNet::BitStream data;
|
RakNet::BitStream data;
|
||||||
data.Write<uint32_t>(7); //LDF key count
|
|
||||||
|
|
||||||
std::unique_ptr<LDFData<LWOOBJID>> objid(new LDFData<LWOOBJID>(u"objid", player));
|
std::vector<std::unique_ptr<LDFBaseData>> ldfData;
|
||||||
std::unique_ptr<LDFData<LOT>> lot(new LDFData<LOT>(u"template", 1));
|
ldfData.push_back(std::move(make_unique<LDFData<LWOOBJID>>(u"objid", player)));
|
||||||
std::unique_ptr<LDFData<std::string>> xmlConfigData(new LDFData<std::string>(u"xmlData", xmlData));
|
ldfData.push_back(std::move(make_unique<LDFData<LOT>>(u"template", 1)));
|
||||||
std::unique_ptr<LDFData<std::u16string>> name(new LDFData<std::u16string>(u"name", username));
|
ldfData.push_back(std::move(make_unique<LDFData<string>>(u"xmlData", xmlData)));
|
||||||
std::unique_ptr<LDFData<int32_t>> gmlevel(new LDFData<int32_t>(u"gmlevel", static_cast<int32_t>(gm)));
|
ldfData.push_back(std::move(make_unique<LDFData<u16string>>(u"name", username)));
|
||||||
std::unique_ptr<LDFData<int32_t>> chatmode(new LDFData<int32_t>(u"chatmode", static_cast<int32_t>(gm)));
|
ldfData.push_back(std::move(make_unique<LDFData<int32_t>>(u"gmlevel", static_cast<int32_t>(gm))));
|
||||||
std::unique_ptr<LDFData<int64_t>> reputationLdf(new LDFData<int64_t>(u"reputation", reputation));
|
ldfData.push_back(std::move(make_unique<LDFData<int32_t>>(u"chatmode", static_cast<int32_t>(gm))));
|
||||||
|
ldfData.push_back(std::move(make_unique<LDFData<int64_t>>(u"reputation", reputation)));
|
||||||
objid->WriteToPacket(data);
|
ldfData.push_back(std::move(make_unique<LDFData<int32_t>>(u"propertycloneid", cloneID)));
|
||||||
lot->WriteToPacket(data);
|
|
||||||
name->WriteToPacket(data);
|
data.Write<uint32_t>(ldfData.size());
|
||||||
gmlevel->WriteToPacket(data);
|
for (const auto& toSerialize : ldfData) toSerialize->WriteToPacket(data);
|
||||||
chatmode->WriteToPacket(data);
|
|
||||||
xmlConfigData->WriteToPacket(data);
|
|
||||||
reputationLdf->WriteToPacket(data);
|
|
||||||
|
|
||||||
//Compress the data before sending:
|
//Compress the data before sending:
|
||||||
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());
|
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());
|
||||||
uint8_t* compressedData = new uint8_t[reservedSize];
|
uint8_t* compressedData = new uint8_t[reservedSize];
|
||||||
|
|
||||||
// TODO There should be better handling here for not enough memory...
|
// TODO There should be better handling here for not enough memory...
|
||||||
if (!compressedData) return;
|
if (!compressedData) return;
|
||||||
@@ -177,7 +174,7 @@ void WorldPackets::SendHTTPMonitorInfo(const SystemAddress& sysAddr, const HTTPM
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPackets::SendDebugOuput(const SystemAddress& sysAddr, const std::string& data){
|
void WorldPackets::SendDebugOuput(const SystemAddress& sysAddr, const std::string& data) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::DEBUG_OUTPUT);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::DEBUG_OUTPUT);
|
||||||
bitStream.Write<uint32_t>(data.size());
|
bitStream.Write<uint32_t>(data.size());
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace WorldPackets {
|
|||||||
void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response);
|
void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response);
|
||||||
void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift);
|
void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift);
|
||||||
void SendServerState(const SystemAddress& sysAddr);
|
void SendServerState(const SystemAddress& sysAddr);
|
||||||
void SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm);
|
void SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm, const LWOCLONEID cloneID);
|
||||||
void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::set<std::pair<uint8_t, uint8_t>> unacceptedItems);
|
void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::set<std::pair<uint8_t, uint8_t>> unacceptedItems);
|
||||||
void SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel);
|
void SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel);
|
||||||
void SendHTTPMonitorInfo(const SystemAddress& sysAddr, const HTTPMonitorInfo& info);
|
void SendHTTPMonitorInfo(const SystemAddress& sysAddr, const HTTPMonitorInfo& info);
|
||||||
|
|||||||
@@ -1040,7 +1040,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||||
if (!characterComponent) return;
|
if (!characterComponent) return;
|
||||||
|
|
||||||
WorldPackets::SendCreateCharacter(packet->systemAddress, player->GetComponent<CharacterComponent>()->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel());
|
WorldPackets::SendCreateCharacter(packet->systemAddress, player->GetComponent<CharacterComponent>()->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel(), c->GetPropertyCloneID());
|
||||||
WorldPackets::SendServerState(packet->systemAddress);
|
WorldPackets::SendServerState(packet->systemAddress);
|
||||||
|
|
||||||
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
||||||
|
|||||||
@@ -114,21 +114,23 @@ These commands are primarily for development and testing. The usage of many of t
|
|||||||
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|
||||||
|getfactions|`/getfactions`|Shows the player's factions|8|
|
|getfactions|`/getfactions`|Shows the player's factions|8|
|
||||||
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
||||||
|
|barfight|`/barfight start`|Starts a barfight (turns everyones pvp on)|8|
|
||||||
|
|despawn|`/despawn <objectID>`|Despawns the entity objectID IF it was spawned in through a slash command.|8|
|
||||||
|crash|`/crash`|Crashes the server.|9|
|
|crash|`/crash`|Crashes the server.|9|
|
||||||
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9|
|
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9|
|
||||||
|castskill|`/castskill <skill id>`|Casts the skill as the player|9|
|
|castskill|`/castskill <skill id>`|Casts the skill as the player|9|
|
||||||
|
|
||||||
## Detailed `/inspect` Usage
|
## Detailed `/inspect` Usage
|
||||||
|
|
||||||
`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`
|
`/inspect <component> (-m <waypoint> | -a <animation> | -p | -f (faction) | -t)`
|
||||||
|
|
||||||
Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has.
|
Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has.
|
||||||
|
This info is then shown in a window on the client which the user can navigate
|
||||||
|
|
||||||
### `/inspect` Options
|
### `/inspect` Options
|
||||||
|
|
||||||
* `-m`: If the entity has a moving platform component, sends it to the given waypoint, or stops the platform if `waypoint` is `-1`.
|
* `-m`: If the entity has a moving platform component, sends it to the given waypoint, or stops the platform if `waypoint` is `-1`.
|
||||||
* `-a`: Plays the given animation on the entity.
|
* `-a`: Plays the given animation on the entity.
|
||||||
* `-s`: Prints the entity's settings and spawner ID.
|
|
||||||
* `-p`: Prints the entity's position
|
* `-p`: Prints the entity's position
|
||||||
* `-f`: If the entity has a destroyable component, prints whether the entity is smashable and its friendly and enemy faction IDs; if `faction` is specified, adds that faction to the entity.
|
* `-f`: If the entity has a destroyable component, prints whether the entity is smashable and its friendly and enemy faction IDs; if `faction` is specified, adds that faction to the entity.
|
||||||
* `-cf`: check if the entity is enemy or friend
|
* `-cf`: check if the entity is enemy or friend
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
<location zone="1400" x="-696.957" y="-3.206" z="-452.441" rw="0.884105" rx="0.00" ry="0.467288" rz="0.00" />
|
<location zone="1400" x="-696.957" y="-3.206" z="-452.441" rw="0.884105" rx="0.00" ry="0.467288" rz="0.00" />
|
||||||
<!--CP Sentinel Point Zeta-->
|
<!--CP Sentinel Point Zeta-->
|
||||||
<location zone="1800" x="-222.634" y="92.373" z="568.392" rw="-0.435024" rx="0.00" ry="0.900419" rz="0.00" />
|
<location zone="1800" x="-222.634" y="92.373" z="568.392" rw="-0.435024" rx="0.00" ry="0.900419" rz="0.00" />
|
||||||
|
<!--CP Monastery-->
|
||||||
|
<location zone="1800" x="-74.633" y="98.449" z="-650.531" rw="0.705469" rx="0.00" ry="0.708741" rz="0.00" />
|
||||||
<!--NJ Monastery Courtyard-->
|
<!--NJ Monastery Courtyard-->
|
||||||
<location zone="2000" x="-63.487" y="208.270" z="379.195" rw="0.00" rx="0.00" ry="1" rz="0.00" />
|
<location zone="2000" x="-63.487" y="208.270" z="379.195" rw="0.00" rx="0.00" ry="1" rz="0.00" />
|
||||||
</locations>
|
</locations>
|
||||||
|
|||||||
Reference in New Issue
Block a user