Skip to content

Commit 6487991

Browse files
committed
Merge branch 'development' into tracy-fixes
2 parents 49f1ca3 + 7bbb2ad commit 6487991

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+771
-285
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
*.APS
99
*.user
1010

11+
/.idea
12+
1113
compile_commands.json
1214
/.ccls-cache
1315

1416
/build*
1517

1618
/enc_temp_folder
1719

20+
/.idea
1821
/_Bin
1922
/NATPunchServer/Server/NATCompleteServer/Debug
2023
/NATPunchServer/Server/NATCompleteServer/Release

Activities/GAScripted.cpp

Lines changed: 51 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ int GAScripted::ReadProperty(const std::string_view &propName, Reader &reader) {
138138
// later recreation with Create(Reader &reader);
139139

140140
int GAScripted::Save(Writer &writer) const {
141-
// Call the script OnSave() function, if it exists
142-
g_LuaMan.GetMasterScriptState().RunScriptString("if " + m_LuaClassName + " and " + m_LuaClassName + ".OnSave then " + m_LuaClassName + ":OnSave(); end");
141+
// Hmm. We should probably be calling this prior to the writer Save, instead of const-casting.
142+
const_cast<GAScripted*>(this)->RunLuaFunction("OnSave");
143143

144144
GameActivity::Save(writer);
145145

@@ -184,63 +184,50 @@ void GAScripted::Destroy(bool notInherited) {
184184
// spawned will use the new scripts.
185185

186186
int GAScripted::ReloadScripts() {
187-
int error = 0;
187+
if (m_ScriptPath.empty()) {
188+
return 0;
189+
}
188190

189-
// Read in the Lua script function definitions for this preset
190-
if (!m_ScriptPath.empty()) {
191-
// Get the required Area:s from the new script
192-
CollectRequiredAreas();
193-
194-
// If it hasn't been yet, run the file that specifies the Lua functions for this' operating logic (including the scene test function)
195-
if (!g_LuaMan.GetMasterScriptState().GlobalIsDefined(m_LuaClassName)) {
196-
// Temporarily store this Activity so the Lua state can access it
197-
g_LuaMan.GetMasterScriptState().SetTempEntity(this);
198-
// Define the var that will hold the script file definitions
199-
if ((error = g_LuaMan.GetMasterScriptState().RunScriptString(m_LuaClassName + " = ToGameActivity(LuaMan.TempEntity);")) < 0) {
200-
return error;
201-
}
202-
}
191+
int error = 0;
192+
CollectRequiredAreas();
203193

204-
// Load and run the file, defining all the scripted functions of this Activity
205-
if ((error = g_LuaMan.GetMasterScriptState().RunScriptFile(m_ScriptPath)) < 0) {
194+
// If it hasn't been yet, run the file that specifies the Lua functions for this' operating logic (including the scene test function)
195+
if (!g_LuaMan.GetMasterScriptState().GlobalIsDefined(m_LuaClassName)) {
196+
// Temporarily store this Activity so the Lua state can access it
197+
g_LuaMan.GetMasterScriptState().SetTempEntity(this);
198+
199+
// Define the var that will hold the script file definitions
200+
if ((error = g_LuaMan.GetMasterScriptState().RunScriptString(m_LuaClassName + " = ToGameActivity(LuaMan.TempEntity);")) < 0) {
206201
return error;
207202
}
208203
}
209204

210-
return error;
205+
std::string luaClearSupportedFunctionsString;
206+
for (const std::string& functionName : GetSupportedScriptFunctionNames()) {
207+
luaClearSupportedFunctionsString += m_LuaClassName + "." + functionName + " = nil; ";
208+
}
209+
210+
if ((error = g_LuaMan.GetMasterScriptState().RunScriptString(luaClearSupportedFunctionsString)) < 0) {
211+
return error;
212+
}
213+
214+
std::unordered_map<std::string, LuabindObjectWrapper*> scriptFileFunctions;
215+
if ((error = g_LuaMan.GetMasterScriptState().RunScriptFileAndRetrieveFunctions(m_ScriptPath, m_LuaClassName, GetSupportedScriptFunctionNames(), scriptFileFunctions)) < 0) {
216+
return error;
217+
}
218+
219+
m_ScriptFunctions.clear();
220+
for (const auto& [functionName, functionObject] : scriptFileFunctions) {
221+
m_ScriptFunctions[functionName] = std::unique_ptr<LuabindObjectWrapper>(functionObject);
222+
}
223+
224+
return 0;
211225
}
212226

213227
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
214228

215229
bool GAScripted::HasSaveFunction() const {
216-
//TODO this method is complicated and manually parsing lua like this sucks. It should be replaceable with a simple check if the function exists in Lua, but it wasn't working when I tried so I just copied this from SceneIsCompatible.
217-
std::ifstream scriptInputFileStream(m_ScriptPath);
218-
if (scriptInputFileStream.good()) {
219-
std::string::size_type commentPos;
220-
bool inBlockComment = false;
221-
while (!scriptInputFileStream.eof()) {
222-
char rawLine[512];
223-
scriptInputFileStream.getline(rawLine, 512);
224-
std::string currentLine(rawLine);
225-
226-
if (!inBlockComment) {
227-
commentPos = currentLine.find("--[[", 0);
228-
inBlockComment = commentPos != std::string::npos;
229-
}
230-
if (inBlockComment) {
231-
commentPos = currentLine.find("]]", commentPos == std::string::npos ? 0 : commentPos);
232-
inBlockComment = commentPos != std::string::npos;
233-
}
234-
if (!inBlockComment) {
235-
commentPos = currentLine.find("--", 0);
236-
std::string::size_type foundTextPos = currentLine.find("OnSave");
237-
if (foundTextPos != std::string::npos && foundTextPos < commentPos) {
238-
return true;
239-
}
240-
}
241-
}
242-
}
243-
return false;
230+
return m_ScriptFunctions.find("OnSave") != m_ScriptFunctions.end();
244231
}
245232

246233
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -329,12 +316,12 @@ int GAScripted::Start() {
329316
}
330317

331318
// Run the file that specifies the Lua functions for this' operating logic
332-
if ((error = g_LuaMan.GetMasterScriptState().RunScriptFile(m_ScriptPath)) < 0) {
319+
if ((error = ReloadScripts()) < 0) {
333320
return error;
334321
}
335322

336-
// Call the defined function, but only after first checking if it exists
337-
if ((error = g_LuaMan.GetMasterScriptState().RunScriptString("if " + m_LuaClassName + ".StartActivity then " + m_LuaClassName + ":StartActivity( " + (initialActivityState == ActivityState::NotStarted ? "true" : "false") + "); end")) < 0) {
323+
// Call the create function
324+
if ((error = RunLuaFunction("StartActivity", {}, { initialActivityState == ActivityState::NotStarted ? "true" : "false" }, {})) < 0) {
338325
return error;
339326
}
340327

@@ -377,8 +364,7 @@ int GAScripted::Start() {
377364
void GAScripted::SetPaused(bool pause) {
378365
GameActivity::SetPaused(pause);
379366

380-
// Call the defined function, but only after first checking if it exists
381-
g_LuaMan.GetMasterScriptState().RunScriptString("if " + m_LuaClassName + ".PauseActivity then " + m_LuaClassName + ":PauseActivity(" + (pause ? "true" : "false") + "); end");
367+
RunLuaFunction("PauseActivity", {}, { pause ? "true" : "false" }, {});
382368

383369
// Pause all global scripts
384370
for (std::vector<GlobalScript *>::iterator sItr = m_GlobalScriptsList.begin(); sItr < m_GlobalScriptsList.end(); ++sItr) {
@@ -397,9 +383,7 @@ void GAScripted::SetPaused(bool pause) {
397383
void GAScripted::End() {
398384
GameActivity::End();
399385

400-
// Call the defined function, but only after first checking if it exists
401-
g_LuaMan.GetMasterScriptState().RunScriptString("if " + m_LuaClassName + ".EndActivity then " + m_LuaClassName + ":EndActivity(); end");
402-
386+
RunLuaFunction("EndActivity");
403387

404388
// End all global scripts
405389
for (std::vector<GlobalScript *>::iterator sItr = m_GlobalScriptsList.begin(); sItr < m_GlobalScriptsList.end(); ++sItr) {
@@ -456,8 +440,7 @@ void GAScripted::Update() {
456440
if (m_ActivityState != ActivityState::Over) {
457441
AddPieSlicesToActiveActorPieMenus();
458442

459-
// Call the defined function, but only after first checking if it exists
460-
g_LuaMan.GetMasterScriptState().RunScriptString("if " + m_LuaClassName + ".UpdateActivity then " + m_LuaClassName + ":UpdateActivity(); end");
443+
RunLuaFunction("UpdateActivity");
461444

462445
UpdateGlobalScripts(false);
463446
}
@@ -499,6 +482,16 @@ void GAScripted::Draw(BITMAP *pTargetBitmap, const Vector &targetPos) {
499482
GameActivity::Draw(pTargetBitmap, targetPos);
500483
}
501484

485+
int GAScripted::RunLuaFunction(const std::string& functionName, const std::vector<const Entity*>& functionEntityArguments, const std::vector<std::string_view>& functionLiteralArguments, const std::vector<LuabindObjectWrapper*>& functionObjectArguments) {
486+
// Call the defined function, but only after first checking if it exists
487+
auto funcItr = m_ScriptFunctions.find(functionName);
488+
if (funcItr == m_ScriptFunctions.end()) {
489+
return 0;
490+
}
491+
492+
return g_LuaMan.GetMasterScriptState().RunScriptFunctionObject(funcItr->second.get(), "_G", m_LuaClassName, functionEntityArguments, functionLiteralArguments, functionObjectArguments);
493+
}
494+
502495

503496
//////////////////////////////////////////////////////////////////////////////////////////
504497
// Virtual method: CollectRequiredAreas

Activities/GAScripted.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "GlobalScript.h"
1919
#include "Box.h"
2020

21+
#include "LuabindObjectWrapper.h"
22+
2123
namespace RTE
2224
{
2325

@@ -41,6 +43,7 @@ class GAScripted : public GameActivity {
4143

4244
public:
4345

46+
ScriptFunctionNames("StartActivity", "UpdateActivity", "PauseActivity", "EndActivity", "OnSave", "CraftEnteredOrbit", "OnMessage", "OnGlobalMessage");
4447

4548
// Concrete allocation and cloning definitions
4649
EntityAllocation(GAScripted);
@@ -242,6 +245,7 @@ ClassInfoGetters;
242245

243246
void Draw(BITMAP *pTargetBitmap, const Vector& targetPos = Vector()) override;
244247

248+
int RunLuaFunction(const std::string& functionName, const std::vector<const Entity*>& functionEntityArguments = std::vector<const Entity*>(), const std::vector<std::string_view>& functionLiteralArguments = std::vector<std::string_view>(), const std::vector<LuabindObjectWrapper*>& functionObjectArguments = std::vector<LuabindObjectWrapper*>());
245249

246250
//////////////////////////////////////////////////////////////////////////////////////////
247251
// Protected member variable and method declarations
@@ -283,6 +287,8 @@ ClassInfoGetters;
283287
// The list of global scripts allowed to run during this activity
284288
std::vector<GlobalScript *> m_GlobalScriptsList;
285289

290+
std::unordered_map<std::string, std::unique_ptr<LuabindObjectWrapper>> m_ScriptFunctions; //!< A map of LuabindObjectWrappers that hold Lua functions. Used to maintain script execution order and avoid extraneous Lua calls.
291+
286292

287293
//////////////////////////////////////////////////////////////////////////////////////////
288294
// Private member variable and method declarations

Activities/GameActivity.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ void GameActivity::Clear()
8787

8888
m_StartingGold = 0;
8989
m_FogOfWarEnabled = false;
90-
m_RequireClearPathToOrbit = true;
90+
m_RequireClearPathToOrbit = false;
9191

9292
m_DefaultFogOfWar = -1;
9393
m_DefaultRequireClearPathToOrbit = -1;
@@ -1795,7 +1795,7 @@ void GameActivity::Update()
17951795
float lzOffsetY = 0;
17961796
// Holding up or down will allow the player to make multiple orders without exiting the delivery phase. TODO: this should probably have a cooldown?
17971797
if (!m_PlayerController[player].IsState(MOVE_UP) && !m_PlayerController[player].IsState(MOVE_DOWN)) {
1798-
m_LandingZone[player].m_Y = g_SceneMan.FindAltitude(m_LandingZone[player], g_SceneMan.GetSceneHeight(), 10);
1798+
m_LandingZone[player].m_Y = g_SceneMan.FindAltitude(m_LandingZone[player], g_SceneMan.GetSceneHeight(), 10, true);
17991799
if (!g_MovableMan.GetNextTeamActor(team)) {
18001800
m_ObservationTarget[player] = m_LandingZone[player];
18011801
m_ViewState[player] = ViewState::Observe;
@@ -1815,7 +1815,7 @@ void GameActivity::Update()
18151815
lzOffsetY *= -1.0f;
18161816
}
18171817

1818-
m_LandingZone[player].m_Y = g_SceneMan.FindAltitude(m_LandingZone[player], g_SceneMan.GetSceneHeight(), 10) + lzOffsetY;
1818+
m_LandingZone[player].m_Y = g_SceneMan.FindAltitude(m_LandingZone[player], g_SceneMan.GetSceneHeight(), 10, true) + lzOffsetY;
18191819

18201820
if (m_pBuyGUI[player]->GetTotalOrderCost() > GetTeamFunds(team)) {
18211821
g_GUISound.UserErrorSound()->Play(player);
@@ -1847,7 +1847,7 @@ void GameActivity::Update()
18471847
viewOffset *= -1;
18481848
}
18491849

1850-
m_LandingZone[player].m_Y = prevHeight + ((g_SceneMan.FindAltitude(m_LandingZone[player], g_SceneMan.GetSceneHeight(), 10) - prevHeight) * 0.2);
1850+
m_LandingZone[player].m_Y = prevHeight + ((g_SceneMan.FindAltitude(m_LandingZone[player], g_SceneMan.GetSceneHeight(), 10) - prevHeight, true) * 0.2);
18511851

18521852
// Set the view to a little above the LZ position
18531853
Vector viewTarget(m_LandingZone[player].m_X, m_LandingZone[player].m_Y - viewOffset);
@@ -2135,7 +2135,7 @@ void GameActivity::Update()
21352135
// Make view follow the terrain
21362136
float prevHeight = m_ObservationTarget[Players::PlayerFour].m_Y;
21372137
m_ObservationTarget[Players::PlayerFour].m_Y = 0;
2138-
m_ObservationTarget[Players::PlayerFour].m_Y = prevHeight + ((g_SceneMan.FindAltitude(m_ObservationTarget[Players::PlayerFour], g_SceneMan.GetSceneHeight(), 20) - prevHeight) * 0.02);
2138+
m_ObservationTarget[Players::PlayerFour].m_Y = prevHeight + ((g_SceneMan.FindAltitude(m_ObservationTarget[Players::PlayerFour], g_SceneMan.GetSceneHeight(), 20, true) - prevHeight) * 0.02);
21392139
}
21402140
21412141
// Set the view to the observation position

CHANGELOG.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1414

1515
- New `Settings.ini` property `EnableMultithreadedLua`, which can be used to enable multithreaded Lua scripts and AI, for any lua script with the `--[[MULTITHREAD]]--` tag. Defaults to true.
1616

17+
- New generic Lua messaging system, to allow scripts on objects to communicate with other objects or scripts.
18+
Scripts on `MovableObject` now have new callback functions `OnMessage(self, message, context)` and `OnGlobalMessage(self, message, context)`.
19+
Script on `Activity` also have similar functions: `ActivityName:OnMessage(message, context)` and `ActivityName:OnGlobalMessage(message, context)`.
20+
The `OnMessage` callback will be triggered whenever the `SendMessage(message, context)` is called on an object, i.e `Object:SendMessage("Hello World")`.
21+
This `context` argument can be anything, like a table, string or number. It will be nil if left out of the SendMessage function call.
22+
The `OnGlobalMessage` callback works the exact same way, however global messages are sent to every object within the game, instead of a specific object.
23+
To send a global message, use `MovableMan:SendGlobalMessage(message, context)`.
24+
1725
- New Lua event function `SyncedUpdate()`, which will be called in a thread-safe synchronized manner and allows multithreaded scripts to modify game state in a safe and consistent way.
1826

1927
- Multithreaded asynchronous pathfinding, which dramatically improves performance on large maps and improves AI responsiveness.
@@ -38,10 +46,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
3846

3947
- New `AEJetpack` type, which replaces the old technique of `ACrab`/`AHuman` using an `AEmitter` as a jetpack. This type inherits from `AEmitter`.
4048
New INI and Lua (R/W) property `JetpackType`, which can be either `AEJetpack.Standard` or `AEJetpack.JumpPack`. Standard acts the same as the typical jetpack, whereas JumpPacks can only be activated when fully recharged, and fires all of it's fuel in one burst. Defaults to Standard.
49+
New INI and Lua (R/W) property `MinimumFuelRatio`, which defines the ratio of current fuel to max fuel that has to be met to fire the jetpack. Defaults to 0 for Standard and 0.25 for JumpPacks.
4150
New INI and Lua (R/W) property `CanAdjustAngleWhileFiring`, which defines whether the jet angle can change while the jetpack is active. Defaults to true.
4251
New INI and Lua (R/W) property `AdjustsThrottleForWeight`, which defines whether the jetpack will adjust it's throttle (between `NegativeThrottleMultiplier` and `PositiveThrottleMultiplier`) to account for any extra inventory mass. Increased throttle will decrease jet time accordingly. Defaults to true.
4352

44-
4553
- New `HeldDevice` Lua (R) function `IsBeingHeld`, which returns whether or not the `HeldDevice` is currently being held.
4654

4755
- New `HeldDevice` INI and Lua (R/W) property `GetsHitByMOsWhenHeld`, which defines whether this `HeldDevice` can be hit by MOs while equipped and held by an actor. Defaults to true.
@@ -70,6 +78,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
7078

7179
- New `SLTerrain` INI property `OrbitDirection`, which defines which direction is considered to be orbit, for the sake of brain-path-to-orbit, dropship spawn/return location, etc. Can be any of `Up`, `Down`, `Left` or `Right`. Defaults to `Up`.
7280

81+
- New FMOD and SoundContainer features:
82+
The game is now divided into SFX, UI, and Music busses which all route into the Master bus.
83+
The SFX bus has compression added for a better listening experience, and a safety volume limiter has been added to the Master bus.
84+
Aside from volume being attenuated, sounds will now also be lowpass filtered as distance increases.
85+
New `SoundContainer` INI and Lua (R/W) property `BusRouting`, which denotes which bus the SoundContainer routes to. Available busses: `SFX, UI, Music`. Defaults to `SFX`.
86+
`Enum` binding for `SoundContainer.BusRouting`: `SFX = 0, UI = 1, MUSIC = 2`.
87+
New `SoundContainer` INI and Lua (R/W) property `PanningStrengthMultiplier`, which will multiply the strength of 3D panning. This can be used to achieve for example a psuedo-Immobile effect where attenuation effects are still applied but the sound does not move from the center. Recommended to keep between 0.0 and 1.0.
88+
7389
</details>
7490

7591
<details><summary><b>Changed</b></summary>

Entities/ACDropShip.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,9 @@ float ACDropShip::GetAltitude(int max, int accuracy)
209209
g_SceneMan.WrapPosition(rPos);
210210

211211
// Check center too
212-
float cAlt = g_SceneMan.FindAltitude(m_Pos, max, accuracy);
213-
float rAlt = g_SceneMan.FindAltitude(rPos, max, accuracy);
214-
float lAlt = g_SceneMan.FindAltitude(lPos, max, accuracy);
212+
float cAlt = g_SceneMan.FindAltitude(m_Pos, max, accuracy, true);
213+
float rAlt = g_SceneMan.FindAltitude(rPos, max, accuracy, true);
214+
float lAlt = g_SceneMan.FindAltitude(lPos, max, accuracy, true);
215215

216216
// Return the lowest of the three
217217
return MIN(cAlt, MIN(rAlt, lAlt));

Entities/ACRocket.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ float ACRocket::GetAltitude(int max, int accuracy)
268268
else
269269
pos = m_Pos;
270270

271-
return g_SceneMan.FindAltitude(pos, max, accuracy);
271+
return g_SceneMan.FindAltitude(pos, max, accuracy, true);
272272
}
273273

274274
//////////////////////////////////////////////////////////////////////////////////////////

Entities/ACraft.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,17 @@ bool ACraft::HandlePieCommand(PieSlice::SliceType pieSliceIndex) {
550550
} else if (pieSliceIndex == PieSlice::SliceType::Stay) {
551551
m_AIMode = AIMODE_STAY;
552552
m_DeliveryState = FALL;
553+
} else if (pieSliceIndex == PieSlice::SliceType::Sentry) {
554+
m_AIMode = AIMODE_SENTRY;
555+
m_DeliveryState = FALL;
556+
} else if (pieSliceIndex == PieSlice::SliceType::Return) {
557+
m_AIMode = AIMODE_RETURN;
558+
m_DeliveryState = LAUNCH;
559+
} else if (pieSliceIndex == PieSlice::SliceType::GoTo) {
560+
m_AIMode = AIMODE_GOTO;
561+
m_DeliveryState = FALL;
562+
ClearAIWaypoints();
563+
m_UpdateMovePath = true;
553564
} else if (pieSliceIndex == PieSlice::SliceType::Scuttle) {
554565
m_AIMode = AIMODE_SCUTTLE;
555566
} else {

0 commit comments

Comments
 (0)