diff --git a/.github/actions/osxcross/macports.patch b/.github/actions/osxcross/macports.patch index 769f28cd34..ca74677475 100644 --- a/.github/actions/osxcross/macports.patch +++ b/.github/actions/osxcross/macports.patch @@ -24,3 +24,12 @@ index 3e87735..5c48e4e 100755 "$CACHE/$file.rmd160" "$CACHE/$file" 1>/dev/null if [ $? -ne 0 ]; then +@@ -360,7 +362,7 @@ getPkgUrl() + grep -o -E '"version":"[^"]+"' | \ + cut -d'"' -f4) + +- pkgs=$(getFileStdout "$MIRROR/$pkgname/?C=M;O=A" | \ ++ pkgs=$(getFileStdout "$MIRROR/$pkgname/?C=M;O=D" | \ + grep -o -E 'href="([^"#]+)"' | \ + cut -d'"' -f2 | grep '.tbz2$' | uniq) + diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml index 04bdcc4d9b..7624f8b7a0 100644 --- a/.github/workflows/meson.yml +++ b/.github/workflows/meson.yml @@ -100,7 +100,7 @@ jobs: CC: "ccache gcc" CXX: "ccache g++" run: | - meson setup --buildtype=${{inputs.build_type}} -Ddebug_type=${{inputs.debug_level}} -Db_lto=false build + meson setup --buildtype=${{inputs.build_type}} -Ddebug_type=${{inputs.debug_level}} -Db_lto=false -Db_pch=false build - name: Configure for AppImage if: ${{inputs.upload_artefacts}} @@ -178,7 +178,7 @@ jobs: echo "::group::Installing pkg-config" sudo apt install pkg-config echo "::group::Installing mac deps" - omp install SDL3 onetbb lz4 libpng minizip luajit flac + omp --x86_64 install SDL3 onetbb lz4 libpng minizip luajit flac echo "OSXCROSS_PKG_CONFIG_PATH=${{env.OSXCROSS_TARGET}}/macports/pkgs/opt/local/libexec/onetbb/lib/pkgconfig" >> $GITHUB_ENV echo "::endgroup::" echo "::group::Installing meson" @@ -201,7 +201,7 @@ jobs: env: LDFLAGS: "-static-libgcc -static-libstdc++" run: | - meson setup --cross-file=${{steps.osxcross.outputs.meson-osxcross}} --buildtype=${{inputs.build_type}} -Ddebug_type=${{inputs.debug_level}} -Db_lto=false build + meson setup --cross-file=${{steps.osxcross.outputs.meson-osxcross}} --buildtype=${{inputs.build_type}} -Ddebug_type=${{inputs.debug_level}} -Db_lto=false -Db_pch=false build - name: Configure for App Bundle if: ${{inputs.upload_artefacts}} @@ -262,7 +262,7 @@ jobs: - name: Setup run: | - meson setup --buildtype=${{inputs.build_type}} -Ddebug_type=${{inputs.debug_level}} --vsenv build + meson setup -Db_pch=false --buildtype=${{inputs.build_type}} -Ddebug_type=${{inputs.debug_level}} --vsenv build - name: Build run: | diff --git a/.gitignore b/.gitignore index efb3ceae1a..cffa58a2cf 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ *.user # IDE files /.idea +# Meson files +*.wraplock compile_commands.json **/.ccls-cache diff --git a/.vscode/launch.json b/.vscode/launch.json index 81416f8e04..b3473ffa74 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,13 +20,28 @@ } }, { - "name": "meson Debug (Release)", + "name": "meson Configure Final & Launch", "type": "cppdbg", "osx": { "MIMode": "lldb" }, "request": "launch", - "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand_debug", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand", + "cwd": "${workspaceFolder}", + "preLaunchTask": "meson Build Release", + "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", + "presentation": { + "group": "unix" + } + }, + { + "name": "meson Configure Debug (Release) & Launch", + "type": "cppdbg", + "osx": { + "MIMode": "lldb" + }, + "request": "launch", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand", "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Debug (Release)", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", @@ -35,13 +50,13 @@ } }, { - "name": "meson Debug (Minimal)", + "name": "meson Configure Debug (Minimal) & Launch", "type": "cppdbg", "osx": { "MIMode": "lldb" }, "request": "launch", - "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand_debug", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand", "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Debug (Minimal)", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", @@ -50,13 +65,13 @@ } }, { - "name": "meson Debug (Full)", + "name": "meson Configure Debug (Full) & Launch", "type": "cppdbg", "osx": { "MIMode": "lldb" }, "request": "launch", - "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand_debug", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/CortexCommand", "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Debug (Full)", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", @@ -116,6 +131,18 @@ "request": "launch", "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.exe", "cwd": "${workspaceFolder}", + "preLaunchTask": "Meson: Build all targets", + "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", + "presentation": { + "group": "windows" + } + }, + { + "name": "meson Configure Final & Launch [Windows]", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.exe", + "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Release", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", "presentation": { @@ -123,10 +150,10 @@ } }, { - "name": "meson Debug (Release) [Windows]", + "name": "meson Configure Debug (Release) & Launch [Windows]", "type": "cppvsdbg", "request": "launch", - "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.debug.release.exe", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.exe", "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Debug (Release)", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", @@ -135,10 +162,10 @@ } }, { - "name": "meson Debug (Minimal) [Windows]", + "name": "meson Configure Debug (Minimal) & Launch [Windows]", "type": "cppvsdbg", "request": "launch", - "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.debug.minimal.exe", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.exe", "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Debug (Minimal)", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", @@ -147,10 +174,10 @@ } }, { - "name": "meson Debug (Full) [Windows]", + "name": "meson Configure Debug (Full) & Launch [Windows]", "type": "cppvsdbg", "request": "launch", - "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.debug.full.exe", + "program": "${workspaceFolder}/${config:mesonbuild.buildFolder}/Cortex Command.exe", "cwd": "${workspaceFolder}", "preLaunchTask": "meson Build Debug (Full)", "envFile": "${workspaceFolder}/${config:mesonbuild.buildFolder}/meson-vscode.env", diff --git a/CHANGELOG.md b/CHANGELOG.md index ec6a51d1cb..625e36fbde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -171,6 +171,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Conquest activities will once again fall-back to using base dropships and rockets if a random selection of the selected tech's craft can't find one capable of carrying passengers and/or cargo. +- Actor inventory order is now preserved when AI switches weapons. + +- Constructors now dig sparse terrain more reliably, mostly preventing stray tiny pixels in dug areas. + - `MovableMan:OpenAllDoors()`, when passed `NOTEAM`, will now open/close doors specifically for `NOTEAM` (instead of all doors). - MOs now only play the BurstSound of the first Wound they receive in a frame, which not only solves audio spam during e.g. explosions but also preserves intended audio when firing guns with a high ParticleCount at them. diff --git a/Data/Base.rte/AI/NativeCrabAI.lua b/Data/Base.rte/AI/NativeCrabAI.lua index 075c9b7852..56ea852cfa 100644 --- a/Data/Base.rte/AI/NativeCrabAI.lua +++ b/Data/Base.rte/AI/NativeCrabAI.lua @@ -321,14 +321,7 @@ function NativeCrabAI:Update(Owner) end end - local newFlying = false; - if not (Owner.LeftFGLeg and Owner.RightFGLeg and Owner.LeftBGLeg and Owner.RightBGLeg) then - newFlying = true; - end - - if self.groundContact < 0 then - newFlying = true; - end + local newFlying = self.groundContact < 0; if self.flying ~= newFlying then Owner:SendMessage("AI_IsFlying", newFlying); diff --git a/Data/Base.rte/AI/NativeHumanAI.lua b/Data/Base.rte/AI/NativeHumanAI.lua index 1e782b3ee5..d5bd291045 100644 --- a/Data/Base.rte/AI/NativeHumanAI.lua +++ b/Data/Base.rte/AI/NativeHumanAI.lua @@ -260,14 +260,7 @@ function NativeHumanAI:Update(Owner) end end - local newFlying = false; - if not (Owner.FGLeg and Owner.BGLeg) then - newFlying = true; - end - - if self.groundContact < 0 then - newFlying = true; - end + local newFlying = self.groundContact < 0; if self.flying ~= newFlying then Owner:SendMessage("AI_IsFlying", newFlying); diff --git a/Data/Base.rte/Activities/BunkerBreach.lua b/Data/Base.rte/Activities/BunkerBreach.lua index 7176670b28..92ff92fcc2 100644 --- a/Data/Base.rte/Activities/BunkerBreach.lua +++ b/Data/Base.rte/Activities/BunkerBreach.lua @@ -142,16 +142,16 @@ function BunkerBreach:SetupDefenderActors() local crabToHumanSpawnRatio = self:GetCrabToHumanSpawnRatio(techID); local loadoutNames = {"Light", "Heavy", "Sniper", "Engineer", "Mecha", "Turret"}; - + local hasSpawnAreas = false; for _, loadoutName in pairs(loadoutNames) do if SceneMan.Scene:HasArea(loadoutName .. " Defenders") then hasSpawnAreas = true; end end - + for actor in MovableMan.AddedActors do - if not actor:IsInGroup("Brains") and not actor:IsInGroup("Bunker Systems") then + if not actor:IsInGroup("Brains") and not actor:IsInGroup("Bunker Systems") and not IsADoor(actor) then if hasSpawnAreas then actor.ToDelete = true; elseif actor.Team ~= self.defenderTeam then @@ -162,7 +162,7 @@ function BunkerBreach:SetupDefenderActors() actor.Team = self.defenderTeam; end end - + if hasSpawnAreas then for _, loadoutName in pairs({"Light", "Heavy", "Sniper", "Engineer", "Mecha", "Turret"}) do if SceneMan.Scene:HasArea(loadoutName .. " Defenders") then @@ -261,7 +261,7 @@ function BunkerBreach:StartActivity(isNewGame) FrameMan:ClearScreenText(self:ScreenOfPlayer(player)); end end - + MusicMan:PlayDynamicSong("Generic Battle Music"); if isNewGame then @@ -675,7 +675,7 @@ function BunkerBreach:CreateInternalReinforcements(loadout, numberOfReinforcemen numberOfInternalReinforcementsToCreateAtPosition = 3; end end - + for i = 1, numberOfInternalReinforcementsToCreateAtPosition do local internalReinforcement; if loadout then diff --git a/Data/Base.rte/Craft/Shared/AttachableTurret.lua b/Data/Base.rte/Craft/Shared/AttachableTurret.lua index df2d3a9f0c..a3b8830663 100644 --- a/Data/Base.rte/Craft/Shared/AttachableTurret.lua +++ b/Data/Base.rte/Craft/Shared/AttachableTurret.lua @@ -56,7 +56,7 @@ function Update(self) PrimitiveMan:DrawCirclePrimitive(self.Team, aimPos, (self.searchRange * 0.5), 13); end local aimTarget = MovableMan:GetClosestEnemyActor(self.Team, aimPos, (self.searchRange * 0.5), Vector()); - if aimTarget and aimTarget.Status < Actor.INACTIVE then + if aimTarget and aimTarget.Status < Actor.INACTIVE and aimTarget.GetsHitByMOs then --Debug: visualize search trace if self.showAim then PrimitiveMan:DrawLinePrimitive(self.Team, aimPos, aimTarget.Pos, 13); @@ -89,7 +89,7 @@ function Update(self) end local color = 13; --Debug trace color: red - if target and IsActor(target) and ToActor(target).Status < Actor.INACTIVE then + if target and IsActor(target) and ToActor(target).Status < Actor.INACTIVE and target.GetsHitByMOs then self:EnableEmission(true); self:TriggerBurst(); self.fireTimer:Reset(); @@ -106,7 +106,7 @@ function Update(self) end end end - + if self.fireTimer:IsPastSimTimeLimit() then self:EnableEmission(false); end diff --git a/Data/Base.rte/Devices/Tools/Constructor/Constructor.lua b/Data/Base.rte/Devices/Tools/Constructor/Constructor.lua index a7258748f1..306cf1720f 100644 --- a/Data/Base.rte/Devices/Tools/Constructor/Constructor.lua +++ b/Data/Base.rte/Devices/Tools/Constructor/Constructor.lua @@ -326,11 +326,19 @@ function Update(self) end else for i = 1, self.RoundsFired do - local trace = Vector(self.digLength, 0):RadRotate(angle + RangeRand(-1, 1) * self.spreadRange); - local digPos = ConstructorTerrainRay(self.MuzzlePos, trace, 0); - if SceneMan:GetTerrMatter(digPos.X, digPos.Y) ~= rte.airID then + local trace, digPos, diggingAir + for _ = 1, 5 do + -- Try up to 5 times to find a pixel to dig + trace = Vector(self.digLength, 0):RadRotate(angle + RangeRand(-1, 1) * self.spreadRange); + digPos = ConstructorTerrainRay(self.MuzzlePos, trace, 0); + diggingAir = SceneMan:GetTerrMatter(digPos.X, digPos.Y) == rte.airID + if not diggingAir then + break + end + end + if not diggingAir then local digWeightTotal = 0; local totalVel = Vector(); local found = 0; @@ -463,6 +471,8 @@ function Update(self) if cursorMovement:MagnitudeIsGreaterThan(0) then self.cursor = self.cursor + (mouseControlled and cursorMovement or cursorMovement:SetMagnitude(self.cursorMoveSpeed * (aiming and 0.5 or 1))); + + SceneMan:ForceBounds(self.cursor); end local precise = not mouseControlled and aiming; @@ -554,21 +564,23 @@ function Update(self) for x = 1, cellSize do for y = 1, cellSize do local pos = Vector(startPos.X + x, startPos.Y + y); - local strengthRatio = SceneMan:GetMaterialFromID(SceneMan:GetTerrMatter(pos.X, pos.Y)).StructuralIntegrity/self.digStrength; - if strengthRatio < 1 and SceneMan:GetMOIDPixel(pos.X, pos.Y) == rte.NoMOID then - local name = ""; - if bx + x == 0 or bx + x == self.buildList[1][4] - 1 or by + y == 0 or by + y == self.buildList[1][4] - 1 then - name = "Base.rte/Constructor Border Tile " .. math.random(4); - else - name = "Base.rte/Constructor Tile " .. math.random(16); - end - - local terrainObject = CreateTerrainObject(name); - terrainObject.Pos = pos; - SceneMan:AddSceneObject(terrainObject); + if SceneMan:IsWithinBounds(pos.X, pos.Y, 0) then + local strengthRatio = SceneMan:GetMaterialFromID(SceneMan:GetTerrMatter(pos.X, pos.Y)).StructuralIntegrity/self.digStrength; + if strengthRatio < 1 and SceneMan:GetMOIDPixel(pos.X, pos.Y) == rte.NoMOID then + local name = ""; + if bx + x == 0 or bx + x == self.buildList[1][4] - 1 or by + y == 0 or by + y == self.buildList[1][4] - 1 then + name = "Base.rte/Constructor Border Tile " .. math.random(4); + else + name = "Base.rte/Constructor Tile " .. math.random(16); + end + + local terrainObject = CreateTerrainObject(name); + terrainObject.Pos = pos; + SceneMan:AddSceneObject(terrainObject); - didBuild = true; - totalCost = 1 - strengthRatio; + didBuild = true; + totalCost = 1 - strengthRatio; + end end end end @@ -609,4 +621,4 @@ function Update(self) elseif self.cursor then self.cursor = nil; end -end \ No newline at end of file +end diff --git a/Data/Base.rte/GUIs/Title/Intro/PreTitle.png b/Data/Base.rte/GUIs/Title/Intro/PreTitle.png index cd9ac52d68..dc6b53eb9a 100644 Binary files a/Data/Base.rte/GUIs/Title/Intro/PreTitle.png and b/Data/Base.rte/GUIs/Title/Intro/PreTitle.png differ diff --git a/Data/Base.rte/GUIs/Title/Moon.png b/Data/Base.rte/GUIs/Title/Moon.png index 8ebf118edc..49c660dc49 100644 Binary files a/Data/Base.rte/GUIs/Title/Moon.png and b/Data/Base.rte/GUIs/Title/Moon.png differ diff --git a/Data/Base.rte/GUIs/Title/Planet.png b/Data/Base.rte/GUIs/Title/Planet.png index 21fa4bc37b..017d38c016 100644 Binary files a/Data/Base.rte/GUIs/Title/Planet.png and b/Data/Base.rte/GUIs/Title/Planet.png differ diff --git a/Data/Base.rte/Scenes/Objects/Bunkers/BunkerSystems/GenericCapturable/GenericCapturable.lua b/Data/Base.rte/Scenes/Objects/Bunkers/BunkerSystems/GenericCapturable/GenericCapturable.lua index ac3e84d19c..601833b93b 100644 --- a/Data/Base.rte/Scenes/Objects/Bunkers/BunkerSystems/GenericCapturable/GenericCapturable.lua +++ b/Data/Base.rte/Scenes/Objects/Bunkers/BunkerSystems/GenericCapturable/GenericCapturable.lua @@ -46,7 +46,18 @@ function Create(self) end end - self.captureProgress = self:NumberValueExists("captureProgress") and self:GetNumberValue("captureProgress") or 1; + -- If we have a saved value, use that. + if self:NumberValueExists("captureProgress") then + self.captureProgress = self:GetNumberValue("captureProgress") + else + -- Otherwise, initialize properly according to whether we are captured by a real team or not by default. + if self.Team == -1 then + self.captureProgress = 0.0; + else + self.captureProgress = 1.0; + end + end + self.capturingTeam = self:NumberValueExists("capturingTeam") and self:GetNumberValue("capturingTeam") or self.Team; self.dominantTeam = self:NumberValueExists("dominantTeam") and self:GetNumberValue("dominantTeam") or self.Team; diff --git a/Data/Base.rte/Shaders/Background.frag b/Data/Base.rte/Shaders/Background.frag index 7f8449e15b..1110efcbbd 100644 --- a/Data/Base.rte/Shaders/Background.frag +++ b/Data/Base.rte/Shaders/Background.frag @@ -1,4 +1,4 @@ -#version 330 +#version 330 core #extension GL_KHR_blend_equation_advanced: enable #extension GL_ARB_sample_shading: enable @@ -16,7 +16,7 @@ uniform bool rteBlendInvert = false; uniform bool drawMasked = false; -vec4 texture2DAA(sampler2D tex, vec2 uv) { +vec4 textureAA(sampler2D tex, vec2 uv) { vec2 texsize = vec2(textureSize(tex, 0)); vec2 uv_texspace = uv * texsize; vec2 seam = floor(uv_texspace + .5); @@ -26,13 +26,13 @@ vec4 texture2DAA(sampler2D tex, vec2 uv) { } void main() { - float red = texture2D(rteTexture, textureUV).r; + float red = texture(rteTexture, textureUV).r; if (red==0 && drawMasked) { discard; } if (!rteBlendInvert) { - FragColor = texture2DAA(rtePalette, vec2(red * vertexColor.r, 0.0)) * vec4(rteColor.rgb, rteColor.a * vertexColor.a); + FragColor = textureAA(rtePalette, vec2(red * vertexColor.r, 0.0)) * vec4(rteColor.rgb, rteColor.a * vertexColor.a); } else { - FragColor = vec4(vec3(1.0), 0.0) - (texture2DAA(rtePalette, vec2(red * vertexColor.r, 0.0)) * vec4(rteColor.rgb, -rteColor.a * vertexColor.a)); + FragColor = vec4(vec3(1.0), 0.0) - (textureAA(rtePalette, vec2(red * vertexColor.r, 0.0)) * vec4(rteColor.rgb, -rteColor.a * vertexColor.a)); } } diff --git a/Data/Base.rte/Shaders/Blit8.frag b/Data/Base.rte/Shaders/Blit8.frag index f61dfd7831..a1b5e05aff 100644 --- a/Data/Base.rte/Shaders/Blit8.frag +++ b/Data/Base.rte/Shaders/Blit8.frag @@ -1,5 +1,5 @@ // Blit8.frag -#version 130 +#version 330 core in vec2 textureUV; diff --git a/Data/Base.rte/Shaders/Blit8.vert b/Data/Base.rte/Shaders/Blit8.vert index ee58dc5626..da626baa08 100644 --- a/Data/Base.rte/Shaders/Blit8.vert +++ b/Data/Base.rte/Shaders/Blit8.vert @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec3 rteVertexPosition; in vec2 rteVertexTexUV; diff --git a/Data/Base.rte/Shaders/Dissolve.frag b/Data/Base.rte/Shaders/Dissolve.frag index 446027755b..859e7e2775 100644 --- a/Data/Base.rte/Shaders/Dissolve.frag +++ b/Data/Base.rte/Shaders/Dissolve.frag @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec2 textureUV; in vec4 vertexColor; @@ -32,7 +32,7 @@ float noise( vec2 U ) return mix( C.x, C.y, U.y ); } -vec4 texture2DAA(sampler2D tex, vec2 uv) { +vec4 textureAA(sampler2D tex, vec2 uv) { vec2 texsize = vec2(textureSize(tex, 0)); vec2 uv_texspace = uv * texsize; vec2 seam = floor(uv_texspace + .5); @@ -45,8 +45,8 @@ void main() { if (noise(gl_FragCoord.xy + textureUV) < 0.5) { discard; } - float red = texture2D(rteTexture, textureUV).r; - vec4 color = texture2DAA(rtePalette, vec2(red * vertexColor.r, 0.0)) * vec4(rteColor.rgb, rteColor.a * vertexColor.a); + float red = texture(rteTexture, textureUV).r; + vec4 color = textureAA(rtePalette, vec2(red * vertexColor.r, 0.0)) * vec4(rteColor.rgb, rteColor.a * vertexColor.a); FragColor = color; } \ No newline at end of file diff --git a/Data/Base.rte/Shaders/Flat.frag b/Data/Base.rte/Shaders/Flat.frag index cb0e6e1dfe..cad17c7f4b 100644 --- a/Data/Base.rte/Shaders/Flat.frag +++ b/Data/Base.rte/Shaders/Flat.frag @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec2 textureUV; diff --git a/Data/Base.rte/Shaders/PostProcess.frag b/Data/Base.rte/Shaders/PostProcess.frag index ed2835c5fd..c49408f682 100644 --- a/Data/Base.rte/Shaders/PostProcess.frag +++ b/Data/Base.rte/Shaders/PostProcess.frag @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec2 textureUV; in vec4 vertexColor; @@ -9,7 +9,7 @@ uniform sampler2D rteTexture; uniform vec4 rteColor; -vec4 texture2DAA(sampler2D tex, vec2 uv) { +vec4 textureAA(sampler2D tex, vec2 uv) { vec2 texsize = vec2(textureSize(tex, 0)); vec2 uv_texspace = uv * texsize; vec2 seam = floor(uv_texspace + .5); @@ -19,5 +19,5 @@ vec4 texture2DAA(sampler2D tex, vec2 uv) { } void main() { - FragColor = texture2DAA(rteTexture, textureUV) * rteColor * vertexColor; + FragColor = textureAA(rteTexture, textureUV) * rteColor * vertexColor; } diff --git a/Data/Base.rte/Shaders/PostProcess.vert b/Data/Base.rte/Shaders/PostProcess.vert index 8c2ba4bfa1..affd9d6b06 100644 --- a/Data/Base.rte/Shaders/PostProcess.vert +++ b/Data/Base.rte/Shaders/PostProcess.vert @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec3 rteVertexPosition; in vec2 rteVertexTexUV; diff --git a/Data/Base.rte/Shaders/ScreenBlit.frag b/Data/Base.rte/Shaders/ScreenBlit.frag index 6ce4707916..48b5e42ba6 100644 --- a/Data/Base.rte/Shaders/ScreenBlit.frag +++ b/Data/Base.rte/Shaders/ScreenBlit.frag @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec2 textureUV; @@ -7,7 +7,7 @@ out vec4 FragColor; uniform sampler2D rteTexture; uniform sampler2D rteGUITexture; -vec4 texture2DAA(sampler2D tex, vec2 uv) { +vec4 textureAA(sampler2D tex, vec2 uv) { vec2 texsize = vec2(textureSize(tex, 0)); vec2 uv_texspace = uv * texsize; vec2 seam = floor(uv_texspace + .5); @@ -17,8 +17,8 @@ vec4 texture2DAA(sampler2D tex, vec2 uv) { } void main() { - vec4 guiColor = texture2DAA(rteGUITexture, vec2(textureUV.x, -textureUV.y)); + vec4 guiColor = textureAA(rteGUITexture, vec2(textureUV.x, -textureUV.y)); float guiSolid = float((guiColor.r + guiColor.g + guiColor.b) > 0.0); float blendRatio = max(guiColor.a, guiSolid); - FragColor = (texture2DAA(rteTexture, textureUV) * (1.0F - blendRatio)) + guiColor * blendRatio; + FragColor = (textureAA(rteTexture, textureUV) * (1.0F - blendRatio)) + guiColor * blendRatio; } diff --git a/Data/Base.rte/Shaders/ScreenBlit.vert b/Data/Base.rte/Shaders/ScreenBlit.vert index 3532362c5e..a5f67d44a3 100644 --- a/Data/Base.rte/Shaders/ScreenBlit.vert +++ b/Data/Base.rte/Shaders/ScreenBlit.vert @@ -1,4 +1,4 @@ -#version 130 +#version 330 core in vec3 rteVertexPosition; in vec2 rteVertexTexUV; diff --git a/Data/Browncoats.rte/Devices/Weapons/Flash/Flash.lua b/Data/Browncoats.rte/Devices/Weapons/Flash/Flash.lua index 5caab04d4d..5593cd431e 100644 --- a/Data/Browncoats.rte/Devices/Weapons/Flash/Flash.lua +++ b/Data/Browncoats.rte/Devices/Weapons/Flash/Flash.lua @@ -1,14 +1,14 @@ function Create(self) self.fireVel = 17; self.spread = math.rad(self.ShakeRange); - + self.searchRange = 100 + FrameMan.PlayerScreenWidth * 0.3; self.searchTimer = Timer(); self.searchTimer:SetSimTimeLimitMS(250); self.lockThreshold = 2; - + self.targets = {}; - + self.targetLockSound = CreateSoundContainer("Mine Activate", "Base.rte"); end @@ -45,16 +45,16 @@ function ThreadedUpdate(self) end if self.Magazine.RoundCount > 0 then if controller:IsState(Controller.AIM_SHARP) then - + if self.searchTimer:IsPastSimTimeLimit() then self.searchTimer:Reset(); - + local searchPos = parent.ViewPoint; local lastTargetCount = #self.targets; self.targets = {}; for actor in MovableMan.Actors do - if #self.targets < self.RoundInMagCapacity and actor.Team ~= self.Team then + if #self.targets < self.RoundInMagCapacity and actor.Team ~= self.Team and actor.GetsHitByMOs then if (SceneMan:ShortestDistance(searchPos, actor.Pos, SceneMan.SceneWrapsX).Magnitude - actor.Radius) < self.searchRange and (actor.Vel.Magnitude + math.abs(actor.AngularVel) + 1)/math.sqrt(actor.Radius) < self.lockThreshold @@ -99,7 +99,7 @@ function ThreadedUpdate(self) if target.actor and target.actor.ID ~= rte.NoMOID then local screen = ActivityMan:GetActivity():ScreenOfPlayer(ToActor(parent):GetController().Player); PrimitiveMan:DrawBoxPrimitive(screen, target.actor.Pos + target.topLeft, target.actor.Pos + target.bottomRight, 149); - + if self.RoundInMagCount == 0 then target.topLeft = target.topLeft * 0.9; target.bottomRight = target.bottomRight * 0.9; diff --git a/Data/Browncoats.rte/Devices/Weapons/Heatlance/Heatlance.lua b/Data/Browncoats.rte/Devices/Weapons/Heatlance/Heatlance.lua index 35bdb99973..16bf2771e4 100644 --- a/Data/Browncoats.rte/Devices/Weapons/Heatlance/Heatlance.lua +++ b/Data/Browncoats.rte/Devices/Weapons/Heatlance/Heatlance.lua @@ -126,7 +126,7 @@ function ThreadedUpdate(self) end end -function OnDestroy(self) +function Destroy(self) self.flameSwingLoopSound.Volume = 0; self.plumeLoopSound.Volume = 0; end @@ -134,4 +134,4 @@ end function OnDetach(self) self.flameSwingLoopSound.Volume = 0; self.plumeLoopSound.Volume = 0; -end \ No newline at end of file +end diff --git a/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryConsole/RefineryConsole.lua b/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryConsole/RefineryConsole.lua index c383f4befa..0fac435827 100644 --- a/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryConsole/RefineryConsole.lua +++ b/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryConsole/RefineryConsole.lua @@ -6,8 +6,8 @@ function Create(self) self.loopSound:Play(self.Pos); end -function OnDestroy(self) +function Destroy(self) self.Activity:SendMessage("RefineryAssault_RefineryConsoleBroken"); -end \ No newline at end of file +end diff --git a/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryDrill/RefineryDrill.lua b/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryDrill/RefineryDrill.lua index c73935fe2f..3c6673acab 100644 --- a/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryDrill/RefineryDrill.lua +++ b/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryDrill/RefineryDrill.lua @@ -33,6 +33,6 @@ function ThreadedUpdate(self) end end -function OnDestroy(self) +function Destroy(self) self.loopSound:Stop(-1); -end \ No newline at end of file +end diff --git a/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryGenerator/RefineryGenerator.lua b/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryGenerator/RefineryGenerator.lua index 0aafa548ce..3d47aeedbc 100644 --- a/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryGenerator/RefineryGenerator.lua +++ b/Data/Browncoats.rte/Scenes/Objects/Breakables/RefineryGenerator/RefineryGenerator.lua @@ -15,6 +15,6 @@ function ThreadedUpdate(self) end end -function OnDestroy(self) +function Destroy(self) self.Activity:SendMessage("RefineryAssault_RefineryGeneratorBroken"); -end \ No newline at end of file +end diff --git a/Data/Coalition.rte/Devices/Weapons/MissileLauncher/MissileLauncher.lua b/Data/Coalition.rte/Devices/Weapons/MissileLauncher/MissileLauncher.lua index e4976be587..32712b4f21 100644 --- a/Data/Coalition.rte/Devices/Weapons/MissileLauncher/MissileLauncher.lua +++ b/Data/Coalition.rte/Devices/Weapons/MissileLauncher/MissileLauncher.lua @@ -43,7 +43,7 @@ function ThreadedUpdate(self) local moCheck = SceneMan:GetMOIDPixel(hitPos.X, hitPos.Y); if moCheck ~= rte.NoMOID then local mo = ToMOSRotating(MovableMan:GetMOFromID(MovableMan:GetMOFromID(moCheck).RootID)); - if mo and mo.ClassName ~= "ADoor" and mo.Team ~= parent.Team then + if mo and mo.ClassName ~= "ADoor" and mo.Team ~= parent.Team and mo.GetsHitByMOs then local movement = (mo.Vel.Magnitude + math.abs(mo.AngularVel) + 0.1) * math.sqrt(mo.Radius); if movement > self.lockThreshold then diff --git a/Data/Techion.rte/Devices/Weapons/NucleoSwarm/NucleoSwarmShot.lua b/Data/Techion.rte/Devices/Weapons/NucleoSwarm/NucleoSwarmShot.lua index 894da5d6bb..f02dab1012 100644 --- a/Data/Techion.rte/Devices/Weapons/NucleoSwarm/NucleoSwarmShot.lua +++ b/Data/Techion.rte/Devices/Weapons/NucleoSwarm/NucleoSwarmShot.lua @@ -21,7 +21,7 @@ function Create(self) local moCheck = SceneMan:GetMOIDPixel(checkPos.X, checkPos.Y); if moCheck ~= rte.NoMOID then local actor = MovableMan:GetMOFromID(MovableMan:GetMOFromID(moCheck).RootID); - if actor and actor.Team ~= self.Team then + if actor and actor.Team ~= self.Team and actor.GetsHitByMOs then self.target = actor; break; end @@ -66,7 +66,7 @@ function Update(self) self.seekerTimer:Reset(); self.seekerDelay = 1000 - math.random(1000); for actor in MovableMan.Actors do - if actor.Team ~= self.Team then + if actor.Team ~= self.Team and actor.GetsHitByMOs then self.potentialtargetdist = SceneMan:ShortestDistance(self.Pos, actor.Pos, SceneMan.SceneWrapsX); if (self.lastdist == nil or (self.lastdist ~= nil and self.potentialtargetdist:MagnitudeIsLessThan(self.lastdist))) and not self.potentialtargetdist:MagnitudeIsGreaterThan(500) and SceneMan:CastStrengthRay(self.Pos, self.potentialtargetdist:SetMagnitude(self.potentialtargetdist.Magnitude - actor.Radius), 0, Vector(), 5, rte.airID, SceneMan.SceneWrapsX) == false then self.lastdist = self.potentialtargetdist.Magnitude; @@ -81,7 +81,7 @@ function Update(self) if self.lifeTimer:IsPastSimMS(8000) then self:GibThis(); end - + --TODO: Add wounds through Lua like the other disintegrator weapons if SceneMan:GetTerrMatter(self.Pos.X, self.Pos.Y) == rte.airID then local moCheck = SceneMan:GetMOIDPixel(self.Pos.X, self.Pos.Y); diff --git a/README.md b/README.md index 2907ae5b54..007de18323 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Cortex Command Community Project Source *The Cortex Command Community Project is Free/Libre and Open Source under GNU AGPL v3* -[![Meson Build (Linux, macOS)](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/actions/workflows/meson.yml/badge.svg)](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/actions/workflows/meson.yml) [![Windows Build](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/actions/workflows/msbuild.yml/badge.svg)](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/actions/workflows/msbuild.yml) +[![Meson Build (Linux, macOS)](https://github.com/cortex-command-community/Cortex-Command-Community-Project/actions/workflows/meson.yml/badge.svg)](https://github.com/cortex-command-community/Cortex-Command-Community-Project/actions/workflows/meson.yml) [![Windows Build](https://github.com/cortex-command-community/Cortex-Command-Community-Project/actions/workflows/msbuild.yml/badge.svg)](https://github.com/cortex-command-community/Cortex-Command-Community-Project/actions/workflows/msbuild.yml) This is a community-driven effort to continue the development of Cortex Command. Stay up to date in our [Discord channel](https://discord.gg/TSU6StNQUG). @@ -24,7 +24,7 @@ Please feel free to add issues and bugs. It's as simple as going to the issues t If you've got any C++ experience, experience with the game's ini data through modding it, are good at spriting, or know Lua, you can contribute some of your time directly to the project. We'll gladly consider all pull requests that come in and are always happy to have more hands on deck. # More Information -See the [Information and Recommendations](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/wiki/Information,-Recommended-Plugins-and-Useful-Links) page for more details and useful development tools. +See the [Information and Recommendations](https://github.com/cortex-command-community/Cortex-Command-Community-Project/wiki/Information,-Recommended-Plugins-and-Useful-Links) page for more details and useful development tools. *** @@ -34,17 +34,11 @@ First you need to download the necessary files: 1. Install the necessary tools. You'll probably want [Visual Studio Community Edition](https://visualstudio.microsoft.com/downloads/) (build supports 2019 (>=16.10) and 2022 versions. Earlier versions are not supported due to lack of C++20 standard library features and conformance). You also need to have both x86 and x64 versions of the [Visual C++ Redistributable for Visual Studio 2015-2022](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) installed in order to run the compiled builds. -You may also want to check out the list of recommended Visual Studio plugins [here](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/wiki/Information,-Recommended-Plugins-and-Useful-Links). +You may also want to check out the list of recommended Visual Studio plugins [here](https://github.com/cortex-command-community/Cortex-Command-Community-Project/wiki/Information,-Recommended-Plugins-and-Useful-Links). 2. Clone this Repository into a folder. -3. Copy the following libraries from `Cortex-Command-Community-Project\external\lib\win` into the root directory: -* `fmod.dll` -* `SDL2.dll` - - For 32-bit builds, copy the following libraries from the `x86` folder inside `...\lib\win` as well: -* `fmodL.dll` -* `SDL2-32.dll` +3. Copy the `fmod.dll` library from `Cortex-Command-Community-Project\external\lib\win` into the root directory. Now you're ready to build and launch the game. Simply open `RTEA.sln` with Visual Studio, choose your target platform (x86 or x64) and configuration, and run the project. @@ -75,10 +69,9 @@ The Linux build uses the meson build system, and builds against system libraries ## Dependencies -* [`meson`](https://www.mesonbuild.com)`>= 1.0.0` (`pip install meson` if your distro doesn't include a recent version) +* [`meson`](https://www.mesonbuild.com)`>= 1.6.0` (`pip install meson`/`brew install meson` if your distro doesn't include a recent version) * `ninja` -* `gcc`, `g++` (>=12, clang unsupported) -* `sdl2` +* `gcc`, `g++` (>=13, clang unsupported) * `opengl` (usually provided by the gpu driver) * `flac` * `luajit` @@ -88,7 +81,6 @@ The Linux build uses the meson build system, and builds against system libraries * `lz4>=1.9.0` * `libpng` * `dylibbundler` (required only if installing on macOS) -* `SDL2_image` (linux only) For unspecified versions assume compatibility with the latest ubuntu LTS release. @@ -105,7 +97,7 @@ For unspecified versions assume compatibility with the latest ubuntu LTS release 5. (optional) `sudo ninja install -C build` (To uninstall later, keep the build directory intact. The game can then be uninstalled by `sudo ninja uninstall -C build`) -If you want to change the buildtype afterwards, you can use `meson configure --buildtype {release or debug}` in the build directory or create a secondary build directory as in Step 3. There are also additional build options documented in the [wiki](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/wiki/Meson-build-options) as well as through running `meson configure` in the build directory. +If you want to change the buildtype afterwards, you can use `meson configure --buildtype {release or debug}` in the build directory or create a secondary build directory as in Step 3. There are also additional build options documented in the [wiki](https://github.com/cortex-command-community/Cortex-Command-Community-Project/wiki/Meson-build-options) as well as through running `meson configure` in the build directory. ## Running (If you installed the game in step 5 above, it should appear with your regular applications and will just run) @@ -123,13 +115,13 @@ If you want to change the buildtype afterwards, you can use `meson configure --b - `Xcode` or `Command Line Tools for Xcode` (if you need to, you can also generate an xcode project from meson using the `--backend=xcode` option on setup) **Homebrew (macOS):** -`brew install pkg-config sdl2 minizip lz4 flac luajit lua libpng tbb gcc@13 ninja meson dylibbundler` +`brew install pkg-config sdl3 minizip lz4 flac luajit lua libpng tbb gcc@13 ninja meson dylibbundler` **Arch Linux:** -`sudo pacman -S sdl2 sdl2_image tbb flac luajit lua minizip lz4 libpng meson ninja base-devel` +`sudo pacman -S tbb flac luajit lua minizip lz4 libpng meson ninja base-devel` **Ubuntu >=22.04:** -`sudo apt-get install build-essential libsdl2-dev libsdl2-image-dev libloadpng4-dev libflac++-dev luajit-5.1-dev liblua5.1-dev libminizip-dev liblz4-dev libpng++-dev libtbb-dev ninja-build python3-pip` +`sudo apt-get install build-essential libflac++-dev luajit-5.1-dev liblua5.1-dev libminizip-dev liblz4-dev libpng++-dev libtbb-dev ninja-build python3-pip` `sudo python3 -m pip install meson` **Fedora:** @@ -165,7 +157,7 @@ This repository includes launch configurations to automatically build and debug - The [`lldb`](https://lldb.llvm.org/) debugger -These launch configurations are accessible via the [Run and Debug](https://code.visualstudio.com/docs/editor/debugging#_run-and-debug-view) view, and provide profiles to build and run the game in Release mode or any of the [3 Debug modes](https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/wiki/Meson-build-options). +These launch configurations are accessible via the [Run and Debug](https://code.visualstudio.com/docs/editor/debugging#_run-and-debug-view) view, and provide profiles to build and run the game in Release mode or any of the [3 Debug modes](https://github.com/cortex-command-community/Cortex-Command-Community-Project/wiki/Meson-build-options). All configurations will run pre-launch tasks to build the game using the supported backend before launching. diff --git a/RTEA.vcxproj b/RTEA.vcxproj index e2e0b94c41..a7f062590a 100644 --- a/RTEA.vcxproj +++ b/RTEA.vcxproj @@ -50,6 +50,7 @@ MultiByte v142 v143 + v145 10.0 _Bin\$(Platform)\$(Configuration)\ .\ @@ -236,6 +237,7 @@ false #undef GetClassName false + /bigobj %(AdditionalOptions) winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug.lib;loadpng-debug.lib;liblz4_debug_static.lib;luajit-debug.lib;luabind-debug.lib;raknet-debug.lib;SDL3_image-static-debug.lib;SDL3-static-debug.lib;opengl32.lib;dbghelp.lib;%(AdditionalDependencies) @@ -342,6 +344,7 @@ false #undef GetClassName false + /bigobj %(AdditionalOptions) winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug.lib;loadpng-debug.lib;liblz4_debug_static.lib;luajit-debug-release.lib;luabind-debug.lib;raknet-debug.lib;SDL3-static-debug.lib;SDL3_image-static-debug.lib;opengl32.lib;dbghelp.lib;%(AdditionalDependencies) @@ -525,6 +528,7 @@ true false #undef GetClassName + /bigobj %(AdditionalOptions) winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug-release.lib;loadpng-debug-release.lib;liblz4_release_static.lib;luajit-debug-release.lib;luabind-debug-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) @@ -587,6 +591,7 @@ true false #undef GetClassName + /bigobj %(AdditionalOptions) winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug-release.lib;loadpng-debug-release.lib;liblz4_release_static.lib;luajit-debug-release.lib;luabind-debug-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) @@ -707,6 +712,7 @@ true false #undef GetClassName + /bigobj %(AdditionalOptions) winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-release.lib;loadpng-release.lib;liblz4_release_static.lib;luajit-release.lib;luabind-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) diff --git a/Source/Activities/AssemblyEditor.cpp b/Source/Activities/AssemblyEditor.cpp index 3d103e407d..a37b9f2fc2 100644 --- a/Source/Activities/AssemblyEditor.cpp +++ b/Source/Activities/AssemblyEditor.cpp @@ -377,7 +377,7 @@ void AssemblyEditor::Draw(BITMAP* pTargetBitmap, const Vector& targetPos) { EditorActivity::Draw(pTargetBitmap, targetPos); } -BunkerAssembly* AssemblyEditor::BuildAssembly(std::string saveAsName) { +BunkerAssembly* AssemblyEditor::BuildAssembly(const std::string& saveAsName) { // Create new bunker assembly to save BunkerAssembly* pBA = new BunkerAssembly(); pBA->Create(m_pEditorGUI->GetCurrentAssemblyScheme()); diff --git a/Source/Activities/AssemblyEditor.h b/Source/Activities/AssemblyEditor.h index 6883e1d022..9f72496ac4 100644 --- a/Source/Activities/AssemblyEditor.h +++ b/Source/Activities/AssemblyEditor.h @@ -107,7 +107,7 @@ namespace RTE { /// it's pointer. Owhership IS transfered. /// @param saveAsName New assembly name. /// @return Built BunkerAssembly - BunkerAssembly* BuildAssembly(std::string saveAsName); + BunkerAssembly* BuildAssembly(const std::string& saveAsName); /// Saves the current BunkerAssembly to an appropriate ini file, and asks user if they want to overwrite first if a BunkerAssembly of this name exists. /// @param saveAsName The name of the new BunkerAssembly to be saved. diff --git a/Source/Activities/GAScripted.h b/Source/Activities/GAScripted.h index 9c749dad6e..0f8c41faa7 100644 --- a/Source/Activities/GAScripted.h +++ b/Source/Activities/GAScripted.h @@ -49,8 +49,8 @@ namespace RTE { /// @return An error return value signaling sucess or any particular failure. /// Anything below 0 is an error signal. int Create(std::string scriptPath, std::string scriptClassName) { - m_ScriptPath = scriptPath; - m_LuaClassName = scriptClassName; + m_ScriptPath = std::move(scriptPath); + m_LuaClassName = std::move(scriptClassName); return Create(); }; diff --git a/Source/Activities/GATutorial.cpp b/Source/Activities/GATutorial.cpp index 319c6c2f74..b4cfa88e45 100644 --- a/Source/Activities/GATutorial.cpp +++ b/Source/Activities/GATutorial.cpp @@ -35,10 +35,11 @@ GATutorial::~GATutorial() { Destroy(true); } -GATutorial::TutStep::TutStep(std::string text, int stepDuration, std::string screensPath, int frameCount, int frameDuration) { - m_Text = text; - m_Duration = stepDuration; - m_FrameDuration = frameDuration; +GATutorial::TutStep::TutStep(std::string text, int stepDuration, const std::string& screensPath, int frameCount, int frameDuration) : + m_Text(std::move(text)), + m_Duration(stepDuration), + m_FrameDuration(frameDuration) + { if (!screensPath.empty()) { ContentFile(screensPath.c_str()).GetAsAnimation(m_pScreens, frameCount); @@ -677,7 +678,7 @@ void GATutorial::DrawGUI(BITMAP* pTargetBitmap, const Vector& targetPos, int whi int timePhase = (int)m_AreaTimer.GetElapsedRealTimeMS() % 1200; revealText = revealText + (timePhase > 900 ? "..." : (timePhase > 600 ? ".. " : (timePhase > 300 ? ". " : " "))); } - g_FrameMan.GetSmallFont()->DrawAligned(&pBitmapInt, screenTextPos.m_X, screenTextPos.m_Y, revealText.c_str(), GUIFont::Centre); + g_FrameMan.GetSmallFont()->DrawAligned(&pBitmapInt, screenTextPos.m_X, screenTextPos.m_Y, revealText, GUIFont::Centre); } } diff --git a/Source/Activities/GATutorial.h b/Source/Activities/GATutorial.h index 040f7d100a..0eb45f0958 100644 --- a/Source/Activities/GATutorial.h +++ b/Source/Activities/GATutorial.h @@ -150,7 +150,7 @@ namespace RTE { // The duration of one frame int m_FrameDuration; - TutStep(std::string text, int stepDuration, std::string screensPath = "", int frameCount = 1, int frameDuration = 250); + TutStep(std::string text, int stepDuration, const std::string& screensPath = "", int frameCount = 1, int frameDuration = 250); }; // Member variables diff --git a/Source/Activities/GameActivity.cpp b/Source/Activities/GameActivity.cpp index 118a4e0742..e0d65161e3 100644 --- a/Source/Activities/GameActivity.cpp +++ b/Source/Activities/GameActivity.cpp @@ -282,7 +282,7 @@ void GameActivity::Destroy(bool notInherited) { Clear(); } -void GameActivity::SetTeamTech(int team, std::string tech) { +void GameActivity::SetTeamTech(int team, const std::string& tech) { if (team >= Teams::TeamOne && team < Teams::MaxTeamCount) { if (tech == "-All-" || tech == "-Random-") m_TeamTech[team] = tech; @@ -388,7 +388,7 @@ void GameActivity::SwitchToPrevActor(int player, int team, Actor* pSkip) { } } -void GameActivity::AddObjectivePoint(std::string description, Vector objPos, int whichTeam, ObjectiveArrowDir arrowDir) { +void GameActivity::AddObjectivePoint(const std::string& description, Vector objPos, int whichTeam, ObjectiveArrowDir arrowDir) { m_Objectives.push_back(ObjectivePoint(description, objPos, whichTeam, arrowDir)); } @@ -468,7 +468,7 @@ int GameActivity::SetOverridePurchaseList(const Loadout* pLoadout, int player) { return finalListCost; } -int GameActivity::SetOverridePurchaseList(std::string loadoutName, int player) { +int GameActivity::SetOverridePurchaseList(const std::string& loadoutName, int player) { // Find out the native module of this player int nativeModule = 0; MetaPlayer* pMetaPlayer = g_MetaMan.GetMetaPlayerOfInGamePlayer(player); @@ -664,7 +664,7 @@ void GameActivity::SetupPlayers() { int GameActivity::Start() { // Set the split screen config before the Scene (and it SceneLayers, specifially) are loaded - int humanCount = GetHumanCount(); + uint8_t humanCount = GetHumanCount(); // Depending on the resolution aspect ratio, split first horizontally (if wide screen) if (((float)g_WindowMan.GetResX() / (float)g_WindowMan.GetResY()) >= 1.6) g_FrameMan.ResetSplitScreens(humanCount > 1, humanCount > 2); @@ -2474,7 +2474,7 @@ void GameActivity::ObjectivePoint::Draw(BITMAP* pTargetBitmap, BITMAP* pArrowBit } } -std::string& GameActivity::GetNetworkPlayerName(int player) { +const std::string& GameActivity::GetNetworkPlayerName(int player) { if (player >= Players::PlayerOne && player < Players::MaxPlayerCount) return m_NetworkPlayerNames[player]; else @@ -2483,5 +2483,5 @@ std::string& GameActivity::GetNetworkPlayerName(int player) { void GameActivity::SetNetworkPlayerName(int player, std::string name) { if (player >= Players::PlayerOne && player < Players::MaxPlayerCount) - m_NetworkPlayerNames[player] = name; + m_NetworkPlayerNames[player] = std::move(name); } diff --git a/Source/Activities/GameActivity.h b/Source/Activities/GameActivity.h index 8578b45c7a..1abd3ec86a 100644 --- a/Source/Activities/GameActivity.h +++ b/Source/Activities/GameActivity.h @@ -238,7 +238,7 @@ namespace RTE { /// @param objPos The very short description of what the objective is (three short words max) /// @param whichTeam The absolute scene coordiante position of the objective. (default: Teams::TeamOne) /// @param arrowDir The desired direction of the arrow when the point is on screen. (default: ARROWDOWN) - void AddObjectivePoint(std::string description, Vector objPos, int whichTeam = Teams::TeamOne, ObjectiveArrowDir arrowDir = ARROWDOWN); + void AddObjectivePoint(const std::string& description, Vector objPos, int whichTeam = Teams::TeamOne, ObjectiveArrowDir arrowDir = ARROWDOWN); /// Sorts all objective points according to their positions on the Y axis. void YSortObjectivePoints(); @@ -265,7 +265,7 @@ namespace RTE { /// @param loadoutName The name of the Loadout preset to set the override purchase list to /// represent. /// @return The new total value of what's in the override purchase list. - int SetOverridePurchaseList(std::string loadoutName, int player); + int SetOverridePurchaseList(const std::string& loadoutName, int player); /// Clears all items from a specific player's override purchase list. /// @param m_PurchaseOverride[player].clear( Which player's override purchase list to clear. @@ -352,7 +352,7 @@ namespace RTE { /// Sets tech module name for specified team. Module must set must be loaded. /// @param team Team to set module, module name, for example Dummy.rte - void SetTeamTech(int team, std::string tech); + void SetTeamTech(int team, const std::string& tech); /// Indicates whether a specific team is assigned a CPU player in the current game. /// @param team Which team index to check. @@ -448,7 +448,7 @@ namespace RTE { /// Returns network player name /// @param player Player /// @return Network player name - std::string& GetNetworkPlayerName(int player); + const std::string& GetNetworkPlayerName(int player); /// Sets network player name /// @param player Player number, player name @@ -470,12 +470,13 @@ namespace RTE { m_Team = Teams::NoTeam; m_ArrowDir = ARROWDOWN; } - ObjectivePoint(const std::string& desc, const Vector& pos, int team = -1, ObjectiveArrowDir arrowDir = ARROWDOWN) { - m_Description = desc; - m_ScenePos = pos; - m_Team = (Teams)team; - m_ArrowDir = arrowDir; - } + + ObjectivePoint(std::string desc, const Vector& pos, int team = -1, ObjectiveArrowDir arrowDir = ARROWDOWN) : + m_Description(std::move(desc)), + m_ScenePos(pos), + m_Team((Teams)team), + m_ArrowDir(arrowDir) + {} /// Simply draws this' arrow relative to a point on a bitmap. /// @param pTargetBitmap A pointer to the BITMAP to draw on. diff --git a/Source/Entities/ADoor.cpp b/Source/Entities/ADoor.cpp index 8425c21942..095f601ba5 100644 --- a/Source/Entities/ADoor.cpp +++ b/Source/Entities/ADoor.cpp @@ -465,11 +465,6 @@ void ADoor::Update() { Actor::Update(); - // Start the spinning out of control animation for the motor, start it slow - if (!m_Door) { - m_SpriteAnimDuration *= 4; - } - if (m_SpriteAnimMode == LOOPWHENOPENCLOSE && m_FrameCount > 1 && (m_DoorState == OPENING || m_DoorState == CLOSING) && m_SpriteAnimTimer.IsPastSimMS(m_SpriteAnimDuration)) { m_Frame = (m_Frame + 1) % m_FrameCount; m_SpriteAnimTimer.Reset(); diff --git a/Source/Entities/AEJetpack.cpp b/Source/Entities/AEJetpack.cpp index 2778752789..1ed7e02056 100644 --- a/Source/Entities/AEJetpack.cpp +++ b/Source/Entities/AEJetpack.cpp @@ -195,7 +195,10 @@ void AEJetpack::Burst(Actor& parentActor, float fuelUseMultiplier) { EnableEmission(true); AlarmOnEmit(m_Team); // Jetpacks are noisy! - float fuelUsage = g_TimerMan.GetDeltaTimeMS() * static_cast(std::max(GetTotalBurstSize(), 2)) * (CanTriggerBurst() ? 1.0F : 0.5F) * fuelUseMultiplier; // burst fuel + // TODO: burst emissions shouldn't be affected by delta time, but they were. + // However our values were tuned for 60hz, so hack in constant 60Hz deltatime in milliseconds. + float fuelUsage = (1000.0f / 60.0f) * static_cast(std::max(GetTotalBurstSize(), 2)) * (CanTriggerBurst() ? 1.0F : 0.5F) * fuelUseMultiplier; // burst fuel + fuelUsage += g_TimerMan.GetDeltaTimeMS() * fuelUseMultiplier; // emit fuel m_JetTimeLeft -= fuelUsage; } diff --git a/Source/Entities/AEmitter.cpp b/Source/Entities/AEmitter.cpp index 40bdedc416..5803b963ab 100644 --- a/Source/Entities/AEmitter.cpp +++ b/Source/Entities/AEmitter.cpp @@ -276,26 +276,28 @@ float AEmitter::EstimateImpulse(bool burst) { for (Emission* emission: m_EmissionList) { // Only check emissions that push the emitter if (emission->PushesEmitter()) { - // Todo... we're not checking emission start/stop times here, so this will always calculate the impulse as if the emission was active. + // TODO: we're not checking emission start/stop times here, so this will always calculate the impulse as if the emission was active. // There's not really an easy way to do this, since the emission rate is not necessarily constant over time. - float emissions = (emission->GetRate() / 60.0f) * g_TimerMan.GetDeltaTimeSecs(); + float emissionsPerFrame = (emission->GetRate() / 60.0f) * g_TimerMan.GetDeltaTimeSecs(); float scale = 1.0F; + + // Get all the particles emitted this frame + emissionsPerFrame *= emission->GetParticleCount(); + + // When bursting, add on all the bursted emissions + // We also use m_BurstScale on ALL emissions, not just the extra bursted ones + // This is a bit funky but consistent with the code that applies the impulse if (burst) { - emissions *= emission->GetBurstSize(); + emissionsPerFrame += emission->GetBurstSize(); scale = m_BurstScale; } - if (emissions > 0) { - int extraEmissions = emission->GetParticleCount() - 1; - emissions += extraEmissions; - } - float velMin = emission->GetMinVelocity() * scale; - float velRange = (emission->GetMaxVelocity() - emission->GetMinVelocity()) * scale * 0.5f; - float spread = (std::max(static_cast(c_PI) - (emission->GetSpread() * scale), 0.0F) / c_PI); // A large spread will cause the forces to cancel eachother out + float velRange = (emission->GetMaxVelocity() - emission->GetMinVelocity()) * scale * 0.5f; + float spread = (std::max(static_cast(c_PI) - (emission->GetSpread() * scale), 0.0F) / c_PI); // A large spread will cause the forces to cancel eachother out // Add to accumulative recoil impulse generated, F = m * a. - impulse += (velMin + velRange) * spread * emission->m_pEmission->GetMass() * emissions; + impulse += (velMin + velRange) * spread * emission->m_pEmission->GetMass() * emissionsPerFrame; } } @@ -453,17 +455,18 @@ void AEmitter::Update() { } else { emission->m_Accumulator = 0; } + float scale = 1.0F; // Add extra emissions if bursting. if (m_BurstTriggered) { emissionCount += emission->GetBurstSize(); scale = m_BurstScale; } + + // We don't consider extra particles for our emission count, so add prior to multiply emissionCountTotal += emissionCount; - if (emissionCount > 0) { - int extraEmissions = emission->GetParticleCount() - 1; - emissionCount += extraEmissions; - } + emissionCount *= emission->GetParticleCount(); + pParticle = 0; emitVel.Reset(); parentVel = pRootParent->GetVel() * emission->InheritsVelocity(); diff --git a/Source/Entities/AHuman.cpp b/Source/Entities/AHuman.cpp index f84fecb1bb..e032cd8a02 100644 --- a/Source/Entities/AHuman.cpp +++ b/Source/Entities/AHuman.cpp @@ -1,6 +1,7 @@ #include "AHuman.h" #include "AtomGroup.h" +#include "RTETools.h" #include "ThrownDevice.h" #include "Arm.h" #include "Leg.h" @@ -686,7 +687,7 @@ bool AHuman::EquipFirearm(bool doEquip) { return false; } -bool AHuman::EquipDeviceInGroup(std::string group, bool doEquip) { +bool AHuman::EquipDeviceInGroup(const std::string& group, bool doEquip) { if (!(m_pFGArm && m_pFGArm->IsAttached())) { return false; } @@ -748,7 +749,7 @@ bool AHuman::EquipDeviceInGroup(std::string group, bool doEquip) { return false; } -bool AHuman::EquipLoadedFirearmInGroup(std::string group, std::string excludeGroup, bool doEquip) { +bool AHuman::EquipLoadedFirearmInGroup(const std::string& group, const std::string& excludeGroup, bool doEquip) { if (!(m_pFGArm && m_pFGArm->IsAttached())) { return false; } @@ -967,27 +968,60 @@ float AHuman::EstimateJumpHeight() const { return 0.0F; } + // Estimate by "simulating" the character velocity frame by frame as the jetpack is used. + // In pixels per second. Positive value means moving upward. + // + // Start with zero, for now. + float currentYVelocity = 0.0F; + + // Upward acceleration per frame. + float yGravity = -(g_SceneMan.GetGlobalAcc().GetY() * g_TimerMan.GetDeltaTimeSecs()); + float totalMass = GetMass(); - float fuelTime = m_pJetpack->GetJetTimeTotal(); - float fuelUseMultiplier = m_pJetpack->GetThrottleFactor(); float impulseBurst = m_pJetpack->EstimateImpulse(true) / totalMass; float impulseThrust = m_pJetpack->EstimateImpulse(false) / totalMass; + float fuelTime = m_pJetpack->GetJetTimeTotal(); + float fuelUseMultiplierThrust = m_pJetpack->GetThrottleFactor(); + float fuelUseMultiplierBurst = fuelUseMultiplierThrust * impulseBurst / impulseThrust; + + bool hasBursted = false; + + float totalHeight = 0.0F; + + // Simulate up until we start falling. + while (true) { + // Account for the forces upon us. + if (!hasBursted && fuelTime > 0.0F) { + currentYVelocity += impulseBurst; + // TODO: burst emissions shouldn't be affected by delta time, but they were. + // However our values were tuned for 60hz, so hack in constant 60Hz deltatime in milliseconds. + fuelTime -= (1000.0f / 60.0f) * fuelUseMultiplierBurst; + hasBursted = true; + } - Vector globalAcc = g_SceneMan.GetGlobalAcc() * g_TimerMan.GetDeltaTimeSecs(); - Vector currentVelocity = Vector(0.0F, -impulseBurst); - float totalHeight = currentVelocity.GetY() * g_TimerMan.GetDeltaTimeSecs() * c_PPM; - do { - currentVelocity += globalAcc; - totalHeight += currentVelocity.GetY() * g_TimerMan.GetDeltaTimeSecs() * c_PPM; if (fuelTime > 0.0F) { - currentVelocity.m_Y -= impulseThrust; - fuelTime -= g_TimerMan.GetDeltaTimeMS() * fuelUseMultiplier; + currentYVelocity += impulseThrust; + fuelTime -= g_TimerMan.GetDeltaTimeMS() * fuelUseMultiplierThrust; + } + + if (currentYVelocity + yGravity >= currentYVelocity) { + // Velocity is too big or gravity is too small. Either way, this will loop forever now. + // Just assume that we can reach the stars. + return FLT_MAX; + } + + currentYVelocity += yGravity; + + if (currentYVelocity > 0.0F) { + // If we're still flying up, that means more height. + totalHeight += currentYVelocity * g_TimerMan.GetDeltaTimeSecs() * c_PPM; + } else { + // If we're not, that means we're done simulating. + break; } - } while (currentVelocity.GetY() < 0.0F); + } - float finalCalculatedHeight = totalHeight * -1.0F * c_MPP; - float finalHeightMultipler = 0.6f; // Make us think we can do less because AI path following is shit - return finalCalculatedHeight * finalHeightMultipler; + return totalHeight * c_MPP; } bool AHuman::EquipShield() { @@ -1831,7 +1865,7 @@ void AHuman::PreControllerUpdate() { } } else { m_CanActivateBGItem = true; - if (thrownDevice = dynamic_cast(device)) { + if ((thrownDevice = dynamic_cast(device))) { thrownDevice->SetSharpAim(isSharpAiming ? 1.0F : 0); if (m_Controller.IsState(WEAPON_FIRE)) { if (m_ArmsState != THROWING_PREP) { @@ -2023,7 +2057,7 @@ void AHuman::PreControllerUpdate() { } // Item currently set to be within reach has expired or is now out of range - if (m_pItemInReach && (!m_pItemInReach->IsPickupableBy(this) || !g_MovableMan.IsDevice(m_pItemInReach) || g_SceneMan.ShortestDistance(reachPoint, m_pItemInReach->GetPos(), g_SceneMan.SceneWrapsX()).MagnitudeIsGreaterThan(reach + m_pItemInReach->GetRadius()))) { + if (m_pItemInReach && (m_pItemInReach->ToDelete() || !m_pItemInReach->IsPickupableBy(this) || !g_MovableMan.IsDevice(m_pItemInReach) || g_SceneMan.ShortestDistance(reachPoint, m_pItemInReach->GetPos(), g_SceneMan.SceneWrapsX()).MagnitudeIsGreaterThan(reach + m_pItemInReach->GetRadius()))) { m_pItemInReach = nullptr; } @@ -2529,8 +2563,8 @@ void AHuman::Update() { if (m_ProneState == GOPRONE) { if (!m_ProneTimer.IsPastSimMS(333)) { if (std::abs(rotDiff) > 0.1F && std::abs(rotDiff) < c_PI) { - m_AngularVel += rotDiff * 0.4F; - m_Vel.m_X += (m_HFlipped ? -std::abs(rotDiff) : std::abs(rotDiff)) / std::max(m_Vel.GetMagnitude(), 4.0F); + m_AngularVel += rotDiff * 24.0F * g_TimerMan.GetDeltaTimeSecs(); + m_Vel.m_X += (m_HFlipped ? -std::abs(rotDiff) : std::abs(rotDiff)) / std::max(m_Vel.GetMagnitude(), 4.0F) * 60.0F * g_TimerMan.GetDeltaTimeSecs(); } } else { // Done going down, now stay down without spring. @@ -2540,9 +2574,9 @@ void AHuman::Update() { } else if (m_ProneState == LAYINGPRONE) { // If down, try to keep flat against the ground. if (std::abs(rotDiff) > c_SixteenthPI && std::abs(rotDiff) < c_HalfPI) { - m_AngularVel += rotDiff * 0.65F; + m_AngularVel += rotDiff * 39.0F * g_TimerMan.GetDeltaTimeSecs(); } else if (std::abs(m_AngularVel) > 0.3F) { - m_AngularVel *= 0.85F; + m_AngularVel = ExpDecay(m_AngularVel, 0, 10, g_TimerMan.GetDeltaTimeSecs()); } } } else { @@ -2562,6 +2596,7 @@ void AHuman::Update() { rot = rotTarget; } else { // Lerp towards the angle + // TODO: make framerate independent m_AngularVel = m_AngularVel * (0.98F - 0.06F * (m_Health / m_MaxHealth)) - (rotDiff * 0.5F); } @@ -2578,14 +2613,14 @@ void AHuman::Update() { float rotDiff = rotTarget - rot; if (std::abs(rotDiff) > 0.1F && std::abs(rotDiff) < c_PI) { - m_AngularVel += rotDiff * 0.05F; + m_AngularVel += rotDiff * 3.0F * g_TimerMan.GetDeltaTimeSecs(); } } else if (m_Status == DYING) { float rotTarget = m_Vel.m_X - (rot + m_AngularVel) > 0 ? -c_HalfPI : c_HalfPI; float rotDiff = rotTarget - rot; if (!m_DeathTmr.IsPastSimMS(125) && std::abs(rotDiff) > 0.1F && std::abs(rotDiff) < c_PI) { // TODO: finetune this for situations like low gravity! - float velScalar = 0.5F; //* (g_SceneMan.GetGlobalAcc().GetY() * m_GlobalAccScalar) / c_PPM; + float velScalar = 30.0F * g_TimerMan.GetDeltaTimeSecs(); //* (g_SceneMan.GetGlobalAcc().GetY() * m_GlobalAccScalar) / c_PPM; m_AngularVel += rotDiff * velScalar; m_Vel.m_X += (rotTarget > 0 ? -std::abs(rotDiff) : std::abs(rotDiff)) * velScalar * 0.5F; } else { @@ -2600,7 +2635,7 @@ void AHuman::Update() { if (!m_pHead && m_Status != DYING && m_Status != DEAD) { m_Health -= m_MaxHealth + 1.0F; } else if (!m_pFGArm && !m_pBGArm && !m_pFGLeg && !m_pBGLeg && m_Status != DYING && m_Status != DEAD) { - m_Health -= 0.1F; + m_Health -= 6.0F * g_TimerMan.GetDeltaTimeSecs(); } if (m_Status == DYING) { @@ -2684,7 +2719,7 @@ void AHuman::DrawHUD(BITMAP* pTargetBitmap, const Vector& targetPos, int whichSc return; } - Actor::DrawHUD(pTargetBitmap, targetPos, whichScreen); + Actor::DrawHUD(pTargetBitmap, targetPos, whichScreen, playerControlled); if (!m_HUDVisible) { return; diff --git a/Source/Entities/AHuman.h b/Source/Entities/AHuman.h index 85b5e1e09e..a292b42a09 100644 --- a/Source/Entities/AHuman.h +++ b/Source/Entities/AHuman.h @@ -243,7 +243,7 @@ namespace RTE { /// @param doEquip Whether to actually equip any matching item found in the inventory, (default: true) /// or just report that it's there or not. /// @return Whether a firearm was successfully switched to, or already held. - bool EquipDeviceInGroup(std::string group, bool doEquip = true); + bool EquipDeviceInGroup(const std::string& group, bool doEquip = true); /// Switches the currently held device (if any) to the first loaded HDFirearm /// of the specified group in the inventory. If no such weapon is in the @@ -253,7 +253,7 @@ namespace RTE { /// @param doEquip Whether to actually equip any matching item found in the inventory, (default: true) /// or just report that it's there or not. /// @return Whether a firearm was successfully switched to, or already held. - bool EquipLoadedFirearmInGroup(std::string group, std::string exludeGroup, bool doEquip = true); + bool EquipLoadedFirearmInGroup(const std::string& group, const std::string& exludeGroup, bool doEquip = true); /// Switches the equipped HeldDevice (if any) to the first found device with the specified preset name in the inventory. /// If the equipped HeldDevice is of that module and preset name, nothing happens. diff --git a/Source/Entities/Activity.cpp b/Source/Entities/Activity.cpp index b984c51b09..767a64b8e6 100644 --- a/Source/Entities/Activity.cpp +++ b/Source/Entities/Activity.cpp @@ -467,8 +467,8 @@ void Activity::ClearPlayers(bool resetFunds) { m_PlayerCount = m_TeamCount = 0; } -int Activity::GetHumanCount() const { - int humans = 0; +uint8_t Activity::GetHumanCount() const { + uint8_t humans = 0; for (int player = Players::PlayerOne; player < Players::MaxPlayerCount; ++player) { if (m_IsActive[player] && m_IsHuman[player]) { humans++; @@ -583,7 +583,7 @@ float Activity::GetPlayerFundsShare(int player) const { } void Activity::SetPlayerBrain(Actor* newBrain, int player) { - if ((player >= Players::PlayerOne || player < Players::MaxPlayerCount) && newBrain) { + if ((player >= Players::PlayerOne && player < Players::MaxPlayerCount) && newBrain) { if (newBrain->GetTeam() != m_Team[player]) { newBrain->SetTeam(m_Team[player]); } diff --git a/Source/Entities/Activity.h b/Source/Entities/Activity.h index 88385920a1..fa111b4149 100644 --- a/Source/Entities/Activity.h +++ b/Source/Entities/Activity.h @@ -129,7 +129,7 @@ namespace RTE { /// Gets the user-friendly description of this Activity. /// @return A string with the user-friendly description of this Activity. - std::string GetDescription() const { return m_Description; } + const std::string& GetDescription() const { return m_Description; } /// Gets the max number of players supported by this Activity. /// @return The max number of players supported by this Activity. @@ -156,11 +156,11 @@ namespace RTE { /// Gets the name of the current scene. /// @return A string with the instance name of the scene. - std::string GetSceneName() const { return m_SceneName; } + const std::string& GetSceneName() const { return m_SceneName; } /// Sets the name of the scene this is associated with. /// @param sceneName The new name of the scene to load next game. - void SetSceneName(const std::string sceneName) { m_SceneName = sceneName; } + void SetSceneName(std::string sceneName) { m_SceneName = std::move(sceneName); } /// Gets whether craft must be considered orbited if they reach the map border on non-wrapped maps. /// @return Whether craft are considered orbited when at the border of a non-wrapping map. @@ -228,7 +228,7 @@ namespace RTE { /// Gets the total number of human players in the current Activity. /// @return The total number of players in the current Activity. - int GetHumanCount() const; + uint8_t GetHumanCount() const; /// Indicates whether a specific player is human in the current game, ie not an AI player and has a screen etc. /// @param player Which player index to check. diff --git a/Source/Entities/Actor.cpp b/Source/Entities/Actor.cpp index 1ea044ee05..7ea36f424b 100644 --- a/Source/Entities/Actor.cpp +++ b/Source/Entities/Actor.cpp @@ -1047,6 +1047,7 @@ float Actor::EstimateDigStrength() const { } float Actor::EstimateJumpHeight() const { + // Sentinel value that is explicitly checked for within pathfinder code. return FLT_MAX; } diff --git a/Source/Entities/Actor.h b/Source/Entities/Actor.h index 3da398ddc0..00be2213e7 100644 --- a/Source/Entities/Actor.h +++ b/Source/Entities/Actor.h @@ -6,6 +6,9 @@ /// http://www.datarealms.com /// Inclusions of header files #include "MOSRotating.h" +#include "PathFinder.h" + +#include namespace RTE { @@ -665,7 +668,7 @@ namespace RTE { /// @return The actor's dig strength. virtual float EstimateDigStrength() const; - /// Estimates how high this actor can jump. + /// Estimates how high this actor can jump. Default implementation returns FLT_MAX. /// @return The actor's jump height. virtual float EstimateJumpHeight() const; diff --git a/Source/Entities/BunkerAssembly.cpp b/Source/Entities/BunkerAssembly.cpp index e1ce60c73a..4f460cb806 100644 --- a/Source/Entities/BunkerAssembly.cpp +++ b/Source/Entities/BunkerAssembly.cpp @@ -195,7 +195,7 @@ int BunkerAssembly::ReadProperty(const std::string_view& propName, Reader& reade } else { // Do not allow to define assemblies prior to corresponding assembly scheme char s[256]; - std::snprintf(s, sizeof(s), "Required BunkerAssemblyScheme '%s%' not found when trying to load BunkerAssembly '%s'! BunkerAssemblySchemes MUST be defined before dependent BunkerAssmeblies.", parentScheme.c_str(), m_PresetName.c_str()); + std::snprintf(s, sizeof(s), "Required BunkerAssemblyScheme '%s' not found when trying to load BunkerAssembly '%s'! BunkerAssemblySchemes MUST be defined before dependent BunkerAssmeblies.", parentScheme.c_str(), m_PresetName.c_str()); RTEAbort(s); } }); diff --git a/Source/Entities/BunkerAssembly.h b/Source/Entities/BunkerAssembly.h index cdffa444b8..61a80203ad 100644 --- a/Source/Entities/BunkerAssembly.h +++ b/Source/Entities/BunkerAssembly.h @@ -61,7 +61,7 @@ namespace RTE { /// Description: /// Return value: - std::string GetParentAssemblySchemeName() const { return m_ParentAssemblyScheme; } + const std::string& GetParentAssemblySchemeName() const { return m_ParentAssemblyScheme; } /// Indicates whether this' current graphical representation overlaps /// a point in absolute scene coordinates. @@ -97,11 +97,11 @@ namespace RTE { /// Gets the name of an assembly symmetric to this one. /// @return Symmetric assembly name. - std::string GetSymmetricAssemblyName() const { return m_SymmetricAssembly; }; + const std::string& GetSymmetricAssemblyName() const { return m_SymmetricAssembly; }; /// Sets the name of an assembly symmetric to this one. /// @param newSymmetricAssembly Symmetric assembly name. - void SetSymmetricAssemblyName(std::string newSymmetricAssembly) { m_SymmetricAssembly = newSymmetricAssembly; }; + void SetSymmetricAssemblyName(std::string newSymmetricAssembly) { m_SymmetricAssembly = std::move(newSymmetricAssembly); }; /// Draws this TerrainObject's current graphical representation to a /// BITMAP of choice. diff --git a/Source/Entities/BunkerAssemblyScheme.h b/Source/Entities/BunkerAssemblyScheme.h index 7146fa956c..f31a046390 100644 --- a/Source/Entities/BunkerAssemblyScheme.h +++ b/Source/Entities/BunkerAssemblyScheme.h @@ -129,11 +129,11 @@ namespace RTE { /// Gets the name of the scheme symmetric to this one. /// @return Symmetric scheme name. - std::string GetSymmetricSchemeName() const { return m_SymmetricScheme; } + const std::string& GetSymmetricSchemeName() const { return m_SymmetricScheme; } /// Gets the name of group to which assemblies linked with this scheme must be added. /// @return Assembly group name. - std::string GetAssemblyGroup() const { return m_AssemblyGroup; } + const std::string& GetAssemblyGroup() const { return m_AssemblyGroup; } /// Returns the limit of these schemes per scene. 0 - no limit. /// @return Scheme limit. diff --git a/Source/Entities/Deployment.cpp b/Source/Entities/Deployment.cpp index d98a800d2b..b79e76be79 100644 --- a/Source/Entities/Deployment.cpp +++ b/Source/Entities/Deployment.cpp @@ -50,7 +50,7 @@ int Deployment::Create() { } int Deployment::Create(std::string loadoutName, const Icon& icon, float spawnRadius) { - m_LoadoutName = loadoutName; + m_LoadoutName = std::move(loadoutName); m_Icon = icon; m_SpawnRadius = spawnRadius; m_WalkRadius = 250; diff --git a/Source/Entities/Deployment.h b/Source/Entities/Deployment.h index a3491884f6..c3b3642515 100644 --- a/Source/Entities/Deployment.h +++ b/Source/Entities/Deployment.h @@ -79,7 +79,7 @@ namespace RTE { /// Gets a bitmap showing a good identifyable icon of this. /// @return The Icon that represents this graphically. - Icon GetIcon() { return m_Icon; } + const Icon& GetIcon() { return m_Icon; } /// Gets the radius around this deployment that gets checked if another /// actor/item of the same type and name already exists and will block diff --git a/Source/Entities/HDFirearm.cpp b/Source/Entities/HDFirearm.cpp index 28e3a6a4e7..dee6346f0f 100644 --- a/Source/Entities/HDFirearm.cpp +++ b/Source/Entities/HDFirearm.cpp @@ -414,7 +414,7 @@ std::string HDFirearm::GetNextMagazineName() const { return m_pMagazineReference->GetPresetName(); } -bool HDFirearm::SetNextMagazineName(std::string magName) { +bool HDFirearm::SetNextMagazineName(const std::string& magName) { const Magazine* pNewMag = dynamic_cast(g_PresetMan.GetEntityPreset("Magazine", magName)); if (pNewMag) { m_pMagazineReference = pNewMag; diff --git a/Source/Entities/HDFirearm.h b/Source/Entities/HDFirearm.h index f6d3ec6081..6a4f6e983c 100644 --- a/Source/Entities/HDFirearm.h +++ b/Source/Entities/HDFirearm.h @@ -101,7 +101,7 @@ namespace RTE { /// this gun. This changes all future mags that will be reloaded. /// @param magName The preset name of the new Magazine to load into this from now on. /// @return Whether the specified magazine was found and successfully prepared. - bool SetNextMagazineName(std::string magName); + bool SetNextMagazineName(const std::string& magName); /// Gets the number of rounds still in the loaded magazine. Negative value /// means infinite ammo. diff --git a/Source/Entities/Icon.h b/Source/Entities/Icon.h index 06261083d3..717e8349e5 100644 --- a/Source/Entities/Icon.h +++ b/Source/Entities/Icon.h @@ -53,11 +53,11 @@ namespace RTE { /// Gets the array of 8-bit bitmaps of this Icon, as many as GetFrameCount says. Neither the array nor the BITMAPs are transferred ownership! /// @return The BITMAPs in 8bpp of this Icon. - std::vector GetBitmaps8() const { return m_BitmapsIndexed; } + const std::vector& GetBitmaps8() const { return m_BitmapsIndexed; } /// Gets the array of 32-bit bitmaps of this Icon, as many as GetFrameCount says. Neither the array nor the BITMAPs are transferred ownership! /// @return The BITMAPs in 32bpp of this Icon. - std::vector GetBitmaps32() const { return m_BitmapsTrueColor; } + const std::vector& GetBitmaps32() const { return m_BitmapsTrueColor; } #pragma endregion #pragma region Operator Overloads diff --git a/Source/Entities/LimbPath.cpp b/Source/Entities/LimbPath.cpp index 5ed8fef054..3c9fc8fd5e 100644 --- a/Source/Entities/LimbPath.cpp +++ b/Source/Entities/LimbPath.cpp @@ -172,6 +172,23 @@ Vector LimbPath::RotatePoint(const Vector& point) const { return (((point - offset) * m_Rotation) + offset) + m_PositionOffset; } +Vector LimbPath::InverseRotatePoint(const Vector& point) const { + Vector offset = (m_RotationOffset).GetXFlipped(m_HFlipped); + return (((point - m_PositionOffset) - offset) / m_Rotation) + offset; +} + +Vector LimbPath::ToLocalSpace(const Vector& position) const { + // The position might be on one side of a border of a wrapping scene while the joint is on another. + // Account for that. + Vector posWrapped = m_JointPos + g_SceneMan.ShortestDistance(m_JointPos, position); + + return InverseRotatePoint(posWrapped - m_JointPos) / GetTotalScaleMultiplier(); +} + +Vector LimbPath::ToWorldSpace(const Vector& position) const { + return m_JointPos + (RotatePoint(position * GetTotalScaleMultiplier())); +} + int LimbPath::Save(Writer& writer) const { Entity::Save(writer); @@ -199,43 +216,44 @@ void LimbPath::Destroy(bool notInherited) { Clear(); } -Vector LimbPath::GetProgressPos() { +Vector LimbPath::GetCurrentSegStartLocal() const { Vector returnVec(m_Start); - if (IsStaticPoint()) { - return m_JointPos + (RotatePoint(returnVec * GetTotalScaleMultiplier())); - } - // Add all the segments before the current one - std::deque::const_iterator itr; - for (itr = m_Segments.begin(); itr != m_CurrentSegment; ++itr) { - returnVec += *itr; - } - - // Add any from the progress made on the current one - if (itr != m_Segments.end()) { - returnVec += *m_CurrentSegment * m_SegProgress; + if (!IsStaticPoint()) { + // Add all the segments before the current one + std::deque::const_iterator itr; + for (itr = m_Segments.begin(); itr != m_CurrentSegment; ++itr) { + returnVec += *itr; + } } - return m_JointPos + (RotatePoint(returnVec * GetTotalScaleMultiplier())); + return returnVec; } -Vector LimbPath::GetCurrentSegTarget() { - Vector returnVec(m_Start); - if (IsStaticPoint()) { - return m_JointPos + (RotatePoint(returnVec * GetTotalScaleMultiplier())); +Vector LimbPath::GetProgressPos() { + Vector returnVec = GetCurrentSegStartLocal(); + + if (!IsStaticPoint()) { + if (m_CurrentSegment != m_Segments.end()) { + // Add approximation based on progress. + returnVec += *m_CurrentSegment * m_SegProgress; + } } - std::deque::const_iterator itr; + return ToWorldSpace(returnVec); +} - for (itr = m_Segments.begin(); itr != m_CurrentSegment; ++itr) { - returnVec += *itr; - } +Vector LimbPath::GetCurrentSegTarget() { + Vector returnVec = GetCurrentSegStartLocal(); - if (itr != m_Segments.end()) { - returnVec += *m_CurrentSegment; + if (!IsStaticPoint()) { + if (m_CurrentSegment != m_Segments.end()) { + // Add the current one as well. + returnVec += *m_CurrentSegment; + } } - return m_JointPos + (RotatePoint(returnVec * GetTotalScaleMultiplier())); + return ToWorldSpace(returnVec); } Vector LimbPath::GetCurrentVel(const Vector& limbPos) { @@ -292,29 +310,138 @@ void LimbPath::ReportProgress(const Vector& limbPos) { if (IsStaticPoint()) { const float staticPointEndedThreshold = 1.0F; m_Ended = g_SceneMan.ShortestDistance(limbPos, GetCurrentSegTarget()).MagnitudeIsLessThan(staticPointEndedThreshold); - } else { - // Check if we are sufficiently close to the target to start going after the next one. + } else if (m_CurrentSegment == m_Segments.end()) { + // Current path has already come to an end. Compute progress and m_Ended based on last segment's target. Vector distVec = g_SceneMan.ShortestDistance(limbPos, GetCurrentSegTarget()); - float distance = distVec.GetMagnitude(); - float segMag = (*m_CurrentSegment * GetTotalScaleMultiplier()).GetMagnitude(); + float distanceSqr = distVec.GetSqrMagnitude(); + float segMagSqr = (*m_CurrentSegment * GetTotalScaleMultiplier()).GetSqrMagnitude(); - if (distance < m_SegmentEndedThreshold) { - if (++(m_CurrentSegment) == m_Segments.end()) { - --(m_CurrentSegment); - // Get normalized progress measure toward the target. - m_SegProgress = distance > segMag ? 0.0F : (1.0F - (distance / segMag)); - m_Ended = true; + // Get normalized progress measure toward the target. + + if (distanceSqr > segMagSqr) + // We're too far away from this target. + m_SegProgress = 0.0; + else + m_SegProgress = (1.0F - (std::sqrt(distanceSqr) / std::sqrt(segMagSqr))); + + m_Ended = distVec.MagnitudeIsLessThan(m_SegmentEndedThreshold); + } else { + // Presume we're not done with all path segments until proven otherwise. + m_Ended = false; + + // Check if we are sufficiently close to the current target, or any of the next ones, + // to start going to whatever target is after that one. + // + // The limb might have been yanked and is closer to one of the future targets, so check them too. + + // This rest of the code will be working in local space, so convert input limb pos to that. + Vector limbPosLocal = ToLocalSpace(limbPos); + + + // Iterate over all segments and find one whose target is closest to the limb position. + + + // Segment positions are accumulative, so keep an accumulator. + Vector currentSegmentStartPos = GetCurrentSegStartLocal(); // Will be needed later. + Vector segmentPosAccumulator = currentSegmentStartPos; + + Vector closestSegmentStartPos; + float closestSegmentTargetDistanceSqr = std::numeric_limits::max(); + std::deque::iterator closestSegment = m_CurrentSegment; + + for (std::deque::iterator itr = m_CurrentSegment; itr != m_Segments.end(); ++itr) { + + // We want to find a closest segment to work off of, but we don't want to + // snap from collision-enabled segments to collision-disabled segments, + // because doing so tends to produce erratic foot behavior. + + // If the current segment of the limbpath is collision-enabled... + if (!FootCollisionsShouldBeDisabled()) { + // If the currently looked at segment is collision-disabled... + if (m_FootCollisionsDisabledSegment >= 0 && + m_Segments.size() - (itr - m_Segments.begin()) <= m_FootCollisionsDisabledSegment) { + + // ...Then break. + + // Note: if the first of the above two checks has passed, + // this means that the current segment is collision-enabled. + // And, since this iterator starts with it, this means that + // *at least* the current segment was picked as closest already. + // + // In other words, if this break was hit, then closest segment vars have + // been properly initialized already. Therefore, it's safe to break. + + break; + } } - // Next segment! - else { - m_SegProgress = 0.0F; + + Vector thisSegmentStartPos = segmentPosAccumulator; + segmentPosAccumulator += *itr; // The accumulator's value is now the target pos of this segment. + float thisSegmentDistanceSqr = (segmentPosAccumulator - limbPosLocal).GetSqrMagnitude(); + + if (thisSegmentDistanceSqr < closestSegmentTargetDistanceSqr) { + // This one's closer. + closestSegmentStartPos = thisSegmentStartPos; + closestSegmentTargetDistanceSqr = thisSegmentDistanceSqr; + closestSegment = itr; + } + } + + + // Branches below will determine the new current segment and write the distance to it here. + // We need this distance to compute progress towards it, whatever it ends up being. + float distanceToCurrentSegmentTargetSqr; + + if (closestSegmentTargetDistanceSqr < m_SegmentEndedThreshold * m_SegmentEndedThreshold) { + // We're sufficiently close to this segment's target to go on. + // Either declare this path ended, or continue from the next segment. + + if (closestSegment + 1 == m_Segments.end()) { + // Closest segment is the last segment and we are at its target. Declare done. + m_Ended = true; + m_CurrentSegment = closestSegment; + + distanceToCurrentSegmentTargetSqr = closestSegmentTargetDistanceSqr; + + } else { + // Time to switch to next segment! m_SegTimer.Reset(); - m_Ended = false; + + m_CurrentSegment = closestSegment + 1; + + Vector currentSegmentTarget = closestSegmentStartPos + *closestSegment + *m_CurrentSegment; + distanceToCurrentSegmentTargetSqr = (currentSegmentTarget - limbPosLocal).GetSqrMagnitude(); } } else { - m_SegProgress = distance > segMag ? 0.0F : (1.0F - (distance / segMag)); - m_Ended = false; + // We're not close enough to that closest segment's target, but we can still try to do better. + + Vector currentSegmentTargetPos = currentSegmentStartPos + *m_CurrentSegment; + float currentSegmentDistanceSqr = (currentSegmentTargetPos - limbPosLocal).GetSqrMagnitude(); + + if (closestSegmentTargetDistanceSqr < currentSegmentDistanceSqr) { + // The target for this closest segment is closer than the current segment's. + // Fast-forward to it. + m_SegTimer.Reset(); + + m_CurrentSegment = closestSegment; + + distanceToCurrentSegmentTargetSqr = closestSegmentTargetDistanceSqr; + } else { + // Just get the distance to current segment's target. + Vector currentSegmentTarget = currentSegmentStartPos + *m_CurrentSegment; + distanceToCurrentSegmentTargetSqr = (currentSegmentTarget - limbPosLocal).GetSqrMagnitude(); + } } + + // Now compute a normalized progress measure towards the current segment. + + float currentSegmentMagnitudeSqr = m_CurrentSegment->GetSqrMagnitude(); + + if (distanceToCurrentSegmentTargetSqr > currentSegmentMagnitudeSqr) + // We're too far away from this target. + m_SegProgress = 0.0; + else + m_SegProgress = (1.0F - (std::sqrt(distanceToCurrentSegmentTargetSqr) / std::sqrt(currentSegmentMagnitudeSqr))); } } @@ -343,13 +470,11 @@ float LimbPath::GetRegularProgress() const { } int LimbPath::GetCurrentSegmentNumber() const { - int progress = 0; - if (!m_Ended && !IsStaticPoint()) { - for (std::deque::const_iterator itr = m_Segments.begin(); itr != m_CurrentSegment; ++itr) { - progress++; - } + if (m_Ended || IsStaticPoint()) { + return 0; + } else { + return m_CurrentSegment - m_Segments.begin(); } - return progress; } void LimbPath::Terminate() { @@ -379,7 +504,7 @@ bool LimbPath::RestartFree(Vector& limbPos, MOID MOIDToIgnore, int ignoreTeam) { if (IsStaticPoint()) { Vector notUsed; - Vector targetPos = m_JointPos + (RotatePoint(m_Start * GetTotalScaleMultiplier())); + Vector targetPos = ToWorldSpace(m_Start); Vector beginPos = targetPos; // TODO: don't hardcode the beginpos beginPos.m_Y -= 24; @@ -397,7 +522,7 @@ bool LimbPath::RestartFree(Vector& limbPos, MOID MOIDToIgnore, int ignoreTeam) { m_CurrentSegment = m_Segments.begin(); // Find the first start segment that has an obstacle on it - int i = 0; + size_t i = 0; for (; i < m_StartSegCount; ++i) { Vector segmentStart = GetProgressPos(); ++m_CurrentSegment; @@ -517,8 +642,8 @@ void LimbPath::Draw(BITMAP* pTargetBitmap, for (std::deque::const_iterator itr = m_Segments.begin(); itr != m_Segments.end(); ++itr) { nextPoint += *itr; - Vector prevWorldPosition = m_JointPos + (RotatePoint(prevPoint * GetTotalScaleMultiplier())); - Vector nextWorldPosition = m_JointPos + (RotatePoint(nextPoint * GetTotalScaleMultiplier())); + Vector prevWorldPosition = ToWorldSpace(prevPoint) - targetPos; + Vector nextWorldPosition = ToWorldSpace(nextPoint) - targetPos; line(pTargetBitmap, prevWorldPosition.m_X, prevWorldPosition.m_Y, nextWorldPosition.m_X, nextWorldPosition.m_Y, color); Vector min(std::min(prevWorldPosition.m_X, nextWorldPosition.m_X), std::min(prevWorldPosition.m_Y, nextWorldPosition.m_Y)); @@ -528,3 +653,4 @@ void LimbPath::Draw(BITMAP* pTargetBitmap, prevPoint += *itr; } } + diff --git a/Source/Entities/LimbPath.h b/Source/Entities/LimbPath.h index 6153f43378..57e718aff9 100644 --- a/Source/Entities/LimbPath.h +++ b/Source/Entities/LimbPath.h @@ -20,7 +20,7 @@ namespace RTE { /// Public member variable, method and friend function declarations public: - // Concrete allocation and cloning definitions + /// Concrete allocation and cloning definitions EntityAllocation(LimbPath); SerializableOverrideMethods; ClassInfoGetters; @@ -83,7 +83,7 @@ namespace RTE { /// Gets the number of Vector:s the internal array of 'waypoints' or /// segments of this LimbPath. - /// @return An int with he count. + /// @return An int with the count. int GetSegCount() const { return m_Segments.size(); } /// Gets a pointer to the segment at the given index. Ownership is NOT transferred. @@ -109,7 +109,7 @@ namespace RTE { /// Gets the APPROXIMATE scene position that the limb was reported to be /// last frame. This really shouldn't be used by external clients. - /// @return A Vector with the APPROXIAMTE scene/world coordinates of the limb as + /// @return A Vector with the APPROXIMATE scene/world coordinates of the limb as /// reported last. Vector GetProgressPos(); @@ -369,75 +369,62 @@ namespace RTE { protected: static Entity::ClassInfo m_sClass; - // The starting point of the path. - Vector m_Start; + Vector m_Start; //!< The starting point of the path. - // The number of starting segments, counting into the path from its beginning, - // that upon restart of this path will be tried in reverse order till one which - // yields a starting position that is clear of terrain is found. - int m_StartSegCount; + /// The number of starting segments, counting into the path from its beginning, + /// that upon restart of this path will be tried in reverse order till one which + /// yields a starting position that is clear of terrain is found. + size_t m_StartSegCount; - // Array containing the actual 'waypoints' or segments for the path. - std::deque m_Segments; + std::deque m_Segments; //!< Array containing the actual 'waypoints' or segments for the path. - // The iterator to the segment of the path that the limb ended up on the end of + /// The iterator to the segment of the path that the limb ended up on the end of. std::deque::iterator m_CurrentSegment; - int m_FootCollisionsDisabledSegment; //!< The segment after which foot collisions will be disabled for this limbpath, if it's for legs. + /// Count of segments at the end of the segments list for which foot collisions should be disabled + /// for this limbpath, if it's for legs. + int m_FootCollisionsDisabledSegment; - // Normalized measure of how far the limb has progressed toward the - // current segment's target. 0.0 means its farther away than the - // magnitude of the entire segment. 0.5 means it's half the mag of the segment - // away from the target. + /// Normalized measure of how far the limb has progressed toward the current + /// segment's target. + /// + /// 0.0 means its farther away than the magnitude of the entire segment. + /// 0.5 means it's half the mag of the segment away from the target. float m_SegProgress; - // The constant speed that the limb traveling this path has in m/s. - float m_TravelSpeed; + float m_TravelSpeed; //!< The constant speed that the limb traveling this path has in m/s. - // How close we must get to the end of each segment to consider it finished - float m_SegmentEndedThreshold; + float m_SegmentEndedThreshold; //!< How close we must get to the end of each segment to consider it finished - // The base/current travel speed multiplier - float m_BaseTravelSpeedMultiplier; - float m_CurrentTravelSpeedMultiplier; + float m_BaseTravelSpeedMultiplier; //!< The base travel speed multiplier + float m_CurrentTravelSpeedMultiplier; //!< The current travel speed multiplier - // The base/current scale multiplier (we extend the walkpath when running fast to take longer strides) - // This is a vector to allow scaling on seperate axis + /// The base scale multiplier for both axes. Vector m_BaseScaleMultiplier; + /// The current scale multiplier for both axes. (we extend the walkpath when running fast to take longer strides) Vector m_CurrentScaleMultiplier; - // The max force that a limb travelling along this path can push. - // In kg * m/(s^2) - float m_PushForce; - - // The latest known position of the owning actor's joint in world coordinates. - Vector m_JointPos; - // The latest known velocity of the owning actor's joint in world coordinates. - Vector m_JointVel; - // The rotation applied to this walkpath. - Matrix m_Rotation; - // The point we should be rotated around, in local space. - Vector m_RotationOffset; - // The offset to apply to our walkpath position, in local space. - Vector m_PositionOffset; - - // If GetNextTimeSeg() couldn't use up all frame time because the current segment - // ended,this var stores the remainder of time that should be used to progress - // on the next segment during the same frame. + float m_PushForce; //!< The max force that a limb travelling along this path can push, in kg * m/(s^2). + + Vector m_JointPos; //!< The latest known position of the owning actor's joint in world coordinates. + Vector m_JointVel; //!< The latest known velocity of the owning actor's joint in world coordinates. + Matrix m_Rotation; //!< The rotation applied to this walkpath. + Vector m_RotationOffset; //!< The point we should be rotated around, in local space. + Vector m_PositionOffset; //!< The offset to apply to our walkpath position, in local space. + + /// If GetNextTimeSeg() couldn't use up all frame time because the current segment + /// ended, this var stores the remainder of time that should be used to progress + /// on the next segment during the same frame. float m_TimeLeft; - // Times the amount of sim time spent since the last path traversal was started - Timer m_PathTimer; - // Times the amount of sim time spent pursuing the current segment's target. - Timer m_SegTimer; + Timer m_PathTimer; //!< Records the amount of sim time spent since the last path traversal was started. + Timer m_SegTimer; //!< Records the amount of sim time spent pursuing the current segment's target. - // Total length of this LimbPath, including the alternative starting segments, in pixel units - float m_TotalLength; - // Length of this LimbPath, excluding the alternative starting segments. - float m_RegularLength; - bool m_SegmentDone; - bool m_Ended; - bool m_HFlipped; + float m_TotalLength; //!< Total length of this LimbPath, including the alternative starting segments, in pixel units + float m_RegularLength; //!< Length of this LimbPath, excluding the alternative starting segments. + bool m_SegmentDone; //!< Unused? + bool m_Ended; //!< True if this path has ended. See method `PathEnded` for more information. + bool m_HFlipped; //!< True if this path is horizontally flipped. /// Private member variable and method declarations private: @@ -449,6 +436,26 @@ namespace RTE { /// @param point The point to rotate. /// @return The rotated point. Vector RotatePoint(const Vector& point) const; + + /// Inverse of RotatePoint. + /// @param point The rotated point + /// @return The point pre-rotation. + Vector InverseRotatePoint(const Vector& point) const; + + /// Converts an input position, absolute and in scene/world space, to local space for this LimbPath, + /// taking into account rotation and scaling. + /// @param position World space position + /// @returns Local space position + Vector ToLocalSpace(const Vector& position) const; + + /// Converts an input position, in local space for this LimbPath, into scene/world space, + /// taking into account rotation and scaling. + /// @param position Local space position + /// @returns World space position + Vector ToWorldSpace(const Vector& position) const; + + /// Gets the current segment's starting position (i.e. last segment's target) in local space. + Vector GetCurrentSegStartLocal() const; }; } // namespace RTE diff --git a/Source/Entities/MOPixel.cpp b/Source/Entities/MOPixel.cpp index 534541929b..17811231e3 100644 --- a/Source/Entities/MOPixel.cpp +++ b/Source/Entities/MOPixel.cpp @@ -222,10 +222,8 @@ void MOPixel::Update() { } void MOPixel::Draw(BITMAP* targetBitmap, const Vector& targetPos, DrawMode mode, bool onlyPhysical) const { - // Don't draw color if this isn't a drawing frame - if (!g_TimerMan.DrawnSimUpdate() && mode == g_DrawColor) { - return; - } + // Note: don't skip this drawing even if it's not a drawn sim update and + // the DrawMode is g_DrawColor, because this might be a draw to a scene terrain. int drawColor = -1; diff --git a/Source/Entities/MOSParticle.h b/Source/Entities/MOSParticle.h index 045b4840af..5e1eb8739a 100644 --- a/Source/Entities/MOSParticle.h +++ b/Source/Entities/MOSParticle.h @@ -31,7 +31,7 @@ namespace RTE { /// @param lifetime The amount of time in ms this MOSParticle will exist. 0 means unlimited. /// @return An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create(ContentFile spriteFile, const int frameCount = 1, const float mass = 1, const Vector& position = Vector(0, 0), const Vector& velocity = Vector(0, 0), const unsigned long lifetime = 0) { - MOSprite::Create(spriteFile, frameCount, mass, position, velocity, lifetime); + MOSprite::Create(std::move(spriteFile), frameCount, mass, position, velocity, lifetime); return 0; } diff --git a/Source/Entities/MOSRotating.cpp b/Source/Entities/MOSRotating.cpp index 20fc63d2ff..fd036c301f 100644 --- a/Source/Entities/MOSRotating.cpp +++ b/Source/Entities/MOSRotating.cpp @@ -178,7 +178,7 @@ int MOSRotating::Create(ContentFile spriteFile, const Vector& position, const Vector& velocity, const unsigned long lifetime) { - MOSprite::Create(spriteFile, frameCount, mass, position, velocity, lifetime); + MOSprite::Create(std::move(spriteFile), frameCount, mass, position, velocity, lifetime); if (!m_pFlipBitmap && m_aSprite[0]) { m_pFlipBitmap = create_bitmap_ex(8, m_aSprite[0]->w, m_aSprite[0]->h); diff --git a/Source/Entities/MOSprite.cpp b/Source/Entities/MOSprite.cpp index ef43a25f82..7739e8d2e4 100644 --- a/Source/Entities/MOSprite.cpp +++ b/Source/Entities/MOSprite.cpp @@ -78,7 +78,7 @@ int MOSprite::Create(ContentFile spriteFile, const unsigned long lifetime) { MovableObject::Create(mass, position, velocity, 0, 0, lifetime); - m_SpriteFile = spriteFile; + m_SpriteFile = std::move(spriteFile); m_FrameCount = frameCount; m_aSprite.clear(); m_SpriteFile.GetAsAnimation(m_aSprite, m_FrameCount); @@ -180,18 +180,18 @@ int MOSprite::ReadProperty(const std::string_view& propName, Reader& reader) { EndPropertyList; } -void MOSprite::SetEntryWound(std::string presetName, std::string moduleName) { +void MOSprite::SetEntryWound(const std::string& presetName, std::string moduleName) { if (presetName == "") m_pEntryWound = 0; else - m_pEntryWound = dynamic_cast(g_PresetMan.GetEntityPreset("AEmitter", presetName, moduleName)); + m_pEntryWound = dynamic_cast(g_PresetMan.GetEntityPreset("AEmitter", presetName, std::move(moduleName))); } -void MOSprite::SetExitWound(std::string presetName, std::string moduleName) { +void MOSprite::SetExitWound(const std::string& presetName, std::string moduleName) { if (presetName == "") m_pExitWound = 0; else - m_pExitWound = dynamic_cast(g_PresetMan.GetEntityPreset("AEmitter", presetName, moduleName)); + m_pExitWound = dynamic_cast(g_PresetMan.GetEntityPreset("AEmitter", presetName, std::move(moduleName))); } std::string MOSprite::GetEntryWoundPresetName() const { diff --git a/Source/Entities/MOSprite.h b/Source/Entities/MOSprite.h index d4b2715f2c..02264dd323 100644 --- a/Source/Entities/MOSprite.h +++ b/Source/Entities/MOSprite.h @@ -305,11 +305,11 @@ namespace RTE { /// Sets entry wound emitter for this MOSprite /// @param presetName Emitter preset name and module name - void SetEntryWound(std::string presetName, std::string moduleName); + void SetEntryWound(const std::string& presetName, std::string moduleName); /// Sets exit wound emitter for this MOSprite /// @param presetName Emitter preset name and module name - void SetExitWound(std::string presetName, std::string moduleName); + void SetExitWound(const std::string& presetName, std::string moduleName); /// Returns entry wound emitter preset name for this MOSprite /// @return Wound emitter preset name diff --git a/Source/Entities/MetaPlayer.h b/Source/Entities/MetaPlayer.h index ae8da008c7..a741889c2c 100644 --- a/Source/Entities/MetaPlayer.h +++ b/Source/Entities/MetaPlayer.h @@ -54,11 +54,11 @@ namespace RTE { #pragma region Getters and Setters /// Gets the name of the MetaPlayer. /// @return The name of the player. - std::string GetName() const { return m_Name; } + const std::string& GetName() const { return m_Name; } /// Sets the name of the MetaPlayer. /// @param newName The new name to set. - void SetName(std::string newName) { m_Name = newName; } + void SetName(std::string newName) { m_Name = std::move(newName); } /// Gets the Team of this MetaPlayer. /// @return The Team of this player. @@ -107,11 +107,11 @@ namespace RTE { /// Gets the name of the scene this MetaPlayer is targeting for offensive. /// @return The name of the Scene this MetaPlayer is targeting. - std::string GetOffensiveTargetName() const { return m_OffensiveTarget; } + const std::string& GetOffensiveTargetName() const { return m_OffensiveTarget; } /// Sets the name of the scene this MetaPlayer is targeting for offensive. /// @param targetName The name of the Scene this MetaPlayer is targeting. - void SetOffensiveTargetName(std::string targetName) { m_OffensiveTarget = targetName; } + void SetOffensiveTargetName(std::string targetName) { m_OffensiveTarget = std::move(targetName); } #pragma endregion #pragma region Funds and Costs diff --git a/Source/Entities/MetaSave.cpp b/Source/Entities/MetaSave.cpp index cde45f2bb2..095056ab17 100644 --- a/Source/Entities/MetaSave.cpp +++ b/Source/Entities/MetaSave.cpp @@ -31,7 +31,7 @@ int MetaSave::Create(std::string savePath) { g_ConsoleMan.PrintString("ERROR: Tried to save a Metagame that isn't in progress!?"); return -1; } - m_SavePath = savePath; + m_SavePath = std::move(savePath); m_PlayerCount = g_MetaMan.m_Players.size(); m_Difficulty = g_MetaMan.m_Difficulty; diff --git a/Source/Entities/MetaSave.h b/Source/Entities/MetaSave.h index e3a32d6f21..2508be5438 100644 --- a/Source/Entities/MetaSave.h +++ b/Source/Entities/MetaSave.h @@ -44,7 +44,7 @@ namespace RTE { #pragma region Getters /// Gets the full path to the ini file that stores the state of the MetaMan this is associated with. /// @return The path to the ini with the MetaMan state info. - std::string GetSavePath() const { return m_SavePath; } + const std::string& GetSavePath() const { return m_SavePath; } /// Gets the total number of players this game has (including AIs). /// @return The player count. diff --git a/Source/Entities/MovableObject.cpp b/Source/Entities/MovableObject.cpp index 36b2e9cc44..a8190cc418 100644 --- a/Source/Entities/MovableObject.cpp +++ b/Source/Entities/MovableObject.cpp @@ -1100,7 +1100,7 @@ bool MovableObject::DrawToTerrain(SLTerrain* terrain) { } }; BITMAP* tempBitmap = g_SceneMan.GetIntermediateBitmapForSettlingIntoTerrain(static_cast(GetDiameter())); - Vector tempBitmapPos = m_Pos.GetFloored() - Vector(static_cast(tempBitmap->w / 2), static_cast(tempBitmap->w / 2)); + Vector tempBitmapPos = m_Pos.GetFloored() - Vector(static_cast(tempBitmap->w) / 2, static_cast(tempBitmap->w) / 2); clear_bitmap(tempBitmap); // Draw the object to the temp bitmap, then draw the foreground layer on top of it, then draw it to the foreground layer. diff --git a/Source/Entities/MovableObject.h b/Source/Entities/MovableObject.h index 60dd5b94a2..b1c7599c78 100644 --- a/Source/Entities/MovableObject.h +++ b/Source/Entities/MovableObject.h @@ -391,7 +391,7 @@ namespace RTE { /// Gets the file path of this MovableObject's current screen effect. /// @param pathToFile A string containing the file path of the new screen effect. - void SetScreenEffectPath(std::string pathToFile) { + void SetScreenEffectPath(std::string& pathToFile) { m_ScreenEffectFile.SetDataPath(pathToFile); m_pScreenEffect = m_ScreenEffectFile.GetAsBitmap(); m_ScreenEffectHash = m_ScreenEffectFile.GetHash(); @@ -1302,7 +1302,7 @@ namespace RTE { // Unique ID of particle hit this MO long int m_ParticleUniqueIDHit; // Number of sim update frame when last collision was detected - int m_LastCollisionSimFrameNumber; + unsigned int m_LastCollisionSimFrameNumber; int m_SimUpdatesBetweenScriptedUpdates; //!< The number of Sim updates between each scripted update for this MovableObject. int m_SimUpdatesSinceLastScriptedUpdate; //!< The counter for the current number of Sim updates since this MovableObject last ran a scripted update. diff --git a/Source/Entities/PEmitter.cpp b/Source/Entities/PEmitter.cpp index 1734c56744..13141a80b1 100644 --- a/Source/Entities/PEmitter.cpp +++ b/Source/Entities/PEmitter.cpp @@ -232,26 +232,28 @@ float PEmitter::EstimateImpulse(bool burst) { for (Emission* emission: m_EmissionList) { // Only check emissions that push the emitter if (emission->PushesEmitter()) { - // Todo... we're not checking emission start/stop times here, so this will always calculate the impulse as if the emission was active. + // TODO: we're not checking emission start/stop times here, so this will always calculate the impulse as if the emission was active. // There's not really an easy way to do this, since the emission rate is not necessarily constant over time. - float emissions = (emission->GetRate() / 60.0f) * g_TimerMan.GetDeltaTimeSecs(); + float emissionsPerFrame = (emission->GetRate() / 60.0f) * g_TimerMan.GetDeltaTimeSecs(); float scale = 1.0F; + + // Get all the particles emitted this frame + emissionsPerFrame *= emission->GetParticleCount(); + + // When bursting, add on all the bursted emissions + // We also use m_BurstScale on ALL emissions, not just the extra bursted ones + // This is a bit funky but consistent with the code that applies the impulse if (burst) { - emissions *= emission->GetBurstSize(); + emissionsPerFrame += emission->GetBurstSize(); scale = m_BurstScale; } - if (emissions > 0) { - int extraEmissions = emission->GetParticleCount() - 1; - emissions += extraEmissions; - } - float velMin = emission->GetMinVelocity() * scale; float velRange = (emission->GetMaxVelocity() - emission->GetMinVelocity()) * scale * 0.5f; float spread = (std::max(static_cast(c_PI) - (emission->GetSpread() * scale), 0.0F) / c_PI); // A large spread will cause the forces to cancel eachother out // Add to accumulative recoil impulse generated, F = m * a. - impulse += (velMin + velRange) * spread * emission->m_pEmission->GetMass() * emissions; + impulse += (velMin + velRange) * spread * emission->m_pEmission->GetMass() * emissionsPerFrame; } } @@ -320,7 +322,7 @@ void PEmitter::Update() { else m_BurstTriggered = false; - int emissions = 0; + int emissionCountTotal = 0; float velMin, velRange, spread; double currentPPM, SPE; MovableObject* pParticle = 0; @@ -331,7 +333,7 @@ void PEmitter::Update() { if (emission->IsEmissionTime()) { // Apply the throttle factor to the emission rate currentPPM = emission->GetRate() * throttleFactor; - emissions = 0; + int emissionCount = 0; // Only do all this if the PPM is acutally above zero if (currentPPM > 0) { @@ -342,25 +344,32 @@ void PEmitter::Update() { emission->m_Accumulator += m_LastEmitTmr.GetElapsedSimTimeS(); // Now figure how many full emissions can fit in the current accumulator - emissions = std::floor(emission->m_Accumulator / SPE); + emissionCount = std::floor(emission->m_Accumulator / SPE); // Deduct the about to be emitted emissions from the accumulator - emission->m_Accumulator -= emissions * SPE; + emission->m_Accumulator -= emissionCount * SPE; RTEAssert(emission->m_Accumulator >= 0, "Emission accumulator negative!"); } + float scale = 1.0F; // Add extra emissions if bursting. - if (m_BurstTriggered) - emissions += emission->GetBurstSize() * std::floor(throttleFactor); + if (m_BurstTriggered) { + emissionCount += emission->GetBurstSize(); + scale = m_BurstScale; + } + + // We don't consider extra particles for our emission count, so add prior to multiply + emissionCountTotal += emissionCount; + emissionCount *= emission->GetParticleCount(); pParticle = 0; emitVel.Reset(); parentVel = pRootParent->GetVel() * emission->InheritsVelocity(); - for (int i = 0; i < emissions; ++i) { - velMin = emission->GetMinVelocity() * (m_BurstTriggered ? m_BurstScale : 1.0); - velRange = emission->GetMaxVelocity() - emission->GetMinVelocity() * (m_BurstTriggered ? m_BurstScale : 1.0); - spread = emission->GetSpread() * (m_BurstTriggered ? m_BurstScale : 1.0); + for (int i = 0; i < emissionCount; ++i) { + velMin = emission->GetMinVelocity() * scale; + velRange = emission->GetMaxVelocity() - emission->GetMinVelocity() * scale; + spread = emission->GetSpread() * scale; // Make a copy after the reference particle pParticle = dynamic_cast(emission->GetEmissionParticlePreset()->Clone()); // Set up its position and velocity according to the parameters of this. @@ -405,7 +414,7 @@ void PEmitter::Update() { m_LastEmitTmr.Reset(); // Count the total emissions since enabling, and stop emitting if beyong limit (and limit is also enabled) - m_EmitCount += emissions; + m_EmitCount += emissionCountTotal; if (m_EmitCountLimit > 0 && m_EmitCount > m_EmitCountLimit) EnableEmission(false); diff --git a/Source/Entities/PieMenu.cpp b/Source/Entities/PieMenu.cpp index 44c6472e35..7fa69610dd 100644 --- a/Source/Entities/PieMenu.cpp +++ b/Source/Entities/PieMenu.cpp @@ -14,6 +14,8 @@ #include "GUIFont.h" #include "AllegroBitmap.h" +#include + using namespace RTE; ConcreteClassInfo(PieMenu, Entity, 20); @@ -1212,6 +1214,11 @@ bool PieMenu::SetHoveredPieSlice(const PieSlice* pieSliceToSelect, bool moveCurs return false; } + if (m_ActiveSubPieMenu) { + m_ActiveSubPieMenu->SetEnabled(false, false); + m_ActiveSubPieMenu = nullptr; + } + m_HoveredPieSlice = pieSliceToSelect; m_SubPieMenuHoverOpenTimer.Reset(); m_BGBitmapNeedsRedrawing = true; diff --git a/Source/Entities/Scene.cpp b/Source/Entities/Scene.cpp index 90ef1f84a0..3c08ece911 100644 --- a/Source/Entities/Scene.cpp +++ b/Source/Entities/Scene.cpp @@ -815,7 +815,7 @@ int Scene::ExpandAIPlanAssemblySchemes() { return 0; } -int Scene::SaveData(std::string pathBase) { +int Scene::SaveData(const std::string& pathBase) { const std::string fullPathBase = g_PresetMan.GetFullModulePath(pathBase); if (fullPathBase.empty()) return -1; diff --git a/Source/Entities/Scene.h b/Source/Entities/Scene.h index 8ff79af15b..33ffcd467b 100644 --- a/Source/Entities/Scene.h +++ b/Source/Entities/Scene.h @@ -67,7 +67,7 @@ namespace RTE { } Area(std::string name) { Clear(); - m_Name = name; + m_Name = std::move(name); Create(); } Area(const Area& reference) { @@ -164,7 +164,7 @@ namespace RTE { /// Gets the name of the Area /// @return The name used to ID this Area. - std::string GetName() const { return m_Name; } + const std::string& GetName() const { return m_Name; } /// Protected member variable and method declarations protected: @@ -244,7 +244,7 @@ namespace RTE { /// everything up to the extension. "FG" and "Mat" etc will be added. /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int SaveData(std::string pathBase); + int SaveData(const std::string& pathBase); // Gets copied bitmaps of our scene layers, for saving. // @return A list of SceneLayerInfo including our name and a copied bitmap. @@ -549,7 +549,7 @@ namespace RTE { /// Returns parent scene name of this metascene. /// @return Name of a parent scene. - std::string GetMetasceneParent() const { return m_MetasceneParent; } + const std::string& GetMetasceneParent() const { return m_MetasceneParent; } /// Sets the specified location of this Scene in the scene /// @param newLocation A Vector with the desired location of this Scene in the scene. diff --git a/Source/Entities/SoundSet.cpp b/Source/Entities/SoundSet.cpp index a931c93477..7820637b04 100644 --- a/Source/Entities/SoundSet.cpp +++ b/Source/Entities/SoundSet.cpp @@ -32,7 +32,7 @@ int SoundSet::Create(const SoundSet& reference) { m_SoundSelectionCycleMode = reference.m_SoundSelectionCycleMode; m_CurrentSelection = reference.m_CurrentSelection; for (SoundData referenceSoundData: reference.m_SoundData) { - m_SoundData.push_back(referenceSoundData); + m_SoundData.push_back(std::move(referenceSoundData)); } for (const SoundSet* referenceSoundSet: reference.m_SubSoundSets) { SoundSet* soundSet = new SoundSet(*referenceSoundSet); diff --git a/Source/Entities/TerrainObject.cpp b/Source/Entities/TerrainObject.cpp index a2ac8b8173..d782348927 100644 --- a/Source/Entities/TerrainObject.cpp +++ b/Source/Entities/TerrainObject.cpp @@ -4,6 +4,8 @@ #include "Draw.h" #include "FrameMan.h" +#include + using namespace RTE; ConcreteClassInfo(TerrainObject, SceneObject, 0); diff --git a/Source/GUI/GUIBanner.cpp b/Source/GUI/GUIBanner.cpp index d0b435c66f..eefb7fbbbf 100644 --- a/Source/GUI/GUIBanner.cpp +++ b/Source/GUI/GUIBanner.cpp @@ -40,7 +40,7 @@ bool GUIBanner::Create(const std::string fontFilePath, const std::string fontBlu int y, dotColor; for (int mode = REGULAR; mode < FONTMODECOUNT; ++mode) { // Load the font images - fontFile.SetDataPath(filePaths[mode].c_str()); + fontFile.SetDataPath(filePaths[mode]); m_pFontImage[mode] = fontFile.GetAsBitmap(bitDepth == 8 ? COLORCONV_REDUCE_TO_256 : COLORCONV_8_TO_32); RTEAssert(m_pFontImage[mode], "Couldn't load font bitmap for banner font from this file:\n" + fontFilePath); @@ -345,7 +345,7 @@ void GUIBanner::Draw(BITMAP* pTargetBitmap) { } } -int GUIBanner::CalculateWidth(const std::string text, FontMode mode) const { +int GUIBanner::CalculateWidth(const std::string& text, FontMode mode) const { unsigned char c; int Width = 0; diff --git a/Source/GUI/GUIBanner.h b/Source/GUI/GUIBanner.h index 56b0f74750..1d4144c2d7 100644 --- a/Source/GUI/GUIBanner.h +++ b/Source/GUI/GUIBanner.h @@ -84,7 +84,7 @@ namespace RTE { /// Gets the currently displayed text string. /// @return The currently displayed text string. - std::string GetBannerText() const { return m_BannerText; } + const std::string& GetBannerText() const { return m_BannerText; } /// Gets the current state of the overall animation of this banner. /// @return The current state of the animation. @@ -96,7 +96,7 @@ namespace RTE { /// Calculates the width of a piece of text. /// @param Text Text. - int CalculateWidth(const std::string Text, FontMode mode) const; + int CalculateWidth(const std::string& Text, FontMode mode) const; /// Calculates the width of a piece of text. /// @param Character Character. diff --git a/Source/GUI/GUIButton.cpp b/Source/GUI/GUIButton.cpp index 8b48e88c6e..e8fcaaafde 100644 --- a/Source/GUI/GUIButton.cpp +++ b/Source/GUI/GUIButton.cpp @@ -6,15 +6,17 @@ using namespace RTE; GUIButton::GUIButton(GUIManager* Manager, GUIControlManager* ControlManager) : - GUIControl(), GUIPanel(Manager) { - m_ControlID = "BUTTON"; - m_DrawBitmap = nullptr; + GUIControl(), + GUIPanel(Manager), + m_DrawBitmap(nullptr), + m_Pushed(false), + m_Over(false), + m_Text(nullptr), + m_Icon(nullptr), + m_BorderSizes(nullptr) { + m_ControlManager = ControlManager; - m_Pushed = false; - m_Over = false; - m_Text = nullptr; - m_Icon = nullptr; - m_BorderSizes = nullptr; + m_ControlID = "BUTTON"; } void GUIButton::Create(const std::string& Name, int X, int Y, int Width, int Height) { diff --git a/Source/GUI/GUICheckbox.cpp b/Source/GUI/GUICheckbox.cpp index 0fd5c850ac..c4692ab860 100644 --- a/Source/GUI/GUICheckbox.cpp +++ b/Source/GUI/GUICheckbox.cpp @@ -241,7 +241,7 @@ void GUICheckbox::SetText(const std::string& Text) { m_Text = Text; } -std::string GUICheckbox::GetText() const { +const std::string& GUICheckbox::GetText() const { return m_Text; } diff --git a/Source/GUI/GUICheckbox.h b/Source/GUI/GUICheckbox.h index 50d01f37c1..7544fb5b36 100644 --- a/Source/GUI/GUICheckbox.h +++ b/Source/GUI/GUICheckbox.h @@ -87,7 +87,7 @@ namespace RTE { void SetText(const std::string& Text); /// Gets the text. - std::string GetText() const; + const std::string& GetText() const; /// Sets the check state. /// @param Check Check state. diff --git a/Source/GUI/GUIControl.cpp b/Source/GUI/GUIControl.cpp index b7690df3fa..d91fbbe82f 100644 --- a/Source/GUI/GUIControl.cpp +++ b/Source/GUI/GUIControl.cpp @@ -57,7 +57,7 @@ std::string GUIControl::GetToolTip() { return tip; } -std::string GUIControl::GetID() const { +const std::string& GUIControl::GetID() const { return m_ControlID; } @@ -259,7 +259,7 @@ bool GUIControl::IsContainer() { return m_IsContainer; } -void GUIControl::RemoveChild(const std::string Name) { +void GUIControl::RemoveChild(const std::string& Name) { // Note: We do NOT free the children because they are still linked in through their panels. This merely removes the control from the list. // This will cause a small memory leak, but this is only designed for the GUI Editor and is a bit of a hack. std::vector::iterator it; diff --git a/Source/GUI/GUIControl.h b/Source/GUI/GUIControl.h index fb90e05200..2c0c06055f 100644 --- a/Source/GUI/GUIControl.h +++ b/Source/GUI/GUIControl.h @@ -57,7 +57,7 @@ namespace RTE { std::string GetToolTip(); /// Returns a string representing the control's ID - std::string GetID() const; + const std::string& GetID() const; /// Returns the anchor flags. int GetAnchor(); @@ -122,7 +122,7 @@ namespace RTE { /// Removes a child based on name. /// @param Name Child Name. - void RemoveChild(const std::string Name); + void RemoveChild(const std::string& Name); /// Removes all the children. void RemoveChildren(); diff --git a/Source/GUI/GUIControlManager.cpp b/Source/GUI/GUIControlManager.cpp index 70ac52b917..35f73e6dcf 100644 --- a/Source/GUI/GUIControlManager.cpp +++ b/Source/GUI/GUIControlManager.cpp @@ -378,7 +378,7 @@ bool GUIControlManager::Save(GUIWriter* W) { bool GUIControlManager::Load(const std::string& Filename, bool keepOld) { GUIReader reader; const std::string pathFile = g_PresetMan.GetFullModulePath(Filename); - if (reader.Create(pathFile.c_str()) != 0) { + if (reader.Create(pathFile) != 0) { return false; } diff --git a/Source/GUI/GUIFont.cpp b/Source/GUI/GUIFont.cpp index 717afd4e74..ba416fed6a 100644 --- a/Source/GUI/GUIFont.cpp +++ b/Source/GUI/GUIFont.cpp @@ -4,20 +4,19 @@ using namespace RTE; -GUIFont::GUIFont(const std::string& Name) { - m_Screen = nullptr; - m_Font = nullptr; - m_FontHeight = 0; - m_Name = Name; - m_Kerning = 0; - m_Leading = 0; - m_ColorCache.clear(); +GUIFont::GUIFont(const std::string& Name) : + m_Font(nullptr), + m_Screen(nullptr), + m_FontHeight(0), + m_MainColor(15), + m_CurrentColor(m_MainColor), + m_CurrentBitmap(nullptr), + m_Name(Name), // Color index of the main font color + m_CharIndexCap(256), + m_Kerning(0), + m_Leading(0) { - m_MainColor = 15; // Color index of the main font color - m_CurrentColor = m_MainColor; - m_CurrentBitmap = nullptr; - - m_CharIndexCap = 256; + m_ColorCache.clear(); } bool GUIFont::Load(GUIScreen* Screen, const std::string& Filename) { diff --git a/Source/GUI/GUILabel.cpp b/Source/GUI/GUILabel.cpp index 92a7500581..5ab19a1df5 100644 --- a/Source/GUI/GUILabel.cpp +++ b/Source/GUI/GUILabel.cpp @@ -4,18 +4,20 @@ using namespace RTE; GUILabel::GUILabel(GUIManager* Manager, GUIControlManager* ControlManager) : - GUIControl(), GUIPanel(Manager) { + GUIControl(), + GUIPanel(Manager), + m_Text(""), + m_HAlignment(GUIFont::Left), + m_VAlignment(GUIFont::Middle), + m_HorizontalOverflowScroll(false), + m_VerticalOverflowScroll(false), + m_OverflowScrollState(OverflowScrollState::Deactivated), + m_OverflowScrollTimer(Timer()) { + m_ControlID = "LABEL"; m_ControlManager = ControlManager; m_Font = nullptr; m_FontColor = 0; - m_Text = ""; - m_HAlignment = GUIFont::Left; - m_VAlignment = GUIFont::Middle; - m_HorizontalOverflowScroll = false; - m_VerticalOverflowScroll = false; - m_OverflowScrollState = OverflowScrollState::Deactivated; - m_OverflowScrollTimer = Timer(); } void GUILabel::Create(const std::string& Name, int X, int Y, int Width, int Height) { diff --git a/Source/GUI/GUIProperties.cpp b/Source/GUI/GUIProperties.cpp index 493ee37d0c..4414dc65da 100644 --- a/Source/GUI/GUIProperties.cpp +++ b/Source/GUI/GUIProperties.cpp @@ -4,13 +4,15 @@ using namespace RTE; -GUIProperties::GUIProperties(const std::string& Name) { - m_Name = Name; +GUIProperties::GUIProperties(std::string Name) : + m_Name(std::move(Name)) { + m_VariableList.clear(); } -GUIProperties::GUIProperties() { - m_Name = ""; +GUIProperties::GUIProperties() : + m_Name("") { + m_VariableList.clear(); } @@ -234,7 +236,7 @@ bool GUIProperties::GetValue(const std::string& Variable, bool* Value) { return true; } -std::string GUIProperties::GetName() const { +const std::string& GUIProperties::GetName() const { return m_Name; } diff --git a/Source/GUI/GUIProperties.h b/Source/GUI/GUIProperties.h index 33642b7ec8..1a1c2e6cce 100644 --- a/Source/GUI/GUIProperties.h +++ b/Source/GUI/GUIProperties.h @@ -9,7 +9,7 @@ namespace RTE { /// Constructor method used to instantiate a GUIProperties object in /// system memory. /// @param Name Name of section. - explicit GUIProperties(const std::string& Name); + explicit GUIProperties(std::string Name); /// Constructor method used to instantiate a GUIProperties object in /// system memory. @@ -79,7 +79,7 @@ namespace RTE { bool GetValue(const std::string& Variable, bool* Value); /// Gets the property name - std::string GetName() const; + const std::string& GetName() const; /// Converts the properties to a string std::string ToString(); diff --git a/Source/GUI/GUIRadioButton.cpp b/Source/GUI/GUIRadioButton.cpp index 22d897e6d7..cbd9d9cbff 100644 --- a/Source/GUI/GUIRadioButton.cpp +++ b/Source/GUI/GUIRadioButton.cpp @@ -4,15 +4,17 @@ using namespace RTE; GUIRadioButton::GUIRadioButton(GUIManager* Manager, GUIControlManager* ControlManager) : - GUIControl(), GUIPanel(Manager) { + GUIControl(), + GUIPanel(Manager), + m_Image(nullptr), + m_Checked(false), + m_Mouseover(false), + m_Text("") { + m_ControlID = "RADIOBUTTON"; - m_Image = nullptr; m_ControlManager = ControlManager; - m_Checked = false; m_Font = 0; - m_Mouseover = false; m_FontColor = 0; - m_Text = ""; } void GUIRadioButton::Create(const std::string& Name, int X, int Y, int Width, int Height) { @@ -270,7 +272,7 @@ void GUIRadioButton::SetText(const std::string& Text) { m_Text = Text; } -std::string GUIRadioButton::GetText() const { +const std::string& GUIRadioButton::GetText() const { return m_Text; } diff --git a/Source/GUI/GUIRadioButton.h b/Source/GUI/GUIRadioButton.h index 7b9eb5532f..6c725ba5ca 100644 --- a/Source/GUI/GUIRadioButton.h +++ b/Source/GUI/GUIRadioButton.h @@ -84,7 +84,7 @@ namespace RTE { void SetText(const std::string& Text); /// Gets the text. - std::string GetText() const; + const std::string& GetText() const; /// Applies new properties to the control. /// @param Props GUIProperties. diff --git a/Source/GUI/GUIReader.cpp b/Source/GUI/GUIReader.cpp index 3c504b04f9..e871e8c006 100644 --- a/Source/GUI/GUIReader.cpp +++ b/Source/GUI/GUIReader.cpp @@ -42,7 +42,7 @@ std::istream* GUIReader::GetStream() const { return m_Stream.get(); } -std::string GUIReader::GetCurrentFilePath() const { +const std::string& GUIReader::GetCurrentFilePath() const { return m_FilePath; } diff --git a/Source/GUI/GUIReader.h b/Source/GUI/GUIReader.h index 8673572bc0..7780656b33 100644 --- a/Source/GUI/GUIReader.h +++ b/Source/GUI/GUIReader.h @@ -25,7 +25,7 @@ namespace RTE { /// Gets the path of the current file this reader is reading from. /// @return A string with the path, relative from the working directory. - std::string GetCurrentFilePath() const; + const std::string& GetCurrentFilePath() const; /// Gets the line of the current file line this reader is reading from. /// @return A string with the line number that will be read from next. diff --git a/Source/GUI/GUITab.cpp b/Source/GUI/GUITab.cpp index 83e1c93073..0b0098d599 100644 --- a/Source/GUI/GUITab.cpp +++ b/Source/GUI/GUITab.cpp @@ -4,15 +4,17 @@ using namespace RTE; GUITab::GUITab(GUIManager* Manager, GUIControlManager* ControlManager) : - GUIControl(), GUIPanel(Manager) { + GUIControl(), + GUIPanel(Manager), + m_Image(nullptr), + m_Selected(false), + m_Mouseover(false), + m_Text("") { + m_ControlID = "TAB"; - m_Image = nullptr; m_ControlManager = ControlManager; - m_Selected = false; m_Font = nullptr; - m_Mouseover = false; m_FontColor = 0; - m_Text = ""; } void GUITab::Create(const std::string& Name, int X, int Y, int Width, int Height) { @@ -272,7 +274,7 @@ void GUITab::SetText(const std::string& Text) { m_Text = Text; } -std::string GUITab::GetText() const { +const std::string& GUITab::GetText() const { return m_Text; } diff --git a/Source/GUI/GUITab.h b/Source/GUI/GUITab.h index 49538d3a5c..899bd30d48 100644 --- a/Source/GUI/GUITab.h +++ b/Source/GUI/GUITab.h @@ -85,7 +85,7 @@ namespace RTE { void SetText(const std::string& Text); /// Gets the text. - std::string GetText() const; + const std::string& GetText() const; /// Applies new properties to the control. /// @param Props GUIProperties. diff --git a/Source/GUI/GUITextPanel.cpp b/Source/GUI/GUITextPanel.cpp index 7f732a540b..f10a09c9fe 100644 --- a/Source/GUI/GUITextPanel.cpp +++ b/Source/GUI/GUITextPanel.cpp @@ -30,26 +30,25 @@ GUITextPanel::GUITextPanel(GUIManager* Manager) : // TODO: Both constructors use a common clear function?? Same with other panels GUITextPanel::GUITextPanel() : - GUIPanel() { + GUIPanel(), + m_FontSelectColor(0), + m_Text(""), + m_Locked(false), + m_WidthMargin(3), + m_HeightMargin(0), + m_CursorX(m_CursorY = 0), + m_CursorIndex(0), + m_StartIndex(0), + m_GotSelection(false), + m_SelectedColorIndex(0), + m_MaxTextLength(0), + m_NumericOnly(false), + m_MaxNumericValue(0) { + m_Font = nullptr; - m_Text = ""; - m_CursorX = m_CursorY = 0; - m_CursorIndex = 0; m_CursorColor = 0; - m_BlinkTimer.Reset(); - m_FontColor = 0; - m_FontSelectColor = 0; - m_StartIndex = 0; - m_GotSelection = false; - m_SelectedColorIndex = 0; - m_Locked = false; - m_WidthMargin = 3; - m_HeightMargin = 0; - - m_MaxTextLength = 0; - m_NumericOnly = false; - m_MaxNumericValue = 0; + m_BlinkTimer.Reset(); } void GUITextPanel::Create(int X, int Y, int Width, int Height) { diff --git a/Source/GUI/GUITextPanel.h b/Source/GUI/GUITextPanel.h index 9e9e7664b5..ec4e4f080f 100644 --- a/Source/GUI/GUITextPanel.h +++ b/Source/GUI/GUITextPanel.h @@ -71,10 +71,10 @@ namespace RTE { void SetRightText(const std::string& rightText); /// Gets the text in the textpanel. - std::string GetText() const { return m_Text; } + const std::string& GetText() const { return m_Text; } /// Gets the extra text which appears right-justified in the textpanel. - std::string GetRightText() const { return m_RightText; } + const std::string& GetRightText() const { return m_RightText; } /// Sets the start and end indexes of the selection text. /// @param Start Start, End. diff --git a/Source/GUI/GUIWriter.cpp b/Source/GUI/GUIWriter.cpp index 9f6d54fa73..b7cc5ed2cb 100644 --- a/Source/GUI/GUIWriter.cpp +++ b/Source/GUI/GUIWriter.cpp @@ -32,15 +32,15 @@ int GUIWriter::Create(const std::string& fileName, bool append) { return 0; } -std::string GUIWriter::GetFilePath() const { +const std::string& GUIWriter::GetFilePath() const { return m_FilePath; } -std::string GUIWriter::GetFileName() const { +const std::string& GUIWriter::GetFileName() const { return m_FileName; } -std::string GUIWriter::GetFolderPath() const { +const std::string& GUIWriter::GetFolderPath() const { return m_FolderPath; } diff --git a/Source/GUI/GUIWriter.h b/Source/GUI/GUIWriter.h index a7c1cef631..5d32237ee5 100644 --- a/Source/GUI/GUIWriter.h +++ b/Source/GUI/GUIWriter.h @@ -24,15 +24,15 @@ namespace RTE { #pragma region Getters /// Gets the path to the file being written. /// @return The full path to the file being written. - std::string GetFilePath() const; + const std::string& GetFilePath() const; /// Gets the name (without path) of the file being written. /// @return The name of file being written. - std::string GetFileName() const; + const std::string& GetFileName() const; /// Gets the folder path (without filename) to where the file is being written. /// @return The name of folder being written in. - std::string GetFolderPath() const; + const std::string& GetFolderPath() const; #pragma endregion #pragma region Writing Operations diff --git a/Source/GUI/Wrappers/AllegroScreen.cpp b/Source/GUI/Wrappers/AllegroScreen.cpp index a18e92f567..a501ef94fd 100644 --- a/Source/GUI/Wrappers/AllegroScreen.cpp +++ b/Source/GUI/Wrappers/AllegroScreen.cpp @@ -5,9 +5,9 @@ using namespace RTE; -AllegroScreen::AllegroScreen(BITMAP* backBuffer) { - m_BackBufferBitmap = std::make_unique(backBuffer); -} +AllegroScreen::AllegroScreen(BITMAP* backBuffer) : + m_BackBufferBitmap(std::make_unique(backBuffer)) +{} AllegroScreen::~AllegroScreen() { Destroy(); diff --git a/Source/GUI/Wrappers/GUIInputWrapper.cpp b/Source/GUI/Wrappers/GUIInputWrapper.cpp index 2faf180e97..c59dab8f0d 100644 --- a/Source/GUI/Wrappers/GUIInputWrapper.cpp +++ b/Source/GUI/Wrappers/GUIInputWrapper.cpp @@ -11,9 +11,10 @@ using namespace RTE; GUIInputWrapper::GUIInputWrapper(int whichPlayer, bool keyJoyMouseCursor) : - GUIInput(whichPlayer, keyJoyMouseCursor) { - m_KeyTimer = std::make_unique(); - m_CursorAccelTimer = std::make_unique(); + GUIInput(whichPlayer, keyJoyMouseCursor), + m_KeyTimer(std::make_unique()), + m_CursorAccelTimer(std::make_unique()) + { memset(m_KeyboardBuffer, 0, sizeof(uint8_t) * GUIInput::Constants::KEYBOARD_BUFFER_SIZE); memset(m_ScanCodeState, 0, sizeof(uint8_t) * GUIInput::Constants::KEYBOARD_BUFFER_SIZE); @@ -179,4 +180,6 @@ void GUIInputWrapper::UpdateKeyJoyMouseInput(float keyElapsedTime) { m_MouseButtonsStates[0] = GUIInput::Up; m_MouseButtonsEvents[0] = GUIInput::None; } + + m_MouseWheelChange = g_UInputMan.MouseWheelMovedByPlayer(m_Player); } diff --git a/Source/Lua/LuaBindingsActivities.cpp b/Source/Lua/LuaBindingsActivities.cpp index 19f3d69119..08d1dbcc71 100644 --- a/Source/Lua/LuaBindingsActivities.cpp +++ b/Source/Lua/LuaBindingsActivities.cpp @@ -152,7 +152,7 @@ LuaBindingRegisterFunctionDefinitionForType(ActivityLuaBindings, GameActivity) { .def("ClearObjectivePoints", &GameActivity::ClearObjectivePoints) .def("AddOverridePurchase", &GameActivity::AddOverridePurchase) .def("SetOverridePurchaseList", (int(GameActivity::*)(const Loadout*, int)) & GameActivity::SetOverridePurchaseList) - .def("SetOverridePurchaseList", (int(GameActivity::*)(std::string, int)) & GameActivity::SetOverridePurchaseList) + .def("SetOverridePurchaseList", (int(GameActivity::*)(const std::string&, int)) & GameActivity::SetOverridePurchaseList) .def("ClearOverridePurchase", &GameActivity::ClearOverridePurchase) .def("CreateDelivery", (bool(GameActivity::*)(int)) & GameActivity::CreateDelivery) .def("CreateDelivery", (bool(GameActivity::*)(int, int)) & GameActivity::CreateDelivery) diff --git a/Source/Lua/LuaBindingsEntities.cpp b/Source/Lua/LuaBindingsEntities.cpp index 945221093f..6b138782a3 100644 --- a/Source/Lua/LuaBindingsEntities.cpp +++ b/Source/Lua/LuaBindingsEntities.cpp @@ -21,7 +21,7 @@ LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Entity) { .property("RandomWeight", &Entity::GetRandomWeight) .property("Groups", &Entity::GetGroups, luabind::return_stl_iterator) - .def("Clone", &LuaAdaptersEntityClone::CloneEntity) + .def("Clone", &LuaAdaptersEntityClone::CloneEntity, luabind::adopt(luabind::result)) .def("Reset", &Entity::Reset) .def("GetModuleAndPresetName", &Entity::GetModuleAndPresetName) .def("AddToGroup", &Entity::AddToGroup) @@ -252,8 +252,8 @@ LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Actor) { .def("RemoveInventoryItem", (void(Actor::*)(const std::string&)) & Actor::RemoveInventoryItem) .def("RemoveInventoryItem", (void(Actor::*)(const std::string&, const std::string&)) & Actor::RemoveInventoryItem) .def("RemoveInventoryItemAtIndex", &Actor::RemoveInventoryItemAtIndex, luabind::adopt(luabind::return_value)) - .def("SwapNextInventory", &Actor::SwapNextInventory) - .def("SwapPrevInventory", &Actor::SwapPrevInventory) + .def("SwapNextInventory", &Actor::SwapNextInventory, luabind::adopt(luabind::result) + luabind::adopt(_2)) + .def("SwapPrevInventory", &Actor::SwapPrevInventory, luabind::adopt(luabind::result) + luabind::adopt(_2)) .def("DropAllInventory", &Actor::DropAllInventory) .def("DropAllGold", &Actor::DropAllGold) .def("IsInventoryEmpty", &Actor::IsInventoryEmpty) diff --git a/Source/Lua/LuaBindingsGUI.cpp b/Source/Lua/LuaBindingsGUI.cpp index d9c1e63cff..706b93ee84 100644 --- a/Source/Lua/LuaBindingsGUI.cpp +++ b/Source/Lua/LuaBindingsGUI.cpp @@ -72,7 +72,7 @@ LuaBindingRegisterFunctionDefinitionForType(GUILuaBindings, SceneEditorGUI) { .def("SetCursorPos", &SceneEditorGUI::SetCursorPos) .def("GetCurrentObject", &SceneEditorGUI::GetCurrentObject) - .def("SetCurrentObject", &SceneEditorGUI::SetCurrentObject) + .def("SetCurrentObject", &SceneEditorGUI::SetCurrentObject, luabind::adopt(_2)) .def("SetModuleSpace", &SceneEditorGUI::SetModuleSpace) .def("SetNativeTechModule", &SceneEditorGUI::SetNativeTechModule) .def("SetForeignCostMultiplier", &SceneEditorGUI::SetForeignCostMultiplier) diff --git a/Source/Lua/LuaBindingsManagers.cpp b/Source/Lua/LuaBindingsManagers.cpp index 61f870beed..55d60d8bfc 100644 --- a/Source/Lua/LuaBindingsManagers.cpp +++ b/Source/Lua/LuaBindingsManagers.cpp @@ -204,8 +204,8 @@ LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PresetMan) { .def("GetTotalModuleCount", &PresetMan::GetTotalModuleCount) .def("GetOfficialModuleCount", &PresetMan::GetOfficialModuleCount) .def("AddPreset", &PresetMan::AddEntityPreset) - .def("GetPreset", (const Entity* (PresetMan::*)(std::string, std::string, int)) & PresetMan::GetEntityPreset) - .def("GetPreset", (const Entity* (PresetMan::*)(std::string, std::string, std::string)) & PresetMan::GetEntityPreset) + .def("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, int)) & PresetMan::GetEntityPreset) + .def("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, std::string)) & PresetMan::GetEntityPreset) .def("GetLoadout", (Actor * (PresetMan::*)(std::string, std::string, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) .def("GetLoadout", (Actor * (PresetMan::*)(std::string, int, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) .def("GetRandomOfGroup", &PresetMan::GetRandomOfGroup) @@ -305,8 +305,8 @@ LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, SceneMan) { .property("KgPerOz", &SceneMan::GetKgPerOz) .property("ScrapCompactingHeight", &SceneMan::GetScrapCompactingHeight, &SceneMan::SetScrapCompactingHeight) - .def("LoadScene", (int(SceneMan::*)(std::string, bool, bool)) & SceneMan::LoadScene) - .def("LoadScene", (int(SceneMan::*)(std::string, bool)) & SceneMan::LoadScene) + .def("LoadScene", (int(SceneMan::*)(const std::string&, bool, bool)) & SceneMan::LoadScene) + .def("LoadScene", (int(SceneMan::*)(const std::string&, bool)) & SceneMan::LoadScene) .def("GetTerrain", &SceneMan::GetTerrain) .def("GetMaterial", &SceneMan::GetMaterial) diff --git a/Source/Lua/LuaBindingsSystem.cpp b/Source/Lua/LuaBindingsSystem.cpp index c130f01fd6..19aa29ac4d 100644 --- a/Source/Lua/LuaBindingsSystem.cpp +++ b/Source/Lua/LuaBindingsSystem.cpp @@ -1,6 +1,7 @@ // Make sure that binding definition files are always set to NOT use pre-compiled headers and conformance mode (/permissive) otherwise everything will be on fire! #include "LuaBindingRegisterDefinitions.h" +#include "return_reference_to_policy.hpp" using namespace RTE; @@ -206,30 +207,30 @@ LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, Vector) { .def("MagnitudeIsGreaterThan", &Vector::MagnitudeIsGreaterThan) .def("MagnitudeIsLessThan", &Vector::MagnitudeIsLessThan) - .def("SetMagnitude", &Vector::SetMagnitude) + .def("SetMagnitude", &Vector::SetMagnitude, luabind::return_reference_to(_1)) .def("GetXFlipped", &Vector::GetXFlipped) .def("GetYFlipped", &Vector::GetYFlipped) - .def("CapMagnitude", &Vector::CapMagnitude) - .def("ClampMagnitude", &Vector::ClampMagnitude) - .def("FlipX", &Vector::FlipX) - .def("FlipY", &Vector::FlipY) + .def("CapMagnitude", &Vector::CapMagnitude, luabind::return_reference_to(_1)) + .def("ClampMagnitude", &Vector::ClampMagnitude, luabind::return_reference_to(_1)) + .def("FlipX", &Vector::FlipX, luabind::return_reference_to(_1)) + .def("FlipY", &Vector::FlipY, luabind::return_reference_to(_1)) .def("IsZero", &Vector::IsZero) .def("IsOpposedTo", &Vector::IsOpposedTo) .def("Dot", &Vector::Dot) .def("Cross", &Vector::Cross) - .def("Round", &Vector::Round) - .def("ToHalf", &Vector::ToHalf) - .def("Floor", &Vector::Floor) - .def("Ceiling", &Vector::Ceiling) - .def("Normalize", &Vector::Normalize) - .def("Perpendicularize", &Vector::Perpendicularize) + .def("Round", &Vector::Round, luabind::return_reference_to(_1)) + .def("ToHalf", &Vector::ToHalf, luabind::return_reference_to(_1)) + .def("Floor", &Vector::Floor, luabind::return_reference_to(_1)) + .def("Ceiling", &Vector::Ceiling, luabind::return_reference_to(_1)) + .def("Normalize", &Vector::Normalize, luabind::return_reference_to(_1)) + .def("Perpendicularize", &Vector::Perpendicularize, luabind::return_reference_to(_1)) .def("Reset", &Vector::Reset) - .def("RadRotate", &Vector::RadRotate) - .def("DegRotate", &Vector::DegRotate) + .def("RadRotate", &Vector::RadRotate, luabind::return_reference_to(_1)) + .def("DegRotate", &Vector::DegRotate, luabind::return_reference_to(_1)) .def("GetRadRotatedCopy", &Vector::GetRadRotatedCopy) .def("GetDegRotatedCopy", &Vector::GetDegRotatedCopy) - .def("AbsRotateTo", &Vector::AbsRotateTo) - .def("SetXY", &Vector::SetXY); + .def("AbsRotateTo", &Vector::AbsRotateTo, luabind::return_reference_to(_1)) + .def("SetXY", &Vector::SetXY, luabind::return_reference_to(_1)); } LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, PathRequest) { diff --git a/Source/Managers/ActivityMan.cpp b/Source/Managers/ActivityMan.cpp index 3503a9f57e..8c6d7b9b91 100644 --- a/Source/Managers/ActivityMan.cpp +++ b/Source/Managers/ActivityMan.cpp @@ -25,14 +25,20 @@ #include "MusicMan.h" +#ifdef SYSTEM_MINIZIP +#include +#include +#else #include "zip.h" #include "unzip.h" +#endif #include "tracy/Tracy.hpp" #include "SDL3/SDL_surface.h" #include +#include #include using namespace RTE; @@ -205,6 +211,7 @@ bool ActivityMan::SaveCurrentGame(const std::string& fileName) { SDL_Palette* palette = ContentFile::DefaultPaletteToSDL(); SDL_SetSurfacePalette(image, palette); + SDL_SetSurfaceColorKey(image, false, 0); bool result = IMG_SavePNG_IO(image, stream, false); SDL_FlushIO(stream); @@ -282,7 +289,7 @@ bool ActivityMan::LoadAndLaunchGame(const std::string& fileName) { unz_file_info info; char* buffer = nullptr; - auto unzipFileIntoBuffer = [&](std::string fullFileName) { + auto unzipFileIntoBuffer = [&](const std::string& fullFileName) { // These need to use NULL instead of nullptr to compile on Linux/OSX? if (unzLocateFile(zippedSaveFile, fullFileName.c_str(), NULL) == UNZ_END_OF_LIST_OF_FILE) { return false; @@ -309,11 +316,16 @@ bool ActivityMan::LoadAndLaunchGame(const std::string& fileName) { SDL_Surface* image = stream ? IMG_LoadPNG_IO(stream) : nullptr; SDL_CloseIO(stream); + int bitDepth = SDL_GetPixelFormatDetails(image->format)->bits_per_pixel; SDL_Palette* palette = ContentFile::DefaultPaletteToSDL(); - SDL_Surface* newImage = SDL_ConvertSurfaceAndColorspace(image, SDL_PIXELFORMAT_INDEX8, palette, SDL_COLORSPACE_UNKNOWN, 0); + if (bitDepth != 8) { + SDL_Surface* newImage = SDL_ConvertSurfaceAndColorspace(image, SDL_PIXELFORMAT_INDEX8, palette, SDL_COLORSPACE_UNKNOWN, 0); + SDL_DestroySurface(image); + image = newImage; + } else { + SDL_SetSurfacePalette(image, palette); + } SDL_DestroyPalette(palette); - SDL_DestroySurface(image); - image = newImage; free(buffer); return image; diff --git a/Source/Managers/ActivityMan.h b/Source/Managers/ActivityMan.h index a918d95d80..4fcf90a3d6 100644 --- a/Source/Managers/ActivityMan.h +++ b/Source/Managers/ActivityMan.h @@ -83,7 +83,7 @@ namespace RTE { #pragma region Default Activity Handling /// Gets the type name of the default Activity to be loaded if nothing else is available. /// @return The default Activity type name. - std::string GetDefaultActivityType() const { return m_DefaultActivityType; } + const std::string& GetDefaultActivityType() const { return m_DefaultActivityType; } /// Sets the type name of the default Activity to be loaded if nothing else is available. /// @param defaultActivityType The default Activity type name. @@ -91,7 +91,7 @@ namespace RTE { /// Gets the name of the default Activity to be loaded if nothing else is available. /// @return The default Activity preset name. - std::string GetDefaultActivityName() const { return m_DefaultActivityName; } + const std::string& GetDefaultActivityName() const { return m_DefaultActivityName; } /// Sets the preset name of the default Activity to be loaded if nothing else is available. /// @param defaultActivityName The default Activity preset name. diff --git a/Source/Managers/AudioMan.cpp b/Source/Managers/AudioMan.cpp index 2a86e5e1bb..4839b0af5f 100644 --- a/Source/Managers/AudioMan.cpp +++ b/Source/Managers/AudioMan.cpp @@ -3,15 +3,13 @@ #include "CameraMan.h" #include "ConsoleMan.h" #include "FrameMan.h" -#include "SettingsMan.h" #include "SceneMan.h" #include "ActivityMan.h" #include "SoundContainer.h" -#include "GUISound.h" -#include "PresetMan.h" #include "WindowMan.h" #include "SoundSet.h" +#include #include using namespace RTE; @@ -158,7 +156,7 @@ void AudioMan::Update() { if (!g_ActivityMan.ActivityPaused()) { const Activity* currentActivity = g_ActivityMan.GetActivity(); - int currentActivityHumanCount = m_IsInMultiplayerMode ? 1 : currentActivity->GetHumanCount(); + uint8_t currentActivityHumanCount = m_IsInMultiplayerMode ? 1 : currentActivity->GetHumanCount(); if (m_CurrentActivityHumanPlayerPositions.size() != currentActivityHumanCount) { status = status == FMOD_OK ? m_AudioSystem->set3DNumListeners(currentActivityHumanCount) : status; @@ -213,11 +211,16 @@ void AudioMan::SetGlobalPitch(float pitch, bool includeImmobileSounds, bool incl } m_GlobalPitch = std::clamp(pitch, 0.125F, 8.0F); + + m_SFXChannelGroup->setPitch(m_GlobalPitch); + + if (includeImmobileSounds) { + m_UIChannelGroup->setPitch(m_GlobalPitch); + } + if (includeMusic) { m_MusicChannelGroup->setPitch(m_GlobalPitch); } - - m_SFXChannelGroup->setPitch(m_GlobalPitch); } bool AudioMan::SetMusicPitch(float pitch) { @@ -585,7 +588,7 @@ bool AudioMan::StopSoundContainerPlayingChannels(SoundContainer* soundContainer, RegisterSoundEvent(player, SOUND_STOP, soundContainer); } - FMOD_RESULT result; + FMOD_RESULT result = FMOD_OK; FMOD::Channel* soundChannel; const std::unordered_set* channels = soundContainer->GetPlayingChannels(); @@ -659,8 +662,7 @@ void AudioMan::Update3DEffectsForSFXChannels() { result = m_SFXChannelGroup->getChannel(i, &soundChannel); FMOD_MODE mode; result = (result == FMOD_OK) ? soundChannel->getMode(&mode) : result; - unsigned modeResult = mode & FMOD_2D; - if (modeResult == 0) { + if (result == FMOD_OK && (mode & FMOD_2D) == 0) { FMOD_VECTOR channelPosition; result = result == FMOD_OK ? soundChannel->get3DAttributes(&channelPosition, nullptr) : result; result = result == FMOD_OK ? UpdatePositionalEffectsForSoundChannel(soundChannel, &channelPosition) : result; @@ -671,13 +673,15 @@ void AudioMan::Update3DEffectsForSFXChannels() { float doubleMinimumDistanceForPanning = m_MinimumDistanceForPanning * 2.0F; void* userData; result = result == FMOD_OK ? soundChannel->getUserData(&userData) : result; - const SoundContainer* soundContainer = static_cast(userData); - if (sqrDistanceToPlayer < (m_MinimumDistanceForPanning * m_MinimumDistanceForPanning) || soundContainer->GetCustomPanValue() != 0.0f) { - soundChannel->set3DLevel(0); - } else if (sqrDistanceToPlayer < (doubleMinimumDistanceForPanning * doubleMinimumDistanceForPanning)) { - soundChannel->set3DLevel(Lerp(0, 1, 0, m_SoundPanningEffectStrength * soundContainer->GetPanningStrengthMultiplier(), channel3dLevel)); - } else { - soundChannel->set3DLevel(m_SoundPanningEffectStrength * soundContainer->GetPanningStrengthMultiplier()); + if (result == FMOD_OK) { + const SoundContainer* soundContainer = static_cast(userData); + if (sqrDistanceToPlayer < (m_MinimumDistanceForPanning * m_MinimumDistanceForPanning) || soundContainer->GetCustomPanValue() != 0.0f) { + result = soundChannel->set3DLevel(0); + } else if (sqrDistanceToPlayer < (doubleMinimumDistanceForPanning * doubleMinimumDistanceForPanning)) { + result = soundChannel->set3DLevel(Lerp(0, 1, 0, m_SoundPanningEffectStrength * soundContainer->GetPanningStrengthMultiplier(), channel3dLevel)); + } else { + result = soundChannel->set3DLevel(m_SoundPanningEffectStrength * soundContainer->GetPanningStrengthMultiplier()); + } } } } @@ -690,10 +694,13 @@ void AudioMan::Update3DEffectsForSFXChannels() { } FMOD_RESULT AudioMan::UpdatePositionalEffectsForSoundChannel(FMOD::Channel* soundChannel, const FMOD_VECTOR* positionOverride) const { - FMOD_RESULT result = FMOD_OK; - void* userData; - result = result == FMOD_OK ? soundChannel->getUserData(&userData) : result; + FMOD_RESULT result = soundChannel->getUserData(&userData); + + if (result != FMOD_OK) { + return result; + } + const SoundContainer* channelSoundContainer = static_cast(userData); bool sceneWraps = g_SceneMan.SceneWrapsX(); @@ -714,7 +721,11 @@ FMOD_RESULT AudioMan::UpdatePositionalEffectsForSoundChannel(FMOD::Channel* soun if (!sceneWraps) { wrappedChannelPositions = {channelPosition}; } else { - wrappedChannelPositions = (channelPosition.x <= halfSceneWidth) ? wrappedChannelPositions = {channelPosition, {channelPosition.x + g_SceneMan.GetSceneWidth(), channelPosition.y}} : wrappedChannelPositions = {FMOD_VECTOR({channelPosition.x - g_SceneMan.GetSceneWidth(), channelPosition.y}), channelPosition}; + if (channelPosition.x <= halfSceneWidth) { + wrappedChannelPositions = {channelPosition, {channelPosition.x + g_SceneMan.GetSceneWidth(), channelPosition.y, 0.0}}; + } else { + wrappedChannelPositions = {FMOD_VECTOR({channelPosition.x - g_SceneMan.GetSceneWidth(), channelPosition.y, 0.0}), channelPosition}; + } } float sqrShortestDistance = c_SoundMaxAudibleDistance * c_SoundMaxAudibleDistance; @@ -738,6 +749,9 @@ FMOD_RESULT AudioMan::UpdatePositionalEffectsForSoundChannel(FMOD::Channel* soun int soundChannelIndex; result = result == FMOD_OK ? soundChannel->getIndex(&soundChannelIndex) : result; + if (result != FMOD_OK) { + return result; + } float attenuationStartDistance = c_DefaultAttenuationStartDistance; float soundMaxDistance = 0.0F; @@ -760,7 +774,7 @@ FMOD_RESULT AudioMan::UpdatePositionalEffectsForSoundChannel(FMOD::Channel* soun float minimumAudibleDistance = m_SoundChannelMinimumAudibleDistances.at(soundChannelIndex); if (shortestDistance >= soundMaxDistance) { attenuatedVolume = 0.0F; - } else if (m_SoundChannelMinimumAudibleDistances.empty() || m_SoundChannelMinimumAudibleDistances.find(soundChannelIndex) == m_SoundChannelMinimumAudibleDistances.end()) { + } else if (m_SoundChannelMinimumAudibleDistances.find(soundChannelIndex) == m_SoundChannelMinimumAudibleDistances.end()) { g_ConsoleMan.PrintString("ERROR: An error occurred when checking to see if the sound at channel " + std::to_string(soundChannelIndex) + " was less than its minimum audible distance away from the farthest listener."); } else if (sqrLongestDistance < (minimumAudibleDistance * minimumAudibleDistance)) { attenuatedVolume = 0.0F; @@ -777,7 +791,7 @@ FMOD_RESULT AudioMan::UpdatePositionalEffectsForSoundChannel(FMOD::Channel* soun return result; } -FMOD_RESULT F_CALLBACK AudioMan::SoundChannelEndedCallback(FMOD_CHANNELCONTROL* channelControl, FMOD_CHANNELCONTROL_TYPE channelControlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void* unusedCommandData1, void* unusedCommandData2) { +FMOD_RESULT F_CALLBACK AudioMan::SoundChannelEndedCallback(FMOD_CHANNELCONTROL* channelControl, FMOD_CHANNELCONTROL_TYPE channelControlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void*, void*) { if (channelControlType == FMOD_CHANNELCONTROL_CHANNEL && callbackType == FMOD_CHANNELCONTROL_CALLBACK_END) { FMOD::Channel* channel = reinterpret_cast(channelControl); int channelIndex; diff --git a/Source/Managers/ConsoleMan.cpp b/Source/Managers/ConsoleMan.cpp index 1bfa8563fb..fecce2ba09 100644 --- a/Source/Managers/ConsoleMan.cpp +++ b/Source/Managers/ConsoleMan.cpp @@ -153,9 +153,8 @@ void ConsoleMan::AddLoadWarningLogExtensionMismatchEntry(const std::string& path PrintString(newEntry); } else { std::transform(newEntry.begin(), newEntry.end(), newEntry.begin(), ::tolower); - if (m_LoadWarningLog.find(newEntry) == m_LoadWarningLog.end()) { - m_LoadWarningLog.emplace(newEntry); - } + // Emplace inserts only if there is no existing entry. + m_LoadWarningLog.emplace(newEntry); } } diff --git a/Source/Managers/FrameMan.cpp b/Source/Managers/FrameMan.cpp index 549cbb7f4c..0799a475c6 100644 --- a/Source/Managers/FrameMan.cpp +++ b/Source/Managers/FrameMan.cpp @@ -32,6 +32,8 @@ #include "tracy/TracyOpenGL.hpp" #include +#include + using namespace RTE; void BitmapDeleter::operator()(BITMAP* bitmap) const { destroy_bitmap(bitmap); } diff --git a/Source/Managers/LuaMan.cpp b/Source/Managers/LuaMan.cpp index 194bfac083..f0911901e7 100644 --- a/Source/Managers/LuaMan.cpp +++ b/Source/Managers/LuaMan.cpp @@ -105,7 +105,7 @@ void LuaStateWrapper::Initialize() { luabind::def("LERP", (float (*)(float, float, float, float, float))&Lerp), luabind::def("Lerp", (float (*)(float, float, float, float, float))&Lerp), luabind::def("Lerp", (Vector(*)(float, float, Vector, Vector, float))&Lerp), - luabind::def("Lerp", (Matrix(*)(float, float, Matrix, Matrix, float))&Lerp), + luabind::def("Lerp", (Matrix(*)(float, float, const Matrix&, const Matrix&, float))&Lerp), luabind::def("EaseIn", &EaseIn), luabind::def("EaseOut", &EaseOut), luabind::def("EaseInOut", &EaseInOut), diff --git a/Source/Managers/LuaMan.h b/Source/Managers/LuaMan.h index 62502714c7..1d2b3cbbbc 100644 --- a/Source/Managers/LuaMan.h +++ b/Source/Managers/LuaMan.h @@ -7,6 +7,8 @@ #include "BS_thread_pool.hpp" +#include + #define g_LuaMan LuaMan::Instance() struct lua_State; diff --git a/Source/Managers/MetaMan.cpp b/Source/Managers/MetaMan.cpp index 2991eb3aad..89e7618c73 100644 --- a/Source/Managers/MetaMan.cpp +++ b/Source/Managers/MetaMan.cpp @@ -314,7 +314,7 @@ void MetaMan::Destroy() { Clear(); } -int MetaMan::SaveSceneData(std::string pathBase) { +int MetaMan::SaveSceneData(const std::string& pathBase) { for (std::vector::const_iterator sItr = m_Scenes.begin(); sItr != m_Scenes.end(); ++sItr) { // Only save the data of revealed scenes that have already had their layers built and saved into files if ((*sItr)->IsRevealed() && (*sItr)->GetTerrain() && (*sItr)->GetTerrain()->IsLoadedFromDisk()) { diff --git a/Source/Managers/MetaMan.h b/Source/Managers/MetaMan.h index f8cb254154..9e1f93c171 100644 --- a/Source/Managers/MetaMan.h +++ b/Source/Managers/MetaMan.h @@ -99,7 +99,7 @@ namespace RTE { /// everything up to and including the unique name of the game. /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int SaveSceneData(std::string pathBase); + int SaveSceneData(const std::string& pathBase); /// Loads the bitmap data of all Scenes of this Metagame that have once /// been saved to files. @@ -123,12 +123,12 @@ namespace RTE { /// Sets the name of the currently played Metagame. It's what's used when /// saving to disk. /// @param newName The Metagame's name. - void SetGameName(std::string newName) { m_GameName = newName; } + void SetGameName(std::string newName) { m_GameName = std::move(newName); } /// Gets the name of the currently played Metagame. It's what's used when /// saving to disk. /// @return The name of the current metagame. - std::string GetGameName() const { return m_GameName; } + const std::string& GetGameName() const { return m_GameName; } /// Gets the GUI controller of this Metagame. /// @return The GUI controller of the metagame. diff --git a/Source/Managers/MovableMan.cpp b/Source/Managers/MovableMan.cpp index e68d56cf0d..904ddba508 100644 --- a/Source/Managers/MovableMan.cpp +++ b/Source/Managers/MovableMan.cpp @@ -27,11 +27,10 @@ using namespace RTE; -AlarmEvent::AlarmEvent(const Vector& pos, int team, float range) { - m_ScenePos = pos; - m_Team = (Activity::Teams)team; - m_Range = range * g_FrameMan.GetPlayerScreenWidth() * 0.51F; -} +AlarmEvent::AlarmEvent(const Vector& pos, int team, float range) : + m_ScenePos(pos), + m_Team((Activity::Teams)team), + m_Range(range * g_FrameMan.GetPlayerScreenWidth() * 0.51F) {} const std::string MovableMan::c_ClassName = "MovableMan"; @@ -1484,8 +1483,6 @@ void MovableMan::Update() { if (!(*aIt)->IsSetToDelete()) m_Actors.push_back(*aIt); else { - m_ValidActors.erase(*aIt); - // Also remove actor from the roster if ((*aIt)->GetTeam() >= 0) { // m_ActorRoster[(*aIt)->GetTeam()].remove(*aIt); @@ -1494,6 +1491,8 @@ void MovableMan::Update() { (*aIt)->DestroyScriptState(); delete (*aIt); + + m_ValidActors.erase(*aIt); } } m_AddedActors.clear(); @@ -1504,9 +1503,9 @@ void MovableMan::Update() { if (!(*iIt)->IsSetToDelete()) { m_Items.push_back(*iIt); } else { - m_ValidItems.erase(*iIt); (*iIt)->DestroyScriptState(); delete (*iIt); + m_ValidItems.erase(*iIt); } } m_AddedItems.clear(); @@ -1517,9 +1516,9 @@ void MovableMan::Update() { if (!(*parIt)->IsSetToDelete()) { m_Particles.push_back(*parIt); } else { - m_ValidParticles.erase(*parIt); (*parIt)->DestroyScriptState(); delete (*parIt); + m_ValidParticles.erase(*parIt); } } m_AddedParticles.clear(); @@ -1571,8 +1570,8 @@ void MovableMan::Update() { if ((*iIt)->GetRestThreshold() < 0) { (*iIt)->SetRestThreshold(500); } - m_ValidItems.erase(*iIt); m_Particles.push_back(*iIt); + m_ValidItems.erase(*iIt); iIt++; } m_Items.erase(imidIt, m_Items.end()); @@ -1600,9 +1599,9 @@ void MovableMan::Update() { RemoveActorFromTeamRoster(*aIt); // Delete - m_ValidActors.erase(*aIt); (*aIt)->DestroyScriptState(); delete (*aIt); + m_ValidActors.erase(*aIt); aIt++; } // Try to set the existing iterator to a safer value, erase can crash in debug mode otherwise? @@ -1614,9 +1613,9 @@ void MovableMan::Update() { imidIt = iIt; while (iIt != m_Items.end()) { - m_ValidItems.erase(*iIt); (*iIt)->DestroyScriptState(); delete (*iIt); + m_ValidItems.erase(*iIt); iIt++; } m_Items.erase(imidIt, m_Items.end()); @@ -1626,9 +1625,9 @@ void MovableMan::Update() { midIt = parIt; while (parIt != m_Particles.end()) { - m_ValidParticles.erase(*parIt); (*parIt)->DestroyScriptState(); delete (*parIt); + m_ValidParticles.erase(*parIt); parIt++; } m_Particles.erase(midIt, m_Particles.end()); @@ -1658,9 +1657,9 @@ void MovableMan::Update() { if ((*parIt)->GetDrawPriority() >= terrMat->GetPriority()) { (*parIt)->DrawToTerrain(g_SceneMan.GetTerrain()); } - m_ValidParticles.erase(*parIt); (*parIt)->DestroyScriptState(); delete (*parIt); + m_ValidParticles.erase(*parIt); parIt++; } m_Particles.erase(midIt, m_Particles.end()); diff --git a/Source/Managers/MusicMan.h b/Source/Managers/MusicMan.h index 4717eb759a..e0aa541d20 100644 --- a/Source/Managers/MusicMan.h +++ b/Source/Managers/MusicMan.h @@ -66,7 +66,7 @@ namespace RTE { /// Gets the current DynamicSongSectionType being played. /// @return The current DynamicSongSectionType being played. - std::string GetCurrentSongSectionType() const { return m_CurrentSongSectionType; } + const std::string& GetCurrentSongSectionType() const { return m_CurrentSongSectionType; } /// Sets the current playing dynamic music to end, disabling further playback of new music. /// @param fadeOutCurrent Whether to also fade out the current playing music or not. diff --git a/Source/Managers/PerformanceMan.cpp b/Source/Managers/PerformanceMan.cpp index 1232352025..b53759b508 100644 --- a/Source/Managers/PerformanceMan.cpp +++ b/Source/Managers/PerformanceMan.cpp @@ -6,6 +6,8 @@ #include "GUI.h" #include "AllegroBitmap.h" +#include + using namespace RTE; const std::array PerformanceMan::m_PerfCounterNames = {"Total", "Act AI", "Act Travel", "Act Update", "Prt Travel", "Prt Update", "Activity", "Scripts"}; diff --git a/Source/Managers/PostProcessMan.cpp b/Source/Managers/PostProcessMan.cpp index 6081b966b1..9c0e0ff2bc 100644 --- a/Source/Managers/PostProcessMan.cpp +++ b/Source/Managers/PostProcessMan.cpp @@ -20,6 +20,8 @@ #include "tracy/Tracy.hpp" #include "tracy/TracyOpenGL.hpp" +#include + using namespace RTE; PostProcessMan::PostProcessMan() { diff --git a/Source/Managers/PresetMan.cpp b/Source/Managers/PresetMan.cpp index 5d7a6a5999..487352ddc8 100644 --- a/Source/Managers/PresetMan.cpp +++ b/Source/Managers/PresetMan.cpp @@ -18,6 +18,8 @@ #include "SettingsMan.h" #include "System.h" +#include + using namespace RTE; const std::array PresetMan::c_OfficialModules = {"Base.rte", "Coalition.rte", "Imperatus.rte", "Techion.rte", "Dummy.rte", "Ronin.rte", "Browncoats.rte", "Uzira.rte", "MuIlaak.rte", "Missions.rte"}; @@ -195,13 +197,13 @@ int PresetMan::GetModuleID(std::string moduleName) { return (*itr).second; // Try with or without the .rte on the end before giving up - int dotPos = moduleName.find_last_of('.'); + size_t dotPos = moduleName.find_last_of('.'); // Wasnt, so try adding it if (dotPos == std::string::npos) moduleName = moduleName + System::GetModulePackageExtension(); // There was ".rte", so try to shave it off the name else - moduleName = moduleName.substr(0, dotPos); + moduleName.resize(dotPos); // Try to find the module again! itr = m_DataModuleIDs.find(moduleName); @@ -294,19 +296,19 @@ std::string PresetMan::GetFullModulePath(const std::string& modulePath) const { return (pathTopDir == moduleTopDir) ? modulePathGeneric : moduleTopDir + modulePathGeneric; } -bool PresetMan::AddEntityPreset(Entity* pEntToAdd, int whichModule, bool overwriteSame, std::string readFromFile) { +bool PresetMan::AddEntityPreset(Entity* pEntToAdd, int whichModule, bool overwriteSame, const std::string& readFromFile) { RTEAssert(whichModule >= 0 && whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); return m_pDataModules[whichModule]->AddEntityPreset(pEntToAdd, overwriteSame, readFromFile); } -const Entity* PresetMan::GetEntityPreset(std::string type, std::string preset, int whichModule) { +const Entity* PresetMan::GetEntityPreset(const std::string& type, std::string preset, int whichModule) { RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); const Entity* pRetEntity = 0; // Preset name might have "[ModuleName]/" preceding it, detect it here and select proper module! - int slashPos = preset.find_first_of('/'); + size_t slashPos = preset.find_first_of('/'); if (slashPos != std::string::npos) { // Get the module ID and cut off the module specifier in the string whichModule = GetModuleID(preset.substr(0, slashPos)); @@ -417,7 +419,7 @@ Entity* PresetMan::ReadReflectedPreset(Reader& reader) { return 0; } -bool PresetMan::GetAllOfType(std::list& entityList, std::string type, int whichModule) { +bool PresetMan::GetAllOfType(std::list& entityList, const std::string& type, int whichModule) { if (type.empty()) return false; @@ -438,7 +440,7 @@ bool PresetMan::GetAllOfType(std::list& entityList, std::string type, i return foundAny; } -bool PresetMan::GetAllOfTypeInModuleSpace(std::list& entityList, std::string type, int whichModuleSpace) { +bool PresetMan::GetAllOfTypeInModuleSpace(std::list& entityList, const std::string& type, int whichModuleSpace) { if (type.empty()) return false; @@ -495,7 +497,7 @@ bool PresetMan::GetAllNotOfGroups(std::list& entityList, const std::vec return foundAny; } -Entity* PresetMan::GetRandomOfGroup(std::string group, std::string type, int whichModule) { +Entity* PresetMan::GetRandomOfGroup(std::string group, const std::string& type, int whichModule) { RTEAssert(!group.empty(), "Looking for empty group!"); bool foundAny = false; @@ -532,7 +534,7 @@ Entity* PresetMan::GetRandomOfGroup(std::string group, std::string type, int whi return 0; } -Entity* PresetMan::GetRandomBuyableOfGroupFromTech(std::string group, std::string type, int whichModule) { +Entity* PresetMan::GetRandomBuyableOfGroupFromTech(std::string group, const std::string& type, int whichModule) { RTEAssert(!group.empty(), "Looking for empty group!"); bool foundAny = false; @@ -625,7 +627,7 @@ Entity* PresetMan::GetRandomBuyableOfGroupFromTech(std::string group, std::strin return 0; } -bool PresetMan::GetAllOfGroupInModuleSpace(std::list& entityList, std::string group, std::string type, int whichModuleSpace) { +bool PresetMan::GetAllOfGroupInModuleSpace(std::list& entityList, const std::string& group, const std::string& type, int whichModuleSpace) { RTEAssert(!group.empty(), "Looking for empty group!"); bool foundAny = false; @@ -646,7 +648,7 @@ bool PresetMan::GetAllOfGroupInModuleSpace(std::list& entityList, std:: return foundAny; } -Entity* PresetMan::GetRandomOfGroupInModuleSpace(std::string group, std::string type, int whichModuleSpace) { +Entity* PresetMan::GetRandomOfGroupInModuleSpace(const std::string& group, const std::string& type, int whichModuleSpace) { RTEAssert(!group.empty(), "Looking for empty group!"); bool foundAny = false; @@ -683,7 +685,7 @@ Entity* PresetMan::GetRandomOfGroupInModuleSpace(std::string group, std::string return 0; } -std::string PresetMan::GetEntityDataLocation(std::string type, std::string preset, int whichModule) { +std::string PresetMan::GetEntityDataLocation(const std::string& type, const std::string& preset, int whichModule) { RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); std::string pRetPath = ""; @@ -752,7 +754,7 @@ bool PresetMan::ReloadEntityPreset(const std::string& presetName, const std::str m_ReloadEntityPresetCalledThisUpdate = true; - Reader reader(presetDataLocation.c_str(), true); + Reader reader(presetDataLocation, true); while (reader.NextProperty()) { reader.ReadPropName(); g_PresetMan.GetEntityPreset(reader); @@ -795,7 +797,7 @@ void PresetMan::RegisterGroup(std::string newGroup, int whichModule) { m_pDataModules[whichModule]->RegisterGroup(newGroup); } -bool PresetMan::GetGroups(std::list& groupList, int whichModule, std::string withType) const { +bool PresetMan::GetGroups(std::list& groupList, int whichModule, const std::string& withType) const { RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); bool foundAny = false; @@ -833,7 +835,7 @@ bool PresetMan::GetGroups(std::list& groupList, int whichModule, st return foundAny; } -bool PresetMan::GetModuleSpaceGroups(std::list& groupList, int whichModule, std::string withType) const { +bool PresetMan::GetModuleSpaceGroups(std::list& groupList, int whichModule, const std::string& withType) const { RTEAssert(whichModule < (int)m_pDataModules.size(), "Tried to access an out of bounds data module number!"); bool foundAny = false; diff --git a/Source/Managers/PresetMan.h b/Source/Managers/PresetMan.h index b9f4f6bb25..71fac092b7 100644 --- a/Source/Managers/PresetMan.h +++ b/Source/Managers/PresetMan.h @@ -68,7 +68,7 @@ namespace RTE { /// Sets the single module to be loaded after the official modules. This will be the ONLY non-official module to be loaded. /// @param moduleName Name of the module to load. - void SetSingleModuleToLoad(std::string moduleName) { m_SingleModuleToLoad = moduleName; } + void SetSingleModuleToLoad(std::string moduleName) { m_SingleModuleToLoad = std::move(moduleName); } /// Gets a specific loaded DataModule /// @param whichModule The ID of the module to get. (default: 0) @@ -134,7 +134,7 @@ namespace RTE { /// @return Whether or not a copy of the passed-in instance was successfully inserted /// into the module. False will be returned if there already was an instance /// of that class and instance name inserted previously, unless overwritten. - bool AddEntityPreset(Entity* pEntToAdd, int whichModule = 0, bool overwriteSame = false, std::string readFromFile = "Same"); + bool AddEntityPreset(Entity* pEntToAdd, int whichModule = 0, bool overwriteSame = false, const std::string& readFromFile = "Same"); /// Gets a previously read in (defined) Entity, by type and instance name. /// @param type The type name of the derived Entity. Ownership is NOT transferred! @@ -143,9 +143,9 @@ namespace RTE { /// the official modules will be searched also. -1 means search ALL modules! /// @return A pointer to the requested Entity instance. 0 if no Entity with that /// derived type or instance name was found. Ownership is NOT transferred! - const Entity* GetEntityPreset(std::string type, std::string preset, int whichModule = -1); + const Entity* GetEntityPreset(const std::string& type, std::string preset, int whichModule = -1); // Helper for passing in string module name instead of ID - const Entity* GetEntityPreset(std::string type, std::string preset, std::string module) { return GetEntityPreset(type, preset, GetModuleID(module)); } + const Entity* GetEntityPreset(const std::string& type, std::string preset, std::string module) { return GetEntityPreset(type, std::move(preset), GetModuleID(std::move(module))); } /// Reads an instance of an Entity that will be used as preset /// to later on be used to generate more instances of the same state. @@ -173,7 +173,7 @@ namespace RTE { /// @param whichModule The type name of the Entitys you want. (default: -1) /// Whether to only get those of one specific DataModule (0-n), or all (-1). /// @return Whether any Entity:s were found and added to the list. - bool GetAllOfType(std::list& entityList, std::string type, int whichModule = -1); + bool GetAllOfType(std::list& entityList, const std::string& type, int whichModule = -1); /// Adds to a list all previously read in (defined) Entitys which are /// of a specific type, and only exist in a specific module space. @@ -184,7 +184,7 @@ namespace RTE { /// official modules loaded earlier than the one specified here. -1 means /// get ALL groups ever reg'd. /// @return Whether any Entity:s were found and added to the list. - bool GetAllOfTypeInModuleSpace(std::list& entityList, std::string type, int whichModuleSpace); + bool GetAllOfTypeInModuleSpace(std::list& entityList, const std::string& type, int whichModuleSpace); /// Adds to a list all previously read in (defined) Entities which are associated with a specific group. /// @param entityList Reference to a list which will get all matching Entities added to it. Ownership of the list or the Entities placed in it are NOT transferred! @@ -225,7 +225,7 @@ namespace RTE { /// "All" will look at all types. /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1). (default: -1) /// @return The Entity preset that was randomly selected. Ownership is NOT transferred! - Entity* GetRandomOfGroup(std::string group, std::string type = "All", int whichModule = -1); + Entity* GetRandomOfGroup(std::string group, const std::string& type = "All", int whichModule = -1); /// Returns a previously read in (defined) Entity which is randomly /// selected from a specific group only if it belongs to some tech. @@ -235,7 +235,7 @@ namespace RTE { /// @param whichModule Whether to only get those of one specific DataModule (0-n), or all (-1) (default: -1) /// or all modules uncluding non-tech ones. /// @return The Entity preset that was randomly selected. Ownership is NOT transferred! - Entity* GetRandomBuyableOfGroupFromTech(std::string group, std::string type = "All", int whichModule = -1); + Entity* GetRandomBuyableOfGroupFromTech(std::string group, const std::string& type = "All", int whichModule = -1); /// Adds to a list all previously read in (defined) Entitys which are /// associated with a specific group, and only exist in a specific module @@ -249,7 +249,7 @@ namespace RTE { /// official modules loaded earlier than the one specified here. -1 means /// get ALL groups ever reg'd. /// @return Whether any Entity:s were found and added to the list. - bool GetAllOfGroupInModuleSpace(std::list& entityList, std::string group, std::string type, int whichModuleSpace); + bool GetAllOfGroupInModuleSpace(std::list& entityList, const std::string& group, const std::string& type, int whichModuleSpace); /// Returns a previously read in (defined) Entity which is associated with /// a specific group, randomly selected and only exist in a specific module @@ -263,7 +263,7 @@ namespace RTE { /// get ALL groups ever reg'd. /// @return The randomly select preset, if any was found with thse search params. /// Ownership is NOT transferred! - Entity* GetRandomOfGroupInModuleSpace(std::string group, std::string type, int whichModuleSpace); + Entity* GetRandomOfGroupInModuleSpace(const std::string& group, const std::string& type, int whichModuleSpace); /// Gets the data file path of a previously read in (defined) Entity. /// @param type The type name of the derived Entity. Ownership is NOT transferred! @@ -272,7 +272,7 @@ namespace RTE { /// the official modules will be searched also. /// @return The file path of the data file that the specified Entity was read from. /// If no Entity of that description was found, "" is returned. - std::string GetEntityDataLocation(std::string type, std::string preset, int whichModule); + std::string GetEntityDataLocation(const std::string& type, const std::string& preset, int whichModule); /// Reloads all scripted Entity Presets with the latest version of their respective script files. void ReloadAllScripts() const; @@ -323,7 +323,7 @@ namespace RTE { /// @param withType Pass a type name here and only groups with entitys of that type will be (default: "All") /// be included. "All" means don't consider what types are in the groups. /// @return Whether any groups were found and thus added to the list. - bool GetGroups(std::list& groupList, int whichModule = -1, std::string withType = "All") const; + bool GetGroups(std::list& groupList, int whichModule = -1, const std::string& withType = "All") const; /// Fills out a list with all groups registered in all official modules, /// PLUS a specific non-official module as well. @@ -334,7 +334,7 @@ namespace RTE { /// @param withType Pass a type name here and only groups with entitys of that type will be (default: "All") /// be included. "All" means don't consider what types are in the groups. /// @return Whether any groups were found and thus added to the list. - bool GetModuleSpaceGroups(std::list& groupList, int whichModule, std::string withType = "All") const; + bool GetModuleSpaceGroups(std::list& groupList, int whichModule, const std::string& withType = "All") const; /// Creates and returns actor defined in the specified loadout. /// @param loadoutName Loadout preset name, module name, whether or not spawn delivery craft defined for that loadout diff --git a/Source/Managers/SceneMan.cpp b/Source/Managers/SceneMan.cpp index 346db5e84b..2fd0682046 100644 --- a/Source/Managers/SceneMan.cpp +++ b/Source/Managers/SceneMan.cpp @@ -3,7 +3,6 @@ #include "PresetMan.h" #include "FrameMan.h" #include "ActivityMan.h" -#include "UInputMan.h" #include "CameraMan.h" #include "ConsoleMan.h" #include "PrimitiveMan.h" @@ -14,14 +13,10 @@ #include "TerrainObject.h" #include "MovableObject.h" #include "ContentFile.h" -#include "AHuman.h" -#include "ACRocket.h" #include "MOPixel.h" #include "Atom.h" #include "Material.h" #include "SoundContainer.h" -// Temp -#include "Controller.h" #include "tracy/Tracy.hpp" @@ -91,7 +86,7 @@ void SceneMan::Initialize() const { {512, create_bitmap_ex(8, 512, 512)}}; } -int SceneMan::Create(std::string readerFile) { +int SceneMan::Create(const std::string& readerFile) { Reader* reader = new Reader(); if (reader->Create(readerFile.c_str())) g_ConsoleMan.PrintString("ERROR: Could not find Scene definition file!"); @@ -133,7 +128,6 @@ int SceneMan::LoadScene(Scene* pNewScene, bool placeObjects, bool placeUnits) { g_ConsoleMan.PrintString("SYSTEM: Scene \"" + m_pCurrentScene->GetPresetName() + "\" was loaded"); // Set the proper scales of the unseen obscuring SceneLayers - SceneLayer* pUnseenLayer = 0; for (int team = Activity::TeamOne; team < Activity::MaxTeamCount; ++team) { if (!g_ActivityMan.GetActivity()->TeamActive(team)) continue; @@ -177,7 +171,7 @@ int SceneMan::LoadScene(Scene* pNewScene, bool placeObjects, bool placeUnits) { return 0; } -int SceneMan::SetSceneToLoad(std::string sceneName, bool placeObjects, bool placeUnits) { +int SceneMan::SetSceneToLoad(const std::string& sceneName, bool placeObjects, bool placeUnits) { // Use the name passed in to load the preset requested const Scene* pSceneRef = dynamic_cast(g_PresetMan.GetEntityPreset("Scene", sceneName)); @@ -209,7 +203,7 @@ int SceneMan::LoadScene() { return LoadScene(dynamic_cast(m_pSceneToLoad->Clone()), m_PlaceObjects, m_PlaceUnits); } -int SceneMan::LoadScene(std::string sceneName, bool placeObjects, bool placeUnits) { +int SceneMan::LoadScene(const std::string& sceneName, bool placeObjects, bool placeUnits) { // First retrieve and set up the preset reference int error = SetSceneToLoad(sceneName, placeObjects, placeUnits); if (error < 0) @@ -903,7 +897,7 @@ void SceneMan::MakeAllUnseen(Vector pixelSize, const int team) { m_pCurrentScene->FillUnseenLayer(pixelSize, team); } -bool SceneMan::LoadUnseenLayer(std::string bitmapPath, int team) { +bool SceneMan::LoadUnseenLayer(const std::string& bitmapPath, int team) { ContentFile bitmapFile(bitmapPath.c_str()); SceneLayer* pUnseenLayer = new SceneLayer(); if (pUnseenLayer->Create(bitmapFile.GetAsBitmap(COLORCONV_NONE, false), true, Vector(), m_pCurrentScene->WrapsX(), m_pCurrentScene->WrapsY(), Vector(1.0, 1.0)) < 0) { @@ -1046,7 +1040,7 @@ void SceneMan::RestoreUnseenBox(const int posX, const int posY, const int width, } bool SceneMan::CastTerrainPenetrationRay(const Vector& start, const Vector& ray, Vector& endPos, int strengthLimit, int skip) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; bool stopped = false; unsigned char materialID; @@ -1138,7 +1132,7 @@ bool SceneMan::CastUnseenRay(int team, const Vector& start, const Vector& ray, V if (!m_pCurrentScene->GetUnseenLayer(team)) return false; - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int size = 40 - GetUnseenResolution(team).GetLargest(); int intPos[2], delta[2], delta2[2], increment[2]; bool affectedAny = false; @@ -1202,14 +1196,18 @@ bool SceneMan::CastUnseenRay(int team, const Vector& start, const Vector& ray, V // Scene wrapping WrapPosition(intPos[X], intPos[Y]); + bool is_unseen = IsUnseen(intPos[X], intPos[Y], team) || IsUnseen(intPos[X] - size, intPos[Y] - size, team) || IsUnseen(intPos[X] + size, intPos[Y] - size, team) || IsUnseen(intPos[X] + size, intPos[Y] + size, team) || IsUnseen(intPos[X] - size, intPos[Y] + size, team) || IsUnseen(intPos[X] - size, intPos[Y], team) || IsUnseen(intPos[X] + size, intPos[Y], team) || IsUnseen(intPos[X], intPos[Y] - size, team) || IsUnseen(intPos[X], intPos[Y] + size, team); + // Reveal if we can, save the result if (reveal) { - if (affectedAny = IsUnseen(intPos[X], intPos[Y], team) || IsUnseen(intPos[X] - size, intPos[Y] - size, team) || IsUnseen(intPos[X] + size, intPos[Y] - size, team) || IsUnseen(intPos[X] + size, intPos[Y] + size, team) || IsUnseen(intPos[X] - size, intPos[Y] + size, team) || IsUnseen(intPos[X] - size, intPos[Y], team) || IsUnseen(intPos[X] + size, intPos[Y], team) || IsUnseen(intPos[X], intPos[Y] - size, team) || IsUnseen(intPos[X], intPos[Y] + size, team)) { + if (is_unseen) { RevealUnseenBox(intPos[X] - size / 2, intPos[Y] - size / 2, size, size, team); + affectedAny = true; } } else { - if (affectedAny = !(IsUnseen(intPos[X], intPos[Y], team) || IsUnseen(intPos[X] - size, intPos[Y] - size, team) || IsUnseen(intPos[X] + size, intPos[Y] - size, team) || IsUnseen(intPos[X] + size, intPos[Y] + size, team) || IsUnseen(intPos[X] - size, intPos[Y] + size, team) || IsUnseen(intPos[X] - size, intPos[Y], team) || IsUnseen(intPos[X] + size, intPos[Y], team) || IsUnseen(intPos[X], intPos[Y] - size, team) || IsUnseen(intPos[X], intPos[Y] + size, team))) { + if (!is_unseen) { RestoreUnseenBox(intPos[X] - size / 2, intPos[Y] - size / 2, size, size, team); + affectedAny = true; } } @@ -1246,7 +1244,7 @@ bool SceneMan::CastUnseeRay(int team, const Vector& start, const Vector& ray, Ve bool SceneMan::CastMaterialRay(const Vector& start, const Vector& ray, unsigned char material, Vector& result, int skip, bool wrap) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; bool foundPixel = false; @@ -1339,7 +1337,7 @@ float SceneMan::CastMaterialRay(const Vector& start, const Vector& ray, unsigned } bool SceneMan::CastNotMaterialRay(const Vector& start, const Vector& ray, unsigned char material, Vector& result, int skip, bool checkMOs) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; bool foundPixel = false; @@ -1437,7 +1435,6 @@ float SceneMan::CastStrengthSumRay(const Vector& start, const Vector& end, int s int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; - bool foundPixel = false; unsigned char materialID; Material foundMaterial; @@ -1522,7 +1519,6 @@ const Material* SceneMan::CastMaxStrengthRayMaterial(const Vector& start, const int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; - bool foundPixel = false; intPos[X] = std::floor(start.m_X); intPos[Y] = std::floor(start.m_Y); @@ -1600,7 +1596,7 @@ const Material* SceneMan::CastMaxStrengthRayMaterial(const Vector& start, const } bool SceneMan::CastStrengthRay(const Vector& start, const Vector& ray, float strength, Vector& result, int skip, unsigned char ignoreMaterial, bool wrap) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; bool foundPixel = false; unsigned char materialID; @@ -1693,7 +1689,7 @@ bool SceneMan::CastStrengthRay(const Vector& start, const Vector& ray, float str } bool SceneMan::CastWeaknessRay(const Vector& start, const Vector& ray, float strength, Vector& result, int skip, bool wrap) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; bool foundPixel = false; unsigned char materialID; @@ -1783,7 +1779,7 @@ bool SceneMan::CastWeaknessRay(const Vector& start, const Vector& ray, float str } MOID SceneMan::CastMORay(const Vector& start, const Vector& ray, const std::vector& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, bool ignoreAllTerrain, int skip) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; MOID hitMOID = g_NoMOID; unsigned char hitTerrain = 0; @@ -1884,7 +1880,7 @@ MOID SceneMan::CastMORay(const Vector& start, const Vector& ray, const std::vect } bool SceneMan::CastFindMORay(const Vector& start, const Vector& ray, MOID targetMOID, Vector& resultPos, unsigned char ignoreMaterial, bool ignoreAllTerrain, int skip, bool findChildMOIDs) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; MOID hitMOID = g_NoMOID; unsigned char hitTerrain = 0; @@ -1980,7 +1976,7 @@ const std::vector* SceneMan::CastAllMOsRay(const Vector& start, const SpatialPartitionGrid& partitionGrid = GetMOIDGrid(); - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; unsigned char hitTerrain = 0; @@ -2041,7 +2037,7 @@ const std::vector* SceneMan::CastAllMOsRay(const Vector& start, // Detect MOs std::vector hitMOs; - hitMOs = std::move(partitionGrid.GetMOsAtPosition(intPos[X], intPos[Y], ignoreTeam, false)); + hitMOs = partitionGrid.GetMOsAtPosition(intPos[X], intPos[Y], ignoreTeam, false); // Loop through the gotten MOs and check if we're ignoring their IDs - if not, put them onto our return vector for (MovableObject* mo : hitMOs) { @@ -2078,7 +2074,7 @@ const std::vector* SceneMan::CastAllMOsRay(const Vector& start, } float SceneMan::CastObstacleRay(const Vector& start, const Vector& ray, Vector& obstaclePos, Vector& freePos, const std::vector& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, int skip) { - int hitCount = 0, error, dom, sub, domSteps, skipped = skip; + int error, dom, sub, domSteps, skipped = skip; int intPos[2], delta[2], delta2[2], increment[2]; bool hitObstacle = false; @@ -2591,11 +2587,11 @@ void SceneMan::Draw(BITMAP* targetBitmap, BITMAP* targetGUIBitmap, const Vector& Box targetDimensions(Vector(), targetBitmap->w, targetBitmap->h); if (!terrain->WrapsX() && targetBitmap->w > GetSceneWidth()) { - targetBox.SetCorner(Vector(static_cast((targetBitmap->w - GetSceneWidth()) / 2), targetBox.GetCorner().GetY())); + targetBox.SetCorner(Vector(static_cast((targetBitmap->w - GetSceneWidth())) / 2, targetBox.GetCorner().GetY())); targetBox.SetWidth(static_cast(GetSceneWidth())); } if (!terrain->WrapsY() && targetBitmap->h > GetSceneHeight()) { - targetBox.SetCorner(Vector(targetBox.GetCorner().GetX(), static_cast((targetBitmap->h - GetSceneHeight()) / 2))); + targetBox.SetCorner(Vector(targetBox.GetCorner().GetX(), static_cast((targetBitmap->h - GetSceneHeight())) / 2)); targetBox.SetHeight(static_cast(GetSceneHeight())); } @@ -2656,7 +2652,7 @@ void SceneMan::Draw(BITMAP* targetBitmap, BITMAP* targetGUIBitmap, const Vector& static int s_drawPathfinderDebugForTeam = -2; if (s_drawPathfinderDebugForTeam > -2) { - m_pCurrentScene->GetPathFinder(static_cast(s_drawPathfinderDebugForTeam)).DebugRender(targetBitmap, targetPos, m_LastUpdatedScreen); + m_pCurrentScene->GetPathFinder(static_cast(s_drawPathfinderDebugForTeam)).DebugRender(targetBitmap, targetPos); } if (m_pDebugLayer) { diff --git a/Source/Managers/SceneMan.h b/Source/Managers/SceneMan.h index de205a77f6..068bc1e2c1 100644 --- a/Source/Managers/SceneMan.h +++ b/Source/Managers/SceneMan.h @@ -69,26 +69,26 @@ namespace RTE { /// Makes the SceneMan object ready for use. /// @param readerFile A string with the filepath to a Reader file from screen this SceneMan's /// data should be created. - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int Create(std::string readerFile); + int Create(const std::string& readerFile); /// Sets the instance name of the default Scene to be loaded if nothing /// else is available. /// @param defaultSceneName The default scene instance name. - void SetDefaultSceneName(std::string defaultSceneName) { m_DefaultSceneName = defaultSceneName; } + void SetDefaultSceneName(std::string defaultSceneName) { m_DefaultSceneName = std::move(defaultSceneName); } /// Gets the name of the default A to be loaded if nothing /// else is available. /// @return The default Scene instance name. - std::string GetDefaultSceneName() const { return m_DefaultSceneName; } + const std::string& GetDefaultSceneName() const { return m_DefaultSceneName; } /// Actually loads a new Scene into memory. has to be done before using /// this object. /// @param pNewScene The instance of the Scene, ownership IS transferred! /// @param placeObjects Whether the scene should actually apply all its SceneObject:s placed (default: true) /// in its definition. - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. int LoadScene(Scene* pNewScene, bool placeObjects = true, bool placeUnits = true); @@ -106,9 +106,9 @@ namespace RTE { /// @param sceneName The name of the Scene preset instance to load. /// @param placeObjects Whether the scene should actually apply all its SceneObject:s placed (default: true) /// in its definition. - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int SetSceneToLoad(std::string sceneName, bool placeObjects = true, bool placeUnits = true); + int SetSceneToLoad(const std::string& sceneName, bool placeObjects = true, bool placeUnits = true); /// Gets the stored Scene reference to be loaded later into the SceneMan. /// @return The instance reference of the Scene, ownership IS NOT (!!) transferred! @@ -123,7 +123,7 @@ namespace RTE { bool GetPlaceUnitsOnLoad() const { return m_PlaceUnits; } /// Actually loads the Scene set to be loaded in SetSceneToLoad. - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. int LoadScene(); @@ -132,17 +132,17 @@ namespace RTE { /// @param placeObjects Whether the scene should actually apply all its SceneObject:s placed (default: true) /// in its definition. /// @param placeUnits Whether the scene should actually deploy all units placed in its definition. (default: true) - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int LoadScene(std::string sceneName, bool placeObjects = true, bool placeUnits = true); + int LoadScene(const std::string& sceneName, bool placeObjects = true, bool placeUnits = true); /// Loads a Scene right now, by preset name. /// @param sceneName The name of the Scene preset instance to load. /// @param placeObjects Whether the scene should actually apply all its SceneObject:s placed (default: true) { return LoadScene(sceneName) /// in its definition. - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int LoadScene(std::string sceneName, bool placeObjects = true) { return LoadScene(sceneName, placeObjects, true); } + int LoadScene(const std::string& sceneName, bool placeObjects = true) { return LoadScene(sceneName, placeObjects, true); } /// Resets the entire SceneMan, including its inherited members, to /// their default settings or values. @@ -440,7 +440,7 @@ namespace RTE { /// @param bitmapPath The path to the bitmap to use as the unseen layer. /// @param team Which team we're talking about. /// @return Whether the loading was successful or not. - bool LoadUnseenLayer(std::string bitmapPath, const int team); + bool LoadUnseenLayer(const std::string& bitmapPath, const int team); /// Tells whether a team has anything still unseen on the scene. /// @param team The team we're talking about. diff --git a/Source/Managers/SettingsMan.h b/Source/Managers/SettingsMan.h index e7b0d061f6..4bb438cdfb 100644 --- a/Source/Managers/SettingsMan.h +++ b/Source/Managers/SettingsMan.h @@ -203,7 +203,7 @@ namespace RTE { #pragma region Network Settings /// Gets the player name that is used in network multiplayer matches. /// @return String with the network player name. - std::string GetPlayerNetworkName() const { return m_PlayerNetworkName; } + const std::string& GetPlayerNetworkName() const { return m_PlayerNetworkName; } /// Sets the player name that will be used in network multiplayer matches. /// @param newName String with the new player name to use. @@ -211,7 +211,7 @@ namespace RTE { /// Gets the LAN server address to connect to. /// @return The current LAN server address to connect to. - std::string GetNetworkServerAddress() const { return m_NetworkServerAddress; } + const std::string& GetNetworkServerAddress() const { return m_NetworkServerAddress; } /// Sets the LAN server address to connect to. /// @param newName New LAN server address to connect to. @@ -219,7 +219,7 @@ namespace RTE { /// Gets the NAT punch-through server address. /// @return The current NAT punch-through server address to connect to. - std::string& GetNATServiceAddress() { return m_NATServiceAddress; } + const std::string& GetNATServiceAddress() { return m_NATServiceAddress; } /// Sets the NAT punch-through server address. /// @param newValue New NAT punch-through server address to connect to. @@ -227,7 +227,7 @@ namespace RTE { /// Gets the server name used when connecting via NAT punch-through service. /// @return Name of the NAT punch-through server. - std::string& GetNATServerName() { return m_NATServerName; } + const std::string& GetNATServerName() { return m_NATServerName; } /// Sets the server name to use when connecting via NAT punch-through service. /// @param newValue New NAT punch-through server name. @@ -235,7 +235,7 @@ namespace RTE { /// Gets the server password to use when connecting via NAT punch-through service. /// @return The server password to use when connecting via NAT punch-through service. - std::string& GetNATServerPassword() { return m_NATServerPassword; } + const std::string& GetNATServerPassword() { return m_NATServerPassword; } /// Sets the server password to use when connecting via NAT punch-through service. /// @param newValue New password to use when connecting via NAT punch-through service. @@ -253,7 +253,7 @@ namespace RTE { #pragma region Editor Settings /// Returns the list of visible assembly groups. /// @return List of visible assembly groups. - std::list GetVisibleAssemblyGroupsList() const { return m_VisibleAssemblyGroupsList; } + const std::list& GetVisibleAssemblyGroupsList() const { return m_VisibleAssemblyGroupsList; } /// Whether editors will allow to select Base.rte as a module to save in /// @return True of editors are allowed to select Base.rte as a module to save in. diff --git a/Source/Managers/UInputMan.cpp b/Source/Managers/UInputMan.cpp index 882b481c42..a1d4c261ff 100644 --- a/Source/Managers/UInputMan.cpp +++ b/Source/Managers/UInputMan.cpp @@ -14,6 +14,7 @@ #include "System.h" #include +#include #include #include diff --git a/Source/Managers/WindowMan.cpp b/Source/Managers/WindowMan.cpp index bfd3a2da11..51c87a1616 100644 --- a/Source/Managers/WindowMan.cpp +++ b/Source/Managers/WindowMan.cpp @@ -136,7 +136,7 @@ void WindowMan::Initialize() { ImGui::StyleColorsDark(); ImGui_ImplSDL3_InitForOpenGL(m_PrimaryWindow.get(), m_GLContext.get()); - ImGui_ImplOpenGL3_Init("#version 130"); + ImGui_ImplOpenGL3_Init("#version 330 core"); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL3_NewFrame(); ImGui::NewFrame(); @@ -675,12 +675,14 @@ void WindowMan::DisplaySwitchOut() const { SDL_SetCursor(nullptr); } -void WindowMan::HandleWindowExposedEvent(void *userdata, SDL_Event *event) { +bool WindowMan::HandleWindowExposedEvent(void *userdata, SDL_Event *event) { if (event->type == SDL_EVENT_WINDOW_EXPOSED) { g_WindowMan.SetViewportLetterboxed(); g_WindowMan.ClearBackbuffer(false); g_WindowMan.UploadFrame(); } + + return true; } void WindowMan::QueueWindowEvent(const SDL_Event& windowEvent) { diff --git a/Source/Managers/WindowMan.h b/Source/Managers/WindowMan.h index 3295c1ef44..53452dbed2 100644 --- a/Source/Managers/WindowMan.h +++ b/Source/Managers/WindowMan.h @@ -168,8 +168,8 @@ namespace RTE { #pragma endregion #pragma region Concrete Methods - /// SDL_EventFilter to hadnle window exposed events for live resize. - static void HandleWindowExposedEvent(void* userdata, SDL_Event* event); + /// SDL_EventFilter to handle window exposed events for live resize. + static bool HandleWindowExposedEvent(void* userdata, SDL_Event* event); /// Adds an SDL_Event to the Event queue for processing on Update. /// @param windowEvent The SDL window event to queue. diff --git a/Source/Menus/AreaEditorGUI.cpp b/Source/Menus/AreaEditorGUI.cpp index e199bdac1f..e67551a769 100644 --- a/Source/Menus/AreaEditorGUI.cpp +++ b/Source/Menus/AreaEditorGUI.cpp @@ -120,7 +120,7 @@ void AreaEditorGUI::SetCurrentArea(Scene::Area* pArea) { } } -void AreaEditorGUI::UpdatePickerList(std::string selectAreaName) { +void AreaEditorGUI::UpdatePickerList(const std::string& selectAreaName) { m_pPicker->UpdateAreasList(selectAreaName); } diff --git a/Source/Menus/AreaEditorGUI.h b/Source/Menus/AreaEditorGUI.h index d7b0a97a1d..db0b6aac8f 100644 --- a/Source/Menus/AreaEditorGUI.h +++ b/Source/Menus/AreaEditorGUI.h @@ -107,7 +107,7 @@ namespace RTE { /// Updates the list that the GUI's Area picker has, from the current /// scene state. /// @param selectAreaName The name of the Area to leave selected after the list is updated. (default: "") - void UpdatePickerList(std::string selectAreaName = ""); + void UpdatePickerList(const std::string& selectAreaName = ""); /// Updates the state of this Menu each frame void Update(); diff --git a/Source/Menus/AreaPickerGUI.cpp b/Source/Menus/AreaPickerGUI.cpp index f2858b3c7c..ce370c9b51 100644 --- a/Source/Menus/AreaPickerGUI.cpp +++ b/Source/Menus/AreaPickerGUI.cpp @@ -53,7 +53,7 @@ void AreaPickerGUI::Clear() { m_CursorPos.Reset(); } -int AreaPickerGUI::Create(Controller* pController, std::string onlyOfType) { +int AreaPickerGUI::Create(Controller* pController, const std::string& onlyOfType) { RTEAssert(pController, "No controller sent to AreaPickerGUI on creation!"); m_pController = pController; @@ -77,7 +77,7 @@ int AreaPickerGUI::Create(Controller* pController, std::string onlyOfType) { // Stretch the invisible root box to fill the screen dynamic_cast(m_pGUIController->GetControl("base"))->SetSize(g_WindowMan.GetResX(), g_WindowMan.GetResY()); - // Make sure we have convenient points to teh containing GUI colleciton boxes that we will manipulate the positions of + // Make sure we have convenient points to the containing GUI colleciton boxes that we will manipulate the positions of if (!m_pParentBox) { m_pParentBox = dynamic_cast(m_pGUIController->GetControl("PickerGUIBox")); @@ -194,7 +194,7 @@ Scene::Area* AreaPickerGUI::GetPrevArea() { return 0; } -void AreaPickerGUI::UpdateAreasList(std::string selectAreaName) { +void AreaPickerGUI::UpdateAreasList(const std::string& selectAreaName) { m_pAreasList->ClearList(); if (g_SceneMan.GetScene() && !g_SceneMan.GetScene()->m_AreaList.empty()) { diff --git a/Source/Menus/AreaPickerGUI.h b/Source/Menus/AreaPickerGUI.h index 33f726d521..ca416b11c1 100644 --- a/Source/Menus/AreaPickerGUI.h +++ b/Source/Menus/AreaPickerGUI.h @@ -37,12 +37,12 @@ namespace RTE { ~AreaPickerGUI(); /// Makes the AreaPickerGUI area ready for use. - /// @param pController A poitner to a Controller which will control this Menu. Ownership is + /// @param pController A pointer to a Controller which will control this Menu. Ownership is /// @param onlyOfType NOT TRANSFERRED! (default: "All") /// Which lowest common denominator type to be showing. - /// @return An error return value signaling sucess or any particular failure. + /// @return An error return value signaling success or any particular failure. /// Anything below 0 is an error signal. - int Create(Controller* pController, std::string onlyOfType = "All"); + int Create(Controller* pController, const std::string& onlyOfType = "All"); /// Resets the entire AreaPickerGUI, including its inherited members, to /// their default settings or values. @@ -98,7 +98,7 @@ namespace RTE { /// Adds all areas of the currently selected group to the Areas list. /// @param selectAreaName The name of the Area to leave selected after the list is updated. (default: "") - void UpdateAreasList(std::string selectAreaName = ""); + void UpdateAreasList(const std::string& selectAreaName = ""); /// Updates the state of this Menu each frame void Update(); diff --git a/Source/Menus/AssemblyEditorGUI.h b/Source/Menus/AssemblyEditorGUI.h index 7ea76f9718..521d7fac95 100644 --- a/Source/Menus/AssemblyEditorGUI.h +++ b/Source/Menus/AssemblyEditorGUI.h @@ -152,11 +152,11 @@ namespace RTE { /// Returns the name of currently edited assembly /// @return Name of currently edited assembly. - std::string GetCurrentAssemblyName() { return m_CurrentAssemblyName; } + const std::string& GetCurrentAssemblyName() { return m_CurrentAssemblyName; } /// Sets new name of currently edited assembly /// @param newName New name for assembly. - void SetCurrentAssemblyName(std::string newName) { m_CurrentAssemblyName = newName; } + void SetCurrentAssemblyName(std::string newName) { m_CurrentAssemblyName = std::move(newName); } /// Protected member variable and method declarations protected: diff --git a/Source/Menus/BuyMenuGUI.h b/Source/Menus/BuyMenuGUI.h index 72aebf91e5..955da7afc3 100644 --- a/Source/Menus/BuyMenuGUI.h +++ b/Source/Menus/BuyMenuGUI.h @@ -198,11 +198,11 @@ namespace RTE { /// If the list is not empty then everything not in the list is removed from the buy menu /// Items will be removed from the buy menu when it's called, category changed or after a ForceRefresh(). /// @param presetName Full preset name to add. - void AddAllowedItem(std::string presetName) { m_AllowedItems[presetName] = true; }; + void AddAllowedItem(std::string presetName) { m_AllowedItems[std::move(presetName)] = true; }; /// Removes an item from the list of allowed items. /// @param m_AllowedItems.erase(presetName Full preset name to remove. - void RemoveAllowedItem(std::string presetName) { m_AllowedItems.erase(presetName); }; + void RemoveAllowedItem(const std::string& presetName) { m_AllowedItems.erase(presetName); }; /// Clears the list of allowed items void ClearAllowedItems() { m_AllowedItems.clear(); }; @@ -213,11 +213,11 @@ namespace RTE { /// Adds an item to the list of always allowed items. This list overrides all previous constraints. /// @param presetName Full preset name to add. - void AddAlwaysAllowedItem(std::string presetName) { m_AlwaysAllowedItems[presetName] = true; }; + void AddAlwaysAllowedItem(std::string presetName) { m_AlwaysAllowedItems[std::move(presetName)] = true; }; /// Removes an item from the list of always allowed items. /// @param m_AlwaysAllowedItems.erase(presetName Full preset name to remove. - void RemoveAlwaysAllowedItem(std::string presetName) { m_AlwaysAllowedItems.erase(presetName); }; + void RemoveAlwaysAllowedItem(const std::string& presetName) { m_AlwaysAllowedItems.erase(presetName); }; /// Clears the list of allowed items void ClearAlwaysAllowedItems() { m_AlwaysAllowedItems.clear(); }; @@ -229,11 +229,11 @@ namespace RTE { /// Adds an item prohibited to buy from the buy menu. /// The item will be removed from the buy menu when it's called, category changed or after a ForceRefresh(). /// @param presetName Full preset name to add. - void AddProhibitedItem(std::string presetName) { m_ProhibitedItems[presetName] = true; }; + void AddProhibitedItem(std::string presetName) { m_ProhibitedItems[std::move(presetName)] = true; }; /// Removes item from the list of prohibited items /// @param m_ProhibitedItems.erase(presetName Full preset name to remove. - void RemoveProhibitedItem(std::string presetName) { m_ProhibitedItems.erase(presetName); }; + void RemoveProhibitedItem(const std::string& presetName) { m_ProhibitedItems.erase(presetName); }; /// Clears the list of prohibited items void ClearProhibitedItems() { m_ProhibitedItems.clear(); }; @@ -273,7 +273,7 @@ namespace RTE { /// Sets the amount of specified items to be owned in this buy menu /// @param presetName Full preset name of item to own. Amount of owned items. - void SetOwnedItemsAmount(std::string presetName, int amount) { m_OwnedItems[presetName] = amount; }; + void SetOwnedItemsAmount(std::string presetName, int amount) { m_OwnedItems[std::move(presetName)] = amount; }; /// Returns the amount of specified items owned in this buy menu /// @param presetName Full preset name of item. diff --git a/Source/Menus/InventoryMenuGUI.cpp b/Source/Menus/InventoryMenuGUI.cpp index b7563521ef..469ce8131e 100644 --- a/Source/Menus/InventoryMenuGUI.cpp +++ b/Source/Menus/InventoryMenuGUI.cpp @@ -1421,7 +1421,7 @@ void InventoryMenuGUI::DrawCarouselItemBoxForeground(const CarouselItemBox& item }); std::string massString = totalItemMass < 0.1F ? "<0.1 kg" : RoundFloatToPrecision(std::fminf(999, totalItemMass), (totalItemMass < 9.95F ? 1 : 0)) + (totalItemMass > 999 ? "+ " : " ") + "kg"; - m_SmallFont->DrawAligned(carouselAllegroBitmap, itemBoxToDraw.IconCenterPosition.GetFloorIntX(), itemBoxToDraw.IconCenterPosition.GetFloorIntY() - ((itemBoxToDraw.CurrentSize.GetFloorIntY() + m_SmallFont->GetFontHeight()) / 2) + 1, massString.c_str(), GUIFont::Centre); + m_SmallFont->DrawAligned(carouselAllegroBitmap, itemBoxToDraw.IconCenterPosition.GetFloorIntX(), itemBoxToDraw.IconCenterPosition.GetFloorIntY() - ((itemBoxToDraw.CurrentSize.GetFloorIntY() + m_SmallFont->GetFontHeight()) / 2) + 1, massString, GUIFont::Centre); } void InventoryMenuGUI::DrawFullMode(BITMAP* targetBitmap, const Vector& drawPos) const { diff --git a/Source/Menus/MainMenuGUI.h b/Source/Menus/MainMenuGUI.h index c56c51e8e7..5e80a505e1 100644 --- a/Source/Menus/MainMenuGUI.h +++ b/Source/Menus/MainMenuGUI.h @@ -6,6 +6,8 @@ #include "SettingsGUI.h" #include "ModManagerGUI.h" +#include + namespace RTE { class AllegroScreen; diff --git a/Source/Menus/MetagameGUI.cpp b/Source/Menus/MetagameGUI.cpp index be5100127b..3884a63a30 100644 --- a/Source/Menus/MetagameGUI.cpp +++ b/Source/Menus/MetagameGUI.cpp @@ -157,7 +157,7 @@ void MetagameGUI::Clear() { m_AnimMetaPlayer = Players::NoPlayer; m_AnimDefenseTeam = Activity::NoTeam; m_AnimActivityChange = false; - Scene* m_pAnimScene = 0; + m_pAnimScene = 0; m_AnimRatio = 0; m_AnimProgress = 0; m_AnimTotalFunds = 0; @@ -594,7 +594,7 @@ void MetagameGUI::MoveLocationsIntoTheScreen() { // We need to calculate planet center manually because m_PlanetCenter reflects coords of moving planet // which is outside the screen when this is called first time - Vector planetCenter = Vector(m_RootBoxMaxWidth / 2, g_WindowMan.GetResY() / 2); + Vector planetCenter = Vector(m_RootBoxMaxWidth / 2.0, g_WindowMan.GetResY() / 2.0); // Correct planet pos a bit when it's location is known if (!m_PlanetCenter.IsZero()) planetCenter = m_PlanetCenter; @@ -799,7 +799,7 @@ void MetagameGUI::SelectScene(Scene* pScene) { } } -bool MetagameGUI::SelectScene(std::string sceneName) { +bool MetagameGUI::SelectScene(const std::string& sceneName) { for (std::vector::iterator sItr = g_MetaMan.m_Scenes.begin(); sItr != g_MetaMan.m_Scenes.end(); ++sItr) { // Only allow selection if the Scene is revealed yet! if ((*sItr)->GetPresetName() == sceneName && (*sItr)->IsRevealed()) { @@ -828,33 +828,32 @@ void MetagameGUI::SwitchToScreen(int newScreen) { } std::string MetagameGUI::GetRoundName(int roundNumber) { - if (roundNumber < 12) { - if (roundNumber == 0) - return "ONE"; - else if (roundNumber == 1) - return "TWO"; - else if (roundNumber == 2) - return "THREE"; - else if (roundNumber == 3) - return "FOUR"; - else if (roundNumber == 4) - return "FIVE"; - else if (roundNumber == 5) - return "SIX"; - else if (roundNumber == 6) - return "SEVEN"; - else if (roundNumber == 7) - return "EIGHT"; - else if (roundNumber == 8) - return "NINE"; - else if (roundNumber == 9) - return "TEN"; - else if (roundNumber == 10) - return "ELEVEN"; - else if (roundNumber == 11) - return "TWELVE"; - } - char numStr[8]; + if (roundNumber == 0) + return "ONE"; + else if (roundNumber == 1) + return "TWO"; + else if (roundNumber == 2) + return "THREE"; + else if (roundNumber == 3) + return "FOUR"; + else if (roundNumber == 4) + return "FIVE"; + else if (roundNumber == 5) + return "SIX"; + else if (roundNumber == 6) + return "SEVEN"; + else if (roundNumber == 7) + return "EIGHT"; + else if (roundNumber == 8) + return "NINE"; + else if (roundNumber == 9) + return "TEN"; + else if (roundNumber == 10) + return "ELEVEN"; + else if (roundNumber == 11) + return "TWELVE"; + + char numStr[11]; std::snprintf(numStr, sizeof(numStr), "%d", roundNumber + 1); return std::string(numStr); } @@ -1059,7 +1058,7 @@ bool MetagameGUI::LoadGame() { UpdateIncomeCounting(true); // Reconstruct the player action lines - they are important! - for (int metaPlayer = Players::PlayerOne; metaPlayer < g_MetaMan.m_Players.size(); ++metaPlayer) + for (size_t metaPlayer = Players::PlayerOne; metaPlayer < g_MetaMan.m_Players.size(); ++metaPlayer) UpdatePlayerActionLines(metaPlayer); // Re-init some other GUI elements @@ -1090,7 +1089,7 @@ bool MetagameGUI::LoadGame() { return false; } -bool MetagameGUI::SaveGame(std::string saveName, std::string savePath, bool resaveSceneData) { +bool MetagameGUI::SaveGame(const std::string& saveName, const std::string& savePath, bool resaveSceneData) { const std::string fullSavePath = g_PresetMan.GetFullModulePath(savePath); // If specified, first load all bitmap data of all Scenes in the current Metagame that have once saved em, so we can re-save them to the new files if (resaveSceneData) @@ -1104,7 +1103,7 @@ bool MetagameGUI::SaveGame(std::string saveName, std::string savePath, bool resa g_MetaMan.SaveSceneData(METASAVEPATH + saveName); // Whichever new or existing, create a writer with the path - Writer metaWriter(fullSavePath.c_str()); + Writer metaWriter(fullSavePath); // Now that all the updated data files have been written to disk and their paths updated, send the MetaMan state for actual writing to an ini if (g_MetaMan.Save(metaWriter) < 0) return false; @@ -1574,7 +1573,6 @@ void MetagameGUI::Update() { if (!m_pDraggedBox && (mousePos - m_PlanetCenter).MagnitudeIsLessThan(m_PlanetRadius)) { // If unlocked, detect any Scene close to the mouse and highlight it bool foundAnyHover = false; - bool foundNewHover = false; std::vector::iterator sItr; std::vector::iterator newCandidateItr = g_MetaMan.m_Scenes.end(); @@ -1607,7 +1605,6 @@ void MetagameGUI::Update() { // Set new hovered scene to be the one now closest to the cursor, if there is any and if it is different the a currently hovered one if (newCandidateItr != g_MetaMan.m_Scenes.end() && (*newCandidateItr) != m_pHoveredScene) { m_pHoveredScene = (*newCandidateItr); - foundNewHover = true; g_GUISound.SelectionChangeSound()->Play(); } @@ -1698,7 +1695,7 @@ void MetagameGUI::Draw(BITMAP* drawBitmap) { // Make sure team is within bounds to show an icon pIcon = g_MetaMan.IsActiveTeam(team) ? g_MetaMan.GetTeamIcon(team).GetBitmaps32()[0] : 0; if (pIcon) - masked_blit(pIcon, drawBitmap, 0, 0, screenLocation.m_X - (pIcon->w / 2), screenLocation.m_Y - (pIcon->h / 2), pIcon->w, pIcon->h); + masked_blit(pIcon, drawBitmap, 0, 0, screenLocation.m_X - (pIcon->w / 2.0), screenLocation.m_Y - (pIcon->h / 2.0), pIcon->w, pIcon->h); // Ownership not known, so place nondescript dot instead else { // Make it flicker more if it's currently being fought over @@ -1714,7 +1711,7 @@ void MetagameGUI::Draw(BITMAP* drawBitmap) { // Draw the lines etc pointing at the selected Scene from the Scene Info box if (m_pSelectedScene && m_pSceneInfoPopup->GetVisible() && !m_PreTurn) { - Vector sceneInfoBoxPos(m_pSceneInfoPopup->GetXPos() + (m_pSceneInfoPopup->GetWidth() / 2), m_pSceneInfoPopup->GetYPos() + (m_pSceneInfoPopup->GetHeight() / 2)); + Vector sceneInfoBoxPos(m_pSceneInfoPopup->GetXPos() + (m_pSceneInfoPopup->GetWidth() / 2.0), m_pSceneInfoPopup->GetYPos() + (m_pSceneInfoPopup->GetHeight() / 2.0)); DrawScreenLineToSitePoint(drawBitmap, sceneInfoBoxPos, m_pSelectedScene->GetLocation() + m_pSelectedScene->GetLocationOffset(), c_GUIColorWhite, -1, -1, (m_pSceneInfoPopup->GetHeight() / 2) + CHAMFERSIZE + 6, 1.0, g_MetaMan.IsActiveTeam(m_pSelectedScene->GetTeamOwnership())); } @@ -1738,7 +1735,7 @@ void MetagameGUI::Draw(BITMAP* drawBitmap) { // Action lines // If during a player's round phase, and not showing any income lines if (!m_PreTurn && !g_MetaMan.m_StateChanged && g_MetaMan.m_GameState >= MetaMan::PLAYER1TURN && g_MetaMan.m_GameState <= MetaMan::BUILDBASES && m_ActivePlayerIncomeLines == Players::NoPlayer) { - int metaPlayer = 0; + size_t metaPlayer = 0; // Show the lines of the relevant player during turns if (g_MetaMan.m_GameState >= MetaMan::PLAYER1TURN && g_MetaMan.m_GameState <= MetaMan::PLAYER4TURN) metaPlayer = g_MetaMan.m_GameState - MetaMan::PLAYER1TURN; @@ -1746,7 +1743,7 @@ void MetagameGUI::Draw(BITMAP* drawBitmap) { else if (g_MetaMan.m_GameState == MetaMan::BUILDBASES && m_AnimMetaPlayer < g_MetaMan.m_Players.size()) metaPlayer = m_AnimMetaPlayer; - for (int slI = 0; slI < m_ActionSiteLines[metaPlayer].size(); ++slI) { + for (size_t slI = 0; slI < m_ActionSiteLines[metaPlayer].size(); ++slI) { // Only draw the lines of the active player // if (m_ActionSiteLines[metaPlayer][slI].m_Player != m_ActivePlayerIncomeLines) // continue; @@ -1779,7 +1776,7 @@ void MetagameGUI::Draw(BITMAP* drawBitmap) { // Draw the attack lines that are currently being revealed by possibly multiple attackers for (int metaPlayer = Players::PlayerOne; metaPlayer < Players::MaxPlayerCount; ++metaPlayer) { - for (int slI = 0; slI < m_ActionSiteLines[metaPlayer].size(); ++slI) { + for (size_t slI = 0; slI < m_ActionSiteLines[metaPlayer].size(); ++slI) { DrawPlayerLineToSitePoint(drawBitmap, m_ActionSiteLines[metaPlayer][slI], m_ActionMeterDrawOverride); } } @@ -2118,7 +2115,6 @@ void MetagameGUI::UpdateInput() { if (anEvent.GetControl() == m_apMetaButton[SCENEACTION] && m_pSelectedScene) { // Set up site scan of it (for a price) int metaPlayer = g_MetaMan.GetPlayerTurn(); - int team = g_MetaMan.m_Players[metaPlayer]->GetTeam(); // Check if we have enough money for this! if (g_MetaMan.GetRemainingFundsOfPlayer(metaPlayer, 0, false, false) < SCANCOST) { m_apMetaButton[SCENEACTION]->SetText("NOT ENOUGH FUNDS!"); @@ -2678,8 +2674,9 @@ bool MetagameGUI::AutoResolveOffensive(GAScripted* pOffensive, Scene* pScene, bo // NOTE: Brain pool resource counter gets adjusted down in FinalizeOffense // Find the player's tech's brain, and instantiate it - if (pLoadout = dynamic_cast(g_PresetMan.GetEntityPreset("Loadout", "Infantry Brain", pMetaPlayer->GetNativeTechModule()))) + if ((pLoadout = dynamic_cast(g_PresetMan.GetEntityPreset("Loadout", "Infantry Brain", pMetaPlayer->GetNativeTechModule())))) pBrain = pLoadout->CreateFirstActor(pMetaPlayer->GetNativeTechModule(), pMetaPlayer->GetForeignCostMultiplier(), pMetaPlayer->GetNativeCostMultiplier(), cost); + // Pass the instance and ownership thereof to the scene as a resident if (pBrain) { // Set a pos outside the Scene so it'll be gracefully placed later when Scene's Terrain is actually loaded @@ -2791,8 +2788,10 @@ bool MetagameGUI::AutoResolveOffensive(GAScripted* pOffensive, Scene* pScene, bo // NOTE: Brain pool resource counter gets adjusted down in FinalizeOffense // Find the player's tech's brain, and instantiate it - if (pLoadout = dynamic_cast(g_PresetMan.GetEntityPreset("Loadout", "Infantry Brain", aMetaPlayers[player]->GetNativeTechModule()))) + + if ((pLoadout = dynamic_cast(g_PresetMan.GetEntityPreset("Loadout", "Infantry Brain", aMetaPlayers[player]->GetNativeTechModule())))) pBrain = pLoadout->CreateFirstActor(aMetaPlayers[player]->GetNativeTechModule(), aMetaPlayers[player]->GetForeignCostMultiplier(), aMetaPlayers[player]->GetNativeCostMultiplier(), cost); + // Pass the instance and ownership thereof to the scene as a resident if (pBrain) { // Set a pos outside the Scene so it'll be gracefully placed later when Scene's Terrain is actually loaded @@ -2853,7 +2852,7 @@ void MetagameGUI::UpdateSiteRevealing() { // Reset the extra to 0 now after we've applied it g_MetaMan.m_RevealExtra = 0; // Don't reveal more than there are scenes! - if ((int)std::floor(g_MetaMan.m_RevealedScenes) >= g_MetaMan.m_Scenes.size()) + if ((size_t)std::floor(g_MetaMan.m_RevealedScenes) >= g_MetaMan.m_Scenes.size()) g_MetaMan.m_RevealedScenes = g_MetaMan.m_Scenes.size(); // Figure out how many new sites we gots this round int delta = (int)std::floor(g_MetaMan.m_RevealedScenes) - m_AnimCountStart; @@ -2891,7 +2890,7 @@ void MetagameGUI::UpdateSiteRevealing() { // Animate the existing crosshairs double shrinkTime = 0; double shrinkInterval = 600; - for (int i = 0; i < (m_AnimCountCurrent - m_AnimCountStart); ++i) { + for (size_t i = 0; i < (m_AnimCountCurrent - m_AnimCountStart); ++i) { // How long have we been animating this one? shrinkTime = m_AnimTimer2.GetElapsedRealTimeMS() - m_NewSiteIndicators[i].m_StartTime; // If it's still in the shrink interval, keep doing it @@ -2962,7 +2961,7 @@ void MetagameGUI::UpdateIncomeCounting(bool initOverride) { // Init all the SiteLine:s and make them hidden; we will reveal each one sequentially with an animation m_IncomeSiteLines.clear(); - for (int metaPlayer = 0; metaPlayer < g_MetaMan.m_Players.size(); ++metaPlayer) + for (size_t metaPlayer = 0; metaPlayer < g_MetaMan.m_Players.size(); ++metaPlayer) m_aStationIncomeLineIndices[metaPlayer] = -1; m_AnimMetaPlayer = m_ActivePlayerIncomeLines = Players::PlayerOne; m_pAnimScene = 0; @@ -2997,7 +2996,7 @@ void MetagameGUI::UpdateIncomeCounting(bool initOverride) { // SCENE INCOME // Loop through the scenes owned by that player, setting up the site line for each if (!initOverride) { - while (m_pAnimScene = g_MetaMan.GetNextSceneOfPlayer(m_AnimMetaPlayer, m_pAnimScene)) { + while ((m_pAnimScene = g_MetaMan.GetNextSceneOfPlayer(m_AnimMetaPlayer, m_pAnimScene))) { m_IncomeSiteLines.push_back(SiteLine(m_AnimMetaPlayer, 1.0, 0, m_pAnimScene->GetLocation() + m_pAnimScene->GetLocationOffset(), m_pAnimScene->GetPresetName(), m_pAnimScene, c_GUIColorYellow, -1, 0, channelHeight, 1.0f, g_MetaMan.IsActiveTeam(m_pAnimScene->GetTeamOwnership()))); // Star them at 0, make them go to the round income for this base m_IncomeSiteLines.back().m_FundsAmount = 0; @@ -3222,7 +3221,7 @@ void MetagameGUI::UpdateIncomeCounting(bool initOverride) { // Check if there's more lines to draw, and if so, if the next one is of a different player // OR if there's no lines left at all, just retract the last player's lines we just finished // Then pause to retract all the lines of the just finished player - if ((m_AnimIncomeLineIndex + 1) >= static_cast(m_IncomeSiteLines.size()) || m_IncomeSiteLines[m_AnimIncomeLineIndex + 1].m_Player != m_AnimMetaPlayer) { + if ((m_AnimIncomeLineIndex + 1) >= m_IncomeSiteLines.size() || m_IncomeSiteLines[m_AnimIncomeLineIndex + 1].m_Player != m_AnimMetaPlayer) { // Wait for a little bit when we've displayed all sites of a player if (m_AnimTimer2.IsPastRealMS(500)) ChangeAnimMode(RETRACTLINES); @@ -3244,12 +3243,12 @@ void MetagameGUI::UpdateIncomeCounting(bool initOverride) { // Show the change, if any if (fabs(m_IncomeSiteLines[m_AnimIncomeLineIndex].m_FundsTarget - m_IncomeSiteLines[m_AnimIncomeLineIndex].m_FundsAmount) > 0) { // Show why we are paying money - PlayerTextIndication(m_AnimMetaPlayer, "TradeStar brain storage rent", Vector(m_apPlayerBarLabel[m_AnimMetaPlayer]->GetXPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetWidth() / 2), m_apPlayerBarLabel[m_AnimMetaPlayer]->GetYPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetHeight() / 2)), m_AnimModeDuration); + PlayerTextIndication(m_AnimMetaPlayer, "TradeStar brain storage rent", Vector(m_apPlayerBarLabel[m_AnimMetaPlayer]->GetXPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetWidth() / 2.0), m_apPlayerBarLabel[m_AnimMetaPlayer]->GetYPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetHeight() / 2.0)), m_AnimModeDuration); FundsChangeIndication(m_AnimMetaPlayer, m_IncomeSiteLines[m_AnimIncomeLineIndex].m_FundsTarget - m_IncomeSiteLines[m_AnimIncomeLineIndex].m_FundsAmount, Vector(m_apPlayerBarLabel[m_AnimMetaPlayer]->GetXPos() + m_apPlayerBarLabel[m_AnimMetaPlayer]->GetWidth(), m_apPlayerBarLabel[m_AnimMetaPlayer]->GetYPos()), m_AnimModeDuration); } // Indicate why we're not paying anything else - PlayerTextIndication(m_AnimMetaPlayer, "No brains; no rent!", Vector(m_apPlayerBarLabel[m_AnimMetaPlayer]->GetXPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetWidth() / 2), m_apPlayerBarLabel[m_AnimMetaPlayer]->GetYPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetHeight() / 2)), m_AnimModeDuration); + PlayerTextIndication(m_AnimMetaPlayer, "No brains; no rent!", Vector(m_apPlayerBarLabel[m_AnimMetaPlayer]->GetXPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetWidth() / 2.0), m_apPlayerBarLabel[m_AnimMetaPlayer]->GetYPos() + (m_apPlayerBarLabel[m_AnimMetaPlayer]->GetHeight() / 2.0)), m_AnimModeDuration); /* This is done above on init now // Only charge rent if we've still got brains at the tradestar @@ -3331,13 +3330,13 @@ void MetagameGUI::UpdateIncomeCounting(bool initOverride) { } // If no more lines, DONE, continue phase to next - if (m_AnimIncomeLineIndex >= static_cast(m_IncomeSiteLines.size()) && !initOverride) + if (m_AnimIncomeLineIndex >= m_IncomeSiteLines.size() && !initOverride) m_ContinuePhase = true; // Phase ending, make sure everything is set up to continue if (m_ContinuePhase || initOverride) { // Set all lines' fund amounts to their targets and reset their segment animations so we can see them - int lineIndex = 0; + size_t lineIndex = 0; for (std::vector::iterator slItr = m_IncomeSiteLines.begin(); slItr != m_IncomeSiteLines.end(); ++slItr) { (*slItr).m_FundsAmount = (*slItr).m_FundsTarget; (*slItr).m_OnlyFirstSegments = -1; @@ -3461,7 +3460,7 @@ void MetagameGUI::UpdateBaseBuilding() { // ChangeAnimMode(PAUSEANIM); // Find the next green defense line of this player - while (m_AnimActionLine < static_cast(m_ActionSiteLines[m_AnimMetaPlayer].size()) && m_ActionSiteLines[m_AnimMetaPlayer][m_AnimActionLine].m_Color != c_GUIColorGreen) + while (m_AnimActionLine < m_ActionSiteLines[m_AnimMetaPlayer].size() && m_ActionSiteLines[m_AnimMetaPlayer][m_AnimActionLine].m_Color != c_GUIColorGreen) m_AnimActionLine++; // Regular site line, start with bar bracket and line appearing toward the site @@ -3474,7 +3473,7 @@ void MetagameGUI::UpdateBaseBuilding() { // Animate defense spending sitelines into view, and then count them away one by one // for (vector::iterator slItr = m_ActionSiteLines[m_AnimMetaPlayer].begin(); slItr != m_ActionSiteLines[m_AnimMetaPlayer].end(); ++slItr) - if (!m_ActionSiteLines[m_AnimMetaPlayer].empty() && m_AnimActionLine < static_cast(m_ActionSiteLines[m_AnimMetaPlayer].size())) { + if (!m_ActionSiteLines[m_AnimMetaPlayer].empty() && m_AnimActionLine < m_ActionSiteLines[m_AnimMetaPlayer].size()) { if (m_AnimMode == BLINKMETER) { if (NewAnimMode()) { m_AnimTimer1.Reset(); @@ -3598,7 +3597,7 @@ void MetagameGUI::UpdateBaseBuilding() { } // If no more lines, DONE, continue to next player, and if no more players, continue to next phase of the round - if (m_AnimActionLine >= static_cast(m_ActionSiteLines[m_AnimMetaPlayer].size())) { + if (m_AnimActionLine >= m_ActionSiteLines[m_AnimMetaPlayer].size()) { m_AnimActionLineChange = true; m_AnimActionLine = 0; @@ -3834,7 +3833,7 @@ void MetagameGUI::UpdateOffensives() { // Find out how much gold this player has left after all allocations and previous battles this turn float remainingFunds = g_MetaMan.GetRemainingFundsOfPlayer(mp); // UPDATE the contributed funds of the defending player to whatever gold he has left after all (if any) previous battles this turn! - bool updated = g_MetaMan.m_RoundOffensives[g_MetaMan.m_CurrentOffensive]->UpdatePlayerFundsContribution(g_MetaMan.m_Players[mp]->GetInGamePlayer(), remainingFunds); + g_MetaMan.m_RoundOffensives[g_MetaMan.m_CurrentOffensive]->UpdatePlayerFundsContribution(g_MetaMan.m_Players[mp]->GetInGamePlayer(), remainingFunds); // Add the unused build budget FOR THIS SCENE to the battle funds display - doesn't do anyhting now because build budgets are set to 0 in UpdateBaseBuilding m_aBattleFunds[mp] += m_pAnimScene->GetBuildBudget(g_MetaMan.m_Players[mp]->GetInGamePlayer()); // Add the unallocated funds meter, even if there's 0 left.. it shows why there's 0, and also the meter can grow after battle if the defending player digs up gold @@ -5595,7 +5594,7 @@ void MetagameGUI::UpdatePlayerBars() { } } -void MetagameGUI::UpdateSiteNameLabel(bool visible, std::string text, const Vector& location, float height) { +void MetagameGUI::UpdateSiteNameLabel(bool visible, const std::string& text, const Vector& location, float height) { // Set up the hover label to appear over any hovered scene location m_pScenePlanetLabel->SetVisible(visible); if (visible) { @@ -5618,7 +5617,7 @@ void MetagameGUI::UpdateSiteNameLabel(bool visible, std::string text, const Vect } } -void MetagameGUI::PlayerTextIndication(int metaPlayer, std::string text, const Vector& screenPos, double animLengthMS) { +void MetagameGUI::PlayerTextIndication(int metaPlayer, const std::string& text, const Vector& screenPos, double animLengthMS) { m_apFundsChangeLabel[metaPlayer]->SetText(text); m_apFundsChangeLabel[metaPlayer]->SetHAlignment(GUIFont::Centre); m_apFundsChangeLabel[metaPlayer]->SetVAlignment(GUIFont::Middle); diff --git a/Source/Menus/MetagameGUI.h b/Source/Menus/MetagameGUI.h index 50b005f437..c4615c9445 100644 --- a/Source/Menus/MetagameGUI.h +++ b/Source/Menus/MetagameGUI.h @@ -80,20 +80,20 @@ namespace RTE { int onlyLastSegments = -1, int channelHeight = 60, float circleSize = 1.0f, - bool squareSite = false) { - m_Player = player; - m_StartMeterAt = startMeterAt; - m_MeterAmount = meterAmount; - m_PlanetPoint = planetPoint; - m_SiteName = siteName; - m_pScene = pScene; - m_Color = color; - m_OnlyFirstSegments = onlyFirstSegments; - m_OnlyLastSegments = onlyLastSegments; - m_ChannelHeight = channelHeight; - m_CircleSize = circleSize; - m_Square = squareSite; - } + bool squareSite = false) : + + m_Player(player), + m_StartMeterAt(startMeterAt), + m_MeterAmount(meterAmount), + m_PlanetPoint(planetPoint), + m_SiteName(std::move(siteName)), + m_pScene(pScene), + m_Color(color), + m_OnlyFirstSegments(onlyFirstSegments), + m_OnlyLastSegments(onlyLastSegments), + m_ChannelHeight(channelHeight), + m_CircleSize(circleSize), + m_Square(squareSite) {} }; // For storing info about target crosshairs over sites @@ -128,14 +128,14 @@ namespace RTE { float animProgress, int style, int color, - double startTime = 0) { - m_CenterPos = centerPos; - m_AnimProgress = animProgress; - m_Style = style; - m_Color = color; - m_StartTime = startTime; - m_AnimTimer.Reset(); - } + double startTime = 0) : + m_CenterPos(centerPos), + m_AnimProgress(animProgress), + m_Style(style), + m_Color(color), + m_StartTime(startTime) { + m_AnimTimer.Reset(); + } /// Draws this SiteTarget onto a bitmap of choice. /// @param drawBitmap The bitmap to draw to. @@ -200,7 +200,7 @@ namespace RTE { /// Tries to select a specifically named scene on the metagame field. /// @param sceneName The name of the Scene to try to find and select. /// @return Whether mission was found and selected. - bool SelectScene(std::string sceneName); + bool SelectScene(const std::string& sceneName); /// Reports whether the player has decided to continue to next phase of the /// round of the current game. @@ -241,7 +241,7 @@ namespace RTE { /// @param resaveSceneData Whether to load all the scene data that is on disk first so it will (default: false) /// be re-saved to the new location here. /// @return Whether the game was able to be saved there. - bool SaveGame(std::string saveName, std::string savePath, bool resaveSceneData = false); + bool SaveGame(const std::string& saveName, const std::string& savePath, bool resaveSceneData = false); /// Attempts to save a Metagame to disk using the settings set in the /// Save Game dialog box. @@ -405,7 +405,7 @@ namespace RTE { /// @param text Text to show above the location. (default: "") /// @param location The location in planetary coords. (default: Vector()) /// @param height How high above the location to show the text, adjustment from a good default. (default: 1.0) - void UpdateSiteNameLabel(bool visible, std::string text = "", const Vector& location = Vector(), float height = 1.0); + void UpdateSiteNameLabel(bool visible, const std::string& text = "", const Vector& location = Vector(), float height = 1.0); /// Starts an animation of a label showing a text string over a player bar /// @param player Which player the indication is relevant to @@ -413,7 +413,7 @@ namespace RTE { /// @param screenPos Where, in screen coords the change should be indicated. The CENTER of /// the floating label will line up with this pos. /// @param animLengthMS How long, in MS, that the animation should linger - void PlayerTextIndication(int player, std::string text, const Vector& screenPos, double animLengthMS); + void PlayerTextIndication(int player, const std::string& text, const Vector& screenPos, double animLengthMS); /// Starts an animation of a label showing funds changing for a player /// @param player Which player the change is relevant to diff --git a/Source/Menus/ModManagerGUI.cpp b/Source/Menus/ModManagerGUI.cpp index 2c0f1437bf..864ed6a4cb 100644 --- a/Source/Menus/ModManagerGUI.cpp +++ b/Source/Menus/ModManagerGUI.cpp @@ -88,25 +88,81 @@ void ModManagerGUI::PopulateKnownModsList() { m_ModsListFetched = true; } -void ModManagerGUI::PopulateKnownScriptsList() { - std::list globalScriptList; - g_PresetMan.GetAllOfType(globalScriptList, "GlobalScript"); - - for (Entity* globalScriptListEntry: globalScriptList) { - if (const GlobalScript* globalScript = dynamic_cast(globalScriptListEntry)) { - ScriptRecord scriptRecord = {globalScript->GetModuleAndPresetName(), globalScript->GetDescription(), g_SettingsMan.IsGlobalScriptEnabled(scriptRecord.PresetName)}; - m_KnownScripts.emplace_back(scriptRecord); +//todo to fetch +void ModManagerGUI::InitializeKnownScripts() { + int totalModuleCount = g_PresetMan.GetTotalModuleCount(); + for (int currentModuleIndex = 0; currentModuleIndex < totalModuleCount; ++currentModuleIndex) { + // todo: try GetFriendlyName() + std::list globalScriptListForThisModule; + g_PresetMan.GetAllOfType(globalScriptListForThisModule, "GlobalScript", currentModuleIndex); + + if (globalScriptListForThisModule.empty()) { + continue; } - } - std::sort(m_KnownScripts.begin(), m_KnownScripts.end()); - for (int i = 0; i < m_KnownScripts.size(); i++) { - m_ScriptsListBox->AddItem(m_KnownScripts.at(i).GetDisplayString(), std::string(), nullptr, nullptr, i); + + std::vector& currentModuleScripts = + m_KnownScriptsPerModule.emplace_back( + g_PresetMan.GetDataModule(currentModuleIndex)->GetFileName(), + g_PresetMan.GetDataModule(currentModuleIndex)->GetFriendlyName() + + "\n" + g_PresetMan.GetDataModule(currentModuleIndex)->GetDescription() + ).Records; + + for (Entity* globalScriptListEntry: globalScriptListForThisModule) { + if (const GlobalScript* globalScript = dynamic_cast(globalScriptListEntry)) { + ScriptRecord scriptRecord = + {globalScript->GetPresetName(), + globalScript->GetModuleAndPresetName(), + globalScript->GetDescription(), + g_SettingsMan.IsGlobalScriptEnabled(globalScript->GetModuleAndPresetName())}; + currentModuleScripts.emplace_back(scriptRecord); + } + } + std::sort(currentModuleScripts.begin(), currentModuleScripts.end()); } m_ScriptsListBox->ScrollToTop(); m_ScriptsListFetched = true; } +int ModManagerGUI::ScriptListEntryEncodeExtraIndex(const int moduleNumber, const int scriptNumber) { + return scriptNumber == -1 + ? (moduleNumber << 10) | EXTRA_INDEX_IS_A_MODULE_LABEL_MASK + : (moduleNumber << 10) + scriptNumber; +} + +std::pair ModManagerGUI::ScriptListEntryDecodeExtraIndex(const int extraIndex) { + if (extraIndex & EXTRA_INDEX_IS_A_MODULE_LABEL_MASK) { + return {(extraIndex ^ EXTRA_INDEX_IS_A_MODULE_LABEL_MASK) >> 10, -1}; + } else { + return {extraIndex >> 10, extraIndex - ((extraIndex >> 10) << 10)}; + } +} + +void ModManagerGUI::PopulateKnownScriptsList(bool clearBeforehand = false) { + if (clearBeforehand) { + m_ScriptsListBox->ClearList(); + } + + for (int moduleIt = 0; moduleIt < m_KnownScriptsPerModule.size(); ++moduleIt) { + auto& scriptRecordsInAModule = m_KnownScriptsPerModule[moduleIt]; + + //display the module ".rte" thingy + m_ScriptsListBox->AddItem(scriptRecordsInAModule.GetDisplayString(), + std::string(), nullptr, nullptr, ScriptListEntryEncodeExtraIndex(moduleIt, -1)); + + if (scriptRecordsInAModule.Collapsed) { + continue; + } + + // then per each .rte display the scripts under: + for (int scriptIt = 0; scriptIt < scriptRecordsInAModule.Records.size(); ++scriptIt) { + auto& scriptRecord = scriptRecordsInAModule.Records[scriptIt]; + m_ScriptsListBox->AddItem(scriptRecord.GetDisplayString(), + std::string(), nullptr, nullptr, ScriptListEntryEncodeExtraIndex(moduleIt, scriptIt)); + } + } +} + void ModManagerGUI::ToggleMod() { int index = m_ModsListBox->GetSelectedIndex(); if (index > -1) { @@ -133,62 +189,142 @@ void ModManagerGUI::ToggleMod() { } } -void ModManagerGUI::ToggleScript() { +ModManagerGUI::ScriptRecord* ModManagerGUI::ScriptListExtraIndexToScriptRecord(int extraIndex) { + + auto [moduleInd, scriptInd] = ScriptListEntryDecodeExtraIndex(extraIndex); + // if the list item is a module label header - return nullptr + if (scriptInd == -1) { + return nullptr; + } + // else - a script, decode where to access it from the item's extra value + return &m_KnownScriptsPerModule.at(moduleInd).Records.at(scriptInd); +} + +void ModManagerGUI::ToggleInScriptList() { int index = m_ScriptsListBox->GetSelectedIndex(); - if (index > -1) { + if (index <= -1) { + return; + } + + GUIListPanel::Item* selectedItem = m_ScriptsListBox->GetSelected(); + int extraIndex = selectedItem->m_ExtraIndex; + auto [moduleInd, scriptInd] = ScriptListEntryDecodeExtraIndex(extraIndex); + //if the list item is a module label header then collapse/expand it + if (scriptInd == -1) { + m_KnownScriptsPerModule[moduleInd].Collapsed ^= 1; //toggle it + PopulateKnownScriptsList(true); + } + // else - it's a script, toggle it: + else { std::unordered_map& enabledScriptList = g_SettingsMan.GetEnabledGlobalScriptMap(); - GUIListPanel::Item* selectedItem = m_ScriptsListBox->GetSelected(); - ScriptRecord& scriptRecord = m_KnownScripts.at(selectedItem->m_ExtraIndex); - scriptRecord.Enabled = !scriptRecord.Enabled; - if (scriptRecord.Enabled) { + ScriptRecord* scriptRecord = ScriptListExtraIndexToScriptRecord(extraIndex); + scriptRecord->Enabled = !scriptRecord->Enabled; + if (scriptRecord->Enabled) { m_ToggleScriptButton->SetText("Disable Script"); - if (enabledScriptList.find(scriptRecord.PresetName) != enabledScriptList.end()) { - enabledScriptList.at(scriptRecord.PresetName) = true; + if (enabledScriptList.find(scriptRecord->ModuleAndPresetName) != enabledScriptList.end()) { + enabledScriptList.at(scriptRecord->ModuleAndPresetName) = true; } else { - enabledScriptList.try_emplace(scriptRecord.PresetName, true); + enabledScriptList.try_emplace(scriptRecord->ModuleAndPresetName, true); } } else { m_ToggleScriptButton->SetText("Enable Script"); - enabledScriptList.at(scriptRecord.PresetName) = false; + enabledScriptList.at(scriptRecord->ModuleAndPresetName) = false; } - selectedItem->m_Name = scriptRecord.GetDisplayString(); - m_ScriptsListBox->SetSelectedIndex(index); - m_ScriptsListBox->Invalidate(); - g_GUISound.ItemChangeSound()->Play(); + + selectedItem->m_Name = scriptRecord->GetDisplayString(); } + m_ScriptsListBox->SetSelectedIndex(index); + m_ScriptsListBox->Invalidate(); + g_GUISound.ItemChangeSound()->Play(); +} + +void ModManagerGUI::ResetSelectionsAndGoToTop() { + m_ModsListBox->ScrollToTop(); + m_ScriptsListBox->ScrollToTop(); + + m_ModOrScriptDescriptionLabel->SetText(m_DisclaimerText); } bool ModManagerGUI::HandleInputEvents() { if (!ListsFetched()) { + m_DisclaimerText = m_ModOrScriptDescriptionLabel->GetText(); PopulateKnownModsList(); + InitializeKnownScripts(); PopulateKnownScriptsList(); + ResetSelectionsAndGoToTop(); } m_GUIControlManager->Update(); GUIEvent guiEvent; while (m_GUIControlManager->GetEvent(&guiEvent)) { + // buttons if (guiEvent.GetType() == GUIEvent::Command) { if (guiEvent.GetControl() == m_BackToMainButton) { + ResetSelectionsAndGoToTop(); return true; } else if (guiEvent.GetControl() == m_ToggleModButton) { ToggleMod(); } else if (guiEvent.GetControl() == m_ToggleScriptButton) { - ToggleScript(); + ToggleInScriptList(); } - } else if (guiEvent.GetType() == GUIEvent::Notification) { + } + + else if (guiEvent.GetType() == GUIEvent::Notification) { + // button hover sound if (guiEvent.GetMsg() == GUIButton::Focused && dynamic_cast(guiEvent.GetControl())) { g_GUISound.SelectionChangeSound()->Play(); } - if (guiEvent.GetControl() == m_ModsListBox && (guiEvent.GetMsg() == GUIListBox::Select && m_ModsListBox->GetSelectedIndex() > -1)) { - const ModRecord& modRecord = m_KnownMods.at(m_ModsListBox->GetSelected()->m_ExtraIndex); - m_ModOrScriptDescriptionLabel->SetText(modRecord.Description); - m_ToggleModButton->SetText(modRecord.Disabled ? "Enable Mod" : "Disable Mod"); - } else if (guiEvent.GetControl() == m_ScriptsListBox && (guiEvent.GetMsg() == GUIListBox::Select && m_ScriptsListBox->GetSelectedIndex() > -1)) { - const ScriptRecord& scriptRecord = m_KnownScripts.at(m_ScriptsListBox->GetSelected()->m_ExtraIndex); - m_ModOrScriptDescriptionLabel->SetText(scriptRecord.Description); - m_ToggleScriptButton->SetText(scriptRecord.Enabled ? "Disable Script" : "Enable Script"); + // list entries + if (guiEvent.GetControl() == m_ModsListBox && m_ModsListBox->GetSelectedIndex() > -1) { + switch (guiEvent.GetMsg()) { + case GUIListBox::Select: { + g_GUISound.SelectionChangeSound()->Play(); + const ModRecord& modRecord = m_KnownMods.at(m_ModsListBox->GetSelected()->m_ExtraIndex); + m_ModOrScriptDescriptionLabel->SetText(modRecord.Description); + m_ToggleModButton->SetText(modRecord.Disabled ? "Enable Mod" : "Disable Mod"); + break; + } + case GUIListBox::KeyDown: + if (guiEvent.GetData() != 13) //enter key but doesnt work, todo + break; + case GUIListBox::DoubleClick: + g_GUISound.SelectionChangeSound()->FadeOut(0); + g_GUISound.ItemChangeSound()->Play(); + ToggleMod(); + break; + } + } else if (guiEvent.GetControl() == m_ScriptsListBox && m_ScriptsListBox->GetSelectedIndex() > -1) { + switch (guiEvent.GetMsg()) { + case GUIListBox::Select: { + g_GUISound.SelectionChangeSound()->Play(); + int extraIndex = m_ScriptsListBox->GetSelected()->m_ExtraIndex; + auto [moduleInd, scriptInd] = ScriptListEntryDecodeExtraIndex(extraIndex); + // if we're on a script item + if (scriptInd != -1) { + const ScriptRecord* scriptRecord = ScriptListExtraIndexToScriptRecord(extraIndex); + m_ModOrScriptDescriptionLabel->SetText(scriptRecord->Description.empty() ? "No description." : scriptRecord->Description); + m_ToggleScriptButton->SetText(scriptRecord->Enabled ? "Disable Script" : "Enable Script"); + } + // if we're on a module label + else { + ScriptRecordsInAModule* module = + &m_KnownScriptsPerModule[moduleInd]; + m_ModOrScriptDescriptionLabel->SetText(module->Description); + m_ToggleScriptButton->SetText(module->Collapsed ? "Expand Category" : "Collapse Category"); + } + break; + } + case GUIListBox::KeyDown: + if (guiEvent.GetData() != 13) //todo, check above + break; + case GUIListBox::DoubleClick: + g_GUISound.SelectionChangeSound()->FadeOut(0); + g_GUISound.ItemChangeSound()->Play(); + ToggleInScriptList(); + break; + } } } } diff --git a/Source/Menus/ModManagerGUI.h b/Source/Menus/ModManagerGUI.h index 3c5fbeb018..6b835c2c15 100644 --- a/Source/Menus/ModManagerGUI.h +++ b/Source/Menus/ModManagerGUI.h @@ -54,24 +54,48 @@ namespace RTE { /// Struct containing information about a valid GlobalScript. struct ScriptRecord { - std::string PresetName; //!< Script PresetName. + std::string DisplayName; + std::string ModuleAndPresetName; std::string Description; //!< Script description. bool Enabled; //!< Whether the script is enabled through the settings file or not. /// Makes GUI displayable string with script info. /// @return String with script info. - std::string GetDisplayString() const { return (!Enabled ? "- " : "+ ") + PresetName; } + std::string GetDisplayString() const { + return (!Enabled ? " - " : " + ") + DisplayName; + } /// Comparison operator for sorting the KnownScripts list alphabetically by PresetName with std::sort. /// @param rhs ScriptRecord to compare with. /// @return Bool with result of the alphabetical comparison. - bool operator<(const ScriptRecord& rhs) const { return PresetName < rhs.PresetName; } + bool operator<(const ScriptRecord& rhs) const { return DisplayName < rhs.DisplayName; } + }; + + struct ScriptRecordsInAModule { + std::string ModuleName; + std::string Description; + std::vector Records; + bool Collapsed = false; + + ScriptRecordsInAModule(std::string moduleName, std::string description) { + ModuleName = moduleName; + Description = description; + } + + ScriptRecord& operator[](int i) { + return Records[i]; + } + + std::string GetDisplayString() const { + return (Collapsed ? "+ " : "- ") + ModuleName; + } }; std::unique_ptr m_GUIControlManager; //!< The GUIControlManager which holds all the GUIControls of the ModManagerGUI. std::vector m_KnownMods; //!< Contains ModRecords for all valid mod DataModules. std::vector m_KnownScripts; //!< Contains ScriptRecords for all valid GlobalScripts. + std::vector m_KnownScriptsPerModule; bool m_ModsListFetched; //!< Whether the known mods list was fetched, even if no valid mod DataModules were added to it. bool m_ScriptsListFetched; //!< Whether the known scripts list was fetched, even if no valid GlobalScripts were added to it. @@ -84,6 +108,9 @@ namespace RTE { GUIListBox* m_ScriptsListBox; GUILabel* m_ModOrScriptDescriptionLabel; + //todo + std::string m_DisclaimerText; + #pragma region Mod and Script Handling /// Gets whether both lists were fetched, even if nothing valid was added to them. /// @return Whether both lists were fetched, even if nothing valid was added to them. @@ -92,14 +119,25 @@ namespace RTE { /// Fills the KnownMods list with all valid mod DataModules, then fills the ModsListBox using it. void PopulateKnownModsList(); - /// Fills the KnownScripts list with all valid GlobalScripts, then fills the ScriptsListBox using it. - void PopulateKnownScriptsList(); + void InitializeKnownScripts(); + + int ScriptListEntryEncodeExtraIndex(const int, const int); + std::pair ScriptListEntryDecodeExtraIndex(const int); + + const int EXTRA_INDEX_IS_A_MODULE_LABEL_MASK = 1 << 24; + + void PopulateKnownScriptsList(bool); + + void ResetSelectionsAndGoToTop(); /// Turns currently selected mod on and off and changes GUI elements accordingly. void ToggleMod(); - /// Turns currently selected script on and off and changes GUI elements accordingly. - void ToggleScript(); + //todo + ScriptRecord* ScriptListExtraIndexToScriptRecord(int); + + /// todo Turns currently selected script on and off and changes GUI elements accordingly. + void ToggleInScriptList(); #pragma endregion // Disallow the use of some implicit methods. diff --git a/Source/Menus/SaveLoadMenuGUI.cpp b/Source/Menus/SaveLoadMenuGUI.cpp index 4846d958c7..03350d905e 100644 --- a/Source/Menus/SaveLoadMenuGUI.cpp +++ b/Source/Menus/SaveLoadMenuGUI.cpp @@ -21,8 +21,13 @@ #include +#ifdef SYSTEM_MINIZIP +#include +#include +#else #include "zip.h" #include "unzip.h" +#endif using namespace RTE; diff --git a/Source/Menus/ScenarioActivityConfigGUI.cpp b/Source/Menus/ScenarioActivityConfigGUI.cpp index 916e999746..6d675ce237 100644 --- a/Source/Menus/ScenarioActivityConfigGUI.cpp +++ b/Source/Menus/ScenarioActivityConfigGUI.cpp @@ -65,8 +65,6 @@ ScenarioActivityConfigGUI::ScenarioActivityConfigGUI(GUIControlManager* parentCo m_CPULockLabel = dynamic_cast(m_GUIControlManager->GetControl("LabelCPUTeamLock")); m_StartErrorLabel = dynamic_cast(m_GUIControlManager->GetControl("LabelStartError")); m_StartGameButton = dynamic_cast(m_GUIControlManager->GetControl("ButtonStartGame")); - - m_TechListFetched = false; } void ScenarioActivityConfigGUI::PopulateTechComboBoxes() { diff --git a/Source/Menus/ScenarioActivityConfigGUI.h b/Source/Menus/ScenarioActivityConfigGUI.h index f859d3db02..62b2fea672 100644 --- a/Source/Menus/ScenarioActivityConfigGUI.h +++ b/Source/Menus/ScenarioActivityConfigGUI.h @@ -65,16 +65,16 @@ namespace RTE { GUIControlManager* m_GUIControlManager; //!< The GUIControlManager which holds all the GUIControls of this menu. Not owned by this. - const GameActivity* m_SelectedActivity; //!< The Activity this ScenarioActivityConfigGUI is configuring. - const GameActivity* m_PreviouslySelectedActivity; //!< The Activity this ScenarioActivityConfigGUI was configuring last, before it got was disabled. - Scene* m_SelectedScene; //!< The Scene the selected Activity will be using. - int m_LockedCPUTeam = Activity::Teams::NoTeam; //!< Which team the CPU is locked to, if any. + const GameActivity* m_SelectedActivity {}; //!< The Activity this ScenarioActivityConfigGUI is configuring. + const GameActivity* m_PreviouslySelectedActivity {}; //!< The Activity this ScenarioActivityConfigGUI was configuring last, before it got was disabled. + Scene* m_SelectedScene {}; //!< The Scene the selected Activity will be using. + int m_LockedCPUTeam { Activity::Teams::NoTeam }; //!< Which team the CPU is locked to, if any. - bool m_StartingGoldAdjustedManually; //!< Whether the player adjusted the starting gold, meaning it should stop automatically adjusting to the difficulty setting default starting gold where applicable. + bool m_StartingGoldAdjustedManually {}; //!< Whether the player adjusted the starting gold, meaning it should stop automatically adjusting to the difficulty setting default starting gold where applicable. Timer m_StartGameButtonBlinkTimer; //!< Timer for blinking the start game button. - bool m_TechListFetched; //!< Whether the tech list was fetched and each team's ComboBox was populated with it, even if no valid tech modules were added. + bool m_TechListFetched {}; //!< Whether the tech list was fetched and each team's ComboBox was populated with it, even if no valid tech modules were added. /// GUI elements that compose the Activity setup box. GUICollectionBox* m_ActivityConfigBox; diff --git a/Source/Menus/SettingsInputMappingGUI.cpp b/Source/Menus/SettingsInputMappingGUI.cpp index 683a3492b2..de28b72a97 100644 --- a/Source/Menus/SettingsInputMappingGUI.cpp +++ b/Source/Menus/SettingsInputMappingGUI.cpp @@ -8,6 +8,8 @@ #include "GUIScrollbar.h" #include "GUILabel.h" +#include + using namespace RTE; std::array SettingsInputMappingGUI::m_InputElementsUsedByMouse = {InputElements::INPUT_FIRE, InputElements::INPUT_PIEMENU_ANALOG, InputElements::INPUT_AIM, InputElements::INPUT_AIM_UP, InputElements::INPUT_AIM_DOWN, InputElements::INPUT_AIM_LEFT, InputElements::INPUT_AIM_RIGHT}; diff --git a/Source/Menus/TitleScreen.cpp b/Source/Menus/TitleScreen.cpp index c2ab3eccae..906aabd09b 100644 --- a/Source/Menus/TitleScreen.cpp +++ b/Source/Menus/TitleScreen.cpp @@ -1,5 +1,6 @@ #include "TitleScreen.h" +#include "Constants.h" #include "WindowMan.h" #include "FrameMan.h" #include "UInputMan.h" @@ -12,9 +13,11 @@ #include "AllegroBitmap.h" #include "PresetMan.h" #include "MusicMan.h" +#include "WindowMan.h" #include "raylib/raylib.h" #include "raylib/rlgl.h" +#include "Draw.h" using namespace RTE; @@ -546,13 +549,13 @@ void TitleScreen::Draw() { } if (m_IntroSequenceState >= IntroSequence::DataRealmsLogoFadeIn && m_IntroSequenceState <= IntroSequence::DataRealmsLogoFadeOut) { - draw_sprite(g_FrameMan.GetBackBuffer32(), m_DataRealmsLogo, (m_TitleScreenMaxWidth - m_DataRealmsLogo->w) / 2, (g_WindowMan.GetResY() - m_DataRealmsLogo->h) / 2); + DrawTexture(m_DataRealmsLogo, (m_TitleScreenMaxWidth - m_DataRealmsLogo->w) / 2, (g_WindowMan.GetResY() - m_DataRealmsLogo->h) / 2, RLColor(255, 255, 255, 255)); std::string copyrightNotice(64, '\0'); std::snprintf(copyrightNotice.data(), copyrightNotice.size(), "Cortex Command is TM and %c 2023 Data Realms, LLC", -35); AllegroBitmap guiBackBuffer(g_FrameMan.GetBackBuffer32()); m_IntroTextFont->DrawAligned(&guiBackBuffer, m_TitleScreenMaxWidth / 2, g_WindowMan.GetResY() - m_IntroTextFont->GetFontHeight() - 5, copyrightNotice, GUIFont::Centre); } else if (m_IntroSequenceState >= IntroSequence::FmodLogoFadeIn && m_IntroSequenceState <= IntroSequence::FmodLogoFadeOut) { - draw_sprite(g_FrameMan.GetBackBuffer32(), m_FmodLogo, (m_TitleScreenMaxWidth - m_FmodLogo->w) / 2, (g_WindowMan.GetResY() - m_FmodLogo->h) / 2); + DrawTexture(m_FmodLogo, (m_TitleScreenMaxWidth - m_FmodLogo->w) / 2, (g_WindowMan.GetResY() - m_FmodLogo->h) / 2, RLColor(255, 255, 255, 255)); AllegroBitmap guiBackBuffer(g_FrameMan.GetBackBuffer32()); m_IntroTextFont->DrawAligned(&guiBackBuffer, m_TitleScreenMaxWidth / 2, g_WindowMan.GetResY() - m_IntroTextFont->GetFontHeight() - 5, "Made with FMOD Studio by Firelight Technologies Pty Ltd.", GUIFont::Centre); } else if (m_IntroSequenceState >= IntroSequence::ShowSlide1 && m_IntroSequenceState <= IntroSequence::ShowSlide8) { @@ -582,13 +585,9 @@ void TitleScreen::Draw() { } void TitleScreen::DrawTitleScreenScene() { - // This only needs to be done once, but bitmaps can be reloaded which effectively undoes this, so just do it all the time to not deal with flags and checks. - set_write_alpha_blender(); - draw_trans_sprite(m_Planet.GetSpriteFrame(0), ContentFile("Base.rte/GUIs/Title/PlanetAlpha.png").GetAsBitmap(), 0, 0); - draw_trans_sprite(m_Moon.GetSpriteFrame(0), ContentFile("Base.rte/GUIs/Title/MoonAlpha.png").GetAsBitmap(), 0, 0); rlDisableDepthTest(); - Box nebulaTargetBox(Vector(), g_FrameMan.GetBackBuffer32()->w, g_FrameMan.GetBackBuffer32()->h); + Box nebulaTargetBox(Vector(), g_FrameMan.GetBackBuffer32()->w, g_FrameMan.GetBackBuffer32()->h); m_Nebula.SetOffset(Vector(static_cast((m_TitleScreenMaxWidth - m_Nebula.GetBitmap()->w) / 2), m_ScrollOffset.GetY())); m_Nebula.Draw(nebulaTargetBox, nebulaTargetBox, true); @@ -598,10 +597,10 @@ void TitleScreen::DrawTitleScreenScene() { for (const Star& star: m_BackdropStars) { int intensity = star.Intensity + RandomNum(0, (star.Size == Star::StarSize::StarSmall) ? 35 : 70); - //set_screen_blender(intensity, intensity, intensity, intensity); + // set_screen_blender(intensity, intensity, intensity, intensity); int starPosY = static_cast(star.Position.GetY() - (m_ScrollOffset.GetY() * (m_Nebula.GetScrollRatio().GetY() * ((star.Size == Star::StarSize::StarSmall) ? 0.8F : 1.0F)))); DrawTexture(g_GLResourceMan.GetStaticTextureFromBitmap(star.Bitmap), star.Position.m_X, starPosY, RLColor(intensity, intensity, intensity, intensity)); - //draw_trans_sprite(g_FrameMan.GetBackBuffer32(), star.Bitmap, star.Position.GetFloorIntX(), starPosY); + // draw_trans_sprite(g_FrameMan.GetBackBuffer32(), star.Bitmap, star.Position.GetFloorIntX(), starPosY); } rlSetBlendMode(RL_BLEND_ALPHA); @@ -618,20 +617,20 @@ void TitleScreen::DrawTitleScreenScene() { m_StationOffset.RadRotate(m_StationOrbitRotation); m_Station.SetPos(m_PlanetPos + m_StationOffset); m_Station.SetRotAngle(-c_HalfPI + m_StationOrbitRotation); - //m_Station.Draw(g_FrameMan.GetBackBuffer32()); + // m_Station.Draw(g_FrameMan.GetBackBuffer32()); DrawTextureEx(g_GLResourceMan.GetStaticTextureFromBitmap(m_Station.GetSpriteFrame(0)), m_Station.GetPos() + m_Station.GetSpriteOffset() + Vector(m_Station.GetSpriteFrame(0)->w / 2, m_Station.GetSpriteFrame(0)->h / 2), m_StationOrbitRotation - c_HalfPI, 1.0f, {255, 255, 255, 255}); } void TitleScreen::DrawGameLogo() { DrawTextureV(g_GLResourceMan.GetStaticTextureFromBitmap(m_GameLogo.GetSpriteFrame(0)), m_GameLogo.GetPos() + m_GameLogo.GetSpriteOffset(), {255, 255, 255, 255}); - //m_GameLogo.Draw(g_FrameMan.GetBackBuffer32()); + // m_GameLogo.Draw(g_FrameMan.GetBackBuffer32()); m_GameLogoGlow.SetPos(m_GameLogo.GetPos()); rlEnableColorBlend(); rlSetBlendFactorsSeparate(GL_ONE, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_FUNC_ADD, GL_FUNC_ADD); rlSetBlendMode(RL_BLEND_CUSTOM_SEPARATE); int glowIntensity = 220 + RandomNum(-35, 35); - //set_screen_blender(glowIntensity, glowIntensity, glowIntensity, glowIntensity); - //m_GameLogoGlow.Draw(g_FrameMan.GetBackBuffer32(), Vector(), DrawMode::g_DrawTrans); + // set_screen_blender(glowIntensity, glowIntensity, glowIntensity, glowIntensity); + // m_GameLogoGlow.Draw(g_FrameMan.GetBackBuffer32(), Vector(), DrawMode::g_DrawTrans); DrawTextureV(g_GLResourceMan.GetStaticTextureFromBitmap(m_GameLogoGlow.GetSpriteFrame(0)), m_GameLogoGlow.GetPos() + m_GameLogoGlow.GetSpriteOffset(), RLColor(glowIntensity, glowIntensity, glowIntensity, glowIntensity)); } @@ -654,7 +653,8 @@ void TitleScreen::DrawSlideshowSlide() { // Set a clipping rect so parts of slides that are too wide to fit the primary window's display (left-most) don't get drawn on other displays. This only has effect in multi-display fullscreen. set_clip_rect(g_FrameMan.GetBackBuffer32(), 0, 0, m_TitleScreenMaxWidth - g_WindowMan.GetResMultiplier(), g_WindowMan.GetResY()); - draw_trans_sprite(g_FrameMan.GetBackBuffer32(), m_IntroSlides.at(slide), slidePos.GetFloorIntX(), slidePos.GetFloorIntY()); + //draw_trans_sprite(g_FrameMan.GetBackBuffer32(), m_IntroSlides.at(slide), slidePos.GetFloorIntX(), slidePos.GetFloorIntY()); + DrawTextureV(g_GLResourceMan.GetStaticTextureFromBitmap(m_IntroSlides.at(slide)), slidePos, RLColor(255, 255, 255, fadeAmount)); // Have to immediately reset the clipping rect otherwise the stars in the other displays slowly go into warp speed until the intro sequence is done. set_clip_rect(g_FrameMan.GetBackBuffer32(), 0, 0, g_FrameMan.GetBackBuffer32()->w, g_FrameMan.GetBackBuffer32()->h); @@ -668,4 +668,8 @@ void TitleScreen::DrawSlideshowSlide() { void TitleScreen::DrawOverlayEffectBitmap() const { set_trans_blender(m_FadeAmount, m_FadeAmount, m_FadeAmount, m_FadeAmount); draw_trans_sprite(g_FrameMan.GetBackBuffer32(), g_FrameMan.GetOverlayBitmap32(), 0, 0); + rlEnableColorBlend(); + rlSetBlendMode(RL_BLEND_ALPHA); + DrawRectangle(0, 0, g_WindowMan.GetResX(), g_WindowMan.GetResY(), RLColor(1, 1, 1, m_FadeAmount)); + rlDrawRenderBatchActive(); } diff --git a/Source/Renderer/GraphicalPrimitive.cpp b/Source/Renderer/GraphicalPrimitive.cpp index 3b282d1a46..9b9797c78d 100644 --- a/Source/Renderer/GraphicalPrimitive.cpp +++ b/Source/Renderer/GraphicalPrimitive.cpp @@ -9,6 +9,8 @@ #include "AllegroBitmap.h" #include "Draw.h" + +#include #include using namespace RTE; diff --git a/Source/Renderer/RenderTarget.cpp b/Source/Renderer/RenderTarget.cpp index 9765eb310a..eafc09d82b 100644 --- a/Source/Renderer/RenderTarget.cpp +++ b/Source/Renderer/RenderTarget.cpp @@ -16,7 +16,7 @@ RenderTarget::RenderTarget(const FloatRect& size, const FloatRect& defaultViewpo m_Viewport = defaultViewport; if (!defaultFB0) { if (colorTexture.id != 0) { - m_Texture = colorTexture; + m_Texture = std::move(colorTexture); m_ColorTextureOwned = false; } else { m_Texture = { diff --git a/Source/Renderer/RenderTarget.h b/Source/Renderer/RenderTarget.h index 9cdaf0dd2f..19c66001b0 100644 --- a/Source/Renderer/RenderTarget.h +++ b/Source/Renderer/RenderTarget.h @@ -30,9 +30,9 @@ namespace RTE { /// @return The FBO. GLuint GetFramebuffer() { return m_FBO; } /// Getter for the color buffer - Texture2D GetColorTexture() { return m_Texture; } + const Texture2D& GetColorTexture() { return m_Texture; } /// Getter for the depth buffer. - Texture2D GetDepthTexture() { return m_Depth; } + const Texture2D& GetDepthTexture() { return m_Depth; } /// Getter for the size of this target. const FloatRect& GetSize() { return m_Size; } @@ -47,4 +47,4 @@ namespace RTE { Texture2D m_Depth{}; bool m_ColorTextureOwned{true}; }; -} // namespace RTE \ No newline at end of file +} // namespace RTE diff --git a/Source/Renderer/Shader.h b/Source/Renderer/Shader.h index 2cc9cd11fd..14e51df99c 100644 --- a/Source/Renderer/Shader.h +++ b/Source/Renderer/Shader.h @@ -6,6 +6,8 @@ #include "raylib/raylib.h" #include "raylib/rlgl.h" +#include + namespace RTE { class Shader: public Entity { public: diff --git a/Source/System/Atom.cpp b/Source/System/Atom.cpp index 73c39aa87c..e0f3ae690c 100644 --- a/Source/System/Atom.cpp +++ b/Source/System/Atom.cpp @@ -518,7 +518,7 @@ int Atom::SetupSeg(Vector startPos, Vector trajectory, float stepRatio) { return m_Delta[m_Dom] - m_DomSteps; } -bool Atom::StepForward(int numSteps) { +bool Atom::StepForward() { RTEAssert(m_OwnerMO, "Stepping an Atom without a parent MO!"); // Only take the step if the step ratio permits it @@ -1046,7 +1046,7 @@ int Atom::Travel(float travelTime, bool autoTravel) { Vector bottomRightExtent = topLeftExtent + Vector(1.0F, 1.0F); int length = static_cast(static_cast(m_TrailLength) * RandomNum(1.0F - m_TrailLengthVariation, 1.0F)); - for (int i = trailPoints.size() - std::min(length, static_cast(trailPoints.size())); i < trailPoints.size(); ++i) { + for (size_t i = trailPoints.size() - std::min(length, static_cast(trailPoints.size())); i < trailPoints.size(); ++i) { putpixel(trailBitmap, trailPoints[i].first, trailPoints[i].second, m_TrailColor.GetIndex()); topLeftExtent.m_X = std::min(topLeftExtent.m_X, static_cast(trailPoints[i].first)); diff --git a/Source/System/Atom.h b/Source/System/Atom.h index 094d916a22..ea5f3d2d03 100644 --- a/Source/System/Atom.h +++ b/Source/System/Atom.h @@ -293,7 +293,7 @@ namespace RTE { /// @return /// Whether anything was hit during the steps or not. MO hits will only be reported if this Atom is set to hit them, and the MO hit is not ignored by this Atom (if the segment started on that MO). /// Also if terrain hits are temporarily disabled, they will not be reported. - bool StepForward(int numSteps = 1); + bool StepForward(); /// Takes one step back, or undos the step, if any, previously taken along the trajectory segment set up by SetupSeg(). /// @remark CAUTION: The previous HitWhat vars are not reset to what they previously were! diff --git a/Source/System/Box.cpp b/Source/System/Box.cpp index 5f30a7c9c5..9fa1267b0d 100644 --- a/Source/System/Box.cpp +++ b/Source/System/Box.cpp @@ -79,10 +79,7 @@ void Box::Unflip() { } bool Box::IsWithinBox(const Vector& point) const { - return !IsEmpty() && (((m_Width > 0 && point.m_X >= m_Corner.m_X && point.m_X < (m_Corner.m_X + m_Width)) || - (m_Width < 0 && point.m_X < m_Corner.m_X && point.m_X >= (m_Corner.m_X + m_Width))) && - (m_Height > 0 && point.m_Y >= m_Corner.m_Y && point.m_Y < (m_Corner.m_Y + m_Height)) || - (m_Height < 0 && point.m_Y < m_Corner.m_Y && point.m_Y <= (m_Corner.m_Y + m_Height))); + return !IsEmpty() && IsWithinBoxX(point.m_X) && IsWithinBoxY(point.m_Y); } bool Box::IsWithinBoxX(float pointX) const { @@ -142,4 +139,4 @@ Box Box::GetIntersection(const Box& rhs) const { std::min(box1.m_Corner.m_Y + box1.m_Height, box2.m_Corner.m_Y + box2.m_Height))); return returnBox; -} \ No newline at end of file +} diff --git a/Source/System/ContentFile.cpp b/Source/System/ContentFile.cpp index c11a99faac..3d7b9b4b8f 100644 --- a/Source/System/ContentFile.cpp +++ b/Source/System/ContentFile.cpp @@ -12,6 +12,7 @@ #include "fmod/fmod_errors.h" #include +#include #include using namespace RTE; @@ -62,7 +63,7 @@ void ContentFile::FreeAllLoaded() { int ContentFile::ReadProperty(const std::string_view& propName, Reader& reader) { StartPropertyList(return Serializable::ReadProperty(propName, reader)); - MatchForwards("FilePath") + MatchForwards("FilePath") MatchProperty("Path", { SetDataPath(reader.ReadPropValue()); }); MatchProperty("IsMemoryPNG", { reader >> m_IsMemoryPNG; }); @@ -248,8 +249,8 @@ BITMAP* ContentFile::GetAsBitmap(int conversionMode, bool storeBitmap, const std SDL_DestroySurface(surface); s_MemoryPNGs.erase(dataPathToLoad); } - } - + } + if (returnBitmap == nullptr) { if (!System::PathExistsCaseSensitive(dataPathToLoad)) { const std::string dataPathWithoutExtension = dataPathToLoad.substr(0, dataPathToLoad.length() - m_DataPathExtension.length()); @@ -301,11 +302,19 @@ void ContentFile::GetAsAnimation(std::vector& vectorToFill, int frameCo } } } -SDL_Palette* ContentFile::DefaultPaletteToSDL() { +SDL_Palette* ContentFile::DefaultPaletteToSDL(bool preMask) { SDL_Palette* palette = SDL_CreatePalette(256); std::array paletteColor; const PALETTE& defaultPalette = g_FrameMan.GetDefaultPalette(); - paletteColor[0] = {.r = 0, .g = 0, .b = 0, .a = 0}; + if (preMask) { + paletteColor[0] = {.r = 0, .g = 0, .b = 0, .a = 0}; + } else { + paletteColor[0] = {.r = defaultPalette[0].r, + .g = defaultPalette[0].g, + .b = defaultPalette[0].b, + .a = 255 + }; + } for (size_t i = 1; i < paletteColor.size(); ++i) { paletteColor[i].r = defaultPalette[i].r; paletteColor[i].g = defaultPalette[i].g; @@ -329,7 +338,7 @@ SDL_Surface* ContentFile::LoadImageAsSurface(int conversionMode, const std::stri image = newImage; bitDepth = 8; } else if (bitDepth != 8 || convert8To32) { - SDL_Palette* palette = DefaultPaletteToSDL(); + SDL_Palette* palette = DefaultPaletteToSDL(true); if (SDL_GetPixelFormatDetails(image->format)->bits_per_pixel == 8) { SDL_SetSurfacePalette(image, palette); SDL_SetSurfaceColorKey(image, true, 0); @@ -390,7 +399,7 @@ FMOD::Sound* ContentFile::LoadAndReleaseSound(bool abortGameForInvalidSound, boo } if (!System::PathExistsCaseSensitive(m_DataPath)) { bool foundAltExtension = false; - for (const std::string& altFileExtension: c_SupportedAudioFormats) { + for (const char* altFileExtension: c_SupportedAudioFormats) { const std::string altDataPathToLoad = m_DataPathWithoutExtension + altFileExtension; if (System::PathExistsCaseSensitive(altDataPathToLoad)) { g_ConsoleMan.AddLoadWarningLogExtensionMismatchEntry(m_DataPath, m_FormattedReaderPosition, altFileExtension); @@ -442,15 +451,14 @@ void ContentFile::ReloadBitmap(const std::string& filePath, int conversionMode) SDL_Surface* newImage = LoadImageAsSurface(conversionMode, filePath); - BITMAP* newBitmap = create_bitmap_ex(SDL_GetPixelFormatDetails(newImage->format)->bits_per_pixel, newImage->w, newImage->h); // allegro doesn't (always) align lines to 4byte, so copy line by line. SDL_Surface.pitch is the size in bytes per line + alignment padding. for (int y = 0; y < newImage->h; y++) { - memcpy(newBitmap->line[y], static_cast(newImage->pixels) + y * newImage->pitch, newImage->w * SDL_GetPixelFormatDetails(newImage->format)->bytes_per_pixel); + memcpy(newBitmap->line[y], static_cast(newImage->pixels) + y * newImage->pitch, newImage->w * SDL_GetPixelFormatDetails(newImage->format)->bytes_per_pixel); } - //AddAlphaChannel(newBitmap); + // AddAlphaChannel(newBitmap); BITMAP swap; std::memcpy(&swap, loadedBitmap, sizeof(BITMAP)); diff --git a/Source/System/ContentFile.h b/Source/System/ContentFile.h index bfcd119d69..454511d13b 100644 --- a/Source/System/ContentFile.h +++ b/Source/System/ContentFile.h @@ -157,7 +157,8 @@ namespace RTE { #pragma endregion /// Copies the default palette to an sdl palette. - static SDL_Palette* DefaultPaletteToSDL(); + /// @param preMask Whether to replace mask color with 0 alpha (necessary for loading indexed to 32-bit image) + static SDL_Palette* DefaultPaletteToSDL(bool preMask = false); private: /// Enumeration for loading BITMAPs by bit depth. NOTE: This can't be lower down because s_LoadedBitmaps relies on this definition. diff --git a/Source/System/Controller.cpp b/Source/System/Controller.cpp index 1ea45a8199..e7807102f8 100644 --- a/Source/System/Controller.cpp +++ b/Source/System/Controller.cpp @@ -6,6 +6,8 @@ #include "Actor.h" #include "PieMenu.h" +#include + using namespace RTE; void Controller::Clear() { diff --git a/Source/System/Entity.cpp b/Source/System/Entity.cpp index c8f34f15fe..3aa2579c63 100644 --- a/Source/System/Entity.cpp +++ b/Source/System/Entity.cpp @@ -1,7 +1,6 @@ #include "Entity.h" #include "RTETools.h" #include "PresetMan.h" -#include "ConsoleMan.h" #include "DataModule.h" namespace RTE { @@ -64,7 +63,7 @@ namespace RTE { MatchForwards("PresetName") MatchProperty("InstanceName", { SetPresetName(reader.ReadPropValue()); // Preset name might have "[ModuleName]/" preceding it, detect it here and select proper module! - int slashPos = m_PresetName.find_first_of('/'); + size_t slashPos = m_PresetName.find_first_of('/'); if (slashPos != std::string::npos) { m_PresetName = m_PresetName.substr(slashPos + 1); } @@ -238,6 +237,11 @@ namespace RTE { } void Entity::ClassInfo::FillPool(int fillAmount) { +#ifdef __SANITIZE_ADDRESS__ + // If we have ASan, make this a no-op. + (void)(fillAmount); // Silence warning about unused variable. +#else + // Default to the set block allocation size if fillAmount is 0 if (fillAmount <= 0) { fillAmount = m_PoolAllocBlockCount; @@ -249,6 +253,7 @@ namespace RTE { m_AllocatedPool.push_back(m_Allocate()); } } +#endif } bool Entity::ClassInfo::IsClassOrChildClassOf(const ClassInfo* classInfoToCheck) const { @@ -261,6 +266,13 @@ namespace RTE { } void* Entity::ClassInfo::GetPoolMemory() { +#ifdef __SANITIZE_ADDRESS__ + // If compiled with ASan, sidestep pooling and just use the allocator normally. + + void* foundMemory = m_Allocate(); + RTEAssert(foundMemory, "m_Allocate failed! to make memory!"); +#else + std::lock_guard guard(m_Mutex); RTEAssert(IsConcrete(), "Trying to get pool memory of an abstract Entity class!"); @@ -275,6 +287,7 @@ namespace RTE { m_AllocatedPool.pop_back(); RTEAssert(foundMemory, "Could not find an available instance in the pool, even after increasing its size!"); +#endif // Keep track of the number of instances passed out m_InstancesInUse++; @@ -286,8 +299,14 @@ namespace RTE { if (!returnedMemory) { return 0; } + +#ifdef __SANITIZE_ADDRESS__ + // If compiled with ASan, sidestep pooling and just use the allocator normally. + m_Deallocate(returnedMemory); +#else std::lock_guard guard(m_Mutex); m_AllocatedPool.push_back(returnedMemory); +#endif // Keep track of the number of instances passed in m_InstancesInUse--; diff --git a/Source/System/Entity.h b/Source/System/Entity.h index 82e2584cd3..0bd377360b 100644 --- a/Source/System/Entity.h +++ b/Source/System/Entity.h @@ -3,9 +3,18 @@ #include "Serializable.h" #include "RTEError.h" +#include #include #include +// Concoction based on: +// https://stackoverflow.com/questions/34813412/how-to-detect-if-building-with-address-sanitizer-when-building-with-gcc-4-8#78444624 +#if defined(__has_feature) // MSVC doesn't have this +# if __has_feature(address_sanitizer) // for Clang +# define __SANITIZE_ADDRESS__ // GCC and MSVC already set this +# endif +#endif + namespace RTE { typedef std::function MemoryAllocate; //!< Convenient name definition for the memory allocation callback function. @@ -172,7 +181,9 @@ namespace RTE { int m_PoolAllocBlockCount; //!< The number of instances to fill up the pool of this type with each time it runs dry. int m_InstancesInUse; //!< The number of allocated instances passed out from the pool. +#ifndef __ADDRESS_SANITIZER__ // Unused when ASan is enabled. std::mutex m_Mutex; //!< Mutex to ensure multiple things aren't grabbing/deallocating memory at the same time +#endif // Forbidding copying ClassInfo(const ClassInfo& reference) = delete; @@ -357,7 +368,7 @@ namespace RTE { /// Gets the class name of this Entity. /// @return A string with the friendly-formatted type name of this Entity. - virtual const std::string& GetClassName() const { return m_sClass.GetName(); } + virtual const std::string& GetClassName() const override { return m_sClass.GetName(); } #pragma endregion protected: diff --git a/Source/System/InputMapping.h b/Source/System/InputMapping.h index 1efee2d575..db3bca67b8 100644 --- a/Source/System/InputMapping.h +++ b/Source/System/InputMapping.h @@ -29,7 +29,7 @@ namespace RTE { #pragma region Getters and Setters /// Gets the description of the input scheme preset that this element is part of, if any preset has been set for this element's scheme. /// @return The description associated with this element by the scheme preset, if any has been set. This string is empty otherwise. - std::string GetPresetDescription() const { return m_PresetDescription; } + const std::string& GetPresetDescription() const { return m_PresetDescription; } /// Sets the description of the input scheme preset that this element is part of, if any preset has been set for this element's scheme. /// @param presetDescription The description associated with this element by the scheme preset, if any has been set. This string should be empty otherwise. diff --git a/Source/System/Matrix.cpp b/Source/System/Matrix.cpp index c0b15e3bb5..19418c0970 100644 --- a/Source/System/Matrix.cpp +++ b/Source/System/Matrix.cpp @@ -136,13 +136,14 @@ Vector Matrix::operator/(const Vector& rhs) { } Vector retVec = rhs; - // Apply flipping as set. - retVec.m_X = m_Flipped[X] ? -retVec.m_X : retVec.m_X; - retVec.m_Y = m_Flipped[Y] ? -retVec.m_Y : retVec.m_Y; // Do the matrix multiplication. retVec.SetXY(m_Elements[0][0] * retVec.m_X + m_Elements[1][0] * retVec.m_Y, m_Elements[0][1] * retVec.m_X + m_Elements[1][1] * retVec.m_Y); + // Apply flipping as set. + retVec.m_X = m_Flipped[X] ? -retVec.m_X : retVec.m_X; + retVec.m_Y = m_Flipped[Y] ? -retVec.m_Y : retVec.m_Y; + return retVec; } diff --git a/Source/System/Matrix.h b/Source/System/Matrix.h index aacbdb03c6..d0f335f8c8 100644 --- a/Source/System/Matrix.h +++ b/Source/System/Matrix.h @@ -233,11 +233,21 @@ namespace RTE { /// @param rhs A Matrix reference as the right hand side operand. /// @return A reference to the resulting Vector. friend Vector operator*(const Vector& lhs, const Matrix& rhs) { + // Multiplication might call Matrix::UpdateElements and therefore + // needs to modify it. + // + // However, this function signature uses const ref for the matrix. + // + // Therefore, the only way to perform this as needed + // without changing it to mut ref is by copying the matrix. + // + // TODO: see if we can unjank this? Matrix m(rhs); return m * lhs; } /// Division operator overload for a Matrix and a Vector. The vector will be transformed according to the Matrix's elements. + /// Flipping, if set, is performed after rotating. /// @param rhs A Vector reference as the right hand side operand. /// @return The resulting transformed Vector. Vector operator/(const Vector& rhs); @@ -246,7 +256,19 @@ namespace RTE { /// @param lhs A Vector reference as the left hand side operand. /// @param rhs A Matrix reference as the right hand side operand. /// @return A reference to the resulting Vector. - friend Vector operator/(const Vector& lhs, Matrix& rhs) { return rhs / lhs; } + friend Vector operator/(const Vector& lhs, const Matrix& rhs) { + // Division might call Matrix::UpdateElements and therefore + // needs to modify it. + // + // However, this function signature uses const ref for the matrix. + // + // Therefore, the only way to perform this as needed + // without changing it to mut ref is by copying the matrix. + // + // TODO: see if we can unjank this? + Matrix m(rhs); + return m / lhs; + } /// Self-multiplication operator overload for Vector with a Matrix. /// @param lhs A Vector reference as the left hand side operand. diff --git a/Source/System/PathFinder.cpp b/Source/System/PathFinder.cpp index a4dc5808c2..c62653b9a1 100644 --- a/Source/System/PathFinder.cpp +++ b/Source/System/PathFinder.cpp @@ -4,10 +4,10 @@ #include "Scene.h" #include "SceneMan.h" #include "ThreadMan.h" -#include "ConsoleMan.h" #include "tracy/Tracy.hpp" +#include #include using namespace RTE; @@ -172,9 +172,16 @@ int PathFinder::CalculatePath(Vector start, Vector end, std::list& pathR // Actors capable of jumping/jetpacking can jump upwards. s_JumpHeight = jumpHeight; - // How high up we can jump from this node - s_JumpHeightVertical = std::max(1, static_cast(jumpHeight / (m_NodeDimension * c_MPP))); // min of 1 so automovers work a bit better - s_JumpHeightDiagonal = std::max(1, static_cast((jumpHeight * 0.7F) / (m_NodeDimension * c_MPP))); + // How high up we can jump from this node. + if(jumpHeight == FLT_MAX) { + // Probably quite high. + s_JumpHeightVertical = INT_MAX; + s_JumpHeightDiagonal = INT_MAX; + } else { + // Assume at least 1 so automovers work a bit better + s_JumpHeightVertical = std::max(1, static_cast(jumpHeight / (m_NodeDimension * c_MPP))); + s_JumpHeightDiagonal = std::max(1, static_cast((jumpHeight * 0.7F) / (m_NodeDimension * c_MPP))); + } // Actors capable of digging can use s_DigStrength to modify the node adjacency cost. s_DigStrength = digStrength; @@ -258,14 +265,14 @@ void PathFinder::RecalculateAllCosts() { // I hate this copy, but fuck it. std::vector pathNodesIdsVec; pathNodesIdsVec.reserve(m_NodeGrid.size()); - for (int i = 0; i < m_NodeGrid.size(); ++i) { + for (size_t i = 0; i < m_NodeGrid.size(); ++i) { pathNodesIdsVec.push_back(i); } UpdateNodeList(pathNodesIdsVec); } -std::vector PathFinder::RecalculateAreaCosts(std::deque& boxList, int nodeUpdateLimit) { +std::vector PathFinder::RecalculateAreaCosts(std::deque& boxList, size_t nodeUpdateLimit) { ZoneScoped; std::unordered_set nodeIDsToUpdate; @@ -610,7 +617,7 @@ void PathFinder::MarkBoxNavigable(Box box, bool navigable) { void PathFinder::MarkAllNodesNavigable(bool navigable) { std::vector pathNodesIdsVec; pathNodesIdsVec.reserve(m_NodeGrid.size()); - for (int i = 0; i < m_NodeGrid.size(); ++i) { + for (size_t i = 0; i < m_NodeGrid.size(); ++i) { pathNodesIdsVec.push_back(i); } @@ -647,7 +654,7 @@ int PathFinder::ConvertCoordsToNodeId(int x, int y) const { return (y * m_GridWidth) + x; } -void PathFinder::DebugRender(BITMAP* targetBitmap, const Vector& targetPos, int whichScreen) const { +void PathFinder::DebugRender(BITMAP* targetBitmap, const Vector& targetPos) const { for (int x = 0; x < m_GridWidth; ++x) { Vector startPos = (m_NodeGrid[ConvertCoordsToNodeId(x, 0)].Pos - m_Offset) - targetPos; Vector endPos = startPos + Vector(0.0F, m_NodeDimension * m_GridHeight); diff --git a/Source/System/PathFinder.h b/Source/System/PathFinder.h index d6c448a77c..13adbae122 100644 --- a/Source/System/PathFinder.h +++ b/Source/System/PathFinder.h @@ -3,6 +3,7 @@ #include "Box.h" #include "System/MicroPather/micropather.h" +#include #include #include #include @@ -126,7 +127,7 @@ namespace RTE { /// @param boxList The deque of Boxes representing the updated areas. /// @param nodeUpdateLimit The maximum number of PathNodes we'll try to update this frame. True PathNode update count can be higher if we received a big box, as we always do at least 1 box. /// @return The set of PathNode ids that were updated. - std::vector RecalculateAreaCosts(std::deque& boxList, int nodeUpdateLimit); + std::vector RecalculateAreaCosts(std::deque& boxList, size_t nodeUpdateLimit); /// Updates a set of PathNodes, adjusting their transitions. /// This does NOT update the pather, which is required if PathNode costs changed. @@ -172,8 +173,8 @@ namespace RTE { /// Draws a debug rendering for this pathfinder to a BITMAP of choice. /// @param targetBitmap A pointer to a BITMAP to draw on. - /// @param targetGUIBitmap The offset into the scene where the target bitmap's upper left corner is located. - void DebugRender(BITMAP* targetBitmap, const Vector& targetPos = Vector(), int whichScreen = 0) const; + /// @param targetPos The offset into the scene where the target bitmap's upper left corner is located. + void DebugRender(BITMAP* targetBitmap, const Vector& targetPos = Vector()) const; #pragma endregion private: diff --git a/Source/System/PieQuadrant.cpp b/Source/System/PieQuadrant.cpp index 1188d21527..0163aa7088 100644 --- a/Source/System/PieQuadrant.cpp +++ b/Source/System/PieQuadrant.cpp @@ -2,6 +2,8 @@ #include "RTETools.h" +#include + using namespace RTE; void PieQuadrant::Clear() { diff --git a/Source/System/RTETools.cpp b/Source/System/RTETools.cpp index 9e3e1572d5..4c99c80bec 100644 --- a/Source/System/RTETools.cpp +++ b/Source/System/RTETools.cpp @@ -45,7 +45,7 @@ namespace RTE { return startPos + (startToEnd * Lerp(scaleStart, scaleEnd, 0.0F, 1.0F, progressScalar)); } - Matrix Lerp(float scaleStart, float scaleEnd, Matrix startRot, Matrix endRot, float progressScalar) { + Matrix Lerp(float scaleStart, float scaleEnd, const Matrix& startRot, const Matrix& endRot, float progressScalar) { const float fullTurn = c_PI * 2.0F; float angleDelta = std::fmod(endRot.GetRadAngle() - startRot.GetRadAngle(), fullTurn); float angleDistance = std::fmod(angleDelta * 2.0F, fullTurn) - angleDelta; diff --git a/Source/System/RTETools.h b/Source/System/RTETools.h index 26b14ce615..0ce5e77a77 100644 --- a/Source/System/RTETools.h +++ b/Source/System/RTETools.h @@ -143,7 +143,7 @@ namespace RTE { /// @param endRot The end rotation of your Lerp. /// @param progressScalar How far your Lerp has progressed. Automatically normalized through use of scaleStart and scaleEnd. /// @return Interpolated value. - Matrix Lerp(float scaleStart, float scaleEnd, Matrix startRot, Matrix endRot, float progressScalar); + Matrix Lerp(float scaleStart, float scaleEnd, const Matrix& startRot, const Matrix& endRot, float progressScalar); /// Nonlinear ease-in interpolation. Starts slow. /// @param start Start value. @@ -301,5 +301,35 @@ namespace RTE { template int Sign(const Type& value) { return (Type(0) < value) - (Type(0) > value); } + + /// Exponential decay function. Allows decaying a value from A to B at the same rate regardless of delta time. Always stable. + /// + /// As an example, assuming variables like this: + /// float current = 1.0f; + /// float target = 0.0f; + /// float decay = 10.0f; + /// + /// Then running this: + /// + /// current = ExpDecay(current, target, decay, 1.0f / 30.0f); + /// + /// Preduces the same result (barring precision errors) as: + /// + /// current = ExpDecay(current, target, decay, 1.0f / 60.0f); + /// current = ExpDecay(current, target, decay, 1.0f / 60.0f); + /// + /// In both cases, "current" will be equal to about 0.716531310573789. + /// + /// Lecture on the topic: https://youtube.com/watch?v=LSNQuFEDOyQ + /// + /// @param current The current value that we're decaying. + /// @param target Target we're decaying to. + /// @param decay Rate of decay. For example, with 0.7 the value will be decayed about halfway there in 1 second. + /// @param deltaTime Amount of time of decay to simulate. + /// @returns The decayed value. + inline float ExpDecay(float current, float target, float decay, float deltaTime) { + return target + (current - target) * std::exp(-decay * deltaTime); + } + #pragma endregion } // namespace RTE diff --git a/Source/System/Reader.h b/Source/System/Reader.h index 9159c3e0f3..fa41d4ab66 100644 --- a/Source/System/Reader.h +++ b/Source/System/Reader.h @@ -65,7 +65,7 @@ namespace RTE { /// Gets the path of the current file this reader is reading from. /// @return A string with the path, relative from the working directory. - std::string GetCurrentFilePath() const { return m_FilePath; } + const std::string& GetCurrentFilePath() const { return m_FilePath; } /// Gets the line of the current file line this reader is reading from. /// @return A string with the line number that will be read from next. @@ -185,6 +185,16 @@ namespace RTE { *m_Stream >> var; return *this; } + Reader& operator>>(long long& var) { + DiscardEmptySpace(); + *m_Stream >> var; + return *this; + } + Reader& operator>>(unsigned long long& var) { + DiscardEmptySpace(); + *m_Stream >> var; + return *this; + } // Yeah, this is dumb - read as double and cast. // This is because, for whatever fucking reason, iostream can save out floats at a precision that it's then unable to read... Reader& operator>>(float& var) { diff --git a/Source/System/Serializable.h b/Source/System/Serializable.h index ffc782c5f1..7af59c409e 100644 --- a/Source/System/Serializable.h +++ b/Source/System/Serializable.h @@ -3,9 +3,7 @@ #include "Reader.h" #include "Writer.h" -#include #include -#include #include namespace RTE { diff --git a/Source/System/SpatialPartitionGrid.h b/Source/System/SpatialPartitionGrid.h index 347ce1d59e..79f04fde66 100644 --- a/Source/System/SpatialPartitionGrid.h +++ b/Source/System/SpatialPartitionGrid.h @@ -7,6 +7,8 @@ #include "tsl/hopscotch_set.h" +#include + namespace RTE { class Box; diff --git a/Source/System/System.cpp b/Source/System/System.cpp index 853e540cd9..cb41eb6f16 100644 --- a/Source/System/System.cpp +++ b/Source/System/System.cpp @@ -1,7 +1,11 @@ #include "System.h" #include "RTETools.h" +#ifdef SYSTEM_MINIZIP +#include +#else #include "unzip.h" +#endif #include "RTEError.h" @@ -265,7 +269,7 @@ std::string System::ExtractZippedDataModule(const std::string& zippedModulePath) std::array fileBuffer; // Go through and extract every file inside this zip, overwriting every colliding file that already exists in the install directory. - for (int i = 0; i < zippedModuleInfo.number_entry && !abortExtract; ++i) { + for (size_t i = 0; i < zippedModuleInfo.number_entry && !abortExtract; ++i) { unz_file_info currentFileInfo; std::array outputFileInfoData; if (unzGetCurrentFileInfo(zippedModule, ¤tFileInfo, outputFileInfoData.data(), s_MaxFileName, nullptr, 0, nullptr, 0) != UNZ_OK) { @@ -323,32 +327,33 @@ std::string System::ExtractZippedDataModule(const std::string& zippedModulePath) FILE* outputFile = fopen(outputFileName.c_str(), "wb"); if (outputFile == nullptr) { extractionProgressReport << "\tSkipped file: " + outputFileName + " - Could not open/create destination file!\n"; + } else { + // Write the entire file out, reading in buffer size chunks and spitting them out to the output stream. + bool abortWrite = false; + int bytesRead = 0; + int totalBytesRead = 0; + do { + bytesRead = unzReadCurrentFile(zippedModule, fileBuffer.data(), s_FileBufferSize); + totalBytesRead += bytesRead; + + if (bytesRead < 0) { + extractionProgressReport << "\tSkipped file: " + outputFileName + " - File is empty or corrupt!\n"; + abortWrite = true; + // Sanity check how damn big this file we're writing is becoming. could prevent zip bomb exploits: http://en.wikipedia.org/wiki/Zip_bomb + } else if (totalBytesRead >= s_MaxUnzippedFileSize) { + extractionProgressReport << "\tSkipped file: " + outputFileName + " - File is too large, extract it manually!\n"; + abortWrite = true; + } + if (abortWrite) { + break; + } + fwrite(fileBuffer.data(), bytesRead, 1, outputFile); + // Keep going while bytes are still being read (0 means end of file). + } while (bytesRead > 0 && outputFile); + + fclose(outputFile); } - // Write the entire file out, reading in buffer size chunks and spitting them out to the output stream. - bool abortWrite = false; - int bytesRead = 0; - int totalBytesRead = 0; - do { - bytesRead = unzReadCurrentFile(zippedModule, fileBuffer.data(), s_FileBufferSize); - totalBytesRead += bytesRead; - - if (bytesRead < 0) { - extractionProgressReport << "\tSkipped file: " + outputFileName + " - File is empty or corrupt!\n"; - abortWrite = true; - // Sanity check how damn big this file we're writing is becoming. could prevent zip bomb exploits: http://en.wikipedia.org/wiki/Zip_bomb - } else if (totalBytesRead >= s_MaxUnzippedFileSize) { - extractionProgressReport << "\tSkipped file: " + outputFileName + " - File is too large, extract it manually!\n"; - abortWrite = true; - } - if (abortWrite) { - break; - } - fwrite(fileBuffer.data(), bytesRead, 1, outputFile); - // Keep going while bytes are still being read (0 means end of file). - } while (bytesRead > 0 && outputFile); - - fclose(outputFile); unzCloseCurrentFile(zippedModule); extractionProgressReport << "\tExtracted file: " + outputFileName + "\n"; diff --git a/Source/System/Timer.h b/Source/System/Timer.h index 86b8ebbbd8..cac289e3e2 100644 --- a/Source/System/Timer.h +++ b/Source/System/Timer.h @@ -39,6 +39,15 @@ namespace RTE { Create(reference); } + /// Copy assignment operator for Timers. + /// @param rhs A Timer reference. + /// @return A reference to the changed Timer. + inline Timer& operator=(const Timer& rhs) { + Clear(); + Create(rhs); + return *this; + } + /// Makes the Timer object ready for use. /// @return An error return value signaling success or any particular failure. Anything below 0 is an error signal. int Create(); diff --git a/Source/System/Vector.h b/Source/System/Vector.h index cf8d40e7d0..1c7fa28916 100644 --- a/Source/System/Vector.h +++ b/Source/System/Vector.h @@ -31,6 +31,14 @@ namespace RTE { /// @param inputY Float defining the initial Y value of this Vector. inline Vector(const float inputX, const float inputY) : m_X(inputX), m_Y(inputY){}; + + /// Copy constructor method used to instantiate a Vector object + /// identical to an already existing one. + /// @param reference A Vector object which is passed in by reference. + Vector(const Vector& reference) { + m_X = reference.m_X; + m_Y = reference.m_Y; + } #pragma endregion #pragma region Destruction diff --git a/Source/System/Writer.h b/Source/System/Writer.h index b6a2249c3e..c85e83c5d4 100644 --- a/Source/System/Writer.h +++ b/Source/System/Writer.h @@ -40,15 +40,15 @@ namespace RTE { #pragma region Getters /// Gets the path to the file being written. /// @return The full path to the file being written. - std::string GetFilePath() const { return m_FilePath; } + const std::string& GetFilePath() const { return m_FilePath; } /// Gets the name (without path) of the file being written. /// @return The name of file being written. - std::string GetFileName() const { return m_FileName; } + const std::string& GetFileName() const { return m_FileName; } /// Gets the folder path (without filename) to where the file is being written. /// @return The name of folder being written in. - std::string GetFolderPath() const { return m_FolderPath; } + const std::string& GetFolderPath() const { return m_FolderPath; } #pragma endregion #pragma region Writing Operations diff --git a/Source/meson.build b/Source/meson.build index b17159f358..7140aa9ba9 100644 --- a/Source/meson.build +++ b/Source/meson.build @@ -1,9 +1,4 @@ - -if use_pch - pch = meson.current_source_dir()/'System/StandardIncludes.h' -else - pch = '' -endif +pch = meson.current_source_dir()/'System/StandardIncludes.h' sources = [] source_libs = [] source_inc_dirs += [include_directories( diff --git a/external/sources/allegro 4.4.3.1-custom/include/allegro/inline/draw.inl b/external/sources/allegro 4.4.3.1-custom/include/allegro/inline/draw.inl index b09d85af19..a77e1fb530 100644 --- a/external/sources/allegro 4.4.3.1-custom/include/allegro/inline/draw.inl +++ b/external/sources/allegro 4.4.3.1-custom/include/allegro/inline/draw.inl @@ -320,6 +320,7 @@ AL_INLINE(void, draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), (sprite->vtable->color_depth == 8))); bmp->vtable->draw_trans_sprite(bmp, sprite, x, y); } + TracyCZoneEnd(ctx); }) diff --git a/meson.build b/meson.build index 62b313c7a2..171c895161 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('Cortex-Command-Community-Project', ['cpp','c'], subproject_dir: 'external/sources', default_options:['cpp_std=c++20', 'buildtype=release', 'default_library=static'], version:'0.1.0-Pre-4.1', meson_version:'>=1.0.0') +project('Cortex-Command-Community-Project', ['cpp','c'], subproject_dir: 'external/sources', default_options:['cpp_std=c++20', 'buildtype=release', 'default_library=static'], version:'7.0.0-dev', meson_version:'>=1.6.0') #### Build environment Setup #### @@ -26,19 +26,6 @@ if get_option('debug') and get_option('b_lto') warning('Link time optimization enabled in debug mode, debug symbols may not be fully available. Disable b_lto with "meson configure -Db_lto=false".') endif -use_pch = get_option('use_pch').enabled() - -if get_option('use_pch').auto() - ccache = find_program('ccache', required : false) - if ccache.found() - message('Detected ccache, disabling precompiled headers') - use_pch = false - else - message('Using precompiled headers') - use_pch = true - endif -endif - if compiler.get_argument_syntax()== 'gcc' # used for gcc compatible compilers # Build against system libraries on linux message('gcc detected') @@ -133,16 +120,12 @@ elif compiler.get_argument_syntax()== 'msvc' link_args+=['-ignore:4099', '-ignore:4217'] buildtype_debug = get_option('debug') if buildtype_debug - elfname+='.debug' debug_type = get_option('debug_type') if debug_type == 'release' - elfname+='.release' preprocessor_flags += ['-DDEBUG_RELEASE_BUILD'] # enable minimal debug features elif debug_type == 'minimal' - elfname += '.minimal' preprocessor_flags += ['-DDEBUGMODE'] # enable some debug features elif debug_type == 'full' - elfname += '.full' preprocessor_flags += ['-DDEBUG_BUILD', '-DDEBUGMODE'] # enable all debug features; may slow down game endif else @@ -202,6 +185,7 @@ if host_machine.system() in ['linux','darwin'] dependency('tbb'), dependency('gl') ] + preprocessor_flags+=['-DSYSTEM_MINIZIP'] if host_machine.system()=='darwin' deps += dependency('appleframeworks', modules: ['Foundation']) endif @@ -244,6 +228,8 @@ sdl3_image_dep = sdl3_image_proj.get_variable('sdl3_image_dep') boost_dep = declare_dependency(include_directories: include_directories('external/include/boost_1_75')) meson.override_dependency('boost-175', boost_dep) install_rpath = prefix/get_option('fmod_dir') +tracy_proj = subproject('tracy') +tracy_dep = dependency('tracy') allegro_proj = subproject('allegro 4.4.3.1-custom') luajit_proj = subproject('LuaJIT-2.1') luajit_dep = dependency('luajit') @@ -254,8 +240,6 @@ luabind_proj = subproject('luabind-0.7.1') luabind_dep = dependency('luabind') raknet_proj = subproject('RakNet') raknet_dep = dependency('RakNet') -tracy_proj = subproject('tracy') -tracy_dep = dependency('tracy') deps += [sdl3_dep, sdl3_image_dep, allegro_dep, luajit_dep, loadpng_dep, raknet_dep, boost_dep, tracy_dep] #### Sources Setup #### diff --git a/meson_options.txt b/meson_options.txt index 16073dd29f..13a5a867c3 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -16,5 +16,3 @@ option('tracy_enable', type: 'boolean', value: true, description: 'Enable Tracy option('tracy_callstack', type : 'integer', value : 0, description : 'Enfore callstack collection for tracy regions') option('tracy_on_demand', type : 'boolean', value : true, description : 'On-demand profiling') option('tracy_debuginfod', type : 'boolean', value : false, description : 'Enable debuginfod support') - -option('use_pch', type : 'feature', value : 'auto')