2021-12-05 17:54:36 +00:00
|
|
|
#include "RocketLaunchpadControlComponent.h"
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include "GameMessages.h"
|
|
|
|
#include "CharacterComponent.h"
|
|
|
|
#include "dZoneManager.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "Item.h"
|
|
|
|
#include "Game.h"
|
|
|
|
#include "dLogger.h"
|
|
|
|
#include "CDClientDatabase.h"
|
|
|
|
#include "ChatPackets.h"
|
|
|
|
#include "MissionComponent.h"
|
|
|
|
#include "PropertyEntranceComponent.h"
|
|
|
|
#include "dServer.h"
|
|
|
|
#include "dMessageIdentifiers.h"
|
|
|
|
#include "PacketUtils.h"
|
|
|
|
|
|
|
|
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
|
2022-01-13 03:48:27 +00:00
|
|
|
auto query = CDClientDatabase::CreatePreppedStmt(
|
2022-01-15 19:02:14 +00:00
|
|
|
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;");
|
2022-01-13 03:48:27 +00:00
|
|
|
query.bind(1, rocketId);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2022-01-13 03:48:27 +00:00
|
|
|
auto result = query.execQuery();
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!result.eof() && !result.fieldIsNull(0))
|
|
|
|
{
|
|
|
|
m_TargetZone = result.getIntField(0);
|
|
|
|
m_DefaultZone = result.getIntField(1);
|
|
|
|
m_TargetScene = result.getStringField(2);
|
|
|
|
m_AltPrecondition = new PreconditionExpression(result.getStringField(3));
|
|
|
|
m_AltLandingScene = result.getStringField(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
result.finalize();
|
|
|
|
}
|
|
|
|
|
|
|
|
RocketLaunchpadControlComponent::~RocketLaunchpadControlComponent() {
|
|
|
|
delete m_AltPrecondition;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RocketLaunchpadControlComponent::RocketEquip(Entity* entity, LWOOBJID rocketID) {
|
|
|
|
if (m_PlayersInRadius.find(entity->GetObjectID()) != m_PlayersInRadius.end()) {
|
|
|
|
Launch(entity, rocketID);
|
|
|
|
|
|
|
|
//Go ahead and save the player
|
|
|
|
//This causes a double-save, but it should prevent players from not being saved
|
|
|
|
//before the next world server starts loading their data.
|
|
|
|
if (entity->GetCharacter())
|
|
|
|
entity->GetCharacter()->SaveXMLToDatabase();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID optionalRocketID, LWOMAPID mapId, LWOCLONEID cloneId) {
|
|
|
|
auto zone = mapId == LWOMAPID_INVALID ? m_TargetZone : mapId;
|
|
|
|
|
|
|
|
if (zone == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
TellMasterToPrepZone(zone);
|
|
|
|
|
|
|
|
// This also gets triggered by a proximity monitor + item equip, I will set that up when havok is ready
|
|
|
|
auto* inventoryComponent = originator->GetComponent<InventoryComponent>();
|
|
|
|
auto* characterComponent = originator->GetComponent<CharacterComponent>();
|
|
|
|
|
|
|
|
auto* character = originator->GetCharacter();
|
|
|
|
|
|
|
|
if (inventoryComponent == nullptr || characterComponent == nullptr || character == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select the rocket
|
|
|
|
|
|
|
|
Item* rocket = nullptr;
|
|
|
|
|
|
|
|
if (optionalRocketID != LWOOBJID_EMPTY)
|
|
|
|
{
|
|
|
|
rocket = inventoryComponent->FindItemById(optionalRocketID);
|
|
|
|
}
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (rocket == nullptr)
|
|
|
|
{
|
|
|
|
rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rocket == nullptr)
|
|
|
|
{
|
|
|
|
rocket = inventoryComponent->FindItemByLot(6416);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rocket == nullptr)
|
|
|
|
{
|
|
|
|
Game::logger->Log("RocketLaunchpadControlComponent", "Unable to find rocket (%llu)!\n", optionalRocketID);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rocket->GetConfig().empty()) // Sanity check
|
|
|
|
{
|
|
|
|
rocket->SetCount(0, false, false);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Achievement unlocked: "All zones unlocked"
|
|
|
|
|
|
|
|
if (!m_AltLandingScene.empty() && m_AltPrecondition->Check(originator)) {
|
|
|
|
character->SetTargetScene(m_AltLandingScene);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
character->SetTargetScene(m_TargetScene);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (characterComponent) {
|
|
|
|
for (LDFBaseData* data : rocket->GetConfig()) {
|
|
|
|
if (data->GetKey() == u"assemblyPartLOTs") {
|
|
|
|
std::string newRocketStr;
|
|
|
|
for (char character : data->GetValueAsString()) {
|
|
|
|
if (character == '+') {
|
|
|
|
newRocketStr.push_back(';');
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
newRocketStr.push_back(character);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newRocketStr.push_back(';');
|
|
|
|
characterComponent->SetLastRocketConfig(GeneralUtils::ASCIIToUTF16(newRocketStr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
// Store the last used rocket item's ID
|
|
|
|
characterComponent->SetLastRocketItemID(rocket->GetId());
|
|
|
|
|
|
|
|
characterComponent->UpdatePlayerStatistic(RocketsUsed);
|
|
|
|
|
|
|
|
character->SaveXMLToDatabase();
|
|
|
|
|
|
|
|
SetSelectedMapId(originator->GetObjectID(), zone);
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
GameMessages::SendFireEventClientSide(m_Parent->GetObjectID(), originator->GetSystemAddress(), u"RocketEquipped", rocket->GetId(), cloneId, -1, originator->GetObjectID());
|
|
|
|
|
|
|
|
rocket->Equip(true);
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
GameMessages::SendChangeObjectWorldState(rocket->GetId(), WORLDSTATE_ATTACHED, UNASSIGNED_SYSTEM_ADDRESS);
|
2022-01-15 19:02:14 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(originator);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RocketLaunchpadControlComponent::OnUse(Entity* originator) {
|
|
|
|
auto* propertyEntrance = m_Parent->GetComponent<PropertyEntranceComponent>();
|
|
|
|
|
|
|
|
if (propertyEntrance != nullptr)
|
|
|
|
{
|
|
|
|
propertyEntrance->OnUse(originator);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Launch(originator);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RocketLaunchpadControlComponent::OnProximityUpdate(Entity* entering, std::string name, std::string status) {
|
|
|
|
// Proximity rockets are handled by item equipment
|
|
|
|
}
|
|
|
|
|
2022-01-15 19:02:14 +00:00
|
|
|
void RocketLaunchpadControlComponent::SetSelectedMapId(LWOOBJID player, LWOMAPID mapID)
|
2021-12-05 17:54:36 +00:00
|
|
|
{
|
|
|
|
m_SelectedMapIds[player] = mapID;
|
|
|
|
}
|
|
|
|
|
|
|
|
LWOMAPID RocketLaunchpadControlComponent::GetSelectedMapId(LWOOBJID player) const
|
|
|
|
{
|
|
|
|
const auto index = m_SelectedMapIds.find(player);
|
|
|
|
|
|
|
|
if (index == m_SelectedMapIds.end()) return 0;
|
|
|
|
|
|
|
|
return index->second;
|
|
|
|
}
|
|
|
|
|
2022-01-15 19:02:14 +00:00
|
|
|
void RocketLaunchpadControlComponent::SetSelectedCloneId(LWOOBJID player, LWOCLONEID cloneId)
|
2021-12-05 17:54:36 +00:00
|
|
|
{
|
|
|
|
m_SelectedCloneIds[player] = cloneId;
|
|
|
|
}
|
|
|
|
|
|
|
|
LWOCLONEID RocketLaunchpadControlComponent::GetSelectedCloneId(LWOOBJID player) const
|
|
|
|
{
|
|
|
|
const auto index = m_SelectedCloneIds.find(player);
|
|
|
|
|
|
|
|
if (index == m_SelectedCloneIds.end()) return 0;
|
|
|
|
|
|
|
|
return index->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RocketLaunchpadControlComponent::TellMasterToPrepZone(int zoneID) {
|
|
|
|
CBITSTREAM;
|
|
|
|
PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_PREP_ZONE);
|
|
|
|
bitStream.Write(zoneID);
|
|
|
|
Game::server->SendToMaster(&bitStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LWOMAPID RocketLaunchpadControlComponent::GetTargetZone() const
|
|
|
|
{
|
|
|
|
return m_TargetZone;
|
|
|
|
}
|
|
|
|
|
|
|
|
LWOMAPID RocketLaunchpadControlComponent::GetDefaultZone() const
|
|
|
|
{
|
|
|
|
return m_DefaultZone;
|
|
|
|
}
|