From 552571ac9798b02d3938a5649c651a427842fd68 Mon Sep 17 00:00:00 2001 From: Eric Mor Date: Wed, 8 Nov 2023 23:24:48 +0100 Subject: [PATCH] Added `cSpaceTrading` class, with methods such as `ObtainTradingObject()`, `AssignPlanetSpice()`, and `GenerateNPCStore()`. Added `cSpaceInventoryItem::CreateTradingObject()`. Added messages `SimulatorMessages::kMsgkMsgSpaceRareFound` and `kMsgSpaceRareDiscovered`. Added `cDistributeEffect`. Added `cSpaceInventoryItem::CreateTradingObject()`. Added messages `SimulatorMessages::kMsgkMsgSpaceRareFound` and `kMsgSpaceRareDiscovered`. Added `cDistributeEffect`. --- .../SourceCode/DLL/AddressesSimulator.cpp | 27 +++- .../Simulator/SimulatorSpaceGame.cpp | 29 +++++ .../SourceCode/Simulator/SpaceInventory.cpp | 9 +- Spore ModAPI/Spore ModAPI.vcxproj | 1 + Spore ModAPI/Spore ModAPI.vcxproj.filters | 3 + .../Spore/Simulator/SimulatorMessages.h | 16 +++ .../Spore/Simulator/SubSystem/SpaceTrading.h | 117 ++++++++++++++++++ Spore ModAPI/Spore/Simulator/cPlanetRecord.h | 1 + .../Spore/Simulator/cSpaceInventoryItem.h | 14 ++- Spore ModAPI/Spore/Swarm/cDistributeEffect.h | 62 ++++++++++ 10 files changed, 271 insertions(+), 8 deletions(-) create mode 100644 Spore ModAPI/Spore/Simulator/SubSystem/SpaceTrading.h create mode 100644 Spore ModAPI/Spore/Swarm/cDistributeEffect.h diff --git a/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp b/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp index 900b55ca..c0c97953 100644 --- a/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp +++ b/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -662,6 +663,8 @@ namespace Simulator namespace Addresses(cSpaceInventoryItem) { DefineAddress(CreateMultiDeliveryObject, SelectAddress(0xC86C00, 0xC86C00)); + DefineAddress(SetPropList, SelectAddress(0xC86B20, 0xC87980)); + DefineAddress(CreateTradingObject, SelectAddress(0x103B470, 0x103A490)); } namespace Addresses(cTribeArchetype) @@ -713,12 +716,12 @@ namespace Simulator namespace Addresses(cScenarioTerraformMode) { - DefineAddress(StartHistoryEntry, SelectAddress(0xF33AD0, 0xF33A90)); // 0xF33AD0, 0xF33A90 - DefineAddress(CommitHistoryEntry, SelectAddress(0xF45D50, 0xF34400)); // 0xF45D50, 0xF34400 - DefineAddress(SetWaterColor, SelectAddress(0xF32140, 0xF31FA0)); // 0xF32140, 0xF31FA0 - DefineAddress(SetAtmosphereColor, SelectAddress(0xF32190, 0xF31FF0)); // 0xF32190, 0xF31FF0 - DefineAddress(SetBeachColor, SelectAddress(0xF321E0, 0xF32040)); // 0xF321E0, 0xF32040 - DefineAddress(SetCliffColor, SelectAddress(0xF32230, 0xF32090)); // 0xF32230, 0xF32090 + DefineAddress(StartHistoryEntry, SelectAddress(0xF33AD0, 0xF33A90)); + DefineAddress(CommitHistoryEntry, SelectAddress(0xF45D50, 0xF34400)); + DefineAddress(SetWaterColor, SelectAddress(0xF32140, 0xF31FA0)); + DefineAddress(SetAtmosphereColor, SelectAddress(0xF32190, 0xF31FF0)); + DefineAddress(SetBeachColor, SelectAddress(0xF321E0, 0xF32040)); + DefineAddress(SetCliffColor, SelectAddress(0xF32230, 0xF32090)); } namespace Addresses(cHerd) @@ -932,6 +935,18 @@ namespace Simulator DefineAddress(sCellSerializableData, SelectAddress(0x16B8060, 0x16B3DE0)); } #endif + + namespace Addresses(cSpaceTrading) + { + DefineAddress(Get, SelectAddress(0xB3D330, 0xB3D4D0)); + DefineAddress(ClearNPCStores, SelectAddress(0x103E9D0, 0x103DCD0)); + DefineAddress(IsRare, SelectAddress(0x103B3B0, 0x103A3D0)); + DefineAddress(ObtainTradingObject, SelectAddress(0x1040890, 0x103FC20)); + DefineAddress(AssignPlanetSpice, SelectAddress(0x103D750, 0x103CA50)); + DefineAddress(GetRareHasBeenFound, SelectAddress(0x103BC30, 0x103AC50)); + DefineAddress(SetRareAsFound, SelectAddress(0x1040820, 0x103FBB0)); + DefineAddress(GenerateNPCStore, SelectAddress(0x103F560, 0x103E8F0)); + } } #ifdef SDK_TO_GHIDRA diff --git a/Spore ModAPI/SourceCode/Simulator/SimulatorSpaceGame.cpp b/Spore ModAPI/SourceCode/Simulator/SimulatorSpaceGame.cpp index ab805eb8..5068107a 100644 --- a/Spore ModAPI/SourceCode/Simulator/SimulatorSpaceGame.cpp +++ b/Spore ModAPI/SourceCode/Simulator/SimulatorSpaceGame.cpp @@ -18,6 +18,7 @@ * along with this program. If not, see . ****************************************************************************/ #include +#include namespace Simulator { @@ -29,5 +30,33 @@ namespace Simulator auto_STATIC_METHOD_(cSimulatorSpaceGame, cSimulatorSpaceGame*, Get); auto_METHOD_VOID(cSimPlanetHighLOD, DestroyCity, Args(cCity* pCity, uint32_t aggressorEmpireID), Args(pCity, aggressorEmpireID)); + + /// -- cSpaceTrading -- /// + + auto_STATIC_METHOD_(cSpaceTrading, cSpaceTrading*, Get); + + auto_METHOD_VOID_(cSpaceTrading, ClearNPCStores); + + auto_STATIC_METHOD(cSpaceTrading, bool, IsRare, Args(const ResourceKey& key), Args(key)); + + auto_METHOD_VOID(cSpaceTrading, ObtainTradingObject, + Args(const ResourceKey& key, int amount), + Args(key, amount)); + + auto_METHOD_VOID(cSpaceTrading, AssignPlanetSpice, + Args(cPlanetRecord* planetRecord, bool forceReassign), + Args(planetRecord, forceReassign)); + + auto_METHOD(cSpaceTrading, int, GetRareHasBeenFound, + Args(const ResourceKey& key), + Args(key)); + + auto_METHOD_VOID(cSpaceTrading, SetRareAsFound, + Args(const ResourceKey& key, bool found), + Args(key, found)); + + auto_METHOD_VOID(cSpaceTrading, GenerateNPCStore, + Args(cPlanetRecord* planetRecord, LocalizedString& dstSpiceText), + Args(planetRecord, dstSpiceText)); } #endif diff --git a/Spore ModAPI/SourceCode/Simulator/SpaceInventory.cpp b/Spore ModAPI/SourceCode/Simulator/SpaceInventory.cpp index ecd6b794..acb8e4d7 100644 --- a/Spore ModAPI/SourceCode/Simulator/SpaceInventory.cpp +++ b/Spore ModAPI/SourceCode/Simulator/SpaceInventory.cpp @@ -18,9 +18,16 @@ namespace Simulator Args(const ResourceKey& speciesId), Args(speciesId)); + + auto_METHOD_VOID(cSpaceInventoryItem, SetPropList, Args(App::PropertyList* propList), Args(propList)); + auto_STATIC_METHOD_VOID(cSpaceInventoryItem, CreateMultiDeliveryObject, - Args(cSpaceInventoryItem& dst, const ResourceKey& itemID, uint32_t instanceID), + Args(cSpaceInventoryItemPtr& dst, const ResourceKey& itemID, uint32_t instanceID), Args(dst, itemID, instanceID)); + + auto_STATIC_METHOD_VOID(cSpaceInventoryItem, CreateTradingObject, + Args(cSpaceInventoryItemPtr& dst, const ResourceKey& itemID, int itemCount, float itemCost), + Args(dst, itemID, itemCount, itemCost)); } #endif diff --git a/Spore ModAPI/Spore ModAPI.vcxproj b/Spore ModAPI/Spore ModAPI.vcxproj index 71cc47ca..cc0c3f24 100644 --- a/Spore ModAPI/Spore ModAPI.vcxproj +++ b/Spore ModAPI/Spore ModAPI.vcxproj @@ -449,6 +449,7 @@ + diff --git a/Spore ModAPI/Spore ModAPI.vcxproj.filters b/Spore ModAPI/Spore ModAPI.vcxproj.filters index 15f66286..082b8ef1 100644 --- a/Spore ModAPI/Spore ModAPI.vcxproj.filters +++ b/Spore ModAPI/Spore ModAPI.vcxproj.filters @@ -2127,6 +2127,9 @@ Header Files + + Header Files + diff --git a/Spore ModAPI/Spore/Simulator/SimulatorMessages.h b/Spore ModAPI/Spore/Simulator/SimulatorMessages.h index f25b156c..098d5a8f 100644 --- a/Spore ModAPI/Spore/Simulator/SimulatorMessages.h +++ b/Spore ModAPI/Spore/Simulator/SimulatorMessages.h @@ -89,6 +89,11 @@ namespace Simulator kMsgGalaxyGenerateBinaryGM = 0x3DFF9C1, /// Message emitted by the galaxy generation effect to create binary M-M (red-red) star systems (StarType::BinaryMM). kMsgGalaxyGenerateBinaryMM = 0x3DFF9C6, + + /// Simulator::SpaceRareFoundMessage ; sent when a rare item is found (even if it had already been found before) in Space Stage. + kMsgSpaceRareFound = 0xF46092D4, + /// Sent when a rare item is discovered (i.e. it had not been found before) in Space Stage. The parameter is a uint32_t* to the rare instance ID. + kMsgSpaceRareDiscovered = 0x6779F04, }; class IMessageParameters @@ -228,4 +233,15 @@ namespace Simulator return params[0]._float; } }; + + /// Sent when a rare item is found (even if it had already been found before) in Space Stage. + class SpaceRareFoundMessage : App::StandardMessage + { + public: + static const uint32_t ID = kMsgSpaceRareFound; + + inline uint32_t GetRareID() { + return params[0].uint32; + } + }; } \ No newline at end of file diff --git a/Spore ModAPI/Spore/Simulator/SubSystem/SpaceTrading.h b/Spore ModAPI/Spore/Simulator/SubSystem/SpaceTrading.h new file mode 100644 index 00000000..7caf711f --- /dev/null +++ b/Spore ModAPI/Spore/Simulator/SubSystem/SpaceTrading.h @@ -0,0 +1,117 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SpaceTrading (*Simulator::cSpaceTrading::Get()) +#define cNPCStorePtr eastl::intrusive_ptr + +namespace Simulator +{ + class cNPCStore + : public RefCountTemplate + , public ISimulatorSerializable + { + public: + static const uint32_t TYPE = 0x5B82EF9; + static const uint32_t NOUN_ID = 0x5B82EFA; + + public: + /* 0Ch */ uint32_t planetkey; // -1 + /* 10h */ cGonzagoTimer lifetime; + /* 30h */ int spiceBought; + /* 34h */ eastl::vector mNPCInventory; + /* 48h */ eastl::vector mNPCInventoryAges; + /// If true, this store is not valid anymore and must be refreshed + /* 5Ch */ bool mbDirty; + /* 60h */ eastl::fixed_vector mSpiceID; + /* 9Ch */ eastl::fixed_vector mSpiceCost; + }; + ASSERT_SIZE(cNPCStore, 0xC0); + + class cSpaceTrading + /* 00h */ : public cStrategy + /* 1Ch */ , public App::IMessageListener + { + public: + static cSpaceTrading* Get(); + + void ClearNPCStores(); + + /// Returns true if the space trading item configuration in `spacetrading~` folder + /// has its `spaceTradingType` set to `rare`. + /// @param key Key of the trading item, only the instance ID is used + /// @returns True if the item is rare + static bool IsRare(const ResourceKey& key); + + /// Gives the specified trading object to the player, adding it to its inventory. + /// The key must be a `.prop` file in GroupIDs::SpaceTrading group. + /// If the item is a rare, it will show an event log, give a badge if necessary, and emit the SimulatorMessages::kMsgSpaceRareFound message. + /// @param key The key of the item + /// @param amount Quantity to give + void ObtainTradingObject(const ResourceKey& key, int amount = 1); + + /// Assigns the spice of a planet; if the planet already has a spice, it will only recalculate it if `forceReassign` is true. + /// The function checks all the spices in cSpaceTrading::mSpices, and picks one based on the probabilities and the planet + /// type and difficulty (blue orbit on easy, red orbit on hard, etc.). It then sets the cPlanetRecord::mSpiceGen key. + /// @param planetRecord + /// @param forceReassign [Optional] If this is true, it will assign a new spice even if the planet already had one. + void AssignPlanetSpice(cPlanetRecord* planetRecord, bool forceReassign = false); + + /// Returns whether the given rare has been discovered yet or not. + /// @param key + int GetRareHasBeenFound(const ResourceKey& key); + + /// Marks whether the given rare has been found or not. If found is true, it will emit a message. + /// @param key + /// @param found + void SetRareAsFound(const ResourceKey& key, bool found); + + /// Generates what the NPC sells and buys from the player; called when the player enters the store communication screen. + /// @param planetRecord Current planet where the player is trading + /// @param[out] dstSpiceText + void GenerateNPCStore(cPlanetRecord* planetRecord, LocalizedString& dstSpiceText); + + public: + struct RareGroup { + /* 00h */ uint32_t mGroupID; + /* 04h */ int field_4; + /* 08h */ int field_8; + /* 0Ch */ int field_C; + /* 10h */ eastl::vector mRares; + }; + ASSERT_SIZE(RareGroup, 0x24); + + /// List of possible spices for planets + /* 20h */ eastl::vector mSpices; + /* 34h */ eastl::vector field_34; + /* 48h */ eastl::fixed_vector mNPCStore; + /* 74h */ eastl::vector field_74; + /* 88h */ eastl::vector field_88; + /* 9Ch */ int mLastNPCStoreIndex; // not initalized + /// When a rare is found, it's key is set to 1 in this map + /* A0h */ eastl::map mRareMap; + /* BCh */ eastl::vector mRareGroups; + /* D0h */ int field_D0[5]; //TODO + /* E4h */ eastl::vector mNewlyAvailableCommodities; + }; + ASSERT_SIZE(cSpaceTrading, 0xF8); + + namespace Addresses(cSpaceTrading) + { + DeclareAddress(Get); // 0xB3D330 0xB3D4D0 + DeclareAddress(ClearNPCStores); // 0x103E9D0 0x103DCD0 + DeclareAddress(IsRare); // 0x103B3B0 0x103A3D0 + DeclareAddress(ObtainTradingObject); // 0x1040890 0x103FC20 + DeclareAddress(AssignPlanetSpice); // 0x103D750 0x103CA50 + DeclareAddress(GetRareHasBeenFound); // 0x103BC30 0x103AC50 + DeclareAddress(SetRareAsFound); // 0x1040820 0x103FBB0 + DeclareAddress(GenerateNPCStore); // 0x103F560 0x103E8F0 + } +} \ No newline at end of file diff --git a/Spore ModAPI/Spore/Simulator/cPlanetRecord.h b/Spore ModAPI/Spore/Simulator/cPlanetRecord.h index 2c87676e..5c740b30 100644 --- a/Spore ModAPI/Spore/Simulator/cPlanetRecord.h +++ b/Spore ModAPI/Spore/Simulator/cPlanetRecord.h @@ -223,6 +223,7 @@ namespace Simulator /* 184h */ PlanetID mKey; /* 188h */ ResourceKey field_188; /* 194h */ TechLevel mTechLevel; + /// ID of the spice file of this planet in GroupIDs::SpaceTrading; all zeros if it hasn't been assigned yet /* 198h */ ResourceKey mSpiceGen; /* 1A4h */ ResourceKey mGeneratedTerrainKey; }; diff --git a/Spore ModAPI/Spore/Simulator/cSpaceInventoryItem.h b/Spore ModAPI/Spore/Simulator/cSpaceInventoryItem.h index 4614f759..71cd486f 100644 --- a/Spore ModAPI/Spore/Simulator/cSpaceInventoryItem.h +++ b/Spore ModAPI/Spore/Simulator/cSpaceInventoryItem.h @@ -76,13 +76,23 @@ namespace Simulator /* 48h */ virtual bool func48h(); /* 4Ch */ virtual void ParseProp(); + /// Assigns and reads the property list for this item. Most are stored in `spacetrading~`. + /// @param propList + void SetPropList(App::PropertyList* propList); /// Creates an inventory item for multi-delivery mission objects. It will read a .prop file with /// name `instanceID` in the folder `multiDelivery_mision_objects~` (`0x37D494E`). /// @param dst /// @param itemID /// @param instanceIDcddc - static void CreateMultiDeliveryObject(cSpaceInventoryItem& dst, const ResourceKey& itemID, uint32_t instanceID); + static void CreateMultiDeliveryObject(cSpaceInventoryItemPtr& dst, const ResourceKey& itemID, uint32_t instanceID); + + /// Creates a trading object, which is an inventory item from GroupIDs::SpaceTrading. + /// @param[out] dst Pointer where the new object will be written. + /// @param itemID Key to the item configuration in GroupIDs::SpaceTrading + /// @param itemCount Number of items to create + /// @param itemCost Cost of the object + static void CreateTradingObject(cSpaceInventoryItemPtr& dst, const ResourceKey& itemID, int itemCount, float itemCost); public: /* 10h */ size_t mItemCount; // 1 @@ -113,5 +123,7 @@ namespace Simulator namespace Addresses(cSpaceInventoryItem) { DeclareAddress(CreateMultiDeliveryObject); + DeclareAddress(SetPropList); // 0xC86B20 0xC87980 + DeclareAddress(CreateTradingObject); // 0x103B470 0x103A490 } } \ No newline at end of file diff --git a/Spore ModAPI/Spore/Swarm/cDistributeEffect.h b/Spore ModAPI/Spore/Swarm/cDistributeEffect.h new file mode 100644 index 00000000..9488da78 --- /dev/null +++ b/Spore ModAPI/Spore/Swarm/cDistributeEffect.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Swarm +{ + class cDistributeEffect + /* 00h */ : public cComponentBase + /* 0Ch */ , public ITextureParticleStreamer + /* 10h */ , public IModelParticleStreamer + { + public: + /* 14h */ cDistributeDescription* mpDescription; + /* 18h */ int field_18; + /* 1Ch */ IEffectsWorld* mpEffectsWorld; + /* 20h */ cGlobalParams* mpGlobalParams; + /* 24h */ cEffectParams* mpEffectParams; + /* 28h */ int field_28; + /* 2Ch */ Transform field_2C; + /* 64h */ Transform field_64; + /* 9Ch */ int field_9C; + /* A0h */ float mAltitudeRange[2]; // -10000.0, 10000.0 + /* A8h */ eastl::vector field_A8; + /* BCh */ eastl::vector field_BC; + /* D0h */ int field_D0; + /* D4h */ int field_D4; + /* D8h */ eastl::vector field_D8; + /* ECh */ int field_EC; // -1 + /* F0h */ int field_F0; // -1 + /* F4h */ int field_F4; // -1 + /* F8h */ bool field_F8; + /* FCh */ int field_FC; // not initialized + /* 100h */ Math::BoundingBox field_100; + /* 118h */ int field_118; + /* 11Ch */ eastl::vector mSurfaces; + /* 130h */ eastl::vector field_130; + /* 144h */ eastl::vector field_144; + /* 158h */ int field_158; + /* 15Ch */ IEffectMapPtr mpEmitMap; + /* 160h */ IEffectMapPtr mpColorMap; + /* 164h */ IEffectMapPtr mpPinMap; + /* 168h */ int mEmitMapModificationCount; + /* 16Ch */ int field_16C; // not initialized + /* 170h */ float field_170; // 1.0 + /* 174h */ float field_174; // 1.0 + /* 178h */ float field_178; // 1.0 + /* 17Ch */ float field_17C; // 1.0 + /* 180h */ float field_180; // 1.0 + /* 184h */ float field_184; // 1.0 + /* 188h */ float field_188; // 1.0 + /* 18Ch */ float field_18C; // 1.0 + /* 190h */ int field_190; + /* 194h */ int field_194; // 1 + /* 19Ch */ eastl::vector field_19C; + }; + ASSERT_SIZE(cDistributeEffect, 0x1B0); +} \ No newline at end of file