Merge branch 'main' into leaderboards-again

This commit is contained in:
David Markowitz
2025-05-05 00:21:43 -07:00
132 changed files with 51229 additions and 1114 deletions

View File

@@ -16,6 +16,7 @@ void DLUVanityTeleportingObject::OnStartup(Entity* self) {
void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "setupTeleport") {
RenderComponent::PlayAnimation(self, u"interact");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportBeam", "teleportBeam");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 6478, u"teleportRings", "teleportRings");
@@ -27,7 +28,6 @@ void DLUVanityTeleportingObject::OnTimerDone(Entity* self, std::string timerName
} else if (timerName == "teleport") {
std::vector<VanityObjectLocation>& locations = m_Object->m_Locations[Game::server->GetZoneID()];
selectLocation:
VanityObjectLocation& newLocation = locations[GeneralUtils::GenerateRandomNumber<size_t>(0, locations.size() - 1)];
// try to get not the same position, but if we get the same one twice, it's fine

View File

@@ -8,16 +8,11 @@ void AmTeapotServer::OnUse(Entity* self, Entity* user) {
auto* inventoryComponent = user->GetComponent<InventoryComponent>();
if (!inventoryComponent) return;
auto* blueFlowerItem = inventoryComponent->FindItemByLot(BLUE_FLOWER_LEAVES, eInventoryType::ITEMS);
if (!blueFlowerItem) {
blueFlowerItem = inventoryComponent->FindItemByLot(BLUE_FLOWER_LEAVES, eInventoryType::VAULT_ITEMS);
if (!blueFlowerItem) return;
}
// The client allows you to use the teapot only if you have a stack of 10 leaves in some inventory somewhere.
if (blueFlowerItem->GetCount() >= 10) {
blueFlowerItem->SetCount(blueFlowerItem->GetCount() - 10);
if (inventoryComponent->GetLotCountNonTransfer(BLUE_FLOWER_LEAVES, false) >= 10) {
inventoryComponent->RemoveItem(BLUE_FLOWER_LEAVES, 10, eInventoryType::ALL);
inventoryComponent->AddItem(WU_S_IMAGINATION_TEA, 1);
}
GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID());
}

View File

@@ -10,49 +10,38 @@ void NsLegoClubDoor::OnStartup(Entity* self) {
self->SetVar(u"teleportString", m_TeleportString);
self->SetVar(u"spawnPoint", m_SpawnPoint);
args = {};
teleportArgs.Reset();
args.Insert("callbackClient", std::to_string(self->GetObjectID()));
args.Insert("strIdentifier", "choiceDoor");
args.Insert("title", "%[UI_CHOICE_DESTINATION]");
teleportArgs.Insert("callbackClient", std::to_string(self->GetObjectID()));
teleportArgs.Insert("strIdentifier", "choiceDoor");
teleportArgs.Insert("title", "%[UI_CHOICE_DESTINATION]");
AMFArrayValue* choiceOptions = args.InsertArray("options");
auto& choiceOptions = *teleportArgs.InsertArray("options");
{
AMFArrayValue* nsArgs = choiceOptions->PushArray();
auto& nsArgs = *choiceOptions.PushArray();
nsArgs->Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds");
nsArgs->Insert("caption", "%[UI_CHOICE_NS]");
nsArgs->Insert("identifier", "zoneID_1200");
nsArgs->Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]");
nsArgs.Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds");
nsArgs.Insert("caption", "%[UI_CHOICE_NS]");
nsArgs.Insert("identifier", "zoneID_1200");
nsArgs.Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]");
}
{
AMFArrayValue* ntArgs = choiceOptions->PushArray();
auto& ntArgs = *choiceOptions.PushArray();
ntArgs->Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds");
ntArgs->Insert("caption", "%[UI_CHOICE_NT]");
ntArgs->Insert("identifier", "zoneID_1900");
ntArgs->Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]");
ntArgs.Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds");
ntArgs.Insert("caption", "%[UI_CHOICE_NT]");
ntArgs.Insert("identifier", "zoneID_1900");
ntArgs.Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]");
}
options = choiceOptions;
}
void NsLegoClubDoor::OnUse(Entity* self, Entity* user) {
auto* player = user;
if (CheckChoice(self, player)) {
AMFArrayValue multiArgs;
multiArgs.Insert("callbackClient", std::to_string(self->GetObjectID()));
multiArgs.Insert("strIdentifier", "choiceDoor");
multiArgs.Insert("title", "%[UI_CHOICE_DESTINATION]");
multiArgs.Insert("options", static_cast<AMFBaseValue*>(options));
GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", multiArgs);
multiArgs.Remove("options", false); // We do not want the local amf to delete the options!
GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", teleportArgs);
} else if (self->GetVar<int32_t>(u"currentZone") != m_ChoiceZoneID) {
AMFArrayValue multiArgs;
multiArgs.Insert("state", "Lobby");

View File

@@ -19,6 +19,5 @@ private:
std::string m_SpawnPoint = "NS_LEGO_Club";
std::u16string m_TeleportAnim = u"lup-teleport";
std::u16string m_TeleportString = u"ROCKET_TOOLTIP_USE_THE_GATEWAY_TO_TRAVEL_TO_LUP_WORLD";
AMFArrayValue args = {};
AMFArrayValue* options = {};
AMFArrayValue teleportArgs{};
};

View File

@@ -503,7 +503,7 @@ void BaseSurvivalServer::ActivateSpawnerNetwork(SpawnerNetworkCollection& spawne
if (!possibleSpawners.empty()) {
auto* spawnerObject = possibleSpawners.at(0);
spawnerObject->Activate();
spawnerObject->Reset();
spawnerObject->SoftReset();
}
}
}

