mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-25 06:57:28 +00:00
Proper Rocket Holding
Sanity checks on Prop and LUP launchpads to not open if no valid rocket Add serialization for sending item configs so that rockets show for other players
This commit is contained in:
parent
24745c2e7a
commit
ec207838d4
@ -13,6 +13,7 @@
|
||||
#include "PossessorComponent.h"
|
||||
#include "VehiclePhysicsComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Item.h"
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
|
||||
m_Character = character;
|
||||
@ -448,6 +449,56 @@ void CharacterComponent::SetLastRocketConfig(std::u16string config) {
|
||||
m_LastRocketConfig = config;
|
||||
}
|
||||
|
||||
Item* CharacterComponent::GetRocket(Entity* player) {
|
||||
Item* rocket = nullptr;
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
|
||||
if (!inventoryComponent) return rocket;
|
||||
|
||||
// Select the rocket
|
||||
if (!rocket){
|
||||
rocket = inventoryComponent->FindItemById(GetLastRocketItemID());
|
||||
}
|
||||
|
||||
if (!rocket) {
|
||||
rocket = inventoryComponent->FindItemByLot(6416);
|
||||
}
|
||||
|
||||
if (!rocket) {
|
||||
Game::logger->Log("CharacterComponent", "Unable to find rocket to equip!\n");
|
||||
return rocket;
|
||||
}
|
||||
return rocket;
|
||||
}
|
||||
|
||||
Item* CharacterComponent::RocketEquip(Entity* player) {
|
||||
Item* rocket = GetRocket(player);
|
||||
if (!rocket) return rocket;
|
||||
|
||||
// build and define the rocket config
|
||||
for (LDFBaseData* data : rocket->GetConfig()) {
|
||||
if (data->GetKey() == u"assemblyPartLOTs") {
|
||||
std::string newRocketStr = data->GetValueAsString() + ";";
|
||||
GeneralUtils::ReplaceInString(newRocketStr, "+", ";");
|
||||
SetLastRocketConfig(GeneralUtils::ASCIIToUTF16(newRocketStr));
|
||||
}
|
||||
}
|
||||
|
||||
// Store the last used rocket item's ID
|
||||
SetLastRocketItemID(rocket->GetId());
|
||||
// carry the rocket
|
||||
rocket->Equip(true);
|
||||
return rocket;
|
||||
}
|
||||
|
||||
void CharacterComponent::RocketUnEquip(Entity* player) {
|
||||
Item* rocket = GetRocket(player);
|
||||
if (!rocket) return;
|
||||
// We don't want to carry it anymore
|
||||
rocket->UnEquip();
|
||||
}
|
||||
|
||||
void CharacterComponent::TrackMissionCompletion(bool isAchievement) {
|
||||
UpdatePlayerStatistic(MissionsCompleted);
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "RakNetTypes.h"
|
||||
#include "Character.h"
|
||||
#include "Component.h"
|
||||
#include "Item.h"
|
||||
#include <string>
|
||||
#include "CDMissionsTable.h"
|
||||
#include "tinyxml2.h"
|
||||
@ -74,6 +75,26 @@ public:
|
||||
*/
|
||||
void SetLastRocketConfig(std::u16string config);
|
||||
|
||||
/**
|
||||
* Find a player's rocket
|
||||
* @param player the entity that triggered the event
|
||||
* @return rocket
|
||||
*/
|
||||
Item* GetRocket(Entity* player);
|
||||
|
||||
/**
|
||||
* Equip a player's rocket
|
||||
* @param player the entity that triggered the event
|
||||
* @return rocket
|
||||
*/
|
||||
Item* RocketEquip(Entity* player);
|
||||
|
||||
/**
|
||||
* Find a player's rocket and unequip it
|
||||
* @param player the entity that triggered the event
|
||||
*/
|
||||
void RocketUnEquip(Entity* player);
|
||||
|
||||
/**
|
||||
* Gets the current level of the entity
|
||||
* @return the current level of the entity
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "InventoryComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@ -797,7 +797,26 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b
|
||||
|
||||
outBitStream->Write0();
|
||||
|
||||
outBitStream->Write0(); //TODO: This is supposed to be true and write the assemblyPartLOTs when they're present.
|
||||
bool flag = !item.config.empty();
|
||||
outBitStream->Write(flag);
|
||||
if (flag) {
|
||||
RakNet::BitStream ldfStream;
|
||||
ldfStream.Write<int32_t>(item.config.size()); // Key count
|
||||
for (LDFBaseData* data : item.config) {
|
||||
if (data->GetKey() == u"assemblyPartLOTs") {
|
||||
std::string newRocketStr = data->GetValueAsString() + ";";
|
||||
GeneralUtils::ReplaceInString(newRocketStr, "+", ";");
|
||||
LDFData<std::u16string>* ldf_data = new LDFData<std::u16string>(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(newRocketStr));
|
||||
ldf_data->WriteToPacket(&ldfStream);
|
||||
delete ldf_data;
|
||||
} else {
|
||||
data->WriteToPacket(&ldfStream);
|
||||
}
|
||||
}
|
||||
outBitStream->Write(ldfStream.GetNumberOfBytesUsed() + 1);
|
||||
outBitStream->Write<uint8_t>(0); // Don't compress
|
||||
outBitStream->Write(ldfStream);
|
||||
}
|
||||
|
||||
outBitStream->Write1();
|
||||
}
|
||||
@ -1043,7 +1062,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks)
|
||||
|
||||
GenerateProxies(item);
|
||||
|
||||
UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot() });
|
||||
UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot(), item->GetConfig() });
|
||||
|
||||
ApplyBuff(item);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "PropertyEntranceComponent.h"
|
||||
#include "PropertyEntranceComponent.h"
|
||||
|
||||
#include <CDPropertyEntranceComponentTable.h>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "PropertyManagementComponent.h"
|
||||
#include "PropertySelectQueryProperty.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "UserManager.h"
|
||||
#include "dLogger.h"
|
||||
|
||||
@ -22,8 +23,13 @@ PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entit
|
||||
this->m_PropertyName = entry.propertyName;
|
||||
}
|
||||
|
||||
void PropertyEntranceComponent::OnUse(Entity* entity)
|
||||
{
|
||||
void PropertyEntranceComponent::OnUse(Entity* entity) {
|
||||
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
|
||||
auto* rocket = entity->GetComponent<CharacterComponent>()->RocketEquip(entity);
|
||||
if (!rocket) return;
|
||||
|
||||
GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), entity->GetSystemAddress());
|
||||
|
||||
AMFArrayValue args;
|
||||
@ -75,7 +81,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index,
|
||||
|
||||
launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId);
|
||||
|
||||
launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId);
|
||||
launcher->Launch(entity, launcher->GetTargetZone(), cloneId);
|
||||
}
|
||||
|
||||
PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "RocketLaunchLupComponent.h"
|
||||
#include "CDClientDatabase.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "Item.h"
|
||||
|
||||
RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(parent) {
|
||||
m_Parent = parent;
|
||||
@ -21,20 +21,11 @@ RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(p
|
||||
RocketLaunchLupComponent::~RocketLaunchLupComponent() {}
|
||||
|
||||
void RocketLaunchLupComponent::OnUse(Entity* originator) {
|
||||
// the LUP world menu is just the property menu, the client knows how to handle it
|
||||
GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress());
|
||||
|
||||
// get the rocket to "equip" it so we are holding it
|
||||
// taken from the RocketLaunchControlComponent
|
||||
auto* inventoryComponent = originator->GetComponent<InventoryComponent>();
|
||||
auto* characterComponent = originator->GetComponent<CharacterComponent>();
|
||||
|
||||
if (!inventoryComponent || !characterComponent) return;
|
||||
|
||||
Item* rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID());
|
||||
auto* rocket = originator->GetComponent<CharacterComponent>()->RocketEquip(originator);
|
||||
if (!rocket) return;
|
||||
|
||||
rocket->Equip(true);
|
||||
// the LUP world menu is just the property menu, the client knows how to handle it
|
||||
GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress());
|
||||
}
|
||||
|
||||
void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) {
|
||||
@ -45,5 +36,5 @@ void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index)
|
||||
|
||||
if (!rocketLaunchpadControlComponent) return;
|
||||
|
||||
rocketLaunchpadControlComponent->Launch(originator, LWOOBJID_EMPTY, m_LUPWorlds[index], 0);
|
||||
rocketLaunchpadControlComponent->Launch(originator, m_LUPWorlds[index], 0);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "ChatPackets.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "PropertyEntranceComponent.h"
|
||||
#include "RocketLaunchLupComponent.h"
|
||||
#include "dServer.h"
|
||||
#include "dMessageIdentifiers.h"
|
||||
#include "PacketUtils.h"
|
||||
@ -40,19 +41,7 @@ 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) {
|
||||
void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOMAPID mapId, LWOCLONEID cloneId) {
|
||||
auto zone = mapId == LWOMAPID_INVALID ? m_TargetZone : mapId;
|
||||
|
||||
if (zone == 0)
|
||||
@ -60,53 +49,22 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID option
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!characterComponent || !character) return;
|
||||
|
||||
auto* rocket = characterComponent->GetRocket(originator);
|
||||
if (!rocket) {
|
||||
Game::logger->Log("RocketLaunchpadControlComponent", "Unable to find rocket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Select the rocket
|
||||
|
||||
Item* rocket = nullptr;
|
||||
|
||||
if (optionalRocketID != LWOOBJID_EMPTY)
|
||||
{
|
||||
rocket = inventoryComponent->FindItemById(optionalRocketID);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// we have the ability to launch, so now we prep the zone
|
||||
TellMasterToPrepZone(zone);
|
||||
|
||||
// Achievement unlocked: "All zones unlocked"
|
||||
|
||||
if (!m_AltLandingScene.empty() && m_AltPrecondition->Check(originator)) {
|
||||
character->SetTargetScene(m_AltLandingScene);
|
||||
}
|
||||
@ -114,27 +72,6 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID option
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the last used rocket item's ID
|
||||
characterComponent->SetLastRocketItemID(rocket->GetId());
|
||||
|
||||
characterComponent->UpdatePlayerStatistic(RocketsUsed);
|
||||
|
||||
character->SaveXMLToDatabase();
|
||||
@ -143,23 +80,31 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID option
|
||||
|
||||
GameMessages::SendFireEventClientSide(m_Parent->GetObjectID(), originator->GetSystemAddress(), u"RocketEquipped", rocket->GetId(), cloneId, -1, originator->GetObjectID());
|
||||
|
||||
rocket->Equip(true);
|
||||
|
||||
GameMessages::SendChangeObjectWorldState(rocket->GetId(), WORLDSTATE_ATTACHED, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(originator);
|
||||
}
|
||||
|
||||
void RocketLaunchpadControlComponent::OnUse(Entity* originator) {
|
||||
// If we are have the property or the LUP component, we don't want to immediately launch
|
||||
// instead we let their OnUse handlers do their things
|
||||
// which components of an Object have their OnUse called when using them
|
||||
// so we don't need to call it here
|
||||
auto* propertyEntrance = m_Parent->GetComponent<PropertyEntranceComponent>();
|
||||
|
||||
if (propertyEntrance != nullptr)
|
||||
{
|
||||
propertyEntrance->OnUse(originator);
|
||||
|
||||
if (propertyEntrance) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* rocketLaunchLUP = m_Parent->GetComponent<RocketLaunchLupComponent>();
|
||||
if (rocketLaunchLUP) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No rocket no launch
|
||||
auto* rocket = originator->GetComponent<CharacterComponent>()->RocketEquip(originator);
|
||||
if (!rocket) {
|
||||
return;
|
||||
}
|
||||
Launch(originator);
|
||||
}
|
||||
|
||||
|
@ -22,21 +22,13 @@ public:
|
||||
RocketLaunchpadControlComponent(Entity* parent, int rocketId);
|
||||
~RocketLaunchpadControlComponent() override;
|
||||
|
||||
/**
|
||||
* Launches the passed entity using the passed rocket and saves their data
|
||||
* @param entity the entity to launch
|
||||
* @param rocketID the ID of the rocket to use
|
||||
*/
|
||||
void RocketEquip(Entity* entity, LWOOBJID rocketID);
|
||||
|
||||
/**
|
||||
* Launches some entity to another world
|
||||
* @param originator the entity to launch
|
||||
* @param optionalRocketID the ID of the rocket to launch
|
||||
* @param mapId the world to go to
|
||||
* @param cloneId the clone ID (for properties)
|
||||
*/
|
||||
void Launch(Entity* originator, LWOOBJID optionalRocketID = LWOOBJID_EMPTY, LWOMAPID mapId = LWOMAPID_INVALID, LWOCLONEID cloneId = LWOCLONEID_INVALID);
|
||||
void Launch(Entity* originator, LWOMAPID mapId = LWOMAPID_INVALID, LWOCLONEID cloneId = LWOCLONEID_INVALID);
|
||||
|
||||
/**
|
||||
* Handles an OnUse event from some entity, preparing it for launch to some other world
|
||||
|
@ -5329,21 +5329,11 @@ void GameMessages::HandleEquipItem(RakNet::BitStream* inStream, Entity* entity)
|
||||
|
||||
Item* item = inv->FindItemById(objectID);
|
||||
if (!item) return;
|
||||
/*if (item->GetLot() == 6416) { // if it's a rocket
|
||||
std::vector<Entity*> rocketPads = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_ROCKET_LAUNCH);
|
||||
for (Entity* rocketPad : rocketPads) {
|
||||
RocketLaunchpadControlComponent* rocketComp = static_cast<RocketLaunchpadControlComponent*>(rocketPad->GetComponent(COMPONENT_TYPE_ROCKET_LAUNCH));
|
||||
if (rocketComp) {
|
||||
rocketComp->RocketEquip(entity, objectID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else*/ {
|
||||
|
||||
item->Equip();
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::HandleUnequipItem(RakNet::BitStream* inStream, Entity* entity) {
|
||||
bool immediate;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "dCommonVars.h"
|
||||
#include "LDFFormat.h"
|
||||
|
||||
/**
|
||||
* An item that's equipped, generally as a smaller return type than the regular Item class
|
||||
@ -26,4 +27,9 @@ struct EquippedItem
|
||||
* The slot this item is stored in
|
||||
*/
|
||||
uint32_t slot = 0;
|
||||
|
||||
/**
|
||||
* The configuration of the item with any extra data
|
||||
*/
|
||||
std::vector<LDFBaseData*> config = {};
|
||||
};
|
||||
|
@ -972,7 +972,10 @@ void HandlePacket(Packet* packet) {
|
||||
|
||||
EntityManager::Instance()->ConstructAllEntities(packet->systemAddress);
|
||||
|
||||
player->GetComponent<CharacterComponent>()->SetLastRocketConfig(u"");
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
if (characterComponent) {
|
||||
player->GetComponent<CharacterComponent>()->RocketUnEquip(player);
|
||||
}
|
||||
|
||||
c->SetRetroactiveFlags();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user