mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-06-28 15:50:02 +00:00
Merge branch 'main' into more-behaviors
This commit is contained in:
commit
263c329932
5
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
5
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -16,7 +16,10 @@ body:
|
|||||||
I have validated that this issue is not a syntax error of either MySQL or SQLite.
|
I have validated that this issue is not a syntax error of either MySQL or SQLite.
|
||||||
required: true
|
required: true
|
||||||
- label: >
|
- label: >
|
||||||
I have pulled the latest version of the main branch of DarkflameServer and have confirmed that the issue exists there.
|
I have downloaded/pulled the latest version of the main branch of DarkflameServer and have confirmed that the issue exists there.
|
||||||
|
required: true
|
||||||
|
- label: >
|
||||||
|
I have verified that my boot.cfg is configured as per the [README](https://github.com/DarkflameUniverse/DarkflameServer?tab=readme-ov-file#allowing-a-user-to-connect-to-your-server).
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: server-version
|
id: server-version
|
||||||
|
@ -324,13 +324,15 @@ While a character has a gmlevel of anything but `0`, some gameplay behavior will
|
|||||||
Some changes to the client `boot.cfg` file are needed to play on your server.
|
Some changes to the client `boot.cfg` file are needed to play on your server.
|
||||||
|
|
||||||
## Allowing a user to connect to your server
|
## Allowing a user to connect to your server
|
||||||
|
**ALL OF THESE CHANGES ARE REQUIRED. PLEASE FULLY READ THIS SECTION**
|
||||||
|
|
||||||
To connect to a server follow these steps:
|
To connect to a server follow these steps:
|
||||||
* In the client directory, locate `boot.cfg`
|
* In the client directory, locate `boot.cfg`
|
||||||
* Open it in a text editor and locate where it says `AUTHSERVERIP=0:`
|
* Open `boot.cfg` in a text editor and locate the line `UGCUSE3DSERVICES=7:`
|
||||||
* Replace the contents after to `:` and the following `,` with what you configured as the server's public facing IP. For example `AUTHSERVERIP=0:localhost` for locally hosted servers
|
|
||||||
* Next locate the line `UGCUSE3DSERVICES=7:`
|
|
||||||
* Ensure the number after the 7 is a `0`
|
* Ensure the number after the 7 is a `0`
|
||||||
* Alternatively, remove the line with `UGCUSE3DSERVICES` altogether
|
* Alternatively, remove the line with `UGCUSE3DSERVICES` altogether
|
||||||
|
* Next locate where it says `AUTHSERVERIP=0:`
|
||||||
|
* Replace the contents after to `:` and the following `,` with what you configured as the server's public facing IP. For example `AUTHSERVERIP=0:localhost` for locally hosted servers
|
||||||
* Launch `legouniverse.exe`, through `wine` if on a Unix-like operating system
|
* Launch `legouniverse.exe`, through `wine` if on a Unix-like operating system
|
||||||
* Note that if you are on WSL2, you will need to configure the public IP in the server and client to be the IP of the WSL2 instance and not localhost, which can be found by running `ifconfig` in the terminal. Windows defaults to WSL1, so this will not apply to most users.
|
* Note that if you are on WSL2, you will need to configure the public IP in the server and client to be the IP of the WSL2 instance and not localhost, which can be found by running `ifconfig` in the terminal. Windows defaults to WSL1, so this will not apply to most users.
|
||||||
As an example, here is what the boot.cfg is required to contain for a server with the ip 12.34.56.78
|
As an example, here is what the boot.cfg is required to contain for a server with the ip 12.34.56.78
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
# define DluAssert(expression) do { assert(expression) } while(0)
|
# define DluAssert(expression) do { assert(expression); } while(0)
|
||||||
#else
|
#else
|
||||||
# define DluAssert(expression)
|
# define DluAssert(expression)
|
||||||
#endif
|
#endif
|
||||||
|
@ -83,6 +83,12 @@ public:
|
|||||||
this->value = value;
|
this->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Initializer
|
||||||
|
LDFData(const std::string& key, const T& value) {
|
||||||
|
this->key = GeneralUtils::ASCIIToUTF16(key);
|
||||||
|
this->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
~LDFData(void) override {}
|
~LDFData(void) override {}
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEnt
|
|||||||
return m_SpawnPoints;
|
return m_SpawnPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
|
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
LOG("Attempted to construct null entity");
|
LOG("Attempted to construct null entity");
|
||||||
return;
|
return;
|
||||||
@ -363,10 +363,9 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
|||||||
entity->WriteComponents(stream, eReplicaPacketType::CONSTRUCTION);
|
entity->WriteComponents(stream, eReplicaPacketType::CONSTRUCTION);
|
||||||
|
|
||||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
||||||
if (skipChecks) {
|
|
||||||
Game::server->Send(stream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
|
||||||
} else {
|
|
||||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||||
|
// Don't need to construct the player to themselves
|
||||||
|
if (entity->GetObjectID() == player->GetObjectID()) continue;
|
||||||
if (player->GetPlayerReadyForUpdates()) {
|
if (player->GetPlayerReadyForUpdates()) {
|
||||||
Game::server->Send(stream, player->GetSystemAddress(), false);
|
Game::server->Send(stream, player->GetSystemAddress(), false);
|
||||||
} else {
|
} else {
|
||||||
@ -374,7 +373,6 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
|||||||
if (ghostComponent) ghostComponent->AddLimboConstruction(entity->GetObjectID());
|
if (ghostComponent) ghostComponent->AddLimboConstruction(entity->GetObjectID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Game::server->Send(stream, sysAddr, false);
|
Game::server->Send(stream, sysAddr, false);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
const std::unordered_map<LWOOBJID, Entity*> GetAllEntities() const { return m_Entities; }
|
const std::unordered_map<LWOOBJID, Entity*> GetAllEntities() const { return m_Entities; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ConstructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS, bool skipChecks = false);
|
void ConstructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
void DestructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
void DestructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
void SerializeEntity(Entity* entity);
|
void SerializeEntity(Entity* entity);
|
||||||
void SerializeEntity(const Entity& entity);
|
void SerializeEntity(const Entity& entity);
|
||||||
|
@ -334,7 +334,7 @@ bool ActivityComponent::IsPlayedBy(LWOOBJID playerID) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ActivityComponent::TakeCost(Entity* player) const {
|
bool ActivityComponent::CheckCost(Entity* player) const {
|
||||||
if (m_ActivityInfo.optionalCostLOT <= 0 || m_ActivityInfo.optionalCostCount <= 0)
|
if (m_ActivityInfo.optionalCostLOT <= 0 || m_ActivityInfo.optionalCostCount <= 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -345,11 +345,19 @@ bool ActivityComponent::TakeCost(Entity* player) const {
|
|||||||
if (inventoryComponent->GetLotCount(m_ActivityInfo.optionalCostLOT) < m_ActivityInfo.optionalCostCount)
|
if (inventoryComponent->GetLotCount(m_ActivityInfo.optionalCostLOT) < m_ActivityInfo.optionalCostCount)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
inventoryComponent->RemoveItem(m_ActivityInfo.optionalCostLOT, m_ActivityInfo.optionalCostCount);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ActivityComponent::TakeCost(Entity* player) const{
|
||||||
|
|
||||||
|
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||||
|
if (CheckCost(player)) {
|
||||||
|
inventoryComponent->RemoveItem(m_ActivityInfo.optionalCostLOT, m_ActivityInfo.optionalCostCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ActivityComponent::PlayerReady(Entity* player, bool bReady) {
|
void ActivityComponent::PlayerReady(Entity* player, bool bReady) {
|
||||||
for (Lobby* lobby : m_Queue) {
|
for (Lobby* lobby : m_Queue) {
|
||||||
for (LobbyPlayer* lobbyPlayer : lobby->players) {
|
for (LobbyPlayer* lobbyPlayer : lobby->players) {
|
||||||
@ -382,7 +390,7 @@ ActivityInstance* ActivityComponent::NewInstance() {
|
|||||||
void ActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector<LobbyPlayer*>& lobby) const {
|
void ActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector<LobbyPlayer*>& lobby) const {
|
||||||
for (LobbyPlayer* player : lobby) {
|
for (LobbyPlayer* player : lobby) {
|
||||||
auto* entity = player->GetEntity();
|
auto* entity = player->GetEntity();
|
||||||
if (entity == nullptr || !TakeCost(entity)) {
|
if (entity == nullptr || !CheckCost(entity)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,10 +234,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool IsPlayedBy(LWOOBJID playerID) const;
|
bool IsPlayedBy(LWOOBJID playerID) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entity has enough cost to play this activity
|
||||||
|
* @param player the entity to check
|
||||||
|
* @return true if the entity has enough cost to play this activity, false otherwise
|
||||||
|
*/
|
||||||
|
bool CheckCost(Entity* player) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the cost of the activity (e.g. green imaginate) for the entity that plays this activity
|
* Removes the cost of the activity (e.g. green imaginate) for the entity that plays this activity
|
||||||
* @param player the entity to take cost for
|
* @param player the entity to take cost for
|
||||||
* @return true if the cost was successfully deducted, false otherwise
|
* @return true if the cost was taken, false otherwise
|
||||||
*/
|
*/
|
||||||
bool TakeCost(Entity* player) const;
|
bool TakeCost(Entity* player) const;
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
|||||||
m_SourcePosition = m_Parent->GetPosition();
|
m_SourcePosition = m_Parent->GetPosition();
|
||||||
m_Paused = false;
|
m_Paused = false;
|
||||||
m_SavedVelocity = NiPoint3Constant::ZERO;
|
m_SavedVelocity = NiPoint3Constant::ZERO;
|
||||||
|
m_IsBounced = false;
|
||||||
|
|
||||||
if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path"));
|
if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path"));
|
||||||
}
|
}
|
||||||
@ -158,8 +159,9 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
if (m_Path->pathBehavior == PathBehavior::Loop) {
|
if (m_Path->pathBehavior == PathBehavior::Loop) {
|
||||||
SetPath(m_Path->pathWaypoints);
|
SetPath(m_Path->pathWaypoints);
|
||||||
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
||||||
|
m_IsBounced = !m_IsBounced;
|
||||||
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
|
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
|
||||||
std::reverse(waypoints.begin(), waypoints.end());
|
if (m_IsBounced) std::reverse(waypoints.begin(), waypoints.end());
|
||||||
SetPath(waypoints);
|
SetPath(waypoints);
|
||||||
} else if (m_Path->pathBehavior == PathBehavior::Once) {
|
} else if (m_Path->pathBehavior == PathBehavior::Once) {
|
||||||
Stop();
|
Stop();
|
||||||
|
@ -321,6 +321,8 @@ private:
|
|||||||
bool m_Paused;
|
bool m_Paused;
|
||||||
|
|
||||||
NiPoint3 m_SavedVelocity;
|
NiPoint3 m_SavedVelocity;
|
||||||
|
|
||||||
|
bool m_IsBounced{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOVEMENTAICOMPONENT_H
|
#endif // MOVEMENTAICOMPONENT_H
|
||||||
|
@ -42,35 +42,6 @@ std::unordered_map<LWOOBJID, LWOOBJID> PetComponent::activePets{};
|
|||||||
* Maps all the pet lots to a flag indicating that the player has caught it. All basic pets have been guessed by ObjID
|
* Maps all the pet lots to a flag indicating that the player has caught it. All basic pets have been guessed by ObjID
|
||||||
* while the faction ones could be checked using their respective missions.
|
* while the faction ones could be checked using their respective missions.
|
||||||
*/
|
*/
|
||||||
const std::map<LOT, int32_t> PetComponent::petFlags{
|
|
||||||
{ 3050, 801 }, // Elephant
|
|
||||||
{ 3054, 803 }, // Cat
|
|
||||||
{ 3195, 806 }, // Triceratops
|
|
||||||
{ 3254, 807 }, // Terrier
|
|
||||||
{ 3261, 811 }, // Skunk
|
|
||||||
{ 3672, 813 }, // Bunny
|
|
||||||
{ 3994, 814 }, // Crocodile
|
|
||||||
{ 5635, 815 }, // Doberman
|
|
||||||
{ 5636, 816 }, // Buffalo
|
|
||||||
{ 5637, 818 }, // Robot Dog
|
|
||||||
{ 5639, 819 }, // Red Dragon
|
|
||||||
{ 5640, 820 }, // Tortoise
|
|
||||||
{ 5641, 821 }, // Green Dragon
|
|
||||||
{ 5643, 822 }, // Panda, see mission 786
|
|
||||||
{ 5642, 823 }, // Mantis
|
|
||||||
{ 6720, 824 }, // Warthog
|
|
||||||
{ 3520, 825 }, // Lion, see mission 1318
|
|
||||||
{ 7638, 826 }, // Goat
|
|
||||||
{ 7694, 827 }, // Crab
|
|
||||||
{ 12294, 829 }, // Reindeer
|
|
||||||
{ 12431, 830 }, // Stegosaurus, see mission 1386
|
|
||||||
{ 12432, 831 }, // Saber cat, see mission 1389
|
|
||||||
{ 12433, 832 }, // Gryphon, see mission 1392
|
|
||||||
{ 12434, 833 }, // Alien, see mission 1188
|
|
||||||
// 834: unknown?, see mission 506, 688
|
|
||||||
{ 16210, 836 }, // Ninjago Earth Dragon, see mission 1836
|
|
||||||
{ 13067, 838 }, // Skeleton dragon
|
|
||||||
};
|
|
||||||
|
|
||||||
PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Component{ parentEntity } {
|
PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Component{ parentEntity } {
|
||||||
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentId); // TODO: Make reference when safe
|
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentId); // TODO: Make reference when safe
|
||||||
@ -556,9 +527,8 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Triggers the catch a pet missions
|
// Triggers the catch a pet missions
|
||||||
if (petFlags.find(m_Parent->GetLOT()) != petFlags.end()) {
|
constexpr auto PET_FLAG_BASE = 800;
|
||||||
tamer->GetCharacter()->SetPlayerFlag(petFlags.at(m_Parent->GetLOT()), true);
|
tamer->GetCharacter()->SetPlayerFlag(PET_FLAG_BASE + m_ComponentId, true);
|
||||||
}
|
|
||||||
|
|
||||||
auto* missionComponent = tamer->GetComponent<MissionComponent>();
|
auto* missionComponent = tamer->GetComponent<MissionComponent>();
|
||||||
|
|
||||||
|
@ -250,11 +250,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
static std::unordered_map<LWOOBJID, LWOOBJID> currentActivities;
|
static std::unordered_map<LWOOBJID, LWOOBJID> currentActivities;
|
||||||
|
|
||||||
/**
|
|
||||||
* Flags that indicate that a player has tamed a pet, indexed by the LOT of the pet
|
|
||||||
*/
|
|
||||||
static const std::map<LOT, int32_t> petFlags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the component in the pet component table
|
* The ID of the component in the pet component table
|
||||||
*/
|
*/
|
||||||
|
@ -272,6 +272,10 @@ void PropertyManagementComponent::OnStartBuilding() {
|
|||||||
model->HandleMsg(reset);
|
model->HandleMsg(reset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto* const entity : Game::entityManager->GetEntitiesInGroup("SpawnedPropertyEnemies")) {
|
||||||
|
if (entity) entity->Smash();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyManagementComponent::OnFinishBuilding() {
|
void PropertyManagementComponent::OnFinishBuilding() {
|
||||||
@ -296,6 +300,10 @@ void PropertyManagementComponent::OnFinishBuilding() {
|
|||||||
model->HandleMsg(reset);
|
model->HandleMsg(reset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto* const entity : Game::entityManager->GetEntitiesInGroup("SpawnedPropertyEnemies")) {
|
||||||
|
if (entity) entity->Smash();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const NiPoint3 position, NiQuaternion rotation) {
|
void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const NiPoint3 position, NiQuaternion rotation) {
|
||||||
|
@ -84,9 +84,11 @@ void Strip::HandleMsg(MigrateActionsMessage& msg) {
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Strip::HandleMsg(GameMessages::RequestUse& msg) {
|
void Strip::HandleMsg(GameMessages::RequestUse& msg) {
|
||||||
if (m_PausedTime > 0.0f) return;
|
if (m_PausedTime > 0.0f || !HasMinimumActions()) return;
|
||||||
|
|
||||||
if (m_Actions[m_NextActionIndex].GetType() == "OnInteract") {
|
auto& nextAction = GetNextAction();
|
||||||
|
|
||||||
|
if (nextAction.GetType() == "OnInteract") {
|
||||||
IncrementAction();
|
IncrementAction();
|
||||||
m_WaitingForAction = false;
|
m_WaitingForAction = false;
|
||||||
}
|
}
|
||||||
@ -113,7 +115,9 @@ void Strip::Spawn(LOT lot, Entity& entity) {
|
|||||||
info.pos = entity.GetPosition();
|
info.pos = entity.GetPosition();
|
||||||
info.rot = NiQuaternionConstant::IDENTITY;
|
info.rot = NiQuaternionConstant::IDENTITY;
|
||||||
info.spawnerID = entity.GetObjectID();
|
info.spawnerID = entity.GetObjectID();
|
||||||
Game::entityManager->ConstructEntity(Game::entityManager->CreateEntity(info, nullptr, &entity));
|
auto* const spawnedEntity = Game::entityManager->CreateEntity(info, nullptr, &entity);
|
||||||
|
spawnedEntity->AddToGroup("SpawnedPropertyEnemies");
|
||||||
|
Game::entityManager->ConstructEntity(spawnedEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawns a specific drop for all
|
// Spawns a specific drop for all
|
||||||
@ -139,6 +143,7 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent) {
|
|||||||
|
|
||||||
// Default velocity is 3 units per second.
|
// Default velocity is 3 units per second.
|
||||||
entity.SetVelocity(NiPoint3{0.0f, isFlyDown ? -3.0f : 3.0f, 0.0f});
|
entity.SetVelocity(NiPoint3{0.0f, isFlyDown ? -3.0f : 3.0f, 0.0f});
|
||||||
|
modelComponent.SetVelocity(NiPoint3{0.0f, isFlyDown ? -3.0f : 3.0f, 0.0f});
|
||||||
}
|
}
|
||||||
else if (nextActionType == "MoveRight" || nextActionType == "MoveLeft") {
|
else if (nextActionType == "MoveRight" || nextActionType == "MoveLeft") {
|
||||||
bool isMoveLeft = nextActionType == "MoveLeft";
|
bool isMoveLeft = nextActionType == "MoveLeft";
|
||||||
@ -205,7 +210,6 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent) {
|
|||||||
LOG("Tried to play action (%s) which is not supported.", nextActionType.data());
|
LOG("Tried to play action (%s) which is not supported.", nextActionType.data());
|
||||||
g_WarnedActions.insert(nextActionType.data());
|
g_WarnedActions.insert(nextActionType.data());
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IncrementAction();
|
IncrementAction();
|
||||||
@ -259,13 +263,19 @@ bool Strip::CheckMovement(float deltaTime, ModelComponent& modelComponent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Strip::Update(float deltaTime, ModelComponent& modelComponent) {
|
void Strip::Update(float deltaTime, ModelComponent& modelComponent) {
|
||||||
|
// No point in running a strip with only one action.
|
||||||
|
// Strips are also designed to have 2 actions or more to run.
|
||||||
|
if (!HasMinimumActions()) return;
|
||||||
|
|
||||||
if (!CheckMovement(deltaTime, modelComponent)) return;
|
if (!CheckMovement(deltaTime, modelComponent)) return;
|
||||||
|
|
||||||
|
// Don't run this strip if we're paused.
|
||||||
m_PausedTime -= deltaTime;
|
m_PausedTime -= deltaTime;
|
||||||
if (m_PausedTime > 0.0f) return;
|
if (m_PausedTime > 0.0f) return;
|
||||||
|
|
||||||
m_PausedTime = 0.0f;
|
m_PausedTime = 0.0f;
|
||||||
|
|
||||||
|
// Return here if we're waiting for external interactions to continue.
|
||||||
if (m_WaitingForAction) return;
|
if (m_WaitingForAction) return;
|
||||||
|
|
||||||
auto& entity = *modelComponent.GetParent();
|
auto& entity = *modelComponent.GetParent();
|
||||||
|
@ -37,6 +37,9 @@ public:
|
|||||||
void SpawnDrop(LOT dropLOT, Entity& entity);
|
void SpawnDrop(LOT dropLOT, Entity& entity);
|
||||||
void ProcNormalAction(float deltaTime, ModelComponent& modelComponent);
|
void ProcNormalAction(float deltaTime, ModelComponent& modelComponent);
|
||||||
void RemoveStates(ModelComponent& modelComponent) const;
|
void RemoveStates(ModelComponent& modelComponent) const;
|
||||||
|
|
||||||
|
// 2 actions are required for strips to work
|
||||||
|
bool HasMinimumActions() const { return m_Actions.size() >= 2; }
|
||||||
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 };
|
||||||
|
@ -336,6 +336,7 @@
|
|||||||
#include "NsRaceServer.h"
|
#include "NsRaceServer.h"
|
||||||
#include "TrialFactionArmorServer.h"
|
#include "TrialFactionArmorServer.h"
|
||||||
#include "ImaginationBackPack.h"
|
#include "ImaginationBackPack.h"
|
||||||
|
#include "NsWinterRaceServer.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -656,6 +657,7 @@ namespace {
|
|||||||
//FB
|
//FB
|
||||||
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua", []() {return new RockHydrantBroken();}},
|
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua", []() {return new RockHydrantBroken();}},
|
||||||
{"scripts\\ai\\NS\\L_NS_WH_FANS.lua", []() {return new WhFans();}},
|
{"scripts\\ai\\NS\\L_NS_WH_FANS.lua", []() {return new WhFans();}},
|
||||||
|
{"scripts\\ai\\RACING\\TRACK_NS_WINTER\\NS_WINTER_RACE_SERVER.lua", []() {return new NsWinterRaceServer();}},
|
||||||
|
|
||||||
//WBL
|
//WBL
|
||||||
{"scripts\\zone\\LUPs\\WBL_generic_zone.lua", []() {return new WblGenericZone();}},
|
{"scripts\\zone\\LUPs\\WBL_generic_zone.lua", []() {return new WblGenericZone();}},
|
||||||
|
@ -13,6 +13,12 @@ foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_NS})
|
|||||||
set(DSCRIPTS_SOURCES_AI_RACING ${DSCRIPTS_SOURCES_AI_RACING} "TRACK_NS/${file}")
|
set(DSCRIPTS_SOURCES_AI_RACING ${DSCRIPTS_SOURCES_AI_RACING} "TRACK_NS/${file}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
add_subdirectory(TRACK_NS_WINTER)
|
||||||
|
|
||||||
|
foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_NS_WINTER})
|
||||||
|
set(DSCRIPTS_SOURCES_AI_RACING ${DSCRIPTS_SOURCES_AI_RACING} "TRACK_NS_WINTER/${file}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
add_subdirectory(TRACK_GF)
|
add_subdirectory(TRACK_GF)
|
||||||
|
|
||||||
foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_GF})
|
foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_GF})
|
||||||
@ -26,5 +32,5 @@ foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_FV})
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_library(dScriptsAiRacing OBJECT ${DSCRIPTS_SOURCES_AI_RACING})
|
add_library(dScriptsAiRacing OBJECT ${DSCRIPTS_SOURCES_AI_RACING})
|
||||||
target_include_directories(dScriptsAiRacing PUBLIC "." "OBJECTS" "TRACK_NS" "TRACK_GF" "TRACK_FV")
|
target_include_directories(dScriptsAiRacing PUBLIC "." "OBJECTS" "TRACK_NS" "TRACK_NS_WINTER" "TRACK_GF" "TRACK_FV")
|
||||||
target_precompile_headers(dScriptsAiRacing REUSE_FROM dScriptsBase)
|
target_precompile_headers(dScriptsAiRacing REUSE_FROM dScriptsBase)
|
||||||
|
3
dScripts/ai/RACING/TRACK_NS_WINTER/CMakeLists.txt
Normal file
3
dScripts/ai/RACING/TRACK_NS_WINTER/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
set(DSCRIPTS_SOURCES_AI_RACING_TRACK_NS_WINTER
|
||||||
|
"NsWinterRaceServer.cpp"
|
||||||
|
PARENT_SCOPE)
|
53
dScripts/ai/RACING/TRACK_NS_WINTER/NsWinterRaceServer.cpp
Normal file
53
dScripts/ai/RACING/TRACK_NS_WINTER/NsWinterRaceServer.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#include "NsWinterRaceServer.h"
|
||||||
|
#include "GameMessages.h"
|
||||||
|
#include "RacingControlComponent.h"
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
void NsWinterRaceServer::OnStartup(Entity* self) {
|
||||||
|
GameMessages::ConfigureRacingControl config;
|
||||||
|
auto& raceSet = config.racingSettings;
|
||||||
|
|
||||||
|
raceSet.push_back(make_unique<LDFData<std::u16string>>("GameType", u"Racing"));
|
||||||
|
raceSet.push_back(make_unique<LDFData<std::u16string>>("GameState", u"Starting"));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Number_Of_PlayersPerTeam", 6));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Minimum_Players_to_Start", 2));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Minimum_Players_for_Group_Achievments", 2));
|
||||||
|
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Car_Object", 7703));
|
||||||
|
raceSet.push_back(make_unique<LDFData<std::u16string>>("Race_PathName", u"MainPath"));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Current_Lap", 1));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Number_of_Laps", 3));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("activityID", 42));
|
||||||
|
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_1", 100));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_2", 90));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_3", 80));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_4", 70));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_5", 60));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Place_6", 50));
|
||||||
|
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_1", 15));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_2", 25));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_3", 50));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_4", 85));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_5", 90));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Num_of_Players_6", 100));
|
||||||
|
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Number_of_Spawn_Groups", 1));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Spawners", 4847));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Spawners", 4848));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Flag", 4850));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Flag", 4851));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Point", 4846));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Point", 4845));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Red_Mark", 4844));
|
||||||
|
raceSet.push_back(make_unique<LDFData<int32_t>>("Blue_Mark", 4843));
|
||||||
|
|
||||||
|
const auto racingControllers = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::RACING_CONTROL);
|
||||||
|
for (auto* const racingController : racingControllers) {
|
||||||
|
auto* const racingComponent = racingController->GetComponent<RacingControlComponent>();
|
||||||
|
if (racingComponent) racingComponent->MsgConfigureRacingControl(config);
|
||||||
|
}
|
||||||
|
}
|
15
dScripts/ai/RACING/TRACK_NS_WINTER/NsWinterRaceServer.h
Normal file
15
dScripts/ai/RACING/TRACK_NS_WINTER/NsWinterRaceServer.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Darkflame Universe
|
||||||
|
// Copyright 2025
|
||||||
|
|
||||||
|
#ifndef NSWINTERRACESERVER_H
|
||||||
|
#define NSWINTERRACESERVER_H
|
||||||
|
|
||||||
|
#include "CppScripts.h"
|
||||||
|
#include "RaceImaginationServer.h"
|
||||||
|
|
||||||
|
class NsWinterRaceServer : public RaceImaginationServer {
|
||||||
|
public:
|
||||||
|
void OnStartup(Entity* self) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!NSWINTERRACESERVER_H
|
@ -713,12 +713,12 @@ void HandleMasterPacket(Packet* packet) {
|
|||||||
//Create our user and send them in:
|
//Create our user and send them in:
|
||||||
UserManager::Instance()->CreateUser(it->second.sysAddr, username.GetAsString(), userHash);
|
UserManager::Instance()->CreateUser(it->second.sysAddr, username.GetAsString(), userHash);
|
||||||
|
|
||||||
auto zone = Game::zoneManager->GetZone();
|
if (Game::zoneManager->HasZone()) {
|
||||||
if (zone) {
|
|
||||||
float x = 0.0f;
|
float x = 0.0f;
|
||||||
float y = 0.0f;
|
float y = 0.0f;
|
||||||
float z = 0.0f;
|
float z = 0.0f;
|
||||||
|
|
||||||
|
auto zone = Game::zoneManager->GetZone();
|
||||||
if (zone->GetZoneID().GetMapID() == 1100) {
|
if (zone->GetZoneID().GetMapID() == 1100) {
|
||||||
auto pos = zone->GetSpawnPos();
|
auto pos = zone->GetSpawnPos();
|
||||||
x = pos.x;
|
x = pos.x;
|
||||||
@ -1045,7 +1045,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
|
|
||||||
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
||||||
|
|
||||||
Game::entityManager->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS, true);
|
Game::entityManager->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
|
||||||
if (respawnPoint != NiPoint3Constant::ZERO) {
|
if (respawnPoint != NiPoint3Constant::ZERO) {
|
||||||
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternionConstant::IDENTITY);
|
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternionConstant::IDENTITY);
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
/* Gets a pointer to the currently loaded zone. */
|
/* Gets a pointer to the currently loaded zone. */
|
||||||
Zone* GetZoneMut() const;
|
Zone* GetZoneMut() const;
|
||||||
const Zone* GetZone() const { return GetZoneMut(); };
|
const Zone* GetZone() const { return GetZoneMut(); };
|
||||||
|
bool HasZone() const { return m_pZone != nullptr; };
|
||||||
void LoadZone(const LWOZONEID& zoneID); //Discard the current zone (if any) and loads a new zone.
|
void LoadZone(const LWOZONEID& zoneID); //Discard the current zone (if any) and loads a new zone.
|
||||||
|
|
||||||
/* Adds a spawner to the zone with the specified ID. */
|
/* Adds a spawner to the zone with the specified ID. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user