mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-06-28 07:39:59 +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.
|
||||
required: true
|
||||
- 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
|
||||
- type: input
|
||||
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.
|
||||
|
||||
## 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:
|
||||
* In the client directory, locate `boot.cfg`
|
||||
* Open it in a text editor and 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
|
||||
* Next locate the line `UGCUSE3DSERVICES=7:`
|
||||
* Open `boot.cfg` in a text editor and locate the line `UGCUSE3DSERVICES=7:`
|
||||
* Ensure the number after the 7 is a `0`
|
||||
* 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
|
||||
* 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
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
# define DluAssert(expression) do { assert(expression) } while(0)
|
||||
# define DluAssert(expression) do { assert(expression); } while(0)
|
||||
#else
|
||||
# define DluAssert(expression)
|
||||
#endif
|
||||
|
@ -83,6 +83,12 @@ public:
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
//! Initializer
|
||||
LDFData(const std::string& key, const T& value) {
|
||||
this->key = GeneralUtils::ASCIIToUTF16(key);
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
~LDFData(void) override {}
|
||||
|
||||
|
@ -320,7 +320,7 @@ const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEnt
|
||||
return m_SpawnPoints;
|
||||
}
|
||||
|
||||
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
|
||||
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
||||
if (!entity) {
|
||||
LOG("Attempted to construct null entity");
|
||||
return;
|
||||
@ -363,10 +363,9 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
||||
entity->WriteComponents(stream, eReplicaPacketType::CONSTRUCTION);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) {
|
||||
if (skipChecks) {
|
||||
Game::server->Send(stream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
} else {
|
||||
for (auto* player : PlayerManager::GetAllPlayers()) {
|
||||
// Don't need to construct the player to themselves
|
||||
if (entity->GetObjectID() == player->GetObjectID()) continue;
|
||||
if (player->GetPlayerReadyForUpdates()) {
|
||||
Game::server->Send(stream, player->GetSystemAddress(), false);
|
||||
} else {
|
||||
@ -374,7 +373,6 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
|
||||
if (ghostComponent) ghostComponent->AddLimboConstruction(entity->GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Game::server->Send(stream, sysAddr, false);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
const std::unordered_map<LWOOBJID, Entity*> GetAllEntities() const { return m_Entities; }
|
||||
#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 SerializeEntity(Entity* entity);
|
||||
void SerializeEntity(const Entity& entity);
|
||||
|
@ -334,7 +334,7 @@ bool ActivityComponent::IsPlayedBy(LWOOBJID playerID) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ActivityComponent::TakeCost(Entity* player) const {
|
||||
bool ActivityComponent::CheckCost(Entity* player) const {
|
||||
if (m_ActivityInfo.optionalCostLOT <= 0 || m_ActivityInfo.optionalCostCount <= 0)
|
||||
return true;
|
||||
|
||||
@ -345,11 +345,19 @@ bool ActivityComponent::TakeCost(Entity* player) const {
|
||||
if (inventoryComponent->GetLotCount(m_ActivityInfo.optionalCostLOT) < m_ActivityInfo.optionalCostCount)
|
||||
return false;
|
||||
|
||||
inventoryComponent->RemoveItem(m_ActivityInfo.optionalCostLOT, m_ActivityInfo.optionalCostCount);
|
||||
|
||||
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) {
|
||||
for (Lobby* lobby : m_Queue) {
|
||||
for (LobbyPlayer* lobbyPlayer : lobby->players) {
|
||||
@ -382,7 +390,7 @@ ActivityInstance* ActivityComponent::NewInstance() {
|
||||
void ActivityComponent::LoadPlayersIntoInstance(ActivityInstance* instance, const std::vector<LobbyPlayer*>& lobby) const {
|
||||
for (LobbyPlayer* player : lobby) {
|
||||
auto* entity = player->GetEntity();
|
||||
if (entity == nullptr || !TakeCost(entity)) {
|
||||
if (entity == nullptr || !CheckCost(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -234,10 +234,17 @@ public:
|
||||
*/
|
||||
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
|
||||
* @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;
|
||||
|
||||
|
@ -54,6 +54,7 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
||||
m_SourcePosition = m_Parent->GetPosition();
|
||||
m_Paused = false;
|
||||
m_SavedVelocity = NiPoint3Constant::ZERO;
|
||||
m_IsBounced = false;
|
||||
|
||||
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) {
|
||||
SetPath(m_Path->pathWaypoints);
|
||||
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
||||
m_IsBounced = !m_IsBounced;
|
||||
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
|
||||
std::reverse(waypoints.begin(), waypoints.end());
|
||||
if (m_IsBounced) std::reverse(waypoints.begin(), waypoints.end());
|
||||
SetPath(waypoints);
|
||||
} else if (m_Path->pathBehavior == PathBehavior::Once) {
|
||||
Stop();
|
||||
|
@ -321,6 +321,8 @@ private:
|
||||
bool m_Paused;
|
||||
|
||||
NiPoint3 m_SavedVelocity;
|
||||
|
||||
bool m_IsBounced{};
|
||||
};
|
||||
|
||||
#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
|
||||
* 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 } {
|
||||
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
|
||||
if (petFlags.find(m_Parent->GetLOT()) != petFlags.end()) {
|
||||
tamer->GetCharacter()->SetPlayerFlag(petFlags.at(m_Parent->GetLOT()), true);
|
||||
}
|
||||
constexpr auto PET_FLAG_BASE = 800;
|
||||
tamer->GetCharacter()->SetPlayerFlag(PET_FLAG_BASE + m_ComponentId, true);
|
||||
|
||||
auto* missionComponent = tamer->GetComponent<MissionComponent>();
|
||||
|
||||
|
@ -250,11 +250,6 @@ private:
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -272,6 +272,10 @@ void PropertyManagementComponent::OnStartBuilding() {
|
||||
model->HandleMsg(reset);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* const entity : Game::entityManager->GetEntitiesInGroup("SpawnedPropertyEnemies")) {
|
||||
if (entity) entity->Smash();
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::OnFinishBuilding() {
|
||||
@ -296,6 +300,10 @@ void PropertyManagementComponent::OnFinishBuilding() {
|
||||
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) {
|
||||
|
@ -84,9 +84,11 @@ void Strip::HandleMsg(MigrateActionsMessage& msg) {
|
||||
|
||||
template<>
|
||||
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();
|
||||
m_WaitingForAction = false;
|
||||
}
|
||||
@ -113,7 +115,9 @@ void Strip::Spawn(LOT lot, Entity& entity) {
|
||||
info.pos = entity.GetPosition();
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
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
|
||||
@ -139,6 +143,7 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent) {
|
||||
|
||||
// Default velocity is 3 units per second.
|
||||
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") {
|
||||
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());
|
||||
g_WarnedActions.insert(nextActionType.data());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
IncrementAction();
|
||||
@ -259,13 +263,19 @@ bool Strip::CheckMovement(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;
|
||||
|
||||
// Don't run this strip if we're paused.
|
||||
m_PausedTime -= deltaTime;
|
||||
if (m_PausedTime > 0.0f) return;
|
||||
|
||||
m_PausedTime = 0.0f;
|
||||
|
||||
// Return here if we're waiting for external interactions to continue.
|
||||
if (m_WaitingForAction) return;
|
||||
|
||||
auto& entity = *modelComponent.GetParent();
|
||||
|
@ -37,6 +37,9 @@ public:
|
||||
void SpawnDrop(LOT dropLOT, Entity& entity);
|
||||
void ProcNormalAction(float deltaTime, ModelComponent& modelComponent);
|
||||
void RemoveStates(ModelComponent& modelComponent) const;
|
||||
|
||||
// 2 actions are required for strips to work
|
||||
bool HasMinimumActions() const { return m_Actions.size() >= 2; }
|
||||
private:
|
||||
// Indicates this Strip is waiting for an action to be taken upon it to progress to its actions
|
||||
bool m_WaitingForAction{ false };
|
||||
|
@ -336,6 +336,7 @@
|
||||
#include "NsRaceServer.h"
|
||||
#include "TrialFactionArmorServer.h"
|
||||
#include "ImaginationBackPack.h"
|
||||
#include "NsWinterRaceServer.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -656,6 +657,7 @@ namespace {
|
||||
//FB
|
||||
{"scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua", []() {return new RockHydrantBroken();}},
|
||||
{"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
|
||||
{"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}")
|
||||
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)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_GF})
|
||||
@ -26,5 +32,5 @@ foreach(file ${DSCRIPTS_SOURCES_AI_RACING_TRACK_FV})
|
||||
endforeach()
|
||||
|
||||
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)
|
||||
|
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:
|
||||
UserManager::Instance()->CreateUser(it->second.sysAddr, username.GetAsString(), userHash);
|
||||
|
||||
auto zone = Game::zoneManager->GetZone();
|
||||
if (zone) {
|
||||
if (Game::zoneManager->HasZone()) {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
|
||||
auto zone = Game::zoneManager->GetZone();
|
||||
if (zone->GetZoneID().GetMapID() == 1100) {
|
||||
auto pos = zone->GetSpawnPos();
|
||||
x = pos.x;
|
||||
@ -1045,7 +1045,7 @@ void HandlePacket(Packet* packet) {
|
||||
|
||||
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) {
|
||||
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternionConstant::IDENTITY);
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
/* Gets a pointer to the currently loaded zone. */
|
||||
Zone* GetZoneMut() const;
|
||||
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.
|
||||
|
||||
/* Adds a spawner to the zone with the specified ID. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user