View File

@@ -334,6 +334,8 @@
#include "AgSpiderBossMessage.h"
#include "GfRaceInstancer.h"
#include "NsRaceServer.h"
#include "TrialFactionArmorServer.h"
#include "ImaginationBackPack.h"
#include <map>
#include <string>
@@ -700,6 +702,8 @@ namespace {
{"scripts\\ai\\RACING\\TRACK_GF\\GF_RACE_SERVER.lua", []() {return new GfRaceServer();}},
{"scripts\\ai\\RACING\\TRACK_FV\\FV_RACE_SERVER.lua", []() {return new FvRaceServer();}},
{"scripts\\ai\\RACING\\OBJECTS\\VEHICLE_DEATH_TRIGGER_WATER_SERVER.lua", []() {return new VehicleDeathTriggerWaterServer();}},
{"scripts\\equipmenttriggers\\L_TRIAL_FACTION_ARMOR_SERVER.lua", []() {return new TrialFactionArmorServer();}},
{"scripts\\equipmenttriggers\\ImaginationBackPack.lua", []() {return new ImaginationBackPack();}},
};

View File

@@ -186,6 +186,8 @@ namespace CppScripts {
*/
virtual void NotifyHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {};
virtual void NotifyPlayerResurrectionFinished(Entity& self, GameMessages::PlayerResurrectionFinished& msg) {};
/**
* Invoked when a player has responsed to a mission.
*

View File

@@ -1,5 +1,7 @@
set(DSCRIPTS_SOURCES_EQUIPMENTTRIGGERSSCRIPTS
"CoilBackpackBase.cpp")
"CoilBackpackBase.cpp"
"ImaginationBackPack.cpp"
"TrialFactionArmorServer.cpp")
add_library(dScriptsEquipmentTriggers OBJECT ${DSCRIPTS_SOURCES_EQUIPMENTTRIGGERSSCRIPTS})
target_include_directories(dScriptsEquipmentTriggers PUBLIC ".")

View File

@@ -0,0 +1,22 @@
#include "ImaginationBackPack.h"
#include "SkillComponent.h"
void ImaginationBackPack::OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) {
LOG("Subscribing to PlayerResurrectionFinished");
itemOwner->Subscribe(itemObjId, this, "PlayerResurrectionFinished");
}
void ImaginationBackPack::NotifyPlayerResurrectionFinished(Entity& self, GameMessages::PlayerResurrectionFinished& msg) {
LOG("PlayerResurrectionFinished");
auto* skillComponent = self.GetComponent<SkillComponent>();
if (!skillComponent) return;
LOG("Casting skill 1334");
skillComponent->CastSkill(1334);
}
void ImaginationBackPack::OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) {
LOG("Unsubscribing from PlayerResurrectionFinished");
itemOwner->Unsubscribe(itemObjId, "PlayerResurrectionFinished");
}

View File

@@ -0,0 +1,13 @@
#ifndef IMAGINATIONBACKPACK_H
#define IMAGINATIONBACKPACK_H
#include "CppScripts.h"
class ImaginationBackPack : public CppScripts::Script {
public:
void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) override;
void NotifyPlayerResurrectionFinished(Entity& self, GameMessages::PlayerResurrectionFinished& msg) override;
void OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) override;
};
#endif //!IMAGINATIONBACKPACK_H

View File

@@ -0,0 +1,13 @@
#ifndef __OBYXSHARDPACK__H__
#define __OBYXSHARDPACK__H__
#include "CoilBackpackBase.h"
class ObyxShardPack : public CoilBackpackBase {
public:
ObyxShardPack() : CoilBackpackBase(skillId) {};
private:
static const uint32_t skillId = 1751;
};
#endif //!__OBYXSHARDPACK__H__

View File

@@ -0,0 +1,13 @@
#ifndef __RUBYSHARDPACK__H__
#define __RUBYSHARDPACK__H__
#include "CoilBackpackBase.h"
class RubyShardPack : public CoilBackpackBase {
public:
RubyShardPack() : CoilBackpackBase(skillId) {};
private:
static const uint32_t skillId = 1750;
};
#endif //!__RUBYSHARDPACK__H__

View File

@@ -0,0 +1,27 @@
#include "TrialFactionArmorServer.h"
#include "Character.h"
#include "ePlayerFlag.h"
#include "DestroyableComponent.h"
void TrialFactionArmorServer::OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) {
auto* character = itemOwner->GetCharacter();
if (!character) return;
auto flag = character->GetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR);
if (!flag) {
character->SetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR, true);
// technically a TimerWithCancel but our current implementation doesnt support this.
itemOwner->AddCallbackTimer(1.0f, [itemOwner]() {
auto* destroyableComponent = itemOwner->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->SetHealth(destroyableComponent->GetMaxHealth());
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor());
destroyableComponent->SetImagination(destroyableComponent->GetMaxImagination());
Game::entityManager->SerializeEntity(itemOwner);
});
}
}

View File

@@ -0,0 +1,11 @@
#ifndef TRIALFACTIONARMORSERVER_
#define TRIALFACTIONARMORSERVER_
#include "CppScripts.h"
class TrialFactionArmorServer : public CppScripts::Script {
public:
void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) override;
};
#endif //!TRIALFACTIONARMORSERVER_

View File

@@ -9,9 +9,10 @@ void ActSharkPlayerDeathTrigger::OnFireEventServerSide(Entity* self, Entity* sen
auto missionComponent = sender->GetComponent<MissionComponent>();
if (!missionComponent) return;
missionComponent->Progress(eMissionTaskType::SCRIPT, 8419);
// This check is only needed because dlu doesnt have proper collision checks on rotated phantom physics
if (sender->GetIsDead() || !sender->GetPlayerReadyForUpdates()) return; //Don't kill already dead players or players not ready
missionComponent->Progress(eMissionTaskType::SCRIPT, 8419);
if (sender->GetCharacter()) {
sender->Smash(self->GetObjectID(), eKillType::VIOLENT, u"big-shark-death");

View File

@@ -36,14 +36,14 @@ void AgSpiderBossMessage::OnCollisionPhantom(Entity* self, Entity* target) {
auto box = GetBox(self);
// knockback the target
auto forward = target->GetRotation().GetForwardVector();
auto forward = self->GetRotation().GetForwardVector();
box.boxTarget = target->GetObjectID();
GameMessages::SendPlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack");
RenderComponent::PlayAnimation(target, "knockback-recovery");
forward.y += 15;
forward.x *= 100;
forward.z *= 100;
GameMessages::SendKnockback(target->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, forward);
GameMessages::SendKnockback(target->GetObjectID(), LWOOBJID_EMPTY, LWOOBJID_EMPTY, 0, forward);
if (box.isTouch || box.isDisplayed) return;
box.boxSelf = self->GetObjectID();

View File

@@ -613,7 +613,7 @@ void SGCannon::StopGame(Entity* self, bool cancel) {
// Destroy all spawners
for (auto* entity : Game::entityManager->GetEntitiesInGroup("SGEnemy")) {
entity->Kill();
entity->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
}
ResetVars(self);