diff --git a/3rdParty/BuildSporeModAPI.bat b/3rdParty/BuildSporeModAPI.bat
index 9ef0513..4758b8c 100644
--- a/3rdParty/BuildSporeModAPI.bat
+++ b/3rdParty/BuildSporeModAPI.bat
@@ -4,7 +4,7 @@ set SPOREMODAPI_CUR_DIR=%~dp0
msbuild "%SPOREMODAPI_CUR_DIR%\Spore-ModAPI\Spore ModAPI" ^
/p:Configuration="Release DLL" ^
- /p:SDK_BUILD_VER=324 ^
+ /p:SDK_BUILD_VER=327 ^
/p:EXECUTABLE_TYPE=10 ^
/p:Platform=Win32 ^
/m
diff --git a/3rdParty/Spore-ModAPI/.gitrepo b/3rdParty/Spore-ModAPI/.gitrepo
index eac0a5e..fc6a6e7 100644
--- a/3rdParty/Spore-ModAPI/.gitrepo
+++ b/3rdParty/Spore-ModAPI/.gitrepo
@@ -6,7 +6,7 @@
[subrepo]
remote = git@github.com:emd4600/Spore-ModAPI.git
branch = master
- commit = 6108aaf8a4ab9d3d430ae9b020cce794162f1895
- parent = efe450b69168156a4fd745e2b27347647bb3c88d
+ commit = b4eee234431e61ca3dc2fdec54d91b36f753c426
+ parent = 591cf63f26650206adb0b71c570941b9f6c7b577
method = merge
cmdver = 0.4.6
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp
index 0ff82ad..e848598 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/DLL/AddressesSimulator.cpp
@@ -811,6 +811,7 @@ namespace Simulator
DefineAddress(GetPerihelion, SelectAddress(0xC70190, 0xC70FC0));
DefineAddress(FillPlanetDataForTechLevel, SelectAddress(0xB96820, 0xB97090));
DefineAddress(CalculateSpiceProduction, SelectAddress(0xC6F920, 0xC70760));
+ DefineAddress(CalculateDeltaSpiceProduction, SelectAddress(0xC71200, 0xC720A0));
}
namespace Addresses(cCivData) {
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/Planets.cpp b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/Planets.cpp
index 4666838..fe37615 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/Planets.cpp
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/SourceCode/Simulator/Planets.cpp
@@ -65,5 +65,11 @@ namespace Simulator
auto_STATIC_METHOD(cPlanetRecord, int, CalculateSpiceProduction,
Args(cPlanetRecord* planetRecord, int removeSpice), Args(planetRecord, removeSpice));
+
+ auto_STATIC_METHOD(cPlanetRecord, float, CalculateDeltaSpiceProduction,
+ Args(float baseValue, float maxOutput, float extraFactor, bool isHomeWorld,
+ bool useSuperpowerMultiplier, bool useStorageMultiplier, float finalFactor, int numCities, bool limitOutput),
+ Args(baseValue, maxOutput, extraFactor, isHomeWorld, useSuperpowerMultiplier, useStorageMultiplier, finalFactor, numCities, limitOutput));
+
}
#endif
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj
index 526d594..20c9586 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj
@@ -437,6 +437,8 @@
+
+
@@ -444,6 +446,7 @@
+
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj.filters b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj.filters
index 8f89e15..e8db9bb 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj.filters
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore ModAPI.vcxproj.filters
@@ -2181,6 +2181,15 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator.h
index 3148abf..db785ce 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator.h
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator.h
@@ -81,6 +81,8 @@
#include
#include
#include
+#include
+#include
#include
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMission.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMission.h
index 0b56101..d976cea 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMission.h
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMission.h
@@ -71,6 +71,13 @@ namespace Simulator
/// @param pEmpire
void SetTargetEmpire(cEmpire* pEmpire);
+ inline void AcceptMission() {
+ SetState(MissionState::Accepted);
+ }
+ inline void CompleteMission() {
+ SetState(MissionState::Completed);
+ }
+
/* 54h */ virtual int func54h();
/* 58h */ virtual int func58h();
/* 5Ch */ virtual int func5Ch();
@@ -283,7 +290,7 @@ namespace Simulator
/* 108h */ eastl::vector field_108;
/* 11Ch */ eastl::vector mUnlockToolIDList;
/* 130h */ int mFlags;
- /* 134h */ eastl::vector field_134;
+ /* 134h */ eastl::vector mAssociatedEventLogIDs;
/* 148h */ uint32_t mProgressEventID; // -1
/* 14Ch */ eastl::string16 mTitle;
/* 15Ch */ eastl::string16 field_15C;
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMissionManager.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMissionManager.h
index 43aeb0e..03fa433 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMissionManager.h
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cMissionManager.h
@@ -58,7 +58,7 @@ namespace Simulator
/// @param pOwnerEmpire Empire that is assigning the mission.
/// @param pParentMission Parent mission, this is generally null unless you want the new mission to be part of a larger, multi-step mission.
/// @returns The created cMission subclass object, or nullptr.
- cMission* CreateMission(uint32_t missionID, cPlanetRecord* pSourcePlanetRecord, cEmpire* pOwnerEmpire, cMission* pParentMission);
+ cMission* CreateMission(uint32_t missionID, cPlanetRecord* pSourcePlanetRecord, cEmpire* pOwnerEmpire, cMission* pParentMission = nullptr);
/// This function decides what mission needs to be done for the given empire.
/// To be precise, if you communicate with empire `pEmpire` on planet `pPlanetRecord`
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cPlanetRecord.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cPlanetRecord.h
index 142604b..c976022 100644
--- a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cPlanetRecord.h
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cPlanetRecord.h
@@ -199,7 +199,7 @@ namespace Simulator
/// @param techLevel
static void FillPlanetDataForTechLevel(cPlanetRecord* planetRecord, TechLevel techLevel);
- /// Calculates the current spice production of a planet, which is the sum of the
+ /// Calculates the current total spice of a planet, which is the sum of the
/// production of all its cities. If 'removeSpice' is not 0, that amount of spice will be
/// removed from the planet.
/// @param planetRecord
@@ -207,6 +207,22 @@ namespace Simulator
/// @returns The total spice production of the planet.
static int CalculateSpiceProduction(cPlanetRecord* planetRecord, int removeSpice = 0);
+ /// Method that calculates how much spice is being produced on a single planet, based on difficulty tunings
+ /// and number of cities. This method is called every X ticks to update the total spice held on each city.
+ /// @param baseValue Base value of the computation (e.g. cCityData::mSpiceProduction)
+ /// @param maxOutput Maximum output value, only applied if `limitOutput` is true
+ /// @param extraFactor Extra multilpier for the base value
+ /// @param isHomeWorld
+ /// @param useSuperpowerMultiplier
+ /// @param useStorageMultiplier
+ /// @param finalFactor Extra multiplied applied to the final output value
+ /// @param numCities
+ /// @param limitOutput If true, the output value will be capped at `maxOutput`
+ /// @returns
+ static float CalculateDeltaSpiceProduction(
+ float baseValue, float maxOutput, float extraFactor, bool isHomeWorld,
+ bool useSuperpowerMultiplier, bool useStorageMultiplier, float finalFactor, int numCities, bool limitOutput);
+
public:
/* 18h */ eastl::string16 mName;
/// The type of the planet, which determines whether it is a gas giant, asteroid belt, or regular rocky planet.
@@ -261,6 +277,7 @@ namespace Simulator
DeclareAddress(GetPerihelion); // 0xC70190 0xC70FC0
DeclareAddress(FillPlanetDataForTechLevel); // 0xB96820 0xB97090
DeclareAddress(CalculateSpiceProduction); // 0xC6F920 0xC70760
+ DeclareAddress(CalculateDeltaSpiceProduction); // 0xC71200 0xC720A0
}
inline ResourceKey cPlanetRecord::GenerateTerrainKey()
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cRaidEvent.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cRaidEvent.h
new file mode 100644
index 0000000..c2e8d12
--- /dev/null
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cRaidEvent.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include
+#include
+#include
+
+namespace Simulator
+{
+ /// The kind of mission for raid events. Example usage, to raid the current planet:
+ /// ```cpp
+ /// using namespace Simulator;
+ /// auto planet = GetActivePlanetRecord();
+ /// auto empireID = planet->GetStarRecord()->mEmpireID;
+ /// auto empire = StarManager.GetEmpire(empireID);
+ /// auto mission = MissionManager.CreateMission(id("RaidEvent"), planet, empire);
+ /// auto raidEvent = object_cast(mission);
+ /// raidEvent->mpTargetPlanet = GetActivePlanet();
+ /// raidEvent->mNumBombers = 10;
+ /// raidEvent->AcceptMission();
+ /// ```
+ class cRaidEvent
+ : public cMission
+ {
+ public:
+ static const uint32_t TYPE = 0x3960C0E;
+ static const uint32_t NOUN_ID = 0x3960C0A;
+
+ public:
+ /* 1F0h */ cGameDataUFOPtr mGalaxyBomber;
+ /* 1F4h */ int mOriginStarRecordID;
+ /* 1F8h */ int mNumBombers;
+ /* 1FCh */ int mNumFighters;
+ /* 200h */ ResourceKey mPendingUFOKey;
+ /* 20Ch */ float mDamageRemainder;
+ /* 210h */ float mDamageRemainderUFO;
+ /* 214h */ bool mShouldDestroyColonyObject;
+ /* 215h */ bool mWaitingForRaid; // true
+ /* 218h */ int field_218;
+ /* 21Ch */ bool mUFOsLeaveOnArrival;
+ /* 21Dh */ bool mInitialized;
+ /* 21Eh */ bool mShowDefaultEventLog; // true
+ /* 220h */ uint32_t mTimeOfArrivalMS;
+ /* 224h */ Math::Vector3 mUFOSpawnLocation;
+ /* 230h */ uint32_t mAttackerEmpire; // -1
+ /* 234h */ bool mIsPlayerSummoned;
+ /* 238h */ eastl::vector mBackgroundShipsList;
+ };
+ ASSERT_SIZE(cRaidEvent, 0x250);
+}
\ No newline at end of file
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cRaidPlunderEvent.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cRaidPlunderEvent.h
new file mode 100644
index 0000000..a19b738
--- /dev/null
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cRaidPlunderEvent.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include
+#include
+
+namespace Simulator
+{
+ /// The kind of mission for pirate raid events. Example usage, to raid the current planet:
+ /// ```cpp
+ /// using namespace Simulator;
+ /// auto planet = GetActivePlanetRecord();
+ /// auto empireID = planet->GetStarRecord()->mEmpireID;
+ /// auto empire = StarManager.GetEmpire(empireID);
+ /// auto mission = MissionManager.CreateMission(id("RaidPlunderEvent"), planet, empire);
+ /// auto raidEvent = object_cast(mission);
+ /// raidEvent->mNumPirates = 20;
+ /// raidEvent->mNumBombers = 10;
+ /// raidEvent->mpTargetPlanet = GetActivePlanet();
+ /// raidEvent->AcceptMission();
+ /// auto eventID = UIEventLog.ShowEvent(0x31DF9AC0, GroupIDs::SpacePopups);
+ /// raidEvent->mAssociatedEventLogIDs.push_back(eventID);
+ /// ```
+ class cRaidPlunderEvent
+ : public cMission
+ {
+ public:
+ static const uint32_t TYPE = 0x397BFF2;
+ static const uint32_t NOUN_ID = 0x397BFF3;
+
+ public:
+ /* 1F0h */ ResourceKey mPendingUFOKey;
+ /* 1FCh */ bool mCanStart;
+ /* 200h */ int mNumPirates;
+ /* 204h */ int mNumBombers;
+ /* 208h */ int mNumFighters;
+ /* 20Ch */ float mDamageRemainderUFO;
+ /* 210h */ float mStolenSpiceFraction;
+ /* 214h */ eastl::vector mBackgroundShipsList;
+ };
+ ASSERT_SIZE(cRaidPlunderEvent, 0x228);
+}
\ No newline at end of file
diff --git a/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cShipBackgroundData.h b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cShipBackgroundData.h
new file mode 100644
index 0000000..27aa0b6
--- /dev/null
+++ b/3rdParty/Spore-ModAPI/Spore ModAPI/Spore/Simulator/cShipBackgroundData.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include
+#include
+#include
+
+namespace Simulator
+{
+ class cShipBackgroundData
+ : public ISimulatorSerializable
+ {
+ public:
+ /* 04h */ UfoType mUfoType;
+ /* 08h */ Math::Vector3 mPosition;
+ /* 14h */ float mHealth;
+ /* 18h */ float mMaxHealth;
+ /* 1Ch */ int mBomberIndex;
+ };
+ ASSERT_SIZE(cShipBackgroundData, 0x20);
+}
\ No newline at end of file