mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-28 00:17:23 +00:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
a6c6474e67
@ -89,8 +89,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
# Create a /res directory
|
||||
make_directory(${CMAKE_BINARY_DIR}/res)
|
||||
# Create a /resServer directory
|
||||
make_directory(${CMAKE_BINARY_DIR}/resServer)
|
||||
|
||||
# Create a /logs directory
|
||||
make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||
@ -176,6 +176,7 @@ set(INCLUDED_DIRECTORIES
|
||||
"dScripts/ai"
|
||||
"dScripts/client"
|
||||
"dScripts/EquipmentScripts"
|
||||
"dScripts/EquipmentTriggers"
|
||||
"dScripts/zone"
|
||||
"dScripts/02_server/DLU"
|
||||
"dScripts/02_server/Enemy"
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include "eSqliteDataType.h"
|
||||
|
||||
std::map<eSqliteDataType, std::string> FdbToSqlite::Convert::sqliteType = {
|
||||
std::map<eSqliteDataType, std::string> FdbToSqlite::Convert::m_SqliteType = {
|
||||
{ eSqliteDataType::NONE, "none"},
|
||||
{ eSqliteDataType::INT32, "int32"},
|
||||
{ eSqliteDataType::REAL, "real"},
|
||||
@ -23,15 +23,21 @@ std::map<eSqliteDataType, std::string> FdbToSqlite::Convert::sqliteType = {
|
||||
{ eSqliteDataType::TEXT_8, "text_8"}
|
||||
};
|
||||
|
||||
FdbToSqlite::Convert::Convert(std::string basePath) {
|
||||
this->basePath = basePath;
|
||||
FdbToSqlite::Convert::Convert(std::string basePath, std::string binaryOutPath) {
|
||||
this->m_BasePath = basePath;
|
||||
this->m_BinaryOutPath = binaryOutPath;
|
||||
m_Fdb.open(m_BasePath + "/cdclient.fdb", std::ios::binary);
|
||||
}
|
||||
|
||||
FdbToSqlite::Convert::~Convert() {
|
||||
this->m_Fdb.close();
|
||||
}
|
||||
|
||||
bool FdbToSqlite::Convert::ConvertDatabase() {
|
||||
fdb.open(basePath + "/cdclient.fdb", std::ios::binary);
|
||||
|
||||
if (m_ConversionStarted) return false;
|
||||
this->m_ConversionStarted = true;
|
||||
try {
|
||||
CDClientDatabase::Connect(basePath + "/CDServer.sqlite");
|
||||
CDClientDatabase::Connect(m_BinaryOutPath + "/CDServer.sqlite");
|
||||
|
||||
CDClientDatabase::ExecuteQuery("BEGIN TRANSACTION;");
|
||||
|
||||
@ -44,13 +50,12 @@ bool FdbToSqlite::Convert::ConvertDatabase() {
|
||||
return false;
|
||||
}
|
||||
|
||||
fdb.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t FdbToSqlite::Convert::ReadInt32() {
|
||||
int32_t nextInt{};
|
||||
BinaryIO::BinaryRead(fdb, nextInt);
|
||||
BinaryIO::BinaryRead(m_Fdb, nextInt);
|
||||
return nextInt;
|
||||
}
|
||||
|
||||
@ -58,26 +63,26 @@ int64_t FdbToSqlite::Convert::ReadInt64() {
|
||||
int32_t prevPosition = SeekPointer();
|
||||
|
||||
int64_t value{};
|
||||
BinaryIO::BinaryRead(fdb, value);
|
||||
BinaryIO::BinaryRead(m_Fdb, value);
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string FdbToSqlite::Convert::ReadString() {
|
||||
int32_t prevPosition = SeekPointer();
|
||||
|
||||
auto readString = BinaryIO::ReadString(fdb);
|
||||
auto readString = BinaryIO::ReadString(m_Fdb);
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
return readString;
|
||||
}
|
||||
|
||||
int32_t FdbToSqlite::Convert::SeekPointer() {
|
||||
int32_t position{};
|
||||
BinaryIO::BinaryRead(fdb, position);
|
||||
int32_t prevPosition = fdb.tellg();
|
||||
fdb.seekg(position);
|
||||
BinaryIO::BinaryRead(m_Fdb, position);
|
||||
int32_t prevPosition = m_Fdb.tellg();
|
||||
m_Fdb.seekg(position);
|
||||
return prevPosition;
|
||||
}
|
||||
|
||||
@ -91,7 +96,7 @@ std::string FdbToSqlite::Convert::ReadColumnHeader() {
|
||||
std::string newTable = "CREATE TABLE IF NOT EXISTS '" + tableName + "' (" + columns + ");";
|
||||
CDClientDatabase::ExecuteDML(newTable);
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
|
||||
return tableName;
|
||||
}
|
||||
@ -104,7 +109,7 @@ void FdbToSqlite::Convert::ReadTables(int32_t& numberOfTables) {
|
||||
ReadRowHeader(columnHeader);
|
||||
}
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
}
|
||||
|
||||
std::string FdbToSqlite::Convert::ReadColumns(int32_t& numberOfColumns) {
|
||||
@ -117,10 +122,10 @@ std::string FdbToSqlite::Convert::ReadColumns(int32_t& numberOfColumns) {
|
||||
if (i != 0) columnsToCreate << ", ";
|
||||
dataType = static_cast<eSqliteDataType>(ReadInt32());
|
||||
name = ReadString();
|
||||
columnsToCreate << "'" << name << "' " << FdbToSqlite::Convert::sqliteType[dataType];
|
||||
columnsToCreate << "'" << name << "' " << FdbToSqlite::Convert::m_SqliteType[dataType];
|
||||
}
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
return columnsToCreate.str();
|
||||
}
|
||||
|
||||
@ -131,7 +136,7 @@ void FdbToSqlite::Convert::ReadRowHeader(std::string& tableName) {
|
||||
if (numberOfAllocatedRows != 0) assert((numberOfAllocatedRows & (numberOfAllocatedRows - 1)) == 0); // assert power of 2 allocation size
|
||||
ReadRows(numberOfAllocatedRows, tableName);
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
}
|
||||
|
||||
void FdbToSqlite::Convert::ReadRows(int32_t& numberOfAllocatedRows, std::string& tableName) {
|
||||
@ -141,28 +146,24 @@ void FdbToSqlite::Convert::ReadRows(int32_t& numberOfAllocatedRows, std::string&
|
||||
for (int32_t row = 0; row < numberOfAllocatedRows; row++) {
|
||||
int32_t rowPointer = ReadInt32();
|
||||
if (rowPointer == -1) rowid++;
|
||||
else ReadRow(rowid, rowPointer, tableName);
|
||||
else ReadRow(rowPointer, tableName);
|
||||
}
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
}
|
||||
|
||||
void FdbToSqlite::Convert::ReadRow(int32_t& rowid, int32_t& position, std::string& tableName) {
|
||||
int32_t prevPosition = fdb.tellg();
|
||||
fdb.seekg(position);
|
||||
void FdbToSqlite::Convert::ReadRow(int32_t& position, std::string& tableName) {
|
||||
int32_t prevPosition = m_Fdb.tellg();
|
||||
m_Fdb.seekg(position);
|
||||
|
||||
while (true) {
|
||||
ReadRowInfo(tableName);
|
||||
int32_t linked = ReadInt32();
|
||||
|
||||
rowid += 1;
|
||||
|
||||
if (linked == -1) break;
|
||||
|
||||
fdb.seekg(linked);
|
||||
m_Fdb.seekg(linked);
|
||||
}
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
}
|
||||
|
||||
void FdbToSqlite::Convert::ReadRowInfo(std::string& tableName) {
|
||||
@ -171,7 +172,7 @@ void FdbToSqlite::Convert::ReadRowInfo(std::string& tableName) {
|
||||
int32_t numberOfColumns = ReadInt32();
|
||||
ReadRowValues(numberOfColumns, tableName);
|
||||
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
}
|
||||
|
||||
void FdbToSqlite::Convert::ReadRowValues(int32_t& numberOfColumns, std::string& tableName) {
|
||||
@ -191,7 +192,7 @@ void FdbToSqlite::Convert::ReadRowValues(int32_t& numberOfColumns, std::string&
|
||||
if (i != 0) insertedRow << ", "; // Only append comma and space after first entry in row.
|
||||
switch (static_cast<eSqliteDataType>(ReadInt32())) {
|
||||
case eSqliteDataType::NONE:
|
||||
BinaryIO::BinaryRead(fdb, emptyValue);
|
||||
BinaryIO::BinaryRead(m_Fdb, emptyValue);
|
||||
assert(emptyValue == 0);
|
||||
insertedRow << "NULL";
|
||||
break;
|
||||
@ -202,7 +203,7 @@ void FdbToSqlite::Convert::ReadRowValues(int32_t& numberOfColumns, std::string&
|
||||
break;
|
||||
|
||||
case eSqliteDataType::REAL:
|
||||
BinaryIO::BinaryRead(fdb, floatValue);
|
||||
BinaryIO::BinaryRead(m_Fdb, floatValue);
|
||||
insertedRow << std::fixed << std::setprecision(34) << floatValue; // maximum precision of floating point number
|
||||
break;
|
||||
|
||||
@ -224,7 +225,7 @@ void FdbToSqlite::Convert::ReadRowValues(int32_t& numberOfColumns, std::string&
|
||||
}
|
||||
|
||||
case eSqliteDataType::INT_BOOL:
|
||||
BinaryIO::BinaryRead(fdb, boolValue);
|
||||
BinaryIO::BinaryRead(m_Fdb, boolValue);
|
||||
insertedRow << static_cast<bool>(boolValue);
|
||||
break;
|
||||
|
||||
@ -244,5 +245,5 @@ void FdbToSqlite::Convert::ReadRowValues(int32_t& numberOfColumns, std::string&
|
||||
|
||||
auto copiedString = insertedRow.str();
|
||||
CDClientDatabase::ExecuteDML(copiedString);
|
||||
fdb.seekg(prevPosition);
|
||||
m_Fdb.seekg(prevPosition);
|
||||
}
|
||||
|
@ -12,38 +12,142 @@ enum class eSqliteDataType : int32_t;
|
||||
namespace FdbToSqlite {
|
||||
class Convert {
|
||||
public:
|
||||
Convert(std::string inputFile);
|
||||
/**
|
||||
* Create a new convert object with an input .fdb file and an output binary path.
|
||||
*
|
||||
* @param inputFile The file which ends in .fdb to be converted
|
||||
* @param binaryPath The base path where the file will be saved
|
||||
*/
|
||||
Convert(std::string inputFile, std::string binaryOutPath);
|
||||
|
||||
/**
|
||||
* Destroy the convert object and close the fdb file.
|
||||
*/
|
||||
~Convert();
|
||||
|
||||
/**
|
||||
* Converts the input file to sqlite. Calling multiple times is safe.
|
||||
*
|
||||
* @return true if the database was converted properly, false otherwise.
|
||||
*/
|
||||
bool ConvertDatabase();
|
||||
|
||||
/**
|
||||
* @brief Reads a 32 bit int from the fdb file.
|
||||
*
|
||||
* @return The read value
|
||||
*/
|
||||
int32_t ReadInt32();
|
||||
|
||||
/**
|
||||
* @brief Reads a 64 bit integer from the fdb file.
|
||||
*
|
||||
* @return The read value
|
||||
*/
|
||||
int64_t ReadInt64();
|
||||
|
||||
/**
|
||||
* @brief Reads a string from the fdb file.
|
||||
*
|
||||
* @return The read string
|
||||
*
|
||||
* TODO This needs to be translated to latin-1!
|
||||
*/
|
||||
std::string ReadString();
|
||||
|
||||
/**
|
||||
* @brief Seeks to a pointer position.
|
||||
*
|
||||
* @return The previous position before the seek
|
||||
*/
|
||||
int32_t SeekPointer();
|
||||
|
||||
/**
|
||||
* @brief Reads a column header from the fdb file and creates the table in the database
|
||||
*
|
||||
* @return The table name
|
||||
*/
|
||||
std::string ReadColumnHeader();
|
||||
|
||||
/**
|
||||
* @brief Read the tables from the fdb file.
|
||||
*
|
||||
* @param numberOfTables The number of tables to read
|
||||
*/
|
||||
void ReadTables(int32_t& numberOfTables);
|
||||
|
||||
/**
|
||||
* @brief Reads the columns from the fdb file.
|
||||
*
|
||||
* @param numberOfColumns The number of columns to read
|
||||
* @return All columns of the table formatted for a sql query
|
||||
*/
|
||||
std::string ReadColumns(int32_t& numberOfColumns);
|
||||
|
||||
/**
|
||||
* @brief Reads the row header from the fdb file.
|
||||
*
|
||||
* @param tableName The tables name
|
||||
*/
|
||||
void ReadRowHeader(std::string& tableName);
|
||||
|
||||
/**
|
||||
* @brief Read the rows from the fdb file.,
|
||||
*
|
||||
* @param numberOfAllocatedRows The number of rows that were allocated. Always a power of 2!
|
||||
* @param tableName The tables name.
|
||||
*/
|
||||
void ReadRows(int32_t& numberOfAllocatedRows, std::string& tableName);
|
||||
|
||||
void ReadRow(int32_t& rowid, int32_t& position, std::string& tableName);
|
||||
/**
|
||||
* @brief Reads a row from the fdb file.
|
||||
*
|
||||
* @param position The position to seek in the fdb to
|
||||
* @param tableName The tables name
|
||||
*/
|
||||
void ReadRow(int32_t& position, std::string& tableName);
|
||||
|
||||
/**
|
||||
* @brief Reads the row info from the fdb file.
|
||||
*
|
||||
* @param tableName The tables name
|
||||
*/
|
||||
void ReadRowInfo(std::string& tableName);
|
||||
|
||||
/**
|
||||
* @brief Reads each row and its values from the fdb file and inserts them into the database
|
||||
*
|
||||
* @param numberOfColumns The number of columns to read in
|
||||
* @param tableName The tables name
|
||||
*/
|
||||
void ReadRowValues(int32_t& numberOfColumns, std::string& tableName);
|
||||
private:
|
||||
static std::map<eSqliteDataType, std::string> sqliteType;
|
||||
std::string basePath{};
|
||||
std::ifstream fdb{};
|
||||
}; // class FdbToSqlite
|
||||
|
||||
/**
|
||||
* Maps each sqlite data type to its string equivalent.
|
||||
*/
|
||||
static std::map<eSqliteDataType, std::string> m_SqliteType;
|
||||
|
||||
/**
|
||||
* Base path of the folder containing the fdb file
|
||||
*/
|
||||
std::string m_BasePath{};
|
||||
|
||||
/**
|
||||
* ifstream containing the fdb file
|
||||
*/
|
||||
std::ifstream m_Fdb{};
|
||||
|
||||
/**
|
||||
* Whether or not a conversion was started. If one was started, do not attempt to convert the file again.
|
||||
*/
|
||||
bool m_ConversionStarted{};
|
||||
|
||||
/**
|
||||
* The path where the CDServer will be stored
|
||||
*/
|
||||
std::string m_BinaryOutPath{};
|
||||
}; //! class FdbToSqlite
|
||||
}; //! namespace FdbToSqlite
|
||||
|
||||
#endif //!__FDBTOSQLITE__H__
|
||||
|
@ -54,7 +54,7 @@ void MigrationRunner::RunMigrations() {
|
||||
if (doExit) continue;
|
||||
|
||||
Game::logger->Log("MigrationRunner", "Running migration: %s", migration.name.c_str());
|
||||
if (migration.name == "5_brick_model_sd0.sql") {
|
||||
if (migration.name == "dlu/5_brick_model_sd0.sql") {
|
||||
runSd0Migrations = true;
|
||||
} else {
|
||||
finalSQL.append(migration.data.c_str());
|
||||
|
@ -824,6 +824,22 @@ std::vector<ScriptComponent*> Entity::GetScriptComponents() {
|
||||
return comps;
|
||||
}
|
||||
|
||||
void Entity::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, const std::string& notificationName) {
|
||||
if (notificationName == "HitOrHealResult" || notificationName == "Hit") {
|
||||
auto* destroyableComponent = GetComponent<DestroyableComponent>();
|
||||
if (!destroyableComponent) return;
|
||||
destroyableComponent->Subscribe(scriptObjId, scriptToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationName) {
|
||||
if (notificationName == "HitOrHealResult" || notificationName == "Hit") {
|
||||
auto* destroyableComponent = GetComponent<DestroyableComponent>();
|
||||
if (!destroyableComponent) return;
|
||||
destroyableComponent->Unsubscribe(scriptObjId);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::SetProximityRadius(float proxRadius, std::string name) {
|
||||
ProximityMonitorComponent* proxMon = GetComponent<ProximityMonitorComponent>();
|
||||
if (!proxMon) {
|
||||
|
@ -26,8 +26,13 @@ class Spawner;
|
||||
class ScriptComponent;
|
||||
class dpEntity;
|
||||
class Component;
|
||||
class Item;
|
||||
class Character;
|
||||
|
||||
namespace CppScripts {
|
||||
class Script;
|
||||
};
|
||||
|
||||
/**
|
||||
* An entity in the world. Has multiple components.
|
||||
*/
|
||||
@ -139,6 +144,9 @@ public:
|
||||
|
||||
std::vector<ScriptComponent*> GetScriptComponents();
|
||||
|
||||
void Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, const std::string& notificationName);
|
||||
void Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationName);
|
||||
|
||||
void SetProximityRadius(float proxRadius, std::string name);
|
||||
void SetProximityRadius(dpEntity* entity, std::string name);
|
||||
|
||||
|
@ -631,6 +631,7 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
||||
auto* attacker = EntityManager::Instance()->GetEntity(source);
|
||||
m_Parent->OnHit(attacker);
|
||||
m_Parent->OnHitOrHealResult(attacker, sourceDamage);
|
||||
NotifySubscribers(attacker, sourceDamage);
|
||||
|
||||
for (const auto& cb : m_OnHitCallbacks) {
|
||||
cb(attacker);
|
||||
@ -648,6 +649,29 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
||||
Smash(source, eKillType::VIOLENT, u"", skillID);
|
||||
}
|
||||
|
||||
void DestroyableComponent::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd) {
|
||||
m_SubscribedScripts.insert(std::make_pair(scriptObjId, scriptToAdd));
|
||||
Game::logger->LogDebug("DestroyableComponent", "Added script %llu to entity %llu", scriptObjId, m_Parent->GetObjectID());
|
||||
Game::logger->LogDebug("DestroyableComponent", "Number of subscribed scripts %i", m_SubscribedScripts.size());
|
||||
}
|
||||
|
||||
void DestroyableComponent::Unsubscribe(LWOOBJID scriptObjId) {
|
||||
auto foundScript = m_SubscribedScripts.find(scriptObjId);
|
||||
if (foundScript != m_SubscribedScripts.end()) {
|
||||
m_SubscribedScripts.erase(foundScript);
|
||||
Game::logger->LogDebug("DestroyableComponent", "Removed script %llu from entity %llu", scriptObjId, m_Parent->GetObjectID());
|
||||
} else {
|
||||
Game::logger->LogDebug("DestroyableComponent", "Tried to remove a script for Entity %llu but script %llu didnt exist", m_Parent->GetObjectID(), scriptObjId);
|
||||
}
|
||||
Game::logger->LogDebug("DestroyableComponent", "Number of subscribed scripts %i", m_SubscribedScripts.size());
|
||||
}
|
||||
|
||||
void DestroyableComponent::NotifySubscribers(Entity* attacker, uint32_t damage) {
|
||||
for (auto script : m_SubscribedScripts) {
|
||||
script.second->NotifyHitOrHealResult(m_Parent, attacker, damage);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType, uint32_t skillID) {
|
||||
if (m_iHealth > 0) {
|
||||
SetArmor(0);
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
|
||||
namespace CppScripts {
|
||||
class Script;
|
||||
}; //! namespace CppScripts
|
||||
|
||||
/**
|
||||
* Represents the stats of an entity, for example its health, imagination and armor. Also handles factions, which
|
||||
* indicate which enemies this entity has.
|
||||
@ -422,6 +426,17 @@ public:
|
||||
*/
|
||||
void AddFactionNoLookup(int32_t faction) { m_FactionIDs.push_back(faction); };
|
||||
|
||||
/**
|
||||
* Notify subscribed scripts of Damage actions.
|
||||
*
|
||||
* @param attacker The attacking Entity
|
||||
* @param damage The amount of damage that was done
|
||||
*/
|
||||
void NotifySubscribers(Entity* attacker, uint32_t damage);
|
||||
|
||||
void Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd);
|
||||
void Unsubscribe(LWOOBJID scriptObjId);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Whether or not the health should be serialized
|
||||
@ -557,6 +572,11 @@ private:
|
||||
* The list of callbacks that will be called when this entity gets hit
|
||||
*/
|
||||
std::vector<std::function<void(Entity*)>> m_OnHitCallbacks;
|
||||
|
||||
/**
|
||||
* The list of scripts subscribed to this components actions
|
||||
*/
|
||||
std::map<LWOOBJID, CppScripts::Script*> m_SubscribedScripts;
|
||||
};
|
||||
|
||||
#endif // DESTROYABLECOMPONENT_H
|
||||
|
@ -27,8 +27,9 @@
|
||||
#include "dConfig.h"
|
||||
#include "eItemType.h"
|
||||
#include "eUnequippableActiveType.h"
|
||||
#include "CppScripts.h"
|
||||
|
||||
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) {
|
||||
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document): Component(parent) {
|
||||
this->m_Dirty = true;
|
||||
this->m_Equipped = {};
|
||||
this->m_Pushed = {};
|
||||
@ -867,6 +868,8 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
||||
|
||||
AddItemSkills(item->GetLot());
|
||||
|
||||
EquipScripts(item);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
@ -895,6 +898,8 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
||||
|
||||
PurgeProxies(item);
|
||||
|
||||
UnequipScripts(item);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
|
||||
// Trigger property event
|
||||
@ -904,6 +909,37 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InventoryComponent::EquipScripts(Item* equippedItem) {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
if (!compRegistryTable) return;
|
||||
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(equippedItem->GetLot(), COMPONENT_TYPE_SCRIPT, -1);
|
||||
if (scriptComponentID > -1) {
|
||||
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance()->GetTable<CDScriptComponentTable>("ScriptComponent");
|
||||
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
if (!itemScript) {
|
||||
Game::logger->Log("InventoryComponent", "null script?");
|
||||
}
|
||||
itemScript->OnFactionTriggerItemEquipped(m_Parent, equippedItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::UnequipScripts(Item* unequippedItem) {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
if (!compRegistryTable) return;
|
||||
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(unequippedItem->GetLot(), COMPONENT_TYPE_SCRIPT, -1);
|
||||
if (scriptComponentID > -1) {
|
||||
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance()->GetTable<CDScriptComponentTable>("ScriptComponent");
|
||||
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
if (!itemScript) {
|
||||
Game::logger->Log("InventoryComponent", "null script?");
|
||||
}
|
||||
itemScript->OnFactionTriggerItemUnequipped(m_Parent, unequippedItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::HandlePossession(Item* item) {
|
||||
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
@ -352,6 +352,20 @@ public:
|
||||
*/
|
||||
static uint32_t FindSkill(LOT lot);
|
||||
|
||||
/**
|
||||
* Call this when you equip an item. This calls OnFactionTriggerItemEquipped for any scripts found on the items.
|
||||
*
|
||||
* @param equippedItem The item script to lookup and call equip on
|
||||
*/
|
||||
void EquipScripts(Item* equippedItem);
|
||||
|
||||
/**
|
||||
* Call this when you unequip an item. This calls OnFactionTriggerItemUnequipped for any scripts found on the items.
|
||||
*
|
||||
* @param unequippedItem The item script to lookup and call unequip on
|
||||
*/
|
||||
void UnequipScripts(Item* unequippedItem);
|
||||
|
||||
~InventoryComponent() override;
|
||||
|
||||
private:
|
||||
|
@ -98,7 +98,7 @@ void RacingControlComponent::OnPlayerLoaded(Entity* player) {
|
||||
}
|
||||
|
||||
void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
||||
bool initialLoad) {
|
||||
uint32_t positionNumber, bool initialLoad) {
|
||||
// Load the player's vehicle.
|
||||
|
||||
if (player == nullptr) {
|
||||
@ -126,33 +126,18 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
||||
auto* path = dZoneManager::Instance()->GetZone()->GetPath(
|
||||
GeneralUtils::UTF16ToWTF8(m_PathName));
|
||||
|
||||
auto startPosition = path->pathWaypoints[0].position + NiPoint3::UNIT_Y * 3;
|
||||
|
||||
const auto spacing = 15;
|
||||
|
||||
// This sometimes spawns the vehicle out of the map if there are lots of
|
||||
// players loaded.
|
||||
|
||||
const auto range = m_LoadedPlayers * spacing;
|
||||
|
||||
startPosition =
|
||||
startPosition + NiPoint3::UNIT_Z * ((m_LeadingPlayer / 2) +
|
||||
m_RacingPlayers.size() * spacing);
|
||||
|
||||
auto startRotation =
|
||||
NiQuaternion::LookAt(startPosition, startPosition + NiPoint3::UNIT_X);
|
||||
|
||||
auto angles = startRotation.GetEulerAngles();
|
||||
|
||||
angles.y -= M_PI;
|
||||
|
||||
startRotation = NiQuaternion::FromEulerAngles(angles);
|
||||
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Start position <%f, %f, %f>, <%f, %f, %f>",
|
||||
startPosition.x, startPosition.y, startPosition.z,
|
||||
angles.x * (180.0f / M_PI), angles.y * (180.0f / M_PI),
|
||||
angles.z * (180.0f / M_PI));
|
||||
auto spawnPointEntities = EntityManager::Instance()->GetEntitiesByLOT(4843);
|
||||
auto startPosition = NiPoint3::ZERO;
|
||||
auto startRotation = NiQuaternion::IDENTITY;
|
||||
const std::string placementAsString = std::to_string(positionNumber);
|
||||
for (auto entity : spawnPointEntities) {
|
||||
if (!entity) continue;
|
||||
if (entity->GetVarAsString(u"placement") == placementAsString) {
|
||||
startPosition = entity->GetPosition();
|
||||
startRotation = entity->GetRotation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the player is at the correct position.
|
||||
|
||||
@ -567,12 +552,12 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Loading all players...");
|
||||
|
||||
for (size_t i = 0; i < m_LobbyPlayers.size(); i++) {
|
||||
for (size_t positionNumber = 0; positionNumber < m_LobbyPlayers.size(); positionNumber++) {
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Loading player now!");
|
||||
|
||||
auto* player =
|
||||
EntityManager::Instance()->GetEntity(m_LobbyPlayers[i]);
|
||||
EntityManager::Instance()->GetEntity(m_LobbyPlayers[positionNumber]);
|
||||
|
||||
if (player == nullptr) {
|
||||
return;
|
||||
@ -581,7 +566,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Loading player now NOW!");
|
||||
|
||||
LoadPlayerVehicle(player, true);
|
||||
LoadPlayerVehicle(player, positionNumber + 1, true);
|
||||
|
||||
m_Loaded = true;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ public:
|
||||
* @param player The player who's vehicle to initialize.
|
||||
* @param initialLoad Is this the first time the player is loading in this race?
|
||||
*/
|
||||
void LoadPlayerVehicle(Entity* player, bool initialLoad = false);
|
||||
void LoadPlayerVehicle(Entity* player, uint32_t positionNumber, bool initialLoad = false);
|
||||
|
||||
/**
|
||||
* Invoked when the client says it has loaded in.
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "Spawner.h"
|
||||
#include "MovingPlatformComponent.h"
|
||||
#include "Preconditions.h"
|
||||
#include "TeamManager.h"
|
||||
|
||||
#include "CppScripts.h"
|
||||
|
||||
@ -464,12 +465,20 @@ void RebuildComponent::CompleteRebuild(Entity* user) {
|
||||
|
||||
auto* builder = GetBuilder();
|
||||
|
||||
if (builder != nullptr) {
|
||||
auto* missionComponent = builder->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_ActivityId);
|
||||
if (builder) {
|
||||
auto* team = TeamManager::Instance()->GetTeam(builder->GetObjectID());
|
||||
if (team) {
|
||||
for (const auto memberId : team->members) { // progress missions for all team members
|
||||
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
||||
if (member) {
|
||||
auto* missionComponent = member->GetComponent<MissionComponent>();
|
||||
if (missionComponent) missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_ActivityId);
|
||||
}
|
||||
}
|
||||
} else{
|
||||
auto* missionComponent = builder->GetComponent<MissionComponent>();
|
||||
if (missionComponent) missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_ActivityId);
|
||||
}
|
||||
|
||||
LootGenerator::Instance().DropActivityLoot(builder, m_Parent, m_ActivityId, 1);
|
||||
}
|
||||
|
||||
|
@ -3924,14 +3924,16 @@ void GameMessages::SendDisplayChatBubble(LWOOBJID objectId, const std::u16string
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::SendChangeIdleFlags(LWOOBJID objectId, eAnimationFlags FlagsOn, eAnimationFlags FlagsOff, const SystemAddress& sysAddr) {
|
||||
void GameMessages::SendChangeIdleFlags(LWOOBJID objectId, eAnimationFlags flagsOn, eAnimationFlags flagsOff, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(GAME_MSG::GAME_MSG_CHANGE_IDLE_FLAGS);
|
||||
bitStream.Write(FlagsOff);
|
||||
bitStream.Write(FlagsOn);
|
||||
bitStream.Write<bool>(flagsOff != eAnimationFlags::IDLE_NONE);
|
||||
if (flagsOff != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOff);
|
||||
bitStream.Write<bool>(flagsOn != eAnimationFlags::IDLE_NONE);
|
||||
if (flagsOn != eAnimationFlags::IDLE_NONE) bitStream.Write(flagsOn);
|
||||
|
||||
SEND_PACKET_BROADCAST;
|
||||
}
|
||||
|
@ -1762,6 +1762,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
||||
|
||||
scriptedActivityComponent->ReloadConfig();
|
||||
}
|
||||
Game::server->UpdateMaximumMtuSize();
|
||||
Game::server->UpdateBandwidthLimit();
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Successfully reloaded config for world!");
|
||||
}
|
||||
|
@ -146,26 +146,38 @@ int main(int argc, char** argv) {
|
||||
|
||||
MigrationRunner::RunMigrations();
|
||||
|
||||
// Check CDClient exists
|
||||
if (!std::filesystem::exists(Game::assetManager->GetResPath() / "CDServer.sqlite")) {
|
||||
Game::logger->Log("WorldServer", "CDServer.sqlite could not be opened. Looking for cdclient.fdb to convert to sqlite.");
|
||||
const bool cdServerExists = std::filesystem::exists(BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite");
|
||||
const bool oldCDServerExists = std::filesystem::exists(Game::assetManager->GetResPath() / "CDServer.sqlite");
|
||||
const bool fdbExists = std::filesystem::exists(Game::assetManager->GetResPath() / "cdclient.fdb");
|
||||
|
||||
if (!std::filesystem::exists(Game::assetManager->GetResPath() / "cdclient.fdb")) {
|
||||
Game::logger->Log("WorldServer", "cdclient.fdb could not be opened. Please move a cdclient.fdb or an already converted database to build/res.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Game::logger->Log("WorldServer", "Found cdclient.fdb. Converting to SQLite");
|
||||
|
||||
if (FdbToSqlite::Convert(Game::assetManager->GetResPath().string()).ConvertDatabase() == false) {
|
||||
Game::logger->Log("MasterServer", "Failed to convert fdb to sqlite");
|
||||
return EXIT_FAILURE;
|
||||
if (!cdServerExists) {
|
||||
if (oldCDServerExists) {
|
||||
// If the file doesn't exist in the new CDServer location, copy it there. We copy because we may not have write permissions from the previous directory.
|
||||
Game::logger->Log("MasterServer", "CDServer.sqlite is not located at resServer, but is located at res path. Copying file...");
|
||||
std::filesystem::copy_file(Game::assetManager->GetResPath() / "CDServer.sqlite", BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite");
|
||||
} else {
|
||||
Game::logger->Log("WorldServer",
|
||||
"%s could not be found in resServer or res. Looking for %s to convert to sqlite.",
|
||||
(BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite").c_str(),
|
||||
(Game::assetManager->GetResPath() / "cdclient.fdb").c_str());
|
||||
if (!fdbExists) {
|
||||
Game::logger->Log("WorldServer",
|
||||
"%s could not be opened. Please move cdclient.fdb to %s",
|
||||
(Game::assetManager->GetResPath() / "cdclient.fdb").c_str(),
|
||||
(Game::assetManager->GetResPath().c_str()));
|
||||
return FinalizeShutdown();
|
||||
}
|
||||
Game::logger->Log("WorldServer", "Found cdclient.fdb. Converting to SQLite");
|
||||
if (FdbToSqlite::Convert(Game::assetManager->GetResPath().string(), (BinaryPathFinder::GetBinaryDir() / "resServer").string()).ConvertDatabase() == false) {
|
||||
Game::logger->Log("MasterServer", "Failed to convert fdb to sqlite.");
|
||||
return FinalizeShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Connect to CDClient
|
||||
try {
|
||||
CDClientDatabase::Connect((Game::assetManager->GetResPath() / "CDServer.sqlite").string());
|
||||
CDClientDatabase::Connect((BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite").string());
|
||||
} catch (CppSQLite3Exception& e) {
|
||||
Game::logger->Log("WorldServer", "Unable to connect to CDServer SQLite Database");
|
||||
Game::logger->Log("WorldServer", "Error: %s", e.errorMessage());
|
||||
|
@ -68,7 +68,7 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
|
||||
} else { mLogger->Log("dServer", "FAILED TO START SERVER ON IP/PORT: %s:%i", ip.c_str(), port); return; }
|
||||
|
||||
mLogger->SetLogToConsole(prevLogSetting);
|
||||
mPeer->SetMTUSize(1228); // This is hard coded by lu for some reason.
|
||||
|
||||
//Connect to master if we are not master:
|
||||
if (serverType != ServerType::Master) {
|
||||
SetupForMasterConnection();
|
||||
@ -188,6 +188,7 @@ bool dServer::Startup() {
|
||||
mPeer->SetIncomingPassword("3.25 DARKFLAME1", 15);
|
||||
} else {
|
||||
UpdateBandwidthLimit();
|
||||
UpdateMaximumMtuSize();
|
||||
mPeer->SetIncomingPassword("3.25 ND1", 8);
|
||||
}
|
||||
|
||||
@ -197,6 +198,11 @@ bool dServer::Startup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void dServer::UpdateMaximumMtuSize() {
|
||||
auto maxMtuSize = mConfig->GetValue("maximum_mtu_size");
|
||||
mPeer->SetMTUSize(maxMtuSize.empty() ? 1228 : std::stoi(maxMtuSize));
|
||||
}
|
||||
|
||||
void dServer::UpdateBandwidthLimit() {
|
||||
auto newBandwidth = mConfig->GetValue("maximum_outgoing_bandwidth");
|
||||
mPeer->SetPerConnectionOutgoingBandwidthLimit(!newBandwidth.empty() ? std::stoi(newBandwidth) : 0);
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
ReplicaManager* GetReplicaManager() { return mReplicaManager; }
|
||||
void UpdateReplica();
|
||||
void UpdateBandwidthLimit();
|
||||
void UpdateMaximumMtuSize();
|
||||
|
||||
int GetPing(const SystemAddress& sysAddr) const;
|
||||
int GetLatestPing(const SystemAddress& sysAddr) const;
|
||||
|
@ -63,10 +63,11 @@ void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
skillComponent->Reset();
|
||||
}
|
||||
|
||||
self->SetVar<int32_t>(u"weakpoint", 2);
|
||||
|
||||
GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f);
|
||||
|
||||
self->AddTimer("timeToStunLoop", 1);
|
||||
@ -131,7 +132,9 @@ void AmDarklingDragon::OnTimerDone(Entity* self, std::string timerName) {
|
||||
}
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
skillComponent->Reset();
|
||||
}
|
||||
GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_COMBAT, eAnimationFlags::IDLE_NONE, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
self->SetVar<int32_t>(u"weakspot", -1);
|
||||
GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
@ -59,8 +59,6 @@ void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_
|
||||
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent != nullptr) {
|
||||
Game::logger->Log("FvMaelstromDragon", "Hit %i", destroyableComponent->GetArmor());
|
||||
|
||||
if (destroyableComponent->GetArmor() > 0) return;
|
||||
|
||||
auto weakpoint = self->GetVar<int32_t>(u"weakpoint");
|
||||
@ -80,10 +78,12 @@ void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
skillComponent->Reset();
|
||||
}
|
||||
|
||||
self->SetVar<int32_t>(u"weakpoint", 2);
|
||||
|
||||
GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f);
|
||||
|
||||
self->AddTimer("timeToStunLoop", 1);
|
||||
@ -150,8 +150,9 @@ void FvMaelstromDragon::OnTimerDone(Entity* self, std::string timerName) {
|
||||
|
||||
if (skillComponent != nullptr) {
|
||||
skillComponent->Interrupt();
|
||||
skillComponent->Reset();
|
||||
}
|
||||
|
||||
GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_COMBAT, eAnimationFlags::IDLE_NONE, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
self->SetVar<int32_t>(u"weakspot", -1);
|
||||
|
||||
GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
@ -31,9 +31,12 @@ void BaseEnemyApe::OnHit(Entity* self, Entity* attacker) {
|
||||
if (destroyableComponent != nullptr && destroyableComponent->GetArmor() < 1 && !self->GetBoolean(u"knockedOut")) {
|
||||
StunApe(self, true);
|
||||
self->CancelTimer("spawnQBTime");
|
||||
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (skillComponent) {
|
||||
skillComponent->Reset();
|
||||
}
|
||||
GameMessages::SendPlayAnimation(self, u"disable", 1.7f);
|
||||
|
||||
GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_NONE, eAnimationFlags::IDLE_COMBAT, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
const auto reviveTime = self->GetVar<float_t>(u"reviveTime") != 0.0f
|
||||
? self->GetVar<float_t>(u"reviveTime") : 12.0f;
|
||||
self->AddTimer("reviveTime", reviveTime);
|
||||
@ -50,6 +53,7 @@ void BaseEnemyApe::OnTimerDone(Entity* self, std::string timerName) {
|
||||
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor() / timesStunned);
|
||||
}
|
||||
EntityManager::Instance()->SerializeEntity(self);
|
||||
GameMessages::SendChangeIdleFlags(self->GetObjectID(), eAnimationFlags::IDLE_COMBAT, eAnimationFlags::IDLE_NONE, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
self->SetVar<uint32_t>(u"timesStunned", timesStunned + 1);
|
||||
StunApe(self, false);
|
||||
|
||||
|
@ -39,6 +39,12 @@ foreach(file ${DSCRIPTS_SOURCES_EQUIPMENTSCRIPTS})
|
||||
set(DSCRIPTS_SOURCES ${DSCRIPTS_SOURCES} "EquipmentScripts/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(EquipmentTriggers)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_EQUIPMENTTRIGGERSSCRIPTS})
|
||||
set(DSCRIPTS_SOURCES ${DSCRIPTS_SOURCES} "EquipmentTriggers/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(zone)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_ZONE})
|
||||
|
@ -278,6 +278,9 @@
|
||||
#include "ImaginationBackpackHealServer.h"
|
||||
#include "LegoDieRoll.h"
|
||||
#include "BuccaneerValiantShip.h"
|
||||
#include "GemPack.h"
|
||||
#include "ShardArmor.h"
|
||||
#include "TeslaPack.h"
|
||||
|
||||
// Survival scripts
|
||||
#include "AgSurvivalStromling.h"
|
||||
@ -837,6 +840,12 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
|
||||
script = new BuccaneerValiantShip();
|
||||
else if (scriptName == "scripts\\EquipmentScripts\\FireFirstSkillonStartup.lua")
|
||||
script = new FireFirstSkillonStartup();
|
||||
else if (scriptName == "scripts\\equipmenttriggers\\gempack.lua")
|
||||
script = new GemPack();
|
||||
else if (scriptName == "scripts\\equipmenttriggers\\shardarmor.lua")
|
||||
script = new ShardArmor();
|
||||
else if (scriptName == "scripts\\equipmenttriggers\\coilbackpack.lua")
|
||||
script = new TeslaPack();
|
||||
|
||||
// FB
|
||||
else if (scriptName == "scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua")
|
||||
|
@ -172,6 +172,13 @@ namespace CppScripts {
|
||||
*/
|
||||
virtual void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {};
|
||||
|
||||
/**
|
||||
* Invoked when self has received either a hit or heal. Only used for scripts subscribed to an entity.
|
||||
*
|
||||
* Equivalent to 'function notifyHitOrHealResult(self, msg)'
|
||||
*/
|
||||
virtual void NotifyHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {};
|
||||
|
||||
/**
|
||||
* Invoked when a player has responsed to a mission.
|
||||
*
|
||||
@ -316,6 +323,22 @@ namespace CppScripts {
|
||||
virtual void OnCinematicUpdate(Entity* self, Entity* sender, eCinematicEvent event, const std::u16string& pathName,
|
||||
float_t pathTime, float_t totalTime, int32_t waypoint) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Used by items to tell their owner that they were equipped.
|
||||
*
|
||||
* @param itemOwner The owner of the item
|
||||
* @param itemObjId The items Object ID
|
||||
*/
|
||||
virtual void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) {};
|
||||
|
||||
/**
|
||||
* Used by items to tell their owner that they were unequipped.
|
||||
*
|
||||
* @param itemOwner The owner of the item
|
||||
* @param itemObjId The items Object ID
|
||||
*/
|
||||
virtual void OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) {};
|
||||
};
|
||||
|
||||
Script* GetScript(Entity* parent, const std::string& scriptName);
|
||||
|
3
dScripts/EquipmentTriggers/CMakeLists.txt
Normal file
3
dScripts/EquipmentTriggers/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
set(DSCRIPTS_SOURCES_EQUIPMENTTRIGGERSSCRIPTS
|
||||
"CoilBackpackBase.cpp"
|
||||
PARENT_SCOPE)
|
25
dScripts/EquipmentTriggers/CoilBackpackBase.cpp
Normal file
25
dScripts/EquipmentTriggers/CoilBackpackBase.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "CoilBackpackBase.h"
|
||||
|
||||
#include "Entity.h"
|
||||
#include "SkillComponent.h"
|
||||
|
||||
void CoilBackpackBase::OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) {
|
||||
itemOwner->Subscribe(itemObjId, this, "HitOrHealResult");
|
||||
itemOwner->SetVar<uint8_t>(u"coilCount", 0);
|
||||
}
|
||||
|
||||
void CoilBackpackBase::NotifyHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {
|
||||
if (damage > 0) {
|
||||
self->SetVar<uint8_t>(u"coilCount", self->GetVar<uint8_t>(u"coilCount") + 1);
|
||||
if (self->GetVar<uint8_t>(u"coilCount") > 4) {
|
||||
auto* skillComponent = self->GetComponent<SkillComponent>();
|
||||
if (!skillComponent) return;
|
||||
skillComponent->CalculateBehavior(m_SkillId, m_BehaviorId, self->GetObjectID());
|
||||
self->SetVar<uint8_t>(u"coilCount", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoilBackpackBase::OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) {
|
||||
itemOwner->Unsubscribe(itemObjId, "HitOrHealResult");
|
||||
}
|
21
dScripts/EquipmentTriggers/CoilBackpackBase.h
Normal file
21
dScripts/EquipmentTriggers/CoilBackpackBase.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef __GemPackBase__H__
|
||||
#define __GemPackBase__H__
|
||||
|
||||
#include "CppScripts.h"
|
||||
|
||||
class CoilBackpackBase: public CppScripts::Script {
|
||||
public:
|
||||
CoilBackpackBase(uint32_t skillId, uint32_t behaviorId) {
|
||||
m_SkillId = skillId;
|
||||
m_BehaviorId = behaviorId;
|
||||
};
|
||||
|
||||
void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) override;
|
||||
void NotifyHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
|
||||
void OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) override;
|
||||
private:
|
||||
uint32_t m_SkillId = 0;
|
||||
uint32_t m_BehaviorId = 0;
|
||||
};
|
||||
|
||||
#endif //!__GemPackBase__H__
|
14
dScripts/EquipmentTriggers/GemPack.h
Normal file
14
dScripts/EquipmentTriggers/GemPack.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __GEMPACK__H__
|
||||
#define __GEMPACK__H__
|
||||
|
||||
#include "CoilBackpackBase.h"
|
||||
|
||||
class GemPack : public CoilBackpackBase {
|
||||
public:
|
||||
GemPack() : CoilBackpackBase(skillId, behaviorId) {};
|
||||
private:
|
||||
static const uint32_t skillId = 1488;
|
||||
static const uint32_t behaviorId = 36779;
|
||||
};
|
||||
|
||||
#endif //!__GEMPACK__H__
|
14
dScripts/EquipmentTriggers/ShardArmor.h
Normal file
14
dScripts/EquipmentTriggers/ShardArmor.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __SHARDARMOR__H__
|
||||
#define __SHARDARMOR__H__
|
||||
|
||||
#include "CoilBackpackBase.h"
|
||||
|
||||
class ShardArmor : public CoilBackpackBase {
|
||||
public:
|
||||
ShardArmor() : CoilBackpackBase(skillId, behaviorId) {};
|
||||
private:
|
||||
static const uint32_t skillId = 1249;
|
||||
static const uint32_t behaviorId = 29086;
|
||||
};
|
||||
|
||||
#endif //!__SHARDARMOR__H__
|
14
dScripts/EquipmentTriggers/TeslaPack.h
Normal file
14
dScripts/EquipmentTriggers/TeslaPack.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __TESLAPACK__H__
|
||||
#define __TESLAPACK__H__
|
||||
|
||||
#include "CoilBackpackBase.h"
|
||||
|
||||
class TeslaPack : public CoilBackpackBase {
|
||||
public:
|
||||
TeslaPack() : CoilBackpackBase(skillId, behaviorId) {};
|
||||
private:
|
||||
static const uint32_t skillId = 1001;
|
||||
static const uint32_t behaviorId = 20917;
|
||||
};
|
||||
|
||||
#endif //!__TESLAPACK__H__
|
@ -154,7 +154,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Connect to CDClient
|
||||
try {
|
||||
CDClientDatabase::Connect((Game::assetManager->GetResPath() / "CDServer.sqlite").string());
|
||||
CDClientDatabase::Connect((BinaryPathFinder::GetBinaryDir() / "resServer" / "CDServer.sqlite").string());
|
||||
} catch (CppSQLite3Exception& e) {
|
||||
Game::logger->Log("WorldServer", "Unable to connect to CDServer SQLite Database");
|
||||
Game::logger->Log("WorldServer", "Error: %s", e.errorMessage());
|
||||
|
@ -26,5 +26,13 @@ dump_folder=
|
||||
# Either the folder with /res or with /client and /versions
|
||||
client_location=
|
||||
|
||||
# The maximum outgoing bandwidth in bits
|
||||
# The maximum outgoing bandwidth in bits. If your clients are having
|
||||
# issues with enemies taking a while to catch up to them, increse this value.
|
||||
maximum_outgoing_bandwidth=80000
|
||||
|
||||
# The Maximum Translation Unit (MTU) size for packets. If players are
|
||||
# getting stuck at 55% on the loading screen, lower this number to
|
||||
# reduce the chances of packet loss. This value only has an effect
|
||||
# from 512 <= maximum_mtu_size <= 1492 so make sure to keep this
|
||||
# value within that range.
|
||||
maximum_mtu_size=1228
|
||||
|
Loading…
Reference in New Issue
Block a user