diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt
index c2bd873cce6..4de35b21a25 100644
--- a/Core/GameEngine/CMakeLists.txt
+++ b/Core/GameEngine/CMakeLists.txt
@@ -82,6 +82,7 @@ set(GAMEENGINE_SRC
# Include/Common/MultiplayerSettings.h
# Include/Common/NameKeyGenerator.h
Include/Common/ObjectStatusTypes.h
+ Include/Common/OptionPreferences.h
# Include/Common/OSDisplay.h
# Include/Common/Overridable.h
# Include/Common/Override.h
@@ -144,28 +145,28 @@ set(GAMEENGINE_SRC
# Include/GameClient/AnimateWindowManager.h
# Include/GameClient/CampaignManager.h
Include/GameClient/ChallengeGenerals.h
-# Include/GameClient/ClientInstance.h
+ Include/GameClient/ClientInstance.h
Include/GameClient/ClientRandomValue.h
-# Include/GameClient/Color.h
+ Include/GameClient/Color.h
# Include/GameClient/CommandXlat.h
# Include/GameClient/ControlBar.h
# Include/GameClient/ControlBarResizer.h
# Include/GameClient/ControlBarScheme.h
-# Include/GameClient/Credits.h
+ Include/GameClient/Credits.h
# Include/GameClient/DebugDisplay.h
# Include/GameClient/Diplomacy.h
# Include/GameClient/DisconnectMenu.h
# Include/GameClient/Display.h
-# Include/GameClient/DisplayString.h
-# Include/GameClient/DisplayStringManager.h
+ Include/GameClient/DisplayString.h
+ Include/GameClient/DisplayStringManager.h
# Include/GameClient/Drawable.h
# Include/GameClient/DrawableInfo.h
-# Include/GameClient/DrawGroupInfo.h
+ Include/GameClient/DrawGroupInfo.h
# Include/GameClient/EstablishConnectionsMenu.h
# Include/GameClient/Eva.h
# Include/GameClient/ExtendedMessageBox.h
# Include/GameClient/FontDesc.h
-# Include/GameClient/FXList.h
+ Include/GameClient/FXList.h
# Include/GameClient/Gadget.h
# Include/GameClient/GadgetCheckBox.h
# Include/GameClient/GadgetComboBox.h
@@ -178,29 +179,29 @@ set(GAMEENGINE_SRC
# Include/GameClient/GadgetTabControl.h
# Include/GameClient/GadgetTextEntry.h
# Include/GameClient/GameClient.h
-# Include/GameClient/GameFont.h
+ Include/GameClient/GameFont.h
# Include/GameClient/GameInfoWindow.h
-# Include/GameClient/GameText.h
-# Include/GameClient/GameWindow.h
-# Include/GameClient/GameWindowGlobal.h
+ Include/GameClient/GameText.h
+ Include/GameClient/GameWindow.h
+ Include/GameClient/GameWindowGlobal.h
# Include/GameClient/GameWindowID.h
# Include/GameClient/GameWindowManager.h
-# Include/GameClient/GameWindowTransitions.h
-# Include/GameClient/GlobalLanguage.h
-# Include/GameClient/GraphDraw.h
+ Include/GameClient/GameWindowTransitions.h
+ Include/GameClient/GlobalLanguage.h
+ Include/GameClient/GraphDraw.h
# Include/GameClient/GUICallbacks.h
# Include/GameClient/GUICommandTranslator.h
-# Include/GameClient/HeaderTemplate.h
+ Include/GameClient/HeaderTemplate.h
# Include/GameClient/HintSpy.h
# Include/GameClient/HotKey.h
# Include/GameClient/Image.h
-# Include/GameClient/IMEManager.h
+ Include/GameClient/IMEManager.h
# Include/GameClient/InGameUI.h
-# Include/GameClient/Keyboard.h
+ Include/GameClient/Keyboard.h
# Include/GameClient/KeyDefs.h
-# Include/GameClient/LanguageFilter.h
-# Include/GameClient/Line2D.h
-# Include/GameClient/LoadScreen.h
+ Include/GameClient/LanguageFilter.h
+ Include/GameClient/Line2D.h
+ Include/GameClient/LoadScreen.h
# Include/GameClient/LookAtXlat.h
Include/GameClient/MapUtil.h
# Include/GameClient/MessageBox.h
@@ -208,14 +209,14 @@ set(GAMEENGINE_SRC
# Include/GameClient/Module/AnimatedParticleSysBoneClientUpdate.h
# Include/GameClient/Module/BeaconClientUpdate.h
# Include/GameClient/Module/SwayClientUpdate.h
-# Include/GameClient/Mouse.h
+ Include/GameClient/Mouse.h
Include/GameClient/ParabolicEase.h
Include/GameClient/ParticleSys.h
# Include/GameClient/PlaceEventTranslator.h
-# Include/GameClient/ProcessAnimateWindow.h
-# Include/GameClient/RadiusDecal.h
+ Include/GameClient/ProcessAnimateWindow.h
+ Include/GameClient/RadiusDecal.h
# Include/GameClient/RayEffect.h
-# Include/GameClient/SelectionInfo.h
+ Include/GameClient/SelectionInfo.h
# Include/GameClient/SelectionXlat.h
# Include/GameClient/Shadow.h
# Include/GameClient/Shell.h
@@ -223,16 +224,16 @@ set(GAMEENGINE_SRC
# Include/GameClient/ShellMenuScheme.h
Include/GameClient/Smudge.h
Include/GameClient/Snow.h
-# Include/GameClient/Statistics.h
+ Include/GameClient/Statistics.h
Include/GameClient/TerrainRoads.h
Include/GameClient/TerrainVisual.h
Include/GameClient/VideoPlayer.h
Include/GameClient/View.h
Include/GameClient/Water.h
-# Include/GameClient/WindowLayout.h
+ Include/GameClient/WindowLayout.h
Include/GameClient/WindowVideoManager.h
# Include/GameClient/WindowXlat.h
-# Include/GameClient/WinInstanceData.h
+ Include/GameClient/WinInstanceData.h
# Include/GameLogic/AI.h
# Include/GameLogic/AIDock.h
# Include/GameLogic/AIGuard.h
@@ -621,6 +622,7 @@ set(GAMEENGINE_SRC
# Source/Common/MiniLog.cpp
# Source/Common/MultiplayerSettings.cpp
# Source/Common/NameKeyGenerator.cpp
+ Source/Common/OptionPreferences.cpp
# Source/Common/PartitionSolver.cpp
# Source/Common/PerfTimer.cpp
Source/Common/RandomValue.cpp
@@ -696,24 +698,24 @@ set(GAMEENGINE_SRC
Source/Common/UserPreferences.cpp
# Source/Common/version.cpp
Source/Common/WorkerProcess.cpp
-# Source/GameClient/ClientInstance.cpp
-# Source/GameClient/Color.cpp
-# Source/GameClient/Credits.cpp
+ Source/GameClient/ClientInstance.cpp
+ Source/GameClient/Color.cpp
+ Source/GameClient/Credits.cpp
# Source/GameClient/Display.cpp
-# Source/GameClient/DisplayString.cpp
-# Source/GameClient/DisplayStringManager.cpp
+ Source/GameClient/DisplayString.cpp
+ Source/GameClient/DisplayStringManager.cpp
# Source/GameClient/Drawable.cpp
# Source/GameClient/Drawable/Update/AnimatedParticleSysBoneClientUpdate.cpp
# Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp
# Source/GameClient/Drawable/Update/SwayClientUpdate.cpp
-# Source/GameClient/DrawGroupInfo.cpp
+ Source/GameClient/DrawGroupInfo.cpp
# Source/GameClient/Eva.cpp
-# Source/GameClient/FXList.cpp
+ Source/GameClient/FXList.cpp
# Source/GameClient/GameClient.cpp
# Source/GameClient/GameClientDispatch.cpp
-# Source/GameClient/GameText.cpp
-# Source/GameClient/GlobalLanguage.cpp
-# Source/GameClient/GraphDraw.cpp
+ Source/GameClient/GameText.cpp
+ Source/GameClient/GlobalLanguage.cpp
+ Source/GameClient/GraphDraw.cpp
# Source/GameClient/GUI/AnimateWindowManager.cpp
Source/GameClient/GUI/ChallengeGenerals.cpp
# Source/GameClient/GUI/ControlBar/ControlBar.cpp
@@ -741,12 +743,12 @@ set(GAMEENGINE_SRC
# Source/GameClient/GUI/Gadget/GadgetTabControl.cpp
# Source/GameClient/GUI/Gadget/GadgetTextEntry.cpp
# Source/GameClient/GUI/Gadget/GadgetVerticalSlider.cpp
-# Source/GameClient/GUI/GameFont.cpp
-# Source/GameClient/GUI/GameWindow.cpp
-# Source/GameClient/GUI/GameWindowGlobal.cpp
+ Source/GameClient/GUI/GameFont.cpp
+ Source/GameClient/GUI/GameWindow.cpp
+ Source/GameClient/GUI/GameWindowGlobal.cpp
# Source/GameClient/GUI/GameWindowManager.cpp
# Source/GameClient/GUI/GameWindowManagerScript.cpp
-# Source/GameClient/GUI/GameWindowTransitions.cpp
+ Source/GameClient/GUI/GameWindowTransitions.cpp
# Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
# Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp
# Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
@@ -799,20 +801,20 @@ set(GAMEENGINE_SRC
# Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp
# Source/GameClient/GUI/GUICallbacks/MessageBox.cpp
# Source/GameClient/GUI/GUICallbacks/ReplayControls.cpp
-# Source/GameClient/GUI/HeaderTemplate.cpp
-# Source/GameClient/GUI/IMEManager.cpp
-# Source/GameClient/GUI/LoadScreen.cpp
-# Source/GameClient/GUI/ProcessAnimateWindow.cpp
+ Source/GameClient/GUI/HeaderTemplate.cpp
+ Source/GameClient/GUI/IMEManager.cpp
+ Source/GameClient/GUI/LoadScreen.cpp
+ Source/GameClient/GUI/ProcessAnimateWindow.cpp
# Source/GameClient/GUI/Shell/Shell.cpp
# Source/GameClient/GUI/Shell/ShellMenuScheme.cpp
-# Source/GameClient/GUI/WindowLayout.cpp
+ Source/GameClient/GUI/WindowLayout.cpp
Source/GameClient/GUI/WindowVideoManager.cpp
-# Source/GameClient/GUI/WinInstanceData.cpp
+ Source/GameClient/GUI/WinInstanceData.cpp
# Source/GameClient/InGameUI.cpp
-# Source/GameClient/Input/Keyboard.cpp
-# Source/GameClient/Input/Mouse.cpp
-# Source/GameClient/LanguageFilter.cpp
-# Source/GameClient/Line2D.cpp
+ Source/GameClient/Input/Keyboard.cpp
+ Source/GameClient/Input/Mouse.cpp
+ Source/GameClient/LanguageFilter.cpp
+ Source/GameClient/Line2D.cpp
Source/GameClient/MapUtil.cpp
# Source/GameClient/MessageStream/CommandXlat.cpp
# Source/GameClient/MessageStream/GUICommandTranslator.cpp
@@ -824,10 +826,10 @@ set(GAMEENGINE_SRC
# Source/GameClient/MessageStream/SelectionXlat.cpp
# Source/GameClient/MessageStream/WindowXlat.cpp
Source/GameClient/ParabolicEase.cpp
-# Source/GameClient/RadiusDecal.cpp
-# Source/GameClient/SelectionInfo.cpp
+ Source/GameClient/RadiusDecal.cpp
+ Source/GameClient/SelectionInfo.cpp
Source/GameClient/Snow.cpp
-# Source/GameClient/Statistics.cpp
+ Source/GameClient/Statistics.cpp
# Source/GameClient/System/Anim2D.cpp
# Source/GameClient/System/CampaignManager.cpp
Source/GameClient/System/Debug/AudioDebugDisplay.cpp
diff --git a/Core/GameEngine/Include/Common/OptionPreferences.h b/Core/GameEngine/Include/Common/OptionPreferences.h
new file mode 100644
index 00000000000..9b007449d98
--- /dev/null
+++ b/Core/GameEngine/Include/Common/OptionPreferences.h
@@ -0,0 +1,116 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 Electronic Arts Inc.
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+// //
+// (c) 2001-2003 Electronic Arts Inc. //
+// //
+////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////
+// FILE: OptionPreferences.h
+// Author: Matthew D. Campbell, April 2002
+// Description: Saving/Loading of option preferences
+///////////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include "Common/UserPreferences.h"
+
+typedef UnsignedInt CursorCaptureMode;
+typedef UnsignedInt ScreenEdgeScrollMode;
+
+//-----------------------------------------------------------------------------
+// OptionsPreferences options menu class
+//-----------------------------------------------------------------------------
+class OptionPreferences : public UserPreferences
+{
+public:
+ OptionPreferences();
+ virtual ~OptionPreferences();
+
+ Bool loadFromIniFile();
+
+ UnsignedInt getLANIPAddress(void);
+ UnsignedInt getOnlineIPAddress(void);
+ void setLANIPAddress(AsciiString IP);
+ void setOnlineIPAddress(AsciiString IP);
+ void setLANIPAddress(UnsignedInt IP);
+ void setOnlineIPAddress(UnsignedInt IP);
+ Bool getArchiveReplaysEnabled() const;
+ Bool getAlternateMouseModeEnabled(void);
+ Bool getRetaliationModeEnabled();
+ Bool getDoubleClickAttackMoveEnabled(void);
+ Real getScrollFactor(void);
+ Bool getDrawScrollAnchor(void);
+ Bool getMoveScrollAnchor(void);
+ Bool getCursorCaptureEnabledInWindowedGame() const;
+ Bool getCursorCaptureEnabledInWindowedMenu() const;
+ Bool getCursorCaptureEnabledInFullscreenGame() const;
+ Bool getCursorCaptureEnabledInFullscreenMenu() const;
+ CursorCaptureMode getCursorCaptureMode() const;
+ Bool getScreenEdgeScrollEnabledInWindowedApp() const;
+ Bool getScreenEdgeScrollEnabledInFullscreenApp() const;
+ ScreenEdgeScrollMode getScreenEdgeScrollMode() const;
+ Bool getSendDelay(void);
+ Int getFirewallBehavior(void);
+ Short getFirewallPortAllocationDelta(void);
+ UnsignedShort getFirewallPortOverride(void);
+ Bool getFirewallNeedToRefresh(void);
+ Bool usesSystemMapDir(void);
+ AsciiString getPreferred3DProvider(void);
+ AsciiString getSpeakerType(void);
+ Real getSoundVolume(void);
+ Real get3DSoundVolume(void);
+ Real getSpeechVolume(void);
+ Real getMusicVolume(void);
+ Real getMoneyTransactionVolume(void) const;
+ Bool saveCameraInReplays(void);
+ Bool useCameraInReplays(void);
+ Bool getPlayerObserverEnabled() const;
+ Int getStaticGameDetail(void);
+ Int getIdealStaticGameDetail(void);
+ Real getGammaValue(void);
+ Int getTextureReduction(void);
+ void getResolution(Int *xres, Int *yres);
+ Bool get3DShadowsEnabled(void);
+ Bool get2DShadowsEnabled(void);
+ Bool getCloudShadowsEnabled(void);
+ Bool getLightmapEnabled(void);
+ Bool getSmoothWaterEnabled(void);
+ Bool getTreesEnabled(void);
+ Bool getExtraAnimationsDisabled(void);
+ Bool getUseHeatEffects(void);
+ Bool getDynamicLODEnabled(void);
+ Bool getFPSLimitEnabled(void);
+ Bool getBuildingOcclusionEnabled(void);
+ Int getParticleCap(void);
+
+ Int getCampaignDifficulty(void);
+ void setCampaignDifficulty(Int diff);
+
+ Int getNetworkLatencyFontSize(void);
+ Int getRenderFpsFontSize(void);
+ Int getSystemTimeFontSize(void);
+ Int getGameTimeFontSize(void);
+ Int getPlayerInfoListFontSize(void);
+
+ Real getResolutionFontAdjustment(void);
+
+ Bool getShowMoneyPerMinute(void) const;
+};
diff --git a/Core/GameEngine/Include/Common/Radar.h b/Core/GameEngine/Include/Common/Radar.h
index ce9ed8042d4..50e3e8e4ee0 100644
--- a/Core/GameEngine/Include/Common/Radar.h
+++ b/Core/GameEngine/Include/Common/Radar.h
@@ -106,7 +106,6 @@ class RadarObject : public MemoryPoolObject,
const RadarObject *friend_getNext( void ) const { return m_next; }
Bool isTemporarilyHidden() const;
- static Bool isTemporarilyHidden(const Object* obj);
protected:
@@ -260,12 +259,6 @@ class Radar : public Snapshot,
* in exactly the same priority as the regular
* object list for all other objects */
- // TheSuperHackers @bugfix xezon 22/11/2025 Now stores local heroes in a separate list,
- // because they are treated with special icons but should otherwise work like all other
- // radar objects. In retail version, the cached hero object data was able to dangle
- // for a few frames and cause undefined behavior.
- RadarObject *m_localHeroObjectList; ///< list of hero objects for the local player
-
Real m_terrainAverageZ; ///< average Z for terrain samples
Real m_waterAverageZ; ///< average Z for water samples
diff --git a/Core/GameEngine/Include/Common/UserPreferences.h b/Core/GameEngine/Include/Common/UserPreferences.h
index e3ec9b450ec..64f969f168d 100644
--- a/Core/GameEngine/Include/Common/UserPreferences.h
+++ b/Core/GameEngine/Include/Common/UserPreferences.h
@@ -36,8 +36,6 @@
#include "Common/STLTypedefs.h"
class Money;
-typedef UnsignedInt CursorCaptureMode;
-typedef UnsignedInt ScreenEdgeScrollMode;
//-----------------------------------------------------------------------------
// PUBLIC TYPES ///////////////////////////////////////////////////////////////
@@ -72,87 +70,6 @@ class UserPreferences : public PreferenceMap
AsciiString m_filename;
};
-//-----------------------------------------------------------------------------
-// OptionsPreferences options menu class
-//-----------------------------------------------------------------------------
-class OptionPreferences : public UserPreferences
-{
-public:
- OptionPreferences( );
- virtual ~OptionPreferences();
-
- Bool loadFromIniFile();
-
- UnsignedInt getLANIPAddress(void); // convenience function
- UnsignedInt getOnlineIPAddress(void); // convenience function
- void setLANIPAddress(AsciiString IP); // convenience function
- void setOnlineIPAddress(AsciiString IP); // convenience function
- void setLANIPAddress(UnsignedInt IP); // convenience function
- void setOnlineIPAddress(UnsignedInt IP); // convenience function
- Bool getArchiveReplaysEnabled() const; // convenience function
- Bool getAlternateMouseModeEnabled(void); // convenience function
- Bool getRetaliationModeEnabled(); // convenience function
- Bool getDoubleClickAttackMoveEnabled(void); // convenience function
- Real getScrollFactor(void); // convenience function
- Bool getDrawScrollAnchor(void);
- Bool getMoveScrollAnchor(void);
- Bool getCursorCaptureEnabledInWindowedGame() const;
- Bool getCursorCaptureEnabledInWindowedMenu() const;
- Bool getCursorCaptureEnabledInFullscreenGame() const;
- Bool getCursorCaptureEnabledInFullscreenMenu() const;
- CursorCaptureMode getCursorCaptureMode() const;
- Bool getScreenEdgeScrollEnabledInWindowedApp() const;
- Bool getScreenEdgeScrollEnabledInFullscreenApp() const;
- ScreenEdgeScrollMode getScreenEdgeScrollMode() const;
- Bool getSendDelay(void); // convenience function
- Int getFirewallBehavior(void); // convenience function
- Short getFirewallPortAllocationDelta(void); // convenience function
- UnsignedShort getFirewallPortOverride(void); // convenience function
- Bool getFirewallNeedToRefresh(void); // convenience function
- Bool usesSystemMapDir(void); // convenience function
- AsciiString getPreferred3DProvider(void); // convenience function
- AsciiString getSpeakerType(void); // convenience function
- Real getSoundVolume(void); // convenience function
- Real get3DSoundVolume(void); // convenience function
- Real getSpeechVolume(void); // convenience function
- Real getMusicVolume(void); // convenience function
- Real getMoneyTransactionVolume(void) const;
- Bool saveCameraInReplays(void);
- Bool useCameraInReplays(void);
- Bool getPlayerObserverEnabled() const;
- Int getStaticGameDetail(void); // detail level selected by the user.
- Int getIdealStaticGameDetail(void); // detail level detected for user.
- Real getGammaValue(void);
- Int getTextureReduction(void);
- void getResolution(Int *xres, Int *yres);
- Bool get3DShadowsEnabled(void);
- Bool get2DShadowsEnabled(void);
- Bool getCloudShadowsEnabled(void);
- Bool getLightmapEnabled(void);
- Bool getSmoothWaterEnabled(void);
- Bool getTreesEnabled(void);
- Bool getExtraAnimationsDisabled(void);
- Bool getUseHeatEffects(void);
- Bool getDynamicLODEnabled(void);
- Bool getFPSLimitEnabled(void);
- Bool getNoDynamicLODEnabled(void);
- Bool getBuildingOcclusionEnabled(void);
- Int getParticleCap(void);
-
- Int getCampaignDifficulty(void);
- void setCampaignDifficulty( Int diff );
-
- Int getNetworkLatencyFontSize(void);
- Int getRenderFpsFontSize(void);
- Int getSystemTimeFontSize(void);
- Int getGameTimeFontSize(void);
- Int getPlayerInfoListFontSize(void);
-
- Real getResolutionFontAdjustment(void);
-
- Bool getShowMoneyPerMinute(void) const;
-};
-
//-----------------------------------------------------------------------------
// LANPreferences class
//-----------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Include/GameClient/ClientInstance.h b/Core/GameEngine/Include/GameClient/ClientInstance.h
similarity index 100%
rename from Generals/Code/GameEngine/Include/GameClient/ClientInstance.h
rename to Core/GameEngine/Include/GameClient/ClientInstance.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Color.h b/Core/GameEngine/Include/GameClient/Color.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/Color.h
rename to Core/GameEngine/Include/GameClient/Color.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Credits.h b/Core/GameEngine/Include/GameClient/Credits.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/Credits.h
rename to Core/GameEngine/Include/GameClient/Credits.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/DisplayString.h b/Core/GameEngine/Include/GameClient/DisplayString.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/DisplayString.h
rename to Core/GameEngine/Include/GameClient/DisplayString.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/DisplayStringManager.h b/Core/GameEngine/Include/GameClient/DisplayStringManager.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/DisplayStringManager.h
rename to Core/GameEngine/Include/GameClient/DisplayStringManager.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/DrawGroupInfo.h b/Core/GameEngine/Include/GameClient/DrawGroupInfo.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/DrawGroupInfo.h
rename to Core/GameEngine/Include/GameClient/DrawGroupInfo.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/FXList.h b/Core/GameEngine/Include/GameClient/FXList.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/FXList.h
rename to Core/GameEngine/Include/GameClient/FXList.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameFont.h b/Core/GameEngine/Include/GameClient/GameFont.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameFont.h
rename to Core/GameEngine/Include/GameClient/GameFont.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameText.h b/Core/GameEngine/Include/GameClient/GameText.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameText.h
rename to Core/GameEngine/Include/GameClient/GameText.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameWindow.h b/Core/GameEngine/Include/GameClient/GameWindow.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameWindow.h
rename to Core/GameEngine/Include/GameClient/GameWindow.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowGlobal.h b/Core/GameEngine/Include/GameClient/GameWindowGlobal.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowGlobal.h
rename to Core/GameEngine/Include/GameClient/GameWindowGlobal.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowTransitions.h b/Core/GameEngine/Include/GameClient/GameWindowTransitions.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowTransitions.h
rename to Core/GameEngine/Include/GameClient/GameWindowTransitions.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GlobalLanguage.h b/Core/GameEngine/Include/GameClient/GlobalLanguage.h
similarity index 88%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GlobalLanguage.h
rename to Core/GameEngine/Include/GameClient/GlobalLanguage.h
index d69b73eda4d..cbb44d5f0c1 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameClient/GlobalLanguage.h
+++ b/Core/GameEngine/Include/GameClient/GlobalLanguage.h
@@ -77,6 +77,8 @@ class GlobalLanguage : public SubsystemInterface
ResolutionFontSizeMethod_Default = ResolutionFontSizeMethod_ClassicNoCeiling,
};
+ typedef std::list StringList; // Used for our font file names that we want to load
+
public:
GlobalLanguage();
@@ -84,7 +86,19 @@ class GlobalLanguage : public SubsystemInterface
void init();
void reset();
- void update() { }
+ void update() {}
+
+ Real getResolutionFontSizeAdjustment() const;
+ Int adjustFontSize(Int theFontSize); // Adjusts font size for resolution. jba.
+
+ void parseCustomDefinition();
+
+ // Get current resolution font size scale for the given method and scaler, based on the base game resolution of 800 x 600.
+ // Defaults to a scaler of 1 for a uniform resolution scale.
+ static Real getResolutionFontSizeScale(ResolutionFontSizeMethod method, Real scaler = 1.0f);
+
+ static void parseFontFileName(INI *ini, void *instance, void *store, const void *userData);
+ static void parseFontDesc(INI *ini, void *instance, void *store, const void *userData);
AsciiString m_unicodeFontName;
AsciiString m_unicodeFontFileName;
@@ -111,19 +125,9 @@ class GlobalLanguage : public SubsystemInterface
Real m_resolutionFontSizeAdjustment;
Real m_userResolutionFontSizeAdjustment;
ResolutionFontSizeMethod m_resolutionFontSizeMethod;
-
- float getResolutionFontSizeAdjustment() const;
- Int adjustFontSize(Int theFontSize); // Adjusts font size for resolution. jba.
-
- void parseCustomDefinition();
-
- typedef std::list StringList; // Used for our font file names that we want to load
- typedef StringList::iterator StringListIt;
-
- StringList m_localFonts; // List of the font filenames that are in our local directory
- static void parseFontFileName( INI *ini, void *instance, void *store, const void* userData );
- static void parseFontDesc(INI *ini, void *instance, void *store, const void* userData);
+ StringList m_localFonts; // List of the font filenames that are in our local directory
};
+
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GraphDraw.h b/Core/GameEngine/Include/GameClient/GraphDraw.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/GraphDraw.h
rename to Core/GameEngine/Include/GameClient/GraphDraw.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/HeaderTemplate.h b/Core/GameEngine/Include/GameClient/HeaderTemplate.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/HeaderTemplate.h
rename to Core/GameEngine/Include/GameClient/HeaderTemplate.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/IMEManager.h b/Core/GameEngine/Include/GameClient/IMEManager.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/IMEManager.h
rename to Core/GameEngine/Include/GameClient/IMEManager.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Keyboard.h b/Core/GameEngine/Include/GameClient/Keyboard.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/Keyboard.h
rename to Core/GameEngine/Include/GameClient/Keyboard.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/LanguageFilter.h b/Core/GameEngine/Include/GameClient/LanguageFilter.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/LanguageFilter.h
rename to Core/GameEngine/Include/GameClient/LanguageFilter.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Line2D.h b/Core/GameEngine/Include/GameClient/Line2D.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/Line2D.h
rename to Core/GameEngine/Include/GameClient/Line2D.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h b/Core/GameEngine/Include/GameClient/LoadScreen.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/LoadScreen.h
rename to Core/GameEngine/Include/GameClient/LoadScreen.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Mouse.h b/Core/GameEngine/Include/GameClient/Mouse.h
similarity index 99%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/Mouse.h
rename to Core/GameEngine/Include/GameClient/Mouse.h
index 73e6512381c..ce9edc90e75 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameClient/Mouse.h
+++ b/Core/GameEngine/Include/GameClient/Mouse.h
@@ -323,7 +323,6 @@ class Mouse : public SubsystemInterface
Bool isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt previousMouseClick, UnsignedInt currentMouseClick);
-
AsciiString m_tooltipFontName; ///< tooltip font
Int m_tooltipFontSize; ///< tooltip font
Bool m_tooltipFontIsBold; ///< tooltip font
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/ProcessAnimateWindow.h b/Core/GameEngine/Include/GameClient/ProcessAnimateWindow.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/ProcessAnimateWindow.h
rename to Core/GameEngine/Include/GameClient/ProcessAnimateWindow.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/RadiusDecal.h b/Core/GameEngine/Include/GameClient/RadiusDecal.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/RadiusDecal.h
rename to Core/GameEngine/Include/GameClient/RadiusDecal.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/SelectionInfo.h b/Core/GameEngine/Include/GameClient/SelectionInfo.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/SelectionInfo.h
rename to Core/GameEngine/Include/GameClient/SelectionInfo.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/Statistics.h b/Core/GameEngine/Include/GameClient/Statistics.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/Statistics.h
rename to Core/GameEngine/Include/GameClient/Statistics.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/WinInstanceData.h b/Core/GameEngine/Include/GameClient/WinInstanceData.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/WinInstanceData.h
rename to Core/GameEngine/Include/GameClient/WinInstanceData.h
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/WindowLayout.h b/Core/GameEngine/Include/GameClient/WindowLayout.h
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Include/GameClient/WindowLayout.h
rename to Core/GameEngine/Include/GameClient/WindowLayout.h
diff --git a/Core/GameEngine/Include/GameNetwork/NetworkDefs.h b/Core/GameEngine/Include/GameNetwork/NetworkDefs.h
index 450bee52104..6cb01381c5c 100644
--- a/Core/GameEngine/Include/GameNetwork/NetworkDefs.h
+++ b/Core/GameEngine/Include/GameNetwork/NetworkDefs.h
@@ -41,11 +41,10 @@ extern Int MIN_RUNAHEAD;
extern Int FRAME_DATA_LENGTH;
extern Int FRAMES_TO_KEEP;
-// This is the connection numbering: 1-8 are for players, 9 is a broadcast con.
+// This is the connection numbering: 1-8 are for players
enum ConnectionNumbers CPP_11(: Int)
{
MAX_PLAYER = 7, // The index of the highest possible player number. This is 0 based, so the most players allowed in a game is MAX_PLAYER+1.
- NUM_CONNECTIONS
};
static constexpr const Int MAX_SLOTS = MAX_PLAYER+1;
diff --git a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp
index ea9a1956eed..c2ed8b344e1 100644
--- a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp
+++ b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp
@@ -59,7 +59,7 @@
#include "Common/OSDisplay.h"
#include "Common/Player.h"
#include "Common/PlayerList.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/ControlBar.h"
#include "GameClient/Drawable.h"
diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp
index d1be02f84d9..ddf32efa668 100644
--- a/Core/GameEngine/Source/Common/INI/INI.cpp
+++ b/Core/GameEngine/Source/Common/INI/INI.cpp
@@ -457,7 +457,7 @@ UnsignedInt INI::load( AsciiString filename, INILoadType loadType, Xfer *pXfer,
}
else
{
- DEBUG_ASSERTCRASH( 0, ("[LINE: %d - FILE: '%s'] Unknown block '%s'",
+ DEBUG_CRASH( ("[LINE: %d - FILE: '%s'] Unknown block '%s'",
getLineNum(), getFilename().str(), token ) );
throw INI_UNKNOWN_TOKEN;
}
@@ -543,7 +543,7 @@ void INI::readLine( void )
// check for at the max
if ( p == m_buffer+INI_MAX_CHARS_PER_LINE )
{
- DEBUG_ASSERTCRASH( 0, ("Buffer too small (%d) and was truncated, increase INI_MAX_CHARS_PER_LINE", INI_MAX_CHARS_PER_LINE) );
+ DEBUG_CRASH( ("Buffer too small (%d) and was truncated, increase INI_MAX_CHARS_PER_LINE", INI_MAX_CHARS_PER_LINE) );
}
}
@@ -1639,7 +1639,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
if( what == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("INI::initFromINI - Invalid parameters supplied!") );
+ DEBUG_CRASH( ("INI::initFromINI - Invalid parameters supplied!") );
throw INI_INVALID_PARAMS;
}
@@ -1693,7 +1693,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
if (!found)
{
- DEBUG_ASSERTCRASH( 0, ("[LINE: %d - FILE: '%s'] Unknown field '%s' in block '%s'",
+ DEBUG_CRASH( ("[LINE: %d - FILE: '%s'] Unknown field '%s' in block '%s'",
INI::getLineNum(), INI::getFilename().str(), field, m_curBlockStart) );
}
@@ -1706,7 +1706,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
{
done = TRUE;
- DEBUG_ASSERTCRASH( 0, ("Error parsing block '%s', in INI file '%s'. Missing '%s' token",
+ DEBUG_CRASH( ("Error parsing block '%s', in INI file '%s'. Missing '%s' token",
m_curBlockStart, getFilename().str(), m_blockEndToken) );
throw INI_MISSING_END_TOKEN;
@@ -1782,7 +1782,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
if( nameList == nullptr || nameList[ 0 ] == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("INTERNAL ERROR! scanIndexList, invalid name list") );
+ DEBUG_CRASH( ("INTERNAL ERROR! scanIndexList, invalid name list") );
throw INI_INVALID_NAME_LIST;
}
@@ -1807,7 +1807,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList
{
if( lookupList == nullptr || lookupList[ 0 ].name == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("INTERNAL ERROR! scanLookupList, invalid name list") );
+ DEBUG_CRASH( ("INTERNAL ERROR! scanLookupList, invalid name list") );
throw INI_INVALID_NAME_LIST;
}
diff --git a/Core/GameEngine/Source/Common/OptionPreferences.cpp b/Core/GameEngine/Source/Common/OptionPreferences.cpp
new file mode 100644
index 00000000000..7db1b7f53d3
--- /dev/null
+++ b/Core/GameEngine/Source/Common/OptionPreferences.cpp
@@ -0,0 +1,839 @@
+/*
+** Command & Conquer Generals Zero Hour(tm)
+** Copyright 2025 Electronic Arts Inc.
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+// //
+// (c) 2001-2003 Electronic Arts Inc. //
+// //
+////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////////
+// FILE: OptionPreferences.cpp
+// Author: Matthew D. Campbell, April 2002
+// Description: Saving/Loading of option preferences
+///////////////////////////////////////////////////////////////////////////////////////
+
+// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
+#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
+
+#include "Common/AudioSettings.h"
+#include "Common/GameAudio.h"
+#include "Common/GameLOD.h"
+#include "Common/GlobalData.h"
+#include "Common/OptionPreferences.h"
+
+#include "GameClient/ClientInstance.h"
+#include "GameClient/LookAtXlat.h"
+#include "GameClient/Mouse.h"
+
+#include "GameLogic/ScriptEngine.h"
+
+#include "GameNetwork/IPEnumeration.h"
+
+OptionPreferences::OptionPreferences()
+{
+ loadFromIniFile();
+}
+
+OptionPreferences::~OptionPreferences()
+{
+}
+
+Bool OptionPreferences::loadFromIniFile()
+{
+ if (rts::ClientInstance::getInstanceId() > 1u)
+ {
+ AsciiString fname;
+ fname.format("Options_Instance%.2u.ini", rts::ClientInstance::getInstanceId());
+ return load(fname);
+ }
+
+ return load("Options.ini");
+}
+
+Int OptionPreferences::getCampaignDifficulty(void)
+{
+ OptionPreferences::const_iterator it = find("CampaignDifficulty");
+ if (it == end())
+ return TheScriptEngine->getGlobalDifficulty();
+
+ Int factor = atoi(it->second.str());
+ if (factor < DIFFICULTY_EASY)
+ factor = DIFFICULTY_EASY;
+ if (factor > DIFFICULTY_HARD)
+ factor = DIFFICULTY_HARD;
+
+ return factor;
+}
+
+void OptionPreferences::setCampaignDifficulty(Int diff)
+{
+ AsciiString prefString;
+ prefString.format("%d", diff);
+ (*this)["CampaignDifficulty"] = prefString;
+}
+
+UnsignedInt OptionPreferences::getLANIPAddress(void)
+{
+ AsciiString selectedIP = (*this)["IPAddress"];
+ IPEnumeration IPs;
+ EnumeratedIP *IPlist = IPs.getAddresses();
+ while (IPlist)
+ {
+ if (selectedIP.compareNoCase(IPlist->getIPstring()) == 0)
+ {
+ return IPlist->getIP();
+ }
+ IPlist = IPlist->getNext();
+ }
+ return TheGlobalData->m_defaultIP;
+}
+
+void OptionPreferences::setLANIPAddress(AsciiString IP)
+{
+ (*this)["IPAddress"] = IP;
+}
+
+void OptionPreferences::setLANIPAddress(UnsignedInt IP)
+{
+ AsciiString tmp;
+ tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP));
+ (*this)["IPAddress"] = tmp;
+}
+
+UnsignedInt OptionPreferences::getOnlineIPAddress(void)
+{
+ AsciiString selectedIP = (*this)["GameSpyIPAddress"];
+ IPEnumeration IPs;
+ EnumeratedIP *IPlist = IPs.getAddresses();
+ while (IPlist)
+ {
+ if (selectedIP.compareNoCase(IPlist->getIPstring()) == 0)
+ {
+ return IPlist->getIP();
+ }
+ IPlist = IPlist->getNext();
+ }
+ return TheGlobalData->m_defaultIP;
+}
+
+void OptionPreferences::setOnlineIPAddress(AsciiString IP)
+{
+ (*this)["GameSpyIPAddress"] = IP;
+}
+
+void OptionPreferences::setOnlineIPAddress(UnsignedInt IP)
+{
+ AsciiString tmp;
+ tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP));
+ (*this)["GameSpyIPAddress"] = tmp;
+}
+
+Bool OptionPreferences::getArchiveReplaysEnabled() const
+{
+ OptionPreferences::const_iterator it = find("ArchiveReplays");
+ if (it == end())
+ return FALSE;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getAlternateMouseModeEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("UseAlternateMouse");
+ if (it == end())
+ return TheGlobalData->m_useAlternateMouse;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getRetaliationModeEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("Retaliation");
+ if (it == end())
+ return TheGlobalData->m_clientRetaliationModeEnabled;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getDoubleClickAttackMoveEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("UseDoubleClickAttackMove");
+ if( it == end() )
+ return TheGlobalData->m_doubleClickAttackMove;
+
+ if( stricmp( it->second.str(), "yes" ) == 0 )
+ return TRUE;
+
+ return FALSE;
+}
+
+Real OptionPreferences::getScrollFactor(void)
+{
+ OptionPreferences::const_iterator it = find("ScrollFactor");
+ if (it == end())
+ return TheGlobalData->m_keyboardDefaultScrollFactor;
+
+ Int factor = atoi(it->second.str());
+
+ // TheSuperHackers @tweak xezon 11/07/2025
+ // No longer caps the upper limit to 100, because the options setting can go beyond that.
+ // No longer caps the lower limit to 0, because that would mean standstill.
+ if (factor < 1)
+ factor = 1;
+
+ return factor/100.0f;
+}
+
+Bool OptionPreferences::getDrawScrollAnchor(void)
+{
+ OptionPreferences::const_iterator it = find("DrawScrollAnchor");
+ // TheSuperHackers @info this default is based on the same variable within InGameUi.ini
+ if (it == end())
+ return FALSE;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getMoveScrollAnchor(void)
+{
+ OptionPreferences::const_iterator it = find("MoveScrollAnchor");
+ // TheSuperHackers @info this default is based on the same variable within InGameUi.ini
+ if (it == end())
+ return TRUE;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getCursorCaptureEnabledInWindowedGame() const
+{
+ OptionPreferences::const_iterator it = find("CursorCaptureEnabledInWindowedGame");
+ if (it == end())
+ return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInWindowedGame) != 0;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+Bool OptionPreferences::getCursorCaptureEnabledInWindowedMenu() const
+{
+ OptionPreferences::const_iterator it = find("CursorCaptureEnabledInWindowedMenu");
+ if (it == end())
+ return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInWindowedMenu) != 0;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+Bool OptionPreferences::getCursorCaptureEnabledInFullscreenGame() const
+{
+ OptionPreferences::const_iterator it = find("CursorCaptureEnabledInFullscreenGame");
+ if (it == end())
+ return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInFullscreenGame) != 0;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+Bool OptionPreferences::getCursorCaptureEnabledInFullscreenMenu() const
+{
+ OptionPreferences::const_iterator it = find("CursorCaptureEnabledInFullscreenMenu");
+ if (it == end())
+ return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInFullscreenMenu) != 0;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+CursorCaptureMode OptionPreferences::getCursorCaptureMode() const
+{
+ CursorCaptureMode mode = 0;
+ mode |= getCursorCaptureEnabledInWindowedGame() ? CursorCaptureMode_EnabledInWindowedGame : 0;
+ mode |= getCursorCaptureEnabledInWindowedMenu() ? CursorCaptureMode_EnabledInWindowedMenu : 0;
+ mode |= getCursorCaptureEnabledInFullscreenGame() ? CursorCaptureMode_EnabledInFullscreenGame : 0;
+ mode |= getCursorCaptureEnabledInFullscreenMenu() ? CursorCaptureMode_EnabledInFullscreenMenu : 0;
+ return mode;
+}
+
+Bool OptionPreferences::getScreenEdgeScrollEnabledInWindowedApp() const
+{
+ OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInWindowedApp");
+ if (it == end())
+ return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp) != 0;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+Bool OptionPreferences::getScreenEdgeScrollEnabledInFullscreenApp() const
+{
+ OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInFullscreenApp");
+ if (it == end())
+ return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp) != 0;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+ScreenEdgeScrollMode OptionPreferences::getScreenEdgeScrollMode() const
+{
+ ScreenEdgeScrollMode mode = 0;
+ mode |= getScreenEdgeScrollEnabledInWindowedApp() ? ScreenEdgeScrollMode_EnabledInWindowedApp : 0;
+ mode |= getScreenEdgeScrollEnabledInFullscreenApp() ? ScreenEdgeScrollMode_EnabledInFullscreenApp : 0;
+ return mode;
+}
+
+Bool OptionPreferences::usesSystemMapDir(void)
+{
+ OptionPreferences::const_iterator it = find("UseSystemMapDir");
+ if (it == end())
+ return TRUE;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::saveCameraInReplays(void)
+{
+ OptionPreferences::const_iterator it = find("SaveCameraInReplays");
+ if (it == end())
+ return TRUE;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::useCameraInReplays(void)
+{
+ OptionPreferences::const_iterator it = find("UseCameraInReplays");
+ if (it == end())
+ return TRUE;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getPlayerObserverEnabled() const
+{
+ OptionPreferences::const_iterator it = find("PlayerObserverEnabled");
+ if (it == end())
+ return TRUE;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+Int OptionPreferences::getIdealStaticGameDetail(void)
+{
+ OptionPreferences::const_iterator it = find("IdealStaticGameLOD");
+ if (it == end())
+ return STATIC_GAME_LOD_UNKNOWN;
+
+ return TheGameLODManager->getStaticGameLODIndex(it->second);
+}
+
+Int OptionPreferences::getStaticGameDetail(void)
+{
+ OptionPreferences::const_iterator it = find("StaticGameLOD");
+ if (it == end())
+ return TheGameLODManager->getStaticLODLevel();
+
+ return TheGameLODManager->getStaticGameLODIndex(it->second);
+}
+
+Bool OptionPreferences::getSendDelay(void)
+{
+ OptionPreferences::const_iterator it = find("SendDelay");
+ if (it == end())
+ return TheGlobalData->m_firewallSendDelay;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Int OptionPreferences::getFirewallBehavior()
+{
+ OptionPreferences::const_iterator it = find("FirewallBehavior");
+ if (it == end())
+ return TheGlobalData->m_firewallBehavior;
+
+ Int behavior = atoi(it->second.str());
+ if (behavior < 0)
+ {
+ behavior = 0;
+ }
+ return behavior;
+}
+
+Short OptionPreferences::getFirewallPortAllocationDelta()
+{
+ OptionPreferences::const_iterator it = find("FirewallPortAllocationDelta");
+ if (it == end()) {
+ return TheGlobalData->m_firewallPortAllocationDelta;
+ }
+
+ Short delta = atoi(it->second.str());
+ return delta;
+}
+
+UnsignedShort OptionPreferences::getFirewallPortOverride()
+{
+ OptionPreferences::const_iterator it = find("FirewallPortOverride");
+ if (it == end()) {
+ return TheGlobalData->m_firewallPortOverride;
+ }
+
+ Int override = atoi(it->second.str());
+ if (override < 0 || override > 65535)
+ override = 0;
+ return override;
+}
+
+Bool OptionPreferences::getFirewallNeedToRefresh()
+{
+ OptionPreferences::const_iterator it = find("FirewallNeedToRefresh");
+ if (it == end()) {
+ return FALSE;
+ }
+
+ Bool retval = FALSE;
+ AsciiString str = it->second;
+ if (str.compareNoCase("TRUE") == 0) {
+ retval = TRUE;
+ }
+ return retval;
+}
+
+AsciiString OptionPreferences::getPreferred3DProvider(void)
+{
+ OptionPreferences::const_iterator it = find("3DAudioProvider");
+ if (it == end())
+ return TheAudio->getAudioSettings()->m_preferred3DProvider[MAX_HW_PROVIDERS];
+ return it->second;
+}
+
+AsciiString OptionPreferences::getSpeakerType(void)
+{
+ OptionPreferences::const_iterator it = find("SpeakerType");
+ if (it == end())
+ return TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getAudioSettings()->m_defaultSpeakerType2D);
+ return it->second;
+}
+
+Real OptionPreferences::getSoundVolume(void)
+{
+ OptionPreferences::const_iterator it = find("SFXVolume");
+ if (it == end())
+ {
+ Real relative = TheAudio->getAudioSettings()->m_relative2DVolume;
+ if( relative < 0 )
+ {
+ Real scale = 1.0f + relative;
+ return TheAudio->getAudioSettings()->m_defaultSoundVolume * 100.0f * scale;
+ }
+ return TheAudio->getAudioSettings()->m_defaultSoundVolume * 100.0f;
+ }
+
+ Real volume = (Real) atof(it->second.str());
+ if (volume < 0.0f)
+ {
+ volume = 0.0f;
+ }
+ return volume;
+}
+
+Real OptionPreferences::get3DSoundVolume(void)
+{
+ OptionPreferences::const_iterator it = find("SFX3DVolume");
+ if (it == end())
+ {
+ Real relative = TheAudio->getAudioSettings()->m_relative2DVolume;
+ if( relative > 0 )
+ {
+ Real scale = 1.0f - relative;
+ return TheAudio->getAudioSettings()->m_default3DSoundVolume * 100.0f * scale;
+ }
+ return TheAudio->getAudioSettings()->m_default3DSoundVolume * 100.0f;
+ }
+
+ Real volume = (Real) atof(it->second.str());
+ if (volume < 0.0f)
+ {
+ volume = 0.0f;
+ }
+ return volume;
+}
+
+Real OptionPreferences::getSpeechVolume(void)
+{
+ OptionPreferences::const_iterator it = find("VoiceVolume");
+ if (it == end())
+ return TheAudio->getAudioSettings()->m_defaultSpeechVolume * 100.0f;
+
+ Real volume = (Real) atof(it->second.str());
+ if (volume < 0.0f)
+ {
+ volume = 0.0f;
+ }
+ return volume;
+}
+
+Bool OptionPreferences::getCloudShadowsEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("UseCloudMap");
+ if (it == end())
+ return TheGlobalData->m_useCloudMap;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getLightmapEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("UseLightMap");
+ if (it == end())
+ return TheGlobalData->m_useLightMap;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getSmoothWaterEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("ShowSoftWaterEdge");
+ if (it == end())
+ return TheGlobalData->m_showSoftWaterEdge;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getTreesEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("ShowTrees");
+ if (it == end())
+ return TheGlobalData->m_useTrees;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getExtraAnimationsDisabled(void)
+{
+ OptionPreferences::const_iterator it = find("ExtraAnimations");
+ if (it == end())
+ return TheGlobalData->m_useDrawModuleLOD;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return FALSE; //we are enabling extra animations, so disabled LOD
+ }
+ return TRUE;
+}
+
+Bool OptionPreferences::getUseHeatEffects(void)
+{
+ OptionPreferences::const_iterator it = find("HeatEffects");
+ if (it == end())
+ return TheGlobalData->m_useHeatEffects;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getDynamicLODEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("DynamicLOD");
+ if (it == end())
+ return TheGlobalData->m_enableDynamicLOD;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getFPSLimitEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("FPSLimit");
+ if (it == end())
+ return TheGlobalData->m_useFpsLimit;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::get3DShadowsEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("UseShadowVolumes");
+ if (it == end())
+ return TheGlobalData->m_useShadowVolumes;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::get2DShadowsEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("UseShadowDecals");
+ if (it == end())
+ return TheGlobalData->m_useShadowDecals;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Bool OptionPreferences::getBuildingOcclusionEnabled(void)
+{
+ OptionPreferences::const_iterator it = find("BuildingOcclusion");
+ if (it == end())
+ return TheGlobalData->m_enableBehindBuildingMarkers;
+
+ if (stricmp(it->second.str(), "yes") == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+Int OptionPreferences::getParticleCap(void)
+{
+ OptionPreferences::const_iterator it = find("MaxParticleCount");
+ if (it == end())
+ return TheGlobalData->m_maxParticleCount;
+
+ Int factor = (Int) atoi(it->second.str());
+ if (factor < 100) //clamp to at least 100 particles.
+ factor = 100;
+
+ return factor;
+}
+
+Int OptionPreferences::getTextureReduction(void)
+{
+ OptionPreferences::const_iterator it = find("TextureReduction");
+ if (it == end())
+ return -1; //unknown texture reduction
+
+ Int factor = (Int) atoi(it->second.str());
+ if (factor > 2) //clamp it.
+ factor=2;
+ return factor;
+}
+
+Real OptionPreferences::getGammaValue(void)
+{
+ OptionPreferences::const_iterator it = find("Gamma");
+ if (it == end())
+ return 50.0f;
+
+ Real gamma = (Real) atoi(it->second.str());
+ return gamma;
+}
+
+void OptionPreferences::getResolution(Int *xres, Int *yres)
+{
+ *xres = TheGlobalData->m_xResolution;
+ *yres = TheGlobalData->m_yResolution;
+
+ OptionPreferences::const_iterator it = find("Resolution");
+ if (it == end())
+ return;
+
+ Int selectedXRes,selectedYRes;
+ if (sscanf(it->second.str(),"%d%d", &selectedXRes, &selectedYRes) != 2)
+ return;
+
+ *xres=selectedXRes;
+ *yres=selectedYRes;
+}
+
+Real OptionPreferences::getMusicVolume(void)
+{
+ OptionPreferences::const_iterator it = find("MusicVolume");
+ if (it == end())
+ return TheAudio->getAudioSettings()->m_defaultMusicVolume * 100.0f;
+
+ Real volume = (Real) atof(it->second.str());
+ if (volume < 0.0f)
+ {
+ volume = 0.0f;
+ }
+ return volume;
+}
+
+Real OptionPreferences::getMoneyTransactionVolume(void) const
+{
+ OptionPreferences::const_iterator it = find("MoneyTransactionVolume");
+ if (it == end())
+ return TheAudio->getAudioSettings()->m_defaultMoneyTransactionVolume * 100.0f;
+
+ Real volume = (Real) atof(it->second.str());
+ if (volume < 0.0f)
+ volume = 0.0f;
+
+ return volume;
+}
+
+Int OptionPreferences::getNetworkLatencyFontSize(void)
+{
+ OptionPreferences::const_iterator it = find("NetworkLatencyFontSize");
+ if (it == end())
+ return 8;
+
+ Int fontSize = atoi(it->second.str());
+ if (fontSize < 0)
+ {
+ fontSize = 0;
+ }
+ return fontSize;
+}
+
+Int OptionPreferences::getRenderFpsFontSize(void)
+{
+ OptionPreferences::const_iterator it = find("RenderFpsFontSize");
+ if (it == end())
+ return 8;
+
+ Int fontSize = atoi(it->second.str());
+ if (fontSize < 0)
+ {
+ fontSize = 0;
+ }
+ return fontSize;
+}
+
+Int OptionPreferences::getSystemTimeFontSize(void)
+{
+ OptionPreferences::const_iterator it = find("SystemTimeFontSize");
+ if (it == end())
+ return 8;
+
+ Int fontSize = atoi(it->second.str());
+ if (fontSize < 0)
+ {
+ fontSize = 0;
+ }
+ return fontSize;
+}
+
+Int OptionPreferences::getGameTimeFontSize(void)
+{
+ OptionPreferences::const_iterator it = find("GameTimeFontSize");
+ if (it == end())
+ return 8;
+
+ Int fontSize = atoi(it->second.str());
+ if (fontSize < 0)
+ {
+ fontSize = 0;
+ }
+ return fontSize;
+}
+
+Int OptionPreferences::getPlayerInfoListFontSize(void)
+{
+ OptionPreferences::const_iterator it = find("PlayerInfoListFontSize");
+ if (it == end())
+ return 8;
+
+ Int fontSize = atoi(it->second.str());
+ if (fontSize < 0)
+ {
+ fontSize = 0;
+ }
+ return fontSize;
+}
+
+Real OptionPreferences::getResolutionFontAdjustment(void)
+{
+ OptionPreferences::const_iterator it = find("ResolutionFontAdjustment");
+ if (it == end())
+ return -1.0f;
+
+ Real fontScale = (Real)atof(it->second.str()) / 100.0f;
+ if (fontScale < 0.0f)
+ {
+ fontScale = -1.0f;
+ }
+ return fontScale;
+}
+
+Bool OptionPreferences::getShowMoneyPerMinute(void) const
+{
+ OptionPreferences::const_iterator it = find("ShowMoneyPerMinute");
+ if (it == end())
+ return TheGlobalData->m_showMoneyPerMinute;
+
+ if (stricmp(it->second.str(), "yes") == 0)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/Core/GameEngine/Source/Common/System/Radar.cpp b/Core/GameEngine/Source/Common/System/Radar.cpp
index 4b482a2c188..f69ebaa9ee5 100644
--- a/Core/GameEngine/Source/Common/System/Radar.cpp
+++ b/Core/GameEngine/Source/Common/System/Radar.cpp
@@ -81,7 +81,6 @@ void Radar::deleteListResources( void )
{
deleteList(&m_objectList);
deleteList(&m_localObjectList);
- deleteList(&m_localHeroObjectList);
#ifdef DEBUG_CRASHING
for( Object *obj = TheGameLogic->getFirstObject(); obj; obj = obj->getNextObject() )
@@ -115,14 +114,8 @@ RadarObject::~RadarObject( void )
//-------------------------------------------------------------------------------------------------
Bool RadarObject::isTemporarilyHidden() const
{
- return isTemporarilyHidden(m_object);
-}
+ Drawable* draw = m_object->getDrawable();
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Bool RadarObject::isTemporarilyHidden(const Object* obj)
-{
- Drawable* draw = obj->getDrawable();
if (draw == nullptr || draw->getStealthLook() == STEALTHLOOK_INVISIBLE || draw->isDrawableEffectivelyHidden())
return true;
@@ -192,7 +185,6 @@ Radar::Radar( void )
m_radarWindow = nullptr;
m_objectList = nullptr;
m_localObjectList = nullptr;
- m_localHeroObjectList = nullptr;
std::fill(m_radarHidden, m_radarHidden + ARRAY_SIZE(m_radarHidden), false);
std::fill(m_radarForceOn, m_radarForceOn + ARRAY_SIZE(m_radarForceOn), false);
m_terrainAverageZ = 0.0f;
@@ -416,10 +408,7 @@ Bool Radar::addObject( Object *obj )
//
if( obj->isLocallyControlled() )
{
- if ( obj->isHero() )
- list = &m_localHeroObjectList;
- else
- list = &m_localObjectList;
+ list = &m_localObjectList;
}
else
{
@@ -483,15 +472,13 @@ Bool Radar::removeObject( Object *obj )
if( obj->friend_getRadarData() == nullptr )
return FALSE;
- if( deleteFromList( obj, &m_localHeroObjectList ) == TRUE )
- return TRUE;
if( deleteFromList( obj, &m_localObjectList ) == TRUE )
return TRUE;
else if( deleteFromList( obj, &m_objectList ) == TRUE )
return TRUE;
else
{
- DEBUG_ASSERTCRASH( 0, ("Radar: Tried to remove object '%s' which was not found",
+ DEBUG_CRASH( ("Radar: Tried to remove object '%s' which was not found",
obj->getTemplate()->getName().str()) );
return FALSE;
}
@@ -718,14 +705,10 @@ Object *Radar::objectUnderRadarPixel( const ICoord2D *pixel )
// to the radar location
//
- // search the local hero object list
- obj = searchListForRadarLocationMatch( m_localHeroObjectList, &radar );
-
- // search the local object list if not found
- if( obj == nullptr )
- obj = searchListForRadarLocationMatch( m_localObjectList, &radar );
+ // search the local object list
+ obj = searchListForRadarLocationMatch( m_localObjectList, &radar );
- // search all other objects if still not found
+ // search all other objects if not found
if( obj == nullptr )
obj = searchListForRadarLocationMatch( m_objectList, &radar );
@@ -1365,7 +1348,6 @@ static void xferRadarObjectList( Xfer *xfer, RadarObject **head )
* Version Info:
* 1: Initial version
* 2: TheSuperHackers @tweak Serialize m_radarHidden, m_radarForceOn for each player
- * 3: TheSuperHackers @tweak Serialize m_localHeroObjectList
*/
// ------------------------------------------------------------------------------------------------
void Radar::xfer( Xfer *xfer )
@@ -1375,7 +1357,7 @@ void Radar::xfer( Xfer *xfer )
#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 1;
#else
- XferVersion currentVersion = 3;
+ XferVersion currentVersion = 2;
#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
@@ -1405,66 +1387,12 @@ void Radar::xfer( Xfer *xfer )
xfer->xferUser(&m_radarForceOn, sizeof(m_radarForceOn));
}
- if (version <= 2)
- {
- if (xfer->getXferMode() == XFER_SAVE)
- {
- // TheSuperHackers @info For legacy xfer compatibility.
- // Transfer all local hero objects to local object list.
- RadarObject **fromList = &m_localHeroObjectList;
- RadarObject **toList = &m_localObjectList;
- while (*fromList != nullptr)
- {
- RadarObject* nextObject = (*fromList)->friend_getNext();
- (*fromList)->friend_setNext(nullptr);
- linkRadarObject(*fromList, toList);
- *fromList = nextObject;
- }
- }
- }
- else
- {
- xferRadarObjectList( xfer, &m_localHeroObjectList );
- }
-
// save our local object list
xferRadarObjectList( xfer, &m_localObjectList );
// save the regular object list
xferRadarObjectList( xfer, &m_objectList );
- if (version <= 2)
- {
- // TheSuperHackers @info For legacy xfer compatibility.
- // Transfer hero local object(s) back to local hero object list.
- // This needs to be done on both load and save.
- RadarObject **fromList = &m_localObjectList;
- RadarObject **toList = &m_localHeroObjectList;
- RadarObject *currObject;
- RadarObject *prevObject;
- RadarObject *nextObject;
- prevObject = nullptr;
- for (currObject = *fromList; currObject != nullptr; currObject = nextObject)
- {
- nextObject = currObject->friend_getNext();
- if (currObject->friend_getObject()->isHero())
- {
- if (prevObject != nullptr)
- {
- prevObject->friend_setNext(nextObject);
- }
- else
- {
- *fromList = nextObject;
- }
- currObject->friend_setNext(nullptr);
- linkRadarObject(currObject, toList);
- continue;
- }
- prevObject = currObject;
- }
- }
-
// save the radar event count and data
UnsignedShort eventCountVerify = MAX_RADAR_EVENTS;
UnsignedShort eventCount = eventCountVerify;
diff --git a/Generals/Code/GameEngine/Source/GameClient/ClientInstance.cpp b/Core/GameEngine/Source/GameClient/ClientInstance.cpp
similarity index 100%
rename from Generals/Code/GameEngine/Source/GameClient/ClientInstance.cpp
rename to Core/GameEngine/Source/GameClient/ClientInstance.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/Color.cpp b/Core/GameEngine/Source/GameClient/Color.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/Color.cpp
rename to Core/GameEngine/Source/GameClient/Color.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/Credits.cpp b/Core/GameEngine/Source/GameClient/Credits.cpp
similarity index 99%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/Credits.cpp
rename to Core/GameEngine/Source/GameClient/Credits.cpp
index fc23c65eac8..f732f0a546f 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/Credits.cpp
+++ b/Core/GameEngine/Source/GameClient/Credits.cpp
@@ -460,7 +460,7 @@ void CreditsManager::addText( AsciiString text )
}
break;
default:
- DEBUG_ASSERTCRASH( FALSE, ("CreditsManager::addText we tried to add a credit text with the wrong style before it. Style is %d", m_currentStyle) );
+ DEBUG_CRASH( ("CreditsManager::addText we tried to add a credit text with the wrong style before it. Style is %d", m_currentStyle) );
delete cLine;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/DisplayString.cpp b/Core/GameEngine/Source/GameClient/DisplayString.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/DisplayString.cpp
rename to Core/GameEngine/Source/GameClient/DisplayString.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/DisplayStringManager.cpp b/Core/GameEngine/Source/GameClient/DisplayStringManager.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/DisplayStringManager.cpp
rename to Core/GameEngine/Source/GameClient/DisplayStringManager.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp b/Core/GameEngine/Source/GameClient/DrawGroupInfo.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp
rename to Core/GameEngine/Source/GameClient/DrawGroupInfo.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/FXList.cpp b/Core/GameEngine/Source/GameClient/FXList.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/FXList.cpp
rename to Core/GameEngine/Source/GameClient/FXList.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp b/Core/GameEngine/Source/GameClient/GUI/GameFont.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp
rename to Core/GameEngine/Source/GameClient/GUI/GameFont.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindow.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp
rename to Core/GameEngine/Source/GameClient/GUI/GameWindow.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp
rename to Core/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
similarity index 98%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
rename to Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
index fc99b16ba8b..cd2205a44a2 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
+++ b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
@@ -135,7 +135,7 @@ Transition *getTransitionForStyle( Int style )
return NEW ScoreScaleUpTransition;
default:
- DEBUG_ASSERTCRASH(FALSE, ("getTransitionForStyle:: An invalid style was passed in. Style = %d", style));
+ DEBUG_CRASH(("getTransitionForStyle:: An invalid style was passed in. Style = %d", style));
return nullptr;
}
return nullptr;
@@ -532,7 +532,7 @@ TransitionGroup *GameWindowTransitionsHandler::getNewGroup( AsciiString name )
// test to see if we're trying to add an already existing group.
if(findGroup(name))
{
- DEBUG_ASSERTCRASH(FALSE, ("GameWindowTransitionsHandler::getNewGroup - We already have a group %s", name.str()));
+ DEBUG_CRASH(("GameWindowTransitionsHandler::getNewGroup - We already have a group %s", name.str()));
return nullptr;
}
TransitionGroup *g = NEW TransitionGroup;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp b/Core/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp
rename to Core/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp b/Core/GameEngine/Source/GameClient/GUI/IMEManager.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp
rename to Core/GameEngine/Source/GameClient/GUI/IMEManager.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp b/Core/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
similarity index 95%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
rename to Core/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
index f0234729cb5..e646b216c26 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
+++ b/Core/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
@@ -150,11 +150,8 @@ LoadScreen::LoadScreen( void )
LoadScreen::~LoadScreen( void )
{
- //if(m_loadScreen)
- // delete (m_loadScreen);
if(m_loadScreen)
TheWindowManager->winDestroy( m_loadScreen );
- m_loadScreen = nullptr;
}
void LoadScreen::update( Int percent )
@@ -192,24 +189,14 @@ SinglePlayerLoadScreen::SinglePlayerLoadScreen( void )
SinglePlayerLoadScreen::~SinglePlayerLoadScreen( void )
{
- m_progressBar = nullptr;
- m_percent = nullptr;
- m_objectiveWin = nullptr;
- for(Int i = 0; i < MAX_OBJECTIVE_LINES; ++i)
- m_objectiveLines[i] = nullptr;
-
delete m_videoBuffer;
- m_videoBuffer = nullptr;
if ( m_videoStream )
{
m_videoStream->close();
- m_videoStream = nullptr;
}
TheAudio->removeAudioEvent( m_ambientLoopHandle );
- m_ambientLoopHandle = 0;
-
}
void SinglePlayerLoadScreen::moveWindows( Int frame )
@@ -509,18 +496,36 @@ void SinglePlayerLoadScreen::init( GameInfo *game )
GameWindow *backgroundWin = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:ParentSinglePlayerLoadScreen" ));
if (campaignName.compareNoCase("USA") == 0)
{
- backgroundWin->winSetEnabledImage( 0, TheMappedImageCollection->findImageByName("MissionLoad_USA") );
- m_progressBar->winSetEnabledImage( 6, TheMappedImageCollection->findImageByName("LoadingBar_ProgressCenter2") );
+ if (const Image *image = TheMappedImageCollection->findImageByName("MissionLoad_USA"))
+ {
+ backgroundWin->winSetEnabledImage( 0, image);
+ }
+ if (const Image *image = TheMappedImageCollection->findImageByName("LoadingBar_ProgressCenter2"))
+ {
+ m_progressBar->winSetEnabledImage( 6, image );
+ }
}
else if (campaignName.compareNoCase("GLA") == 0)
{
- backgroundWin->winSetEnabledImage( 0, TheMappedImageCollection->findImageByName("MissionLoad_GLA") );
- m_progressBar->winSetEnabledImage( 6, TheMappedImageCollection->findImageByName("LoadingBar_ProgressCenter3") );
+ if (const Image *image = TheMappedImageCollection->findImageByName("MissionLoad_GLA"))
+ {
+ backgroundWin->winSetEnabledImage( 0, image );
+ }
+ if (const Image *image = TheMappedImageCollection->findImageByName("LoadingBar_ProgressCenter3"))
+ {
+ m_progressBar->winSetEnabledImage( 6, image );
+ }
}
else if (campaignName.compareNoCase("China") == 0)
{
- backgroundWin->winSetEnabledImage( 0, TheMappedImageCollection->findImageByName("MissionLoad_China") );
- m_progressBar->winSetEnabledImage( 6, TheMappedImageCollection->findImageByName("LoadingBar_ProgressCenter1") );
+ if (const Image *image = TheMappedImageCollection->findImageByName("MissionLoad_China"))
+ {
+ backgroundWin->winSetEnabledImage( 0, image );
+ }
+ if (const Image *image = TheMappedImageCollection->findImageByName("LoadingBar_ProgressCenter1"))
+ {
+ m_progressBar->winSetEnabledImage( 6, image );
+ }
}
// else leave the default background screen
@@ -557,8 +562,9 @@ void SinglePlayerLoadScreen::init( GameInfo *game )
m_videoStream->frameDecompress();
m_videoStream->frameRender(m_videoBuffer);
-// PULLED FROM THE MISSION DISK
-// moveWindows( m_videoStream->frameIndex());
+#if RTS_GENERALS
+ moveWindows( m_videoStream->frameIndex());
+#endif
m_videoStream->frameNext();
@@ -583,15 +589,41 @@ void SinglePlayerLoadScreen::init( GameInfo *game )
TheDisplay->draw();
}
+#if !RTS_GENERALS
// let the background image show through
m_videoStream->close();
m_videoStream = nullptr;
m_loadScreen->winGetInstanceData()->setVideoBuffer( nullptr );
TheDisplay->draw();
+#endif
}
else
{
+#if RTS_GENERALS
+ // if we're min speced
+ m_videoStream->frameGoto(m_videoStream->frameCount()); // zero based
+ while(!m_videoStream->isFrameReady())
+ Sleep(1);
+ m_videoStream->frameDecompress();
+ m_videoStream->frameRender(m_videoBuffer);
+ if(m_videoBuffer)
+ m_loadScreen->winGetInstanceData()->setVideoBuffer(m_videoBuffer);
+
+ m_objectiveWin->winHide(FALSE);
+ for(i = 0; i < MAX_DISPLAYED_UNITS; ++i)
+ m_unitDesc[i]->winHide(FALSE);
+ m_location->winHide(FALSE);
+
+ // Audio was choppy so, I chopped it out!
+ TheAudio->friend_forcePlayAudioEventRTS(&TheCampaignManager->getCurrentMission()->m_briefingVoice);
+
+ for(Int i = 0; i < MAX_OBJECTIVE_LINES; ++i)
+ {
+ GadgetStaticTextSetText(m_objectiveLines[i], m_unicodeObjectiveLines[i]);
+ }
+#else
// if we're min spec'ed don't play a movie
+#endif
Int delay = mission->m_voiceLength * 1000;
Int begin = timeGetTime();
@@ -687,54 +719,16 @@ ChallengeLoadScreen::ChallengeLoadScreen( void )
ChallengeLoadScreen::~ChallengeLoadScreen( void )
{
- m_progressBar = nullptr;
-
delete m_videoBuffer;
- m_videoBuffer = nullptr;
if ( m_videoStream )
{
m_videoStream->close();
- m_videoStream = nullptr;
}
- m_bioNameLeft = nullptr;
- m_bioAgeLeft = nullptr;
- m_bioBirthplaceLeft = nullptr;
- m_bioStrategyLeft = nullptr;
- m_bioBigNameEntryLeft = nullptr;
- m_bioNameEntryLeft = nullptr;
- m_bioAgeEntryLeft = nullptr;
- m_bioBirthplaceEntryLeft = nullptr;
- m_bioStrategyEntryLeft = nullptr;
- m_bioBigNameEntryRight = nullptr;
- m_bioNameRight = nullptr;
- m_bioAgeRight = nullptr;
- m_bioBirthplaceRight = nullptr;
- m_bioStrategyRight = nullptr;
- m_bioNameEntryRight = nullptr;
- m_bioAgeEntryRight = nullptr;
- m_bioBirthplaceEntryRight = nullptr;
- m_bioStrategyEntryRight = nullptr;
-
- m_portraitLeft = nullptr;
- m_portraitRight = nullptr;
- m_portraitMovieLeft = nullptr;
- m_portraitMovieRight = nullptr;
-
-// m_overlayReticleCrosshairs = nullptr;
-// m_overlayReticleCircleLineOuter = nullptr;
-// m_overlayReticleCircleLineInner = nullptr;
- m_overlayReticleCircleAlphaOuter = nullptr;
- m_overlayReticleCircleAlphaInner = nullptr;
- m_overlayVsBackdrop = nullptr;
- m_overlayVs = nullptr;
-
delete m_wndVideoManager;
- m_wndVideoManager = nullptr;
TheAudio->removeAudioEvent( m_ambientLoopHandle );
- m_ambientLoopHandle = 0;
}
// accepts the number of chars to advance, the window we're concerned with, the total text for final display, and the current position of the readout
@@ -1184,8 +1178,6 @@ ShellGameLoadScreen::ShellGameLoadScreen( void )
ShellGameLoadScreen::~ShellGameLoadScreen( void )
{
-
- m_progressBar = nullptr;
}
void ShellGameLoadScreen::init( GameInfo *game )
@@ -1238,6 +1230,9 @@ void ShellGameLoadScreen::update( Int percent )
MultiPlayerLoadScreen::MultiPlayerLoadScreen( void )
{
m_mapPreview = nullptr;
+ m_portraitLocalGeneral = nullptr;
+ m_featuresLocalGeneral = nullptr;
+ m_nameLocalGeneral = nullptr;
for(Int i = 0; i < MAX_SLOTS; ++i)
{
@@ -1256,18 +1251,6 @@ MultiPlayerLoadScreen::~MultiPlayerLoadScreen( void )
m_mapPreview->winSetUserData(nullptr);
}
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- m_playerLookup[i] = -1;
- }
-
- m_portraitLocalGeneral = nullptr;
- m_featuresLocalGeneral = nullptr;
- m_nameLocalGeneral = nullptr;
-
TheAudio->removeAudioEvent( AHSV_StopTheMusicFade );
// TheAudio->stopAudio( AudioAffect_Music );
}
@@ -1286,8 +1269,12 @@ void MultiPlayerLoadScreen::init( GameInfo *game )
pt = ThePlayerTemplateStore->getNthPlayerTemplate(lSlot->getPlayerTemplate());
else
pt = ThePlayerTemplateStore->findPlayerTemplate( TheNameKeyGenerator->nameToKey("FactionObserver") );
-// const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen());
+#if RTS_GENERALS
+ const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen());
+ if(loadScreenImage)
+ m_loadScreen->winSetEnabledImage(0, loadScreenImage);
+#else
// add portrait, features, and name for the local player's general
const GeneralPersona *localGeneral = TheChallengeGenerals->getGeneralByTemplateName( pt->getName() );
const Image *portrait = nullptr;
@@ -1319,6 +1306,7 @@ void MultiPlayerLoadScreen::init( GameInfo *game )
GadgetStaticTextSetText( m_featuresLocalGeneral, TheGameText->fetch( features.isEmpty() ? "GUI:PlayerObserver" : pt->getGeneralFeatures() ) );
m_nameLocalGeneral = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "MultiplayerLoadScreen.wnd:LocalGeneralName"));
GadgetStaticTextSetText( m_nameLocalGeneral, localName );
+#endif
AsciiString musicName = pt->getLoadScreenMusic();
if ( ! musicName.isEmpty() )
@@ -1332,9 +1320,6 @@ void MultiPlayerLoadScreen::init( GameInfo *game )
}
-
-// if(loadScreenImage)
-// m_loadScreen->winSetEnabledImage(0, loadScreenImage);
//DEBUG_ASSERTCRASH(TheNetwork, ("Where the Heck is the Network!!!!"));
//DEBUG_LOG(("NumPlayers %d", TheNetwork->getNumPlayers()));
@@ -1382,7 +1367,9 @@ void MultiPlayerLoadScreen::init( GameInfo *game )
continue;
Color houseColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor();
-
+#if RTS_GENERALS
+ GadgetProgressBarSetEnabledBarColor(m_progressBars[netSlot],houseColor );
+#else
// format the progress bar to house colors
AsciiString imageName;
imageName.format("LoadingBar_ProgressCenter%d", slot->getApparentColor());
@@ -1390,6 +1377,7 @@ void MultiPlayerLoadScreen::init( GameInfo *game )
if (! houseImage)
houseImage = TheMappedImageCollection->findImageByName("LoadingBar_Progress");
m_progressBars[netSlot]->winSetEnabledImage( 6, houseImage );
+#endif
UnicodeString name = slot->getName();
GadgetStaticTextSetText(m_playerNames[netSlot], name );
@@ -1484,7 +1472,7 @@ void MultiPlayerLoadScreen::processProgress(Int playerId, Int percentage)
if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1)
{
- DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d", percentage, playerId));
+ DEBUG_CRASH(("Percentage %d was passed in for Player %d", percentage, playerId));
return;
}
//DEBUG_LOG(("Percentage %d was passed in for Player %d (in loadscreen position %d)", percentage, playerId, m_playerLookup[playerId]));
@@ -1498,6 +1486,9 @@ GameSpyLoadScreen::GameSpyLoadScreen( void )
{
m_mapPreview = nullptr;
+ m_portraitLocalGeneral = nullptr;
+ m_featuresLocalGeneral = nullptr;
+ m_nameLocalGeneral = nullptr;
for(Int i = 0; i < MAX_SLOTS; ++i)
{
@@ -1523,18 +1514,6 @@ GameSpyLoadScreen::~GameSpyLoadScreen( void )
{
m_mapPreview->winSetUserData(nullptr);
}
-
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- m_playerLookup[i] = -1;
- m_playerFavoriteFactions[i]= nullptr;
- m_playerTotalDisconnects[i]= nullptr;
- m_playerWin[i]= nullptr;
- m_playerWinLosses[i]= nullptr;
- }
}
extern Int GetAdditionalDisconnectsFromUserFile(Int playerID);
@@ -1555,10 +1534,12 @@ GameSlot *lSlot = game->getSlot(game->getLocalSlotNum());
pt = ThePlayerTemplateStore->getNthPlayerTemplate(lSlot->getPlayerTemplate());
else
pt = ThePlayerTemplateStore->findPlayerTemplate( TheNameKeyGenerator->nameToKey("FactionObserver") );
-// const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen());
-// if(loadScreenImage)
-// m_loadScreen->winSetEnabledImage(0, loadScreenImage);
+#if RTS_GENERALS
+ const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen());
+ if(loadScreenImage)
+ m_loadScreen->winSetEnabledImage(0, loadScreenImage);
+#else
// add portrait, features, and name for the local player's general
const GeneralPersona *localGeneral = TheChallengeGenerals->getGeneralByTemplateName( pt->getName() );
const Image *portrait = nullptr;
@@ -1590,6 +1571,7 @@ GameSlot *lSlot = game->getSlot(game->getLocalSlotNum());
GadgetStaticTextSetText( m_featuresLocalGeneral, TheGameText->fetch( features.isEmpty() ? "GUI:PlayerObserver" : pt->getGeneralFeatures() ) );
m_nameLocalGeneral = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "GameSpyLoadScreen.wnd:LocalGeneralName"));
GadgetStaticTextSetText( m_nameLocalGeneral, localName );
+#endif
GameWindow *teamWin[MAX_SLOTS];
Int i = 0;
@@ -1665,7 +1647,9 @@ GameSlot *lSlot = game->getSlot(game->getLocalSlotNum());
continue;
Color houseColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor();
-
+#if RTS_GENERALS
+ GadgetProgressBarSetEnabledBarColor(m_progressBars[netSlot],houseColor );
+#else
// format the progress bar to house colors
AsciiString imageName;
imageName.format("LoadingBar_ProgressCenter%d", slot->getApparentColor());
@@ -1673,6 +1657,7 @@ GameSlot *lSlot = game->getSlot(game->getLocalSlotNum());
if (! houseImage)
houseImage = TheMappedImageCollection->findImageByName("LoadingBar_Progress");
m_progressBars[netSlot]->winSetEnabledImage( 6, houseImage );
+#endif
UnicodeString name = slot->getName();
GadgetStaticTextSetText(m_playerNames[netSlot], name );
@@ -1846,7 +1831,7 @@ void GameSpyLoadScreen::processProgress(Int playerId, Int percentage)
if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1)
{
- DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d", percentage, playerId));
+ DEBUG_CRASH(("Percentage %d was passed in for Player %d", percentage, playerId));
return;
}
//DEBUG_LOG(("Percentage %d was passed in for Player %d (in loadscreen position %d)", percentage, playerId, m_playerLookup[playerId]));
@@ -1873,16 +1858,6 @@ MapTransferLoadScreen::MapTransferLoadScreen( void )
MapTransferLoadScreen::~MapTransferLoadScreen( void )
{
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_progressText[i]= nullptr;
- m_playerLookup[i] = -1;
- m_oldProgress[i] = -1;
- }
- m_fileNameText = nullptr;
- m_timeoutText = nullptr;
}
void MapTransferLoadScreen::init( GameInfo *game )
@@ -1994,7 +1969,7 @@ void MapTransferLoadScreen::processProgress(Int playerId, Int percentage, AsciiS
if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1)
{
- DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d", percentage, playerId));
+ DEBUG_CRASH(("Percentage %d was passed in for Player %d", percentage, playerId));
return;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp b/Core/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp
rename to Core/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp b/Core/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp
rename to Core/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp b/Core/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
rename to Core/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GameText.cpp b/Core/GameEngine/Source/GameClient/GameText.cpp
similarity index 98%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GameText.cpp
rename to Core/GameEngine/Source/GameClient/GameText.cpp
index 97a2c9d5dfa..27f15985361 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GameText.cpp
+++ b/Core/GameEngine/Source/GameClient/GameText.cpp
@@ -266,7 +266,6 @@ GameTextManager::GameTextManager()
m_buffer2[i] = 0;
m_buffer3[i] = 0;
}
- //
}
//============================================================================
@@ -1038,7 +1037,7 @@ Bool GameTextManager::parseStringFile( const char *filename )
{
if ( stricmp ( m_stringInfo[i].label.str(), m_buffer ) == 0)
{
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' multiply defined!", m_buffer ));
+ DEBUG_CRASH ( ("String label '%s' multiply defined!", m_buffer ));
}
}
@@ -1056,7 +1055,7 @@ Bool GameTextManager::parseStringFile( const char *filename )
{
if (!readLine ( m_buffer, sizeof(m_buffer)-1, file ))
{
- DEBUG_ASSERTCRASH (FALSE, ("Unexpected end of string file"));
+ DEBUG_CRASH (("Unexpected end of string file"));
ok = FALSE;
goto quit;
}
@@ -1074,7 +1073,7 @@ Bool GameTextManager::parseStringFile( const char *filename )
if ( readString )
{
// only one string per label allows
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
+ DEBUG_CRASH ( ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
}
else
{
@@ -1169,7 +1168,7 @@ Bool GameTextManager::parseMapStringFile( const char *filename )
{
if ( stricmp ( m_mapStringInfo[i].label.str(), m_buffer ) == 0)
{
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' multiply defined!", m_buffer ));
+ DEBUG_CRASH ( ("String label '%s' multiply defined!", m_buffer ));
}
}
@@ -1187,7 +1186,7 @@ Bool GameTextManager::parseMapStringFile( const char *filename )
{
if (!readLine ( m_buffer, sizeof(m_buffer)-1, file ))
{
- DEBUG_ASSERTCRASH (FALSE, ("Unexpected end of string file"));
+ DEBUG_CRASH (("Unexpected end of string file"));
ok = FALSE;
goto quit;
}
@@ -1205,7 +1204,7 @@ Bool GameTextManager::parseMapStringFile( const char *filename )
if ( readString )
{
// only one string per label allowed
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
+ DEBUG_CRASH ( ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
}
else
{
@@ -1459,4 +1458,3 @@ static int __cdecl compareLUT ( const void *i1, const void*i2)
return stricmp( lut1->label->str(), lut2->label->str());
}
-
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp b/Core/GameEngine/Source/GameClient/GlobalLanguage.cpp
similarity index 89%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp
rename to Core/GameEngine/Source/GameClient/GlobalLanguage.cpp
index 2683c02d7ff..cdff70b6b9f 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp
+++ b/Core/GameEngine/Source/GameClient/GlobalLanguage.cpp
@@ -56,7 +56,7 @@
#include "Common/INI.h"
#include "Common/Registry.h"
#include "Common/FileSystem.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/Display.h"
#include "GameClient/GlobalLanguage.h"
@@ -64,7 +64,7 @@
//-----------------------------------------------------------------------------
// DEFINES ////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
-GlobalLanguage *TheGlobalLanguageData = nullptr; ///< The global language singleton
+GlobalLanguage *TheGlobalLanguageData = nullptr;
static const LookupListRec ResolutionFontSizeMethodNames[] =
{
@@ -116,7 +116,7 @@ void INI::parseLanguageDefinition( INI *ini )
DEBUG_ASSERTCRASH(TheGlobalLanguageData, ("INI::parseLanguageDefinition - TheGlobalLanguage Data is not around, please create it before trying to parse the ini file."));
return;
}
- // parse the ini weapon definition
+
ini->initFromINI( TheGlobalLanguageData, TheGlobalLanguageDataFieldParseTable );
}
@@ -136,7 +136,7 @@ GlobalLanguage::GlobalLanguage()
GlobalLanguage::~GlobalLanguage()
{
- StringListIt it = m_localFonts.begin();
+ StringList::iterator it = m_localFonts.begin();
while( it != m_localFonts.end())
{
AsciiString font = *it;
@@ -146,7 +146,7 @@ GlobalLanguage::~GlobalLanguage()
}
}
-void GlobalLanguage::init( void )
+void GlobalLanguage::init()
{
{
AsciiString fname;
@@ -156,13 +156,13 @@ void GlobalLanguage::init( void )
ini.loadFileDirectory( fname, INI_LOAD_OVERWRITE, nullptr );
}
- StringListIt it = m_localFonts.begin();
+ StringList::iterator it = m_localFonts.begin();
while( it != m_localFonts.end())
{
AsciiString font = *it;
if(AddFontResource(font.str()) == 0)
{
- DEBUG_ASSERTCRASH(FALSE,("GlobalLanguage::init Failed to add font %s", font.str()));
+ DEBUG_CRASH(("GlobalLanguage::init Failed to add font %s", font.str()));
}
else
{
@@ -174,12 +174,13 @@ void GlobalLanguage::init( void )
// override values with user preferences
OptionPreferences optionPref;
m_userResolutionFontSizeAdjustment = optionPref.getResolutionFontAdjustment();
-
}
-void GlobalLanguage::reset( void ) {}
+void GlobalLanguage::reset()
+{
+}
-void GlobalLanguage::parseFontDesc(INI *ini, void *instance, void *store, const void* userData)
+void GlobalLanguage::parseFontDesc(INI *ini, void *instance, void *store, const void *userData)
{
FontDesc *fontDesc = (FontDesc *)store;
fontDesc->name = ini->getNextQuotedAsciiString();
@@ -187,14 +188,14 @@ void GlobalLanguage::parseFontDesc(INI *ini, void *instance, void *store, const
fontDesc->bold = ini->scanBool(ini->getNextToken());
}
-void GlobalLanguage::parseFontFileName( INI *ini, void * instance, void *store, const void* userData )
+void GlobalLanguage::parseFontFileName(INI *ini, void *instance, void *store, const void *userData)
{
- GlobalLanguage *monkey = (GlobalLanguage *)instance;
+ GlobalLanguage *globalLanguage = static_cast(instance);
AsciiString asciiString = ini->getNextAsciiString();
- monkey->m_localFonts.push_front(asciiString);
+ globalLanguage->m_localFonts.push_front(asciiString);
}
-float GlobalLanguage::getResolutionFontSizeAdjustment( void ) const
+Real GlobalLanguage::getResolutionFontSizeAdjustment() const
{
if (m_userResolutionFontSizeAdjustment >= 0.0f)
return m_userResolutionFontSizeAdjustment;
@@ -202,13 +203,11 @@ float GlobalLanguage::getResolutionFontSizeAdjustment( void ) const
return m_resolutionFontSizeAdjustment;
}
-Int GlobalLanguage::adjustFontSize(Int theFontSize)
+Real GlobalLanguage::getResolutionFontSizeScale(ResolutionFontSizeMethod method, Real scaler)
{
- // TheSuperHackers @todo This function is called very often.
- // Therefore cache the adjustFactor on resolution change to not recompute it on every call.
Real adjustFactor;
- switch (m_resolutionFontSizeMethod)
+ switch (method)
{
default:
case ResolutionFontSizeMethod_Classic:
@@ -216,7 +215,7 @@ Int GlobalLanguage::adjustFontSize(Int theFontSize)
// TheSuperHackers @info The original font scaling for this game.
// Useful for not breaking legacy Addons and Mods. Scales poorly with large resolutions.
adjustFactor = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
+ adjustFactor = 1.0f + (adjustFactor - 1.0f) * scaler;
if (adjustFactor > 2.0f)
adjustFactor = 2.0f;
break;
@@ -226,7 +225,7 @@ Int GlobalLanguage::adjustFontSize(Int theFontSize)
// TheSuperHackers @feature The original font scaling, but without ceiling.
// Useful for not changing the original look of the game. Scales alright with large resolutions.
adjustFactor = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
+ adjustFactor = 1.0f + (adjustFactor - 1.0f) * scaler;
break;
}
case ResolutionFontSizeMethod_Strict:
@@ -236,7 +235,7 @@ Int GlobalLanguage::adjustFontSize(Int theFontSize)
const Real wScale = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
const Real hScale = TheDisplay->getHeight() / (Real)DEFAULT_DISPLAY_HEIGHT;
adjustFactor = min(wScale, hScale);
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
+ adjustFactor = 1.0f + (adjustFactor - 1.0f) * scaler;
break;
}
case ResolutionFontSizeMethod_Balanced:
@@ -265,14 +264,25 @@ Int GlobalLanguage::adjustFontSize(Int theFontSize)
hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
}
adjustFactor = (wScale + hScale) * 0.5f;
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
+ adjustFactor = 1.0f + (adjustFactor - 1.0f) * scaler;
break;
}
}
if (adjustFactor < 1.0f)
adjustFactor = 1.0f;
- Int pointSize = REAL_TO_INT_FLOOR(theFontSize*adjustFactor);
+
+ return adjustFactor;
+}
+
+Int GlobalLanguage::adjustFontSize(Int theFontSize)
+{
+ // TheSuperHackers @todo This function is called very often.
+ // Therefore cache the adjustFactor on resolution change to not recompute it on every call.
+ const Real resolutionScaler = getResolutionFontSizeAdjustment();
+ const Real adjustFactor = getResolutionFontSizeScale(m_resolutionFontSizeMethod, resolutionScaler);
+ const Int pointSize = REAL_TO_INT_FLOOR(theFontSize * adjustFactor);
+
return pointSize;
}
@@ -288,9 +298,9 @@ void GlobalLanguage::parseCustomDefinition()
FontDesc::FontDesc(void)
{
- name = "Arial Unicode MS"; ///newCountMine > 0) {
if (outSelectionInfo->newCountMine == 1 && selectionIsPoint && !TheInGameUI->isInPreferSelectionMode()) {
- return TheGameClient->evaluateContextCommand(newMine, newMine->getPosition(), CommandTranslator::EVALUATE_ONLY) != GameMessage::MSG_INVALID;
+ return TheGameClient->evaluateContextCommand(newMine, newMine->getPosition(), CommandTranslator::EVALUATE_ONLY) != GameMessage::MSG_INVALID;
}
return FALSE;
@@ -346,6 +346,10 @@ Bool addDrawableToList( Drawable *draw, void *userData )
return FALSE;
#if !RTS_GENERALS || !PRESERVE_RETAIL_BEHAVIOR
+ // TheSuperHackers @info
+ // In retail, drag-selecting allows the player to select stealthed objects and objects through the
+ // fog. Some players exploit this bug to determine where an opponent's units are and consider this
+ // an important feature and an advanced skill to pull off, so we must leave the exploit.
if (draw->getFullyObscuredByShroud())
return FALSE;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/Statistics.cpp b/Core/GameEngine/Source/GameClient/Statistics.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngine/Source/GameClient/Statistics.cpp
rename to Core/GameEngine/Source/GameClient/Statistics.cpp
diff --git a/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp b/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp
index 4e4e6d6970a..44bd9d203e1 100644
--- a/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp
+++ b/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp
@@ -1230,7 +1230,10 @@ ParticleSystem::ParticleSystem( const ParticleSystemTemplate *sysTemplate,
m_personalityStore = 0;
m_controlParticle = nullptr;
- TheParticleSystemManager->friend_addParticleSystem(this);
+ if ( m_systemID != INVALID_PARTICLE_SYSTEM_ID )
+ {
+ TheParticleSystemManager->friend_addParticleSystem(this);
+ }
//DEBUG_ASSERTLOG(!(m_totalParticleSystemCount % 10 == 0), ( "TotalParticleSystemCount = %d", m_totalParticleSystemCount ));
}
@@ -1275,7 +1278,10 @@ ParticleSystem::~ParticleSystem()
m_controlParticle = nullptr;
- TheParticleSystemManager->friend_removeParticleSystem(this);
+ if ( m_systemID != INVALID_PARTICLE_SYSTEM_ID )
+ {
+ TheParticleSystemManager->friend_removeParticleSystem(this);
+ }
//DEBUG_ASSERTLOG(!(m_totalParticleSystemCount % 10 == 0), ( "TotalParticleSystemCount = %d", m_totalParticleSystemCount ));
}
@@ -3379,20 +3385,24 @@ void ParticleSystemManager::xfer( Xfer *xfer )
}
// create system
- system = createParticleSystem( systemTemplate, FALSE );
+ // TheSuperHackers @bugfix stephanmeesters 16/02/2026
+ // Particle systems originally were assigned an incrementing system ID in the constructor that did not
+ // always match the ID that was xfer'd. When using findParticleSystem this would cause master/slave lookups to fail.
+ // Defer registering particle systems to ParticleSystemManager until the system ID is properly restored.
+ system = newInstance(ParticleSystem)( systemTemplate, INVALID_PARTICLE_SYSTEM_ID, FALSE );
- if( system == nullptr )
- {
+ // read system data
+ xfer->xferSnapshot( system );
- DEBUG_CRASH(( "ParticleSystemManager::xfer - Unable to allocate particle system '%s'",
+ if( system->getSystemID() == INVALID_PARTICLE_SYSTEM_ID )
+ {
+ DEBUG_CRASH(( "ParticleSystemManager::xfer - Unable to restore system ID to particle system '%s'",
systemName.str() ));
+ deleteInstance(system);
throw SC_INVALID_DATA;
-
}
- // read system data
- xfer->xferSnapshot( system );
-
+ friend_addParticleSystem(system);
}
}
diff --git a/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
index 959c882d625..3cb4483ffa5 100644
--- a/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
+++ b/Core/GameEngine/Source/GameNetwork/ConnectionManager.cpp
@@ -102,7 +102,7 @@ ConnectionManager::~ConnectionManager(void)
m_frameData[i] = nullptr;
}
- for (i = 0; i < NUM_CONNECTIONS; ++i) {
+ for (i = 0; i < MAX_SLOTS; ++i) {
deleteInstance(m_connections[i]);
m_connections[i] = nullptr;
}
@@ -160,7 +160,7 @@ void ConnectionManager::init()
// m_transport->reset();
UnsignedInt i = 0;
- for (; i < NUM_CONNECTIONS; ++i) {
+ for (; i < MAX_SLOTS; ++i) {
m_connections[i] = nullptr;
}
@@ -236,7 +236,7 @@ void ConnectionManager::reset()
m_transport = nullptr;
UnsignedInt i = 0;
- for (; i < (UnsignedInt)NUM_CONNECTIONS; ++i) {
+ for (; i < (UnsignedInt)MAX_SLOTS; ++i) {
deleteInstance(m_connections[i]);
m_connections[i] = nullptr;
}
@@ -302,6 +302,7 @@ Int ConnectionManager::getPingsReceived()
Bool ConnectionManager::isPlayerConnected( Int playerID )
{
+ DEBUG_ASSERTCRASH( playerID < MAX_SLOTS, ("ConnectionManager::isPlayerConnected - %d is an invalid player number", playerID) );
return ( playerID == m_localSlot || (m_connections[playerID] && !m_connections[playerID]->isQuitting()) );
}
@@ -431,6 +432,10 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {
}
// Early validation checks
+ if (msg->getPlayerID() >= MAX_SLOTS) {
+ return TRUE;
+ }
+
if ((m_connections[msg->getPlayerID()] == nullptr) && (msg->getPlayerID() != m_localSlot)) {
// if this is from a player that is no longer in the game, then ignore them.
return TRUE;
@@ -442,7 +447,7 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {
return FALSE;
}
- if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS) && (msg->getPlayerID() != m_localSlot)) {
+ if (msg->getPlayerID() != m_localSlot) {
if (m_connections[msg->getPlayerID()] == nullptr) {
return TRUE;
}
@@ -536,8 +541,8 @@ Bool ConnectionManager::processNetCommand(NetCommandRef *ref) {
void ConnectionManager::processFrameResendRequest(NetFrameResendRequestCommandMsg *msg) {
// first make sure this is a valid slot
- Int playerID = msg->getPlayerID();
- if ((playerID < 0) || (playerID >= MAX_SLOTS)) {
+ const UnsignedInt playerID = msg->getPlayerID();
+ if (playerID >= MAX_SLOTS) {
return;
}
@@ -601,16 +606,19 @@ void ConnectionManager::processWrapper(NetCommandRef *ref)
*/
void ConnectionManager::processRunAheadMetrics(NetRunAheadMetricsCommandMsg *msg)
{
- UnsignedInt player = msg->getPlayerID();
- if ((player >= 0) && (player < MAX_SLOTS) && (isPlayerConnected(player))) {
- m_latencyAverages[player] = msg->getAverageLatency();
- m_fpsAverages[player] = msg->getAverageFps();
+ const UnsignedInt playerID = msg->getPlayerID();
+ if (playerID >= MAX_SLOTS) {
+ return;
+ }
+ if (isPlayerConnected(playerID)) {
+ m_latencyAverages[playerID] = msg->getAverageLatency();
+ m_fpsAverages[playerID] = msg->getAverageFps();
//DEBUG_LOG(("ConnectionManager::processRunAheadMetrics - player %d, fps = %d, latency = %f", player, msg->getAverageFps(), msg->getAverageLatency()));
- if (m_fpsAverages[player] > 100) {
+ if (m_fpsAverages[playerID] > 100) {
// limit the reported frame rate average to 100. This is done because if a
// user alt-tab's out of the game their frame rate climbs to in the neighborhood of
// 300, that was deemed "ugly" by the powers that be.
- m_fpsAverages[player] = 100;
+ m_fpsAverages[playerID] = 100;
}
}
}
@@ -619,7 +627,10 @@ void ConnectionManager::processDisconnectChat(NetDisconnectChatCommandMsg *msg)
{
UnicodeString unitext;
UnicodeString name;
- UnsignedByte playerID = msg->getPlayerID();
+ const UnsignedInt playerID = msg->getPlayerID();
+ if (playerID >= MAX_SLOTS) {
+ return;
+ }
if (playerID == m_localSlot) {
name = m_localUser->GetName();
} else if (isPlayerConnected(playerID)) {
@@ -634,12 +645,15 @@ void ConnectionManager::processChat(NetChatCommandMsg *msg)
{
UnicodeString unitext;
UnicodeString name;
- UnsignedByte playerID = msg->getPlayerID();
+ const UnsignedInt playerID = msg->getPlayerID();
+ if (playerID >= MAX_SLOTS) {
+ return;
+ }
//DEBUG_LOG(("processChat(): playerID = %d", playerID));
if (playerID == m_localSlot) {
name = m_localUser->GetName();
//DEBUG_LOG(("connection is null, using %ls", name.str()));
- } else if (((m_connections[playerID] != nullptr) && (m_connections[playerID]->isQuitting() == FALSE))) {
+ } else if ((m_connections[playerID] != nullptr) && (m_connections[playerID]->isQuitting() == FALSE)) {
name = m_connections[playerID]->getUser()->GetName();
//DEBUG_LOG(("connection is non-null, using %ls", name.str()));
}
@@ -794,9 +808,14 @@ void ConnectionManager::processFileProgress(NetFileProgressCommandMsg *msg)
{
DEBUG_LOG(("ConnectionManager::processFileProgress() - command %d is at %d%%",
msg->getFileID(), msg->getProgress()));
- Int oldProgress = s_fileProgressMap[msg->getPlayerID()][msg->getFileID()];
- s_fileProgressMap[msg->getPlayerID()][msg->getFileID()] = max(oldProgress, msg->getProgress());
+ const UnsignedInt playerID = msg->getPlayerID();
+ if (playerID >= MAX_SLOTS) {
+ return;
+ }
+ const UnsignedShort fileID = msg->getFileID();
+ const Int oldProgress = s_fileProgressMap[playerID][fileID];
+ s_fileProgressMap[playerID][fileID] = max(oldProgress, msg->getProgress());
}
void ConnectionManager::processProgress( NetProgressCommandMsg *msg )
@@ -820,9 +839,9 @@ void ConnectionManager::processTimeOutGameStart( NetCommandMsg *msg )
void ConnectionManager::processFrameInfo(NetFrameCommandMsg *msg) {
//stupid frame info, why don't you process yourself?
- UnsignedInt playerID = msg->getPlayerID();
+ const UnsignedInt playerID = msg->getPlayerID();
- if ((playerID >= 0) && (playerID < MAX_SLOTS)) {
+ if (playerID < MAX_SLOTS) {
if (m_frameData[playerID] != nullptr) {
// DEBUG_LOG(("ConnectionManager::processFrameInfo - player %d, frame %d, command count %d, received on frame %d", playerID, msg->getExecutionFrame(), msg->getCommandCount(), TheGameLogic->getFrame()));
m_frameData[playerID]->setFrameCommandCount(msg->getExecutionFrame(), msg->getCommandCount());
@@ -839,7 +858,7 @@ void ConnectionManager::processAckStage1(NetCommandMsg *msg) {
Bool doDebug = (msg->getNetCommandType() == NETCOMMANDTYPE_DISCONNECTFRAME) ? TRUE : FALSE;
#endif
- UnsignedByte playerID = msg->getPlayerID();
+ const UnsignedInt playerID = msg->getPlayerID();
NetCommandRef *ref = nullptr;
#if defined(RTS_DEBUG)
@@ -848,12 +867,12 @@ void ConnectionManager::processAckStage1(NetCommandMsg *msg) {
}
#endif
- if ((playerID >= 0) && (playerID < NUM_CONNECTIONS)) {
+ if (playerID < MAX_SLOTS) {
if (m_connections[playerID] != nullptr) {
ref = m_connections[playerID]->processAck(msg);
}
} else {
- DEBUG_ASSERTCRASH((playerID >= 0) && (playerID < NUM_CONNECTIONS), ("ConnectionManager::processAck - %d is an invalid player number", playerID));
+ DEBUG_CRASH(("ConnectionManager::processAck - %d is an invalid player number", playerID));
}
if (ref != nullptr) {
@@ -1073,7 +1092,7 @@ void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) {
if (CommandRequiresDirectSend(msg) && CommandRequiresAck(msg)) {
// Send this ack directly back to the sending player, don't go through the packet router.
- if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) {
+ if (msg->getPlayerID() < MAX_SLOTS) {
if (m_connections[msg->getPlayerID()] != nullptr) {
m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID());
}
@@ -1086,21 +1105,21 @@ void ConnectionManager::ackCommand(NetCommandRef *ref, UnsignedInt localSlot) {
m_connections[m_packetRouterSlot]->sendNetCommandMsg(ackmsg, 1 << m_packetRouterSlot);
} else if (m_localSlot == m_packetRouterSlot) {
// we are the packet router, send the ack to the player that sent the command.
- if ((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS)) {
+ if (msg->getPlayerID() < MAX_SLOTS) {
if (m_connections[msg->getPlayerID()] != nullptr) {
// DEBUG_LOG(("ConnectionManager::ackCommand - acking command %d from player %d directly to player.", commandID, msg->getPlayerID()));
m_connections[msg->getPlayerID()]->sendNetCommandMsg(ackmsg, 1 << msg->getPlayerID());
} else {
- // DEBUG_ASSERTCRASH(m_connections[msg->getPlayerID()] != nullptr, ("Connection to player is null"));
+ // DEBUG_CRASH(("Connection to player is null"));
}
} else {
- DEBUG_ASSERTCRASH((msg->getPlayerID() >= 0) && (msg->getPlayerID() < MAX_SLOTS), ("Command sent by an invalid player ID."));
+ DEBUG_CRASH(("Command sent by an invalid player ID."));
}
} else {
- DEBUG_ASSERTCRASH(m_connections[m_packetRouterSlot] != nullptr, ("Connection to packet router is null"));
+ DEBUG_CRASH(("Connection to packet router is null"));
}
} else {
- DEBUG_ASSERTCRASH((m_packetRouterSlot >= 0) && (m_packetRouterSlot < MAX_SLOTS), ("I don't know who the packet router is."));
+ DEBUG_CRASH(("I don't know who the packet router is."));
}
}
@@ -1120,11 +1139,13 @@ void ConnectionManager::sendRemoteCommand(NetCommandRef *msg) {
DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - sending net command %d of type %s from player %d, relay is 0x%x",
msg->getCommand()->getID(), GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getRelay()));
- UnsignedByte relay = msg->getRelay();
- if ((relay & (1 << m_localSlot)) && (m_frameData[msg->getCommand()->getPlayerID()] != nullptr)) {
+ const UnsignedByte relay = msg->getRelay();
+ const UnsignedInt playerID = msg->getCommand()->getPlayerID();
+ FrameDataManager *frameDataMgr = playerID < MAX_SLOTS ? m_frameData[playerID] : nullptr;
+ if ((relay & (1 << m_localSlot)) && (frameDataMgr != nullptr)) {
if (IsCommandSynchronized(msg->getCommand()->getNetCommandType())) {
DEBUG_LOG_LEVEL(DEBUG_LEVEL_NET, ("ConnectionManager::sendRemoteCommand - adding net command of type %s to player %d for frame %d", GetNetCommandTypeAsString(msg->getCommand()->getNetCommandType()), msg->getCommand()->getPlayerID(), msg->getCommand()->getExecutionFrame()));
- m_frameData[msg->getCommand()->getPlayerID()]->addNetCommandMsg(msg->getCommand());
+ frameDataMgr->addNetCommandMsg(msg->getCommand());
}
}
@@ -1190,7 +1211,7 @@ void ConnectionManager::update(Bool isInGame) {
// send any necessary keep-alive packets.
doKeepAlive();
- for (Int i = 0; i < NUM_CONNECTIONS; ++i) {
+ for (Int i = 0; i < MAX_SLOTS; ++i) {
if (m_connections[i] != nullptr) {
/*
if (m_connections[i]->isQueueEmpty() == FALSE) {
diff --git a/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
index 6aec6e5868d..19256a2d54c 100644
--- a/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
+++ b/Core/GameEngine/Source/GameNetwork/DisconnectManager.cpp
@@ -371,7 +371,11 @@ void DisconnectManager::processDisconnectVote(NetCommandMsg *msg, ConnectionMana
void DisconnectManager::processDisconnectFrame(NetCommandMsg *msg, ConnectionManager *conMgr) {
NetDisconnectFrameCommandMsg *cmdMsg = (NetDisconnectFrameCommandMsg *)msg;
- UnsignedInt playerID = cmdMsg->getPlayerID();
+ const UnsignedInt playerID = cmdMsg->getPlayerID();
+ if (playerID >= MAX_SLOTS) {
+ return;
+ }
+
if (m_disconnectFrames[playerID] >= cmdMsg->getDisconnectFrame()) {
// this message isn't valid, we have a disconnect frame that is later than this already.
return;
@@ -415,7 +419,7 @@ void DisconnectManager::processDisconnectScreenOff(NetCommandMsg *msg, Connectio
DEBUG_LOG(("DisconnectManager::processDisconnectScreenOff - got a screen off command from player %d for frame %d", cmdMsg->getPlayerID(), cmdMsg->getNewFrame()));
- if ((playerID < 0) || (playerID >= MAX_SLOTS)) {
+ if (playerID >= MAX_SLOTS) {
return;
}
diff --git a/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp b/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp
index e6619efd0c8..e42b7072d24 100644
--- a/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp
+++ b/Core/GameEngine/Source/GameNetwork/FirewallHelper.cpp
@@ -49,7 +49,7 @@
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
#include "Common/crc.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameNetwork/FirewallHelper.h"
#include "GameNetwork/NAT.h"
#include "GameNetwork/udp.h"
diff --git a/Core/GameEngine/Source/GameNetwork/GameInfo.cpp b/Core/GameEngine/Source/GameNetwork/GameInfo.cpp
index 0b5370f0947..648c13d3354 100644
--- a/Core/GameEngine/Source/GameNetwork/GameInfo.cpp
+++ b/Core/GameEngine/Source/GameNetwork/GameInfo.cpp
@@ -978,7 +978,7 @@ AsciiString GameInfoToAsciiString( const GameInfo *game )
}
else
{
- DEBUG_ASSERTCRASH(false, ("Bad slot type"));
+ DEBUG_CRASH(("Bad slot type"));
str = "X:";
}
optionsString.concat(str);
diff --git a/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
index 592e14b133e..a1b326fa0dd 100644
--- a/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
+++ b/Core/GameEngine/Source/GameNetwork/GameSpy/Thread/PeerThread.cpp
@@ -32,7 +32,7 @@
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
#include "Common/Registry.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
#include "GameNetwork/IPEnumeration.h"
#include "GameNetwork/GameSpy/BuddyThread.h"
diff --git a/Core/GameEngine/Source/GameNetwork/LANAPI.cpp b/Core/GameEngine/Source/GameNetwork/LANAPI.cpp
index c7671fdc5c5..be01cd197fc 100644
--- a/Core/GameEngine/Source/GameNetwork/LANAPI.cpp
+++ b/Core/GameEngine/Source/GameNetwork/LANAPI.cpp
@@ -989,7 +989,7 @@ AsciiString LANAPI::createSlotString( void )
}
else
{
- DEBUG_ASSERTCRASH(false, ("Bad slot type"));
+ DEBUG_CRASH(("Bad slot type"));
str = "X,";
}
@@ -1153,7 +1153,7 @@ void LANAPI::removeGame( LANGameInfo *game )
else
{
// Odd. We went the whole way without finding it in the list.
- DEBUG_ASSERTCRASH(false, ("LANGameInfo wasn't in the list"));
+ DEBUG_CRASH(("LANGameInfo wasn't in the list"));
}
}
}
@@ -1194,7 +1194,7 @@ void LANAPI::removePlayer( LANPlayer *player )
else
{
// Odd. We went the whole way without finding it in the list.
- DEBUG_ASSERTCRASH(false, ("LANPlayer wasn't in the list"));
+ DEBUG_CRASH(("LANPlayer wasn't in the list"));
}
}
}
diff --git a/Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp b/Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
index 2c344553f76..9423e7663fa 100644
--- a/Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
+++ b/Core/GameEngine/Source/GameNetwork/LANAPICallbacks.cpp
@@ -551,7 +551,7 @@ void LANAPI::OnPlayerLeave( UnicodeString player )
if (m_name.compare(player) == 0)
{
// We're leaving. Save options and Pop the shell up a screen.
- //DEBUG_ASSERTCRASH(false, ("Slot is %d", m_currentGame->getLocalSlotNum()));
+ //DEBUG_CRASH(("Slot is %d", m_currentGame->getLocalSlotNum()));
if (m_currentGame && m_currentGame->isInGame() && m_currentGame->getLocalSlotNum() >= 0)
{
LANPreferences pref;
diff --git a/Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp b/Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
index 0f44f1d681d..7f88b835f86 100644
--- a/Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
+++ b/Core/GameEngine/Source/GameNetwork/LANAPIhandlers.cpp
@@ -432,7 +432,7 @@ void LANAPI::handleJoinAccept( LANMessage *msg, UnsignedInt senderIP )
if (!m_currentGame)
{
- DEBUG_ASSERTCRASH(false, ("Could not find game to join!"));
+ DEBUG_CRASH(("Could not find game to join!"));
OnGameJoin(RET_UNKNOWN, nullptr);
}
else
@@ -463,7 +463,7 @@ void LANAPI::handleJoinAccept( LANMessage *msg, UnsignedInt senderIP )
prefs.write();
OnGameJoin(RET_OK, m_currentGame);
- //DEBUG_ASSERTCRASH(false, ("setting host to %ls@%ls", m_currentGame->getLANSlot(0)->getUser()->getLogin().str(),
+ //DEBUG_CRASH(("setting host to %ls@%ls", m_currentGame->getLANSlot(0)->getUser()->getLogin().str(),
// m_currentGame->getLANSlot(0)->getUser()->getHost().str()));
}
m_pendingAction = ACT_NONE;
diff --git a/Core/GameEngine/Source/GameNetwork/NetMessageStream.cpp b/Core/GameEngine/Source/GameNetwork/NetMessageStream.cpp
index c2855eca5ce..2ae6a14899e 100644
--- a/Core/GameEngine/Source/GameNetwork/NetMessageStream.cpp
+++ b/Core/GameEngine/Source/GameNetwork/NetMessageStream.cpp
@@ -181,7 +181,7 @@ Bool AddCommandToPacket(const GameMessage *msg)
commandBuf[0] = MSGTYPE_PARTIALCOMMAND;
if (!TheNetwork->queueSend(BROADCAST_CON, commandBuf, bytesUsed + sizeof(CommandPacketHeader) + 1, MSG_NEEDACK | MSG_SEQUENCED))
{
- //DEBUG_ASSERTCRASH(false, ("Too many commands in one frame! Some will be dropped."));
+ //DEBUG_CRASH(("Too many commands in one frame! Some will be dropped."));
DEBUG_LOG(("Too many commands in one frame! Some will be dropped."));
return false;
}
@@ -192,7 +192,7 @@ Bool AddCommandToPacket(const GameMessage *msg)
if (bytesUsed + sizeof(CommandPacketHeader) + messageSize >= MAX_MESSAGE_LEN)
{
- //DEBUG_ASSERTCRASH(false, ("Too many commands in one frame! Some will be dropped."));
+ //DEBUG_CRASH(("Too many commands in one frame! Some will be dropped."));
DEBUG_LOG(("Too many commands in one frame! Some will be dropped."));
return false;
}
diff --git a/Core/GameEngine/Source/GameNetwork/NetPacket.cpp b/Core/GameEngine/Source/GameNetwork/NetPacket.cpp
index 66546da7190..3d4315f7f2d 100644
--- a/Core/GameEngine/Source/GameNetwork/NetPacket.cpp
+++ b/Core/GameEngine/Source/GameNetwork/NetPacket.cpp
@@ -276,7 +276,7 @@ UnsignedInt NetPacket::GetBufferSizeNeededForCommand(NetCommandMsg *msg) {
// This is where the fun begins...
if (msg == nullptr) {
- return TRUE; // There was nothing to add, so it was successful.
+ return 0; // There was nothing to add.
}
// Use the virtual function for all command message types
return msg->getPackedByteCount();
diff --git a/Core/GameEngineDevice/CMakeLists.txt b/Core/GameEngineDevice/CMakeLists.txt
index 93184aa47b1..25a6583230d 100644
--- a/Core/GameEngineDevice/CMakeLists.txt
+++ b/Core/GameEngineDevice/CMakeLists.txt
@@ -54,7 +54,7 @@ set(GAMEENGINEDEVICE_SRC
# Include/W3DDevice/GameClient/W3DGUICallbacks.h
# Include/W3DDevice/GameClient/W3DInGameUI.h
# Include/W3DDevice/GameClient/W3DMirror.h
-# Include/W3DDevice/GameClient/W3DMouse.h
+ Include/W3DDevice/GameClient/W3DMouse.h
# Include/W3DDevice/GameClient/W3DParticleSys.h
# Include/W3DDevice/GameClient/W3DPoly.h
# Include/W3DDevice/GameClient/W3DProjectedShadow.h
@@ -87,9 +87,9 @@ set(GAMEENGINEDEVICE_SRC
# Include/Win32Device/Common/Win32GameEngine.h
Include/Win32Device/Common/Win32LocalFile.h
Include/Win32Device/Common/Win32LocalFileSystem.h
-# Include/Win32Device/GameClient/Win32DIKeyboard.h
-# Include/Win32Device/GameClient/Win32DIMouse.h
-# Include/Win32Device/GameClient/Win32Mouse.h
+ Include/Win32Device/GameClient/Win32DIKeyboard.h
+ #Include/Win32Device/GameClient/Win32DIMouse.h
+ Include/Win32Device/GameClient/Win32Mouse.h
Source/MilesAudioDevice/MilesAudioManager.cpp
Source/VideoDevice/Bink/BinkVideoPlayer.cpp
# Source/W3DDevice/Common/System/W3DFunctionLexicon.cpp
@@ -158,7 +158,7 @@ set(GAMEENGINEDEVICE_SRC
# Source/W3DDevice/GameClient/W3DFileSystem.cpp
# Source/W3DDevice/GameClient/W3DGameClient.cpp
# Source/W3DDevice/GameClient/W3DInGameUI.cpp
-# Source/W3DDevice/GameClient/W3DMouse.cpp
+ Source/W3DDevice/GameClient/W3DMouse.cpp
# Source/W3DDevice/GameClient/W3DParticleSys.cpp
# Source/W3DDevice/GameClient/W3DPoly.cpp
Source/W3DDevice/GameClient/W3DPropBuffer.cpp
@@ -189,9 +189,9 @@ set(GAMEENGINEDEVICE_SRC
Source/Win32Device/Common/Win32LocalFile.cpp
Source/Win32Device/Common/Win32LocalFileSystem.cpp
# Source/Win32Device/Common/Win32OSDisplay.cpp
-# Source/Win32Device/GameClient/Win32DIKeyboard.cpp
+ Source/Win32Device/GameClient/Win32DIKeyboard.cpp
#Source/Win32Device/GameClient/Win32DIMouse.cpp
-# Source/Win32Device/GameClient/Win32Mouse.cpp
+ Source/Win32Device/GameClient/Win32Mouse.cpp
)
# Add C++ 17 FileSystem implementation for non-VS6 builds
diff --git a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h
rename to Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h
diff --git a/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIKeyboard.h b/Core/GameEngineDevice/Include/Win32Device/GameClient/Win32DIKeyboard.h
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIKeyboard.h
rename to Core/GameEngineDevice/Include/Win32Device/GameClient/Win32DIKeyboard.h
diff --git a/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h b/Core/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h
rename to Core/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h
diff --git a/GeneralsMD/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h b/Core/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h
rename to Core/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h
diff --git a/Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp b/Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
index 4535e76f05a..4dde9b806ae 100644
--- a/Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
+++ b/Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
@@ -602,12 +602,17 @@ void W3DRadar::drawEvents( Int pixelX, Int pixelY, Int width, Int height )
void W3DRadar::drawIcons( Int pixelX, Int pixelY, Int width, Int height )
{
Player *player = rts::getObservedOrLocalPlayer();
- for (RadarObject *heroObj = m_localHeroObjectList; heroObj; heroObj = heroObj->friend_getNext())
+ for (RadarObject *heroObj = m_localObjectList; heroObj; heroObj = heroObj->friend_getNext())
{
- if (canRenderObject(heroObj, player))
- {
- drawHeroIcon(pixelX, pixelY, width, height, heroObj->friend_getObject()->getPosition());
- }
+ const Object *obj = heroObj->friend_getObject();
+
+ if (!obj->isHero())
+ continue;
+
+ if (!canRenderObject(heroObj, player))
+ continue;
+
+ drawHeroIcon(pixelX, pixelY, width, height, obj->getPosition());
}
}
@@ -623,7 +628,6 @@ void W3DRadar::updateObjectTexture(TextureClass *texture)
// rebuild the object overlay
renderObjectList( m_objectList, texture );
renderObjectList( m_localObjectList, texture );
- renderObjectList( m_localHeroObjectList, texture );
}
//-------------------------------------------------------------------------------------------------
diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DLaserDraw.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DLaserDraw.cpp
index 62b3e8669ea..eb76054b6b2 100644
--- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DLaserDraw.cpp
+++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DLaserDraw.cpp
@@ -304,7 +304,7 @@ void W3DLaserDraw::doDrawModule(const Matrix3D* transformMtx)
LaserUpdate *update = (LaserUpdate*)draw->findClientUpdateModule( key_LaserUpdate );
if( !update )
{
- DEBUG_ASSERTCRASH( 0, ("W3DLaserDraw::doDrawModule() expects its owner drawable %s to have a ClientUpdate = LaserUpdate module.", draw->getTemplate()->getName().str() ));
+ DEBUG_CRASH( ("W3DLaserDraw::doDrawModule() expects its owner drawable %s to have a ClientUpdate = LaserUpdate module.", draw->getTemplate()->getName().str() ));
return;
}
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp
rename to Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp b/Core/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp
rename to Core/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp b/Core/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp
rename to Core/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp b/Core/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp
rename to Core/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp
diff --git a/Core/Tools/ImagePacker/Source/ImagePacker.cpp b/Core/Tools/ImagePacker/Source/ImagePacker.cpp
index fb180b69806..3bf47871c9a 100644
--- a/Core/Tools/ImagePacker/Source/ImagePacker.cpp
+++ b/Core/Tools/ImagePacker/Source/ImagePacker.cpp
@@ -251,7 +251,7 @@ Bool ImagePacker::packImages( void )
char buffer[ _MAX_PATH ];
sprintf( buffer, "Unable to add image '%s' to a brand new page!\n", image->m_path );
- DEBUG_ASSERTCRASH( 0, (buffer) );
+ DEBUG_CRASH( (buffer) );
MessageBox( nullptr, buffer, "Internal Error", MB_OK | MB_ICONERROR );
return FALSE;
diff --git a/Core/Tools/ImagePacker/Source/TexturePage.cpp b/Core/Tools/ImagePacker/Source/TexturePage.cpp
index a2520e4c92f..c3ffadf843f 100644
--- a/Core/Tools/ImagePacker/Source/TexturePage.cpp
+++ b/Core/Tools/ImagePacker/Source/TexturePage.cpp
@@ -524,7 +524,7 @@ Bool TexturePage::addImageData( Byte *destBuffer,
char buffer[ _MAX_PATH + 32 ];
sprintf( buffer, "Error loading source file '%s'\n", image->m_path );
- DEBUG_ASSERTCRASH( 0, (buffer) );
+ DEBUG_CRASH( (buffer) );
MessageBox( nullptr, buffer, "Cannot Load Source File", MB_OK | MB_ICONERROR );
return FALSE;
diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt
index 991e6a72698..044a2ec6952 100644
--- a/Generals/Code/GameEngine/CMakeLists.txt
+++ b/Generals/Code/GameEngine/CMakeLists.txt
@@ -133,28 +133,28 @@ set(GAMEENGINE_SRC
Include/GameClient/AnimateWindowManager.h
# Include/GameClient/ChallengeGenerals.h
Include/GameClient/CampaignManager.h
- Include/GameClient/ClientInstance.h
+# Include/GameClient/ClientInstance.h
# Include/GameClient/ClientRandomValue.h
- Include/GameClient/Color.h
+# Include/GameClient/Color.h
Include/GameClient/CommandXlat.h
Include/GameClient/ControlBar.h
Include/GameClient/ControlBarResizer.h
Include/GameClient/ControlBarScheme.h
- Include/GameClient/Credits.h
+# Include/GameClient/Credits.h
Include/GameClient/DebugDisplay.h
Include/GameClient/Diplomacy.h
Include/GameClient/DisconnectMenu.h
Include/GameClient/Display.h
- Include/GameClient/DisplayString.h
- Include/GameClient/DisplayStringManager.h
+# Include/GameClient/DisplayString.h
+# Include/GameClient/DisplayStringManager.h
Include/GameClient/Drawable.h
Include/GameClient/DrawableInfo.h
- Include/GameClient/DrawGroupInfo.h
+# Include/GameClient/DrawGroupInfo.h
Include/GameClient/EstablishConnectionsMenu.h
Include/GameClient/Eva.h
Include/GameClient/ExtendedMessageBox.h
Include/GameClient/FontDesc.h
- Include/GameClient/FXList.h
+# Include/GameClient/FXList.h
Include/GameClient/Gadget.h
Include/GameClient/GadgetCheckBox.h
Include/GameClient/GadgetComboBox.h
@@ -167,29 +167,29 @@ set(GAMEENGINE_SRC
Include/GameClient/GadgetTabControl.h
Include/GameClient/GadgetTextEntry.h
Include/GameClient/GameClient.h
- Include/GameClient/GameFont.h
+# Include/GameClient/GameFont.h
Include/GameClient/GameInfoWindow.h
- Include/GameClient/GameText.h
- Include/GameClient/GameWindow.h
- Include/GameClient/GameWindowGlobal.h
+# Include/GameClient/GameText.h
+# Include/GameClient/GameWindow.h
+# Include/GameClient/GameWindowGlobal.h
Include/GameClient/GameWindowID.h
Include/GameClient/GameWindowManager.h
- Include/GameClient/GameWindowTransitions.h
- Include/GameClient/GlobalLanguage.h
- Include/GameClient/GraphDraw.h
+# Include/GameClient/GameWindowTransitions.h
+# Include/GameClient/GlobalLanguage.h
+# Include/GameClient/GraphDraw.h
Include/GameClient/GUICallbacks.h
Include/GameClient/GUICommandTranslator.h
- Include/GameClient/HeaderTemplate.h
+# Include/GameClient/HeaderTemplate.h
Include/GameClient/HintSpy.h
Include/GameClient/HotKey.h
Include/GameClient/Image.h
- Include/GameClient/IMEManager.h
+# Include/GameClient/IMEManager.h
Include/GameClient/InGameUI.h
- Include/GameClient/Keyboard.h
+# Include/GameClient/Keyboard.h
Include/GameClient/KeyDefs.h
- Include/GameClient/LanguageFilter.h
- Include/GameClient/Line2D.h
- Include/GameClient/LoadScreen.h
+# Include/GameClient/LanguageFilter.h
+# Include/GameClient/Line2D.h
+# Include/GameClient/LoadScreen.h
Include/GameClient/LookAtXlat.h
# Include/GameClient/MapUtil.h
Include/GameClient/MessageBox.h
@@ -197,28 +197,28 @@ set(GAMEENGINE_SRC
Include/GameClient/Module/AnimatedParticleSysBoneClientUpdate.h
Include/GameClient/Module/BeaconClientUpdate.h
Include/GameClient/Module/SwayClientUpdate.h
- Include/GameClient/Mouse.h
+# Include/GameClient/Mouse.h
# Include/GameClient/ParticleSys.h
Include/GameClient/PlaceEventTranslator.h
- Include/GameClient/ProcessAnimateWindow.h
- Include/GameClient/RadiusDecal.h
+# Include/GameClient/ProcessAnimateWindow.h
+# Include/GameClient/RadiusDecal.h
Include/GameClient/RayEffect.h
- Include/GameClient/SelectionInfo.h
+# Include/GameClient/SelectionInfo.h
Include/GameClient/SelectionXlat.h
Include/GameClient/Shadow.h
Include/GameClient/Shell.h
Include/GameClient/ShellHooks.h
Include/GameClient/ShellMenuScheme.h
- Include/GameClient/Statistics.h
+# Include/GameClient/Statistics.h
# Include/GameClient/TerrainRoads.h
# Include/GameClient/TerrainVisual.h
# Include/GameClient/VideoPlayer.h
# Include/GameClient/View.h
# Include/GameClient/Water.h
- Include/GameClient/WindowLayout.h
+# Include/GameClient/WindowLayout.h
# Include/GameClient/WindowVideoManager.h
Include/GameClient/WindowXlat.h
- Include/GameClient/WinInstanceData.h
+# Include/GameClient/WinInstanceData.h
Include/GameLogic/AI.h
Include/GameLogic/AIDock.h
Include/GameLogic/AIGuard.h
@@ -636,24 +636,24 @@ set(GAMEENGINE_SRC
# Source/Common/UserPreferences.cpp
Source/Common/version.cpp
# Source/Common/WorkerProcess.cpp
- Source/GameClient/ClientInstance.cpp
- Source/GameClient/Color.cpp
- Source/GameClient/Credits.cpp
+# Source/GameClient/ClientInstance.cpp
+# Source/GameClient/Color.cpp
+# Source/GameClient/Credits.cpp
Source/GameClient/Display.cpp
- Source/GameClient/DisplayString.cpp
- Source/GameClient/DisplayStringManager.cpp
+# Source/GameClient/DisplayString.cpp
+# Source/GameClient/DisplayStringManager.cpp
Source/GameClient/Drawable.cpp
Source/GameClient/Drawable/Update/AnimatedParticleSysBoneClientUpdate.cpp
Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp
Source/GameClient/Drawable/Update/SwayClientUpdate.cpp
- Source/GameClient/DrawGroupInfo.cpp
+# Source/GameClient/DrawGroupInfo.cpp
Source/GameClient/Eva.cpp
- Source/GameClient/FXList.cpp
+# Source/GameClient/FXList.cpp
Source/GameClient/GameClient.cpp
Source/GameClient/GameClientDispatch.cpp
- Source/GameClient/GameText.cpp
- Source/GameClient/GlobalLanguage.cpp
- Source/GameClient/GraphDraw.cpp
+# Source/GameClient/GameText.cpp
+# Source/GameClient/GlobalLanguage.cpp
+# Source/GameClient/GraphDraw.cpp
Source/GameClient/GUI/AnimateWindowManager.cpp
# Source/GameClient/GUI/ChallengeGenerals.cpp
Source/GameClient/GUI/ControlBar/ControlBar.cpp
@@ -681,12 +681,12 @@ set(GAMEENGINE_SRC
Source/GameClient/GUI/Gadget/GadgetTabControl.cpp
Source/GameClient/GUI/Gadget/GadgetTextEntry.cpp
Source/GameClient/GUI/Gadget/GadgetVerticalSlider.cpp
- Source/GameClient/GUI/GameFont.cpp
- Source/GameClient/GUI/GameWindow.cpp
- Source/GameClient/GUI/GameWindowGlobal.cpp
+# Source/GameClient/GUI/GameFont.cpp
+# Source/GameClient/GUI/GameWindow.cpp
+# Source/GameClient/GUI/GameWindowGlobal.cpp
Source/GameClient/GUI/GameWindowManager.cpp
Source/GameClient/GUI/GameWindowManagerScript.cpp
- Source/GameClient/GUI/GameWindowTransitions.cpp
+# Source/GameClient/GUI/GameWindowTransitions.cpp
Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp
Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
@@ -738,20 +738,20 @@ set(GAMEENGINE_SRC
Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp
Source/GameClient/GUI/GUICallbacks/MessageBox.cpp
Source/GameClient/GUI/GUICallbacks/ReplayControls.cpp
- Source/GameClient/GUI/HeaderTemplate.cpp
- Source/GameClient/GUI/IMEManager.cpp
- Source/GameClient/GUI/LoadScreen.cpp
- Source/GameClient/GUI/ProcessAnimateWindow.cpp
+# Source/GameClient/GUI/HeaderTemplate.cpp
+# Source/GameClient/GUI/IMEManager.cpp
+# Source/GameClient/GUI/LoadScreen.cpp
+# Source/GameClient/GUI/ProcessAnimateWindow.cpp
Source/GameClient/GUI/Shell/Shell.cpp
Source/GameClient/GUI/Shell/ShellMenuScheme.cpp
- Source/GameClient/GUI/WindowLayout.cpp
+# Source/GameClient/GUI/WindowLayout.cpp
# Source/GameClient/GUI/WindowVideoManager.cpp
- Source/GameClient/GUI/WinInstanceData.cpp
+# Source/GameClient/GUI/WinInstanceData.cpp
Source/GameClient/InGameUI.cpp
- Source/GameClient/Input/Keyboard.cpp
- Source/GameClient/Input/Mouse.cpp
- Source/GameClient/LanguageFilter.cpp
- Source/GameClient/Line2D.cpp
+# Source/GameClient/Input/Keyboard.cpp
+# Source/GameClient/Input/Mouse.cpp
+# Source/GameClient/LanguageFilter.cpp
+# Source/GameClient/Line2D.cpp
# Source/GameClient/MapUtil.cpp
Source/GameClient/MessageStream/CommandXlat.cpp
Source/GameClient/MessageStream/GUICommandTranslator.cpp
@@ -762,9 +762,9 @@ set(GAMEENGINE_SRC
Source/GameClient/MessageStream/PlaceEventTranslator.cpp
Source/GameClient/MessageStream/SelectionXlat.cpp
Source/GameClient/MessageStream/WindowXlat.cpp
- Source/GameClient/RadiusDecal.cpp
- Source/GameClient/SelectionInfo.cpp
- Source/GameClient/Statistics.cpp
+# Source/GameClient/RadiusDecal.cpp
+# Source/GameClient/SelectionInfo.cpp
+# Source/GameClient/Statistics.cpp
Source/GameClient/System/Anim2D.cpp
Source/GameClient/System/CampaignManager.cpp
# "Source/GameClient/System/Debug Displayers/AudioDebugDisplay.cpp"
diff --git a/Generals/Code/GameEngine/Include/Common/TunnelTracker.h b/Generals/Code/GameEngine/Include/Common/TunnelTracker.h
index eddc5b3c104..188eb61180c 100644
--- a/Generals/Code/GameEngine/Include/Common/TunnelTracker.h
+++ b/Generals/Code/GameEngine/Include/Common/TunnelTracker.h
@@ -44,6 +44,7 @@ class TunnelTracker : public MemoryPoolObject,
// contain list access
void iterateContained( ContainIterateFunc func, void *userData, Bool reverse );
UnsignedInt getContainCount() const { return m_containListSize; }
+ UnsignedInt getHeroUnitsContained() const { return m_heroUnitsContained; }
Int getContainMax() const;
const ContainedItemsList* getContainedItemsList() const { return &m_containList; }
void swapContainedItemsList(ContainedItemsList& newList);
@@ -85,6 +86,7 @@ class TunnelTracker : public MemoryPoolObject,
ContainedItemsList m_containList; ///< the contained object pointers list
std::list< ObjectID > m_xferContainList;///< for loading of m_containList during post processing
Int m_containListSize; ///< size of the contain list
+ UnsignedInt m_heroUnitsContained; ///< cached hero count
UnsignedInt m_tunnelCount; ///< How many tunnels have registered so we know when we should kill our contain list
UnsignedInt m_framesForFullHeal; ///< How many frames it takes to fully heal a unit
Bool m_needsFullHealTimeUpdate; ///< Set to true when needing to recalc full heal time to batch the operation
diff --git a/Generals/Code/GameEngine/Include/GameClient/CampaignManager.h b/Generals/Code/GameEngine/Include/GameClient/CampaignManager.h
index 77b4fe19875..da034d5ee98 100644
--- a/Generals/Code/GameEngine/Include/GameClient/CampaignManager.h
+++ b/Generals/Code/GameEngine/Include/GameClient/CampaignManager.h
@@ -82,6 +82,7 @@ class Mission : public MemoryPoolObject
AsciiString m_locationNameLabel;
AsciiString m_unitNames[MAX_DISPLAYED_UNITS];
Int m_voiceLength;
+ AsciiString m_generalName;
};
class Campaign : public MemoryPoolObject
diff --git a/Generals/Code/GameEngine/Include/GameClient/Color.h b/Generals/Code/GameEngine/Include/GameClient/Color.h
deleted file mode 100644
index 842827c3028..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/Color.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Color.h //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Color.h
-//
-// Created: Colin Day, July 2001
-//
-// Desc: Management of color representations
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-enum { GAME_COLOR_UNDEFINED = 0x00FFFFFF }; // this is white with zero alpha... safe to use!
-
-/** @todo we need real color representation, this is just placeholder so we
-can more easily identify sections of the code that need it */
-typedef Int Color;
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
-
-inline Color GameMakeColor( UnsignedByte red, UnsignedByte green, UnsignedByte blue, UnsignedByte alpha )
-{
- return (alpha << 24) | (red << 16) | (green << 8) | (blue);
-}
-
-extern void GameGetColorComponents( Color color,
- UnsignedByte *red,
- UnsignedByte *green,
- UnsignedByte *blue,
- UnsignedByte *alpha );
-
-// Put on ice until later - M Lorenzen
-//extern void GameGetColorComponentsWithCheatSpy( Color color,
-// UnsignedByte *red,
-// UnsignedByte *green,
-// UnsignedByte *blue,
-// UnsignedByte *alpha );
-
-
-extern void GameGetColorComponentsReal( Color color, Real *red, Real *green, Real *blue, Real *alpha );
-
-extern Color GameDarkenColor( Color color, Int percent = 10 );
diff --git a/Generals/Code/GameEngine/Include/GameClient/Credits.h b/Generals/Code/GameEngine/Include/GameClient/Credits.h
deleted file mode 100644
index 5055907b0dd..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/Credits.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Credits.h /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Dec 2002
-//
-// Filename: Credits.h
-//
-// author: Chris Huybregts
-//
-// purpose: header file for the credits
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "GameClient/FontDesc.h"
-
-//-----------------------------------------------------------------------------
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class DisplayString;
-//-----------------------------------------------------------------------------
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-enum
-{
-CREDIT_STYLE_TITLE = 0,
-CREDIT_STYLE_POSITION,
-CREDIT_STYLE_NORMAL,
-CREDIT_STYLE_COLUMN,
-CREDIT_STYLE_BLANK, ///< Keep this second to last
-
-MAX_CREDIT_STYLES
-};
-
-enum{ CREDIT_SPACE_OFFSET = 2 };
-
-static const LookupListRec CreditStyleNames[] =
-{
- { "TITLE", CREDIT_STYLE_TITLE },
- { "MINORTITLE", CREDIT_STYLE_POSITION },
- { "NORMAL", CREDIT_STYLE_NORMAL },
- { "COLUMN", CREDIT_STYLE_COLUMN },
- // CREDIT_STYLE_BLANK
- { nullptr, 0 }
-};
-static_assert(ARRAY_SIZE(CreditStyleNames) == MAX_CREDIT_STYLES, "Incorrect array size");
-
-
-class CreditsLine
-{
-public:
- CreditsLine();
- ~CreditsLine();
-
-// parsing variables
- Int m_style;
- UnicodeString m_text;
- UnicodeString m_secondText;
- Bool m_useSecond;
- Bool m_done;
-
-// drawing variables
- DisplayString *m_displayString;
- DisplayString *m_secondDisplayString;
- ICoord2D m_pos;
- Int m_height;
- Int m_color;
-};
-
-class CreditsManager: public SubsystemInterface
-{
-public:
- CreditsManager(void);
- ~CreditsManager(void);
-
- void init(void );
- void load(void );
- void reset( void );
- void update( void );
- void draw( void );
-
- const FieldParse *getFieldParse() const { return m_creditsFieldParseTable; } ///< returns the parsing fields
- static const FieldParse m_creditsFieldParseTable[]; ///< the parse table
- static void parseBlank( INI* ini, void *instance, void *store, const void *userData ); ///< Parse the image part of the INI file
- static void parseText( INI* ini, void *instance, void *store, const void *userData ); ///< Parse the image part of the INI file
-
- Bool isFinished( void ) { return m_isFinished; }
- void addBlank( void );
- void addText( AsciiString text );
-private:
-
- UnicodeString getUnicodeString(AsciiString str);
-
- typedef std::list CreditsLineList;
- CreditsLineList m_creditLineList;
- CreditsLineList::iterator m_creditLineListIt;
-
- CreditsLineList m_displayedCreditLineList;
-
- Int m_scrollRate; // in pixels
- Int m_scrollRatePerFrames;
- Bool m_scrollDown; // if TRUE text will come from the top to the bottom if False, it will go from the bottom up
-
- Color m_titleColor;
- Color m_positionColor;
- Color m_normalColor;
-
- Int m_currentStyle;
-
- Bool m_isFinished;
-
- Int m_framesSinceStarted;
- Int m_normalFontHeight;
-};
-
-
-//-----------------------------------------------------------------------------
-// INLINING ///////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// EXTERNALS //////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-extern CreditsManager *TheCredits;
diff --git a/Generals/Code/GameEngine/Include/GameClient/DisplayString.h b/Generals/Code/GameEngine/Include/GameClient/DisplayString.h
deleted file mode 100644
index 164ad25bbb2..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/DisplayString.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DisplayString.h //////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: DisplayString.h
-//
-// Created: Colin Day, July 2001
-//
-// Desc: Contstuct for holding double byte game string data and being
-// able to draw that text to the screen.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "GameClient/GameFont.h"
-#include "GameClient/Color.h"
-#include "Common/AsciiString.h"
-#include "Common/UnicodeString.h"
-#include "Common/GameMemory.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-class DisplayStringManager;
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-// DisplayString --------------------------------------------------------------
-/** String representation that can also has additional information and
- * methods for drawing to the screen */
-//-----------------------------------------------------------------------------
-class DisplayString : public MemoryPoolObject
-{
-
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( DisplayString, "DisplayString" )
-
-public:
-
- friend DisplayStringManager;
-
- DisplayString( void );
- // virtual ~DisplayString( void ); // destructor defined by memory pool
-
- virtual void setText( UnicodeString text ); ///< set text for this string
- virtual UnicodeString getText( void ); ///< get text for this string
- virtual Int getTextLength( void ); ///< return number of chars in string
- virtual void notifyTextChanged( void ); ///< called when text has changed
- virtual void reset( void ); ///< reset all contents of string
-
- virtual void setFont( GameFont *font ); ///< set a font for display
- virtual GameFont *getFont( void ); ///< return font in string
- virtual void setWordWrap( Int wordWrap ) = 0; ///< Set the width that we want to start wrapping text
- virtual void setWordWrapCentered( Bool isCentered ) = 0; ///< If this is set to true, the text on a new line is centered
- virtual void draw( Int x, Int y, Color color, Color dropColor ) = 0; ///< render text
- virtual void draw( Int x, Int y, Color color, Color dropColor, Int xDrop, Int yDrop ) = 0; ///< render text with the drop shadow being at the offsets passed in
- virtual void getSize( Int *width, Int *height ) = 0; ///< get render size
- virtual Int getWidth( Int charPos = -1 ) = 0; ///< get text with up to charPos characters, 1- = all characters
-
- virtual void setUseHotkey( Bool useHotkey, Color hotKeyColor ) = 0;
-
- virtual void setClipRegion( IRegion2D *region ); ///< clip text in this region
-
- virtual void removeLastChar( void ); ///< remove the last character
- virtual void truncateBy(const Int charCount); ///< remove the last charCount characters
- virtual void truncateTo(const Int maxLength); ///< remove characters, if needed, until the string is maxLength long excluding null terminator
-
- virtual void appendChar( WideChar c ); ///< append character to end
-
- DisplayString *next( void ); ///< return next string
-
-protected:
-
- UnicodeString m_textString;
- GameFont *m_font; ///< font to display this string with
-
- DisplayString *m_next; ///< for the display string factory list ONLY
- DisplayString *m_prev; ///< for the display string factory list ONLY
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// INLINING ///////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-inline UnicodeString DisplayString::getText( void ) { return m_textString; }
-inline Int DisplayString::getTextLength( void ) { return m_textString.getLength(); }
-inline void DisplayString::setFont( GameFont *font ) { m_font = font; }
-inline GameFont *DisplayString::getFont( void ) { return m_font; }
-inline void DisplayString::setClipRegion( IRegion2D *region ) {}
-inline void DisplayString::notifyTextChanged( void ) {}
-inline DisplayString *DisplayString::next( void ) { return m_next; }
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngine/Include/GameClient/DisplayStringManager.h b/Generals/Code/GameEngine/Include/GameClient/DisplayStringManager.h
deleted file mode 100644
index 6ce394d3fe5..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/DisplayStringManager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DisplayStringManager.h ///////////////////////////////////////////////////////////////////
-// Created: Colin Day, July 2001
-// Desc: Access for creating game managed display strings
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/SubsystemInterface.h"
-#include "GameClient/DisplayString.h"
-
-//-------------------------------------------------------------------------------------------------
-/** Factory for managing and creating display strings */
-//-------------------------------------------------------------------------------------------------
-class DisplayStringManager : public SubsystemInterface
-{
-
-public:
-
- DisplayStringManager( void );
- virtual ~DisplayStringManager( void );
-
- virtual void init( void ) {} ///< initialize the factory
- virtual void reset( void ) {} ///< reset system
- virtual void update( void ) {}; ///< update anything we need to in our strings
-
- virtual DisplayString *newDisplayString( void ) = 0; ///< allocate new display string
- virtual void freeDisplayString( DisplayString *string ) = 0; ///< free string
-
- virtual DisplayString *getGroupNumeralString( Int numeral ) = 0;
- virtual DisplayString *getFormationLetterString( void ) = 0;
-protected:
-
- void link( DisplayString *string ); ///< link display string to list
- void unLink( DisplayString *string ); ///< unlink display string from list
-
- DisplayString *m_stringList; ///< list of all display strings
- DisplayString *m_currentCheckpoint; ///< current checkpoint of strings to be freed
-};
-
-// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
-extern DisplayStringManager *TheDisplayStringManager; ///< singleton extern
diff --git a/Generals/Code/GameEngine/Include/GameClient/DrawGroupInfo.h b/Generals/Code/GameEngine/Include/GameClient/DrawGroupInfo.h
deleted file mode 100644
index 0637bd8ec4b..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/DrawGroupInfo.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DrawGroupInfo.h //////////////////////////////////////////////////////////////////////////
-// AudioEventRTS structure
-// Author: John K. McDonald, March 2002
-
-#pragma once
-
-struct DrawGroupInfo
-{
- AsciiString m_fontName;
- Int m_fontSize;
- Bool m_fontIsBold;
-
- Bool m_usePlayerColor;
- Color m_colorForText;
- Color m_colorForTextDropShadow;
-
- Int m_dropShadowOffsetX;
- Int m_dropShadowOffsetY;
-
- union
- {
- Int m_pixelOffsetX;
- Real m_percentOffsetX;
- };
- Bool m_usingPixelOffsetX;
-
- union
- {
- Int m_pixelOffsetY;
- Real m_percentOffsetY;
- };
- Bool m_usingPixelOffsetY;
-
- DrawGroupInfo();
-
- static const FieldParse s_fieldParseTable[]; ///< the parse table for INI definition
- const FieldParse *getFieldParse( void ) const { return s_fieldParseTable; }
-};
-
-extern DrawGroupInfo *TheDrawGroupInfo;
diff --git a/Generals/Code/GameEngine/Include/GameClient/FXList.h b/Generals/Code/GameEngine/Include/GameClient/FXList.h
deleted file mode 100644
index 4d1204c19ea..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/FXList.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: FXList.h /////////////////////////////////////////////////////////////////////////////////
-// Author: Steven Johnson, December 2001
-// Desc: General Effects Descriptions
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "Common/GameMemory.h"
-#include "Common/NameKeyGenerator.h"
-#include "Common/STLTypedefs.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
-class FXNugget;
-class FXList;
-class FXListStore;
-class INI;
-class Object;
-class Matrix3D;
-
-//-------------------------------------------------------------------------------------------------
-/**
- An FXNugget encapsulates a particular type of audio/video effect. FXNuggets are virtually
- never used on their own, but rather, as a component of an FXList (see below).
-
- Important notes:
-
- -- FXNugget is an ABC; all the implementations are (currently) located in FXList.cpp,
- thought they will probably be spread out more as we add more implementations.
-
- -- As part of an FXList, an FXNugget is shared between multiple units. The implication is that
- an FXNugget should not require private data storage to do what it needs to do, aside from stuff
- initialized at FXNugget instantiation time (eg, parameters from an INI file). To help
- enforce this, all it's methods are declared 'const'. If you can't implement what you
- need within this framework, please *don't* simply de-const things, because it could lead to very
- strange side-effects. Instead, the system will have to be enhanced to allow for multiple instances
- of each FXNugget.
-
- -- an individual FXNugget is generally not directly accessible to anyone outside of the
- FXList system; in fact, it could probably be a private class, but isn't, mainly for coding convenience.
-
- -- Unlike most other game systems, FXNuggets can't be overridden by subsequent INI file
- loads. This isn't really a problem, because all you really need to do to "override" one is to
- specify a different one.
-*/
-class FXNugget : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_ABC(FXNugget)
-public:
-
- FXNugget() { }
- //virtual ~FXNugget() { }
-
- /**
- The main guts of the system: actually perform the sound and/or video effects
- needed. Note that primary and/or secondary can be null, so you must check for this.
- */
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx = nullptr, const Real primarySpeed = 0.0f, const Coord3D *secondary = nullptr, const Real overrideRadius = 0.0f) const = 0;
-
- /**
- the object-based version... by default, just call the location-based implementation.
- Note that primary and/or secondary can be null, so you must check for this.
- */
- virtual void doFXObj(const Object* primary, const Object* secondary = nullptr) const;
-
-private:
-
-};
-EMPTY_DTOR(FXNugget)
-
-//-------------------------------------------------------------------------------------------------
-/**
- An FXList is a way of encapsulating a particular set of audio/video effect(s).
- Lots of other game systems (eg, DamageFX) use FXLists to abstract AV effects into data files
- (rather than hardcoding them, which would be suboptimal).
-
- Important notes:
-
- -- an FXList is specified solely by name, and the only parameters it receives when performing
- its AV effects are a primary (and optional secondary) object position.
-
- -- There is no inheritance or overriding of FXLists; if you need an FXList that is nearly-but-not-quite
- identical to an existing one, you must simply make an entirely new FXList. Realistically, this shouldn't
- be a problem, since they are pretty simple to specify, and don't consume a lot of memory.
-
- -- an FXList is shared between multiple units. To help
- enforce this, all it's methods are declared 'const'. If you can't implement the stuff you
- need within this framework, please *don't* simply de-const things, because it could lead to very
- strange side-effects. Instead, the system will have to be enhanced to allow for multiple instances
- of each FXNugget.
-
- -- Unlike most other game systems, FXList can't be overridden by subsequent INI file
- loads. This isn't really a problem, because all you really need to do to "override" one is to
- specify a different one.
-*/
-class FXList
-{
-
-public:
-
- FXList();
- virtual ~FXList();
-
- /**
- Toss the contents.
- */
- void clear();
-
- /**
- add a nugget to the list. It belongs to the FXList, who is responsible for freeing it.
- */
- void addFXNugget(FXNugget *fxn)
- {
- m_nuggets.push_back(fxn);
- }
-
- /// inline convenience method to avoid having to check for null.
- inline static void doFXPos(const FXList* fx, const Coord3D *primary, const Matrix3D* primaryMtx = nullptr, const Real primarySpeed = 0.0f, const Coord3D *secondary = nullptr, const Real overrideRadius = 0.0f)
- {
- if (fx) fx->doFXPos(primary, primaryMtx, primarySpeed, secondary, overrideRadius);
- }
-
- /// inline convenience method to avoid having to check for null.
- inline static void doFXObj(const FXList* fx, const Object* primary, const Object* secondary = nullptr)
- {
- if (fx)
- {
- fx->doFXObj(primary, secondary);
-
- //if (fx->) // here we need to cal doFXRicochet, if fx calls for it
-
- }
-
- }
-
-
-
-protected:
-
-
- /**
- The main guts of the system: actually perform the sound and/or video effects
- needed. Note that primary and/or secondary can be null, so you must check for this.
- */
- void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx = nullptr, const Real primarySpeed = 0.0f, const Coord3D *secondary = nullptr, const Real overrideRadius = 0.0f) const;
-
- /**
- the object-based version... by default, just call the location-based implementation.
- Note that primary and/or secondary can be null, so you must check for this.
- */
- void doFXObj(const Object* primary, const Object* secondary = nullptr) const;
-
-private:
-
- typedef std::list< FXNugget* > FXNuggetList;
-
- FXNuggetList m_nuggets;
-
-};
-
-//-------------------------------------------------------------------------------------------------
-/**
- The "store" used to hold all the FXLists in existence.
-*/
-class FXListStore : public SubsystemInterface
-{
-
-public:
-
- FXListStore();
- ~FXListStore();
-
- void init() { }
- void reset() { }
- void update() { }
-
- /**
- return the FXList with the given namekey.
- return nullptr if no such FXList exists.
- */
- const FXList *findFXList( const char* name ) const;
-
- static void parseFXListDefinition(INI* ini);
-
-private:
-
- // use the hashing function for Ints.
- typedef std::hash_map< NameKeyType, FXList, rts::hash, rts::equal_to > FXListMap;
-
- FXListMap m_fxmap;
-
-};
-
-// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
-extern FXListStore *TheFXListStore;
diff --git a/Generals/Code/GameEngine/Include/GameClient/GameFont.h b/Generals/Code/GameEngine/Include/GameClient/GameFont.h
deleted file mode 100644
index 0119bcf2d8a..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GameFont.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameFont.h ///////////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, June 2001
-// Desc: Game representations for fonts
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/SubsystemInterface.h"
-#include "Lib/BaseType.h"
-#include "Common/AsciiString.h"
-#include "Common/GameMemory.h"
-
-//-------------------------------------------------------------------------------------------------
-/** A font for use in the device independent game */
-//-------------------------------------------------------------------------------------------------
-class GameFont : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameFont, "GameFont")
-public:
- GameFont* next; ///< for library use
- AsciiString nameString;
- Int pointSize; ///< point size of font
- Int height; ///< pixel height of font
- void* fontData; ///< font data to be filled out for device specific font
- Bool bold; ///< is this font bold
-};
-EMPTY_DTOR(GameFont)
-
-//-------------------------------------------------------------------------------------------------
-/** Interface to access fonts for the system */
-//-------------------------------------------------------------------------------------------------
-class FontLibrary : public SubsystemInterface
-{
-
-public:
-
-
-public:
-
- FontLibrary( void );
- virtual ~FontLibrary( void );
-
- virtual void init( void );
- virtual void reset( void );
- virtual void update( void ) { }
-
- GameFont *getFont( AsciiString name, Int pointSize, Bool bold ); ///< get a font pointer
-
- GameFont *firstFont( void ); ///< return first font
- GameFont *nextFont( GameFont *font ); ///< get next font in library
-
- Int getCount( void ); ///< return how many fonts are loaded in this lib
-
-protected:
-
- void deleteAllFonts( void ); ///< delete all fonts in this library
- void linkFont( GameFont *font ); ///< add to font list
- void unlinkFont( GameFont *font ); ///< remove font from list
-
- /// load the font data pointer based on everything else we already have set
- virtual Bool loadFontData( GameFont *font ) = 0;
- /// release the font data pointer
- virtual void releaseFontData( GameFont *font ) { };
-
- GameFont *m_fontList; ///< list of fonts we have loaded
- Int m_count; ///< number of unique fonts loaded in this lib
-
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////////////////////////
-inline Int FontLibrary::getCount( void ) { return m_count; }
-inline GameFont *FontLibrary::firstFont( void ) { return m_fontList; }
-inline GameFont *FontLibrary::nextFont( GameFont *font )
-{
- if( font )
- return font->next;
- return nullptr;
-}
-
-// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
-extern FontLibrary *TheFontLibrary; ///< font library external
diff --git a/Generals/Code/GameEngine/Include/GameClient/GameText.h b/Generals/Code/GameEngine/Include/GameClient/GameText.h
deleted file mode 100644
index bf8c94fb88c..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GameText.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-//----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//----------------------------------------------------------------------------
-//
-// Project: RTS 3
-//
-// File name: GameClient/GameText.h
-//
-// Created: 11/07/01
-//
-//----------------------------------------------------------------------------
-
-#pragma once
-
-//----------------------------------------------------------------------------
-// Includes
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Forward References
-//----------------------------------------------------------------------------
-
-class AsciiString;
-class UnicodeString;
-
-//----------------------------------------------------------------------------
-// Type Defines
-//----------------------------------------------------------------------------
-typedef std::vector AsciiStringVec;
-
-//===============================
-// GameTextInterface
-//===============================
-/** Game text interface object for localised text.
- */
-//===============================
-
-class GameTextInterface : public SubsystemInterface
-{
-
- public:
-
- virtual ~GameTextInterface() {};
-
- virtual UnicodeString fetch( const Char *label, Bool *exists = nullptr ) = 0; ///< Returns the associated labeled unicode text
- virtual UnicodeString fetch( AsciiString label, Bool *exists = nullptr ) = 0; ///< Returns the associated labeled unicode text ; TheSuperHackers @todo Remove
- virtual UnicodeString fetchFormat( const Char *label, ... ) = 0;
-
- // Do not call this directly, but use the FETCH_OR_SUBSTITUTE macro
- virtual UnicodeString fetchOrSubstitute( const Char *label, const WideChar *substituteText ) = 0;
- virtual UnicodeString fetchOrSubstituteFormat( const Char *label, const WideChar *substituteFormat, ... ) = 0;
- virtual UnicodeString fetchOrSubstituteFormatVA( const Char *label, const WideChar *substituteFormat, va_list args ) = 0;
-
- // This function is not performance tuned.. Its really only for Worldbuilder. jkmcd
- virtual AsciiStringVec& getStringsWithLabelPrefix(AsciiString label) = 0;
-
- virtual void initMapStringFile( const AsciiString& filename ) = 0;
-
-#if __cplusplus < 201103L // TheSuperHackers @todo Remove function when abandoning VC6
- inline UnicodeString FETCH_OR_SUBSTITUTE_FORMAT( const Char *label, const WideChar *substituteFormat, ... )
- {
- va_list args;
- va_start(args, substituteFormat);
- UnicodeString str = fetchOrSubstituteFormatVA(label, substituteFormat, args);
- va_end(args);
- return str;
- }
-#endif
-};
-
-
-extern GameTextInterface *TheGameText;
-extern GameTextInterface* CreateGameTextInterface( void );
-
-//----------------------------------------------------------------------------
-// Inlining
-//----------------------------------------------------------------------------
-
-// TheSuperHackers @info This is meant to be used like:
-// TheGameText->FETCH_OR_SUBSTITUTE("GUI:LabelName", L"Substitute Fallback Text")
-// TheGameText->FETCH_OR_SUBSTITUTE_FORMAT("GUI:LabelName", L"Substitute Fallback Text %d %d", 1, 2)
-// The substitute text will be compiled out if ENABLE_GAMETEXT_SUBSTITUTES is not defined.
-//
-// Note: ##__VA_ARGS__ handles zero variadic arguments by removing the preceding comma when empty.
-// Example: FETCH_OR_SUBSTITUTE_FORMAT("Label", L"Text") expands correctly without trailing comma.
-// Without ##, it would expand to fetchOrSubstituteFormat("Label", L"Text",) causing a syntax error.
-// This extension is widely supported (GCC, Clang, MSVC 2015+). C++20 __VA_OPT__ is the standard
-// alternative, but ##__VA_ARGS__ is simpler and compatible across C++11/14/17/20.
-#if ENABLE_GAMETEXT_SUBSTITUTES
-
-#define FETCH_OR_SUBSTITUTE(labelA, substituteTextW) fetchOrSubstitute(labelA, substituteTextW)
-#if __cplusplus >= 201103L // TheSuperHackers @todo Remove condition when abandoning VC6
-#define FETCH_OR_SUBSTITUTE_FORMAT(labelA, substituteFormatW, ...) fetchOrSubstituteFormat(labelA, substituteFormatW, ##__VA_ARGS__)
-#endif
-
-#else
-
-#define FETCH_OR_SUBSTITUTE(labelA, substituteTextW) fetch(labelA)
-#if __cplusplus >= 201103L // TheSuperHackers @todo Remove condition when abandoning VC6
-#define FETCH_OR_SUBSTITUTE_FORMAT(labelA, substituteFormatW, ...) fetchFormat(labelA, ##__VA_ARGS__)
-#endif
-
-#endif // ENABLE_GAMETEXT_SUBSTITUTES
diff --git a/Generals/Code/GameEngine/Include/GameClient/GameWindow.h b/Generals/Code/GameEngine/Include/GameClient/GameWindow.h
deleted file mode 100644
index faed99452bf..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GameWindow.h
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameWindow.h /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: GameWindow.h
-//
-// Created: Colin Day, June 2001
-//
-// Desc: Header for game windowing system for generic windows and GUI
-// elements
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "Common/GameMemory.h"
-#include "GameClient/Image.h"
-#include "GameClient/DisplayString.h"
-#include "GameClient/WinInstanceData.h"
-#include "GameClient/Color.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-class GameWindow;
-class WindowLayout;
-class GameFont;
-class TransitionWindow;
-struct GameWindowEditData;
-
-///////////////////////////////////////////////////////////////////////////////
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-enum { WIN_COLOR_UNDEFINED = GAME_COLOR_UNDEFINED };
-
-// WindowMsgData --------------------------------------------------------------
-//-----------------------------------------------------------------------------
-typedef UnsignedInt WindowMsgData;
-
-//-----------------------------------------------------------------------------
-enum WindowMsgHandledType CPP_11(: Int) { MSG_IGNORED, MSG_HANDLED };
-
-// callback types -------------------------------------------------------------
-typedef void (*GameWinMsgBoxFunc)( void ); //used for the Message box callbacks.
-typedef void (*GameWinDrawFunc)( GameWindow *,
- WinInstanceData * );
-typedef void (*GameWinTooltipFunc)( GameWindow *,
- WinInstanceData *,
- UnsignedInt );
-typedef WindowMsgHandledType (*GameWinInputFunc)( GameWindow *,
- UnsignedInt,
- WindowMsgData,
- WindowMsgData );
-typedef WindowMsgHandledType (*GameWinSystemFunc)( GameWindow *,
- UnsignedInt,
- WindowMsgData,
- WindowMsgData );
-
-enum
-{
-
- WIN_MAX_WINDOWS = 576,
- CURSOR_MOVE_TOL_SQ = 4,
- TOOLTIP_DELAY = 10,
- WIN_TOOLTIP_LEN = 64, // max length of tooltip text
-
-};
-
-// macros for easier conversion -----------------------------------------------
-#define SHORTTOLONG(a, b) ((UnsignedShort)(a) | ((UnsignedShort)(b) << 16))
-#define LOLONGTOSHORT(a) ((a) & 0x0000FFFF)
-#define HILONGTOSHORT(b) (((b) & 0xFFFF0000) >> 16)
-
-// Game window messages -------------------------------------------------------
-//-----------------------------------------------------------------------------
-enum GameWindowMessage CPP_11(: Int)
-{
-
- GWM_NONE = 0,
-
- GWM_CREATE, GWM_DESTROY,
- GWM_ACTIVATE, GWM_ENABLE,
- GWM_LEFT_DOWN, GWM_LEFT_UP,
- GWM_LEFT_DOUBLE_CLICK, GWM_LEFT_DRAG,
- GWM_MIDDLE_DOWN, GWM_MIDDLE_UP,
- GWM_MIDDLE_DOUBLE_CLICK, GWM_MIDDLE_DRAG,
- GWM_RIGHT_DOWN, GWM_RIGHT_UP,
- GWM_RIGHT_DOUBLE_CLICK, GWM_RIGHT_DRAG,
- GWM_MOUSE_ENTERING, GWM_MOUSE_LEAVING,
- GWM_WHEEL_UP, GWM_WHEEL_DOWN,
- GWM_CHAR, GWM_SCRIPT_CREATE,
- // note that GWM_MOUSE_POS is only actually propagated to windows if the static
- // sendMousePosMessages is set to true in the window manager file. See the
- // comment on the static declaration for additional info
- GWM_INPUT_FOCUS, GWM_MOUSE_POS,
- GWM_IME_CHAR, GWM_IME_STRING
-
-};
-
-// WinInputReturnCode ------------------------------------------------------
-/** These return codes are returned when after processing events through
- * the window system */
-//-----------------------------------------------------------------------------
-enum WinInputReturnCode CPP_11(: Int)
-{
- WIN_INPUT_NOT_USED = 0,
- WIN_INPUT_USED,
-};
-
-
-#define GWM_USER 32768
-
-// Window status flags --------------------------------------------------------
-//-----------------------------------------------------------------------------
-enum
-{
-
- // when you edit this, remember to edit WindowStatusNames[]
- WIN_STATUS_NONE = 0x00000000, // No status bits set at all
- WIN_STATUS_ACTIVE = 0x00000001, // At the top of the window list
- WIN_STATUS_TOGGLE = 0x00000002, // If set, click to toggle
- WIN_STATUS_DRAGGABLE = 0x00000004, // Window can be dragged
- WIN_STATUS_ENABLED = 0x00000008, // Window can receive input
- WIN_STATUS_HIDDEN = 0x00000010, // Window is hidden, no input
- WIN_STATUS_ABOVE = 0x00000020, // Window is always above others
- WIN_STATUS_BELOW = 0x00000040, // Window is always below others
- WIN_STATUS_IMAGE = 0x00000080, // Window is drawn with images
- WIN_STATUS_TAB_STOP = 0x00000100, // Window is a tab stop
- WIN_STATUS_NO_INPUT = 0x00000200, // Window does not take input
- WIN_STATUS_NO_FOCUS = 0x00000400, // Window does not take focus
- WIN_STATUS_DESTROYED = 0x00000800, // Window has been destroyed
- WIN_STATUS_BORDER = 0x00001000, // Window will be drawn with Borders & Corners
- WIN_STATUS_SMOOTH_TEXT = 0x00002000, // Window text will be drawn with smoothing
- WIN_STATUS_ONE_LINE = 0x00004000, // Window text will be drawn on only one line
- WIN_STATUS_NO_FLUSH = 0x00008000, // Window images will not be unloaded when window is hidden
- WIN_STATUS_SEE_THRU = 0x00010000, // Will not draw, but it NOT hidden ... does not apply to children
- WIN_STATUS_RIGHT_CLICK = 0x00020000, // Window pays attention to right clicks
- WIN_STATUS_WRAP_CENTERED = 0x00040000, // Text will be centered on each word wrap or \n
- WIN_STATUS_CHECK_LIKE = 0x00080000, // Make push buttons "check-like" with dual state
- WIN_STATUS_HOTKEY_TEXT = 0x00100000, // Make push buttons "check-like" with dual state
- WIN_STATUS_USE_OVERLAY_STATES = 0x00200000, // Push buttons will use the global automatic rendering overlay for disabled, hilited, and pushed.
- WIN_STATUS_NOT_READY = 0x00400000, // A disabled button that is available -- but not yet (power charge, fire delay).
- WIN_STATUS_FLASHING = 0x00800000, // Used for buttons that do cameo flashes.
- WIN_STATUS_ALWAYS_COLOR = 0x01000000, // Never render these buttons using greyscale renderer when button disabled.
- // when you edit this, remember to edit WindowStatusNames[]
-
-};
-
-
-// Message Box Button flags --------------------------------------------------------
-//-----------------------------------------------------------------------------
-enum
-{
- MSG_BOX_YES = 0x01, //Display the yes button
- MSG_BOX_NO = 0x02, //Display the No button
- MSG_BOX_OK = 0x08, //Display the Ok button
- MSG_BOX_CANCEL = 0x04, //Display the Cancel button
-};
-
-
-// WindowMessageBoxData ---------------------------------------------------------
-/** Data attached to each Message box window */
-//-----------------------------------------------------------------------------
-struct WindowMessageBoxData
-{
- GameWinMsgBoxFunc yesCallback; /// m_transitionWindows;
-
-};
-
-// TheSuperHackers @feature helmutbuhler 24/04/2025
-// GameWindow that does nothing. Used for Headless Mode.
-class GameWindowDummy : public GameWindow
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameWindowDummy, "GameWindowDummy")
-public:
- virtual void winDrawBorder() {}
- virtual void* winGetUserData(void) { return nullptr; }
-};
-
-// ModalWindow ----------------------------------------------------------------
-//-----------------------------------------------------------------------------
-class ModalWindow : public MemoryPoolObject
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ModalWindow, "ModalWindow" )
-public:
- GameWindow *window; // Pointer to Modal Window
- ModalWindow *next; // Next Window Pointer
-
-};
-EMPTY_DTOR(ModalWindow)
-
-// Errors returned by window functions
-enum
-{
-
- WIN_ERR_OK = 0, // No Error
- WIN_ERR_GENERAL_FAILURE = -1, // General library failure
- WIN_ERR_INVALID_WINDOW = -2, // Window parameter was invalid
- WIN_ERR_INVALID_PARAMETER = -3, // Parameter was invalid
- WIN_ERR_MOUSE_CAPTURED = -4, // Mouse already captured
- WIN_ERR_KEYBOARD_CAPTURED = -5, // Keyboard already captured
- WIN_ERR_OUT_OF_WINDOWS = -6 // Too many windows have been created
-
-};
-
-// Input capture/release flags
-enum
-{
-
- WIN_CAPTURE_MOUSE = 0x00000001, // capture mouse
- WIN_CAPTURE_KEYBOARD = 0x00000002, // capture keyboard
- WIN_CAPTURE_ALL = 0xFFFFFFFF, // capture keyboard and mouse
-
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
-extern void GameWinDefaultDraw( GameWindow *window,
- WinInstanceData *instData );
-extern WindowMsgHandledType GameWinDefaultSystem( GameWindow *window,
- UnsignedInt msg,
- WindowMsgData mData1,
- WindowMsgData mData2 );
-extern WindowMsgHandledType GameWinDefaultInput( GameWindow *window,
- UnsignedInt msg,
- WindowMsgData mData1,
- WindowMsgData mData2 );
-extern WindowMsgHandledType GameWinBlockInput( GameWindow *window,
- UnsignedInt msg,
- WindowMsgData mData1,
- WindowMsgData mData2 );
-extern void GameWinDefaultTooltip( GameWindow *window,
- WinInstanceData *instData,
- UnsignedInt mouse );
-
-extern const char *const WindowStatusNames[];
-extern const char *const WindowStyleNames[];
diff --git a/Generals/Code/GameEngine/Include/GameClient/GameWindowGlobal.h b/Generals/Code/GameEngine/Include/GameClient/GameWindowGlobal.h
deleted file mode 100644
index d27d107b9e7..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GameWindowGlobal.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameWindowGlobal.h ///////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: GameWindowGlobal.h
-//
-// Created: Colin Day, June 2001
-//
-// Desc: These are some global functions that every game using this
-// window system must implement for their current technology
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "GameClient/Image.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// EXTERNALS //////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngine/Include/GameClient/GameWindowTransitions.h b/Generals/Code/GameEngine/Include/GameClient/GameWindowTransitions.h
deleted file mode 100644
index fdff9dbaf48..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GameWindowTransitions.h
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameWindowTransitions.h /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Dec 2002
-//
-// Filename: GameWindowTransitions.h
-//
-// author: Chris Huybregts
-//
-// purpose:
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/GameCommon.h"
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class GameWindow;
-class Image;
-class DisplayString;
-//-----------------------------------------------------------------------------
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-enum
-{
-TRANSITION_FLASH = 0,
-BUTTON_TRANSITION_FLASH,
-WIN_FADE_TRANSITION,
-WIN_SCALE_UP_TRANSITION,
-MAINMENU_SCALE_UP_TRANSITION,
-TEXT_TYPE_TRANSITION,
-SCREEN_FADE_TRANSITION,
-COUNT_UP_TRANSITION,
-FULL_FADE_TRANSITION,
-TEXT_ON_FRAME_TRANSITION,
-MAINMENU_MEDIUM_SCALE_UP_TRANSITION,
-MAINMENU_SMALL_SCALE_DOWN_TRANSITION,
-CONTROL_BAR_ARROW_TRANSITION,
-SCORE_SCALE_UP_TRANSITION,
-REVERSE_SOUND_TRANSITION,
-
-MAX_TRANSITION_WINDOW_STYLES
-};
-
-static const LookupListRec TransitionStyleNames[] =
-{
- { "FLASH", TRANSITION_FLASH },
- { "BUTTONFLASH", BUTTON_TRANSITION_FLASH },
- { "WINFADE", WIN_FADE_TRANSITION },
- { "WINSCALEUP", WIN_SCALE_UP_TRANSITION },
- { "MAINMENUSCALEUP", MAINMENU_SCALE_UP_TRANSITION },
- { "TYPETEXT", TEXT_TYPE_TRANSITION },
- { "SCREENFADE", SCREEN_FADE_TRANSITION },
- { "COUNTUP", COUNT_UP_TRANSITION },
- { "FULLFADE", FULL_FADE_TRANSITION },
- { "TEXTONFRAME", TEXT_ON_FRAME_TRANSITION },
- { "MAINMENUMEDIUMSCALEUP", MAINMENU_MEDIUM_SCALE_UP_TRANSITION },
- { "MAINMENUSMALLSCALEDOWN", MAINMENU_SMALL_SCALE_DOWN_TRANSITION },
- { "CONTROLBARARROW", CONTROL_BAR_ARROW_TRANSITION },
- { "SCORESCALEUP", SCORE_SCALE_UP_TRANSITION },
- { "REVERSESOUND", REVERSE_SOUND_TRANSITION },
- { nullptr, 0 }
-};
-static_assert(ARRAY_SIZE(TransitionStyleNames) == MAX_TRANSITION_WINDOW_STYLES + 1, "Incorrect array size");
-
-// base class for the transitions
-// inherit off of this adding in all the values
-class Transition
-{
-public:
- Transition ( void );
- virtual ~Transition( void );
-
- virtual void init( GameWindow *win ) = 0;
- virtual void update( Int frame ) = 0;
- virtual void reverse( void ) = 0;
- virtual void draw( void ) = 0;
-
- virtual void skip( void ) = 0;
-
- void unlinkGameWindow(GameWindow* win) { if ( m_win == win ) m_win = nullptr; }
- Bool isFinished( void ) { return m_isFinished; }
- Int getFrameLength( void ){ return m_frameLength; }
-protected:
-
- Int m_frameLength; // how many frames does this thing take.
- Bool m_isFinished; // when we finish we set this
- Bool m_isForward;
- Bool m_isReversed; // when we reverse we set this
- GameWindow *m_win;
-};
-
-//-----------------------------------------------------------------------------
-class TextOnFrameTransition : public Transition
-{
-public:
- TextOnFrameTransition ( void );
- virtual ~TextOnFrameTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- TEXTONFRAMETRANSITION_START = 0,
- TEXTONFRAMETRANSITION_END = 1 // Max text type we'll allow.
- };
-
-};
-
-//-----------------------------------------------------------------------------
-class ReverseSoundTransition : public Transition
-{
-public:
- ReverseSoundTransition ( void );
- virtual ~ReverseSoundTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- REVERSESOUNDTRANSITION_START = 0,
- REVERSESOUNDTRANSITION_FIRESOUND = 1,
- REVERSESOUNDTRANSITION_END = 2 // Max text type we'll allow.
- };
-
-};
-
-//-----------------------------------------------------------------------------
-class FullFadeTransition : public Transition
-{
-public:
- FullFadeTransition ( void );
- virtual ~FullFadeTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- FULLFADETRANSITION_START = 0,
- FULLFADETRANSITION_END = 10 // Max text type we'll allow.
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Real m_percent;
- Int m_drawState;
-
-};
-//-----------------------------------------------------------------------------
-class ControlBarArrowTransition : public Transition
-{
-public:
- ControlBarArrowTransition ( void );
- virtual ~ControlBarArrowTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- CONTROLBARARROWTRANSITION_START = 0,
- CONTROLBARARROWTRANSITION_BEGIN_FADE = 16,
- CONTROLBARARROWTRANSITION_END = 22 // Max text type we'll allow.
- };
- ICoord2D m_pos;
- ICoord2D m_incrementPos;
- ICoord2D m_size;
- Real m_percent;
- Real m_fadePercent;
- Int m_drawState;
- const Image* m_arrowImage;
-
-};
-//-----------------------------------------------------------------------------
-class ScreenFadeTransition : public Transition
-{
-public:
- ScreenFadeTransition ( void );
- virtual ~ScreenFadeTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- SCREENFADETRANSITION_START = 0,
- SCREENFADETRANSITION_END = 30 // Max text type we'll allow.
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Real m_percent;
- Int m_drawState;
-
-};
-//-----------------------------------------------------------------------------
-class CountUpTransition : public Transition
-{
-public:
- CountUpTransition ( void );
- virtual ~CountUpTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- COUNTUPTRANSITION_START = 0,
- COUNTUPTRANSITION_END = 30 // Max text type we'll allow.
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- UnicodeString m_fullText;
- UnicodeString m_partialText;
- Int m_intValue;
- Int m_currentValue;
- enum{
- COUNT_ONES = 1,
- COUNT_100S = 100,
- COUNT_1000S = 1000
- };
- Int m_countState;
-};
-
-//-----------------------------------------------------------------------------
-class TextTypeTransition : public Transition
-{
-public:
- TextTypeTransition ( void );
- virtual ~TextTypeTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- TEXTTYPETRANSITION_START = 0,
- TEXTTYPETRANSITION_END = 30 // Max text type we'll allow.
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- UnicodeString m_fullText;
- UnicodeString m_partialText;
- DisplayString *m_dStr;
-};
-
-//-----------------------------------------------------------------------------
-class MainMenuScaleUpTransition : public Transition
-{
-public:
- MainMenuScaleUpTransition ( void );
- virtual ~MainMenuScaleUpTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- MAINMENUSCALEUPTRANSITION_START = 0,
- MAINMENUSCALEUPTRANSITION_END = 5
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- ICoord2D m_growPos;
- ICoord2D m_growSize;
- ICoord2D m_incrementPos;
- ICoord2D m_incrementSize;
- GameWindow *m_growWin;
-};
-
-
-//-----------------------------------------------------------------------------
-class MainMenuMediumScaleUpTransition : public Transition
-{
-public:
- MainMenuMediumScaleUpTransition ( void );
- virtual ~MainMenuMediumScaleUpTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- MAINMENUMEDIUMSCALEUPTRANSITION_START = 0,
- MAINMENUMEDIUMSCALEUPTRANSITION_END = 3
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- ICoord2D m_growPos;
- ICoord2D m_growSize;
- ICoord2D m_incrementSize;
- GameWindow *m_growWin;
-};
-
-//-----------------------------------------------------------------------------
-class MainMenuSmallScaleDownTransition : public Transition
-{
-public:
- MainMenuSmallScaleDownTransition ( void );
- virtual ~MainMenuSmallScaleDownTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- MAINMENUSMALLSCALEDOWNTRANSITION_START = 0,
- MAINMENUSMALLSCALEDOWNTRANSITION_1 = 1,
- MAINMENUSMALLSCALEDOWNTRANSITION_2 = 2,
- MAINMENUSMALLSCALEDOWNTRANSITION_3 = 3,
- MAINMENUSMALLSCALEDOWNTRANSITION_4 = 4,
- MAINMENUSMALLSCALEDOWNTRANSITION_5 = 5,
- MAINMENUSMALLSCALEDOWNTRANSITION_END
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- ICoord2D m_growPos;
- ICoord2D m_growSize;
- ICoord2D m_incrementSize;
- GameWindow *m_growWin;
-};
-
-//-----------------------------------------------------------------------------
-class ScaleUpTransition : public Transition
-{
-public:
- ScaleUpTransition ( void );
- virtual ~ScaleUpTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- SCALEUPTRANSITION_START = 0,
- SCALEUPTRANSITION_1 = 1,
- SCALEUPTRANSITION_2 = 2,
- SCALEUPTRANSITION_3 = 3,
- SCALEUPTRANSITION_4 = 4,
- SCALEUPTRANSITION_5 = 5,
-// SCALEUPTRANSITION_6 = 6,
-// SCALEUPTRANSITION_7 = 7,
-// SCALEUPTRANSITION_8 = 8,
-// SCALEUPTRANSITION_9 = 9,
-// SCALEUPTRANSITION_10 = 10,
-// SCALEUPTRANSITION_11 = 11,
-// SCALEUPTRANSITION_12 = 12,
-// SCALEUPTRANSITION_13 = 13,
-// SCALEUPTRANSITION_14 = 14,
-// SCALEUPTRANSITION_15 = 15,
-// SCALEUPTRANSITION_16 = 16,
-// SCALEUPTRANSITION_17 = 17,
-// SCALEUPTRANSITION_18 = 18,
-// SCALEUPTRANSITION_19 = 19,
- SCALEUPTRANSITION_END
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- ICoord2D m_centerPos;
- ICoord2D m_incrementSize;
-};
-
-//-----------------------------------------------------------------------------
-class ScoreScaleUpTransition : public Transition
-{
-public:
- ScoreScaleUpTransition ( void );
- virtual ~ScoreScaleUpTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- SCORESCALEUPTRANSITION_START = 0,
- SCORESCALEUPTRANSITION_1 = 1,
- SCORESCALEUPTRANSITION_2 = 2,
- SCORESCALEUPTRANSITION_3 = 3,
- SCORESCALEUPTRANSITION_4 = 4,
- SCORESCALEUPTRANSITION_5 = 5,
-
- SCORESCALEUPTRANSITION_END
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- ICoord2D m_centerPos;
- ICoord2D m_incrementSize;
-};
-
-//-----------------------------------------------------------------------------
-
-
-class FadeTransition : public Transition
-{
-public:
- FadeTransition ( void );
- virtual ~FadeTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- FADETRANSITION_START = 0,
- FADETRANSITION_FADE_IN_1 = 1,
- FADETRANSITION_FADE_IN_2 = 2,
- FADETRANSITION_FADE_IN_3 = 3,
- FADETRANSITION_FADE_IN_4 = 4,
- FADETRANSITION_FADE_IN_5 = 5,
- FADETRANSITION_FADE_IN_6 = 6,
- FADETRANSITION_FADE_IN_7 = 7,
- FADETRANSITION_FADE_IN_8 = 8,
- FADETRANSITION_FADE_IN_9 = 9,
- FADETRANSITION_END
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
-};
-
-
-//-----------------------------------------------------------------------------
-
-class FlashTransition : public Transition
-{
-public:
- FlashTransition ( void );
- virtual ~FlashTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- FLASHTRANSITION_START = 0,
- FLASHTRANSITION_FADE_IN_1 = 1,
- FLASHTRANSITION_FADE_IN_2 = 2,
- FLASHTRANSITION_FADE_IN_3 = 3,
- FLASHTRANSITION_FADE_TO_BACKGROUND_1 = 4,
- FLASHTRANSITION_FADE_TO_BACKGROUND_2 = 5,
- FLASHTRANSITION_FADE_TO_BACKGROUND_3 = 6,
- FLASHTRANSITION_FADE_TO_BACKGROUND_4 = 7,
- FLASHTRANSITION_END
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
-};
-
-//-----------------------------------------------------------------------------
-class ButtonFlashTransition : public Transition
-{
-public:
- ButtonFlashTransition ( void );
- virtual ~ButtonFlashTransition( void );
-
- virtual void init( GameWindow *win );
- virtual void update( Int frame );
- virtual void reverse( void );
- virtual void draw( void );
-
- virtual void skip( void );
-
-protected:
- enum{
- BUTTONFLASHTRANSITION_START = 0,
- BUTTONFLASHTRANSITION_FADE_IN_1 = 1,
- BUTTONFLASHTRANSITION_FADE_IN_2 = 2,
- BUTTONFLASHTRANSITION_FADE_IN_3 = 3,
- BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_1 =4,
- BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_2 = 5,
- BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_3 = 6,
- BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_4 = 7,
- BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1 = 11,
- BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_2 = BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1 +1,
- BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_1 = BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_2 +1,
- BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_2 = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_1 +1,
- BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_3 = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_2 +1,
- BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_4 = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_3 + 1,
- BUTTONFLASHTRANSITION_END, // this is the end of the sequence, we need some special defines... well put them below here
- BUTTONFLASHTRANSITION_SHOW_BACKGROUND
- };
- ICoord2D m_pos;
- ICoord2D m_size;
- Int m_drawState;
- Image *m_gradient;
-};
-
-//-----------------------------------------------------------------------------
-class TransitionWindow
-{
-public:
- TransitionWindow( void );
- ~TransitionWindow( void );
-
- Bool init( void );
- void update( Int frame );
- Bool isFinished( void );
- void reverse( Int totalFrames );
- Int getTotalFrames( void );
- void skip( void );
- void draw( void );
-
- void unlinkGameWindow( GameWindow* win );
-
-// INI parsed vars
- AsciiString m_winName;
- Int m_frameDelay; // what frame number we start on
- Int m_style; // the style we'll be using
-
-// standard vars
- NameKeyType m_winID;
- GameWindow *m_win;
- Transition *m_transition; // each window is allowed one trasition
- Int m_currentFrameDelay; // this will change based on if we're going forward or backwards
-};
-
-//-----------------------------------------------------------------------------
-class TransitionGroup
-{
-public:
- TransitionGroup( void );
- ~TransitionGroup( void );
-
- void init( void );
- void update( void );
- Bool isFinished( void );
- void reverse( void );
- void draw( void );
-
- void skip ( void );
- AsciiString getName( void ) { return m_name; }
- void setName( AsciiString name){ m_name = name; }
- void addWindow( TransitionWindow *transWin );
- Bool isReversed( void );
- Bool isFireOnce( void ) { return m_fireOnce; }
- Bool m_fireOnce;
-private:
- typedef std::list TransitionWindowList;
- TransitionWindowList m_transitionWindowList;
- Int m_directionMultiplier;
- Int m_currentFrame; ///< maintain how long we've spent on this transition;
- AsciiString m_name;
-};
-
-//-----------------------------------------------------------------------------
-class GameWindowTransitionsHandler: public SubsystemInterface
-{
-public:
- GameWindowTransitionsHandler(void);
- ~GameWindowTransitionsHandler( void );
-
- void init(void );
- void load(void );
- void reset( void );
- void update( void );
- void draw( void );
- Bool isFinished( void );
- const FieldParse *getFieldParse() const { return m_gameWindowTransitionsFieldParseTable; } ///< returns the parsing fields
- static const FieldParse m_gameWindowTransitionsFieldParseTable[]; ///< the parse table
- static void parseWindow( INI* ini, void *instance, void *store, const void *userData );
-
- void setGroup(AsciiString groupName, Bool immediate = FALSE); // THis will be the next group to fire off.
- void reverse( AsciiString groupName );// reverse the animations for the current group.
- void remove( AsciiString groupName, Bool skipPending = FALSE );// remove the animation from the current or pending groups.
- TransitionGroup *getNewGroup( AsciiString name );
-private:
- TransitionGroup *findGroup( AsciiString groupName );
- typedef std::list TransitionGroupList;
- TransitionGroupList m_transitionGroupList;
- TransitionGroup *m_currentGroup;
- TransitionGroup *m_pendingGroup;
- TransitionGroup *m_drawGroup;
- TransitionGroup *m_secondaryDrawGroup; // needed to draw the last frame of the previvous draw group once more.
-};
-
-void PushButtonImageDrawThree(GameWindow *window, Int alpha );
-
-
-//-----------------------------------------------------------------------------
-// INLINING ///////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// EXTERNALS //////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-extern GameWindowTransitionsHandler *TheTransitionHandler;
diff --git a/Generals/Code/GameEngine/Include/GameClient/GlobalLanguage.h b/Generals/Code/GameEngine/Include/GameClient/GlobalLanguage.h
deleted file mode 100644
index 9ceb7abe0fa..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GlobalLanguage.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GlobalLanguage.h /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Aug 2002
-//
-// Filename: GlobalLanguage.h
-//
-// author: Chris Huybregts
-//
-// purpose: With workingwith different languages, we need some options that
-// change. Essentially, this is the global data that's unique to languages
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "Common/SubsystemInterface.h"
-#include "Common/STLTypedefs.h"
-#include "GameClient/FontDesc.h"
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class AsciiString;
-//-----------------------------------------------------------------------------
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class GlobalLanguage : public SubsystemInterface
-{
-public:
-
- enum ResolutionFontSizeMethod
- {
- ResolutionFontSizeMethod_Classic, // Uses the original scaling method. Scales poorly on wide screens and large resolutions.
- ResolutionFontSizeMethod_ClassicNoCeiling, // Uses the original scaling method, but without ceiling. Works ok for the original Game UI and with large resolutions. Scales poorly on very wide screens.
- ResolutionFontSizeMethod_Strict, // Uses a strict scaling method. Width and height are strictly bounded on upscales. Works well for accurate UI layouts and with large resolutions.
- ResolutionFontSizeMethod_Balanced, // Uses a balanced scaling method. Width and height are evenly weighted for upscales. Works well for the original Game UI and with large resolutions.
-
- ResolutionFontSizeMethod_Default = ResolutionFontSizeMethod_ClassicNoCeiling,
- };
-
-public:
-
- GlobalLanguage();
- virtual ~GlobalLanguage();
-
- void init();
- void reset();
- void update() { }
-
- AsciiString m_unicodeFontName;
- AsciiString m_unicodeFontFileName;
- Bool m_useHardWrap;
- Int m_militaryCaptionSpeed;
- FontDesc m_copyrightFont;
- FontDesc m_messageFont;
- FontDesc m_militaryCaptionTitleFont;
- FontDesc m_militaryCaptionFont;
- FontDesc m_superweaponCountdownNormalFont;
- FontDesc m_superweaponCountdownReadyFont;
- FontDesc m_namedTimerCountdownNormalFont;
- FontDesc m_namedTimerCountdownReadyFont;
- FontDesc m_drawableCaptionFont;
- FontDesc m_defaultWindowFont;
- FontDesc m_defaultDisplayStringFont;
- FontDesc m_tooltipFontName;
- FontDesc m_nativeDebugDisplay;
- FontDesc m_drawGroupInfoFont;
- FontDesc m_creditsTitleFont;
- FontDesc m_creditsPositionFont;
- FontDesc m_creditsNormalFont;
- Real m_resolutionFontSizeAdjustment;
- Real m_userResolutionFontSizeAdjustment;
- ResolutionFontSizeMethod m_resolutionFontSizeMethod;
-
- float getResolutionFontSizeAdjustment() const;
- Int adjustFontSize(Int theFontSize); // Adjusts font size for resolution. jba.
-
- void parseCustomDefinition();
-
- typedef std::list StringList; // Used for our font file names that we want to load
- typedef StringList::iterator StringListIt;
-
- StringList m_localFonts; // List of the font filenames that are in our local directory
- static void parseFontFileName( INI *ini, void *instance, void *store, const void* userData );
- static void parseFontDesc(INI *ini, void *instance, void *store, const void* userData);
-};
-//-----------------------------------------------------------------------------
-// INLINING ///////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// EXTERNALS //////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-extern GlobalLanguage *TheGlobalLanguageData;
diff --git a/Generals/Code/GameEngine/Include/GameClient/GraphDraw.h b/Generals/Code/GameEngine/Include/GameClient/GraphDraw.h
deleted file mode 100644
index 97cc938851b..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/GraphDraw.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GraphDraw.h //////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Aug 2002
-//
-// Filename: GraphDraw.h
-//
-// author: John McDonald
-//
-// purpose: Contains the functions to queue up and display a single graph for
-// each frame. Note: This class is presently only intended for use by
-// the Performance timers, all though it could be easily adapted for
-// other purposes.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/PerfTimer.h"
-#include "Common/STLTypedefs.h"
-
-#ifdef PERF_TIMERS
-
-typedef std::pair PairAsciiStringReal;
-typedef std::vector VecGraphEntries;
-typedef VecGraphEntries::iterator VecGraphEntriesIt;
-
-enum { MAX_GRAPH_VALUES = 36 };
-enum { BAR_HEIGHT = 14 };
-enum { BAR_SPACE = 2 };
-
-class DisplayString;
-
-class GraphDraw
-{
- public:
- GraphDraw();
- virtual ~GraphDraw();
-
- void addEntry(AsciiString str, Real val);
- // Called during begin/end
- void render();
- void clear();
-
- protected:
- VecGraphEntries m_graphEntries;
- DisplayString *m_displayStrings[MAX_GRAPH_VALUES];
-};
-
-extern GraphDraw *TheGraphDraw;
-
-
-#endif /* PERF_TIMERS */
diff --git a/Generals/Code/GameEngine/Include/GameClient/HeaderTemplate.h b/Generals/Code/GameEngine/Include/GameClient/HeaderTemplate.h
deleted file mode 100644
index edeec5a3c45..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/HeaderTemplate.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: HeaderTemplate.h /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Aug 2002
-//
-// Filename: HeaderTemplate.h
-//
-// author: Chris Huybregts
-//
-// purpose:
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "Common/STLTypedefs.h"
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "Common/AsciiString.h"
-//-----------------------------------------------------------------------------
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class GameFont;
-struct FieldParse;
-class INI;
-//-----------------------------------------------------------------------------
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-class HeaderTemplate
-{
-public:
- HeaderTemplate( void );
- ~HeaderTemplate( void );
-
- GameFont *m_font;
- AsciiString m_name;
- AsciiString m_fontName;
- Int m_point;
- Bool m_bold;
-
-};
-
-class HeaderTemplateManager
-{
-public:
- HeaderTemplateManager( void );
- ~HeaderTemplateManager( void );
-
- void init( void );
-
- const FieldParse *getFieldParse( void ) const { return m_headerFieldParseTable; } ///< Return the field parse info
- static const FieldParse m_headerFieldParseTable[];
-
- HeaderTemplate *findHeaderTemplate( AsciiString name );
- HeaderTemplate *newHeaderTemplate( AsciiString name );
-
- GameFont *getFontFromTemplate( AsciiString name );
- HeaderTemplate *getFirstHeader( void );
- HeaderTemplate *getNextHeader( HeaderTemplate *ht );
-
- void onResolutionChanged(void);
-
-private:
- void populateGameFonts( void );
- typedef std::list< HeaderTemplate* > HeaderTemplateList;
- typedef HeaderTemplateList::iterator HeaderTemplateListIt;
- HeaderTemplateList m_headerTemplateList;
-
-};
-
-
-//-----------------------------------------------------------------------------
-// INLINING ///////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// EXTERNALS //////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-extern HeaderTemplateManager *TheHeaderTemplateManager;
diff --git a/Generals/Code/GameEngine/Include/GameClient/IMEManager.h b/Generals/Code/GameEngine/Include/GameClient/IMEManager.h
deleted file mode 100644
index 4b304ed2953..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/IMEManager.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-//----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//----------------------------------------------------------------------------
-//
-// Project: Generals
-//
-// Module: IME
-//
-// File name: GameClient/IMEManager.h
-//
-// Created: 11/14/01 TR
-//
-//----------------------------------------------------------------------------
-
-#pragma once
-
-//----------------------------------------------------------------------------
-// Includes
-//----------------------------------------------------------------------------
-
-#include "Lib/BaseType.h"
-#include "Common/SubsystemInterface.h"
-#include "Common/UnicodeString.h"
-
-//----------------------------------------------------------------------------
-// Forward References
-//----------------------------------------------------------------------------
-
-class GameWindow;
-class UnicodeString;
-
-//----------------------------------------------------------------------------
-// Type Defines
-//----------------------------------------------------------------------------
-
-
-//===============================
-// IMEManagerInterface
-//===============================
-
-class IMEManagerInterface : public SubsystemInterface
-{
-
- public:
-
- virtual ~IMEManagerInterface() {};
-
- virtual void attach( GameWindow *window ) = 0; ///< attach IME to specified window
- virtual void detach( void ) = 0; ///< detach IME from current window
- virtual void enable( void ) = 0; ///< Enable IME
- virtual void disable( void ) = 0; ///< Disable IME
- virtual Bool isEnabled( void ) = 0; ///< Is IME enabled
- virtual Bool isAttachedTo( GameWindow *window ) = 0; ///< Is the manager currently attached to the window
- virtual GameWindow* getWindow( void ) = 0; ///< Returns the window we are currently attached to
- virtual Bool isComposing( void ) = 0; ///< Manager is currently composing new input string
- virtual void getCompositionString( UnicodeString &string ) = 0; ///< Return the current composition string
- virtual Int getCompositionCursorPosition( void ) =0; ///< Returns the composition cursor position
- virtual Int getIndexBase( void ) = 0; ///< Get index base for candidate list
-
-
- virtual Int getCandidateCount() = 0; ///< Returns the total number of candidates
- virtual const UnicodeString* getCandidate( Int index ) = 0; ///< Returns the candidate string
- virtual Int getSelectedCandidateIndex() = 0; ///< Returns the indexed of the currently selected candidate
- virtual Int getCandidatePageSize() = 0; ///< Returns the page size for the candidates list
- virtual Int getCandidatePageStart() = 0; ///< Returns the index of the first visibel candidate
-
-
-
- /// Checks for and service IME messages. Returns TRUE if message serviced
- virtual Bool serviceIMEMessage( void *windowsHandle,
- UnsignedInt message,
- Int wParam,
- Int lParam ) = 0;
- virtual Int result( void ) = 0; ///< result return value of last serviced IME message
-};
-
-
-extern IMEManagerInterface *TheIMEManager;
-extern IMEManagerInterface *CreateIMEManagerInterface( void );
-
-
-//----------------------------------------------------------------------------
-// Inlining
-//----------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Include/GameClient/Keyboard.h b/Generals/Code/GameEngine/Include/GameClient/Keyboard.h
deleted file mode 100644
index 86452c43e97..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/Keyboard.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Keyboard.h ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Keyboard.h
-//
-// Created: Mike Morrison, 1995
-// Colin Day, June 2001
-//
-// Desc: Basic keyboard
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Common/SubsystemInterface.h"
-#include "GameClient/KeyDefs.h"
-#include "Lib/BaseType.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// TYPE DEFINITIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-// KeyboardIO -----------------------------------------------------------------
-/** Holds a single keyboard event */
-//-----------------------------------------------------------------------------
-struct KeyboardIO
-{
-
- enum StatusType CPP_11(: UnsignedByte)
- {
- STATUS_UNUSED = 0x00, // Key has not been used
- STATUS_USED = 0x01 // Key has been eaten
- };
-
- void setUsed() { status = STATUS_USED; }
-
- UnsignedByte key; // KeyDefType, key data
- UnsignedByte status; // StatusType, above
- UnsignedShort state; // KEY_STATE_* in KeyDefs.h
- UnsignedInt keyDownTimeMsec; // real-time in milliseconds when key went down
-
-};
-
-// class Keyboard =============================================================
-/** Keyboard singleton to interface with the keyboard */
-//=============================================================================
-class Keyboard : public SubsystemInterface
-{
-
- enum
- {
- KEY_REPEAT_DELAY_MSEC = 333, // 10 frames at 30 FPS
- KEY_REPEAT_INTERVAL_MSEC = 67 // ~2 frames at 30 FPS
- };
-
-public:
-
- Keyboard( void );
- virtual ~Keyboard( void );
-
- // you may extend the functionality of these for your device
- virtual void init( void ); /**< initialize the keyboard, only extend this
- functionality, do not replace */
- virtual void reset( void ); ///< Reset keyboard system
- virtual void update( void ); /**< gather current state of all keys, extend
- this functionality, do not replace */
- virtual Bool getCapsState( void ) = 0; ///< get state of caps lock key, return TRUE if down
-
- virtual void createStreamMessages( void ); /**< given state of device, create
- messages and put them on the
- stream for the raw state. */
- // simplified versions where the caller doesn't care which key type was pressed.
- Bool isShift();
- Bool isCtrl();
- Bool isAlt();
- Int getModifierFlags() { return m_modifiers; }
-
- // access methods for key data
- void resetKeys( void ); ///< reset the state of the keys
- KeyboardIO *getFirstKey( void ); ///< get first key ready for processing
- KeyboardIO *findKey( KeyDefType key, KeyboardIO::StatusType status ); ///< get key ready for processing, can return nullptr
- void setKeyStatusData( KeyDefType key,
- KeyboardIO::StatusType data ); ///< set key status
- WideChar translateKey( WideChar keyCode ); ///< translate key code to printable UNICODE char
- WideChar getPrintableKey( KeyDefType key, Int state );
- enum { MAX_KEY_STATES = 3};
-private:
- void refreshAltKeys() const; ///< refresh the state of the alt keys, necessary after alt tab
-protected:
-
- /** get the key data for a single key, KEY_NONE should be returned when
- no key data is available to get anymore, you must implement this for your device */
- virtual void getKey( KeyboardIO *key ) = 0;
-
- // internal methods to update the key states
- void initKeyNames( void ); ///< initialize the key names table
- void updateKeys( void ); ///< update the state of our key data
- Bool checkKeyRepeat( void ); ///< check for repeating keys
- UnsignedByte getKeyStatusData( KeyDefType key ); ///< get key status
- Bool getKeyStateBit( KeyDefType key, Int bit ); ///< get key state bit
- void setKeyStateData( KeyDefType key, UnsignedByte data ); ///< get key state
-
- UnsignedShort m_modifiers;
- // internal keyboard data members
- //Bool m_capsState; // 1 if caps lock is on
- //Bool m_shiftState; // 1 if either shift key is pressed
- //Bool m_shift2State; // 1 if secondary shift key is pressed
- //Bool m_lShiftState; // 1 if left state is down
- //Bool m_rShiftState; // 1 if right shift is down
- //Bool m_lControlState; // 1 if left control is down
- //Bool m_rControlState; // 1 if right control is down
- //Bool m_lAltState; // 1 if left alt is down
- //Bool m_rAltState; // 1 if right alt is down
- KeyDefType m_shift2Key; // what key is the secondary shift key
-
- enum { NUM_KEYS = 256 };
- KeyboardIO m_keys[ NUM_KEYS ]; ///< the keys
- KeyboardIO m_keyStatus[ KEY_COUNT ]; ///< the key status flags
-
- struct
- {
-
- WideChar stdKey;
- WideChar shifted;
- WideChar shifted2;
-
- } m_keyNames[ KEY_COUNT ];
-
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
-extern Keyboard *TheKeyboard;
diff --git a/Generals/Code/GameEngine/Include/GameClient/LanguageFilter.h b/Generals/Code/GameEngine/Include/GameClient/LanguageFilter.h
deleted file mode 100644
index da533ce974d..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/LanguageFilter.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/STLTypedefs.h"
-#include "Common/AsciiString.h"
-#include "Common/UnicodeString.h"
-
-class File;
-
-struct AsciiStringLessThan
-{
- Bool operator()(AsciiString a, AsciiString b) const
- {
- return (a.compareNoCase(b) < 0);
- }
-};
-
-struct UnicodeStringLessThan
-{
- Bool operator()(UnicodeString a, UnicodeString b) const
- {
- return (a.compareNoCase(b) < 0);
- }
-};
-
-struct UnicodeStringsEqual
-{
- Bool operator()(UnicodeString a, UnicodeString b) const
- {
- Bool retval = (a.compareNoCase(b) == 0);
- DEBUG_LOG(("Comparing %ls with %ls, return value is %s.", a.str(), b.str(), retval ? "true" : "false"));
- return retval;
- }
-};
-
-typedef std::map LangMap;
-typedef std::map::iterator LangMapIter;
-
-static const int LANGUAGE_XOR_KEY = 0x5555;
-static const char BadWordFileName[] = "langdata.dat";
-
-class LanguageFilter : public SubsystemInterface {
-public:
- LanguageFilter();
- ~LanguageFilter();
-
- void init();
- void reset();
- void update();
- void filterLine(UnicodeString &line);
-
-protected:
- Bool readWord(File *file1, WideChar *buf);
- void unHaxor(UnicodeString &word);
- LangMap m_wordList;
- LangMap m_subWordList;
-};
-
-extern LanguageFilter *TheLanguageFilter;
-LanguageFilter * createLanguageFilter();
diff --git a/Generals/Code/GameEngine/Include/GameClient/Line2D.h b/Generals/Code/GameEngine/Include/GameClient/Line2D.h
deleted file mode 100644
index e212d4b2b07..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/Line2D.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Line2D.h /////////////////////////////////////////////////////////////////////////////////
-// Author: Colin Day, January 2002
-// Desc: 2D line helping stuff
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-typedef std::vector Coord2DVector;
-typedef std::vector Coord3DVector;
-
-
-// PROTOTYPES /////////////////////////////////////////////////////////////////////////////////////
-extern Bool ClipLine2D( ICoord2D *p1, ICoord2D *p2, ICoord2D *c1, ICoord2D *c2,
- IRegion2D *clipRegion );
-
-///< IntersectLine2D will take two segments delimited by ab and cd and will return whether
-///< they intersect within the length of ab. They will also return the intersection point out
-///< intersection if it is non-null.
-extern Bool IntersectLine2D( const Coord2D *a, const Coord2D *b,
- const Coord2D *c, const Coord2D *d,
- Coord2D *intersection = nullptr);
-
-///< PointInsideRect2D will return true iff inputPoint lies iside of the rectangle specified
-///< by bl, tl, br, tr.
-extern Bool PointInsideRect2D( const Coord2D *bl, const Coord2D *tl,
- const Coord2D *br, const Coord2D *tr,
- const Coord2D *inputPoint);
-
-///< Checks if a point is inside a perfect rectangle (top left and bottom right)
-extern Bool Coord3DInsideRect2D( const Coord3D *inputPoint, const Coord2D *tl, const Coord2D *br );
-
-///< Scales a rect by a factor either growing or shrinking it.
-extern void ScaleRect2D( Coord2D *tl, Coord2D *br, Real scaleFactor );
-
-/** PointInsideRect3D will return true iff inputPoint lies iside of the rectangle specified
-by bl, tl, br, tr. It does not actually consider the Z value, it is merely a convenience function
-for calling PointInsideRect2D */
-extern Bool PointInsideRect3D( const Coord3D *bl, const Coord3D *tl,
- const Coord3D *br, const Coord3D *tr,
- const Coord3D *inputPoint);
-
-
-///< This function will take the ptToTest and will perform even-odd checking against the area.
-///< If the area is not closed, it will be closed for this check.
-extern Bool PointInsideArea2D( const Coord2D *ptToTest,
- const Coord2D *area,
- Int numPointsInArea);
-
-///< This function will take the ptToTest and will perform even-odd checking against the area.
-///< The area and the ptToTest will be flattened first, so a 2-D check will be sufficient.
-///< This function is only for convenience so that points do not need to first be flattened.
-extern Bool PointInsideArea2D( const Coord3D *ptToTest,
- const Coord3D *area,
- Int numPointsInArea);
-
-///< This function will find the shortest distance between the given segment (ab) and the pt.
-///< It will also give the intersection points on the segment (ab) if desired.
-///< outU will return the U value determined. This is a shortcut for panning
-extern void ShortestDistancePointToSegment2D( const Coord2D *a, const Coord2D *b, const Coord2D *pt,
- Real *outDistance, Coord2D *outPosition, Real *outU );
diff --git a/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h b/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h
deleted file mode 100644
index f0f2ac53fe8..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/LoadScreen.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LoadScreen.h /////////////////////////////////////////////////////////////////////////////////
-// Author: Chris Huybregts, March 2002
-// Desc: The file will hold the LoadScreen Base class and it's derived classes
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "Common/SubsystemInterface.h"
-#include "GameClient/GameWindow.h"
-#include "GameNetwork/GameInfo.h"
-#include "GameClient/CampaignManager.h"
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-class VideoBuffer;
-class VideoStreamInterface;
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Class LoadScreen is the parent class for each other kind of load screen
-///////////////////////////////////////////////////////////////////////////////////////////////////
-class LoadScreen
-{
-public:
- LoadScreen( void );
- virtual ~LoadScreen( void );
-
- virtual void init( GameInfo *game ) = 0; ///< Init the loadscreen
- virtual void reset( void ) = 0; ///< Reset the system
- virtual void update( void ) = 0; ///< Update the state of the slider bars
- virtual void update( Int percent ); ///< Update the state of the slider bars
- virtual void processProgress(Int playerId, Int percentage) = 0;
- virtual void setProgressRange( Int min, Int max ) = 0;
-protected:
- void setLoadScreen( GameWindow *g ) { m_loadScreen = g; }
- GameWindow *m_loadScreen; ///< The GameWindow that is our loadscreen
-
-private:
-
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// class SinglePlayerLoadScreen is to be used only when we're loading a single player mission
-///////////////////////////////////////////////////////////////////////////////////////////////////
-class SinglePlayerLoadScreen : public LoadScreen
-{
-public:
- SinglePlayerLoadScreen( void );
- virtual ~SinglePlayerLoadScreen( void );
-
- virtual void init( GameInfo *game ); ///< Init the loadscreen
- virtual void reset( void ); ///< Reset the system
- virtual void update( void )
- {
- DEBUG_CRASH(("Call update(Int) instead. This update isn't supported"));
- };
- virtual void update(Int percent); ///< Update the state of the progress bar
- virtual void processProgress(Int playerId, Int percentage)
- {
- DEBUG_CRASH(("We Got to a single player load screen throw the Network..."));
- }
-
- virtual void setProgressRange( Int min, Int max );
-
-private:
- GameWindow *m_progressBar; ///< Pointer to the Progress Bar on the window
- GameWindow *m_percent;
-
- GameWindow *m_objectiveWin;
- GameWindow *m_objectiveLines[MAX_OBJECTIVE_LINES];
- GameWindow *m_unitDesc[MAX_DISPLAYED_UNITS];
- GameWindow *m_location;
-
- Int m_currentObjectiveLine;
- Int m_currentObjectiveLineCharacter;
- Int m_currentObjectiveWidthOffset;
- Bool m_finishedObjectiveText;
-
- UnicodeString m_unicodeObjectiveLines[MAX_OBJECTIVE_LINES];
-
- VideoBuffer *m_videoBuffer;
- VideoStreamInterface *m_videoStream;
-
- void moveWindows( Int frame );
-
- AudioEventRTS m_ambientLoop;
- AudioHandle m_ambientLoopHandle;
-};
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// class ShellGameLoadScreen is to be used for the Shell Game loadscreen
-//// ///////////////////////////////////////////////////////////////////////////////////////////////
-class ShellGameLoadScreen : public LoadScreen
-{
-public:
- ShellGameLoadScreen( void );
- virtual ~ShellGameLoadScreen( void );
-
- virtual void init( GameInfo *game ); ///< Init the loadscreen
- virtual void reset( void ); ///< Reset the system
- virtual void update( void )
- {
- DEBUG_CRASH(("Call update(Int) instead. This update isn't supported"));
- };
- virtual void update(Int percent); ///< Update the state of the progress bar
- virtual void processProgress(Int playerId, Int percentage)
- {
- DEBUG_CRASH(("We Got to a single player load screen throw the Network..."));
- }
- virtual void setProgressRange( Int min, Int max ) { }
-
-private:
- GameWindow *m_progressBar ; ///< Pointer to the Progress Bar on the window
-
-};
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// class MultiPlayerLoadScreen is to be used for multiplayer communication on the loadscreens
-//// ///////////////////////////////////////////////////////////////////////////////////////////////
-class MultiPlayerLoadScreen : public LoadScreen
-{
-public:
- MultiPlayerLoadScreen( void );
- virtual ~MultiPlayerLoadScreen( void );
-
- virtual void init( GameInfo *game ); ///< Init the loadscreen
- virtual void reset( void ); ///< Reset the system
- virtual void update( void )
- {
- DEBUG_CRASH(("Call update(Int) instead. This update isn't supported"));
- };
- virtual void update(Int percent); ///< Update the state of the progress bar
- void processProgress(Int playerId, Int percentage);
- virtual void setProgressRange( Int min, Int max ) { }
-private:
- GameWindow *m_progressBars[MAX_SLOTS]; ///< pointer array to all the progress bars on the window
- GameWindow *m_playerNames[MAX_SLOTS]; ///< pointer array to all the static text player names on the window
- GameWindow *m_playerSide[MAX_SLOTS]; ///< pointer array to all the static text player sides
- Int m_playerLookup[MAX_SLOTS]; ///< lookup table to translate network slot info screen slot (to account for holes in the slot list)
- GameWindow *m_mapPreview;
- GameWindow *m_buttonMapStartPosition[MAX_SLOTS];
-
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// class MultiPlayerLoadScreen is to be used for multiplayer communication on the loadscreens
-//// ///////////////////////////////////////////////////////////////////////////////////////////////
-class GameSpyLoadScreen : public LoadScreen
-{
-public:
- GameSpyLoadScreen( void );
- virtual ~GameSpyLoadScreen( void );
-
- virtual void init( GameInfo *game ); ///< Init the loadscreen
- virtual void reset( void ); ///< Reset the system
- virtual void update( void )
- {
- DEBUG_CRASH(("Call update(Int) instead. This update isn't supported"));
- };
- virtual void update(Int percent); ///< Update the state of the progress bar
- void processProgress(Int playerId, Int percentage);
- virtual void setProgressRange( Int min, Int max ) { }
-private:
- GameWindow *m_progressBars[MAX_SLOTS]; ///< pointer array to all the progress bars on the window
- GameWindow *m_playerNames[MAX_SLOTS]; ///< pointer array to all the static text player names on the window
- GameWindow *m_playerSide[MAX_SLOTS]; ///< pointer array to all the static text player sides
- GameWindow *m_playerFavoriteFactions[MAX_SLOTS]; ///< pointer array to all the static text player sides
- GameWindow *m_playerTotalDisconnects[MAX_SLOTS]; ///< pointer array to all the static text player sides
- GameWindow *m_playerWin[MAX_SLOTS]; ///< pointer array to all the static text player sides
- GameWindow *m_playerWinLosses[MAX_SLOTS]; ///< pointer array to all the static text player sides
- GameWindow *m_playerRank[MAX_SLOTS]; ///< pointer array to all the static text player sides
- GameWindow *m_playerOfficerMedal[MAX_SLOTS]; ///< pointer array to all the static text player munkees
- GameWindow *m_mapPreview;
- GameWindow *m_buttonMapStartPosition[MAX_SLOTS];
-
- Int m_playerLookup[MAX_SLOTS]; ///< lookup table to translate network slot info screen slot (to account for holes in the slot list)
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// class MapTransferLoadScreen is to be used for map transfers before multiplayer game load screens
-//// ///////////////////////////////////////////////////////////////////////////////////////////////
-class MapTransferLoadScreen : public LoadScreen
-{
-public:
- MapTransferLoadScreen( void );
- virtual ~MapTransferLoadScreen( void );
-
- virtual void init( GameInfo *game ); ///< Init the loadscreen
- virtual void reset( void ); ///< Reset the system
- virtual void update( void )
- {
- DEBUG_CRASH(("Call update(Int) instead. This update isn't supported"));
- };
- virtual void update(Int percent); ///< Update the state of the progress bar
- virtual void processProgress(Int playerId, Int percentage)
- {
- DEBUG_CRASH(("Call processProgress(Int, Int, AsciiString) instead."));
- }
- void processProgress(Int playerId, Int percentage, AsciiString stateStr);
- virtual void setProgressRange( Int min, Int max ) { }
- void processTimeout(Int secondsLeft);
- void setCurrentFilename(AsciiString filename);
-private:
- GameWindow *m_progressBars[MAX_SLOTS]; ///< pointer array to all the progress bars on the window
- GameWindow *m_playerNames[MAX_SLOTS]; ///< pointer array to all the static text player names on the window
- GameWindow *m_progressText[MAX_SLOTS]; ///< pointer array to all the static text player sides
- Int m_playerLookup[MAX_SLOTS]; ///< lookup table to translate network slot info screen slot (to account for holes in the slot list)
- Int m_oldProgress[MAX_SLOTS]; ///< old vals, so we can call processProgress() every frame and not touch the GUI
- GameWindow *m_fileNameText;
- GameWindow *m_timeoutText;
- Int m_oldTimeout; ///< old val, so we can call processTimeout() every frame and not touch the GUI
-};
diff --git a/Generals/Code/GameEngine/Include/GameClient/Mouse.h b/Generals/Code/GameEngine/Include/GameClient/Mouse.h
deleted file mode 100644
index b3955efc6cf..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/Mouse.h
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Mouse.h //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Mouse.h
-//
-// Created: Michael S. Booth, January 1995
-// Colin Day, June 2001
-//
-// Desc: Basic mouse structure layout
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "Common/SubsystemInterface.h"
-#include "Common/AsciiString.h"
-#include "Common/UnicodeString.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-enum GameMode CPP_11(: Int);
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-enum MouseButtonState CPP_11(: Int)
-{
- MBS_None = -1,
- MBS_Up = 0,
- MBS_Down,
- MBS_DoubleClick,
-};
-
-#define MOUSE_MOVE_RELATIVE 0
-#define MOUSE_MOVE_ABSOLUTE 1
-
-// In frames
-#define CLICK_SENSITIVITY 15
-
-// In pixels
-#define CLICK_DISTANCE_DELTA 10
-#define CLICK_DISTANCE_DELTA_SQUARED (CLICK_DISTANCE_DELTA*CLICK_DISTANCE_DELTA)
-
-//
-#define MOUSE_WHEEL_DELTA 120
-
-#define MOUSE_NONE 0x00
-#define MOUSE_OK 0x01
-#define MOUSE_FAILED 0x80
-#define MOUSE_LOST 0xFF
-
-#define MOUSE_EVENT_NONE 0x00
-
-class DisplayString;
-
-#define MAX_2D_CURSOR_ANIM_FRAMES 21
-#define MAX_2D_CURSOR_DIRECTIONS 8
-// MouseIO --------------------------------------------------------------------
-/** @todo this mouse structure needs to be revisited to allow for devices
-with more than 3 buttons */
-//-----------------------------------------------------------------------------
-struct MouseIO
-{
-
- ICoord2D pos; ///< mouse pointer position
- UnsignedInt time; ///< The time that this message was posted.
-
- Int wheelPos; /**< mouse wheel position, 0 is no event, + is up/away from
- user while - is down/toward user */
- ICoord2D deltaPos; ///< overall change in mouse pointer this frame
-
- MouseButtonState leftState; // button state: None (no event), Up, Down, DoubleClick
- Int leftEvent; // Most important event this frame
-
- MouseButtonState rightState;
- Int rightEvent;
-
- MouseButtonState middleState;
- Int middleEvent;
-};
-
-class CursorInfo
-{
-public:
- CursorInfo();
- AsciiString cursorName;
- AsciiString cursorText;
- RGBAColorInt cursorTextColor;
- RGBAColorInt cursorTextDropColor;
- AsciiString textureName;
- AsciiString imageName;
- AsciiString W3DModelName;
- AsciiString W3DAnimName;
- Real W3DScale;
- Bool loop;
- ICoord2D hotSpotPosition;
- Int numFrames;
- Real fps; //frames per ms.
- Int numDirections; //number of directions for cursors like scrolling/panning.
-};
-
-typedef UnsignedInt CursorCaptureMode;
-enum CursorCaptureMode_ CPP_11(: CursorCaptureMode)
-{
- CursorCaptureMode_EnabledInWindowedGame = 1<<0, // Captures the cursor when in game while the app is windowed
- CursorCaptureMode_EnabledInWindowedMenu = 1<<1, // Captures the cursor when in menu while the app is windowed
- CursorCaptureMode_EnabledInFullscreenGame = 1<<2, // Captures the cursor when in game while the app is fullscreen
- CursorCaptureMode_EnabledInFullscreenMenu = 1<<3, // Captures the cursor when in menu while the app is fullscreen
-
- CursorCaptureMode_Default =
- CursorCaptureMode_EnabledInWindowedGame |
- CursorCaptureMode_EnabledInFullscreenGame |
- CursorCaptureMode_EnabledInFullscreenMenu,
-};
-
-// Mouse ----------------------------------------------------------------------
-// Class interface for working with a mouse pointing device
-//
-// TheSuperHackers @feature xezon 26/07/2025 Implements mouse cursor capture
-// functionality. The Mouse class handles most of the logic for it internally.
-//-----------------------------------------------------------------------------
-class Mouse : public SubsystemInterface
-{
-
- // enumerations and types
-
- typedef UnsignedInt CursorCaptureBlockReasonInt;
-
- enum CursorCaptureBlockReason
- {
- CursorCaptureBlockReason_NoInit,
- CursorCaptureBlockReason_Paused,
- CursorCaptureBlockReason_Unfocused,
- CursorCaptureBlockReadon_CursorIsOutside,
-
- CursorCaptureBlockReason_Count
- };
-
-public:
-
- // ----------------------------------------------------------------------------------------------
- /** If you update this enum make sure you update CursorININames[] */
- // ----------------------------------------------------------------------------------------------
- enum MouseCursor
- {
-
- // ***** dont forget to update CursorININames[] *****
- // ***** dont forget to update CursorININames[] *****
- // ***** dont forget to update CursorININames[] *****
- INVALID_MOUSE_CURSOR = -1,
- NONE = 0,
- FIRST_CURSOR,
- NORMAL = FIRST_CURSOR,
- ARROW,
- SCROLL,
- CROSS,
- MOVETO,
- ATTACKMOVETO,
- ATTACK_OBJECT,
- FORCE_ATTACK_OBJECT,
- FORCE_ATTACK_GROUND,
- BUILD_PLACEMENT,
- INVALID_BUILD_PLACEMENT,
- GENERIC_INVALID,
- SELECTING,
- // ***** dont forget to update CursorININames[] *****
- ENTER_FRIENDLY,
- ENTER_AGGRESSIVELY,
- SET_RALLY_POINT,
- GET_REPAIRED,
- GET_HEALED,
- DO_REPAIR,
- RESUME_CONSTRUCTION,
- CAPTUREBUILDING,
- // ***** dont forget to update CursorININames[] *****
- SNIPE_VEHICLE,
- LASER_GUIDED_MISSILES,
- TANKHUNTER_TNT_ATTACK,
- STAB_ATTACK,
- PLACE_REMOTE_CHARGE,
- // ***** dont forget to update CursorININames[] *****
- PLACE_TIMED_CHARGE,
- DEFECTOR,
-#ifdef ALLOW_DEMORALIZE
- DEMORALIZE,
-#endif
- DOCK,
- // ***** dont forget to update CursorININames[] *****
-#ifdef ALLOW_SURRENDER
- PICK_UP_PRISONER,
- RETURN_TO_PRISON,
-#endif
- FIRE_FLAME,
-#ifdef ALLOW_SURRENDER
- FIRE_TRANQ_DARTS,
- FIRE_STUN_BULLETS,
-#endif
- FIRE_BOMB,
- PLACE_BEACON,
- // ***** dont forget to update CursorININames[] *****
- DISGUISE_AS_VEHICLE,
- WAYPOINT,
- OUTRANGE,
- STAB_ATTACK_INVALID,
- PLACE_CHARGE_INVALID,
- HACK,
- PARTICLE_UPLINK_CANNON,
-
-
- // ***** dont forget to update CursorININames[] *****
- NUM_MOUSE_CURSORS
-
- };
-
- enum RedrawMode
- {
-
- RM_WINDOWS=0, //default Windows cursor - very fast.
- RM_W3D, //W3D model tied to frame rate.
- RM_POLYGON, //alpha blended polygon tied to frame rate.
- RM_DX8, //hardware cursor independent of frame rate.
-
- RM_MAX
- };
-
- static const char *const CursorCaptureBlockReasonNames[];
- static const char *const RedrawModeName[];
-
- CursorInfo m_cursorInfo[NUM_MOUSE_CURSORS];
-
-public:
-
- Mouse( void );
- virtual ~Mouse( void );
-
- // you may need to extend these for your device
- virtual void parseIni(void); ///< parse ini settings associated with mouse (do this before init()).
- virtual void init( void ); ///< init mouse, extend this functionality, do not replace
- virtual void reset( void ); ///< Reset the system
- virtual void update( void ); ///< update the state of the mouse position and buttons
- virtual void initCursorResources(void)=0; ///< needed so Win32 cursors can load resources before D3D device created.
-
- virtual void createStreamMessages( void ); /**< given state of device, create
- messages and put them on the
- stream for the raw state. */
-
- virtual void draw( void ); ///< draw the mouse
- virtual void setPosition( Int x, Int y ); ///< set the mouse position
- virtual void setCursor( MouseCursor cursor ) = 0; ///< set mouse cursor
-
- void initCapture(); ///< called once to unlock the mouse capture functionality
- void setCursorCaptureMode(CursorCaptureMode mode); ///< set the rules for the mouse capture
- void refreshCursorCapture(); ///< refresh the mouse capture
- Bool isCursorCaptured(); ///< true if the mouse is captured in the game window
-
- // access methods for the mouse data
- const MouseIO *getMouseStatus( void ) { return &m_currMouse; } ///< get current mouse status
-
- Int getCursorTooltipDelay() { return m_tooltipDelay; }
- void setCursorTooltipDelay(Int delay) { m_tooltipDelay = delay; }
-
- void setCursorTooltip( UnicodeString tooltip, Int tooltipDelay = -1, const RGBColor *color = nullptr, Real width = 1.0f ); ///< set tooltip string at cursor
- void setMouseText( UnicodeString text, const RGBAColorInt *color, const RGBAColorInt *dropColor ); ///< set the cursor text, *NOT* the tooltip text
- virtual void setMouseLimits( void ); ///< update the limit extents the mouse can move in
- MouseCursor getMouseCursor(void) { return m_currentCursor; } ///< get the current mouse cursor image type
- virtual void setRedrawMode(RedrawMode mode) {m_currentRedrawMode=mode;} ///.
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: ProcessAnimateWindow.h /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Mar 2002
-//
-// Filename: ProcessAnimateWindow.h
-//
-// author: Chris Huybregts
-//
-// purpose: If a new animation is wanted to be added for the windows, All you
-// have to do is create a new class derived from ProcessAnimateWindow.
-// Then setup each of the virtual classes to process an AnimateWindow
-// class. The Update and reverse functions get called every frame
-// by the shell and will continue to process the AdminWin until the
-// isFinished flag on the adminWin is set to true.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "Lib/BaseType.h"
-//-----------------------------------------------------------------------------
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-namespace wnd
-{
-class AnimateWindow;
-}
-class GameWindow;
-//-----------------------------------------------------------------------------
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-class ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindow( void ){};
- virtual ~ProcessAnimateWindow( void ){};
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin ) = 0;
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 ) = 0;
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin ) = 0;
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin ) = 0;
- virtual void setMaxDuration(UnsignedInt maxDuration) { }
-};
-
-//-----------------------------------------------------------------------------
-
-class ProcessAnimateWindowSlideFromRight : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromRight( void );
- virtual ~ProcessAnimateWindowSlideFromRight( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
-Coord2D m_maxVel; // top speed windows travel in x and y
-Int m_slowDownThreshold; // when windows get this close to their resting
- // positions they start to slow down
-Real m_slowDownRatio; // how fast the windows slow down (smaller slows quicker)
-Real m_speedUpRatio; // how fast the windows speed up
-
-};
-
-
-//-----------------------------------------------------------------------------
-
-class ProcessAnimateWindowSlideFromLeft : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromLeft( void );
- virtual ~ProcessAnimateWindowSlideFromLeft( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
-Coord2D m_maxVel; // top speed windows travel in x and y
-Int m_slowDownThreshold; // when windows get this close to their resting
- // positions they start to slow down
-Real m_slowDownRatio; // how fast the windows slow down (smaller slows quicker)
-Real m_speedUpRatio; // how fast the windows speed up
-
-};
-
-
-//-----------------------------------------------------------------------------
-
-class ProcessAnimateWindowSlideFromTop : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromTop( void );
- virtual ~ProcessAnimateWindowSlideFromTop( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
-Coord2D m_maxVel; // top speed windows travel in x and y
-Int m_slowDownThreshold; // when windows get this close to their resting
- // positions they start to slow down
-Real m_slowDownRatio; // how fast the windows slow down (smaller slows quicker)
-Real m_speedUpRatio; // how fast the windows speed up
-
-};
-
-//-----------------------------------------------------------------------------
-class ProcessAnimateWindowSlideFromTopFast : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromTopFast( void );
- virtual ~ProcessAnimateWindowSlideFromTopFast( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
-Coord2D m_maxVel; // top speed windows travel in x and y
-Int m_slowDownThreshold; // when windows get this close to their resting
- // positions they start to slow down
-Real m_slowDownRatio; // how fast the windows slow down (smaller slows quicker)
-Real m_speedUpRatio; // how fast the windows speed up
-
-};
-
-
-//-----------------------------------------------------------------------------
-
-class ProcessAnimateWindowSlideFromBottom : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromBottom( void );
- virtual ~ProcessAnimateWindowSlideFromBottom( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
-Coord2D m_maxVel; // top speed windows travel in x and y
-Int m_slowDownThreshold; // when windows get this close to their resting
- // positions they start to slow down
-Real m_slowDownRatio; // how fast the windows slow down (smaller slows quicker)
-Real m_speedUpRatio; // how fast the windows speed up
-
-};
-
-//-----------------------------------------------------------------------------
-
-class ProcessAnimateWindowSpiral : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSpiral( void );
- virtual ~ProcessAnimateWindowSpiral( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
- Real m_deltaTheta;
- Int m_maxR;
-};
-
-//-----------------------------------------------------------------------------
-
-class ProcessAnimateWindowSlideFromBottomTimed : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromBottomTimed( void );
- virtual ~ProcessAnimateWindowSlideFromBottomTimed( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void setMaxDuration(UnsignedInt maxDuration) { m_maxDuration = maxDuration; }
-
-private:
- UnsignedInt m_maxDuration;
-
-};
-
-class ProcessAnimateWindowSlideFromRightFast : public ProcessAnimateWindow
-{
-public:
-
- ProcessAnimateWindowSlideFromRightFast( void );
- virtual ~ProcessAnimateWindowSlideFromRightFast( void );
-
- virtual void initAnimateWindow( wnd::AnimateWindow *animWin );
- virtual void initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay = 0 );
- virtual Bool updateAnimateWindow( wnd::AnimateWindow *animWin );
- virtual Bool reverseAnimateWindow( wnd::AnimateWindow *animWin );
-private:
-Coord2D m_maxVel; // top speed windows travel in x and y
-Int m_slowDownThreshold; // when windows get this close to their resting
- // positions they start to slow down
-Real m_slowDownRatio; // how fast the windows slow down (smaller slows quicker)
-Real m_speedUpRatio; // how fast the windows speed up
-
-};
-
-
-//-----------------------------------------------------------------------------
-// INLINING ///////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// EXTERNALS //////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Include/GameClient/RadiusDecal.h b/Generals/Code/GameEngine/Include/GameClient/RadiusDecal.h
deleted file mode 100644
index c1b3bd5ad12..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/RadiusDecal.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: RadiusDecal.h ///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#include "Common/GameCommon.h"
-#include "Common/GameType.h"
-#include "GameClient/Color.h"
-
-enum ShadowType CPP_11(: Int);
-class Player;
-class Shadow;
-class RadiusDecalTemplate;
-
-// ------------------------------------------------------------------------------------------------
-class RadiusDecal
-{
- friend class RadiusDecalTemplate;
-private:
- const RadiusDecalTemplate* m_template;
- Shadow* m_decal;
- Bool m_empty;
-public:
- RadiusDecal();
- RadiusDecal(const RadiusDecal& that);
- RadiusDecal& operator=(const RadiusDecal& that);
- ~RadiusDecal();
-
- void xferRadiusDecal( Xfer *xfer );
-
- // please note: it is very important, for game/net sync reasons, to ensure that
- // isEmpty() returns the same value, regardless of whether this decal will
- // be visible to the local player or not.
- Bool isEmpty() const { return m_empty; }
- void clear();
- void update();
- void setPosition(const Coord3D& pos);
- void setOpacity( const Real o );
-};
-
-// ------------------------------------------------------------------------------------------------
-class RadiusDecalTemplate
-{
- friend class RadiusDecal;
-private:
- AsciiString m_name;
- ShadowType m_shadowType;
- Real m_minOpacity;
- Real m_maxOpacity;
- UnsignedInt m_opacityThrobTime;
- Color m_color;
- Bool m_onlyVisibleToOwningPlayer;
-
-public:
- RadiusDecalTemplate();
-
- Bool valid() const { return m_name.isNotEmpty(); }
- void xferRadiusDecalTemplate( Xfer *xfer );
-
- // please note: it is very important, for game/net sync reasons, to ensure that
- // a valid radiusdecal is created, even if will not be visible to the local player,
- // since some logic makes decisions based on this.
- void createRadiusDecal(const Coord3D& pos, Real radius, const Player* owningPlayer, RadiusDecal& result) const;
-
- static void parseRadiusDecalTemplate(INI* ini, void *instance, void * store, const void* /*userData*/);
-};
diff --git a/Generals/Code/GameEngine/Include/GameClient/SelectionInfo.h b/Generals/Code/GameEngine/Include/GameClient/SelectionInfo.h
deleted file mode 100644
index e0d07c059a4..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/SelectionInfo.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameClient/ContextSensitiveTranslator.h //////////////////////////////////////////////////
-// Contains the SelectionInfo structure and the contextCommandForNewSelection
-// Author: John McDonald, Jr, October 2002
-
-#pragma once
-
-#include "GameClient/InGameUI.h"
-
-// This structure gives you a rough idea about the counts of the kinds of guys in the
-// current selection, and in the selection that would be made.
-struct SelectionInfo
-{
- Int currentCountEnemies;
- Int currentCountCivilians;
- Int currentCountMine;
- Int currentCountMineInfantry;
- Int currentCountMineBuildings;
- Int currentCountFriends;
-
- Int newCountEnemies;
- Int newCountCivilians;
- Int newCountMine;
- Int newCountMineBuildings;
- Int newCountFriends;
- Int newCountGarrisonableBuildings;
- Int newCountCrates;
-
- Bool selectEnemies;
- Bool selectCivilians;
- Bool selectMine;
- Bool selectMineBuildings;
- Bool selectFriends;
-
-
- SelectionInfo();
-};
-
-//-------------------------------------------------------------------------------------------------
-struct PickDrawableStruct
-{
- // List to fill with Drawables. This should be provided by the caller.
- DrawableList *drawableListToFill;
- Bool forceAttackMode;
-
- // Note, this is OR'd with the things we are attempting to select.
- KindOfMaskType kindofsToMatch;
-
- PickDrawableStruct();
-};
-
-//-------------------------------------------------------------------------------------------------
-extern Bool contextCommandForNewSelection(const DrawableList *currentlySelectedDrawables,
- const DrawableList *newlySelectedDrawables,
- SelectionInfo *outSelectionInfo,
- Bool selectionIsPoint);
-
-
-//-------------------------------------------------------------------------------------------------
-// Returns ORed picktypes.
-extern UnsignedInt getPickTypesForContext(Bool forceAttackMode);
-
-//-------------------------------------------------------------------------------------------------
-// Returns ORed picktypes based on the current selection.
-extern UnsignedInt getPickTypesForCurrentSelection(Bool forceAttackMode);
-
-
-//-------------------------------------------------------------------------------------------------
-// expects ORed picktypes.
-extern void translatePickTypesToKindof(UnsignedInt pickTypes, KindOfMaskType& outmask);
-
-//-------------------------------------------------------------------------------------------------
-// Given a drawable, add it to an stl list. Useful for iterateDrawablesInRegion.
-// userData should be a pointer to a PickDrawableStruct, which is defined in
-// above.
-extern Bool addDrawableToList( Drawable *draw, void *userData );
diff --git a/Generals/Code/GameEngine/Include/GameClient/Statistics.h b/Generals/Code/GameEngine/Include/GameClient/Statistics.h
deleted file mode 100644
index 8031fe35fde..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/Statistics.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Statistics.h
-/*---------------------------------------------------------------------------*/
-/* EA Pacific */
-/* Confidential Information */
-/* Copyright (C) 2001 - All Rights Reserved */
-/* DO NOT DISTRIBUTE */
-/*---------------------------------------------------------------------------*/
-/* Project: RTS3 */
-/* File name: Statistics.h */
-/* Created: John K. McDonald, Jr., 4/2/2002 */
-/* Desc: Common statistical functions */
-/* Revision History: */
-/* 4/2/2002 : Initial creation */
-/*---------------------------------------------------------------------------*/
-
-#pragma once
-
-// INCLUDES ///////////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-// FORWARD DECLARATIONS ///////////////////////////////////////////////////////
-
-
-// valueToRun is the value (between 0 and maxValueForVal) to test.
-// mu is designates the steepness of the curve.
-// The return value is a value in [-1, 1]
-extern Real MuLaw(Real valueToRun, Real maxValueForVal, Real mu);
-
-// valueToNormalize is a value in minRange..maxRange
-// minRange is the smallest value the range contains
-// maxRange is the largest value the range contains
-// the return is a value in [0, 1].
-extern Real Normalize(Real valueToNormalize, Real minRange, Real maxRange);
-
-// same as Normalize, except that output will be in the range [outRangeMin, outRangeMax]
-extern Real NormalizeToRange(Real valueToNormalize, Real minRange, Real maxRange, Real outRangeMin, Real outRangeMax);
diff --git a/Generals/Code/GameEngine/Include/GameClient/WinInstanceData.h b/Generals/Code/GameEngine/Include/GameClient/WinInstanceData.h
deleted file mode 100644
index 1beaf34f9a6..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/WinInstanceData.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: WinInstanceData.h ////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: WinInstanceData.h
-//
-// Created: Colin Day, July 2001
-//
-// Desc: The game window instance dat
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "GameClient/DisplayString.h"
-#include "GameClient/GameFont.h"
-#include "GameClient/Image.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-class GameWindow;
-class VideoBuffer;
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-#define WIN_STATE_HILITED 0x00000002 // Mouse is over window or has focus
-#define WIN_STATE_SELECTED 0x00000004 // Window has been selected
-
-enum
-{
- MAX_WINDOW_NAME_LEN = 64,
- /** how many elements there are for each of the draw states for the inst
- * data of a window, note if you increase this you must update the parsing
- * tables make sure you can parse the new fields from the window scrip
- * files */
- MAX_DRAW_DATA = 9,
- MAX_TEXT_LABEL = 128 ///< max length of text label
-};
-
-// WinDrawData ----------------------------------------------------------------
-//-----------------------------------------------------------------------------
-struct WinDrawData
-{
-
- const Image *image;
- Color color;
- Color borderColor;
-
-};
-
-// TextDrawData ---------------------------------------------------------------
-//-----------------------------------------------------------------------------
-struct TextDrawData
-{
- Color color; ///< the text color
- Color borderColor; ///< outline color
-};
-
-// WinInstanceData ------------------------------------------------------------
-// NOTE if you add data to this make sure you update winSetInstanceData()
-// NOTE if you add data to this make sure you update winSetInstanceData()
-// NOTE if you add data to this make sure you update winSetInstanceData()
-//-----------------------------------------------------------------------------
-class WinInstanceData
-{
-
-public:
-
- WinInstanceData( void ); ///< constructor automatically runs init()
- virtual ~WinInstanceData( void );
-
- void init( void ); ///< initialize default values if desired
-
-
- // setting text
- void setTooltipText( UnicodeString tip ); ///< set tooltip text
- void setText( UnicodeString text ); ///< set instance text text
-
- // a couple of nice access methods
- UnicodeString getTooltipText( void ); ///< get tooltip text
- UnicodeString getText( void ); ///< get instance text
- Int getTextLength( void ); ///< get number of chars in instance text
- Int getTooltipTextLength( void ); ///< get number of chars in tooltip text
- UnsignedInt getStyle( void ); ///< return window style
- UnsignedInt getStatus( void ); ///< return window status
- UnsignedInt getState( void ); ///< return window state
- GameWindow *getOwner( void ); ///< return window owner
- GameFont *getFont( void ); ///< return window font
-
- DisplayString *getTextDisplayString( void ); ///< return the text display string
- DisplayString *getTooltipDisplayString( void ); ///< return the tooltip display string
-
- void setVideoBuffer( VideoBuffer * videoBuffer ); ///< set the videobuffer to display a video frame
-
-// NOTE if you add data to this make sure you update winSetInstanceData()
-// NOTE if you add data to this make sure you update winSetInstanceData()
-// NOTE if you add data to this make sure you update winSetInstanceData()
-
- /** @todo you may want to make these data members protected, they are public
- because of the legacy of porting all this code in from Nox, but they
- really should be protected and have the rest of the code use access
- functions to edit them */
-
- Int m_id; // Id of the window (used mainly for scripts)
- Int m_state; // Flags indicating state of window
- UnsignedInt m_style; // Flags indicating style of window
- UnsignedInt m_status; // Status bits for this window (mirrored in GameWindow)
- GameWindow *m_owner;
-
- WinDrawData m_enabledDrawData[ MAX_DRAW_DATA ]; ///< image/color info for enabled state
- WinDrawData m_disabledDrawData[ MAX_DRAW_DATA ]; ///< image/color info for disabled state
- WinDrawData m_hiliteDrawData[ MAX_DRAW_DATA ]; ///< image/color info for hilite state
-
- TextDrawData m_enabledText; ///< enabled text colors
- TextDrawData m_disabledText; ///< disabled text colors
- TextDrawData m_hiliteText; ///< hilite text colors
- TextDrawData m_imeCompositeText;///< IME composite text colors
-
- ICoord2D m_imageOffset; // dx, dy for blitting bkgnd images
-
- GameFont *m_font; // font which this window should use
-
- AsciiString m_textLabelString; ///< text label from window file if present
- AsciiString m_decoratedNameString; ///< window text name from GUIEdit
- AsciiString m_tooltipString; ///< tooltip Label from window file if present
-
- AsciiString m_headerTemplateName; ///< name of the template we're going to base our font off of.
-
- Int m_tooltipDelay; ///< desired delay before showing tooltip
-
- DisplayString *m_text; ///< generic text for any window to display
- DisplayString *m_tooltip; ///< tooltip for display
-
- //NOTE Video Buffer cannot be transferred to another window.
- VideoBuffer *m_videoBuffer; ///< Each window can be made to play a video in it.
-
-// NOTE if you add data to this make sure you update winSetInstanceData()
-// NOTE if you add data to this make sure you update winSetInstanceData()
-// NOTE if you add data to this make sure you update winSetInstanceData()
-
-protected:
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// INLINING ///////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-inline UnsignedInt WinInstanceData::getStyle( void ) { return m_style; }
-inline UnsignedInt WinInstanceData::getStatus( void ) { return m_status; }
-inline UnsignedInt WinInstanceData::getState( void ) { return m_state; }
-inline GameWindow *WinInstanceData::getOwner( void ) { return m_owner; }
-inline GameFont *WinInstanceData::getFont( void ) { return m_font; }
-inline DisplayString *WinInstanceData::getTextDisplayString( void ) { return m_text; }
-inline DisplayString *WinInstanceData::getTooltipDisplayString( void ) { return m_tooltip; }
-inline UnicodeString WinInstanceData::getTooltipText( void )
-{
- if( m_tooltip )
- return m_tooltip->getText();
- return UnicodeString::TheEmptyString;
-
-}
-inline UnicodeString WinInstanceData::getText( void )
-{
- if( m_text )
- return m_text->getText();
- return UnicodeString::TheEmptyString;
-}
-inline Int WinInstanceData::getTextLength( void )
-{
- if( m_text )
- return m_text->getTextLength();
- return 0;
-}
-inline Int WinInstanceData::getTooltipTextLength( void )
-{
- if( m_tooltip )
- return m_tooltip->getTextLength();
- return 0;
-}
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngine/Include/GameClient/WindowLayout.h b/Generals/Code/GameEngine/Include/GameClient/WindowLayout.h
deleted file mode 100644
index 97362825638..00000000000
--- a/Generals/Code/GameEngine/Include/GameClient/WindowLayout.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: WindowLayout.h ///////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, September 2001
-// Desc: Encapsulation of all windows loaded from a .wnd file for
-// purposes of a "shell" layout screen
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "Common/GameMemory.h"
-#include "GameClient/GameWindow.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
-class GameWindow;
-class WindowLayout;
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////////////////////////
-typedef void (*WindowLayoutInitFunc)( WindowLayout *layout, void *userData );
-typedef void (*WindowLayoutUpdateFunc)( WindowLayout *layout, void *userData );
-typedef void (*WindowLayoutShutdownFunc)( WindowLayout *layout, void *userData );
-
-//-------------------------------------------------------------------------------------------------
-/** The representation of a screen layout loaded from a .wnd layout
- * script file */
-//-------------------------------------------------------------------------------------------------
-class WindowLayout : public MemoryPoolObject
-{
-
- // memory pool for screen layouts
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( WindowLayout, "WindowLayoutPool" );
-
-public:
-
- WindowLayout( void );
- // ~WindowLayout( void ); ///< defined by memory pool glue
-
- // manipulating screen properties ---------------------------------------------------------------
- AsciiString getFilename( void ) const; ///< return source window filename
- Bool load( AsciiString filename ); ///< create windows and load from .wnd file
- void hide( Bool hide ); ///< hide/show all windows on this screen
- Bool isHidden( void ) const; ///< return visible state of screen
- void bringForward( void ); ///< bring all windows in this screen forward
-
- // manipulating window lists --------------------------------------------------------------------
- void addWindow( GameWindow *window ); ///< add window to screen
- void removeWindow( GameWindow *window ); ///< remove window from screen
- void destroyWindows( void ); ///< destroy all windows in this screen
- GameWindow *getFirstWindow( void ) const; ///< get first window in list for screen
-
- // accessing layout callbacks ------------------------------------------------------------------
- void runInit( void *userData = nullptr ); ///< run the init method if available
- void runUpdate( void *userData = nullptr ); ///< run the update method if available
- void runShutdown( void *userData = nullptr ); ///< run the shutdown method if available
- void setInit( WindowLayoutInitFunc init ); ///< set the init callback
- void setUpdate( WindowLayoutUpdateFunc update ); ///< set the update callback
- void setShutdown( WindowLayoutShutdownFunc shutdown); ///< set the shutdown callback
-
-protected:
-
- // internal helpers -----------------------------------------------------------------------------
- GameWindow *findWindow( GameWindow *window ); ///< find window in this layout
-
- //===============================================================================================
- // protected data ===============================================================================
- //===============================================================================================
-
- AsciiString m_filenameString; ///< layout filename
- GameWindow *m_windowList; ///< list of windows in this layout
- GameWindow *m_windowTail; ///< end of m_windowList
- Int m_windowCount; ///< how man windows are in the list
- Bool m_hidden; ///< visible state of this screen
-
- //
- // These are callbacks you can attach to a "layout file" ... they are not
- // automatically called when using the WindowManager to load and create
- // the layout. You can incorporate when and where init, shutdown and update should
- // be called for any system or code that is uses these window layouts
- //
- WindowLayoutInitFunc m_init; ///< init callback
- WindowLayoutUpdateFunc m_update; ///< update callback
- WindowLayoutShutdownFunc m_shutdown; ///< shutdown callback
-
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////////////////////////
-inline AsciiString WindowLayout::getFilename( void ) const { return m_filenameString; }
-inline GameWindow *WindowLayout::getFirstWindow( void ) const { return m_windowList; }
-inline Bool WindowLayout::isHidden( void ) const { return m_hidden; }
-
-inline void WindowLayout::runInit( void *userData ) { if( m_init ) m_init( this, userData ); }
-inline void WindowLayout::runUpdate( void *userData ) { if( m_update ) m_update( this, userData ); }
-inline void WindowLayout::runShutdown( void *userData ) { if( m_shutdown ) m_shutdown( this, userData ); }
-
-inline void WindowLayout::setInit( WindowLayoutInitFunc init ) { m_init = init; }
-inline void WindowLayout::setUpdate( WindowLayoutUpdateFunc update ) { m_update = update; }
-inline void WindowLayout::setShutdown( WindowLayoutShutdownFunc shutdown ) {m_shutdown = shutdown;}
diff --git a/Generals/Code/GameEngine/Include/GameLogic/AIPathfind.h b/Generals/Code/GameEngine/Include/GameLogic/AIPathfind.h
index 0ae24b017fb..ece001ff6a9 100644
--- a/Generals/Code/GameEngine/Include/GameLogic/AIPathfind.h
+++ b/Generals/Code/GameEngine/Include/GameLogic/AIPathfind.h
@@ -247,6 +247,24 @@ class PathfindCellInfo
UnsignedInt m_closed:1; ///< place for marking this cell as on the closed list
};
+// TheSuperHackers @info The PathfindCellList class acts as a new management class for the pathfindcell open and closed lists
+class PathfindCellList
+{
+ friend class PathfindCell;
+
+public:
+ PathfindCellList() : m_head(nullptr) {}
+
+ void reset(PathfindCell* newHead = nullptr) { m_head = newHead; }
+
+ PathfindCell* getHead() const { return m_head; }
+
+ Bool empty() const { return m_head == nullptr; }
+
+private:
+ PathfindCell* m_head;
+};
+
/**
* This represents one cell in the pathfinding grid.
* These cells categorize the world into idealized cellular states,
@@ -307,23 +325,23 @@ class PathfindCell
UnsignedInt costSoFar( PathfindCell *parent );
- /// put self on "open" list in ascending cost order, return new list
- PathfindCell *putOnSortedOpenList( PathfindCell *list );
+ /// put self on "open" list in ascending cost order
+ void putOnSortedOpenList( PathfindCellList &list );
/// remove self from "open" list
- PathfindCell *removeFromOpenList( PathfindCell *list );
+ void removeFromOpenList( PathfindCellList &list );
/// put self on "closed" list, return new list
- PathfindCell *putOnClosedList( PathfindCell *list );
+ void putOnClosedList( PathfindCellList &list );
/// remove self from "closed" list
- PathfindCell *removeFromClosedList( PathfindCell *list );
+ void removeFromClosedList( PathfindCellList &list );
/// remove all cells from closed list.
- static Int releaseClosedList( PathfindCell *list );
+ static Int releaseClosedList( PathfindCellList &list );
/// remove all cells from closed list.
- static Int releaseOpenList( PathfindCell *list );
+ static Int releaseOpenList( PathfindCellList &list );
inline PathfindCell *getNextOpen(void) {return m_info->m_nextOpen?m_info->m_nextOpen->m_cell: nullptr;}
@@ -772,9 +790,6 @@ class Pathfinder : PathfindServicesInterface, public Snapshot
Bool centerInCell, Int radius, const ICoord2D &startCellNdx,
const Object *obj, Int attackDistance);
- Bool pathDestination( Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest,
- PathfindLayerEnum layer, const Coord3D *groupDest); ///< Checks cost between given locations
-
Int checkPathCost(Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
const Coord3D *to);
@@ -848,8 +863,8 @@ class Pathfinder : PathfindServicesInterface, public Snapshot
IRegion2D m_extent; ///< Grid extent limits
IRegion2D m_logicalExtent; ///< Logical grid extent limits
- PathfindCell *m_openList; ///< Cells ready to be explored
- PathfindCell *m_closedList; ///< Cells already explored
+ PathfindCellList m_openList; ///< Cells ready to be explored
+ PathfindCellList m_closedList; ///< Cells already explored
Bool m_isMapReady; ///< True if all cells of map have been classified
Bool m_isTunneling; ///< True if path started in an obstacle
diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h b/Generals/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h
index d560519cd02..2903a7953e0 100644
--- a/Generals/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h
+++ b/Generals/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h
@@ -47,6 +47,7 @@ class CrateCollideModuleData : public CollideModuleData
Bool m_isForbidOwnerPlayer; ///< This crate cannot be picked up by the player of the dead thing that made it.
Bool m_isBuildingPickup; ///< This crate can be picked up by a Building (bypassing AI requirement)
Bool m_isHumanOnlyPickup; ///< Can this crate only be picked up by a human player? (Mission thing)
+ Bool m_allowMultiPickup; ///< Can this crate be picked up by multiple objects on the same frame?
ScienceType m_pickupScience; ///< Can only be picked up by a unit whose player has this science
FXList *m_executeFX; ///< FXList to play when activated
diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h
index 2cb66b61547..372346c2ca9 100644
--- a/Generals/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h
+++ b/Generals/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h
@@ -60,7 +60,7 @@ enum HordeActionType CPP_11(: Int)
HORDEACTION_COUNT,
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
HORDEACTION_DEFAULT = HORDEACTION_HORDE,
#else
HORDEACTION_DEFAULT = HORDEACTION_HORDE_FIXED, ///< Does not change unmodified retail game behavior, because all its horde update modules explicitly set Action = HORDE.
diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/OpenContain.h b/Generals/Code/GameEngine/Include/GameLogic/Module/OpenContain.h
index e77efc5b57e..3af57c7cc7e 100644
--- a/Generals/Code/GameEngine/Include/GameLogic/Module/OpenContain.h
+++ b/Generals/Code/GameEngine/Include/GameLogic/Module/OpenContain.h
@@ -240,7 +240,6 @@ class OpenContain : public UpdateModule,
ObjectEnterExitMap m_objectEnterExitInfo;
UnsignedInt m_stealthUnitsContained; ///< number of stealth units that can't be seen by enemy players.
UnsignedInt m_heroUnitsContained; ///< cached hero count
- XferVersion m_xferVersion; ///< version of loaded save file for loadPostProcess
Int m_whichExitPath; ///< Cycles from 1 to n and is used only in modules whose data has numberOfExitPaths > 1.
UnsignedInt m_doorCloseCountdown; ///< When should I shut my door.
diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h b/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h
index 8e779f1d14e..fad6c4cd63f 100644
--- a/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h
+++ b/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h
@@ -106,6 +106,7 @@ class TunnelContain : public OpenContain, public CreateModuleInterface
// contain list access
virtual void iterateContained( ContainIterateFunc func, void *userData, Bool reverse );
virtual UnsignedInt getContainCount() const;
+ virtual UnsignedInt getHeroUnitsContained() const;
virtual Int getContainMax( void ) const;
virtual const ContainedItemsList* getContainedItemsList() const;
virtual UnsignedInt getFullTimeForHeal(void) const; ///< Returns the time in frames until a contained object becomes fully healed
diff --git a/Generals/Code/GameEngine/Source/Common/CommandLine.cpp b/Generals/Code/GameEngine/Source/Common/CommandLine.cpp
index 661caa280af..09c9258d8c7 100644
--- a/Generals/Code/GameEngine/Source/Common/CommandLine.cpp
+++ b/Generals/Code/GameEngine/Source/Common/CommandLine.cpp
@@ -780,7 +780,6 @@ Int parseNoShaders(char *args[], int)
return 1;
}
-#if defined(RTS_DEBUG)
Int parseNoLogo(char *args[], int)
{
TheWritableGlobalData->m_playIntro = FALSE;
@@ -789,14 +788,6 @@ Int parseNoLogo(char *args[], int)
return 1;
}
-#endif
-
-Int parseNoSizzle( char *args[], int )
-{
- TheWritableGlobalData->m_playSizzle = FALSE;
-
- return 1;
-}
Int parseShellMap(char *args[], int num)
{
@@ -823,13 +814,7 @@ Int parseWinCursors(char *args[], int num)
Int parseQuickStart( char *args[], int num )
{
-#if defined(RTS_DEBUG)
- parseNoLogo( args, num );
-#else
- //Kris: Patch 1.01 -- Allow release builds to skip the sizzle video, but still force the EA logo to show up.
- //This is for legal reasons.
- parseNoSizzle( args, num );
-#endif
+ parseNoLogo( args, num );
parseNoShellMap( args, num );
parseNoWindowAnimation( args, num );
return 1;
@@ -1168,7 +1153,9 @@ static CommandLineParam paramsForStartup[] =
// These Params are parsed during Engine Init before INI data is loaded
static CommandLineParam paramsForEngineInit[] =
{
+ { "-nologo", parseNoLogo }, // TheSuperHackers @tweak Is now available in Release builds.
{ "-noshellmap", parseNoShellMap },
+ { "-noShellAnim", parseNoWindowAnimation }, // TheSuperHackers @tweak Is now available in Release builds.
{ "-xres", parseXRes },
{ "-yres", parseYRes },
{ "-fullVersion", parseFullVersion },
@@ -1294,9 +1281,7 @@ static CommandLineParam paramsForEngineInit[] =
{ "-noshadowvolumes", parseNoShadows },
{ "-nofx", parseNoFX },
{ "-ignoresync", parseSync },
- { "-nologo", parseNoLogo },
{ "-shellmap", parseShellMap },
- { "-noShellAnim", parseNoWindowAnimation },
{ "-winCursors", parseWinCursors },
{ "-constantDebug", parseConstantDebug },
{ "-seed", parseSeed },
@@ -1307,7 +1292,6 @@ static CommandLineParam paramsForEngineInit[] =
{ "-updateImages", parseUpdateImages },
{ "-showTeamDot", parseShowTeamDot },
{ "-extraLogging", parseExtraLogging },
-
#endif
#ifdef DEBUG_LOGGING
diff --git a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp
index 252c354488e..21a25d921d9 100644
--- a/Generals/Code/GameEngine/Source/Common/GameEngine.cpp
+++ b/Generals/Code/GameEngine/Source/Common/GameEngine.cpp
@@ -64,7 +64,7 @@
#include "Common/SpecialPower.h"
#include "Common/TerrainTypes.h"
#include "Common/Upgrade.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/Xfer.h"
#include "Common/XferCRC.h"
#include "Common/GameLOD.h"
diff --git a/Generals/Code/GameEngine/Source/Common/GameLOD.cpp b/Generals/Code/GameEngine/Source/Common/GameLOD.cpp
index 0eb5eed8d2d..15acba3a195 100644
--- a/Generals/Code/GameEngine/Source/Common/GameLOD.cpp
+++ b/Generals/Code/GameEngine/Source/Common/GameLOD.cpp
@@ -36,7 +36,7 @@
#include "Common/GameLOD.h"
#include "GameClient/TerrainVisual.h"
#include "GameClient/GameClient.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#define DEFINE_PARTICLE_SYSTEM_NAMES
#include "GameClient/ParticleSys.h"
diff --git a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp
index 3c8894ac5d9..cc676fdbb3f 100644
--- a/Generals/Code/GameEngine/Source/Common/GlobalData.cpp
+++ b/Generals/Code/GameEngine/Source/Common/GlobalData.cpp
@@ -46,7 +46,7 @@
#include "Common/FileSystem.h"
#include "Common/GameAudio.h"
#include "Common/INI.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
#include "GameLogic/AI.h"
diff --git a/Generals/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp b/Generals/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp
index e2145deaeec..c5082372270 100644
--- a/Generals/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp
+++ b/Generals/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp
@@ -43,7 +43,7 @@ void INI::parseMultiplayerSettingsDefinition( INI* ini )
//
if( ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES )
{
- DEBUG_ASSERTCRASH(false, ("Creating an override of MultiplayerSettings!"));
+ DEBUG_CRASH(("Creating an override of MultiplayerSettings!"));
}
}
else
diff --git a/Generals/Code/GameEngine/Source/Common/RTS/ActionManager.cpp b/Generals/Code/GameEngine/Source/Common/RTS/ActionManager.cpp
index 8afb0603b3b..99eec241894 100644
--- a/Generals/Code/GameEngine/Source/Common/RTS/ActionManager.cpp
+++ b/Generals/Code/GameEngine/Source/Common/RTS/ActionManager.cpp
@@ -482,7 +482,7 @@ Bool ActionManager::canResumeConstructionOf( const Object *obj,
// in the future)
//
Object *builder = TheGameLogic->findObjectByID( objectBeingConstructed->getBuilderID() );
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
if( builder )
#else
// TheSuperHackers @bugfix Stubbjax 18/11/2025 Allow scaffold to be immediately resumed after builder death.
diff --git a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp
index e9f29b1ec96..2c69d693223 100644
--- a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp
+++ b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp
@@ -2028,7 +2028,12 @@ void Player::doBountyForKill(const Object* killer, const Object* victim)
return;
Int costToBuild = victim->getTemplate()->calcCostToBuild(victim->getControllingPlayer());
+#if RETAIL_COMPATIBLE_CRC
Int bounty = REAL_TO_INT_CEIL(costToBuild * m_cashBountyPercent);
+#else
+ // TheSuperHackers @bugfix Stubbjax 20/02/2026 Subtract epsilon to ensure bounty is rounded up correctly.
+ Int bounty = ceil((costToBuild * m_cashBountyPercent) - WWMATH_EPSILON);
+#endif
if( bounty )
{
@@ -3356,7 +3361,7 @@ void Player::removeKindOfProductionCostChange( KindOfMaskType kindOf, Real perce
}
++it;
}
- DEBUG_ASSERTCRASH(FALSE, ("removeKindOfProductionCostChange was called with kindOf=%d and percent=%f. We could not find the entry in the list with these variables. CLH.",kindOf, percent));
+ DEBUG_CRASH(("removeKindOfProductionCostChange was called with kindOf=%d and percent=%f. We could not find the entry in the list with these variables. CLH.",kindOf, percent));
}
//-------------------------------------------------------------------------------------------------
diff --git a/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp b/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp
index 8d62650946c..0f289b1077a 100644
--- a/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp
+++ b/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp
@@ -52,6 +52,7 @@ TunnelTracker::TunnelTracker()
{
m_tunnelCount = 0;
m_containListSize = 0;
+ m_heroUnitsContained = 0;
m_curNemesisID = INVALID_ID;
m_nemesisTimestamp = 0;
m_framesForFullHeal = 0;
@@ -186,6 +187,11 @@ void TunnelTracker::addToContainList( Object *obj )
{
m_containList.push_back(obj);
++m_containListSize;
+
+ if (obj->isKindOf(KINDOF_HERO))
+ {
+ ++m_heroUnitsContained;
+ }
}
// ------------------------------------------------------------------------
@@ -198,6 +204,12 @@ void TunnelTracker::removeFromContain( Object *obj, Bool exposeStealthUnits )
// note that this invalidates the iterator!
m_containList.erase(it);
--m_containListSize;
+
+ if (obj->isKindOf(KINDOF_HERO))
+ {
+ DEBUG_ASSERTCRASH(m_heroUnitsContained > 0, ("TunnelTracker::removeFromContain - Removing hero but hero count is %d", m_heroUnitsContained));
+ --m_heroUnitsContained;
+ }
}
}
@@ -432,6 +444,8 @@ void TunnelTracker::loadPostProcess( void )
}
// translate each object ids on the xferContainList into real object pointers in the contain list
+ m_containListSize = 0;
+ m_heroUnitsContained = 0;
Object *obj;
std::list< ObjectID >::const_iterator it;
for( it = m_xferContainList.begin(); it != m_xferContainList.end(); ++it )
@@ -447,7 +461,7 @@ void TunnelTracker::loadPostProcess( void )
}
// push on the back of the contain list
- m_containList.push_back( obj );
+ addToContainList( obj );
// Crap. This is in OpenContain as a fix, but not here.
{
diff --git a/Generals/Code/GameEngine/Source/Common/Recorder.cpp b/Generals/Code/GameEngine/Source/Common/Recorder.cpp
index a2c38633b6a..d96406dec88 100644
--- a/Generals/Code/GameEngine/Source/Common/Recorder.cpp
+++ b/Generals/Code/GameEngine/Source/Common/Recorder.cpp
@@ -45,7 +45,7 @@
#include "GameLogic/GameLogic.h"
#include "Common/RandomValue.h"
#include "Common/CRCDebug.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
constexpr const char s_genrep[] = "GENREP";
diff --git a/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp
index f3363d35613..ed533c2179e 100644
--- a/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp
+++ b/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp
@@ -583,7 +583,7 @@ void BuildAssistant::iterateFootprint( const ThingTemplate *build,
else
{
- DEBUG_ASSERTCRASH( 0, ("iterateFootprint: Undefined geometry '%d' for '%s'",
+ DEBUG_CRASH( ("iterateFootprint: Undefined geometry '%d' for '%s'",
build->getTemplateGeometryInfo().getGeomType(), build->getName().str()) );
return;
diff --git a/Generals/Code/GameEngine/Source/GameClient/Color.cpp b/Generals/Code/GameEngine/Source/GameClient/Color.cpp
deleted file mode 100644
index deb83281ed9..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/Color.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Color.cpp ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Color.cpp
-//
-// Created: Colin Day, July 2001
-//
-// Desc: Management of color representations
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/Color.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-// GameMakeColor ==============================================================
-/** Create a color representation given red, green, blue, and
- * alpha components
- *
- * NOTE: pure solid white (255, 255, 255, 255) will translate
- * intoa -1 which is GAME_COLOR_UNDEFINED
- */
-//=============================================================================
-
-// GameGetColorComponents =====================================================
-/** Get the RGB color components of a color */
-//=============================================================================
-
-
-
-//Put on ice until later M Lorenzen
-//static UnsignedByte s_cheaterHasBeenSpied = 0;
-
-void GameGetColorComponents( Color color,
- UnsignedByte *red,
- UnsignedByte *green,
- UnsignedByte *blue,
- UnsignedByte *alpha )
-{
-
- *alpha = (color & 0xFF000000) >> 24;
- *red = (color & 0x00FF0000) >> 16;
- *green = (color & 0x0000FF00) >> 8;
- *blue = (color & 0x000000FF);
-
-}
-
-//Put on ice until later M Lorenzen
-//void GameGetColorComponentsWithCheatSpy( Color color,
-// UnsignedByte *red,
-// UnsignedByte *green,
-// UnsignedByte *blue,
-// UnsignedByte *alpha )
-//{
-//
-// *alpha |= (color & 0xFE000000) >> 24; // this waives the low order bit in alpha
-// s_cheaterHasBeenSpied |= *alpha & (1<<0); // this records it and gets angry
-// *red |= (color & 0x00FE0000) >> 16; // decoy
-// s_cheaterHasBeenSpied |= *red & (1<<8); // decoy
-// *green |= (color & 0x0000FE00) >> 8; // decoy
-// s_cheaterHasBeenSpied |= *green & (1<<17); // decoy
-// *blue |= (color & 0x000000FE) >> 0; // decoy
-// s_cheaterHasBeenSpied |= *blue & (1<<25); // decoy
-//
-//} // end GameGetColorComponents
-
-void GameGetColorComponentsReal( Color color, Real *red, Real *green, Real *blue, Real *alpha )
-{
- *alpha = ((color & 0xFF000000) >> 24) / 255.0f;
- *red = ((color & 0x00FF0000) >> 16) / 255.0f;
- *green = ((color & 0x0000FF00) >> 8) / 255.0f;
- *blue = (color & 0x000000FF) / 255.0f;
-}
-
-
-Color GameDarkenColor( Color color, Int percent )
-{
- // if they try to go to dark, just return their old color
- if(percent >= 90 || percent <= 0)
- return color;
-
- UnsignedByte r, g, b, a;
- GameGetColorComponents(color,&r,&g,&b,&a);
- r -= (r * percent / 100);
- g -= (g * percent / 100);
- b -= (b * percent / 100);
-
-// Put on ice until later M Lorenzen
-// TheWritableGlobalData->m_cheaterHasBeenSpiedIfMyLowestBitIsTrue = (r<<24) | (g<<16) | (b<<8) | s_cheaterHasBeenSpied;
-// DEBUG_ASSERTCRASH( TheWritableGlobalData->m_cheaterHasBeenSpiedIfMyLowestBitIsTrue == FALSE, ("DIRTY ROTTEN CHEATER"));
-// //my, but this looks like we just stored an alpha value along with rgb into the global data
-
-
-
-
- return GameMakeColor(r,g,b,a);
-
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/Credits.cpp b/Generals/Code/GameEngine/Source/GameClient/Credits.cpp
deleted file mode 100644
index 21eafbbd786..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/Credits.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Credits.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Dec 2002
-//
-// Filename: Credits.cpp
-//
-// author: Chris Huybregts
-//
-// purpose: This is where all the credit texts is going to be held.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "Common/INI.h"
-#include "GameClient/Credits.h"
-#include "GameClient/DisplayStringManager.h"
-#include "GameClient/Display.h"
-#include "GameClient/GameText.h"
-#include "GameClient/GlobalLanguage.h"
-
-
-//-----------------------------------------------------------------------------
-// DEFINES ////////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-CreditsManager *TheCredits = nullptr;
-
-const FieldParse CreditsManager::m_creditsFieldParseTable[] =
-{
-
- { "ScrollRate", INI::parseInt, nullptr, offsetof( CreditsManager, m_scrollRate ) },
- { "ScrollRateEveryFrames", INI::parseInt, nullptr, offsetof( CreditsManager, m_scrollRatePerFrames ) },
- { "ScrollDown", INI::parseBool, nullptr, offsetof( CreditsManager, m_scrollDown ) },
- { "TitleColor", INI::parseColorInt, nullptr, offsetof( CreditsManager, m_titleColor ) },
- { "MinorTitleColor", INI::parseColorInt, nullptr, offsetof( CreditsManager, m_positionColor ) },
- { "NormalColor", INI::parseColorInt, nullptr, offsetof( CreditsManager, m_normalColor ) },
- { "Style", INI::parseLookupList, CreditStyleNames, offsetof( CreditsManager, m_currentStyle ) },
- { "Blank", CreditsManager::parseBlank, nullptr, 0 },
- { "Text", CreditsManager::parseText, nullptr, 0 },
-
- { nullptr, nullptr, nullptr, 0 }
-
-};
-
-//-----------------------------------------------------------------------------
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-void INI::parseCredits( INI *ini )
-{
- // find existing item if present
- DEBUG_ASSERTCRASH( TheCredits, ("parseCredits: TheCredits has not been ininialized yet.") );
- if( !TheCredits )
- return;
-
- // parse the ini definition
- ini->initFromINI( TheCredits, TheCredits->getFieldParse() );
-
-}
-
-
-CreditsLine::CreditsLine()
-{
- m_useSecond = FALSE;
- m_done = FALSE;
- m_style = CREDIT_STYLE_BLANK;
- m_displayString = nullptr;
- m_secondDisplayString = nullptr;
-}
-
-CreditsLine::~CreditsLine()
-{
- if(m_displayString)
- TheDisplayStringManager->freeDisplayString(m_displayString);
- if(m_secondDisplayString)
- TheDisplayStringManager->freeDisplayString(m_secondDisplayString);
-
- m_displayString = nullptr;
- m_secondDisplayString = nullptr;
-}
-
-
-CreditsManager::CreditsManager(void)
-{
- m_scrollRate = 1; // in pixels
- m_scrollRatePerFrames = 1;
- m_scrollDown = TRUE; // if TRUE text will come from the top to the bottom if False, it will go from the bottom up
- m_framesSinceStarted = 0;
- m_titleColor = m_positionColor = m_normalColor = GameMakeColor(255,255,255,255);
-
- m_currentStyle = CREDIT_STYLE_NORMAL;
- m_isFinished = FALSE;
- m_normalFontHeight = 10;
-}
-
-CreditsManager::~CreditsManager(void)
-{
-
- m_displayedCreditLineList.clear();
- CreditsLineList::iterator it =m_creditLineList.begin();
- while (it != m_creditLineList.end())
- {
- CreditsLine *cLine = *it;
- delete cLine;
- it = m_creditLineList.erase(it);
- }
-}
-
-void CreditsManager::init(void )
-{
- m_isFinished = FALSE;
- m_creditLineListIt = m_creditLineList.begin();
- m_framesSinceStarted = 0;
-}
-
-void CreditsManager::load(void )
-{
- INI ini;
- // Read from INI all the ControlBarSchemes
- ini.loadFileDirectory( "Data\\INI\\Credits", INI_LOAD_OVERWRITE, nullptr );
-
- if(m_scrollRatePerFrames <=0)
- m_scrollRatePerFrames = 1;
- if(m_scrollRate <=0)
- m_scrollRate = 1;
-
- GameFont *font = TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
- TheGlobalLanguageData->m_creditsNormalFont.bold);
-
- m_normalFontHeight = font ? font->height : 0;
-}
-
-void CreditsManager::reset( void )
-{
- m_displayedCreditLineList.clear();
- m_isFinished = FALSE;
- m_creditLineListIt = m_creditLineList.begin();
- m_framesSinceStarted = 0;
-
-}
-
-void CreditsManager::update( void )
-{
- if(m_isFinished)
- return;
- m_framesSinceStarted++;
-
- if(m_framesSinceStarted%m_scrollRatePerFrames != 0)
- return;
-
-
- Int y = 0;
- Int yTest = 0;
- Int lastHeight = 0;
- Int start = m_scrollDown? 0:TheDisplay->getHeight();
- Int end =m_scrollDown? TheDisplay->getHeight():0;
- Int offsetStartMultiplier = m_scrollDown? -1:0; // if we're scrolling from the top, we need to subtract the height
- Int offsetEndMultiplier = m_scrollDown? 0:1;
- Int directionMultiplier = m_scrollDown? 1:-1;
- CreditsLineList::iterator drawIt = m_displayedCreditLineList.begin();
- while (drawIt != m_displayedCreditLineList.end())
- {
- CreditsLine *cLine = *drawIt;
- y = cLine->m_pos.y = cLine->m_pos.y + (m_scrollRate * directionMultiplier);
- lastHeight = cLine->m_height;
- yTest = y + ((lastHeight + CREDIT_SPACE_OFFSET) * offsetEndMultiplier);
- if(((m_scrollDown && (yTest > end)) || (!m_scrollDown && (yTest < end))))
- {
- TheDisplayStringManager->freeDisplayString(cLine->m_displayString);
- TheDisplayStringManager->freeDisplayString(cLine->m_secondDisplayString);
- cLine->m_displayString = nullptr;
- cLine->m_secondDisplayString = nullptr;
- drawIt = m_displayedCreditLineList.erase(drawIt);
- }
- else
- drawIt++;
- }
-
- y= y + ((lastHeight + CREDIT_SPACE_OFFSET) * offsetStartMultiplier);
-
- // is it time to add a new string?
- if(!((m_scrollDown && (yTest >= start)) || (!m_scrollDown && (yTest <= start))))
- return;
-
- if(m_displayedCreditLineList.empty() && m_creditLineListIt == m_creditLineList.end())
- m_isFinished = TRUE;
-
- if(m_creditLineListIt == m_creditLineList.end())
- return;
-
- CreditsLine *cLine = *m_creditLineListIt;
- ICoord2D pos;
- switch (cLine->m_style)
- {
- case CREDIT_STYLE_TITLE:
- {
- cLine->m_color = m_titleColor;
-
- if(TheGlobalLanguageData&& !cLine->m_text.isEmpty())
- {
- DisplayString *ds = TheDisplayStringManager->newDisplayString();
- if(!ds)
- return;
- ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsTitleFont.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsTitleFont.size),
- TheGlobalLanguageData->m_creditsTitleFont.bold));
- ds->setText(cLine->m_text);
- ds->getSize(&pos.x,&pos.y);
- cLine->m_height = pos.y;
- cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
- cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplier);
- cLine->m_displayString = ds;
- }
- }
- break;
- case CREDIT_STYLE_POSITION:
- {
- cLine->m_color = m_positionColor;
-
- if(TheGlobalLanguageData && !cLine->m_text.isEmpty())
- {
- DisplayString *ds = TheDisplayStringManager->newDisplayString();
- if(!ds)
- return;
- ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsPositionFont.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsPositionFont.size),
- TheGlobalLanguageData->m_creditsPositionFont.bold));
- ds->setText(cLine->m_text);
- ds->getSize(&pos.x,&pos.y);
- cLine->m_height = pos.y;
- cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
- cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplier);
- cLine->m_displayString = ds;
- }
- }
- break;
- case CREDIT_STYLE_NORMAL:
- {
- cLine->m_color = m_normalColor;
-
- if(TheGlobalLanguageData && !cLine->m_text.isEmpty())
- {
- DisplayString *ds = TheDisplayStringManager->newDisplayString();
- if(!ds)
- return;
- ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
- TheGlobalLanguageData->m_creditsNormalFont.bold));
- ds->setText(cLine->m_text);
- ds->getSize(&pos.x,&pos.y);
- cLine->m_height = pos.y;
- cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
- cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplier);
- cLine->m_displayString = ds;
- }
- }
- break;
- case CREDIT_STYLE_COLUMN:
- {
- cLine->m_color = m_normalColor;
-
- if(TheGlobalLanguageData && !cLine->m_text.isEmpty())
- {
- DisplayString *ds = TheDisplayStringManager->newDisplayString();
- if(!ds)
- return;
- ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
- TheGlobalLanguageData->m_creditsNormalFont.bold));
- ds->setText(cLine->m_text);
- ds->getSize(&pos.x,&pos.y);
- cLine->m_height = pos.y;
- cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
- cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplier);
- cLine->m_displayString = ds;
- }
- if(TheGlobalLanguageData && !cLine->m_secondText.isEmpty())
- {
- DisplayString *ds = TheDisplayStringManager->newDisplayString();
- if(!ds)
- return;
- ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
- TheGlobalLanguageData->m_creditsNormalFont.bold));
- ds->setText(cLine->m_secondText);
- ds->getSize(&pos.x,&pos.y);
- cLine->m_height = pos.y;
- cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
- cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplier);
- cLine->m_secondDisplayString = ds;
-
- }
- }
- break;
- case CREDIT_STYLE_BLANK:
- {
- cLine->m_height = m_normalFontHeight;
- cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplier);
- }
- break;
- }
-
- m_displayedCreditLineList.push_back(cLine);
-
- if(m_creditLineListIt != m_creditLineList.end())
- m_creditLineListIt++;
-
-}
-
-void CreditsManager::draw( void )
-{
- CreditsLineList::iterator drawIt = m_displayedCreditLineList.begin();
- while (drawIt != m_displayedCreditLineList.end())
- {
- CreditsLine *cLine = *drawIt;
- Int heightChunk = TheDisplay->getHeight()/3;
- Real perc = 0.0f;
- if(cLine->m_pos.y < heightChunk || cLine->m_pos.y > heightChunk * 2)
- {
- // adjust the color
- if( cLine->m_pos.y < 0 || cLine->m_pos.y > TheDisplay->getHeight())
- perc = 0.0f;
- else if( cLine->m_pos.y < heightChunk)
- perc = INT_TO_REAL(cLine->m_pos.y) / heightChunk;
- else
- perc = 1 - INT_TO_REAL(cLine->m_pos.y - 2*heightChunk) / heightChunk;
- }
- else
- perc = 1.0f;
- UnsignedByte r,g,b,a;
- GameGetColorComponents(cLine->m_color, &r, &g, &b, &a);
- Int color = GameMakeColor( r,g,b, a * perc);
- Int bColor= GameMakeColor( 0,0,0, a * perc);
-
- switch (cLine->m_style) {
- case CREDIT_STYLE_TITLE:
- case CREDIT_STYLE_POSITION:
- case CREDIT_STYLE_NORMAL:
- {
- if(cLine->m_displayString)
- cLine->m_displayString->draw(cLine->m_pos.x,cLine->m_pos.y,color, bColor, 1,1 );
- }
- break;
- case CREDIT_STYLE_COLUMN:
- {
- Int chunk = TheDisplay->getWidth()/3;
- ICoord2D pos;
- if(cLine->m_displayString)
- {
- cLine->m_displayString->getSize(&pos.x, &pos.y);
- cLine->m_displayString->draw(chunk - (pos.x/2),cLine->m_pos.y,color, bColor, 1,1 );
- }
- if(cLine->m_secondDisplayString)
- {
- cLine->m_secondDisplayString->getSize(&pos.x, &pos.y);
- cLine->m_secondDisplayString->draw(2*chunk - (pos.x/2),cLine->m_pos.y,color, bColor, 1,1 );
- }
- }
- break;
- }
-
- drawIt++;
- }
-}
-void CreditsManager::addBlank( void )
-{
- CreditsLine *cLine = new CreditsLine;
- cLine->m_style = CREDIT_STYLE_BLANK;
- m_creditLineList.push_back(cLine);
-}
-
-
-
-void CreditsManager::parseBlank( INI* ini, void *instance, void *store, const void *userData )
-{
- CreditsManager *cManager = (CreditsManager *)instance;
- cManager->addBlank();
-}
-
-void CreditsManager::parseText( INI* ini, void *instance, void *store, const void *userData )
-{
-
- AsciiString asciiString = ini->getNextQuotedAsciiString();
- CreditsManager *cManager = (CreditsManager *)instance;
- cManager->addText(asciiString);
-}
-void CreditsManager::addText( AsciiString text )
-{
- CreditsLine *cLine = new CreditsLine;
-
- switch (m_currentStyle)
- {
- case CREDIT_STYLE_TITLE:
- case CREDIT_STYLE_POSITION:
- case CREDIT_STYLE_NORMAL:
- {
- cLine->m_text = getUnicodeString(text);
- cLine->m_style = m_currentStyle;
- m_creditLineList.push_back(cLine);
- }
- break;
- case CREDIT_STYLE_COLUMN:
- {
- CreditsLineList::reverse_iterator rIt = m_creditLineList.rbegin();
- CreditsLine *rcLine = *rIt;
- if(rIt == m_creditLineList.rend() || rcLine->m_style != CREDIT_STYLE_COLUMN
- || (rcLine->m_style == CREDIT_STYLE_COLUMN && rcLine->m_done == TRUE))
- {
- cLine->m_text = getUnicodeString(text);
- cLine->m_style = CREDIT_STYLE_COLUMN;
- cLine->m_useSecond = TRUE;
- m_creditLineList.push_back(cLine);
- }
- else
- {
- rcLine->m_secondText = getUnicodeString(text);
- rcLine->m_done = TRUE;
- delete cLine;
- }
-
- }
- break;
- default:
- DEBUG_ASSERTCRASH( FALSE, ("CreditsManager::addText we tried to add a credit text with the wrong style before it. Style is %d", m_currentStyle) );
- delete cLine;
- }
-
-}
-
-//-----------------------------------------------------------------------------
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-UnicodeString CreditsManager::getUnicodeString(AsciiString str)
-{
- UnicodeString uStr;
- if(str.compare("") == 0)
- return UnicodeString::TheEmptyString;
-
- if(str.find(':'))
- uStr = TheGameText->fetch(str);
- else
- uStr.translate(str);
-
- return uStr;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/DisplayString.cpp b/Generals/Code/GameEngine/Source/GameClient/DisplayString.cpp
deleted file mode 100644
index 2367de67984..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/DisplayString.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DisplayString.cpp ////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: DisplayString.cpp
-//
-// Created: Colin Day, July 2001
-//
-// Desc: Contstuct for holding double byte game string data and being
-// able to draw that text to the screen.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Common/Debug.h"
-#include "Common/Language.h"
-#include "GameClient/DisplayString.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-// DisplayString::DisplayString ===============================================
-/** */
-//=============================================================================
-DisplayString::DisplayString( void )
-{
- // m_textString = ""; // not necessary, done by default
- m_font = nullptr;
-
- m_next = nullptr;
- m_prev = nullptr;
-
-}
-
-// DisplayString::~DisplayString ==============================================
-/** */
-//=============================================================================
-DisplayString::~DisplayString( void )
-{
-
- // free any data
- reset();
-
-}
-
-// DisplayString::setText =====================================================
-/** Copy the text to this instance */
-//=============================================================================
-void DisplayString::setText( UnicodeString text )
-{
- if (text == m_textString)
- return;
-
- m_textString = text;
-
- // our text has now changed
- notifyTextChanged();
-
-}
-
-// DisplayString::reset =======================================================
-/** Free and reset all the data for this string, effectively making this
- * instance like brand new */
-//=============================================================================
-void DisplayString::reset( void )
-{
-
- m_textString.clear();
-
- // no font
- m_font = nullptr;
-
-}
-
-// DisplayString::removeLastChar ==============================================
-/** Remove the last character from the string text */
-//=============================================================================
-void DisplayString::removeLastChar( void )
-{
- m_textString.removeLastChar();
-
- // our text has now changed
- notifyTextChanged();
-
-}
-
-// DisplayString::truncateBy ==================================================
-/** Remove the last charCount characters from the string text */
-//=============================================================================
-void DisplayString::truncateBy(const Int charCount)
-{
- m_textString.truncateBy(charCount);
-
- // our text has now changed
- notifyTextChanged();
-
-}
-
-// DisplayString::truncateTo ==================================================
-/** Remove the last characters from the string text so it's at the most
- * maxLength characters long */
- //=============================================================================
-void DisplayString::truncateTo(const Int maxLength)
-{
- m_textString.truncateTo(maxLength);
-
- // our text has now changed
- notifyTextChanged();
-
-}
-
-// DisplayString::appendChar ==================================================
-/** Append character to the end of the string */
-//=============================================================================
-void DisplayString::appendChar( WideChar c )
-{
- m_textString.concat(c);
-
- // text has now changed
- notifyTextChanged();
-
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/DisplayStringManager.cpp b/Generals/Code/GameEngine/Source/GameClient/DisplayStringManager.cpp
deleted file mode 100644
index 7f55378fd24..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/DisplayStringManager.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: DisplayStringManager.cpp /////////////////////////////////////////////////////////////////
-// Created: Colin Day, July 2001
-// Desc: Access for creating game managed display strings
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/DisplayStringManager.h"
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
-DisplayStringManager *TheDisplayStringManager = nullptr;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-DisplayStringManager::DisplayStringManager( void )
-{
-
- m_stringList = nullptr;
- m_currentCheckpoint = nullptr;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-DisplayStringManager::~DisplayStringManager( void )
-{
-
- //
- // we only keep track of the strings, we do NOT de-allocate them, our
- // list better be cleaned out before we destroy ourselves
- //
- assert( m_stringList == nullptr );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Link a display string to the master list */
-//-------------------------------------------------------------------------------------------------
-void DisplayStringManager::link( DisplayString *string )
-{
-
- assert( string );
- assert( string->m_next == nullptr );
- assert( string->m_prev == nullptr );
-
- string->m_next = m_stringList;
- if( m_stringList )
- m_stringList->m_prev = string;
-
- m_stringList = string;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Unlink a display string from the master list */
-//-------------------------------------------------------------------------------------------------
-void DisplayStringManager::unLink( DisplayString *string )
-{
-
- assert( string );
- assert( m_stringList );
-
- if( string->m_next )
- string->m_next->m_prev = string->m_prev;
- if( string->m_prev )
- string->m_prev->m_next = string->m_next;
- else
- {
-
- assert( string == m_stringList );
- m_stringList = string->m_next;
-
- }
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp b/Generals/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp
deleted file mode 100644
index 65742a9f76a..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// DrawGroupInfo.cpp //////////////////////////////////////////////////////////////////////////////
-// Author: John McDonald, October 2002
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/DrawGroupInfo.h"
-
-// Useful defaults.
-
-DrawGroupInfo::DrawGroupInfo()
-{
- m_fontName = "Arial";
- m_fontSize = 10;
- m_fontIsBold = FALSE;
-
- m_usePlayerColor = TRUE;
- m_colorForText = GameMakeColor(255, 255, 255, 255);
- m_colorForTextDropShadow = GameMakeColor(0, 0, 0, 255);
-
- m_dropShadowOffsetX = -1;
- m_dropShadowOffsetY = -1;
-
- m_percentOffsetX = -0.05f;
- m_usingPixelOffsetX = FALSE;
-
- m_pixelOffsetY = -10;
- m_usingPixelOffsetY = TRUE;
-}
-
-DrawGroupInfo *TheDrawGroupInfo = nullptr;
diff --git a/Generals/Code/GameEngine/Source/GameClient/FXList.cpp b/Generals/Code/GameEngine/Source/GameClient/FXList.cpp
deleted file mode 100644
index 6290a3ddaac..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/FXList.cpp
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: FXList.cpp ///////////////////////////////////////////////////////////////////////////////
-// Author: Steven Johnson, December 2001
-// Desc: FXList descriptions
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/FXList.h"
-
-#include "Common/DrawModule.h"
-#include "Common/GameAudio.h"
-#include "Common/GameUtility.h"
-#include "Common/INI.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/RandomValue.h"
-#include "Common/ThingTemplate.h"
-#include "Common/ThingFactory.h"
-
-#include "GameLogic/Object.h"
-#include "GameLogic/GameLogic.h"
-#include "GameLogic/TerrainLogic.h"
-#include "GameClient/Display.h"
-#include "GameClient/GameClient.h"
-#include "GameClient/Drawable.h"
-#include "GameClient/ParticleSys.h"
-#include "GameLogic/PartitionManager.h"
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-FXListStore *TheFXListStore = nullptr; ///< the FXList store definition
-
-//-------------------------------------------------------------------------------------------------
-static void adjustVector(Coord3D *vec, const Matrix3D* mtx)
-{
- if (mtx)
- {
- Vector3 vectmp;
- vectmp.X = vec->x;
- vectmp.Y = vec->y;
- vectmp.Z = vec->z;
- vectmp = mtx->Rotate_Vector(vectmp);
- vec->x = vectmp.X;
- vec->y = vectmp.Y;
- vec->z = vectmp.Z;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE CLASSES ///////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-void FXNugget::doFXObj(const Object* primary, const Object* secondary) const
-{
- const Coord3D* p = primary ? primary->getPosition() : nullptr;
- const Matrix3D* mtx = primary ? primary->getTransformMatrix() : nullptr;
- const Real speed = 0.0f; // yes, that's right -- NOT the object's speed.
- const Coord3D* s = secondary ? secondary->getPosition() : nullptr;
- doFXPos(p, mtx, speed, s);
-}
-
-//-------------------------------------------------------------------------------------------------
-class SoundFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(SoundFXNugget, "SoundFXNugget")
-
-public:
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
- {
- AudioEventRTS sound(m_soundName);
-
- if (primary)
- {
- sound.setPosition(primary);
- }
-
- TheAudio->addAudioEvent(&sound);
- }
-
- virtual void doFXObj(const Object* primary, const Object* secondary = nullptr) const
- {
- AudioEventRTS sound(m_soundName);
- if (primary)
- {
- sound.setPlayerIndex(primary->getControllingPlayer()->getPlayerIndex());
- sound.setPosition(primary->getPosition());
- }
-
- TheAudio->addAudioEvent(&sound);
- }
-
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "Name", INI::parseAsciiString, nullptr, offsetof( SoundFXNugget, m_soundName ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- SoundFXNugget* nugget = newInstance(SoundFXNugget);
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-private:
- AsciiString m_soundName;
-};
-EMPTY_DTOR(SoundFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-static Real calcDist(const Coord3D& src, const Coord3D& dst)
-{
- Real dx = dst.x - src.x;
- Real dy = dst.y - src.y;
- Real dz = dst.z - src.z;
- return sqrt(dx*dx + dy*dy + dz*dz);
-}
-
-//-------------------------------------------------------------------------------------------------
-class TracerFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TracerFXNugget, "TracerFXNugget")
-public:
-
- TracerFXNugget()
- {
- m_tracerName.set("GenericTracer");
- m_boneName.clear();
- m_speed = 0.0f; // means "use passed-in speed"
- m_decayAt = 1.0f;
- m_length = 10.0f;
- m_width = 1.0f;
- m_color.red = m_color.green = m_color.blue = 1.0f;
- m_probability = 1.0f;
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real primarySpeed, const Coord3D *secondary, const Real /*overrideRadius*/ ) const
- {
- if (m_probability <= GameClientRandomValueReal(0, 1))
- return;
-
- if (primary && secondary)
- {
- Drawable *tracer = TheThingFactory->newDrawable(TheThingFactory->findTemplate(m_tracerName));
- if(!tracer)
- return;
-
- //Kris -- Redid this section Sept 18, 2002
- //Calculate tracer orientations to face from primary to secondary position. This
- //should be the direction that the projectile is being fired towards. It doesn't make
- //sense that the old stuff made use of the muzzle fx bone orientation (because it's a
- //subobject). It had other problems because of elevation variations the tracers would
- //stay on the ground.
- //tracer->setTransformMatrix(primaryMtx);
- Matrix3D tracerMtx;
- Vector3 pos( primary->x, primary->y, primary->z );
- Vector3 dir( secondary->x - primary->x, secondary->y - primary->y, secondary->z - primary->z );
- dir.Normalize(); //This is fantastically crucial for calling buildTransformMatrix!!!!!
- tracerMtx.buildTransformMatrix( pos, dir );
- tracer->setTransformMatrix( &tracerMtx );
- tracer->setPosition(primary);
-
- Real speed = m_speed;
- if (speed == 0.0f)
- {
- speed = primarySpeed;
- }
-
- TracerDrawInterface* tdi = nullptr;
- for (DrawModule** d = tracer->getDrawModules(); *d; ++d)
- {
- if ((tdi = (*d)->getTracerDrawInterface()) != nullptr)
- {
- tdi->setTracerParms(speed, m_length, m_width, m_color, 1.0f);
- }
- }
-
- // estimate how long it will take us to get to the destination
- Real dist = calcDist(*primary, *secondary) - m_length;
- Real frames = (dist >= 0.0f && speed >= 0.0f) ? (dist / speed) : 1;
- Int framesAdjusted = REAL_TO_INT_CEIL(frames * m_decayAt);
- tracer->setExpirationDate(TheGameLogic->getFrame() + framesAdjusted);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary and secondary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "TracerName", INI::parseAsciiString, nullptr, offsetof( TracerFXNugget, m_tracerName ) },
- { "BoneName", INI::parseAsciiString, nullptr, offsetof( TracerFXNugget, m_boneName ) },
- { "Speed", INI::parseVelocityReal, nullptr, offsetof( TracerFXNugget, m_speed ) },
- { "DecayAt", INI::parseReal, nullptr, offsetof( TracerFXNugget, m_decayAt ) },
- { "Length", INI::parseReal, nullptr, offsetof( TracerFXNugget, m_length ) },
- { "Width", INI::parseReal, nullptr, offsetof( TracerFXNugget, m_width ) },
- { "Color", INI::parseRGBColor, nullptr, offsetof( TracerFXNugget, m_color ) },
- { "Probability", INI::parseReal, nullptr, offsetof( TracerFXNugget, m_probability ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- TracerFXNugget* nugget = newInstance( TracerFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-private:
- AsciiString m_tracerName;
- AsciiString m_boneName;
- Real m_speed;
- Real m_decayAt;
- Real m_length;
- Real m_width;
- RGBColor m_color;
- Real m_probability;
-};
-EMPTY_DTOR(TracerFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-class RayEffectFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(RayEffectFXNugget, "RayEffectFXNugget")
-public:
-
- RayEffectFXNugget()
- {
- m_templateName.clear();
- m_primaryOffset.x = m_primaryOffset.y = m_primaryOffset.z = 0;
- m_secondaryOffset.x = m_secondaryOffset.y = m_secondaryOffset.z = 0;
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * secondary, const Real /*overrideRadius*/ ) const
- {
- const ThingTemplate* tmpl = TheThingFactory->findTemplate(m_templateName);
- DEBUG_ASSERTCRASH(tmpl, ("RayEffect %s not found",m_templateName.str()));
- if (primary && secondary && tmpl)
- {
- Coord3D sourcePos = *primary;
- sourcePos.x += m_primaryOffset.x;
- sourcePos.y += m_primaryOffset.y;
- sourcePos.z += m_primaryOffset.z;
-
- Coord3D targetPos = *secondary;
- targetPos.x += m_secondaryOffset.x;
- targetPos.y += m_secondaryOffset.y;
- targetPos.z += m_secondaryOffset.z;
-
- TheGameClient->createRayEffectByTemplate(&sourcePos, &targetPos, tmpl);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary AND secondary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "Name", INI::parseAsciiString, nullptr, offsetof( RayEffectFXNugget, m_templateName ) },
- { "PrimaryOffset", INI::parseCoord3D, nullptr, offsetof( RayEffectFXNugget, m_primaryOffset ) },
- { "SecondaryOffset", INI::parseCoord3D, nullptr, offsetof( RayEffectFXNugget, m_secondaryOffset ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- RayEffectFXNugget* nugget = newInstance( RayEffectFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-private:
- AsciiString m_templateName;
- Coord3D m_primaryOffset;
- Coord3D m_secondaryOffset;
-};
-EMPTY_DTOR(RayEffectFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-class LightPulseFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(LightPulseFXNugget, "LightPulseFXNugget")
-public:
-
- LightPulseFXNugget() : m_radius(0), m_increaseFrames(0), m_decreaseFrames(0), m_boundingCirclePct(0)
- {
- m_color.red = m_color.green = m_color.blue = 0;
- }
-
- virtual void doFXObj(const Object* primary, const Object* /*secondary*/) const
- {
- if (primary)
- {
- Real radius = m_radius;
-
- if (m_boundingCirclePct > 0)
- radius = (primary->getGeometryInfo().getBoundingCircleRadius() * m_boundingCirclePct);
-
- TheDisplay->createLightPulse(primary->getPosition(), &m_color, 1, radius, m_increaseFrames, m_decreaseFrames);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
- {
- if (primary)
- {
- TheDisplay->createLightPulse(primary, &m_color, 1, m_radius, m_increaseFrames, m_decreaseFrames);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "Color", INI::parseRGBColor, nullptr, offsetof( LightPulseFXNugget, m_color ) },
- { "Radius", INI::parseReal, nullptr, offsetof( LightPulseFXNugget, m_radius ) },
- { "RadiusAsPercentOfObjectSize", INI::parsePercentToReal, nullptr, offsetof( LightPulseFXNugget, m_boundingCirclePct ) },
- { "IncreaseTime", INI::parseDurationUnsignedInt, nullptr, offsetof( LightPulseFXNugget, m_increaseFrames ) },
- { "DecreaseTime", INI::parseDurationUnsignedInt, nullptr, offsetof( LightPulseFXNugget, m_decreaseFrames ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- LightPulseFXNugget* nugget = newInstance( LightPulseFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-private:
- RGBColor m_color;
- Real m_radius;
- Real m_boundingCirclePct;
- UnsignedInt m_increaseFrames;
- UnsignedInt m_decreaseFrames;
-};
-EMPTY_DTOR(LightPulseFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-class ViewShakeFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ViewShakeFXNugget, "ViewShakeFXNugget")
-public:
-
- ViewShakeFXNugget() : m_shake(View::SHAKE_NORMAL)
- {
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
- {
- if (primary)
- {
- if (TheTacticalView)
- TheTacticalView->shake(primary, m_shake);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "Type", parseShakeType, nullptr, offsetof( ViewShakeFXNugget, m_shake ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- ViewShakeFXNugget* nugget = newInstance( ViewShakeFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-protected:
- static void parseShakeType( INI* ini, void *instance, void *store, const void* /*userData*/ )
- {
- static const LookupListRec shakeTypeNames[] =
- {
- { "SUBTLE", View::SHAKE_SUBTLE },
- { "NORMAL", View::SHAKE_NORMAL },
- { "STRONG", View::SHAKE_STRONG },
- { "SEVERE", View::SHAKE_SEVERE },
- { "CINE_EXTREME", View::SHAKE_CINE_EXTREME },
- { "CINE_INSANE", View::SHAKE_CINE_INSANE },
- { nullptr, 0 }
- };
- static_assert(ARRAY_SIZE(shakeTypeNames) == View::SHAKE_COUNT + 1, "Incorrect array size");
-
- *(Int *)store = INI::scanLookupList(ini->getNextToken(), shakeTypeNames);
- }
-
-private:
- View::CameraShakeType m_shake;
-
-};
-EMPTY_DTOR(ViewShakeFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-class TerrainScorchFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TerrainScorchFXNugget, "TerrainScorchFXNugget")
-public:
-
- TerrainScorchFXNugget() : m_scorch(-1), m_radius(0)
- {
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
- {
- if (primary)
- {
- Int scorch = m_scorch;
- if (scorch < 0)
- {
- scorch = GameClientRandomValue( SCORCH_1, SCORCH_4 );
- }
- TheGameClient->addScorch(primary, m_radius, (Scorches)scorch);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "Type", parseScorchType, nullptr, offsetof( TerrainScorchFXNugget, m_scorch ) },
- { "Radius", INI::parseReal, nullptr, offsetof( TerrainScorchFXNugget, m_radius ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- TerrainScorchFXNugget* nugget = newInstance( TerrainScorchFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-protected:
-
- static void parseScorchType( INI* ini, void *instance, void *store, const void* /*userData*/ )
- {
- static const LookupListRec scorchTypeNames[] =
- {
- { "SCORCH_1", SCORCH_1 },
- { "SCORCH_2", SCORCH_2 },
- { "SCORCH_3", SCORCH_3 },
- { "SCORCH_4", SCORCH_4 },
- { "SHADOW_SCORCH", SHADOW_SCORCH },
- { "RANDOM", -1 },
- { nullptr, 0 }
- };
- static_assert(ARRAY_SIZE(scorchTypeNames) == SCORCH_COUNT + 2, "Incorrect array size");
-
- *(Int *)store = INI::scanLookupList(ini->getNextToken(), scorchTypeNames);
- }
-
-private:
- Int m_scorch;
- Real m_radius;
-};
-EMPTY_DTOR(TerrainScorchFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-class ParticleSystemFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ParticleSystemFXNugget, "ParticleSystemFXNugget")
-public:
-
- ParticleSystemFXNugget()
- {
- m_name.clear();
- m_count = 1;
- m_radius.setRange(0, 0, GameClientRandomVariable::CONSTANT);
- m_height.setRange(0, 0, GameClientRandomVariable::CONSTANT);
- // -1 means "don't mess with it, just accept the particle-system's defaults"
- m_delay.setRange(-1, -1, GameClientRandomVariable::CONSTANT);
- m_offset.x = m_offset.y = m_offset.z = 0;
- m_orientToObject = false;
- m_attachToObject = false;
- m_createAtGroundHeight = FALSE;
- m_useCallersRadius = FALSE;
- m_rotateX = m_rotateY = m_rotateZ = 0;
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real overrideRadius ) const
- {
- if (primary)
- {
- reallyDoFX(primary, primaryMtx, nullptr, overrideRadius);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- virtual void doFXObj(const Object* primary, const Object* secondary) const
- {
- if (primary)
- {
-
- if (m_ricochet && secondary)
- {
- // HERE WE MUST BUILD A MATRIX WHICH WILL ORIENT THE NEW PARTICLE SYSTEM TO FACE AWAY FROM THE SECONDARY OBJECT
- // THE RESULT SHOULD LOOK LIKE THE DIRECTION OF THE "ATTACK" IS CARRIED THROUGH LIKE A RICOCHET
- Real deltaX = primary->getPosition()->x - secondary->getPosition()->x;
- Real deltaY = primary->getPosition()->y - secondary->getPosition()->y;
- Real aimingAngle = atan2(deltaY, deltaX);
- Matrix3D aimingMatrix(1);
- aimingMatrix.Rotate_Z( aimingAngle );
-
- reallyDoFX(primary->getPosition(), &aimingMatrix, primary, 0.0f);
- }
- else
- // if we have an object, then adjust the offset and direction by the object's transformation
- // matrix, so that (say) an offset of +10 in the z axis "follows" the orientation of the object.
- reallyDoFX(primary->getPosition(), primary->getTransformMatrix(), primary, 0.0f);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "Name", INI::parseAsciiString, nullptr, offsetof( ParticleSystemFXNugget, m_name ) },
- { "Count", INI::parseInt, nullptr, offsetof( ParticleSystemFXNugget, m_count ) },
- { "Offset", INI::parseCoord3D, nullptr, offsetof( ParticleSystemFXNugget, m_offset ) },
- { "Radius", INI::parseGameClientRandomVariable, nullptr, offsetof( ParticleSystemFXNugget, m_radius ) },
- { "Height", INI::parseGameClientRandomVariable, nullptr, offsetof( ParticleSystemFXNugget, m_height ) },
- { "InitialDelay", INI::parseGameClientRandomVariable, nullptr, offsetof( ParticleSystemFXNugget, m_delay ) },
- { "RotateX", INI::parseAngleReal, nullptr, offsetof( ParticleSystemFXNugget, m_rotateX ) },
- { "RotateY", INI::parseAngleReal, nullptr, offsetof( ParticleSystemFXNugget, m_rotateY ) },
- { "RotateZ", INI::parseAngleReal, nullptr, offsetof( ParticleSystemFXNugget, m_rotateZ ) },
- { "OrientToObject", INI::parseBool, nullptr, offsetof( ParticleSystemFXNugget, m_orientToObject ) },
- { "Ricochet", INI::parseBool, nullptr, offsetof( ParticleSystemFXNugget, m_ricochet ) },
- { "AttachToObject", INI::parseBool, nullptr, offsetof( ParticleSystemFXNugget, m_attachToObject ) },
- { "CreateAtGroundHeight", INI::parseBool, nullptr, offsetof( ParticleSystemFXNugget, m_createAtGroundHeight ) },
- { "UseCallersRadius", INI::parseBool, nullptr, offsetof( ParticleSystemFXNugget, m_useCallersRadius ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- ParticleSystemFXNugget* nugget = newInstance( ParticleSystemFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-protected:
-
- void reallyDoFX(const Coord3D *primary, const Matrix3D* mtx, const Object* thingToAttachTo, Real overrideRadius ) const
- {
- Coord3D offset = m_offset;
- if (mtx)
- {
- adjustVector(&offset, mtx);
- }
-
- const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate(m_name);
- DEBUG_ASSERTCRASH(tmp, ("ParticleSystem %s not found",m_name.str()));
- if (tmp)
- {
- for (Int i = 0; i < m_count; i++ )
- {
- ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp);
- if (sys)
- {
- Coord3D newPos;
- Real radius = m_radius.getValue();
- Real angle = GameClientRandomValueReal( 0.0f, 2.0f * PI );
-
- newPos.x = primary->x + offset.x + radius * cos(angle);
- newPos.y = primary->y + offset.y + radius * sin(angle);
- if( m_createAtGroundHeight && TheTerrainLogic )
- {
- //old way:
- //newPos.z = TheTerrainLogic->getGrsoundHeight( newPos.x, newPos.y ) + 1;// The plus one prevents scissoring with terrain
-
- //new way: now we allow bridges in the GroundHeight.
- PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination(&newPos);
- newPos.z = TheTerrainLogic->getLayerHeight( newPos.x, newPos.y, layer );
- }
- else
- newPos.z = primary->z + offset.z + m_height.getValue();
-
-
- if (m_orientToObject && mtx)
- {
- sys->setLocalTransform(mtx);
- }
- if (m_rotateX != 0.0f)
- sys->rotateLocalTransformX(m_rotateX);
- if (m_rotateY != 0.0f)
- sys->rotateLocalTransformY(m_rotateY);
- if (m_rotateZ != 0.0f)
- sys->rotateLocalTransformZ(m_rotateZ);
-
- if (m_attachToObject && thingToAttachTo)
- sys->attachToObject(thingToAttachTo);
- else
- sys->setPosition( &newPos );
-
- Real delayInMsec = m_delay.getValue();
- if (delayInMsec >= 0.0f)
- {
- UnsignedInt delayInFrames = REAL_TO_INT_CEIL(ConvertDurationFromMsecsToFrames(delayInMsec));
- sys->setInitialDelay(delayInFrames);
- }
-
- if( m_useCallersRadius && overrideRadius )
- {
- ParticleSystemInfo::EmissionVolumeType type = sys->getEmisionVolumeType();
-
- if( type == ParticleSystemInfo::EmissionVolumeType::SPHERE )
- sys->setEmissionVolumeSphereRadius( overrideRadius );
- else if( type == ParticleSystemInfo::EmissionVolumeType::CYLINDER )
- sys->setEmissionVolumeCylinderRadius( overrideRadius );
- }
- }
- }
- }
- }
-
-
-private:
- AsciiString m_name;
- Int m_count;
- Coord3D m_offset;
- GameClientRandomVariable m_radius;
- GameClientRandomVariable m_height;
- GameClientRandomVariable m_delay;
- Real m_rotateX, m_rotateY, m_rotateZ;
- Bool m_orientToObject;
- Bool m_attachToObject;
- Bool m_createAtGroundHeight;
- Bool m_useCallersRadius;
- Bool m_ricochet;
-};
-EMPTY_DTOR(ParticleSystemFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-class FXListAtBonePosFXNugget : public FXNugget
-{
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(FXListAtBonePosFXNugget, "FXListAtBonePosFXNugget")
-public:
-
- FXListAtBonePosFXNugget()
- {
- m_fx = nullptr;
- m_boneName.clear();
- m_orientToBone = true;
- }
-
- virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
- {
- DEBUG_CRASH(("You must use the object form for this effect"));
- }
-
- virtual void doFXObj(const Object* primary, const Object* /*secondary*/) const
- {
- if (primary)
- {
- // first, try the unadorned name.
- doFxAtBones(primary, 0);
-
- // then, try the 01,02,03...etc names.
- doFxAtBones(primary, 1);
- }
- else
- {
- DEBUG_CRASH(("You must have a primary source for this effect"));
- }
- }
-
- static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
- {
- static const FieldParse myFieldParse[] =
- {
- { "FX", INI::parseFXList, nullptr, offsetof( FXListAtBonePosFXNugget, m_fx ) },
- { "BoneName", INI::parseAsciiString, nullptr, offsetof( FXListAtBonePosFXNugget, m_boneName ) },
- { "OrientToBone", INI::parseBool, nullptr, offsetof( FXListAtBonePosFXNugget, m_orientToBone ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- FXListAtBonePosFXNugget* nugget = newInstance( FXListAtBonePosFXNugget );
- ini->initFromINI(nugget, myFieldParse);
- ((FXList*)instance)->addFXNugget(nugget);
- }
-
-protected:
-
- void doFxAtBones(const Object* obj, Int start) const
- {
- Coord3D bonePos[MAX_BONE_POINTS];
- Matrix3D boneMtx[MAX_BONE_POINTS];
-
- Drawable* draw = obj->getDrawable();
- if (draw)
- {
- // yes, BONEPOS_CURRENT_CLIENT_ONLY -- this is client-only, so should be safe to do.
- Int count = draw->getCurrentClientBonePositions(m_boneName.str(), start, bonePos, boneMtx, MAX_BONE_POINTS);
- for (Int i = 0; i < count; ++i)
- {
- Coord3D p;
- Matrix3D m;
- obj->convertBonePosToWorldPos(&bonePos[i], &boneMtx[i], &p, &m);
- FXList::doFXPos(m_fx, &p, &m, 0.0f, nullptr, 0.0f);
- }
- }
- }
-
-private:
-
- enum { MAX_BONE_POINTS = 40 };
-
- const FXList* m_fx;
- AsciiString m_boneName;
- Bool m_orientToBone;
-};
-EMPTY_DTOR(FXListAtBonePosFXNugget)
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-
-static const FieldParse TheFXListFieldParse[] =
-{
- { "Sound", SoundFXNugget::parse, nullptr, 0},
- { "RayEffect", RayEffectFXNugget::parse, nullptr, 0},
- { "Tracer", TracerFXNugget::parse, nullptr, 0},
- { "LightPulse", LightPulseFXNugget::parse, nullptr, 0},
- { "ViewShake", ViewShakeFXNugget::parse, nullptr, 0},
- { "TerrainScorch", TerrainScorchFXNugget::parse, nullptr, 0},
- { "ParticleSystem", ParticleSystemFXNugget::parse, nullptr, 0},
- { "FXListAtBonePos", FXListAtBonePosFXNugget::parse, nullptr, 0},
- { nullptr, nullptr, nullptr, 0 }
-};
-
-//-------------------------------------------------------------------------------------------------
-FXList::FXList()
-{
-}
-
-//-------------------------------------------------------------------------------------------------
-FXList::~FXList()
-{
- clear();
-}
-
-//-------------------------------------------------------------------------------------------------
-void FXList::clear()
-{
- for (FXNuggetList::iterator it = m_nuggets.begin(); it != m_nuggets.end(); ++it)
- {
- deleteInstance(*it);
- }
- m_nuggets.clear();
-}
-
-//-------------------------------------------------------------------------------------------------
-void FXList::doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real primarySpeed, const Coord3D *secondary, const Real overrideRadius ) const
-{
- const Int playerIndex = rts::getObservedOrLocalPlayer()->getPlayerIndex();
-
- if (ThePartitionManager->getShroudStatusForPlayer(playerIndex, primary) != CELLSHROUD_CLEAR)
- return;
-
- for (FXNuggetList::const_iterator it = m_nuggets.begin(); it != m_nuggets.end(); ++it)
- {
- (*it)->doFXPos(primary, primaryMtx, primarySpeed, secondary, overrideRadius);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-void FXList::doFXObj(const Object* primary, const Object* secondary) const
-{
- const Int playerIndex = rts::getObservedOrLocalPlayer()->getPlayerIndex();
-
- if (primary && primary->getShroudedStatus(playerIndex) > OBJECTSHROUD_PARTIAL_CLEAR)
- return; //the primary object is fogged or shrouded so don't bother with the effect.
-
- for (FXNuggetList::const_iterator it = m_nuggets.begin(); it != m_nuggets.end(); ++it)
- {
-
- // HERE THE PRIMARY IS THE GUY RECEIVING THE FX, AND SECONDARY MIGHT BE THE GUY DEALING IT
- (*it)->doFXObj(primary, secondary);
- }
-}
-
-
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-
-//-------------------------------------------------------------------------------------------------
-FXListStore::FXListStore()
-{
-}
-
-//-------------------------------------------------------------------------------------------------
-FXListStore::~FXListStore()
-{
- m_fxmap.clear();
-}
-
-//-------------------------------------------------------------------------------------------------
-const FXList *FXListStore::findFXList(const char* name) const
-{
- if (stricmp(name, "None") == 0)
- return nullptr;
-
- FXListMap::const_iterator it = m_fxmap.find(NAMEKEY(name));
- if (it != m_fxmap.end())
- {
- return &(*it).second;
- }
- return nullptr;
-}
-
-//-------------------------------------------------------------------------------------------------
-/*static */ void FXListStore::parseFXListDefinition(INI *ini)
-{
- // read the FXList name
- const char *c = ini->getNextToken();
- NameKeyType key = TheNameKeyGenerator->nameToKey(c);
- FXList& fxl = TheFXListStore->m_fxmap[key];
- fxl.clear();
- ini->initFromINI(&fxl, TheFXListFieldParse);
-}
-
-//-------------------------------------------------------------------------------------------------
-/*static*/ void INI::parseFXListDefinition(INI *ini)
-{
- FXListStore::parseFXListDefinition(ini);
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp
index bb3cb404ed8..a379a01439f 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp
@@ -2354,7 +2354,7 @@ void ControlBar::switchToContext( ControlBarContext context, Drawable *draw )
default:
{
- DEBUG_ASSERTCRASH( 0, ("ControlBar::switchToContext, unknown context '%d'", context) );
+ DEBUG_CRASH( ("ControlBar::switchToContext, unknown context '%d'", context) );
break;
}
@@ -2415,7 +2415,7 @@ void ControlBar::setControlCommand( GameWindow *button, const CommandButton *com
if( button->winGetInputFunc() != GadgetPushButtonInput )
{
- DEBUG_ASSERTCRASH( 0, ("setControlCommand: Window is not a button") );
+ DEBUG_CRASH( ("setControlCommand: Window is not a button") );
return;
}
@@ -2424,7 +2424,7 @@ void ControlBar::setControlCommand( GameWindow *button, const CommandButton *com
if( commandButton == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("setControlCommand: null commandButton passed in") );
+ DEBUG_CRASH( ("setControlCommand: null commandButton passed in") );
return;
}
@@ -2526,7 +2526,7 @@ void ControlBar::setControlCommand( const AsciiString& buttonWindowName, GameWin
if( win == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("setControlCommand: Unable to find window '%s'", buttonWindowName.str()) );
+ DEBUG_CRASH( ("setControlCommand: Unable to find window '%s'", buttonWindowName.str()) );
return;
}
@@ -2995,7 +2995,7 @@ void ControlBar::switchControlBarStage( ControlBarStages stage )
setHiddenControlBar();
break;
default:
- DEBUG_ASSERTCRASH(FALSE,("ControlBar::switchControlBarStage we were passed in a stage that's not supported %d", stage));
+ DEBUG_CRASH(("ControlBar::switchControlBarStage we were passed in a stage that's not supported %d", stage));
}
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp
index e49697e6b8a..d2755500274 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp
@@ -92,7 +92,7 @@ void ControlBar::populateInvDataCallback( Object *obj, void *userData )
if( data->currIndex > data->maxIndex )
{
- DEBUG_ASSERTCRASH( 0, ("There is not enough GUI slots to hold the # of items inside a '%s'",
+ DEBUG_CRASH( ("There is not enough GUI slots to hold the # of items inside a '%s'",
data->transport->getTemplate()->getName().str()) );
return;
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
index 359d837ebfa..d42df100b2d 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
@@ -292,7 +292,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
}
else if (cmt != CANMAKE_OK)
{
- DEBUG_ASSERTCRASH( 0, ("Cannot create '%s' because the factory object '%s' returns false for canMakeUnit",
+ DEBUG_CRASH( ("Cannot create '%s' because the factory object '%s' returns false for canMakeUnit",
whatToBuild->getName().str(),
factory->getTemplate()->getName().str()) );
break;
@@ -305,7 +305,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
if( pu == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("Cannot create '%s' because the factory object '%s' is not capable of producing units",
+ DEBUG_CRASH( ("Cannot create '%s' because the factory object '%s' is not capable of producing units",
whatToBuild->getName().str(),
factory->getTemplate()->getName().str()) );
break;
@@ -339,7 +339,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
if( i == MAX_BUILD_QUEUE_BUTTONS )
{
- DEBUG_ASSERTCRASH( 0, ("Control not found in build queue data") );
+ DEBUG_CRASH( ("Control not found in build queue data") );
break;
}
@@ -463,7 +463,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
if( i == MAX_BUILD_QUEUE_BUTTONS )
{
- DEBUG_ASSERTCRASH( 0, ("Control not found in build queue data") );
+ DEBUG_CRASH( ("Control not found in build queue data") );
break;
}
@@ -731,7 +731,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
//---------------------------------------------------------------------------------------------
default:
- DEBUG_ASSERTCRASH( 0, ("Unknown command '%d'", commandButton->getCommandType()) );
+ DEBUG_CRASH( ("Unknown command '%d'", commandButton->getCommandType()) );
return CBC_COMMAND_NOT_USED;
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp
index bc1a4b564c2..6d1804603d8 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp
@@ -117,7 +117,7 @@ ResizerWindow *ControlBarResizer::findResizerWindow( AsciiString name )
ResizerWindow *rWin = *it;
if( !rWin )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::findResizerWindow"));
+ DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::findResizerWindow"));
it++;
continue;
}
@@ -160,7 +160,7 @@ void ControlBarResizer::sizeWindowsDefault( void )
ResizerWindow *rWin = *it;
if( !rWin )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
+ DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
it++;
continue;
}
@@ -187,7 +187,7 @@ void ControlBarResizer::sizeWindowsAlt( void )
ResizerWindow *rWin = *it;
if( !rWin )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
+ DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
it++;
continue;
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp
index 9171033cf2f..e44b9630cf8 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp
@@ -658,7 +658,7 @@ void ControlBarScheme::addAnimation( ControlBarSchemeAnimation *schemeAnim )
{
if( !schemeAnim )
{
- DEBUG_ASSERTCRASH(FALSE,("Trying to add a null animation to the controlbarscheme"));
+ DEBUG_CRASH(("Trying to add a null animation to the controlbarscheme"));
return;
}
m_animations.push_back( schemeAnim );
@@ -671,13 +671,13 @@ void ControlBarScheme::addImage( ControlBarSchemeImage *schemeImage )
{
if( !schemeImage )
{
- DEBUG_ASSERTCRASH(FALSE,("Trying to add a null image to the controlbarscheme"));
+ DEBUG_CRASH(("Trying to add a null image to the controlbarscheme"));
return;
}
if(schemeImage->m_layer < 0 || schemeImage->m_layer >= MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS)
{
- DEBUG_ASSERTCRASH(FALSE,("SchemeImage %s attempted to be added to layer %d which is not Between to %d, %d",
+ DEBUG_CRASH(("SchemeImage %s attempted to be added to layer %d which is not Between to %d, %d",
schemeImage->m_name.str(), schemeImage->m_layer, 0, MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS));
// bring the foobar to the front so we make it obvious that something's wrong
schemeImage->m_layer = 0;
@@ -700,7 +700,7 @@ void ControlBarScheme::updateAnim (ControlBarSchemeAnimation * anim)
}
default:
{
- DEBUG_ASSERTCRASH(FALSE,("We tried to animate but not animate function was found %d", anim->m_animType));
+ DEBUG_CRASH(("We tried to animate but not animate function was found %d", anim->m_animType));
}
}
}
@@ -717,7 +717,7 @@ void ControlBarScheme::update( void )
ControlBarSchemeAnimation *anim = *it;
if( !anim )
{
- DEBUG_ASSERTCRASH(FALSE,("THere's no Animation in the ControlBarSchemeAnimationList:m_animations"));
+ DEBUG_CRASH(("THere's no Animation in the ControlBarSchemeAnimationList:m_animations"));
return;
}
updateAnim( anim );
@@ -739,7 +739,7 @@ void ControlBarScheme::drawForeground( Coord2D multi, ICoord2D offset )
ControlBarSchemeImage *schemeImage = *it;
if( !schemeImage )
{
- DEBUG_ASSERTCRASH(FALSE,("There is no ControlBarSchemeImage found in the m_layer list"));
+ DEBUG_CRASH(("There is no ControlBarSchemeImage found in the m_layer list"));
it++;
continue;
}
@@ -776,7 +776,7 @@ void ControlBarScheme::drawBackground( Coord2D multi, ICoord2D offset )
ControlBarSchemeImage *schemeImage = *it;
if( !schemeImage )
{
- DEBUG_ASSERTCRASH(FALSE,("There is no ControlBarSchemeImage found in the m_layer list"));
+ DEBUG_CRASH(("There is no ControlBarSchemeImage found in the m_layer list"));
it++;
continue;
}
@@ -899,7 +899,7 @@ ControlBarScheme *ControlBarSchemeManager::newControlBarScheme( AsciiString name
ControlBarScheme *cbScheme = findControlBarScheme(name);
if(cbScheme)
{
- DEBUG_ASSERTCRASH(false,("We're overwriting a previous control bar scheme %s",name.str()));
+ DEBUG_CRASH(("We're overwriting a previous control bar scheme %s",name.str()));
cbScheme->reset();
cbScheme->m_name.set( name );
cbScheme->m_name.toLower();
@@ -910,7 +910,7 @@ ControlBarScheme *ControlBarSchemeManager::newControlBarScheme( AsciiString name
if( !cbScheme || name.isEmpty() )
{
- DEBUG_ASSERTCRASH(FALSE,("Could not create controlbar %s", name.str()));
+ DEBUG_CRASH(("Could not create controlbar %s", name.str()));
return nullptr;
}
@@ -937,7 +937,7 @@ ControlBarScheme *ControlBarSchemeManager::findControlBarScheme( AsciiString nam
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
return nullptr;
}
if(CBScheme->m_name.compareNoCase( name ) == 0)
@@ -957,7 +957,7 @@ void ControlBarSchemeManager::preloadAssets( TimeOfDay timeOfDay )
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
continue;
}
@@ -1011,7 +1011,7 @@ void ControlBarSchemeManager::init( void )
// }
if( m_schemeList.empty() )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList that was just read from the INI file"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList that was just read from the INI file"));
return;
}
@@ -1033,7 +1033,7 @@ void ControlBarSchemeManager::setControlBarScheme(AsciiString schemeName)
}
else
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
m_currentScheme = nullptr;
}
if(m_currentScheme)
@@ -1092,7 +1092,7 @@ void ControlBarSchemeManager::setControlBarSchemeByPlayerTemplate( const PlayerT
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
it++;
continue;
}
@@ -1160,7 +1160,7 @@ void ControlBarSchemeManager::setControlBarSchemeByPlayer(Player *p)
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
it++;
continue;
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
index e544a18f0c8..09132073d4a 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
@@ -537,7 +537,7 @@ void ControlBar::populateBuildTooltipLayout( const CommandButton *commandButton,
}
else
{
- DEBUG_ASSERTCRASH(FALSE, ("ControlBar::populateBuildTooltipLayout We attempted to call the popup tooltip on a game window that has yet to be hand coded in as this fuction was/is designed for only buttons but has been hacked to work with GameWindows."));
+ DEBUG_CRASH(("ControlBar::populateBuildTooltipLayout We attempted to call the popup tooltip on a game window that has yet to be hand coded in as this fuction was/is designed for only buttons but has been hacked to work with GameWindows."));
return;
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp
index ccd05dcd86a..ee2000cabae 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp
@@ -123,7 +123,7 @@ static GameWindow *gogoExMessageBox(Int x, Int y, Int width, Int height, Unsigne
//we shouldn't have button OK and Yes on the same dialog
if((buttonFlags & (MSG_BOX_OK | MSG_BOX_YES)) == (MSG_BOX_OK | MSG_BOX_YES) )
{
- DEBUG_ASSERTCRASH(false, ("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
+ DEBUG_CRASH(("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
}
//Position the OK button if we have one
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp
index 51c1e0a5615..2f81cdb01c6 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp
@@ -51,7 +51,7 @@
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/WindowLayout.h"
#include "GameClient/Gadget.h"
#include "GameClient/Shell.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp
index 96b8ce5471c..654c1b855e7 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp
@@ -40,7 +40,7 @@
#include "Common/Player.h"
#include "Common/PlayerTemplate.h"
#include "Common/QuotedPrintable.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/ClientInstance.h"
#include "GameClient/GameText.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp
index 27806fc907c..e7bd45b8ba2 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp
@@ -38,7 +38,7 @@
#include "Common/GlobalData.h"
#include "Common/NameKeyGenerator.h"
#include "Common/RandomValue.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/ExtendedMessageBox.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp
index 08435310692..ea0844cd577 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp
@@ -33,7 +33,7 @@
#include "Common/GameEngine.h"
#include "Common/MessageStream.h"
#include "Common/RandomValue.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameLogic/GameLogic.h"
#include "GameLogic/ScriptEngine.h"
#include "GameClient/AnimateWindowManager.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp
index 23a0c17767b..1412088c582 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp
@@ -34,7 +34,7 @@
#include "gamespy/peer/peer.h"
#include "Common/QuotedPrintable.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/WindowLayout.h"
#include "GameClient/Gadget.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
index 6222ac9232b..8a6937575d7 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
@@ -36,7 +36,7 @@
#include "Common/AudioSettings.h"
#include "Common/GameAudio.h"
#include "Common/GameEngine.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/GameLOD.h"
#include "Common/Recorder.h"
#include "Common/Registry.h"
@@ -206,800 +206,6 @@ extern void DoResolutionDialog();
static Bool ignoreSelected = FALSE;
WindowLayout *OptionsLayout = nullptr;
-
-OptionPreferences::OptionPreferences( void )
-{
- loadFromIniFile();
-}
-
-OptionPreferences::~OptionPreferences()
-{
-}
-
-Bool OptionPreferences::loadFromIniFile()
-{
- if (rts::ClientInstance::getInstanceId() > 1u)
- {
- AsciiString fname;
- fname.format("Options_Instance%.2u.ini", rts::ClientInstance::getInstanceId());
- return load(fname);
- }
-
- return load("Options.ini");
-}
-
-Int OptionPreferences::getCampaignDifficulty(void)
-{
- OptionPreferences::const_iterator it = find("CampaignDifficulty");
- if (it == end())
- return TheScriptEngine->getGlobalDifficulty();
-
- Int factor = atoi(it->second.str());
- if (factor < DIFFICULTY_EASY)
- factor = DIFFICULTY_EASY;
- if (factor > DIFFICULTY_HARD)
- factor = DIFFICULTY_HARD;
-
- return factor;
-}
-
-void OptionPreferences::setCampaignDifficulty( Int diff )
-{
- AsciiString prefString;
- prefString.format("%d", diff );
- (*this)["CampaignDifficulty"] = prefString;
-}
-
-UnsignedInt OptionPreferences::getLANIPAddress(void)
-{
- AsciiString selectedIP = (*this)["IPAddress"];
- IPEnumeration IPs;
- EnumeratedIP *IPlist = IPs.getAddresses();
- while (IPlist)
- {
- if (selectedIP.compareNoCase(IPlist->getIPstring()) == 0)
- {
- return IPlist->getIP();
- }
- IPlist = IPlist->getNext();
- }
- return TheGlobalData->m_defaultIP;
-}
-
-void OptionPreferences::setLANIPAddress( AsciiString IP )
-{
- (*this)["IPAddress"] = IP;
-}
-
-void OptionPreferences::setLANIPAddress( UnsignedInt IP )
-{
- AsciiString tmp;
- tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP));
- (*this)["IPAddress"] = tmp;
-}
-
-UnsignedInt OptionPreferences::getOnlineIPAddress(void)
-{
- AsciiString selectedIP = (*this)["GameSpyIPAddress"];
- IPEnumeration IPs;
- EnumeratedIP *IPlist = IPs.getAddresses();
- while (IPlist)
- {
- if (selectedIP.compareNoCase(IPlist->getIPstring()) == 0)
- {
- return IPlist->getIP();
- }
- IPlist = IPlist->getNext();
- }
- return TheGlobalData->m_defaultIP;
-}
-
-void OptionPreferences::setOnlineIPAddress( AsciiString IP )
-{
- (*this)["GameSpyIPAddress"] = IP;
-}
-
-void OptionPreferences::setOnlineIPAddress( UnsignedInt IP )
-{
- AsciiString tmp;
- tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP));
- (*this)["GameSpyIPAddress"] = tmp;
-}
-
-Bool OptionPreferences::getArchiveReplaysEnabled() const
-{
- OptionPreferences::const_iterator it = find("ArchiveReplays");
- if (it == end())
- return FALSE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getAlternateMouseModeEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseAlternateMouse");
- if (it == end())
- return TheGlobalData->m_useAlternateMouse;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getRetaliationModeEnabled(void)
-{
- OptionPreferences::const_iterator it = find("Retaliation");
- if (it == end())
- return TheGlobalData->m_clientRetaliationModeEnabled;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getDoubleClickAttackMoveEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseDoubleClickAttackMove");
- if( it == end() )
- return TheGlobalData->m_doubleClickAttackMove;
-
- if( stricmp( it->second.str(), "yes" ) == 0 )
- return TRUE;
-
- return FALSE;
-}
-
-Real OptionPreferences::getScrollFactor(void)
-{
- OptionPreferences::const_iterator it = find("ScrollFactor");
- if (it == end())
- return TheGlobalData->m_keyboardDefaultScrollFactor;
-
- Int factor = atoi(it->second.str());
-
- // TheSuperHackers @tweak xezon 11/07/2025
- // No longer caps the upper limit to 100, because the options setting can go beyond that.
- // No longer caps the lower limit to 0, because that would mean standstill.
- if (factor < 1)
- factor = 1;
-
- return factor/100.0f;
-}
-
-Bool OptionPreferences::getDrawScrollAnchor(void)
-{
- OptionPreferences::const_iterator it = find("DrawScrollAnchor");
- // TheSuperHackers @info this default is based on the same variable within InGameUi.ini
- if (it == end())
- return FALSE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getMoveScrollAnchor(void)
-{
- OptionPreferences::const_iterator it = find("MoveScrollAnchor");
- // TheSuperHackers @info this default is based on the same variable within InGameUi.ini
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInWindowedGame() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInWindowedGame");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInWindowedGame) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInWindowedMenu() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInWindowedMenu");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInWindowedMenu) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInFullscreenGame() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInFullscreenGame");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInFullscreenGame) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInFullscreenMenu() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInFullscreenMenu");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInFullscreenMenu) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-CursorCaptureMode OptionPreferences::getCursorCaptureMode() const
-{
- CursorCaptureMode mode = 0;
- mode |= getCursorCaptureEnabledInWindowedGame() ? CursorCaptureMode_EnabledInWindowedGame : 0;
- mode |= getCursorCaptureEnabledInWindowedMenu() ? CursorCaptureMode_EnabledInWindowedMenu : 0;
- mode |= getCursorCaptureEnabledInFullscreenGame() ? CursorCaptureMode_EnabledInFullscreenGame : 0;
- mode |= getCursorCaptureEnabledInFullscreenMenu() ? CursorCaptureMode_EnabledInFullscreenMenu : 0;
- return mode;
-}
-
-Bool OptionPreferences::getScreenEdgeScrollEnabledInWindowedApp() const
-{
- OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInWindowedApp");
- if (it == end())
- return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getScreenEdgeScrollEnabledInFullscreenApp() const
-{
- OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInFullscreenApp");
- if (it == end())
- return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-ScreenEdgeScrollMode OptionPreferences::getScreenEdgeScrollMode() const
-{
- ScreenEdgeScrollMode mode = 0;
- mode |= getScreenEdgeScrollEnabledInWindowedApp() ? ScreenEdgeScrollMode_EnabledInWindowedApp : 0;
- mode |= getScreenEdgeScrollEnabledInFullscreenApp() ? ScreenEdgeScrollMode_EnabledInFullscreenApp : 0;
- return mode;
-}
-
-Bool OptionPreferences::usesSystemMapDir(void)
-{
- OptionPreferences::const_iterator it = find("UseSystemMapDir");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::saveCameraInReplays(void)
-{
- OptionPreferences::const_iterator it = find("SaveCameraInReplays");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::useCameraInReplays(void)
-{
- OptionPreferences::const_iterator it = find("UseCameraInReplays");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getPlayerObserverEnabled() const
-{
- OptionPreferences::const_iterator it = find("PlayerObserverEnabled");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Int OptionPreferences::getIdealStaticGameDetail(void)
-{
- OptionPreferences::const_iterator it = find("IdealStaticGameLOD");
- if (it == end())
- return STATIC_GAME_LOD_UNKNOWN;
-
- return TheGameLODManager->getStaticGameLODIndex(it->second);
-}
-
-Int OptionPreferences::getStaticGameDetail(void)
-{
- OptionPreferences::const_iterator it = find("StaticGameLOD");
- if (it == end())
- return TheGameLODManager->getStaticLODLevel();
-
- return TheGameLODManager->getStaticGameLODIndex(it->second);
-}
-
-Bool OptionPreferences::getSendDelay(void)
-{
- OptionPreferences::const_iterator it = find("SendDelay");
- if (it == end())
- return TheGlobalData->m_firewallSendDelay;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Int OptionPreferences::getFirewallBehavior()
-{
- OptionPreferences::const_iterator it = find("FirewallBehavior");
- if (it == end())
- return TheGlobalData->m_firewallBehavior;
-
- Int behavior = atoi(it->second.str());
- if (behavior < 0)
- {
- behavior = 0;
- }
- return behavior;
-}
-
-Short OptionPreferences::getFirewallPortAllocationDelta()
-{
- OptionPreferences::const_iterator it = find("FirewallPortAllocationDelta");
- if (it == end()) {
- return TheGlobalData->m_firewallPortAllocationDelta;
- }
-
- Short delta = atoi(it->second.str());
- return delta;
-}
-
-UnsignedShort OptionPreferences::getFirewallPortOverride()
-{
- OptionPreferences::const_iterator it = find("FirewallPortOverride");
- if (it == end()) {
- return TheGlobalData->m_firewallPortOverride;
- }
-
- Int override = atoi(it->second.str());
- if (override < 0 || override > 65535)
- override = 0;
- return override;
-}
-
-Bool OptionPreferences::getFirewallNeedToRefresh()
-{
- OptionPreferences::const_iterator it = find("FirewallNeedToRefresh");
- if (it == end()) {
- return FALSE;
- }
-
- Bool retval = FALSE;
- AsciiString str = it->second;
- if (str.compareNoCase("TRUE") == 0) {
- retval = TRUE;
- }
- return retval;
-}
-
-AsciiString OptionPreferences::getPreferred3DProvider(void)
-{
- OptionPreferences::const_iterator it = find("3DAudioProvider");
- if (it == end())
- return TheAudio->getAudioSettings()->m_preferred3DProvider[MAX_HW_PROVIDERS];
- return it->second;
-}
-
-AsciiString OptionPreferences::getSpeakerType(void)
-{
- OptionPreferences::const_iterator it = find("SpeakerType");
- if (it == end())
- return TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getAudioSettings()->m_defaultSpeakerType2D);
- return it->second;
-}
-
-Real OptionPreferences::getSoundVolume(void)
-{
- OptionPreferences::const_iterator it = find("SFXVolume");
- if (it == end())
- {
- Real relative = TheAudio->getAudioSettings()->m_relative2DVolume;
- if( relative < 0 )
- {
- Real scale = 1.0f + relative;
- return TheAudio->getAudioSettings()->m_defaultSoundVolume * 100.0f * scale;
- }
- return TheAudio->getAudioSettings()->m_defaultSoundVolume * 100.0f;
- }
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Real OptionPreferences::get3DSoundVolume(void)
-{
- OptionPreferences::const_iterator it = find("SFX3DVolume");
- if (it == end())
- {
- Real relative = TheAudio->getAudioSettings()->m_relative2DVolume;
- if( relative > 0 )
- {
- Real scale = 1.0f - relative;
- return TheAudio->getAudioSettings()->m_default3DSoundVolume * 100.0f * scale;
- }
- return TheAudio->getAudioSettings()->m_default3DSoundVolume * 100.0f;
- }
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Real OptionPreferences::getSpeechVolume(void)
-{
- OptionPreferences::const_iterator it = find("VoiceVolume");
- if (it == end())
- return TheAudio->getAudioSettings()->m_defaultSpeechVolume * 100.0f;
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Bool OptionPreferences::getCloudShadowsEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseCloudMap");
- if (it == end())
- return TheGlobalData->m_useCloudMap;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getLightmapEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseLightMap");
- if (it == end())
- return TheGlobalData->m_useLightMap;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getSmoothWaterEnabled(void)
-{
- OptionPreferences::const_iterator it = find("ShowSoftWaterEdge");
- if (it == end())
- return TheGlobalData->m_showSoftWaterEdge;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getTreesEnabled(void)
-{
- OptionPreferences::const_iterator it = find("ShowTrees");
- if (it == end())
- return TheGlobalData->m_useTrees;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getExtraAnimationsDisabled(void)
-{
- OptionPreferences::const_iterator it = find("ExtraAnimations");
- if (it == end())
- return TheGlobalData->m_useDrawModuleLOD;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return FALSE; //we are enabling extra animations, so disabled LOD
- }
- return TRUE;
-}
-
-Bool OptionPreferences::getUseHeatEffects(void)
-{
- OptionPreferences::const_iterator it = find("HeatEffects");
- if (it == end())
- return TheGlobalData->m_useHeatEffects;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getDynamicLODEnabled(void)
-{
- OptionPreferences::const_iterator it = find("DynamicLOD");
- if (it == end())
- return TheGlobalData->m_enableDynamicLOD;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getFPSLimitEnabled(void)
-{
- OptionPreferences::const_iterator it = find("FPSLimit");
- if (it == end())
- return TheGlobalData->m_useFpsLimit;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::get3DShadowsEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseShadowVolumes");
- if (it == end())
- return TheGlobalData->m_useShadowVolumes;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::get2DShadowsEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseShadowDecals");
- if (it == end())
- return TheGlobalData->m_useShadowDecals;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getBuildingOcclusionEnabled(void)
-{
- OptionPreferences::const_iterator it = find("BuildingOcclusion");
- if (it == end())
- return TheGlobalData->m_enableBehindBuildingMarkers;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Int OptionPreferences::getParticleCap(void)
-{
- OptionPreferences::const_iterator it = find("MaxParticleCount");
- if (it == end())
- return TheGlobalData->m_maxParticleCount;
-
- Int factor = (Int) atoi(it->second.str());
- if (factor < 100) //clamp to at least 100 particles.
- factor = 100;
-
- return factor;
-}
-
-Int OptionPreferences::getTextureReduction(void)
-{
- OptionPreferences::const_iterator it = find("TextureReduction");
- if (it == end())
- return -1; //unknown texture reduction
-
- Int factor = (Int) atoi(it->second.str());
- if (factor > 2) //clamp it.
- factor=2;
- return factor;
-}
-
-Real OptionPreferences::getGammaValue(void)
-{
- OptionPreferences::const_iterator it = find("Gamma");
- if (it == end())
- return 50.0f;
-
- Real gamma = (Real) atoi(it->second.str());
- return gamma;
-}
-
-void OptionPreferences::getResolution(Int *xres, Int *yres)
-{
- *xres = TheGlobalData->m_xResolution;
- *yres = TheGlobalData->m_yResolution;
-
- OptionPreferences::const_iterator it = find("Resolution");
- if (it == end())
- return;
-
- Int selectedXRes,selectedYRes;
- if (sscanf(it->second.str(),"%d%d", &selectedXRes, &selectedYRes) != 2)
- return;
-
- *xres=selectedXRes;
- *yres=selectedYRes;
-}
-
-Real OptionPreferences::getMusicVolume(void)
-{
- OptionPreferences::const_iterator it = find("MusicVolume");
- if (it == end())
- return TheAudio->getAudioSettings()->m_defaultMusicVolume * 100.0f;
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Real OptionPreferences::getMoneyTransactionVolume(void) const
-{
- OptionPreferences::const_iterator it = find("MoneyTransactionVolume");
- if (it == end())
- return TheAudio->getAudioSettings()->m_defaultMoneyTransactionVolume * 100.0f;
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- volume = 0.0f;
-
- return volume;
-}
-
-Int OptionPreferences::getNetworkLatencyFontSize(void)
-{
- OptionPreferences::const_iterator it = find("NetworkLatencyFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getRenderFpsFontSize(void)
-{
- OptionPreferences::const_iterator it = find("RenderFpsFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getSystemTimeFontSize(void)
-{
- OptionPreferences::const_iterator it = find("SystemTimeFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getGameTimeFontSize(void)
-{
- OptionPreferences::const_iterator it = find("GameTimeFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getPlayerInfoListFontSize(void)
-{
- OptionPreferences::const_iterator it = find("PlayerInfoListFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Real OptionPreferences::getResolutionFontAdjustment(void)
-{
- OptionPreferences::const_iterator it = find("ResolutionFontAdjustment");
- if (it == end())
- return -1.0f;
-
- Real fontScale = (Real)atof(it->second.str()) / 100.0f;
- if (fontScale < 0.0f)
- {
- fontScale = -1.0f;
- }
- return fontScale;
-}
-
-Bool OptionPreferences::getShowMoneyPerMinute(void) const
-{
- OptionPreferences::const_iterator it = find("ShowMoneyPerMinute");
- if (it == end())
- return TheGlobalData->m_showMoneyPerMinute;
-
- if (stricmp(it->second.str(), "yes") == 0)
- {
- return TRUE;
- }
- return FALSE;
-}
-
static OptionPreferences *pref = nullptr;
static void setDefaults( void )
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp
index 9cb4b869650..fb7323848de 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp
@@ -200,6 +200,11 @@ static void restartMissionMenu()
Int gameMode = TheGameLogic->getGameMode();
AsciiString mapName = TheGlobalData->m_mapName;
+ // TheSuperHackers @bugfix Caball009 07/02/2026 Reuse the previous seed value for the new skirmish match to prevent mismatches.
+ // Campaign, challenge, and skirmish single-player scenarios all use GAME_SINGLE_PLAYER and are expected to use 0 as seed value.
+ DEBUG_ASSERTCRASH((TheSkirmishGameInfo != nullptr) == (gameMode == GAME_SKIRMISH), ("Unexpected game mode on map / mission restart"));
+ const Int seed = TheSkirmishGameInfo ? TheSkirmishGameInfo->getSeed() : 0;
+
//
// if the map name was from a save game it will have "Save/" at the front of it,
// we want to go back to the original pristine map string for the map name when restarting
@@ -238,11 +243,8 @@ static void restartMissionMenu()
TheScriptEngine->getGlobalDifficulty(),
rankPointsStartedWith)
);
- //if (TheGlobalData->m_fixedSeed >= 0)
- //InitRandom(TheGlobalData->m_fixedSeed);
- InitRandom(0);
- //else
- // InitGameLogicRandom(GameClientRandomValue(0, INT_MAX - 1));
+
+ InitRandom(seed);
}
//TheTransitionHandler->remove("QuitFull"); //KRISMORNESS ADD
//quitMenuLayout = nullptr; //KRISMORNESS ADD
@@ -371,7 +373,7 @@ void ToggleQuitMenu()
// load the quit menu from the layout file if needed
if( quitMenuLayout == nullptr )
{
- DEBUG_ASSERTCRASH(FALSE, ("Could not load a quit menu layout"));
+ DEBUG_CRASH(("Could not load a quit menu layout"));
isVisible = FALSE;
TheInGameUI->setQuitMenuVisible(FALSE);
return;
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp
index b6b2ea80f41..9c294162375 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp
@@ -1187,7 +1187,7 @@ void populatePlayerInfo( Player *player, Int pos)
ScoreKeeper *scoreKpr = player->getScoreKeeper();
if(!scoreKpr)
{
- DEBUG_ASSERTCRASH(FALSE,("Player %s does not have a scoreKeeper", player->getPlayerDisplayName().str()));
+ DEBUG_CRASH(("Player %s does not have a scoreKeeper", player->getPlayerDisplayName().str()));
return;
}
AsciiString winName;
@@ -1591,36 +1591,7 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
if (TheNetwork->sawCRCMismatch())
{
++stats.desyncs[ptIdx];
- }
- else if (gameEndedInDisconnect)
- {
- ++stats.discons[ptIdx];
- }
- else if (TheVictoryConditions->isLocalAlliedDefeat() || !TheVictoryConditions->getEndFrame())
- {
- ++stats.losses[ptIdx];
- }
- else
- {
- ++stats.wins[ptIdx];
- }
-
- ScoreKeeper *s = player->getScoreKeeper();
- stats.buildingsBuilt[ptIdx] += s->getTotalBuildingsBuilt();
- stats.buildingsKilled[ptIdx] += s->getTotalBuildingsDestroyed();
- stats.buildingsLost[ptIdx] += s->getTotalBuildingsLost();
-
- if (TheGameSpyGame->isQMGame())
- {
- stats.QMGames[ptIdx]++;
- }
- else
- {
- stats.customGames[ptIdx]++;
- }
- if (TheNetwork->sawCRCMismatch())
- {
stats.lossesInARow = 0;
stats.desyncsInARow++;
stats.disconsInARow = 0;
@@ -1629,6 +1600,8 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
}
else if (gameEndedInDisconnect)
{
+ ++stats.discons[ptIdx];
+
stats.lossesInARow = 0;
stats.desyncsInARow = 0;
stats.disconsInARow++;
@@ -1637,6 +1610,8 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
}
else if (TheVictoryConditions->isLocalAlliedVictory())
{
+ ++stats.wins[ptIdx];
+
stats.lossesInARow = 0;
stats.desyncsInARow = 0;
stats.disconsInARow = 0;
@@ -1645,6 +1620,8 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
}
else
{
+ ++stats.losses[ptIdx];
+
stats.lossesInARow++;
stats.desyncsInARow = 0;
stats.disconsInARow = 0;
@@ -1652,6 +1629,20 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
stats.maxLossesInARow = max(stats.lossesInARow, stats.maxLossesInARow);
}
+ ScoreKeeper *s = player->getScoreKeeper();
+ stats.buildingsBuilt[ptIdx] += s->getTotalBuildingsBuilt();
+ stats.buildingsKilled[ptIdx] += s->getTotalBuildingsDestroyed();
+ stats.buildingsLost[ptIdx] += s->getTotalBuildingsLost();
+
+ if (TheGameSpyGame->isQMGame())
+ {
+ stats.QMGames[ptIdx]++;
+ }
+ else
+ {
+ stats.customGames[ptIdx]++;
+ }
+
stats.earnings[ptIdx] += s->getTotalMoneyEarned();
stats.duration[ptIdx] += TheGameLogic->getFrame() / LOGICFRAMES_PER_SECOND / 60; // in minutes
stats.games[ptIdx]++;
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp
index 77800e749ae..843b87df4ee 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp
@@ -256,7 +256,7 @@ Int SkirmishPreferences::getPreferredFaction(void)
Bool SkirmishPreferences::usesSystemMapDir(void)
{
- OptionPreferences::const_iterator it = find("UseSystemMapDir");
+ SkirmishPreferences::const_iterator it = find("UseSystemMapDir");
if (it == end())
return TRUE;
@@ -420,7 +420,6 @@ void reallyDoStart( void )
TheWritableGlobalData->m_mapName = TheSkirmishGameInfo->getMap();
TheSkirmishGameInfo->startGame(0);
- InitGameLogicRandom(TheSkirmishGameInfo->getSeed());
Bool isSkirmish = TRUE;
const MapMetaData *md = TheMapCache->findMap(TheSkirmishGameInfo->getMap());
@@ -431,6 +430,8 @@ void reallyDoStart( void )
if (isSkirmish)
{
+ InitGameLogicRandom(TheSkirmishGameInfo->getSeed());
+
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
msg->appendIntegerArgument(GAME_SKIRMISH);
msg->appendIntegerArgument(DIFFICULTY_NORMAL); // not really used; just specified so we can add the game speed last
@@ -439,6 +440,8 @@ void reallyDoStart( void )
}
else
{
+ InitGameLogicRandom(0);
+
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
msg->appendIntegerArgument(GAME_SINGLE_PLAYER);
msg->appendIntegerArgument(DIFFICULTY_NORMAL); // not really used; just specified so we can add the game speed last
@@ -735,7 +738,7 @@ void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPosition
}
else
{
- DEBUG_ASSERTCRASH(FALSE,("positionStartSpots:: someone messed with the map cash. We couldn't find waypoint <%s> in map <%s>", waypointName.str(),lowerMap.str()));
+ DEBUG_CRASH(("positionStartSpots:: someone messed with the map cash. We couldn't find waypoint <%s> in map <%s>", waypointName.str(),lowerMap.str()));
}
}
// hide the rest
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp
index 0b5efc26d29..0df35bb63a0 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp
@@ -188,7 +188,7 @@ void InitBuddyControls(Int type)
case BUDDY_WINDOW_WELCOME_SCREEN:
break;
default:
- DEBUG_ASSERTCRASH(FALSE, ("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either"));
+ DEBUG_CRASH(("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either"));
}
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp
index b52212b0374..82376bce101 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp
@@ -32,8 +32,9 @@
#include "Common/GameEngine.h"
#include "Common/GameState.h"
-#include "GameClient/GameText.h"
#include "Common/MultiplayerSettings.h"
+#include "Common/OptionPreferences.h"
+#include "GameClient/GameText.h"
#include "Common/PlayerTemplate.h"
#include "Common/CustomMatchPreferences.h"
#include "GameClient/AnimateWindowManager.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp
index 9e868449842..2560e3b68df 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp
@@ -39,7 +39,7 @@
#include "Common/GameSpyMiscPreferences.h"
#include "Common/QuotedPrintable.h"
#include "Common/Registry.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/ClientInstance.h"
#include "GameClient/WindowLayout.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp
index e4982952296..23bb24173ec 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp
@@ -35,6 +35,7 @@
#include "Common/QuickmatchPreferences.h"
#include "Common/LadderPreferences.h"
#include "Common/MultiplayerSettings.h"
+#include "Common/OptionPreferences.h"
#include "Common/PlayerTemplate.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/WindowLayout.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp
index 7913b610757..96769530207 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp
@@ -395,7 +395,7 @@ WindowMsgHandledType GadgetComboBoxSystem( GameWindow *window, UnsignedInt msg,
GadgetListBoxGetSelected(comboData->listBox, (Int *)mData2);
else
{
- DEBUG_ASSERTCRASH(0,("We don't have a listbox as part of the combo box"));
+ DEBUG_CRASH(("We don't have a listbox as part of the combo box"));
*(Int *)mData2 = -1;
}
break;
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp
index 5c71e3ce255..cd943ef7a47 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp
@@ -344,7 +344,7 @@ static Int addImageEntry( const Image *image, Color color, Int row, Int column,
if( column >= list->columns || row >= list->listLength )
{
- DEBUG_ASSERTCRASH(false, ("Tried to add Image to Listbox at invalid position"));
+ DEBUG_CRASH(("Tried to add Image to Listbox at invalid position"));
return -1;
}
@@ -447,7 +447,7 @@ static Int addEntry( UnicodeString *string, Int color, Int row, Int column, Game
// make sure our params are good
if( column >= list->columns || row >= list->listLength )
{
- DEBUG_ASSERTCRASH(false, ("Tried to add text to Listbox at invalid position"));
+ DEBUG_CRASH(("Tried to add text to Listbox at invalid position"));
return -1;
}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp
deleted file mode 100644
index b05a0a4ce9b..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameFont.cpp /////////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, June 2001
-// Desc: Access to our representation for fonts
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/GameFont.h"
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
-FontLibrary *TheFontLibrary = nullptr;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** Link a font to the font list */
-//-------------------------------------------------------------------------------------------------
-void FontLibrary::linkFont( GameFont *font )
-{
-
- // sanity
- if( font == nullptr )
- return;
-
- // link it
- font->next = m_fontList;
- m_fontList = font;
-
- // increment linked count
- m_count++;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Unlink a font from the font list */
-//-------------------------------------------------------------------------------------------------
-void FontLibrary::unlinkFont( GameFont *font )
-{
- GameFont *other = nullptr;
-
- // sanity
- if( font == nullptr )
- return;
-
- // sanity check and make sure this font is actually in this library
- for( other = m_fontList; other; other = other->next )
- if( other == font )
- break;
- if( other == nullptr )
- {
-
- DEBUG_CRASH(( "Font '%s' not found in library", font->nameString.str() ));
- return;
-
- }
-
- // scan for the font pointing to the one we're going to unlink
- for( other = m_fontList; other; other = other->next )
- if( other->next == font )
- break;
-
- //
- // if nothing was fount this was at the head of the list, otherwise
- // remove from chain
- //
- if( other == nullptr )
- m_fontList = font->next;
- else
- other->next = font->next;
-
- // clean up this font we just unlinked just to be cool!
- font->next = nullptr;
-
- // we now have one less font on the list
- m_count--;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Delete all font data, DO NOT throw an exception ... the destructor uses this */
-//-------------------------------------------------------------------------------------------------
-void FontLibrary::deleteAllFonts( void )
-{
- GameFont *font;
-
- // release all the fonts
- while( m_fontList )
- {
-
- // get temp pointer to this font
- font = m_fontList;
-
- // remove font from the list, this will change m_fontList
- unlinkFont( font );
-
- // release font data
- releaseFontData( font );
-
- // delete the font list element
- deleteInstance(font);
-
- }
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-FontLibrary::FontLibrary( void )
-{
-
- m_fontList = nullptr;
- m_count = 0;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-FontLibrary::~FontLibrary( void )
-{
-
- // delete all font data
- deleteAllFonts();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Initialize what we need to in the font library */
-//-------------------------------------------------------------------------------------------------
-void FontLibrary::init( void )
-{
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset the fonts for this font library */
-//-------------------------------------------------------------------------------------------------
-void FontLibrary::reset( void )
-{
-
- // delete all font data
- deleteAllFonts();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Get a font from our list, if we don't have that font loaded we will
- * attempt to load it */
-//-------------------------------------------------------------------------------------------------
-GameFont *FontLibrary::getFont( AsciiString name, Int pointSize, Bool bold )
-{
- // sanity check the size - anything over 100 is probably wrong. -MW
- // TheSuperHackers @fix Now also no longer creates fonts with zero size.
- if (pointSize < 1 || pointSize > 100)
- {
- return nullptr;
- }
-
- GameFont *font;
-
- // search for font in list
- for( font = m_fontList; font; font = font->next )
- {
-
- if( font->pointSize == pointSize &&
- font->bold == bold &&
- font->nameString == name
- )
- return font; // found
-
- }
-
- // font not found, allocate a new font element
- font = newInstance(GameFont);
- if( font == nullptr )
- {
-
- DEBUG_CRASH(( "getFont: Unable to allocate new font list element" ));
- return nullptr;
-
- }
-
- // copy font data over to new element
- font->nameString = name;
- font->pointSize = pointSize;
- font->bold = bold;
- font->fontData = nullptr;
-
- //DEBUG_LOG(("Font: Loading font '%s' %d point", font->nameString.str(), font->pointSize));
- // load the device specific data pointer
- if( loadFontData( font ) == FALSE )
- {
-
- DEBUG_CRASH(( "getFont: Unable to load font data pointer '%s'", name.str() ));
- deleteInstance(font);
- return nullptr;
-
- }
-
- // tie font into list
- linkFont( font );
-
- // all is done and loaded
- return font;
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp
deleted file mode 100644
index 11b5174d18d..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp
+++ /dev/null
@@ -1,1837 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameWindow.cpp ///////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: GameWindow.cpp
-//
-// Created: Dean Iverson, March 1998
-// Colin Day, June 2001
-//
-// Desc: Game window implementation
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Common/AudioEventRTS.h"
-#include "Common/Language.h"
-#include "GameClient/WindowLayout.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameClient/Gadget.h"
-#include "GameClient/DisplayStringManager.h"
-#include "GameClient/GadgetListBox.h"
-#include "GameClient/GadgetComboBox.h"
-#include "GameClient/GadgetTextEntry.h"
-#include "GameClient/GadgetStaticText.h"
-#include "GameClient/Mouse.h"
-#include "GameClient/SelectionXlat.h"
-#include "GameClient/GameWindowTransitions.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-
-// GameWindow::GameWindow =====================================================
-//=============================================================================
-GameWindow::GameWindow( void )
-{
- m_status = WIN_STATUS_NONE;
-
- m_size.x = 0;
- m_size.y = 0;
-
- m_region.lo.x = 0;
- m_region.lo.y = 0;
- m_region.hi.x = 0;
- m_region.hi.y = 0;
-
- m_cursorX = 0;
- m_cursorY = 0;
-
- m_userData = nullptr;
-
- m_inputData = nullptr;
-
- winSetDrawFunc( TheWindowManager->getDefaultDraw() );
- winSetInputFunc( TheWindowManager->getDefaultInput() );
- winSetSystemFunc( TheWindowManager->getDefaultSystem() );
- // We use to set the default tooltip func to TheWindowManager->getDefaultTooltip()
- // but I removed this so that we can set in GUI edit a text string that will be the
- // default tool tip for a control.
- winSetTooltipFunc( nullptr );
-
- m_next = nullptr;
- m_prev = nullptr;
- m_parent = nullptr;
- m_child = nullptr;
-
- m_nextLayout = nullptr;
- m_prevLayout = nullptr;
- m_layout = nullptr;
-
- m_editData = nullptr;
-
-}
-
-// GameWindow::~GameWindow ====================================================
-//=============================================================================
-GameWindow::~GameWindow( void )
-{
-
- delete m_inputData;
- m_inputData = nullptr;
-
- delete m_editData;
- m_editData = nullptr;
-
- unlinkFromTransitionWindows();
-
-}
-
-// GameWindow::linkTransitionWindow ============================================
-//=============================================================================
-void GameWindow::linkTransitionWindow( TransitionWindow* transitionWindow )
-{
-
- m_transitionWindows.push_back(transitionWindow);
-
-}
-
-// GameWindow::unlinkTransitionWindow =========================================
-//=============================================================================
-void GameWindow::unlinkTransitionWindow( TransitionWindow* transitionWindow )
-{
-
- std::vector::iterator it = m_transitionWindows.begin();
- while ( it != m_transitionWindows.end() )
- {
- if ( *it == transitionWindow )
- {
- *it = m_transitionWindows.back();
- m_transitionWindows.pop_back();
- return;
- }
- ++it;
- }
-
-}
-
-// GameWindow::unlinkFromTransitionWindows =========================================
-//=============================================================================
-void GameWindow::unlinkFromTransitionWindows( void )
-{
-
- while ( !m_transitionWindows.empty() )
- {
- m_transitionWindows.back()->unlinkGameWindow(this);
- m_transitionWindows.pop_back();
- }
-
-}
-
-// GameWindow::normalizeWindowRegion ==========================================
-/** Puts the upper left corner in the window's region.lo field */
-//=============================================================================
-void GameWindow::normalizeWindowRegion( void )
-{
- Int temp;
-
- if( m_region.lo.x > m_region.hi.x)
- {
-
- temp = m_region.lo.x;
- m_region.lo.x = m_region.hi.x;
- m_region.hi.x = temp;
-
- }
-
- if( m_region.lo.y > m_region.hi.y )
- {
-
- temp = m_region.lo.y;
- m_region.lo.y = m_region.hi.y;
- m_region.hi.y = temp;
-
- }
-
-}
-
-// GameWindow::findFirstLeaf ==================================================
-/** Returns the first leaf of the branch */
-//=============================================================================
-GameWindow *GameWindow::findFirstLeaf( void )
-{
- GameWindow *leaf = this;
-
- // Find the root of this branch
- while( leaf->m_parent )
- leaf = leaf->m_parent;
-
- // Find the first leaf
- while( leaf->m_child )
- leaf = leaf->m_child;
-
- return leaf;
-
-}
-
-// GameWindow::findLastLeaf ===================================================
-/** Returns the last leaf of the branch */
-//=============================================================================
-GameWindow *GameWindow::findLastLeaf( void )
-{
- GameWindow *leaf = this;
-
- // Find the root of this branch
- while( leaf->m_parent )
- leaf = leaf->m_parent;
-
- // Find the last leaf
- while( leaf->m_child )
- {
-
- leaf = leaf->m_child;
-
- while( leaf->m_next )
- leaf = leaf->m_next;
-
- }
-
- return leaf;
-
-}
-
-// GameWindow::findPrevLeaf ===================================================
-/** Returns the prev leaf of the tree */
-//=============================================================================
-GameWindow *GameWindow::findPrevLeaf( void )
-{
- GameWindow *leaf = this;
-
- if( leaf->m_prev )
- {
-
- leaf = leaf->m_prev;
-
- while( leaf->m_child &&
- BitIsSet( leaf->m_status, WIN_STATUS_TAB_STOP ) == FALSE )
- {
-
- leaf = leaf->m_child;
-
- while( leaf->m_next )
- leaf = leaf->m_next;
-
- }
-
- return leaf;
-
- }
- else
- {
-
- while( leaf->m_parent )
- {
-
- leaf = leaf->m_parent;
-
- if( leaf->m_parent && leaf->m_prev )
- {
-
- leaf = leaf->m_prev;
-
- while( leaf->m_child &&
- BitIsSet( leaf->m_status, WIN_STATUS_TAB_STOP ) == FALSE )
- {
-
- leaf = leaf->m_child;
-
- while( leaf->m_next )
- leaf = leaf->m_next;
-
- }
-
- return leaf;
-
- }
-
- }
-
- if( leaf )
- return leaf->findLastLeaf();
- else
- return nullptr;
-
- }
-
- return nullptr;
-
-}
-
-// GameWindow::findNextLeaf ===================================================
-/** Returns the next leaf of the tree */
-//=============================================================================
-GameWindow *GameWindow::findNextLeaf( void )
-{
- GameWindow *leaf = this;
-
- if( leaf->m_next )
- {
-
- if( leaf->m_next->m_status & WIN_STATUS_TAB_STOP )
- return leaf->m_next;
-
- for( leaf = leaf->m_next; leaf; leaf = leaf->m_child )
- if( leaf->m_child == nullptr || BitIsSet( leaf->m_status,
- WIN_STATUS_TAB_STOP ) )
- return leaf;
-
- }
- else
- {
-
- while( leaf->m_parent )
- {
-
- leaf = leaf->m_parent;
-
- if( leaf->m_parent && leaf->m_next )
- {
-
- for( leaf = leaf->m_next; leaf; leaf = leaf->m_child )
- if( leaf->m_child == nullptr ||
- BitIsSet( leaf->m_status, WIN_STATUS_TAB_STOP ) )
- return leaf;
-
- }
-
- }
-
- if( leaf )
- return leaf->findFirstLeaf();
- else
- return nullptr;
-
- }
-
- return nullptr;
-
-}
-
-// GameWindow::winNextTab =====================================================
-/** Go to next window in tab chain */
-//=============================================================================
-Int GameWindow::winNextTab( void )
-{
-/*
- GameWindow *newTab = this;
- Bool firstTry = TRUE;
-
- // Un-hilite the current window
- m_instData.m_state &= ~WIN_STATE_HILITED;
-
- do
- {
-
- if( m_parent == nullptr && firstTry )
- {
-
- newTab = findLastLeaf( newTab );
- firstTry = FALSE;
-
- }
- else
- newTab = findPrevLeaf( newTab );
- } while( ( isEnabled( newTab ) == FALSE ) ||
- ( isHidden( newTab ) ) );
-
- newTab->instData.state |= WIN_STATE_HILITED;
- WinSetFocus( newTab );
-
-*/
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winPrevTab =====================================================
-/** Go to previous window in tab chain */
-//=============================================================================
-Int GameWindow::winPrevTab( void )
-{
-/*
- GameWindow *newTab = this;
- Bool firstTry = TRUE;
-
- // Un-hilite the current window
- m_instData.m_state &= ~WIN_STATE_HILITED;
-
- do
- {
-
- if( m_parent == nullptr && firstTry )
- {
-
- newTab = findFirstLeaf( newTab );
- firstTry = FALSE;
-
- }
- else
- newTab = findNextLeaf( newTab );
-
- } while( ( isEnabled( newTab ) == FALSE ) ||
- ( isHidden( newTab ) ) );
-
- newTab->instData.state |= WIN_STATE_HILITED;
- WinSetFocus( newTab );
-
-*/
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winBringToTop ==================================================
-/** Bring this window to the top of the window list, if we have a parent
- * we will go to the top of the child list for that parent */
-//=============================================================================
-Int GameWindow::winBringToTop( void )
-{
- GameWindow *current;
- GameWindow *parent = winGetParent();
-
- if( parent )
- {
-
- TheWindowManager->unlinkChildWindow( this );
- TheWindowManager->addWindowToParent( this, parent );
-// TheWindowManager->addWindowToParentAtEnd( this, parent );
-
- }
- else
- {
-
- // sanity, make sure this window is in the window list
- for( current = TheWindowManager->winGetWindowList();
- current != this;
- current = current->m_next)
- if (current == nullptr)
- return WIN_ERR_INVALID_PARAMETER;
-
- // move to head of windowList
- TheWindowManager->unlinkWindow( this );
- TheWindowManager->linkWindow( this );
-
- }
-
- //
- // if the window is part of a screen layout, move it to the top
- // of the screen layout to reflect the new position of the window
- // in the real window list (it's all about draw order :) )
- //
- if( m_layout )
- {
- WindowLayout *saveLayout = m_layout;
-
- //
- // note we must use saveScreen because removing the window from the
- // screen will clear the m_screen member (as it should for removing
- // a window from a screen)
- //
- saveLayout->removeWindow( this );
- saveLayout->addWindow( this );
-
- }
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winActivate ====================================================
-/** Pop window to top of window list AND activate it */
-//=============================================================================
-Int GameWindow::winActivate( void )
-{
- Int returnCode;
-
- // bring window to top
- returnCode = winBringToTop();
- if( returnCode != WIN_ERR_OK )
- return returnCode;
-
- // activate it and unhide
- BitSet( m_status, WIN_STATUS_ACTIVE );
- winHide( FALSE );
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetPosition =================================================
-/** Set the window's position */
-//=============================================================================
-Int GameWindow::winSetPosition( Int x, Int y )
-{
-
- m_region.lo.x = x;
- m_region.lo.y = y;
-
- m_region.hi.x = x + m_size.x;
- m_region.hi.y = y + m_size.y;
-
- normalizeWindowRegion();
-
- return WIN_ERR_OK;
-
-}
-
-// WinGetPosition =============================================================
-/** Get the window's position */
-//=============================================================================
-Int GameWindow::winGetPosition( Int *x, Int *y )
-{
-
- // sanity
- if( x == nullptr || y == nullptr )
- return WIN_ERR_INVALID_PARAMETER;
-
- *x = m_region.lo.x;
- *y = m_region.lo.y;
-
- return WIN_ERR_OK;
-
-}
-
-// WinSetCursorPosition =============================================================
-/** Set the window's cursor position */
-//=============================================================================
-Int GameWindow::winSetCursorPosition( Int x, Int y )
-{
- m_cursorX = x;
- m_cursorY = y;
-
- return WIN_ERR_OK;
-
-}
-
-// WinGetCursorPosition =============================================================
-/** Get the window's cursor position */
-//=============================================================================
-Int GameWindow::winGetCursorPosition( Int *x, Int *y )
-{
- if ( x )
- {
- *x = m_cursorX;
- }
-
- if ( y )
- {
- *y = m_cursorY;
- }
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetScreenPosition ===========================================
-/** Get the window's position in screen coordinates */
-//=============================================================================
-Int GameWindow::winGetScreenPosition( Int *x, Int *y )
-{
- GameWindow *parent = m_parent;
-
- *x = m_region.lo.x;
- *y = m_region.lo.y;
-
- while( parent )
- {
-
- *x += parent->m_region.lo.x;
- *y += parent->m_region.lo.y;
- parent = parent->m_parent;
-
- }
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetRegion ===================================================
-/** Get the window region */
-//=============================================================================
-Int GameWindow::winGetRegion( IRegion2D *region )
-{
-
- if( region )
- *region = m_region;
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winPointInWindow ===============================================
-/** Check to see if the given point is inside the window. Will
- * still return true if the point is actually in a child. */
-//=============================================================================
-Bool GameWindow::winPointInWindow( Int x, Int y )
-{
- Int winX, winY, width, height;
-
- winGetScreenPosition( &winX, &winY );
- winGetSize( &width, &height );
-
- if (x >= winX && x <= winX + width &&
- y >= winY && y <= winY + height)
- return TRUE;
-
- return FALSE;
-
-}
-
-// GameWindow::winSetSize =====================================================
-/** Set the window's size */
-//=============================================================================
-Int GameWindow::winSetSize( Int width, Int height )
-{
-
- m_size.x = width;
- m_size.y = height;
- m_region.hi.x = m_region.lo.x + width;
- m_region.hi.y = m_region.lo.y + height;
-
- TheWindowManager->winSendSystemMsg( this,
- GGM_RESIZED,
- (WindowMsgData)width,
- (WindowMsgData)height );
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetSize =====================================================
-/** Get the window's size */
-//=============================================================================
-Int GameWindow::winGetSize( Int *width, Int *height )
-{
-
- // sanity
- if( width == nullptr || height == nullptr )
- return WIN_ERR_INVALID_PARAMETER;
-
- *width = m_size.x;
- *height = m_size.y;
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winEnable ======================================================
-/** Enable or disable a window based on the enable parameter.
- * A disabled window can be seen but accepts no input. */
-//=============================================================================
-Int GameWindow::winEnable( Bool enable )
-{
- GameWindow *child;
-
- if( enable )
- BitSet( m_status, WIN_STATUS_ENABLED );
- else
- BitClear( m_status, WIN_STATUS_ENABLED );
-
- if( m_child )
- {
-
- for( child = m_child; child; child = child->m_next)
- child->winEnable( enable );
-
- }
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetEnabled ======================================================
-/** Enable or disable a window based on the enable parameter.
- * A disabled window can be seen but accepts no input. */
-//=============================================================================
-Bool GameWindow::winGetEnabled( void )
-{
- return BitIsSet( m_status, WIN_STATUS_ENABLED );
-
-}
-
-// GameWindow::winHide ========================================================
-/** Hide or show a window based on the hide parameter.
- * A hidden window can't be seen and accepts no input. */
-//=============================================================================
-Int GameWindow::winHide( Bool hide )
-{
-
- if( hide )
- {
-
- //
- // if we're running in small game window mode and this window becomes
- // invisible then there's a good chance that the black border around
- // the game window needs redrawing
- //
- if( !BitIsSet( m_status, WIN_STATUS_NO_FLUSH ) )
- freeImages();
-
- BitSet( m_status, WIN_STATUS_HIDDEN );
-
- // notify the window manger we are hiding
- TheWindowManager->windowHiding( this );
-
- }
- else
- {
-
- BitClear( m_status, WIN_STATUS_HIDDEN );
-
- }
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winIsHidden ====================================================
-/** Am I hidden? */
-//=============================================================================
-Bool GameWindow::winIsHidden( void )
-{
-
- return BitIsSet( m_status, WIN_STATUS_HIDDEN );
-
-}
-
-// GameWindow::winSetStatus ===================================================
-/** Allows the user to directly set a window's status flags. */
-//=============================================================================
-UnsignedInt GameWindow::winSetStatus( UnsignedInt status )
-{
- UnsignedInt oldStatus;
-
- oldStatus = m_status;
- BitSet( m_status, status );
-// m_status = status;
-
- return oldStatus;
-
-}
-
-// GameWindow::winClearStatus =================================================
-/** Allows the user to directly clear a window's status flags. */
-//=============================================================================
-UnsignedInt GameWindow::winClearStatus( UnsignedInt status )
-{
- UnsignedInt oldStatus;
-
- oldStatus = m_status;
- BitClear( m_status, status );
-
- return oldStatus;
-
-}
-
-// GameWindow::winGetStatus ===================================================
-/** Returns a window's status flags. */
-//=============================================================================
-UnsignedInt GameWindow::winGetStatus( void )
-{
-
- return m_status;
-
-}
-
-// GameWindow::winGetStyle ====================================================
-/** Returns a window's style flags. */
-//=============================================================================
-UnsignedInt GameWindow::winGetStyle( void )
-{
-
- return m_instData.m_style;
-
-}
-
-// GameWindow::winSetHiliteState ==============================================
-/** Set whether window is highlighted or not */
-//=============================================================================
-void GameWindow::winSetHiliteState( Bool state )
-{
-
- if( state )
- BitSet( m_instData.m_state, WIN_STATE_HILITED );
- else
- BitClear( m_instData.m_state, WIN_STATE_HILITED );
-
-}
-
-// GameWindow::winSetDrawOffset ===============================================
-/** Set offset for drawing images */
-//=============================================================================
-void GameWindow::winSetDrawOffset( Int x, Int y )
-{
-
- m_instData.m_imageOffset.x = x;
- m_instData.m_imageOffset.y = y;
-
-}
-
-// GameWindow::winGetDrawOffset ===============================================
-/** Get offset for drawing images */
-//=============================================================================
-void GameWindow::winGetDrawOffset( Int *x, Int *y )
-{
-
- // sanity
- if( x == nullptr || y == nullptr )
- return;
-
- *x = m_instData.m_imageOffset.x;
- *y = m_instData.m_imageOffset.y;
-
-}
-
-// GameWindow::winSetText =====================================================
-/** Sets the text in a window */
-//=============================================================================
-Int GameWindow::winSetText( UnicodeString newText )
-{
- // copy text over
- m_instData.setText( newText );
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetText =====================================================
-/** Get text from a window ... this works for static text windows and
- * edit boxes */
-//=============================================================================
-UnicodeString GameWindow::winGetText( void )
-{
- // return the contents of our text field
- return m_instData.getText();
-
-}
-
-// GameWindow::winGetTextLength =====================================================
-//=============================================================================
-Int GameWindow::winGetTextLength()
-{
- // return the contents of our text field
- return m_instData.getTextLength();
-
-}
-
-// GameWindow::winGetFont =====================================================
-/** Get the font being used by this window */
-//=============================================================================
-GameFont *GameWindow::winGetFont( void )
-{
-
- return m_instData.getFont();
-
-}
-
-// GameWindow::winSetFont =====================================================
-/** Set font for text in this window */
-//=============================================================================
-void GameWindow::winSetFont( GameFont *font )
-{
-
- // set font in window member
- m_instData.m_font = font;
-
- // set font for other display strings in special gadget window controls
- if( BitIsSet( m_instData.getStyle(), GWS_SCROLL_LISTBOX ) )
- GadgetListBoxSetFont( this, font );
- else if( BitIsSet( m_instData.getStyle(), GWS_COMBO_BOX ) )
- GadgetComboBoxSetFont( this, font );
- else if( BitIsSet( m_instData.getStyle(), GWS_ENTRY_FIELD ) )
- GadgetTextEntrySetFont( this, font );
- else if( BitIsSet( m_instData.getStyle(), GWS_STATIC_TEXT ) )
- GadgetStaticTextSetFont( this, font );
- else
- {
- DisplayString *dString;
-
- // set the font for the display strings all windows have
- dString = m_instData.getTextDisplayString();
- if( dString )
- dString->setFont( font );
- dString = m_instData.getTooltipDisplayString();
- if( dString )
- dString->setFont( font );
-
- }
-
-}
-
-// GameWindow::winSetEnabledTextColors ========================================
-/** Set the text colors for the enabled state */
-//=============================================================================
-void GameWindow::winSetEnabledTextColors( Color color, Color borderColor )
-{
- m_instData.m_enabledText.color = color;
- m_instData.m_enabledText.borderColor = borderColor;
-
- if( BitIsSet( m_instData.getStyle(), GWS_COMBO_BOX ) )
- GadgetComboBoxSetEnabledTextColors(this, color, borderColor );
-
-
-}
-
-// GameWindow::winSetDisabledTextColors =======================================
-/** Set the text colors for the disabled state */
-//=============================================================================
-void GameWindow::winSetDisabledTextColors( Color color, Color borderColor )
-{
-
- m_instData.m_disabledText.color = color;
- m_instData.m_disabledText.borderColor = borderColor;
-
- if( BitIsSet( m_instData.getStyle(), GWS_COMBO_BOX ) )
- GadgetComboBoxSetDisabledTextColors( this, color, borderColor );
-
-}
-
-// GameWindow::winSetHiliteTextColors =========================================
-/** Set the text colors for the Hilite state */
-//=============================================================================
-void GameWindow::winSetHiliteTextColors( Color color, Color borderColor )
-{
-
- m_instData.m_hiliteText.color = color;
- m_instData.m_hiliteText.borderColor = borderColor;
-
- if( BitIsSet( m_instData.getStyle(), GWS_COMBO_BOX ) )
- GadgetComboBoxSetHiliteTextColors( this, color, borderColor );
-
-}
-
-// GameWindow::winSetIMECompositeTextColors =========================================
-/** Set the text colors for the IME Composite state */
-//=============================================================================
-void GameWindow::winSetIMECompositeTextColors( Color color, Color borderColor )
-{
-
- m_instData.m_imeCompositeText.color = color;
- m_instData.m_imeCompositeText.borderColor = borderColor;
-
- if( BitIsSet( m_instData.getStyle(), GWS_COMBO_BOX ) )
- GadgetComboBoxSetIMECompositeTextColors( this, color, borderColor );
-}
-
-// GameWindow::winGetEnabledTextColor =========================================
-/** Get the enabled text color */
-//=============================================================================
-Color GameWindow::winGetEnabledTextColor( void )
-{
-
- return m_instData.m_enabledText.color;
-
-}
-
-// GameWindow::winGetEnabledTextBorderColor ===================================
-/** Get the enabled text color */
-//=============================================================================
-Color GameWindow::winGetEnabledTextBorderColor( void )
-{
-
- return m_instData.m_enabledText.borderColor;
-
-}
-
-// GameWindow::winGetDisabledTextColor ========================================
-/** Get the disabled text color */
-//=============================================================================
-Color GameWindow::winGetDisabledTextColor( void )
-{
-
- return m_instData.m_disabledText.color;
-
-}
-
-// GameWindow::winGetDisabledTextBorderColor ==================================
-/** Get the disabled text color */
-//=============================================================================
-Color GameWindow::winGetDisabledTextBorderColor( void )
-{
-
- return m_instData.m_disabledText.borderColor;
-
-}
-
-// GameWindow::winGetIMECompositeTextColor ==========================================
-/** Get the IME composite text color */
-//=============================================================================
-Color GameWindow::winGetIMECompositeTextColor( void )
-{
-
- return m_instData.m_imeCompositeText.color;
-
-}
-
-// GameWindow::winGetIMECompositeBorderColor ==========================================
-/** Get the IME composite border color */
-//=============================================================================
-Color GameWindow::winGetIMECompositeBorderColor( void )
-{
-
- return m_instData.m_imeCompositeText.borderColor;
-
-}
-
-// GameWindow::winGetHiliteTextColor ==========================================
-/** Get the hilite text color */
-//=============================================================================
-Color GameWindow::winGetHiliteTextColor( void )
-{
-
- return m_instData.m_hiliteText.color;
-
-}
-
-// GameWindow::winGetHiliteTextBorderColor ====================================
-/** Get the hilite text color */
-//=============================================================================
-Color GameWindow::winGetHiliteTextBorderColor( void )
-{
-
- return m_instData.m_hiliteText.borderColor;
-
-}
-
-// GameWindow::winSetInstanceData =============================================
-/** Sets the window's instance data which includes parameters
- * such as background color. */
-//=============================================================================
-Int GameWindow::winSetInstanceData( WinInstanceData *data )
-{
- DisplayString *text, *tooltipText;
-
- // save our own instance of text and tooltip text display strings
- text = m_instData.m_text;
- tooltipText = m_instData.m_tooltip;
-
- // copy over all values from the inst data passed in
- // using memcpy is VERY VERY bad here, since the strings
- // must be copied 'correctly' or bad things will ensue
- m_instData = *data;
-
- // put our text instance pointers back
- m_instData.m_text = text;
- m_instData.m_tooltip = tooltipText;
-
- // make sure we didn't try to copy over a video buffer.
- m_instData.m_videoBuffer = nullptr;
-
- // set our text display instance text if present
- if( data->getTextLength() )
- m_instData.setText( data->getText() );
- if( data->getTooltipTextLength() )
- m_instData.setTooltipText( data->getTooltipText() );
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetInstanceData =============================================
-/** Return pointer to the instance data for this window */
-//=============================================================================
-WinInstanceData *GameWindow::winGetInstanceData( void )
-{
-
- return &m_instData;
-
-}
-
-// GameWindow::winGetUserData =================================================
-/** Return the user data stored */
-//=============================================================================
-void *GameWindow::winGetUserData( void )
-{
-
- return m_userData;
-
-}
-
-// GameWindow::winSetUserData =================================================
-/** Set the user data stored */
-//=============================================================================
-void GameWindow::winSetUserData( void *data )
-{
-
- m_userData = data;
-
-}
-
-// GameWindow::winSetTooltip ==================================================
-/** Sets the window's tooltip text */
-//=============================================================================
-void GameWindow::winSetTooltip( UnicodeString tip )
-{
-
- m_instData.setTooltipText( tip );
-
-}
-
-// GameWindow::winSetWindowId =================================================
-/** Sets the window's id */
-//=============================================================================
-Int GameWindow::winSetWindowId( Int id )
-{
-
- m_instData.m_id = id;
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetWindowId =================================================
-/** Gets the window's id */
-//=============================================================================
-Int GameWindow::winGetWindowId( void )
-{
-
- return m_instData.m_id;
-
-}
-
-// GameWindow::winSetParent ===================================================
-/** Sets this window's parent */
-//=============================================================================
-Int GameWindow::winSetParent( GameWindow *parent )
-{
-
- if( m_parent == nullptr)
- {
- // Top level window so unlink it
- TheWindowManager->unlinkWindow( this );
- }
- else
- {
- // A child window
- TheWindowManager->unlinkChildWindow( this );
- }
-
- if( parent == nullptr )
- {
-
- // Want to make it a top level window so add to window list
- TheWindowManager->linkWindow( this );
- m_parent = nullptr;
-
- }
- else
- {
-
- // Set it's new parent
- TheWindowManager->addWindowToParent( this, parent );
-
- }
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetParent ===================================================
-/** Gets the window's parent */
-//=============================================================================
-GameWindow *GameWindow::winGetParent( void )
-{
-
- return m_parent;
-
-}
-
-// GameWindow::winIsChild =====================================================
-/** Determines if a window is a child/grand-child of a parent */
-//=============================================================================
-Bool GameWindow::winIsChild( GameWindow *child )
-{
-
- while( child )
- {
-
- if( this == child->m_parent )
- return TRUE;
-
- // set up tree
- child = child->m_parent;
-
- }
-
- return FALSE;
-
-}
-
-// GameWindow::winGetChild ====================================================
-/** Get the child window of this window */
-//=============================================================================
-GameWindow *GameWindow::winGetChild( void )
-{
-
- return m_child;
-
-}
-
-// GameWindow::winSetOwner ====================================================
-/** Sets the window's owner */
-//=============================================================================
-Int GameWindow::winSetOwner( GameWindow *owner )
-{
-
- if( owner == nullptr )
- m_instData.m_owner = this;
- else
- m_instData.m_owner = owner;
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetOwner ====================================================
-/** Gets the window's owner */
-//=============================================================================
-GameWindow *GameWindow::winGetOwner( void )
-{
-
- return m_instData.getOwner();
-
-}
-
-// GameWindow::winSetNext =====================================================
-/** Set next pointer */
-//=============================================================================
-void GameWindow::winSetNext( GameWindow *next )
-{
-
- m_next = next;
-
-}
-
-// GameWindow::winGetNext =====================================================
-/** Gets the next window */
-//=============================================================================
-GameWindow *GameWindow::winGetNext( void )
-{
-
- return m_next;
-
-}
-
-// GameWindow::winSetPrev =====================================================
-/** Set prev pointer */
-//=============================================================================
-void GameWindow::winSetPrev( GameWindow *prev )
-{
-
- m_prev = prev;
-
-}
-
-// GameWindow::winGetPrev =====================================================
-/** Get the previous window */
-//=============================================================================
-GameWindow *GameWindow::winGetPrev( void )
-{
-
- return m_prev;
-
-}
-
-// GameWindow::winSetNextInLayout =============================================
-/** Set next window in layout */
-//=============================================================================
-void GameWindow::winSetNextInLayout( GameWindow *next )
-{
- m_nextLayout = next;
-}
-
-// GameWindow::winSetPrevInLayout =============================================
-/** Set previous window in layout pointer */
-//=============================================================================
-void GameWindow::winSetPrevInLayout( GameWindow *prev )
-{
- m_prevLayout = prev;
-}
-
-// GameWindow::winSetLayout ===================================================
-/** Set this window as belonging to layout 'layout' */
-//=============================================================================
-void GameWindow::winSetLayout( WindowLayout *layout )
-{
- m_layout = layout;
-}
-
-// GameWindow::winGetLayout ===================================================
-/** Get layout this window is a part of, if any */
-//=============================================================================
-WindowLayout *GameWindow::winGetLayout( void )
-{
- return m_layout;
-}
-
-// GameWindow::winGetNextInLayout =============================================
-/** Get next window in layout list if any */
-//=============================================================================
-GameWindow *GameWindow::winGetNextInLayout( void )
-{
- return m_nextLayout;
-}
-
-// GameWindow::winGetPrevInLayout =============================================
-/** Get prev window in layout list if any */
-//=============================================================================
-GameWindow *GameWindow::winGetPrevInLayout( void )
-{
- return m_prevLayout;
-}
-
-// GameWindow::winSetSystemFunc ===============================================
-/** Sets the window's input, system, and redraw callback functions. */
-//=============================================================================
-Int GameWindow::winSetSystemFunc( GameWinSystemFunc system )
-{
- if( system )
- m_system = system;
- else
- m_system = TheWindowManager->getDefaultSystem();
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetInputFunc ================================================
-/** Sets the window's input callback functions. */
-//=============================================================================
-Int GameWindow::winSetInputFunc( GameWinInputFunc input )
-{
-
- if( input )
- m_input = input;
- else
- m_input = TheWindowManager->getDefaultInput();
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetDrawFunc =================================================
-/** Sets the window's redraw callback functions. */
-//=============================================================================
-Int GameWindow::winSetDrawFunc( GameWinDrawFunc draw )
-{
-
- if( draw )
- m_draw = draw;
- else
- m_draw = TheWindowManager->getDefaultDraw();
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetTooltipFunc ==============================================
-/** Sets a window's tooltip callback */
-//=============================================================================
-Int GameWindow::winSetTooltipFunc( GameWinTooltipFunc tooltip )
-{
-
- m_tooltip = tooltip;
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetCallbacks ================================================
-/** Sets the window's input, tooltip, and redraw callback functions. */
-//=============================================================================
-Int GameWindow::winSetCallbacks( GameWinInputFunc input,
- GameWinDrawFunc draw,
- GameWinTooltipFunc tooltip )
-{
-
- winSetInputFunc( input );
- winSetDrawFunc( draw );
- winSetTooltipFunc( tooltip );
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winDrawWindow ==================================================
-/** Draws the default background for the specified window. */
-//=============================================================================
-Int GameWindow::winDrawWindow( void )
-{
-
- if( BitIsSet( m_status, WIN_STATUS_HIDDEN ) == FALSE && m_draw )
- m_draw( this, &m_instData );
-
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winPointInChild ================================================
-/** Given a window and the mouse coordinates, return the child
- * window which contains the mouse pointer. Child windows are
- * relative to their parents */
-//=============================================================================
-GameWindow *GameWindow::winPointInChild( Int x, Int y, Bool ignoreEnableCheck, Bool playDisabledSound )
-{
- GameWindow *parent;
- GameWindow *child;
- ICoord2D origin;
-
- for( child = m_child; child; child = child->m_next )
- {
-
- origin = child->m_region.lo;
- parent = child->winGetParent();
-
- while( parent )
- {
-
- origin.x += parent->m_region.lo.x;
- origin.y += parent->m_region.lo.y;
- parent = parent->m_parent;
-
- }
-
- if( x >= origin.x && x <= origin.x + child->m_size.x &&
- y >= origin.y && y <= origin.y + child->m_size.y )
- {
- Bool enabled = ignoreEnableCheck || BitIsSet( child->m_status, WIN_STATUS_ENABLED );
- Bool hidden = BitIsSet( child->m_status, WIN_STATUS_HIDDEN );
- if( !hidden )
- {
- if( enabled )
- {
- return child->winPointInChild( x, y, ignoreEnableCheck, playDisabledSound );
- }
- else if( playDisabledSound )
- {
- AudioEventRTS disabledClick( "GUIClickDisabled" );
- if( TheAudio )
- {
- TheAudio->addAudioEvent( &disabledClick );
- }
- }
- }
- }
-
- }
-
- // not in any children, must be in parent
- return this;
-
-}
-
-// GameWindow::winPointInAnyChild =============================================
-/** Find the child in which the cursor resides; regardless of
- * whether or not the window is actually enabled */
-//=============================================================================
-GameWindow *GameWindow::winPointInAnyChild( Int x, Int y, Bool ignoreHidden, Bool ignoreEnableCheck )
-{
- GameWindow *parent;
- GameWindow *child;
- ICoord2D origin;
-
- for( child = m_child; child; child = child->m_next )
- {
-
- origin = child->m_region.lo;
- parent = child->m_parent;
-
- while( parent )
- {
-
- origin.x += parent->m_region.lo.x;
- origin.y += parent->m_region.lo.y;
- parent = parent->m_parent;
-
- }
-
- if( x >= origin.x && x <= origin.x + child->m_size.x &&
- y >= origin.y && y <= origin.y + child->m_size.y )
- {
-
- if( !(ignoreHidden == TRUE && BitIsSet( child->m_status, WIN_STATUS_HIDDEN )) )
- return child->winPointInChild( x, y, ignoreEnableCheck );
-
- }
-
- }
-
- // not in any children, must be in parent
- return this;
-
-}
-
-//
-// In release builds the default input and system functions are optimized
-// to the same address since they take the same input and have the same
-// body. Rather than fill them with bogus code we just want to make
-// sure that different functions are actually created. If you change the
-// body of one but not the other so they are different, please remove
-// the dummy code
-//
-
-// GameWinDefaultInput ========================================================
-/** The default input callback. Currently does nothing. */
-//=============================================================================
-WindowMsgHandledType GameWinDefaultInput( GameWindow *window, UnsignedInt msg,
- WindowMsgData mData1, WindowMsgData mData2 )
-{
-
- return MSG_IGNORED;
-
-}
-
-///< Input that blocks all (mouse) input like a wall, instead of passing like it wasn't there
-WindowMsgHandledType GameWinBlockInput( GameWindow *window, UnsignedInt msg,
- WindowMsgData mData1, WindowMsgData mData2 )
-{
- if (msg == GWM_CHAR || msg == GWM_MOUSE_POS)
- return MSG_IGNORED;
-
- if (msg == GWM_LEFT_UP )//|| msg == GWM_LEFT_DRAG)
- {
- //stop drag selecting
-
- TheSelectionTranslator->setLeftMouseButton(FALSE);
- TheSelectionTranslator->setDragSelecting(FALSE);
-
- TheTacticalView->setMouseLock( FALSE );
- TheInGameUI->setSelecting( FALSE );
- TheInGameUI->endAreaSelectHint(nullptr);
-
- }
-
- return MSG_HANDLED;
-
-}
-
-// GameWinDefaultSystem =======================================================
-/** The default system callback. Currently does nothing. */
-//=============================================================================
-WindowMsgHandledType GameWinDefaultSystem( GameWindow *window, UnsignedInt msg,
- WindowMsgData mData1, WindowMsgData mData2 )
-{
-
- return MSG_IGNORED;
-
-}
-
-// GameWinDefaultTooltip ======================================================
-/** Default tooltip callback */
-//=============================================================================
-void GameWinDefaultTooltip( GameWindow *window,
- WinInstanceData *instData,
- UnsignedInt mouse )
-{
- return;
-
-}
-
-// GameWinDefaultDraw =========================================================
-/** Default draw, does nothing */
-//=============================================================================
-void GameWinDefaultDraw( GameWindow *window, WinInstanceData *instData )
-{
-
- return;
-
-}
-
-// GameWindow::winSetEnabledImage =============================================
-/** Set an enabled image into the draw data for the enabled state */
-//=============================================================================
-Int GameWindow::winSetEnabledImage( Int index, const Image *image )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set enabled image, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_enabledDrawData[ index ].image = image;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetEnabledColor =============================================
-/** set color for enabled state at index */
-//=============================================================================
-Int GameWindow::winSetEnabledColor( Int index, Color color )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set enabled color, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_enabledDrawData[ index ].color = color;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetEnabledBorderColor =======================================
-/** set border color for state at this index */
-//=============================================================================
-Int GameWindow::winSetEnabledBorderColor( Int index, Color color )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set enabled border color, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_enabledDrawData[ index ].borderColor = color;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetDisabledImage ============================================
-/** Set an disabled image into the draw data for the disabled state */
-//=============================================================================
-Int GameWindow::winSetDisabledImage( Int index, const Image *image )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set disabled image, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_disabledDrawData[ index ].image = image;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetDisabledColor ============================================
-/** set color for disabled state at index */
-//=============================================================================
-Int GameWindow::winSetDisabledColor( Int index, Color color )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set disabled color, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_disabledDrawData[ index ].color = color;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetDisabledBorderColor ======================================
-/** set border color for state at this index */
-//=============================================================================
-Int GameWindow::winSetDisabledBorderColor( Int index, Color color )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set disabled border color, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_disabledDrawData[ index ].borderColor = color;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetHiliteImage ==============================================
-/** Set an hilite image into the draw data for the hilite state */
-//=============================================================================
-Int GameWindow::winSetHiliteImage( Int index, const Image *image )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set hilite image, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_hiliteDrawData[ index ].image = image;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetHiliteColor ==============================================
-/** set color for hilite state at index */
-//=============================================================================
-Int GameWindow::winSetHiliteColor( Int index, Color color )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set hilite color, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_hiliteDrawData[ index ].color = color;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winSetHiliteBorderColor ========================================
-/** set border color for state at this index */
-//=============================================================================
-Int GameWindow::winSetHiliteBorderColor( Int index, Color color )
-{
-
- // sanity
- if( index < 0 || index >= MAX_DRAW_DATA )
- {
-
- DEBUG_LOG(( "set hilite border color, index out of range '%d'", index ));
- assert( 0 );
- return WIN_ERR_INVALID_PARAMETER;
-
- }
-
- m_instData.m_hiliteDrawData[ index ].borderColor = color;
- return WIN_ERR_OK;
-
-}
-
-// GameWindow::winGetInputFunc ================================================
-//=============================================================================
-GameWinInputFunc GameWindow::winGetInputFunc( void )
-{
-
- return m_input;
-
-}
-
-// GameWindow::winGetSystemFunc ===============================================
-//=============================================================================
-GameWinSystemFunc GameWindow::winGetSystemFunc( void )
-{
-
- return m_system;
-
-}
-
-// GameWindow::winGetTooltipFunc ==============================================
-//=============================================================================
-GameWinTooltipFunc GameWindow::winGetTooltipFunc( void )
-{
-
- return m_tooltip;
-
-}
-
-// GameWindow::winGetDrawFunc =================================================
-//=============================================================================
-GameWinDrawFunc GameWindow::winGetDrawFunc( void )
-{
-
- return m_draw;
-
-}
-
-// GameWindow::winSetEditData =================================================
-//=============================================================================
-void GameWindow::winSetEditData( GameWindowEditData *editData )
-{
-
- m_editData = editData;
-
-}
-
-// GameWindow::winGetEditData =================================================
-//=============================================================================
-GameWindowEditData *GameWindow::winGetEditData( void )
-{
-
- return m_editData;
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp
deleted file mode 100644
index 88ca944604e..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameWindowGlobal.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: GameWindowGlobal.cpp
-//
-// Created: Colin Day, June 2001
-//
-// Desc: These are some global functions that every game using this
-// window system must implement for their current technology
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "GameClient/Image.h"
-#include "GameClient/Display.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameClient/GameFont.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-// GameWindowManager::winDrawImage ============================================
-/** draw image, coord are in screen and should be kepth within
- * that box specified */
-//=============================================================================
-void GameWindowManager::winDrawImage( const Image *image, Int startX, Int startY,
- Int endX, Int endY, Color color )
-{
-
- TheDisplay->drawImage( image, startX, startY, endX, endY, color );
-
-}
-
-// GameWindowManager::winFillRect =============================================
-/** draw filled rect, coords are absolute screen coords */
-//=============================================================================
-void GameWindowManager::winFillRect( Color color, Real width,
- Int startX, Int startY,
- Int endX, Int endY )
-{
-
- TheDisplay->drawFillRect( startX, startY,
- endX - startX, endY - startY,
- color );
-
-}
-
-// GameWindowManager::winOpenRect =============================================
-/** draw rect outline, coords are absolute screen coords */
-//=============================================================================
-void GameWindowManager::winOpenRect( Color color, Real width,
- Int startX, Int startY,
- Int endX, Int endY )
-{
-
- TheDisplay->drawOpenRect( startX, startY,
- endX - startX, endY - startY,
- width, color );
-
-}
-
-// GameWindowManager::winDrawLine =============================================
-/** draw line, coords are absolute screen coords */
-//=============================================================================
-void GameWindowManager::winDrawLine( Color color, Real width,
- Int startX, Int startY,
- Int endX, Int endY )
-{
-
- TheDisplay->drawLine( startX, startY, endX, endY, width, color );
-
-}
-
-// GameWindowManager::winFindImage ============================================
-/** Given an image name, return an image loc to that image information.
- * You may reorganize the image loc structure however you like to suit
- * your individual project */
-//=============================================================================
-const Image *GameWindowManager::winFindImage( const char *name )
-{
-
- assert( TheMappedImageCollection );
- if( TheMappedImageCollection )
- return TheMappedImageCollection->findImageByName( name );
-
- return nullptr;
-
-}
-
-// GameWindowManager::winMakeColor ============================================
-/** Given RGBA, make a color, you can change color representation for your
- * individual project needs */
-//=============================================================================
-Color GameWindowManager::winMakeColor( UnsignedByte red,
- UnsignedByte green,
- UnsignedByte blue,
- UnsignedByte alpha )
-{
-
- return GameMakeColor( red, green, blue, alpha );
-
-}
-
-// GameWindowManager::winFormatText ===========================================
-/** draw text to the screen */
-//=============================================================================
-void GameWindowManager::winFormatText( GameFont *font, UnicodeString text, Color color,
- Int x, Int y, Int width, Int height )
-{
-
- /// @todo make all display string rendering go through here!
-
-}
-
-// GameWindowManager::winGetTextSize ==========================================
-/** get the extent size of text */
-//=============================================================================
-void GameWindowManager::winGetTextSize( GameFont *font, UnicodeString text,
- Int *width, Int *height, Int maxWidth )
-{
-
- /// @todo make display string size stuff go through here
-
- if( width )
- *width = 0;
-
- if( height )
- *height = 0;
-
-}
-
-// GameWindowManager::winFontHeight ===========================================
-/** Return the font height in pixels */
-//=============================================================================
-Int GameWindowManager::winFontHeight( GameFont *font )
-{
-
- if (font == nullptr)
- return 0;
-
- return font->height;
-
-}
-
-// GameWindowManager::winIsDigit ==============================================
-/** You implementation of whether or not character is a digit */
-//=============================================================================
-Int GameWindowManager::winIsDigit( Int c )
-{
-
- return iswdigit( c );
-
-}
-
-// GameWindowManager::winIsAscii ==============================================
-/** You implementation of whether or not character is ascii */
-//=============================================================================
-Int GameWindowManager::winIsAscii( Int c )
-{
-
- return iswascii( c );
-
-}
-
-// GameWindowManager::winIsAlNum ==============================================
-/** Your implementation of whether or not character is alpha numeric */
-//=============================================================================
-Int GameWindowManager::winIsAlNum( Int c )
-{
-
- return iswalnum( c );
-
-}
-
-// GameWindowManager::winFindFont =============================================
-/** Get a font */
-//=============================================================================
-GameFont *GameWindowManager::winFindFont( AsciiString fontName,
- Int pointSize,
- Bool bold )
-{
-
- assert( TheFontLibrary );
- if( TheFontLibrary )
- return TheFontLibrary->getFont( fontName, pointSize, bold );
-
- return nullptr;
-
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
index 6dfe321585d..8fce9f1177e 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
@@ -1704,7 +1704,7 @@ GameWindow *GameWindowManager::gogoMessageBox(Int x, Int y, Int width, Int heigh
//we shouldn't have button OK and Yes on the same dialog
if((buttonFlags & (MSG_BOX_OK | MSG_BOX_YES)) == (MSG_BOX_OK | MSG_BOX_YES) )
{
- DEBUG_ASSERTCRASH(false, ("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
+ DEBUG_CRASH(("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
}
//Position the OK button if we have one
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
deleted file mode 100644
index 21a677c459c..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GameWindowTransitions.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Dec 2002
-//
-// Filename: GameWindowTransitions.cpp
-//
-// author: Chris Huybregts
-//
-// purpose:
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "GameLogic/GameLogic.h"
-#include "GameClient/GameWindowTransitions.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/GameWindowManager.h"
-//-----------------------------------------------------------------------------
-// DEFINES ////////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-GameWindowTransitionsHandler *TheTransitionHandler = nullptr;
-const FieldParse GameWindowTransitionsHandler::m_gameWindowTransitionsFieldParseTable[] =
-{
-
- { "Window", GameWindowTransitionsHandler::parseWindow, nullptr, 0 },
- { "FireOnce", INI::parseBool, nullptr, offsetof( TransitionGroup, m_fireOnce) },
-
- { nullptr, nullptr, nullptr, 0 }
-
-};
-
-void INI::parseWindowTransitions( INI* ini )
-{
- AsciiString name;
- TransitionGroup *g;
-
- // read the name
- const char* c = ini->getNextToken();
- name.set( c );
-
- // find existing item if present
-
- DEBUG_ASSERTCRASH( TheTransitionHandler, ("parseWindowTransitions: TheTransitionHandler doesn't exist yet") );
- if( !TheTransitionHandler )
- return;
-
- // If we have a previously allocated control bar, this will return a cleared out pointer to it so we
- // can overwrite it
- g = TheTransitionHandler->getNewGroup( name );
-
- // sanity
- DEBUG_ASSERTCRASH( g, ("parseWindowTransitions: Unable to allocate group '%s'", name.str()) );
-
- // parse the ini definition
- ini->initFromINI( g, TheTransitionHandler->getFieldParse() );
-
-
-}
-//-----------------------------------------------------------------------------
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-Transition *getTransitionForStyle( Int style )
-{
- switch (style) {
- case TRANSITION_FLASH:
- return NEW FlashTransition;
- case BUTTON_TRANSITION_FLASH:
- return NEW ButtonFlashTransition;
- case WIN_FADE_TRANSITION:
- return NEW FadeTransition;
- case WIN_SCALE_UP_TRANSITION:
- return NEW ScaleUpTransition;
- case MAINMENU_SCALE_UP_TRANSITION:
- return NEW MainMenuScaleUpTransition;
- case TEXT_TYPE_TRANSITION:
- return NEW TextTypeTransition;
- case SCREEN_FADE_TRANSITION:
- return NEW ScreenFadeTransition;
- case COUNT_UP_TRANSITION:
- return NEW CountUpTransition;
- case FULL_FADE_TRANSITION:
- return NEW FullFadeTransition;
- case TEXT_ON_FRAME_TRANSITION:
- return NEW TextOnFrameTransition;
- case REVERSE_SOUND_TRANSITION:
- return NEW ReverseSoundTransition;
-
- case MAINMENU_MEDIUM_SCALE_UP_TRANSITION:
- return NEW MainMenuMediumScaleUpTransition;
- case MAINMENU_SMALL_SCALE_DOWN_TRANSITION:
- return NEW MainMenuSmallScaleDownTransition;
- case CONTROL_BAR_ARROW_TRANSITION:
- return NEW ControlBarArrowTransition;
- case SCORE_SCALE_UP_TRANSITION:
- return NEW ScoreScaleUpTransition;
-
- default:
- DEBUG_ASSERTCRASH(FALSE, ("getTransitionForStyle:: An invalid style was passed in. Style = %d", style));
- return nullptr;
- }
- return nullptr;
-}
-
-TransitionWindow::TransitionWindow( void )
-{
- m_currentFrameDelay = m_frameDelay = 0;
- m_style = 0;
-
- m_winID = NAMEKEY_INVALID;
- m_win = nullptr;
- m_transition = nullptr;
-}
-
-TransitionWindow::~TransitionWindow( void )
-{
- if (m_win)
- m_win->unlinkTransitionWindow(this);
-
- m_win = nullptr;
-
- delete m_transition;
- m_transition = nullptr;
-}
-
-Bool TransitionWindow::init( void )
-{
- m_winID = TheNameKeyGenerator->nameToKey(m_winName);
- m_win = TheWindowManager->winGetWindowFromId(nullptr, m_winID);
- m_currentFrameDelay = m_frameDelay;
-// DEBUG_ASSERTCRASH( m_win, ("TransitionWindow::init Failed to find window %s", m_winName.str()));
-// if( !m_win )
-// return FALSE;
-
- delete m_transition;
- m_transition = getTransitionForStyle( m_style );
- m_transition->init(m_win);
-
- // TheSuperHackers @fix Mauller 15/05/2025 Link TransitionWindow to the GameWindow so the GameWindow can unlink itself when it is destroyed
- if(m_win)
- m_win->linkTransitionWindow(this);
-
- return TRUE;
-}
-
-void TransitionWindow::update( Int frame )
-{
- if(frame < m_currentFrameDelay || frame > (m_currentFrameDelay + m_transition->getFrameLength()))
- return;
-
- if(m_transition)
- m_transition->update( frame - m_currentFrameDelay);
-}
-
-Bool TransitionWindow::isFinished( void )
-{
- if(m_transition)
- return m_transition->isFinished();
- return TRUE;
-}
-
-void TransitionWindow::reverse( Int totalFrames )
-{
- //m_currentFrameDelay = totalFrames - (m_transition->getFrameLength() + m_frameDelay);
- if(m_transition)
- m_transition->reverse();
-}
-
-void TransitionWindow::skip( void )
-{
- if(m_transition)
- m_transition->skip();
-}
-
-void TransitionWindow::draw( void )
-{
- if(m_transition)
- m_transition->draw();
-}
-
-void TransitionWindow::unlinkGameWindow(GameWindow* win)
-{
- if (m_win != win)
- return;
-
- m_transition->unlinkGameWindow(win);
- m_win = nullptr;
-}
-
-Int TransitionWindow::getTotalFrames( void )
-{
- if(m_transition)
- {
- return m_frameDelay + m_transition->getFrameLength();
- }
-
- return m_frameDelay;
-}
-
-//-----------------------------------------------------------------------------
-TransitionGroup::TransitionGroup( void )
-{
- m_currentFrame = 0;
- m_fireOnce = FALSE;
-}
-
-TransitionGroup::~TransitionGroup( void )
-{
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- delete tWin;
- it = m_transitionWindowList.erase(it);
- }
-}
-
-void TransitionGroup::init( void )
-{
- m_currentFrame = 0;
- m_directionMultiplier = 1;
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- tWin->init();
- it++;
- }
-
-}
-
-void TransitionGroup::update( void )
-{
- m_currentFrame += m_directionMultiplier; // we go forward or backwards depending.
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- tWin->update(m_currentFrame);
- it++;
- }
-}
-
-Bool TransitionGroup::isFinished( void )
-{
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- if(tWin->isFinished() == FALSE)
- return FALSE;
- it++;
- }
-
- return TRUE;
-}
-
-void TransitionGroup::reverse( void )
-{
- Int totalFrames =0;
- m_directionMultiplier = -1;
-
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- Int winFrames = tWin->getTotalFrames();
- if(winFrames > totalFrames)
- totalFrames = winFrames;
- it++;
- }
- it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- tWin->reverse(totalFrames);
- it++;
- }
- m_currentFrame = totalFrames;
-// m_currentFrame ++;
-}
-
-Bool TransitionGroup::isReversed( void )
-{
- if(m_directionMultiplier < 0)
- return TRUE;
- return FALSE;
-}
-
-void TransitionGroup::skip ( void )
-{
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- tWin->skip();
- it++;
- }
-}
-
-void TransitionGroup::draw ( void )
-{
- TransitionWindowList::iterator it = m_transitionWindowList.begin();
- while (it != m_transitionWindowList.end())
- {
- TransitionWindow *tWin = *it;
- tWin->draw();
- it++;
- }
-}
-
-void TransitionGroup::addWindow( TransitionWindow *transWin )
-{
- if(!transWin)
- return;
- m_transitionWindowList.push_back(transWin);
-}
-
-//-----------------------------------------------------------------------------
-
-GameWindowTransitionsHandler::GameWindowTransitionsHandler(void)
-{
- m_currentGroup = nullptr;
- m_pendingGroup = nullptr;
- m_drawGroup = nullptr;
- m_secondaryDrawGroup = nullptr;
-
-}
-
-GameWindowTransitionsHandler::~GameWindowTransitionsHandler( void )
-{
- m_currentGroup = nullptr;
- m_pendingGroup = nullptr;
- m_drawGroup = nullptr;
- m_secondaryDrawGroup = nullptr;
-
- TransitionGroupList::iterator it = m_transitionGroupList.begin();
- while( it != m_transitionGroupList.end() )
- {
- TransitionGroup *g = *it;
- delete g;
- it = m_transitionGroupList.erase(it);
- }
-}
-
-void GameWindowTransitionsHandler::init(void )
-{
- m_currentGroup = nullptr;
- m_pendingGroup = nullptr;
- m_drawGroup = nullptr;
- m_secondaryDrawGroup = nullptr;
-}
-
-void GameWindowTransitionsHandler::load(void )
-{
- INI ini;
- // Read from INI all the ControlBarSchemes
- ini.loadFileDirectory( "Data\\INI\\WindowTransitions", INI_LOAD_OVERWRITE, nullptr );
-
-}
-
-void GameWindowTransitionsHandler::reset( void )
-{
- m_currentGroup = nullptr;
- m_pendingGroup = nullptr;
- m_drawGroup = nullptr;
- m_secondaryDrawGroup = nullptr;
-
-}
-
-void GameWindowTransitionsHandler::update( void )
-{
- if(m_drawGroup != m_currentGroup)
- m_secondaryDrawGroup = m_drawGroup;
- else
- m_secondaryDrawGroup = nullptr;
-
- m_drawGroup = m_currentGroup;
- if(m_currentGroup && !m_currentGroup->isFinished())
- m_currentGroup->update();
-
- if(m_currentGroup && m_currentGroup->isFinished() && m_currentGroup->isFireOnce())
- {
- m_currentGroup = nullptr;
- }
-
- if(m_currentGroup && m_pendingGroup && m_currentGroup->isFinished())
- {
- m_currentGroup = m_pendingGroup;
- m_pendingGroup = nullptr;
- }
-
- if(!m_currentGroup && m_pendingGroup)
- {
- m_currentGroup = m_pendingGroup;
- m_pendingGroup = nullptr;
- }
-
- if(m_currentGroup && m_currentGroup->isFinished() && m_currentGroup->isReversed())
- m_currentGroup = nullptr;
-}
-
-
-void GameWindowTransitionsHandler::draw( void )
-{
-// if( TheGameLogic->getFrame() > 0 )//if( areTransitionsEnabled() ) //KRIS
- if(m_drawGroup)
- m_drawGroup->draw();
- if(m_secondaryDrawGroup)
- m_secondaryDrawGroup->draw();
-}
-
-void GameWindowTransitionsHandler::setGroup(AsciiString groupName, Bool immediate )
-{
- if(groupName.isEmpty() && immediate)
- m_currentGroup = nullptr;
- if(immediate && m_currentGroup)
- {
- m_currentGroup->skip();
- m_currentGroup = findGroup(groupName);
- if(m_currentGroup)
- m_currentGroup->init();
- return;
- }
-
- if(m_currentGroup)
- {
- if(!m_currentGroup->isFireOnce() && !m_currentGroup->isReversed())
- m_currentGroup->reverse();
- m_pendingGroup = findGroup(groupName);
- if(m_pendingGroup)
- m_pendingGroup->init();
- return;
- }
-
- m_currentGroup = findGroup(groupName);
- if(m_currentGroup)
- m_currentGroup->init();
-
-
-
-}
-
-void GameWindowTransitionsHandler::reverse( AsciiString groupName )
-{
- TransitionGroup *g = findGroup(groupName);
- if( m_currentGroup == g )
- {
- m_currentGroup->reverse();
- return;
- }
- if( m_pendingGroup == g)
- {
- m_pendingGroup = nullptr;
- return;
- }
- if(m_currentGroup)
- m_currentGroup->skip();
- if(m_pendingGroup)
- m_pendingGroup->skip();
-
- m_currentGroup = g;
- m_currentGroup->init();
- m_currentGroup->skip();
- m_currentGroup->reverse();
- m_pendingGroup = nullptr;
-}
-
-void GameWindowTransitionsHandler::remove( AsciiString groupName, Bool skipPending )
-{
- TransitionGroup *g = findGroup(groupName);
- if(m_pendingGroup == g)
- {
- if(skipPending)
- m_pendingGroup->skip();
-
- m_pendingGroup = nullptr;
- }
- if(m_currentGroup == g)
- {
- m_currentGroup->skip();
- m_currentGroup = nullptr;
- if(m_pendingGroup)
- m_currentGroup = m_pendingGroup;
- }
-}
-
-TransitionGroup *GameWindowTransitionsHandler::getNewGroup( AsciiString name )
-{
- if(name.isEmpty())
- return nullptr;
-
- // test to see if we're trying to add an already existing group.
- if(findGroup(name))
- {
- DEBUG_ASSERTCRASH(FALSE, ("GameWindowTransitionsHandler::getNewGroup - We already have a group %s", name.str()));
- return nullptr;
- }
- TransitionGroup *g = NEW TransitionGroup;
- g->setName(name);
- m_transitionGroupList.push_back(g);
- return g;
-}
-
-Bool GameWindowTransitionsHandler::isFinished( void )
-{
- if(m_currentGroup)
- return m_currentGroup->isFinished();
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-TransitionGroup *GameWindowTransitionsHandler::findGroup( AsciiString groupName )
-{
- if(groupName.isEmpty())
- return nullptr;
-
- TransitionGroupList::iterator it = m_transitionGroupList.begin();
- while( it != m_transitionGroupList.end() )
- {
- TransitionGroup *g = *it;
- if(groupName.compareNoCase(g->getName()) == 0)
- return g;
- it++;
- }
- return nullptr;
-}
-
-void GameWindowTransitionsHandler::parseWindow( INI* ini, void *instance, void *store, const void *userData )
-{
- static const FieldParse myFieldParse[] =
- {
- { "WinName", INI::parseAsciiString, nullptr, offsetof( TransitionWindow, m_winName ) },
- { "Style", INI::parseLookupList, TransitionStyleNames, offsetof( TransitionWindow, m_style ) },
- { "FrameDelay", INI::parseInt, nullptr, offsetof( TransitionWindow, m_frameDelay ) },
- { nullptr, nullptr, nullptr, 0 }
- };
- TransitionWindow *transWin = NEW TransitionWindow;
- ini->initFromINI(transWin, myFieldParse);
- ((TransitionGroup*)instance)->addWindow(transWin);
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
index 877d067e21b..03485ad83e9 100644
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
@@ -113,7 +113,7 @@ void FlashTransition::update( Int frame )
m_drawState = -1;
if(frame < FLASHTRANSITION_START || frame > FLASHTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("FlashTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("FlashTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -269,7 +269,7 @@ void ButtonFlashTransition::update( Int frame )
m_drawState = -1;
if(frame < BUTTONFLASHTRANSITION_START || frame > BUTTONFLASHTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ButtonFlashTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ButtonFlashTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -642,7 +642,7 @@ void FadeTransition::update( Int frame )
m_drawState = -1;
if(frame < FADETRANSITION_START || frame > FADETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("FadeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("FadeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -785,7 +785,7 @@ void ScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < SCALEUPTRANSITION_START || frame > SCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -908,7 +908,7 @@ void ScoreScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < SCORESCALEUPTRANSITION_START || frame > SCORESCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ScoreScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ScoreScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1039,7 +1039,7 @@ void MainMenuScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < MAINMENUSCALEUPTRANSITION_START || frame > MAINMENUSCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("MainMenuScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("MainMenuScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1158,7 +1158,7 @@ void MainMenuMediumScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < MAINMENUMEDIUMSCALEUPTRANSITION_START || frame > MAINMENUMEDIUMSCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("MainMenuMediumScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("MainMenuMediumScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1277,7 +1277,7 @@ void MainMenuSmallScaleDownTransition::update( Int frame )
m_drawState = -1;
if(frame < MAINMENUSMALLSCALEDOWNTRANSITION_START || frame > MAINMENUSMALLSCALEDOWNTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("MainMenuSmallScaleDownTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("MainMenuSmallScaleDownTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1382,7 +1382,7 @@ void TextTypeTransition::update( Int frame )
m_drawState = -1;
if(frame < TEXTTYPETRANSITION_START || frame > TEXTTYPETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("TextTypeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("TextTypeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1521,7 +1521,7 @@ void CountUpTransition::update( Int frame )
m_drawState = -1;
if(frame < COUNTUPTRANSITION_START || frame > COUNTUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("CountUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("CountUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1638,7 +1638,7 @@ void ScreenFadeTransition::update( Int frame )
m_drawState = -1;
if(frame < SCREENFADETRANSITION_START || frame > SCREENFADETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ScreenFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ScreenFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1731,7 +1731,7 @@ void ControlBarArrowTransition::update( Int frame )
m_drawState = -1;
if(frame < CONTROLBARARROWTRANSITION_START || frame > CONTROLBARARROWTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ControlBarArrowTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ControlBarArrowTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1826,7 +1826,7 @@ void FullFadeTransition::update( Int frame )
m_drawState = -1;
if(frame < FULLFADETRANSITION_START || frame > FULLFADETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("FullFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("FullFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1927,7 +1927,7 @@ void TextOnFrameTransition::update( Int frame )
{
if(frame < TEXTONFRAMETRANSITION_START || frame > TEXTONFRAMETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("TextOnFrameTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("TextOnFrameTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -2001,7 +2001,7 @@ void ReverseSoundTransition::update( Int frame )
{
if(frame < REVERSESOUNDTRANSITION_START || frame > REVERSESOUNDTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ReverseSoundTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ReverseSoundTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp
deleted file mode 100644
index dc8a0bcb812..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: HeaderTemplate.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Aug 2002
-//
-// Filename: HeaderTemplate.cpp
-//
-// author: Chris Huybregts
-//
-// purpose: The header template system is used to maintain a unified look across
-// windows. It also allows Localization to customize the looks based
-// on language fonts.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "PreRTS.h"
-
-#include "Common/INI.h"
-#include "Common/FileSystem.h"
-#include "Common/Registry.h"
-#include "GameClient/HeaderTemplate.h"
-#include "GameClient/GameFont.h"
-#include "GameClient/GlobalLanguage.h"
-//-----------------------------------------------------------------------------
-// DEFINES ////////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-const FieldParse HeaderTemplateManager::m_headerFieldParseTable[] =
-{
- { "Font", INI::parseQuotedAsciiString, nullptr, offsetof( HeaderTemplate, m_fontName ) },
- { "Point", INI::parseInt, nullptr, offsetof( HeaderTemplate, m_point) },
- { "Bold", INI::parseBool, nullptr, offsetof( HeaderTemplate, m_bold ) },
- { nullptr, nullptr, nullptr, 0 },
-};
-
-HeaderTemplateManager *TheHeaderTemplateManager = nullptr;
-//-----------------------------------------------------------------------------
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-void INI::parseHeaderTemplateDefinition( INI *ini )
-{
- AsciiString name;
- HeaderTemplate *hTemplate;
-
- // read the name
- const char* c = ini->getNextToken();
- name.set( c );
-
- // find existing item if present
- hTemplate = TheHeaderTemplateManager->findHeaderTemplate( name );
- if( hTemplate == nullptr )
- {
-
- // allocate a new item
- hTemplate = TheHeaderTemplateManager->newHeaderTemplate( name );
-
- }
- else
- {
- DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate header Template %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() ));
- }
- // parse the ini definition
- ini->initFromINI( hTemplate, TheHeaderTemplateManager->getFieldParse() );
-
-}
-
-HeaderTemplate::HeaderTemplate( void ) :
-m_font(nullptr),
-m_point(0),
-m_bold(FALSE)
-{
- m_fontName.clear();
- m_name.clear();
-}
-
-HeaderTemplate::~HeaderTemplate( void ){}
-
-HeaderTemplateManager::HeaderTemplateManager( void )
-{}
-
-HeaderTemplateManager::~HeaderTemplateManager( void )
-{
- HeaderTemplateListIt it = m_headerTemplateList.begin();
- while(it != m_headerTemplateList.end())
- {
- HeaderTemplate *hTemplate = *it;
- delete hTemplate;
- it = m_headerTemplateList.erase(it);
-
- }
-}
-
-void HeaderTemplateManager::init( void )
-{
- {
- AsciiString fname;
- fname.format("Data\\%s\\HeaderTemplate", GetRegistryLanguage().str());
-
- INI ini;
- ini.loadFileDirectory( fname, INI_LOAD_OVERWRITE, nullptr );
- }
-
- populateGameFonts();
-}
-
-HeaderTemplate *HeaderTemplateManager::findHeaderTemplate( AsciiString name )
-{
- HeaderTemplateListIt it = m_headerTemplateList.begin();
- while(it != m_headerTemplateList.end())
- {
- HeaderTemplate *hTemplate = *it;
- if(hTemplate->m_name.compare(name) == 0)
- return hTemplate;
- ++it;
- }
- return nullptr;
-}
-
-HeaderTemplate *HeaderTemplateManager::newHeaderTemplate( AsciiString name )
-{
- HeaderTemplate *newHTemplate = NEW HeaderTemplate;
- DEBUG_ASSERTCRASH(newHTemplate, ("Unable to create a new Header Template in HeaderTemplateManager::newHeaderTemplate"));
- if(!newHTemplate)
- return nullptr;
-
- newHTemplate->m_name = name;
- m_headerTemplateList.push_front(newHTemplate);
- return newHTemplate;
-
-}
-
-GameFont *HeaderTemplateManager::getFontFromTemplate( AsciiString name )
-{
- HeaderTemplate *ht = findHeaderTemplate( name );
- if(!ht)
- {
- //DEBUG_LOG(("HeaderTemplateManager::getFontFromTemplate - Could not find header %s", name.str()));
- return nullptr;
- }
-
- return ht->m_font;
-}
-
-HeaderTemplate *HeaderTemplateManager::getFirstHeader( void )
-{
- HeaderTemplateListIt it = m_headerTemplateList.begin();
- if( it == m_headerTemplateList.end())
- return nullptr;
-
- return *it;
-}
-
-HeaderTemplate *HeaderTemplateManager::getNextHeader( HeaderTemplate *ht )
-{
- HeaderTemplateListIt it = m_headerTemplateList.begin();
- while(it != m_headerTemplateList.end())
- {
- if(*it == ht)
- {
- ++it;
- if( it == m_headerTemplateList.end())
- return nullptr;
- return *it;
- }
- ++it;
- }
- return nullptr;
-
-}
-
-void HeaderTemplateManager::onResolutionChanged( void )
-{
- populateGameFonts();
-}
-//-----------------------------------------------------------------------------
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-void HeaderTemplateManager::populateGameFonts( void )
-{
- HeaderTemplateListIt it = m_headerTemplateList.begin();
- while(it != m_headerTemplateList.end())
- {
- HeaderTemplate *hTemplate = *it;
- Real pointSize = TheGlobalLanguageData->adjustFontSize(hTemplate->m_point);
- GameFont *font = TheFontLibrary->getFont(hTemplate->m_fontName, pointSize,hTemplate->m_bold);
- DEBUG_ASSERTCRASH(font,("HeaderTemplateManager::populateGameFonts - Could not find font %s %d",hTemplate->m_fontName.str(), hTemplate->m_point));
-
- hTemplate->m_font = font;
-
- ++it;
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp
deleted file mode 100644
index d267b84ee4a..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp
+++ /dev/null
@@ -1,1600 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-//----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//----------------------------------------------------------------------------
-//
-// Project: Ganerals
-//
-// Module: IME
-//
-// File name: IMEManager.cpp
-//
-// Created: 11/14/01 TR
-//
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Includes
-//----------------------------------------------------------------------------
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "mbstring.h"
-
-#include "Common/Debug.h"
-#include "Common/Language.h"
-#include "Common/UnicodeString.h"
-#include "GameClient/Display.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameClient/GadgetListBox.h"
-#include "GameClient/IMEManager.h"
-#include "GameClient/Mouse.h"
-#include "GameClient/Color.h"
-#include "Common/NameKeyGenerator.h"
-
-
-//----------------------------------------------------------------------------
-// Externals
-//----------------------------------------------------------------------------
-
-extern HWND ApplicationHWnd; ///< our application window handle
-extern Int IMECandidateWindowLineSpacing;
-
-//----------------------------------------------------------------------------
-// Defines
-//----------------------------------------------------------------------------
-
-
-//#define DEBUG_IME
-
-//----------------------------------------------------------------------------
-// Private Types
-//----------------------------------------------------------------------------
-
-//===============================
-// IMEManager
-//===============================
-
-class IMEManager : public IMEManagerInterface
-{
-
- public:
-
- IMEManager();
- ~IMEManager();
-
- virtual void init( void );
- virtual void reset( void );
- virtual void update( void );
-
- virtual void attach( GameWindow *window ); ///< attach IME to specified window
- virtual void detach( void ); ///< detach IME from current window
- virtual void enable( void ); ///< Enable IME
- virtual void disable( void ); ///< Disable IME
- virtual Bool isEnabled( void ); ///< Is IME enabled
- virtual Bool isAttachedTo( GameWindow *window ); ///< Is the manager attached toa window
- virtual GameWindow* getWindow( void ); ///< Returns the window we are currently attached to
- virtual Bool isComposing( void ); ///< Manager is currently composing new input string
- virtual void getCompositionString( UnicodeString &string ); ///< Return the current composition string
- virtual Int getCompositionCursorPosition( void ); ///< Returns the composition cursor position
- virtual Int getIndexBase( void ); ///< Get index base for candidate list
-
- virtual Int getCandidateCount(); ///< Returns the total number of candidates
- virtual const UnicodeString* getCandidate( Int index ); ///< Returns the candidate string
- virtual Int getSelectedCandidateIndex(); ///< Returns the indexed of the currently selected candidate
- virtual Int getCandidatePageSize(); ///< Returns the page size for the candidates list
- virtual Int getCandidatePageStart(); ///< Returns the index of the first visibel candidate
-
-
-
- /// Checks for and services IME messages. Returns TRUE if message serviced
- virtual Bool serviceIMEMessage( void *windowsHandle,
- UnsignedInt message,
- Int wParam,
- Int lParam );
- virtual Int result( void ); ///< result return value of last serviced IME message
-
- protected:
-
- enum
- {
- MAX_COMPSTRINGLEN = 2*1024
- };
-
- struct MessageInfo
- {
- Char *name;
- Int value;
- };
-
- Int m_result; ///< last IME message's winProc return code
- GameWindow *m_window; ///< window we are accepting input for
- HIMC m_context; ///< Imput Manager Context
- HIMC m_oldContext; ///< Previous IME comtext
- Int m_disabled; ///< IME disable count 0 = enabled
- Bool m_composing; ///< Are we currently composing a new string
- WideChar m_compositionString[MAX_COMPSTRINGLEN+1];
- WideChar m_resultsString[MAX_COMPSTRINGLEN+1];
- Int m_compositionCursorPos;
- Int m_compositionStringLength;
- Int m_indexBase;
-
- Int m_pageStart; ///< index of first visible candidate
- Int m_pageSize; ///< Number of candidate per page
- Int m_selectedIndex; ///< Index of the currently selected candidate
- Int m_candidateCount; ///< Total number of candidate strings
- UnicodeString *m_candidateString; ///< table of canidate strings
- Bool m_unicodeIME; ///< Is this an unicode IME
- Int m_compositionCharsDisplayed; ///< number of temporary composition characters displayed that need to be replaced with result string.
-
- WideChar convertCharToWide( WPARAM mbchar ); ///< Convert multibyte character to wide
- void updateCompositionString( void ); ///< Update the context of the composition string from the IMM
- void getResultsString( void ); ///< Get the final composition string result
- void updateProperties( void ); ///< Read the current IME properties
- void openCandidateList( Int candidateFlags ); ///< open candidate window
- void closeCandidateList( Int candidateFlags ); ///< Close candidate window
- void updateCandidateList( Int candidateFlags ); ///< Update candidate window
- void updateListBox( CANDIDATELIST *candidateList ); ///< Update candidate list box gadget
- void convertToUnicode( Char *mbcs, UnicodeString &unicode );
- void resizeCandidateWindow( Int pageSize );
-
- void openStatusWindow( void );
- void closeStatusWindow( void );
- void updateStatusWindow( void );
-
- GameWindow *m_candidateWindow; ///< IME candidate window interface
- GameWindow *m_statusWindow; ///< IME status window interface
- GameWindow *m_candidateTextArea; ///< list box area
- GameWindow *m_candidateUpArrow; ///< up arrow
- GameWindow *m_candidateDownArrow; ///< down arrow
-
-
-
- #ifdef DEBUG_IME
- static MessageInfo m_mainMessageInfo[];
- static MessageInfo m_notifyInfo[];
- static MessageInfo m_requestInfo[];
- static MessageInfo m_controlInfo[];
- static MessageInfo m_setContextInfo[];
- static MessageInfo m_setCmodeInfo[];
- static MessageInfo m_setSmodeInfo[];
- Char* getMessageName( MessageInfo *msgTable, Int value );
- void buildFlagsString( IMEManager::MessageInfo *msgTable, Int value, AsciiString &string );
- void printMessageInfo( Int message, Int wParam, Int lParam );
- void printConversionStatus( void );
- void printSentenceStatus( void );
- #endif
-};
-
-
-
-
-//----------------------------------------------------------------------------
-// Private Data
-//----------------------------------------------------------------------------
-#ifdef DEBUG_IME
-
-IMEManager::MessageInfo IMEManager::m_mainMessageInfo[] =
-{
- { "WM_IME_SETCONTEXT" , WM_IME_SETCONTEXT },
- { "WM_IME_NOTIFY" , WM_IME_NOTIFY },
- { "WM_IME_CONTROL" , WM_IME_CONTROL },
- { "WM_IME_COMPOSITIONFULL" , WM_IME_COMPOSITIONFULL },
- { "WM_IME_SELECT" , WM_IME_SELECT },
- { "WM_IME_CHAR" , WM_IME_CHAR },
-#ifdef WM_IME_REQUST
- { "WM_IME_REQUEST" , WM_IME_REQUEST },
-#endif
- { "WM_IME_KEYDOWN" , WM_IME_KEYDOWN },
- { "WM_IME_KEYUP" , WM_IME_KEYUP },
- { "WM_IME_STARTCOMPOSITION" , WM_IME_STARTCOMPOSITION},
- { "WM_IME_ENDCOMPOSITION" , WM_IME_ENDCOMPOSITION },
- { "WM_IME_COMPOSITION" , WM_IME_COMPOSITION },
- { "WM_IME_KEYLAST" , WM_IME_KEYLAST },
- { nullptr, 0 }
-};
-
-IMEManager::MessageInfo IMEManager::m_notifyInfo[] =
-{
- { "IMN_CLOSESTATUSWINDOW" , IMN_CLOSESTATUSWINDOW },
- { "IMN_OPENSTATUSWINDOW" , IMN_OPENSTATUSWINDOW },
- { "IMN_CHANGECANDIDATE" , IMN_CHANGECANDIDATE },
- { "IMN_CLOSECANDIDATE" , IMN_CLOSECANDIDATE },
- { "IMN_OPENCANDIDATE" , IMN_OPENCANDIDATE },
- { "IMN_SETCONVERSIONMODE" , IMN_SETCONVERSIONMODE },
- { "IMN_SETSENTENCEMODE" , IMN_SETSENTENCEMODE },
- { "IMN_SETOPENSTATUS" , IMN_SETOPENSTATUS },
- { "IMN_SETCANDIDATEPOS" , IMN_SETCANDIDATEPOS },
- { "IMN_SETCOMPOSITIONFONT" , IMN_SETCOMPOSITIONFONT },
- { "IMN_SETCOMPOSITIONWINDOW" , IMN_SETCOMPOSITIONWINDOW},
- { "IMN_SETSTATUSWINDOWPOS" , IMN_SETSTATUSWINDOWPOS },
- { "IMN_GUIDELINE" , IMN_GUIDELINE },
- { "IMN_PRIVATE" , IMN_PRIVATE },
- { nullptr, 0 }
-};
-
-IMEManager::MessageInfo IMEManager::m_requestInfo[] =
-{
-#ifdef WM_IME_REQUST
- { "IMR_COMPOSITIONWINDOW" , IMR_COMPOSITIONWINDOW },
- { "IMR_CANDIDATEWINDOW" , IMR_CANDIDATEWINDOW },
- { "IMR_COMPOSITIONFONT" , IMR_COMPOSITIONFONT },
- { "IMR_RECONVERTSTRING" , IMR_RECONVERTSTRING },
- { "IMR_CONFIRMRECONVERTSTRING" , IMR_CONFIRMRECONVERTSTRING},
-#endif
- { nullptr, 0 }
-};
-
-
-IMEManager::MessageInfo IMEManager::m_controlInfo[] =
-{
- { "IMC_GETCANDIDATEPOS" , IMC_GETCANDIDATEPOS },
- { "IMC_SETCANDIDATEPOS " , IMC_SETCANDIDATEPOS },
- { "IMC_GETCOMPOSITIONFONT" , IMC_GETCOMPOSITIONFONT },
- { "IMC_SETCOMPOSITIONFONT" , IMC_SETCOMPOSITIONFONT },
- { "IMC_GETCOMPOSITIONWINDOW" , IMC_GETCOMPOSITIONWINDOW},
- { "IMC_SETCOMPOSITIONWINDOW" , IMC_SETCOMPOSITIONWINDOW},
- { "IMC_GETSTATUSWINDOWPOS" , IMC_GETSTATUSWINDOWPOS },
- { "IMC_SETSTATUSWINDOWPOS" , IMC_SETSTATUSWINDOWPOS },
- { "IMC_CLOSESTATUSWINDOW" , IMC_CLOSESTATUSWINDOW },
- { "IMC_OPENSTATUSWINDOW" , IMC_OPENSTATUSWINDOW },
- { nullptr, 0 }
-};
-
-IMEManager::MessageInfo IMEManager::m_setContextInfo[] =
-{
- { "CANDIDATEWINDOW1" , ISC_SHOWUICANDIDATEWINDOW },
- { "CANDIDATEWINDOW2" , ISC_SHOWUICANDIDATEWINDOW<<1 },
- { "CANDIDATEWINDOW3" , ISC_SHOWUICANDIDATEWINDOW<<2 },
- { "CANDIDATEWINDOW4" , ISC_SHOWUICANDIDATEWINDOW<<3 },
- { "COMPOSITIONWINDOW" , ISC_SHOWUICOMPOSITIONWINDOW },
- { "GUIDELINE" , ISC_SHOWUIGUIDELINE },
- { nullptr, 0 }
-};
-
-IMEManager::MessageInfo IMEManager::m_setCmodeInfo[] =
-{
- { "ALPHANUMERIC" , IME_CMODE_ALPHANUMERIC},
- { "NATIVE" , IME_CMODE_NATIVE },
- { "KATAKANA" , IME_CMODE_KATAKANA },
- { "LANGUAGE" , IME_CMODE_LANGUAGE },
- { "FULLSHAPE" , IME_CMODE_FULLSHAPE },
- { "ROMAN" , IME_CMODE_ROMAN },
- { "CHARCODE" , IME_CMODE_CHARCODE },
- { "HANJACONVERT" , IME_CMODE_HANJACONVERT},
- { "SOFTKBD" , IME_CMODE_SOFTKBD },
- { "NOCONVERSION" , IME_CMODE_NOCONVERSION},
- { "EUDC" , IME_CMODE_EUDC },
- { "SYMBOL" , IME_CMODE_SYMBOL },
- { "FIXED" , IME_CMODE_FIXED },
- { nullptr, 0 }
-};
-
-IMEManager::MessageInfo IMEManager::m_setSmodeInfo[] =
-{
- { "NONE" , IME_SMODE_NONE },
- { "PLAURALCLAUSE" , IME_SMODE_PLAURALCLAUSE},
- { "SINGLECONVERT" , IME_SMODE_SINGLECONVERT},
- { "AUTOMATIC" , IME_SMODE_AUTOMATIC },
- { "PHRASEPREDICT" , IME_SMODE_PHRASEPREDICT},
- { "CONVERSATION" , IME_SMODE_CONVERSATION },
- { nullptr, 0 }
-};
-
-#endif
-
-//----------------------------------------------------------------------------
-// Public Data
-//----------------------------------------------------------------------------
-
-IMEManagerInterface *TheIMEManager = nullptr;
-
-
-//----------------------------------------------------------------------------
-// Private Prototypes
-//----------------------------------------------------------------------------
-
-
-
-//----------------------------------------------------------------------------
-// Private Functions
-//----------------------------------------------------------------------------
-
-#ifdef DEBUG_IME
-
-//============================================================================
-// IMEManager::getMessageName
-//============================================================================
-
-Char* IMEManager::getMessageName( IMEManager::MessageInfo *msgTable, Int value )
-{
- Char *name = nullptr;
-
- if ( msgTable )
- {
- while ( msgTable->name )
- {
- if ( msgTable->value == value )
- {
- name = msgTable->name;
- break;
- }
- msgTable++;
- }
- }
-
- return name;
-}
-
-//============================================================================
-// IMEManager::buildFlagsString
-//============================================================================
-
-void IMEManager::buildFlagsString( IMEManager::MessageInfo *msgTable, Int value, AsciiString &string )
-{
- string.clear();
- Bool first = TRUE;
-
- if ( msgTable )
- {
- while ( msgTable->name )
- {
- if ( msgTable->value & value )
- {
- if ( !first )
- {
- string.concat( "|" );
- first = FALSE;
- }
- string.concat( msgTable->name );
- }
- msgTable++;
- }
- }
-}
-
-//============================================================================
-// IMEManager::printMessageInfo
-//============================================================================
-
-void IMEManager::printMessageInfo( Int message, Int wParam, Int lParam )
-{
- Char *messageText = getMessageName( m_mainMessageInfo, message);
-
- switch( message )
- {
- case WM_IME_NOTIFY:
- {
- Char *notifyName = getMessageName( m_notifyInfo, wParam );
- if ( notifyName == nullptr ) notifyName = "unknown";
- DEBUG_LOG(( "IMM: %s(0x%04x) - %s(0x%04x) - 0x%08x", messageText, message, notifyName, wParam, lParam ));
- break;
- }
- case WM_IME_CONTROL:
- {
- Char *controlName = getMessageName( m_controlInfo, wParam );
- if ( controlName == nullptr ) controlName = "unknown";
-
- DEBUG_LOG(( "IMM: %s(0x%04x) - %s(0x%04x) - 0x%08x", messageText, message, controlName, wParam, lParam ));
- break;
- }
- #ifdef WM_IME_REQUEST
- case WM_IME_REQUEST:
- {
- Char *requestName = getMessageName( m_requestInfo, wParam );
- if ( requestName == nullptr ) requestName = "unknown";
-
- DEBUG_LOG(( "IMM: %s(0x%04x) - %s(0x%04x) - 0x%08x", messageText, message, requestName, wParam, lParam ));
- break;
- }
- #endif
- case WM_IME_SETCONTEXT:
- {
- AsciiString flags;
-
- buildFlagsString( m_setContextInfo, lParam, flags );
-
- DEBUG_LOG(( "IMM: %s(0x%04x) - 0x%08x - %s(0x%04x)", messageText, message, wParam, flags.str(), lParam ));
- break;
- }
- default:
- if ( messageText )
- {
- DEBUG_LOG(( "IMM: %s(0x%04x) - 0x%08x - 0x%08x", messageText, message, wParam, lParam ));
- }
- break;
- }
-}
-
-//============================================================================
-// IMEManager::printConversionStatus
-//============================================================================
-
-void IMEManager::printConversionStatus( void )
-{
- DWORD mode;
- if ( m_context )
- {
- ImmGetConversionStatus( m_context, &mode, nullptr );
-
- AsciiString flags;
-
- buildFlagsString( m_setCmodeInfo, mode, flags );
-
- DEBUG_LOG(( "IMM: Conversion mode = (%s)", flags.str()));
- }
-}
-
-//============================================================================
-// IMEManager::printSentenceStatus
-//============================================================================
-
-void IMEManager::printSentenceStatus( void )
-{
- DWORD mode;
- if ( m_context )
- {
- ImmGetConversionStatus( m_context, nullptr, &mode );
-
- AsciiString flags;
-
- buildFlagsString( m_setSmodeInfo, mode, flags );
-
- DEBUG_LOG(( "IMM: Sentence mode = (%s)", flags.str()));
- }
-}
-#endif // DEBUG_IME
-
-
-//----------------------------------------------------------------------------
-// Public Functions
-//----------------------------------------------------------------------------
-
-//============================================================================
-// *CreateIMEManagerInterface
-//============================================================================
-
-IMEManagerInterface *CreateIMEManagerInterface( void )
-{
- return NEW IMEManager;
-}
-
-
-//============================================================================
-// IMEManager::IMEManager
-//============================================================================
-
-IMEManager::IMEManager()
-: m_window(nullptr),
- m_context(nullptr),
- m_candidateWindow(nullptr),
- m_statusWindow(nullptr),
- m_candidateCount(0),
- m_candidateString(nullptr),
- m_compositionStringLength(0),
- m_composing(FALSE),
- m_disabled(0),
- m_result(0),
- m_indexBase(1),
-
- m_compositionCharsDisplayed(0),
- m_candidateDownArrow(nullptr),
- m_candidateTextArea(nullptr),
- m_candidateUpArrow(nullptr),
- m_compositionCursorPos(0),
- m_pageSize(0),
- m_pageStart(0),
- m_selectedIndex(0),
- m_unicodeIME(FALSE)
-{
-}
-
-//============================================================================
-// IMEManager::~IMEManager
-//============================================================================
-
-IMEManager::~IMEManager()
-{
- if ( m_candidateWindow )
- {
- m_candidateWindow->winSetUserData( nullptr );
- m_candidateTextArea->winSetUserData( nullptr );
-
- TheWindowManager->winDestroy( m_candidateWindow );
- }
-
- if ( m_statusWindow )
- {
- TheWindowManager->winDestroy( m_statusWindow );
- }
-
- delete [] m_candidateString;
-
- detach();
- ImmAssociateContext( ApplicationHWnd, m_oldContext );
- ImmReleaseContext( ApplicationHWnd, m_oldContext );
- if ( m_context )
- {
- ImmDestroyContext( m_context );
- }
-}
-
-//============================================================================
-// IMEManager::init
-//============================================================================
-
-void IMEManager::init( void )
-{
- //HWND ImeWindow = ImmGetDefaultIMEWnd(ApplicationHWnd);
- // if(ImeWindow)
- // {
- // DestroyWindow(ImeWindow);
- // }
-
- m_context = ImmCreateContext();
- m_oldContext = ImmGetContext( ApplicationHWnd );
- m_disabled = 0;
- m_candidateWindow = TheWindowManager->winCreateFromScript( "IMECandidateWindow.wnd");
- m_candidateWindow->winSetStatus(WIN_STATUS_ABOVE);
-
- if ( m_candidateWindow )
- {
- m_candidateWindow->winHide( TRUE );
-
- // find text area window
- NameKeyType id = TheNameKeyGenerator->nameToKey( "IMECandidateWindow.wnd:TextArea" );
- m_candidateTextArea = TheWindowManager->winGetWindowFromId(m_candidateWindow, id);
-
- // find arrows
- id = TheNameKeyGenerator->nameToKey( "IMECandidateWindow.wnd:UpArrow" );
- m_candidateUpArrow = TheWindowManager->winGetWindowFromId(m_candidateWindow, id);
-
- id = TheNameKeyGenerator->nameToKey( "IMECandidateWindow.wnd:DownArrow" );
- m_candidateDownArrow = TheWindowManager->winGetWindowFromId(m_candidateWindow, id);
-
-
-
- if ( m_candidateTextArea == nullptr )
- {
- TheWindowManager->winDestroy( m_candidateWindow );
- m_candidateWindow = nullptr;
- }
- }
-
- m_statusWindow = TheWindowManager->winCreateFromScript( "IMEStatusWindow.wnd");
-
- if ( m_statusWindow )
- {
- m_statusWindow->winHide( TRUE );
- }
-
- // attach IMEManager to each window
- if ( m_candidateWindow != nullptr )
- {
- m_candidateWindow->winSetUserData( TheIMEManager );
- m_candidateTextArea->winSetUserData( TheIMEManager );
- }
-
- detach();
- enable();
-}
-
-//============================================================================
-// IMEManager::reset
-//============================================================================
-
-void IMEManager::reset( void )
-{
-
-}
-
-//============================================================================
-// IMEManager::update
-//============================================================================
-
-void IMEManager::update( void )
-{
-
-}
-
-//============================================================================
-// IMEManager::attach
-//============================================================================
-
-void IMEManager::attach( GameWindow *window )
-{
- if ( m_window != window )
- {
- detach();
- if ( m_disabled == 0 )
- {
- ImmAssociateContext( ApplicationHWnd, m_context );
- updateStatusWindow();
- //openStatusWindow();
- }
- m_window = window;
- }
-}
-
-//============================================================================
-// IMEManager::detach
-//============================================================================
-
-void IMEManager::detach( void )
-{
- //ImmAssociateContext( ApplicationHWnd, nullptr );
- m_window = nullptr;
-
-}
-
-//============================================================================
-// IMEManager::serviceIMEMessage
-//============================================================================
-
-Bool IMEManager::serviceIMEMessage( void *windowsHandle, UnsignedInt message, Int wParam, Int lParam )
-{
-
- DEBUG_ASSERTCRASH( windowsHandle == ApplicationHWnd, ("Unexpected window handle for IMEManager") );
- #ifdef DEBUG_IME
- printMessageInfo( message, wParam, lParam );
- #endif
-
- switch(message){
-
- // --------------------------------------------------------------------
- case WM_IME_CHAR:
- {
- WideChar wchar = convertCharToWide(wParam);
- #ifdef DEBUG_IME
- DEBUG_LOG(("IMM: WM_IME_CHAR - '%hc'0x%04x", wchar, wchar ));
- #endif
-
- if ( m_window && (wchar > 32 || wchar == VK_RETURN ))
- {
- TheWindowManager->winSendInputMsg( m_window, GWM_IME_CHAR, (wParam & 0xffff), lParam );
- m_result = 0;
- return TRUE;
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
- case WM_CHAR:
- {
- WideChar wchar = (WideChar) (wParam & 0xffff);
-
- #ifdef DEBUG_IME
- DEBUG_LOG(("IMM: WM_CHAR - '%hc'0x%04x", wchar, wchar ));
- #endif
-
- if ( m_window && (wchar >= 32 || wchar == VK_RETURN) )
- {
- TheWindowManager->winSendInputMsg( m_window, GWM_IME_CHAR, (wParam & 0xffff), lParam );
- m_result = 0;
- return TRUE;
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
- case WM_IME_SELECT:
- DEBUG_LOG(("IMM: WM_IME_SELECT"));
- return FALSE;
- case WM_IME_STARTCOMPOSITION:
- //The WM_IME_STARTCOMPOSITION message is sent immediately before an
- //IME generates a composition string as a result of a user's keystroke.
- //
- m_composing = TRUE;
- m_compositionCharsDisplayed = 0;
- updateCompositionString();
- m_result = 1;
- return TRUE;
- // --------------------------------------------------------------------
- case WM_IME_ENDCOMPOSITION:
- {
- //First remove the composition characters
- m_composing = FALSE;
- while (m_compositionCharsDisplayed > 0)
- { //if cursor has moved since start of composition, we need to move it back using backspace message
- TheWindowManager->winSendInputMsg( m_window, GWM_CHAR, KEY_BACKSPACE, KEY_STATE_DOWN);
- m_compositionCharsDisplayed--;
- }
- closeCandidateList(0);
- return TRUE;
- // I removed the rest of this message handler because we update
- // the strings real time inside WM_IME_COMPOSITION
- // instead of waiting for user to enter separator. -MW
-
- //IMEs send this message to the application when the IMEs' composition
- //windows have closed. Applications that display their own composition
- //characters should process this message. Other applications should
- //send the message to the application IME window or to DefWindowProc,
- //which will pass the message to the default IME window.
- //
-
- m_composing = FALSE; // reset this flag before calling GWM_IME_CHAR
-
- if ( m_window )
- {
- WideChar *ch = m_resultsString;
- getResultsString();
- while ( *ch )
- {
- TheWindowManager->winSendInputMsg( m_window, GWM_IME_CHAR, *ch, 0 );
- ch++;
- }
- }
- m_result = 1;
- return TRUE;
- }
- // --------------------------------------------------------------------
- case WM_IME_COMPOSITION:
- {
- //IMEs send this message to the application when they change composition
- //status in response to a keystroke. Applications that display their own
- //composition characters should process this message by calling
- //ImmGetCompositionString. Other applications should send the message to
- //the application IME window or to DefWindowProc, which will pass the
- //message to the default IME window.
- //
- //The WM_IME_COMPOSITION message is sent to an application when the IME
- //changes composition status as a result of a keystroke. An application
- //should process this message if it displays composition characters itself.
- //Otherwise, it should send the message to the IME window. This message
- //has no return value. wParam = DBCS character. lParam = change indicator.
- //
-
- if (lParam & GCS_RESULTSTR) //added to show instant updates as soon as a character is translated. -MW
- {
- if ( m_window )
- {
- m_composing = FALSE; // reset this flag before calling GWM_IME_CHAR
-
- while (m_compositionCharsDisplayed > 0)
- { //if cursor has moved since start of composition, we need to move it back using backspace message
- TheWindowManager->winSendInputMsg( m_window, GWM_CHAR, KEY_BACKSPACE, KEY_STATE_DOWN);
- m_compositionCharsDisplayed--;
- }
-
- WideChar *ch = m_resultsString;
- getResultsString();
- while ( *ch )
- {
- TheWindowManager->winSendInputMsg( m_window, GWM_IME_CHAR, *ch, 0 );
- ch++;
- }
- }
- m_compositionCharsDisplayed = 0;
- }
- else
- if (lParam & CS_INSERTCHAR && lParam & CS_NOMOVECARET)
- { //we are supposed to display the composition character without moving the cursor. (it's a candidate).
- if (m_window)
- {
- m_composing = FALSE; // reset this flag before calling GWM_IME_CHAR
-
- while (m_compositionCharsDisplayed > 0)
- { //if cursor has moved since start of composition, we need to move it back using backspace message
- TheWindowManager->winSendInputMsg( m_window, GWM_CHAR, KEY_BACKSPACE, KEY_STATE_DOWN);
- m_compositionCharsDisplayed--;
- }
-
- WideChar *ch = m_compositionString;
- updateCompositionString();
- while (*ch)
- {
- TheWindowManager->winSendInputMsg(m_window, GWM_IME_CHAR, *ch, 0 );
- ch++;
- m_compositionCharsDisplayed++;
- }
- m_composing = TRUE; // reset this flag before calling GWM_IME_CHAR
- }
- }
- else
- if (lParam & GCS_COMPSTR)
- { //we are supposed to display the composition character without moving the cursor. (it's a candidate).
- if (m_window)
- {
- m_composing = FALSE; // reset this flag before calling GWM_IME_CHAR
-
- while (m_compositionCharsDisplayed > 0)
- { //if cursor has moved since start of composition, we need to move it back using backspace message
- TheWindowManager->winSendInputMsg( m_window, GWM_CHAR, KEY_BACKSPACE, KEY_STATE_DOWN);
- m_compositionCharsDisplayed--;
- }
-
- WideChar *ch = m_compositionString;
- updateCompositionString();
- while (*ch)
- {
- TheWindowManager->winSendInputMsg(m_window, GWM_IME_CHAR, *ch, 0 );
- ch++;
- m_compositionCharsDisplayed++;
- }
- m_composing = TRUE; // reset this flag before calling GWM_IME_CHAR
- }
- }
-
- m_result = 1;
- return TRUE;
- }
- // --------------------------------------------------------------------
- case WM_IME_SETCONTEXT:
- {
- //The system sends this message to an application when one of the
- //application's windows is activated. Applications should respond by
- //calling ImmGetContext.
- //
- updateProperties();
- //ignore for now
- m_result = 0;
- return FALSE;
- }
-
-
- // --------------------------------------------------------------------
- case WM_IME_NOTIFY:
- {
- //IMEs generate this message to notify the application or the IME window
- //that the IME status has changed. The wParam value is a submessage that
- //specifies the nature of the change.
- //
- switch(wParam)
- {
- case IMN_OPENCANDIDATE:
- {
- //This message is sent to the application when an IME is about to
- //open the candidate window. An application should process this
- //message if it displays candidates. The application can retrieve
- //a list of candidates to display by using theImmGetCandidateList
- //function. The application receives this notification message through
- //the WM_IME_NOTIFY message.
- //
-
- // open candidate window
- openCandidateList( lParam );
- m_result = 1;
- return TRUE;
- }
- case IMN_CLOSECANDIDATE:
- {
- //This message is sent to the application when an IME is about to
- //close the candidate window. An application should process this
- //message if it displays candidates. The application receives this
- //notification message through the WM_IME_NOTIFY message.
- //
- closeCandidateList( lParam );
- m_result = 1;
- return TRUE;
- }
-
- case IMN_CHANGECANDIDATE:
- {
- //This message is sent to the application when an IME is about to
- //change the content of the candidate window. An application should
- //process this notification message if it displays candidates itself.
- //The application receives this notification message through the
- //WM_IME_NOTIFY message.
- //
- updateCandidateList( lParam );
- m_result = 1;
- return TRUE;
- }
- case IMN_GUIDELINE: //This message is sent when an IME is about to show an error message or other data.
- {
- // display error message
- m_result = 1;
- return FALSE;
- }
-
- case IMN_SETCONVERSIONMODE: //This message is sent when the conversion mode of the input context is updated.
- {
- #ifdef DEBUG_IME
- printConversionStatus();
- #endif
- return FALSE;
- }
-
- case IMN_SETSENTENCEMODE: //This message is sent when the sentence mode of the input context is updated.
- {
- #ifdef DEBUG_IME
- printSentenceStatus();
- #endif
- return FALSE;
- }
-/*
- // pass the reset on through to the installed IME
- case IMN_SETCANDIDATEPOS: //This message is sent when the IME is about to move the candidate window.
- case IMN_SETSTATUSWINDOWPOS: //This message is sent when the status window position in the input context is updated.
- return FALSE;
- case IMN_OPENSTATUSWINDOW: //This message is sent when an IME is about to create the status window.
- DEBUG_LOG(("Open Status Window"));
- return FALSE;
- case IMN_CLOSESTATUSWINDOW: //This message is sent to the application when an input method editor (IME) is about to close the status window.
- DEBUG_LOG(("Close Status Window"));
- return FALSE;
- case IMN_SETOPENSTATUS: //This message is sent when the open status of the input context is updated.
- case IMN_SETCOMPOSITIONFONT: //This message is sent when the font of the input context is updated.
- case IMN_SETCOMPOSITIONWINDOW: //This message is sent when the style or position of the composition window is updated.
- case IMN_PRIVATE: //This message is for your own use, it seems.
-*/ default:
- m_result = 1;
- return TRUE;
- }
- break;
- }
-
- // --------------------------------------------------------------------
- case WM_IME_COMPOSITIONFULL:
- {
- //IMEs send this message to the application when they are unable to
- //extend the composition window to accommodate any more characters.
- //Applications should tell IMEs how to display the composition window
- //using the IMC_SETCOMPOSITIONWINDOW message.
- //
- //I'm not sure what to do here.
- m_result = 1;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-//============================================================================
-// IMEManager::result
-//============================================================================
-
-Int IMEManager::result( void )
-{
- return m_result;
-}
-
-//============================================================================
-// IMEManager::enable
-//============================================================================
-
-void IMEManager::enable( void )
-{
- if ( --m_disabled <= 0 )
- {
- m_disabled = 0;
- ImmAssociateContext( ApplicationHWnd, m_context );
- }
-}
-
-//============================================================================
-// IMEManager::disable
-//============================================================================
-
-void IMEManager::disable( void )
-{
- m_disabled++;
- ImmAssociateContext( ApplicationHWnd, nullptr );
-}
-
-//============================================================================
-// IMEManager::isEnabled
-//============================================================================
-
-Bool IMEManager::isEnabled( void )
-{
- return m_context != nullptr && m_disabled == 0;
-}
-
-//============================================================================
-// IMEManager::isAttached
-//============================================================================
-
-Bool IMEManager::isAttachedTo( GameWindow *window )
-{
- return m_window == window;
-}
-
-//============================================================================
-// IMEManager::getWindow
-//============================================================================
-
-GameWindow* IMEManager::getWindow( void )
-{
- return m_window;
-}
-
-
-//============================================================================
-// IMEManager::convertChartoWide
-//============================================================================
-
-WideChar IMEManager::convertCharToWide( WPARAM wParam )
-{
- char dcbsString[3];
-
- if ( wParam&0xff00 )
- {
- dcbsString[0] = (wParam>>8)&0xff;
- dcbsString[1] = wParam&0xff;
- dcbsString[2] = 0;
- }
- else
- {
- dcbsString[0] = wParam&0xff;
- dcbsString[1] = 0;
- }
-
-
- WideChar uniString[2];
-
- if ( MultiByteToWideChar( CP_ACP, 0, dcbsString, strlen( dcbsString ), uniString, 1 ) == 1 )
- {
- return uniString[0];
- }
-
- return 0;
-}
-
-//============================================================================
-// IMEManager::isComposing
-//============================================================================
-
-Bool IMEManager::isComposing( void )
-{
- return m_composing;
-}
-
-
-void IMEManager::getCompositionString ( UnicodeString &string )
-{
- string.set(m_compositionString);
-}
-
-//============================================================================
-// IMEManager::getCompositionCursorPosition
-//============================================================================
-
-Int IMEManager::getCompositionCursorPosition( void )
-{
- return 0;//m_compositionCursorPos;
-}
-
-//============================================================================
-// IMEManager::updateCompositionString
-//============================================================================
-
-void IMEManager::updateCompositionString( void )
-{
- char tempBuf[ (MAX_COMPSTRINGLEN+1)*2];
-
- m_compositionCursorPos = 0;
- m_compositionString[0] = 0;
- m_compositionStringLength = 0;
-
- if ( m_context )
- {
- // try reading unicode directly
- LONG result = ImmGetCompositionStringW( m_context, GCS_COMPSTR, m_compositionString, MAX_COMPSTRINGLEN );
-
- if ( result >= 0 )
- {
- m_compositionStringLength = result/2;
- m_compositionCursorPos = (ImmGetCompositionStringW( m_context, GCS_CURSORPOS, nullptr, 0) & 0xffff );
- }
- else
- {
-
- // read MBCS instead
- result = ImmGetCompositionStringA( m_context, GCS_COMPSTR, tempBuf, MAX_COMPSTRINGLEN*2);
-
- if ( result > 0 )
- {
- tempBuf[ result ] = '\0';
-
- int convRes = MultiByteToWideChar( CP_ACP, 0, tempBuf, -1, m_compositionString, MAX_COMPSTRINGLEN );
- GameArrayEnd(m_compositionString);
-
- if ( convRes < 0)
- {
- convRes = 0;
- }
- else
- {
- m_compositionCursorPos = (ImmGetCompositionString( m_context, GCS_CURSORPOS, nullptr, 0) & 0xffff );
- convRes = wcslen( m_compositionString );
- }
-
- // m_compositionCursorPos is in DBCS characters, need to convert it to Wide characters
-
- //msg_assert ( (int)strlen(tempBuf) >= convRes ,("bad DBCS string: DBCS = %d chars, Wide = %d chars", strlen(tempBuf), convRes));
- m_compositionCursorPos = _mbsnccnt ( (unsigned char *) tempBuf, m_compositionCursorPos );
-
- m_compositionString[convRes] = 0;
- m_compositionStringLength = convRes;
- if ( m_compositionCursorPos > convRes )
- {
- m_compositionCursorPos = convRes;
- }
- else if ( m_compositionCursorPos < 0 )
- {
- m_compositionCursorPos = 0;
- }
- }
- }
- }
-
- DEBUG_ASSERTCRASH( m_compositionStringLength < MAX_COMPSTRINGLEN, ("composition string too large"));
- m_compositionString[m_compositionStringLength] = 0;
- GameArrayEnd(m_compositionString);
-}
-
-//============================================================================
-// IMEManager::getResultsString
-//============================================================================
-
-void IMEManager::getResultsString ( void )
-{
- Int stringLen = 0;
- m_resultsString[0] = 0;
-
- if ( m_context )
- {
- // try reading unicode directly
- LONG result = ImmGetCompositionStringW( m_context, GCS_RESULTSTR, m_resultsString, MAX_COMPSTRINGLEN );
-
- if ( result >= 0 )
- {
- stringLen = result/2;
- }
- else
- {
- char tempBuf[ (MAX_COMPSTRINGLEN+1)*2];
-
- // read MBCS instead
- result = ImmGetCompositionStringA( m_context, GCS_RESULTSTR, tempBuf, MAX_COMPSTRINGLEN*2);
-
- if ( result > 0 )
- {
- tempBuf[ result ] = '\0';
-
- int convRes = MultiByteToWideChar( CP_ACP, 0, tempBuf, strlen(tempBuf), m_resultsString, MAX_COMPSTRINGLEN );
-
- if ( convRes < 0)
- {
- convRes = 0;
- }
- stringLen = convRes;
- }
- }
- }
-
- DEBUG_ASSERTCRASH( stringLen < MAX_COMPSTRINGLEN, ("results string too large"));
- m_resultsString[stringLen] = 0;
- GameArrayEnd(m_resultsString);
-}
-
-//============================================================================
-// IMEManager::convertToUnicode
-//============================================================================
-
-void IMEManager::convertToUnicode ( Char *mbcs, UnicodeString &unicode )
-{
- int size = MultiByteToWideChar( CP_ACP, 0, mbcs, strlen(mbcs), nullptr, 0 );
-
- unicode.clear();
-
- if ( size <= 0 )
- {
- return;
- }
-
- WideChar *buffer = NEW WideChar[ size + 1 ];
-
- if ( buffer )
- {
- size = MultiByteToWideChar( CP_ACP, 0, mbcs, strlen(mbcs), buffer, size );
-
- if ( size <= 0 )
- {
- unicode.clear();
- }
- else
- {
- buffer[size] = 0;
- unicode = buffer;
- }
-
- delete [] buffer;
- }
-}
-
-//============================================================================
-// IMEManager::openCandidateList
-//============================================================================
-
-void IMEManager::openCandidateList( Int candidateFlags )
-{
- if ( m_candidateWindow == nullptr )
- {
- return;
- }
- // first get latest candidate list info
- updateCandidateList( candidateFlags );
- resizeCandidateWindow( m_pageSize );
-
- m_candidateWindow->winHide( FALSE );
- m_candidateWindow->winBringToTop();
- TheWindowManager->winSetModal( m_candidateWindow );
-
- Int wx, wy, wwidth, wheight, wcursorx, wcursory;
- Int cx, cy, cwidth, cheight;
- Int textHeight = 20;
-
-
- if ( m_window )
- {
- m_window->winGetScreenPosition( &wx, &wy);
- m_window->winGetSize( &wwidth, &wheight );
- m_window->winGetCursorPosition( &wcursorx, &wcursory );
- GameFont *font = m_window->winGetFont();
- if ( font )
- {
- textHeight = font->height;
- }
- }
- else
- {
- wx = wy = 0;
- wwidth = 10;
- wheight = 10;
- wcursorx = 0;
- wcursory = 0;
- }
-
- m_candidateWindow->winGetSize( &cwidth, &cheight );
-
-// // try putting the candidate list above the text
-// cx = wx + wcursorx;
-// cy = wy - cheight;
-//
-// if ( cx + cwidth > (Int) TheDisplay->getWidth())
-// {
-// cx = cx - cwidth;
-// }
-// if( cx < 0 )
-// cx = 0;
-// if ( cy < 0 )
-// {
-// // place list below text
-// cy = wy + textHeight + textHeight/2;
-// }
-// if( cy + cheight > TheDisplay->getHeight())
-// cy = 0;
- cx = TheDisplay->getWidth() - cwidth;
- cy = 0;
- updateProperties();
- m_candidateWindow->winSetPosition( cx, cy );
-
-}
-
-//============================================================================
-// IMEManager::closeCandidateList
-//============================================================================
-
-void IMEManager::closeCandidateList( Int candidateFlags )
-{
- if ( m_candidateWindow != nullptr )
- {
- m_candidateWindow->winHide( TRUE );
- TheWindowManager->winUnsetModal( m_candidateWindow );
- }
-
- delete [] m_candidateString;
- m_candidateString = nullptr;
-
- m_candidateCount = 0;
-
-}
-
-//============================================================================
-// IMEManager::updateCandidateList
-//============================================================================
-
-void IMEManager::updateCandidateList( Int candidateFlags )
-{
-
- delete [] m_candidateString;
- m_candidateString = nullptr;
-
- m_pageSize = 10;
- m_candidateCount = 0;
- m_pageStart = 0;
- m_selectedIndex = 0;
-
- if ( m_candidateWindow == nullptr ||
- m_context == nullptr ||
- candidateFlags == 0)
- {
- return;
- }
-
- for( Int i = 0, candidate = 1; i < 32; i++, candidate = candidate << 1 )
- {
- if ( candidateFlags & candidate )
- {
- Bool unicode = TRUE;
- unsigned long listCount = 0;
-
- Int size = ImmGetCandidateListCountW( m_context, &listCount );
-
- if ( size <= 0 )
- {
- unicode = FALSE;
- size = ImmGetCandidateListCountA( m_context, &listCount );
- if ( size <= 0 )
- {
- return;
- }
- }
-
- // create a temporary buffer for reading the candidate list
- Char *buffer = NEW Char[size];
-
- if ( buffer == nullptr )
- {
- return;
- }
-
- memset( buffer, 0, size );
-
- CANDIDATELIST *clist = (CANDIDATELIST*) buffer;
-
- Bool ok = TRUE ;
- Int bytesCopied;
-
- if ( unicode )
- {
- bytesCopied = ImmGetCandidateListW( m_context, i, (CANDIDATELIST*) clist, size );
- }
- else
- {
- bytesCopied = ImmGetCandidateListA( m_context, i, (CANDIDATELIST*) clist, size );
- }
-
- if ( bytesCopied == 0 || bytesCopied > size )
- {
- DEBUG_ASSERTCRASH(bytesCopied < size,("IME candidate buffer overrun"));
- ok = FALSE;
- }
-
- if ( ok && clist->dwStyle != IME_CAND_UNKNOWN && clist->dwStyle != IME_CAND_CODE )
- {
- //Apparently there is an "IME98 bug" (IME bug under Windows 98?) that
- //causes you to have to execute the following code.
- if(( clist->dwPageStart > clist->dwSelection) ||
- (clist->dwSelection >= clist->dwPageStart + clist->dwPageSize))
- {
- clist->dwPageStart = (clist->dwSelection / clist->dwPageSize) * clist->dwPageSize;
- }
-
- m_pageSize = clist->dwPageSize;
- m_candidateCount = clist->dwCount;
- m_pageStart = clist->dwPageStart;
- m_selectedIndex = clist->dwSelection;
-
- #ifdef DEBUG_IME
- DEBUG_LOG(("IME: Candidate Update: Candidates = %d, pageSize = %d pageStart = %d, selected = %d", m_candidateCount, m_pageStart, m_pageSize, m_selectedIndex ));
- #endif
-
- if ( m_candidateUpArrow )
- {
- m_candidateUpArrow->winHide( m_pageStart == 0 );
- }
-
- if ( m_candidateDownArrow )
- {
- m_candidateDownArrow->winHide( m_candidateCount - m_pageStart <= m_pageSize );
- }
-
- if ( m_candidateCount > 0 )
- {
- m_candidateString = NEW UnicodeString[m_candidateCount];
- if ( m_candidateString )
- {
- Int i;
-
- for( i=0; i < m_candidateCount; i++ )
- {
- Char *string = (Char*) ((UnsignedInt) clist + (UnsignedInt) clist->dwOffset[i]);
- if ( unicode )
- {
- m_candidateString[i].set( (WideChar *) string);
- }
- else
- {
- convertToUnicode( string, m_candidateString[i] );
- }
- }
- }
- }
-
- }
- delete [] buffer;
- return;
- }
- }
-}
-
-//============================================================================
-// IMEManager::updateProperties
-//============================================================================
-
-void IMEManager::updateProperties( void )
-{
- HKL kb = GetKeyboardLayout( 0 );
- Int prop = ImmGetProperty( kb, IGP_PROPERTY );
- m_indexBase = prop & IME_PROP_CANDLIST_START_FROM_1 ? 1 : 0 ;
- m_unicodeIME = (prop & IME_PROP_UNICODE) != 0 ;
-}
-
-//============================================================================
-// IMEManager::getIndexBase
-//============================================================================
-
-Int IMEManager::getIndexBase( void )
-{
- return m_indexBase;
-}
-
-//============================================================================
-// IMEManager::resizeCandidateWindow
-//============================================================================
-
-void IMEManager::resizeCandidateWindow( Int pageSize )
-{
- if ( m_candidateWindow == nullptr )
- {
- return;
- }
-
- GameFont *font = m_candidateTextArea->winGetFont();
-
- if ( font == nullptr )
- {
- return;
- }
-
- Int newh = pageSize * (font->height + IMECandidateWindowLineSpacing);
- Int w, h;
- m_candidateTextArea->winGetSize( &w, &h );
-
- Int dif = newh - h;
-
- m_candidateTextArea->winSetSize( w, newh );
-
- m_candidateWindow->winGetSize( &w, &h );
- h += dif;
- m_candidateWindow->winSetSize( w, h );
-
- if ( m_candidateDownArrow )
- {
- Int x, y;
- m_candidateDownArrow->winGetPosition( &x, &y );
- y += dif;
- m_candidateDownArrow->winSetPosition( x, y );
- }
-
-}
-
-//============================================================================
-// IMEManager::getCandidateCount
-//============================================================================
-
-Int IMEManager::getCandidateCount()
-{
- return m_candidateCount;
-}
-
-//============================================================================
-// IMEManager::getCandidate
-//============================================================================
-
-const UnicodeString* IMEManager::getCandidate( Int index )
-{
- if ( m_candidateString != nullptr && index >=0 && index < m_candidateCount )
- {
- return &m_candidateString[index];
- }
-
- return &UnicodeString::TheEmptyString;
-}
-
-//============================================================================
-// IMEManager::getSelectedCandidateIndex
-//============================================================================
-
-Int IMEManager::getSelectedCandidateIndex()
-{
- return m_selectedIndex;
-}
-
-//============================================================================
-// IMEManager::getCandidatePageSize
-//============================================================================
-
-Int IMEManager::getCandidatePageSize()
-{
- return m_pageSize;
-}
-
-//============================================================================
-// IMEManager::getStartCandidateIndex
-//============================================================================
-
-Int IMEManager::getCandidatePageStart()
-{
- return m_pageStart;
-}
-
-//============================================================================
-// IMEManager::openStatusWindow
-//============================================================================
-
-void IMEManager::openStatusWindow( void )
-{
- if ( m_statusWindow == nullptr )
- {
- return;
- }
- m_statusWindow->winHide( FALSE );
-}
-
-//============================================================================
-// IMEManager::closeStatusWindow
-//============================================================================
-
-void IMEManager::closeStatusWindow( void )
-{
- if ( m_statusWindow == nullptr )
- {
- return;
- }
-
- m_statusWindow->winHide( TRUE );
-}
-
-//============================================================================
-// IMEManager::updateStatusWindow
-//============================================================================
-
-void IMEManager::updateStatusWindow( void )
-{
-
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
deleted file mode 100644
index b59692c25ae..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
+++ /dev/null
@@ -1,1391 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: LoadScreen.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Mar 2002
-//
-// Filename: LoadScreen.cpp
-//
-// author: Chris Huybregts
-//
-// purpose: Contains each of the different derived LoadClasses for each of the
-// Different kind of games we can have.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "Common/NameKeyGenerator.h"
-#include "Common/MultiplayerSettings.h"
-#include "Common/GameEngine.h"
-#include "Common/GameState.h"
-#include "Common/PlayerTemplate.h"
-#include "Common/PlayerList.h"
-#include "Common/Player.h"
-#include "Common/GameLOD.h"
-#include "Common/GameAudio.h"
-#include "Common/AudioEventRTS.h"
-#include "Common/AudioHandleSpecialValues.h"
-#include "Common/AudioAffect.h"
-
-#include "GameClient/LoadScreen.h"
-#include "GameClient/Keyboard.h"
-#include "GameClient/Shell.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameClient/GadgetProgressBar.h"
-#include "GameClient/GadgetStaticText.h"
-#include "GameClient/GameText.h"
-#include "GameClient/Display.h"
-#include "GameClient/WindowLayout.h"
-#include "GameClient/Mouse.h"
-#include "GameClient/VideoPlayer.h"
-#include "GameClient/MapUtil.h"
-#include "GameLogic/FPUControl.h"
-#include "GameLogic/GameLogic.h"
-#include "GameNetwork/NetworkInterface.h"
-#include "GameNetwork/GameSpy/PeerDefs.h"
-#include "GameNetwork/GameSpy/PersistentStorageThread.h"
-#include "GameClient/CampaignManager.h"
-#include "GameNetwork/RankPointValue.h"
-#include "GameClient/GameWindowTransitions.h"
-
-//-----------------------------------------------------------------------------
-// DEFINES ////////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-
-//-----------------------------------------------------------------------------
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-void positionStartSpots( GameInfo *myGame, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow);
-void updateMapStartSpots( GameInfo *myGame, GameWindow *buttonMapStartPositions[], Bool onLoadScreen = FALSE );
-void positionAdditionalImages( MapMetaData *mmd, GameWindow *mapWindow, Bool force);
-
-enum{
-FRAME_FUDGE_ADD = 30,
-};
-//-----------------------------------------------------------------------------
-// LoadScreen Class
-//-----------------------------------------------------------------------------
-
-LoadScreen::LoadScreen( void )
-{
- m_loadScreen = nullptr;
-}
-
-LoadScreen::~LoadScreen( void )
-{
- //if(m_loadScreen)
- // delete (m_loadScreen);
- if(m_loadScreen)
- TheWindowManager->winDestroy( m_loadScreen );
- m_loadScreen = nullptr;
-}
-
-void LoadScreen::update( Int percent )
-{
- TheGameEngine->serviceWindowsOS();
- TheWindowManager->update();
- TheDisplay->update();
- // redraw all views, update the GUI
- TheDisplay->draw();
-
- setFPMode();
-}
-
-
-// SinglePlayerLoadScreen Class ///////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-SinglePlayerLoadScreen::SinglePlayerLoadScreen( void )
-{
- m_currentObjectiveLine = 0;
- m_currentObjectiveLineCharacter = 0;
- m_finishedObjectiveText = FALSE;
- m_currentObjectiveWidthOffset = 0;
- m_progressBar = nullptr;
- m_percent = nullptr;
- m_videoStream = nullptr;
- m_videoBuffer = nullptr;
- m_objectiveWin = nullptr;
- for(Int i = 0; i < MAX_OBJECTIVE_LINES; ++i)
- m_objectiveLines[i] = nullptr;
-
-}
-
-SinglePlayerLoadScreen::~SinglePlayerLoadScreen( void )
-{
- m_progressBar = nullptr;
- m_percent = nullptr;
- m_objectiveWin = nullptr;
- for(Int i = 0; i < MAX_OBJECTIVE_LINES; ++i)
- m_objectiveLines[i] = nullptr;
-
- delete m_videoBuffer;
- m_videoBuffer = nullptr;
-
- if ( m_videoStream )
- {
- m_videoStream->close();
- m_videoStream = nullptr;
- }
-
- TheAudio->removeAudioEvent( m_ambientLoopHandle );
- m_ambientLoopHandle = 0;
-
-}
-
-void SinglePlayerLoadScreen::moveWindows( Int frame )
-{
- enum{
- STATE_BEGIN = 250,
- STATE_SHOW_LOCATION = 251,
- STATE_BEGIN_BRIEFING = 255,
-// STATE_BEGIN_ANIMATING_TEXT = 250,
- STATE_SHOW_CAMEO_1 = 434,
- STATE_BEGIN_ANIMATING_TEXT = 356,
- STATE_HIDE_CAMEO_1 = 459,
- STATE_SHOW_CAMEO_2 = 464,
- STATE_HIDE_CAMEO_2 = 492,
- STATE_SHOW_CAMEO_3 = 497,
- STATE_HIDE_CAMEO_3 = 524,
-// STATE_END_ANIM_HEAD = 450,
- STATE_END_ANIMATING_TEXT = 730,
- STATE_END = 730
- };
- if(frame < STATE_BEGIN || frame > STATE_END)
- return;
-
- if( frame == STATE_BEGIN_BRIEFING)
- {
- // add sound support here
- TheAudio->friend_forcePlayAudioEventRTS(&TheCampaignManager->getCurrentMission()->m_briefingVoice);
- }
-
- if( frame == STATE_BEGIN_ANIMATING_TEXT)
- {
- m_objectiveWin->winHide(FALSE);
- // animate the text and stuff
- }
-
- if( frame > STATE_BEGIN_ANIMATING_TEXT && frame <= STATE_END_ANIMATING_TEXT && !m_finishedObjectiveText)
- {
- if(m_currentObjectiveLineCharacter >= m_unicodeObjectiveLines[m_currentObjectiveLine].getLength() )
- {
- m_currentObjectiveLine++;
- m_currentObjectiveLineCharacter =0;
- }
- if(m_currentObjectiveLine >= MAX_OBJECTIVE_LINES || m_unicodeObjectiveLines[m_currentObjectiveLine].isEmpty())
- {
- m_finishedObjectiveText = TRUE;
- }
- else
- {
- WideChar wChar = m_unicodeObjectiveLines[m_currentObjectiveLine].getCharAt(m_currentObjectiveLineCharacter);
- UnicodeString text = GadgetStaticTextGetText(m_objectiveLines[m_currentObjectiveLine]);
- text.concat(wChar);
- GadgetStaticTextSetText(m_objectiveLines[m_currentObjectiveLine], text);
-
- }
- m_currentObjectiveLineCharacter++;
- }
- switch (frame) {
-
- case STATE_SHOW_LOCATION:
- m_location->winHide(FALSE);
- break;
- case STATE_SHOW_CAMEO_1:
- m_unitDesc[0]->winHide(FALSE);
- break;
- case STATE_HIDE_CAMEO_1:
- m_unitDesc[0]->winHide(TRUE);
- break;
- case STATE_SHOW_CAMEO_2:
- m_unitDesc[1]->winHide(FALSE);
- break;
- case STATE_HIDE_CAMEO_2:
- m_unitDesc[1]->winHide(TRUE);
- break;
- case STATE_SHOW_CAMEO_3:
- m_unitDesc[2]->winHide(FALSE);
- break;
- case STATE_HIDE_CAMEO_3:
- m_unitDesc[2]->winHide(TRUE);
- break;
- }
-
-}
-/*
- static Bool on = FALSE;
- static ICoord2D startPos, endPos;
- enum{
- STATE_BEGIN = 275,
- STATE_BEGIN_ANIM = 290,
- STATE_ANIM_CAMEO1 = 300,
- STATE_ANIM_CAMEO1_TRANSITION_CAMEO2 = 350,
- STATE_ANIM_CAMEO2 = 400,
- STATE_ANIM_CAMEO2_TRANSITION_CAMEO3 = 450,
- STATE_ANIM_CAMEO3 = 500,
- STATED_END_ANIM = 550,
- STATE_END = 800
- };
- if(frame < STATE_BEGIN)
- return;
- else if(frame == STATE_BEGIN )
- {
- m_cameoWindow1->winHide(FALSE);
- m_cameoWindow2->winHide(FALSE);
- m_cameoWindow3->winHide(FALSE);
- m_cameoFrame->winHide(FALSE);
- }
- else if( frame == STATE_ANIM_CAMEO1)
- {
- m_cameoWindow1->winEnable(TRUE);
- GadgetStaticTextSetText(m_cameoText, TheGameText->fetch(TheCampaignManager->getCurrentMission()->m_cameoImageName[0]));
- //save of positions
- }
- else if( frame == STATE_ANIM_CAMEO1_TRANSITION_CAMEO2)
- {
- m_cameoWindow1->winEnable(FALSE);
- GadgetStaticTextSetText(m_cameoText, UnicodeString::TheEmptyString);
- ICoord2D tempPos;
- Int xOffset;
- m_cameoFrame->winGetPosition(&startPos.x, &startPos.y);
- m_cameoWindow1->winGetPosition(&tempPos.x, &tempPos.y);
- xOffset = tempPos.x - startPos.x;
- m_cameoWindow2->winGetPosition(&endPos.x, &endPos.y);
- endPos.x = endPos.x - xOffset;
- endPos.y = startPos.y;
-
- }
- else if( frame > STATE_ANIM_CAMEO1_TRANSITION_CAMEO2 && frame < STATE_ANIM_CAMEO2)
- {
-
- //extrapolate between start and end pos
- Real percent = INT_TO_REAL((frame - STATE_ANIM_CAMEO1_TRANSITION_CAMEO2)) / (STATE_ANIM_CAMEO2 - STATE_ANIM_CAMEO1_TRANSITION_CAMEO2);
- m_cameoFrame->winSetPosition(startPos.x + (endPos.x - startPos.x) * percent, endPos.y);
- }
- else if( frame == STATE_ANIM_CAMEO2 )
- {
- m_cameoWindow2->winEnable(TRUE);
- m_cameoFrame->winSetPosition(endPos.x, endPos.y);
- GadgetStaticTextSetText(m_cameoText, TheGameText->fetch(TheCampaignManager->getCurrentMission()->m_cameoImageName[1]));
- }
- else if( frame == STATE_ANIM_CAMEO2_TRANSITION_CAMEO3)
- {
- m_cameoWindow2->winEnable(FALSE);
- GadgetStaticTextSetText(m_cameoText, UnicodeString::TheEmptyString);
- ICoord2D tempPos;
- Int xOffset;
- m_cameoFrame->winGetPosition(&startPos.x, &startPos.y);
- m_cameoWindow2->winGetPosition(&tempPos.x, &tempPos.y);
- xOffset = tempPos.x - startPos.x;
- m_cameoWindow3->winGetPosition(&endPos.x, &endPos.y);
- endPos.x = endPos.x - xOffset;
- endPos.y = startPos.y;
-
- }
- else if( frame > STATE_ANIM_CAMEO2_TRANSITION_CAMEO3 && frame < STATE_ANIM_CAMEO3)
- {
-
- //extrapolate between start and end pos
- Real percent = INT_TO_REAL((frame - STATE_ANIM_CAMEO2_TRANSITION_CAMEO3)) / (STATE_ANIM_CAMEO3 - STATE_ANIM_CAMEO2_TRANSITION_CAMEO3);
- m_cameoFrame->winSetPosition(startPos.x + (endPos.x - startPos.x) * percent, endPos.y);
- }
- else if( frame == STATE_ANIM_CAMEO3 )
- {
- m_cameoFrame->winSetPosition(endPos.x, endPos.y);
- m_cameoWindow3->winEnable(TRUE);
- GadgetStaticTextSetText(m_cameoText, TheGameText->fetch(TheCampaignManager->getCurrentMission()->m_cameoImageName[2]));
- }
- else if( frame ==STATED_END_ANIM)
- {
- m_cameoWindow3->winEnable(FALSE);
- GadgetStaticTextSetText(m_cameoText, UnicodeString::TheEmptyString);
- m_cameoFrame->winHide(TRUE);
-
- }
-}*/
-
-void SinglePlayerLoadScreen::init( GameInfo *game )
-{
- //No music in SinglePlayerLoadScreen
-
- // create the layout of the load screen
- m_loadScreen = TheWindowManager->winCreateFromScript( "Menus/SinglePlayerLoadScreen.wnd" );
- DEBUG_ASSERTCRASH(m_loadScreen, ("Can't initialize the single player loadscreen"));
- m_loadScreen->winHide(FALSE);
- m_loadScreen->winBringToTop();
-// Mission *mission = TheCampaignManager->getCurrentMission();
- // Store the pointer to the progress bar on the loadscreen
- m_progressBar = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:ProgressLoad" ));
- DEBUG_ASSERTCRASH(m_progressBar, ("Can't initialize the progressbar for the single player loadscreen"));
- GadgetProgressBarSetProgress(m_progressBar, 0 );
-
- m_percent = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:Percent" ));
- DEBUG_ASSERTCRASH(m_percent, ("Can't initialize the m_percent for the single player loadscreen"));
- GadgetStaticTextSetText(m_percent,L"0%");
- m_percent->winHide(TRUE);
-
- m_objectiveWin = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:ObjectivesWin" ));
- DEBUG_ASSERTCRASH(m_objectiveWin, ("Can't initialize the m_objectiveWin for the single player loadscreen"));
- m_objectiveWin->winHide(TRUE);
-
-
- Mission *mission = TheCampaignManager->getCurrentMission();
- AsciiString lineName;
- Int i = 0;
- for(; i < MAX_OBJECTIVE_LINES; ++i)
- {
- lineName.format("SinglePlayerLoadScreen.wnd:StaticTextLine%d",i);
- m_objectiveLines[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( lineName ));
- DEBUG_ASSERTCRASH(m_objectiveLines[i], ("Can't initialize the m_objectiveLines[%d] for the single player loadscreen", i));
- GadgetStaticTextSetText(m_objectiveLines[i],UnicodeString::TheEmptyString);
-
- // translate the objective lines
- if(mission->m_missionObjectivesLabel[i].isNotEmpty())
- m_unicodeObjectiveLines[i] = TheGameText->fetch(mission->m_missionObjectivesLabel[i]);
- }
-
- for(i = 0; i < MAX_DISPLAYED_UNITS; ++i)
- {
- lineName.format("SinglePlayerLoadScreen.wnd:StaticTextCameoText%d",i);
- m_unitDesc[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( lineName ));
- DEBUG_ASSERTCRASH(m_unitDesc[i], ("Can't initialize the m_objectiveLines[%d] for the single player loadscreen", i));
- GadgetStaticTextSetText(m_unitDesc[i],TheGameText->fetch(mission->m_unitNames[i]));
- m_unitDesc[i]->winHide(TRUE);
- }
- m_location = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:StaticTextCameoText3" ));
- DEBUG_ASSERTCRASH(m_location, ("Can't initialize the m_objectiveWin for the single player loadscreen"));
- m_location->winHide(TRUE);
- GadgetStaticTextSetText(m_location, TheGameText->fetch(mission->m_locationNameLabel));
-
-
-
- m_currentObjectiveLine = 0;
- m_currentObjectiveWidthOffset = 0;
- m_currentObjectiveLineCharacter = 0;
- m_finishedObjectiveText = FALSE;
-/*
- m_cameoWindow1 = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:WindowCameo1" ));
- DEBUG_ASSERTCRASH(m_cameoWindow1, ("Can't initialize the m_cameoWindow1 for the single player loadscreen"));
- m_cameoWindow1->winHide(TRUE);
- m_cameoWindow1->winEnable(FALSE);
- m_cameoWindow1->winSetEnabledImage(0, mission->m_cameoImage[0]);
- m_cameoWindow1->winSetDisabledImage(0, mission->m_cameoDisabledImage[0]);
-
- m_cameoWindow2 = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:WindowCameo2" ));
- DEBUG_ASSERTCRASH(m_cameoWindow2, ("Can't initialize the m_cameoWindow2 for the single player loadscreen"));
- m_cameoWindow2->winHide(TRUE);
- m_cameoWindow2->winEnable(FALSE);
- m_cameoWindow2->winSetEnabledImage(0, mission->m_cameoImage[1]);
- m_cameoWindow2->winSetDisabledImage(0, mission->m_cameoDisabledImage[1]);
-
- m_cameoWindow3 = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:WindowCameo3" ));
- DEBUG_ASSERTCRASH(m_cameoWindow3, ("Can't initialize the m_cameoWindow3 for the single player loadscreen"));
- m_cameoWindow3->winHide(TRUE);
- m_cameoWindow3->winEnable(FALSE);
- m_cameoWindow3->winSetEnabledImage(0, mission->m_cameoImage[2]);
- m_cameoWindow3->winSetDisabledImage(0, mission->m_cameoDisabledImage[2]);
-
- m_headMovie = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:WindowHead" ));
- DEBUG_ASSERTCRASH(m_headMovie, ("Can't initialize the m_headMovie for the single player loadscreen"));
- m_headMovie->winHide(TRUE);
- m_cameoFrame = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:WindowHiliteCameo" ));
- DEBUG_ASSERTCRASH(m_cameoFrame, ("Can't initialize the m_cameoFrame for the single player loadscreen"));
- m_cameoFrame->winHide(TRUE);
- m_cameoText = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "SinglePlayerLoadScreen.wnd:StaticTextCameoText" ));
- DEBUG_ASSERTCRASH(m_cameoText, ("Can't initialize the m_cameoText for the single player loadscreen"));
-
-*/
- m_ambientLoop.setEventName("LoadScreenAmbient");
- // create the new stream
- m_videoStream = TheVideoPlayer->open( TheCampaignManager->getCurrentMission()->m_movieLabel );
- if ( m_videoStream == nullptr )
- {
- m_percent->winHide(TRUE);
- return;
- }
-
- // Create the new buffer
- m_videoBuffer = TheDisplay->createVideoBuffer();
- if ( m_videoBuffer == nullptr ||
- !m_videoBuffer->allocate( m_videoStream->width(),
- m_videoStream->height())
- )
- {
- delete m_videoBuffer;
- m_videoBuffer = nullptr;
-
- if ( m_videoStream )
- {
- m_videoStream->close();
- m_videoStream = nullptr;
- }
-
- return;
- }
-
- if(TheGameLODManager && TheGameLODManager->didMemPass())
- {
- // TheSuperHackers @bugfix Originally this movie render loop stopped rendering when the game window was inactive.
- // This either skipped the movie or caused decompression artifacts. Now the video just keeps playing until it done.
-
- Int progressUpdateCount = m_videoStream->frameCount() / FRAME_FUDGE_ADD;
- Int shiftedPercent = -FRAME_FUDGE_ADD + 1;
- while (m_videoStream->frameIndex() < m_videoStream->frameCount() - 1 )
- {
- // TheSuperHackers @feature User can now skip video by pressing ESC
- if (TheKeyboard)
- {
- TheKeyboard->UPDATE();
- KeyboardIO *io = TheKeyboard->findKey(KEY_ESC, KeyboardIO::STATUS_UNUSED);
- if (io && BitIsSet(io->state, KEY_STATE_DOWN))
- {
- io->setUsed();
- break;
- }
- }
-
- TheGameEngine->serviceWindowsOS();
-
- if(!m_videoStream->isFrameReady())
- {
- Sleep(1);
- continue;
- }
-
- m_videoStream->frameDecompress();
- m_videoStream->frameRender(m_videoBuffer);
- moveWindows( m_videoStream->frameIndex());
- m_videoStream->frameNext();
-
- if(m_videoBuffer)
- m_loadScreen->winGetInstanceData()->setVideoBuffer(m_videoBuffer);
- if(m_videoStream->frameIndex() % progressUpdateCount == 0)
- {
- shiftedPercent++;
- if(shiftedPercent >0)
- shiftedPercent = 0;
- Int percent = (shiftedPercent + FRAME_FUDGE_ADD)/1.3;
- UnicodeString per;
- per.format(L"%d%%",percent);
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
- GadgetProgressBarSetProgress(m_progressBar, percent);
- GadgetStaticTextSetText(m_percent, per);
-
- }
- TheWindowManager->update();
-
- //TheShell->update();
- //TheDisplay->update();
- // redraw all views, update the GUI
- TheDisplay->draw();
- }
- }
- else
- {
- // if we're min speced
- m_videoStream->frameGoto(m_videoStream->frameCount()); // zero based
- while(!m_videoStream->isFrameReady())
- Sleep(1);
- m_videoStream->frameDecompress();
- m_videoStream->frameRender(m_videoBuffer);
- if(m_videoBuffer)
- m_loadScreen->winGetInstanceData()->setVideoBuffer(m_videoBuffer);
-
- m_objectiveWin->winHide(FALSE);
- for(i = 0; i < MAX_DISPLAYED_UNITS; ++i)
- m_unitDesc[i]->winHide(FALSE);
- m_location->winHide(FALSE);
-
- // Audio was choppy so, I chopped it out!
- TheAudio->friend_forcePlayAudioEventRTS(&TheCampaignManager->getCurrentMission()->m_briefingVoice);
-
- for(Int i = 0; i < MAX_OBJECTIVE_LINES; ++i)
- {
- GadgetStaticTextSetText(m_objectiveLines[i], m_unicodeObjectiveLines[i]);
- }
-
- Int delay = mission->m_voiceLength * 1000;
- Int begin = timeGetTime();
- Int currTime = begin;
- Int fudgeFactor = 0;
- while(begin + delay > currTime )
- {
- fudgeFactor = 30 * ((currTime - begin)/ INT_TO_REAL(delay ));
- GadgetProgressBarSetProgress(m_progressBar, fudgeFactor);
-
- TheWindowManager->update();
- TheDisplay->draw();
- Sleep(100);
- currTime = timeGetTime();
- }
-
-
- TheWindowManager->update();
- TheDisplay->draw();
-
- }
- setFPMode();
- m_percent->winHide(TRUE);
- m_ambientLoopHandle = TheAudio->addAudioEvent(&m_ambientLoop);
-
-}
-
-void SinglePlayerLoadScreen::reset( void )
-{
- setLoadScreen(nullptr);
- m_progressBar = nullptr;
-}
-
-void SinglePlayerLoadScreen::update( Int percent )
-{
- percent = (percent + FRAME_FUDGE_ADD)/1.3;
- UnicodeString per;
- per.format(L"%d%%",percent);
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
- GadgetProgressBarSetProgress(m_progressBar, percent);
- GadgetStaticTextSetText(m_percent, per);
-
- // Do this last!
- LoadScreen::update( percent );
-}
-
-void SinglePlayerLoadScreen::setProgressRange( Int min, Int max )
-{
-
-}
-
-// ShellGameLoadScreen Class //////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-ShellGameLoadScreen::ShellGameLoadScreen( void )
-{
- m_progressBar = nullptr;
-}
-
-ShellGameLoadScreen::~ShellGameLoadScreen( void )
-{
-
- m_progressBar = nullptr;
-}
-
-void ShellGameLoadScreen::init( GameInfo *game )
-{
- static BOOL firstLoad = TRUE;
-
-
- // create the layout of the load screen
- m_loadScreen = TheWindowManager->winCreateFromScript( "Menus/ShellGameLoadScreen.wnd" );
- DEBUG_ASSERTCRASH(m_loadScreen, ("Can't initialize the ShellGame loadscreen"));
- m_loadScreen->winHide(FALSE);
- m_loadScreen->winBringToTop();
-
- // Store the pointer to the progress bar on the loadscreen
- m_progressBar = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "ShellGameLoadScreen.wnd:ProgressLoad" ));
- DEBUG_ASSERTCRASH(m_progressBar, ("Can't initialize the progressbar for the single player loadscreen"));
- GadgetProgressBarSetProgress(m_progressBar, 0 );
- m_progressBar->winHide(TRUE);
-
- if(m_loadScreen && firstLoad && TheGameLODManager && TheGameLODManager->didMemPass())
- {
- m_loadScreen->winSetEnabledImage(0, TheMappedImageCollection->findImageByName("TitleScreen"));
- TheWritableGlobalData->m_breakTheMovie = FALSE;
-
- GameWindow *win = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "ShellGameLoadScreen.wnd:StaticTextLegal" ));
- if(win)
- win->winHide(FALSE);
- firstLoad = FALSE;
- }
- m_progressBar->winHide(FALSE);
-}
-
-void ShellGameLoadScreen::reset( void )
-{
- setLoadScreen(nullptr);
- m_progressBar = nullptr;
-}
-
-void ShellGameLoadScreen::update( Int percent )
-{
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
- GadgetProgressBarSetProgress(m_progressBar, percent);
-
- // Do this last!
- LoadScreen::update( percent );
-}
-
-// MultiPlayerLoadScreen Class //////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-MultiPlayerLoadScreen::MultiPlayerLoadScreen( void )
-{
- m_mapPreview = nullptr;
-
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_buttonMapStartPosition[i] = nullptr;
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- m_playerLookup[i] = -1;
- }
-}
-
-MultiPlayerLoadScreen::~MultiPlayerLoadScreen( void )
-{
- if(m_mapPreview)
- {
- m_mapPreview->winSetUserData(nullptr);
- }
-
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- m_playerLookup[i] = -1;
- }
-
- TheAudio->removeAudioEvent( AHSV_StopTheMusicFade );
-// TheAudio->stopAudio( AudioAffect_Music );
-}
-
-void MultiPlayerLoadScreen::init( GameInfo *game )
-{
- // create the layout of the load screen
- m_loadScreen = TheWindowManager->winCreateFromScript( "Menus/MultiplayerLoadScreen.wnd" );
- DEBUG_ASSERTCRASH(m_loadScreen, ("Can't initialize the Multiplayer loadscreen"));
- m_loadScreen->winHide(FALSE);
- m_loadScreen->winBringToTop();
- m_mapPreview = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "MultiplayerLoadScreen.wnd:WinMapPreview"));
- GameSlot *lSlot = game->getSlot(game->getLocalSlotNum());
- const PlayerTemplate* pt;
- if (lSlot->getPlayerTemplate() >= 0)
- pt = ThePlayerTemplateStore->getNthPlayerTemplate(lSlot->getPlayerTemplate());
- else
- pt = ThePlayerTemplateStore->findPlayerTemplate( TheNameKeyGenerator->nameToKey("FactionObserver") );
- const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen());
-
-
- AsciiString musicName = pt->getLoadScreenMusic();
- if ( ! musicName.isEmpty() )
- {
- TheAudio->removeAudioEvent( AHSV_StopTheMusicFade );
- AudioEventRTS event( musicName );
- event.setShouldFade( TRUE );
-
- TheAudio->addAudioEvent( &event );
- TheAudio->update();//Since GameEngine::update() is suspended until after I am gone...
-
- }
-
-
- if(loadScreenImage)
- m_loadScreen->winSetEnabledImage(0, loadScreenImage);
- //DEBUG_ASSERTCRASH(TheNetwork, ("Where the Heck is the Network!!!!"));
- //DEBUG_LOG(("NumPlayers %d", TheNetwork->getNumPlayers()));
-
- GameWindow *teamWin[MAX_SLOTS];
- Int i = 0;
- for (; i < MAX_SLOTS; ++i)
- {
- teamWin[i] = nullptr;
- }
-
- Int netSlot = 0;
- // Loop through and make the loadscreen look all good.
- for (i = 0; i < MAX_SLOTS; ++i)
- {
- // Load the Progress Bar
- AsciiString winName;
- winName.format( "MultiplayerLoadScreen.wnd:ProgressLoad%d",i);
- m_progressBars[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_progressBars[i], ("Can't initialize the progressbars for the Multiplayer loadscreen"));
- // set the progressbar to zero
- GadgetProgressBarSetProgress(m_progressBars[i], 0 );
-
- // Load MapStart Positions
- winName.format( "MultiplayerLoadScreen.wnd:ButtonMapStartPosition%d",i);
- m_buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_buttonMapStartPosition[i], ("Can't initialize the MapStart Positions for the MultiplayerLoadScreen loadscreen"));
-
-
- // Load the Player's name
- winName.format( "MultiplayerLoadScreen.wnd:StaticTextPlayer%d",i);
- m_playerNames[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerNames[i], ("Can't initialize the Names for the Multiplayer loadscreen"));
-
- // Load the Player's Side
- winName.format( "MultiplayerLoadScreen.wnd:StaticTextSide%d",i);
- m_playerSide[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerSide[i], ("Can't initialize the Sides for the Multiplayer loadscreen"));
-
- winName.format( "MultiplayerLoadScreen.wnd:StaticTextTeam%d",i);
- teamWin[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
-
- // get the slot man!
- GameSlot *slot = game->getSlot(i);
- if (!slot || !slot->isOccupied())
- continue;
- Color houseColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor();
- GadgetProgressBarSetEnabledBarColor(m_progressBars[netSlot],houseColor );
-
- UnicodeString name = slot->getName();
- GadgetStaticTextSetText(m_playerNames[netSlot], name );
- m_playerNames[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor());
-
- GadgetStaticTextSetText(m_playerSide[netSlot], slot->getApparentPlayerTemplateDisplayName() );
- m_playerSide[netSlot]->winSetEnabledTextColors(houseColor, m_playerSide[netSlot]->winGetEnabledTextBorderColor());
-
- if (slot->isAI() && m_progressBars[netSlot])
- m_progressBars[netSlot]->winHide(TRUE);
-
- if (teamWin[netSlot])
- {
- AsciiString teamStr;
- teamStr.format("Team:%d", slot->getTeamNumber() + 1);
- GadgetStaticTextSetText(teamWin[netSlot], TheGameText->fetch(teamStr));
- teamWin[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor());
- }
-
- m_playerLookup[i] = netSlot; // save our mapping so we can update progress correctly
-
- netSlot++;
- }
-
- for(i = netSlot; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i]->winHide(TRUE);
- m_playerNames[i]->winHide(TRUE);
- m_playerSide[i]->winHide(TRUE);
- teamWin[i]->winHide(TRUE);
- }
-
- if(m_mapPreview)
- {
- const MapMetaData *mmd = TheMapCache->findMap(game->getMap());
- Image *image = getMapPreviewImage(game->getMap());
- m_mapPreview->winSetUserData((void *)mmd);
-
- positionStartSpots( game, m_buttonMapStartPosition, m_mapPreview);
- updateMapStartSpots( game, m_buttonMapStartPosition, TRUE );
- //positionAdditionalImages((MapMetaData *)mmd, m_mapPreview, TRUE);
- if(image)
- {
- m_mapPreview->winSetStatus(WIN_STATUS_IMAGE);
- m_mapPreview->winSetEnabledImage(0, image);
- }
- else
- {
- m_mapPreview->winClearStatus(WIN_STATUS_IMAGE);
- }
- }
-
-
- TheGameLogic->initTimeOutValues();
-}
-
-void MultiPlayerLoadScreen::reset( void )
-{
- setLoadScreen(nullptr);
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- }
-}
-
-void MultiPlayerLoadScreen::update( Int percent )
-{
- if (TheNetwork)
- {
- if(percent <= 100)
- TheNetwork->updateLoadProgress( percent );
- TheNetwork->liteupdate();
- }
- else
- {
- if (percent <= 100)
- TheGameLogic->processProgress( TheGameInfo->getLocalSlotNum(), percent );
- }
-
- //GadgetProgressBarSetProgress(m_progressBars[TheNetwork->getLocalPlayerID()], percent );
-
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
-
- // Do this last!
- LoadScreen::update( percent );
-}
-
-void MultiPlayerLoadScreen::processProgress(Int playerId, Int percentage)
-{
-
- if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1)
- {
- DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d", percentage, playerId));
- return;
- }
- //DEBUG_LOG(("Percentage %d was passed in for Player %d (in loadscreen position %d)", percentage, playerId, m_playerLookup[playerId]));
- if(m_progressBars[m_playerLookup[playerId]])
- GadgetProgressBarSetProgress(m_progressBars[m_playerLookup[playerId]], percentage );
-}
-
-// GameSpyLoadScreen Class //////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-GameSpyLoadScreen::GameSpyLoadScreen( void )
-{
-
- m_mapPreview = nullptr;
-
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
-
- m_buttonMapStartPosition[i] = nullptr;
- m_playerRank[i] = nullptr;
-
- m_playerOfficerMedal[i] = nullptr;
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- m_playerLookup[i] = -1;
- m_playerFavoriteFactions[i]= nullptr;
- m_playerTotalDisconnects[i]= nullptr;
- m_playerWin[i]= nullptr;
- m_playerWinLosses[i]= nullptr;
- }
-}
-
-GameSpyLoadScreen::~GameSpyLoadScreen( void )
-{
- if(m_mapPreview)
- {
- m_mapPreview->winSetUserData(nullptr);
- }
-
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- m_playerLookup[i] = -1;
- m_playerFavoriteFactions[i]= nullptr;
- m_playerTotalDisconnects[i]= nullptr;
- m_playerWin[i]= nullptr;
- m_playerWinLosses[i]= nullptr;
- }
-}
-
-extern Int GetAdditionalDisconnectsFromUserFile(Int playerID);
-
-void GameSpyLoadScreen::init( GameInfo *game )
-{
- // create the layout of the load screen
- m_loadScreen = TheWindowManager->winCreateFromScript( "Menus/GameSpyLoadScreen.wnd" );
- DEBUG_ASSERTCRASH(m_loadScreen, ("Can't initialize the Multiplayer loadscreen"));
- m_loadScreen->winHide(FALSE);
- m_loadScreen->winBringToTop();
- m_mapPreview = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "GameSpyLoadScreen.wnd:WinMapPreview"));
- DEBUG_ASSERTCRASH(TheNetwork, ("Where the Heck is the Network!!!!"));
- DEBUG_LOG(("NumPlayers %d", TheNetwork->getNumPlayers()));
-GameSlot *lSlot = game->getSlot(game->getLocalSlotNum());
- const PlayerTemplate* pt;
- if (lSlot->getPlayerTemplate() >= 0)
- pt = ThePlayerTemplateStore->getNthPlayerTemplate(lSlot->getPlayerTemplate());
- else
- pt = ThePlayerTemplateStore->findPlayerTemplate( TheNameKeyGenerator->nameToKey("FactionObserver") );
- const Image *loadScreenImage = TheMappedImageCollection->findImageByName(pt->getLoadScreen());
- if(loadScreenImage)
- m_loadScreen->winSetEnabledImage(0, loadScreenImage);
-
- GameWindow *teamWin[MAX_SLOTS];
- Int i = 0;
- for (; i < MAX_SLOTS; ++i)
- {
- teamWin[i] = nullptr;
- }
-
- Int netSlot = 0;
- // Loop through and make the loadscreen look all good.
- for (i = 0; i < MAX_SLOTS; ++i)
- {
- // Load the Progress Bar
- AsciiString winName;
- winName.format( "GameSpyLoadScreen.wnd:ProgressLoad%d",i);
- m_progressBars[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_progressBars[i], ("Can't initialize the progressbars for the GameSpyLoadScreen loadscreen"));
- // set the progressbar to zero
- GadgetProgressBarSetProgress(m_progressBars[i], 0 );
-
- // Load the Player's name
- winName.format( "GameSpyLoadScreen.wnd:StaticTextPlayer%d",i);
- m_playerNames[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerNames[i], ("Can't initialize the Names for the GameSpyLoadScreen loadscreen"));
-
- // Load MapStart Positions
- winName.format( "GameSpyLoadScreen.wnd:ButtonMapStartPosition%d",i);
- m_buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_buttonMapStartPosition[i], ("Can't initialize the MapStart Positions for the GameSpyLoadScreen loadscreen"));
-
-
- // Load the Player's Side
- winName.format( "GameSpyLoadScreen.wnd:StaticTextSide%d",i);
- m_playerSide[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerSide[i], ("Can't initialize the Sides for the GameSpyLoadScreen loadscreen"));
-
- // Load the Player's window
- winName.format( "GameSpyLoadScreen.wnd:WinPlayer%d",i);
- m_playerWin[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerWin[i], ("Can't initialize the WinPlayer for the GameSpyLoadScreen loadscreen"));
-
- // Load the Player's m_playerTotalDisconnects
- winName.format( "GameSpyLoadScreen.wnd:StaticTextTotalDisconnects%d",i);
- m_playerTotalDisconnects[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerTotalDisconnects[i], ("Can't initialize the m_playerTotalDisconnects for the GameSpyLoadScreen loadscreen"));
-
-// // Load the Player's m_playerFavoriteFactions
-// winName.format( "GameSpyLoadScreen.wnd:StaticTextFavoriteFaction%d",i);
-// m_playerFavoriteFactions[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
-// DEBUG_ASSERTCRASH(m_playerFavoriteFactions[i], ("Can't initialize the StaticTextFavoriteFaction for the GameSpyLoadScreen loadscreen"));
-
- // Load the Player's m_playerWinLosses
- winName.format( "GameSpyLoadScreen.wnd:StaticTextWinLoss%d",i);
- m_playerWinLosses[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerWinLosses[i], ("Can't initialize the m_playerWinLosses for the GameSpyLoadScreen loadscreen"));
-
- // Load the Player's m_playerWinLosses
- winName.format( "GameSpyLoadScreen.wnd:WinRank%d",i);
- m_playerRank[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerRank[i], ("Can't initialize the m_playerRank for the GameSpyLoadScreen loadscreen"));
-
- // Load the Player's m_playerOfficerMedal
- winName.format( "GameSpyLoadScreen.wnd:WinOfficer%d",i);
- m_playerOfficerMedal[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerOfficerMedal[i], ("Can't initialize the m_playerOfficerMedal for the GameSpyLoadScreen loadscreen"));
-
- winName.format( "MultiplayerLoadScreen.wnd:StaticTextTeam%d",i);
- teamWin[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
-
- // get the slot man!
- GameSpyGameSlot *slot = (GameSpyGameSlot *)game->getSlot(i);
- if (!slot || !slot->isOccupied())
- continue;
- Color houseColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor();
- GadgetProgressBarSetEnabledBarColor(m_progressBars[netSlot],houseColor );
-
- UnicodeString name = slot->getName();
- GadgetStaticTextSetText(m_playerNames[netSlot], name );
- m_playerNames[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor());
-
- // Get the stats for the player
- PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(slot->getProfileID());
- DEBUG_LOG(("LoadScreen - populating info for %ls(%d) - stats returned id %d",
- slot->getName().str(), slot->getProfileID(), stats.id));
-
- Bool isPreorder = TheGameSpyInfo->didPlayerPreorder(stats.id);
- Int rankPoints = CalculateRank(stats);
- Int favSide = GetFavoriteSide(stats);
- const Image *preorderImg = TheMappedImageCollection->findImageByName("OfficersClubsmall");
- if (!isPreorder)
- preorderImg = nullptr;
- const Image *rankImg = LookupSmallRankImage(favSide, rankPoints);
- m_playerOfficerMedal[i]->winSetEnabledImage(0, preorderImg);
- m_playerRank[i]->winSetEnabledImage(0, rankImg);
-
- UnicodeString formatString;
-
- // pop wins and losses
- Int numLosses = 0;
- PerGeneralMap::iterator it;
- for(it = stats.losses.begin(); it != stats.losses.end(); ++it)
- {
- numLosses += it->second;
- }
- Int numWins = 0;
- for(it =stats.wins.begin(); it != stats.wins.end(); ++it)
- {
- numWins += it->second;
- }
- formatString.format(L"%d/%d", numWins, numLosses);
- GadgetStaticTextSetText(m_playerWinLosses[netSlot], formatString);
- m_playerWinLosses[netSlot]->winSetEnabledTextColors(houseColor, m_playerWinLosses[netSlot]->winGetEnabledTextBorderColor());
- // favoriteFaction
- Int numGames = 0;
- Int favorite = 0;
- for(it =stats.games.begin(); it != stats.games.end(); ++it)
- {
- if(it->second >= numGames)
- {
- numGames = it->second;
- favorite = it->first;
- }
- }
-// if(numGames == 0)
-// GadgetStaticTextSetText(m_playerFavoriteFactions[netSlot], TheGameText->fetch("GUI:None"));
-// else if( stats.gamesAsRandom > numGames )
-// GadgetStaticTextSetText(m_playerFavoriteFactions[netSlot], TheGameText->fetch("GUI:Random"));
-// else
-// {
-// const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(favorite);
-// if (fac)
-// {
-// AsciiString side;
-// side.format("SIDE:%s", fac->getSide().str());
-//
-// GadgetStaticTextSetText(m_playerFavoriteFactions[netSlot], TheGameText->fetch(side));
-// }
-// }
-// m_playerFavoriteFactions[netSlot]->winSetEnabledTextColors(houseColor, m_playerFavoriteFactions[netSlot]->winGetEnabledTextBorderColor());
- // disconnects
- numGames = 0;
- for(it =stats.discons.begin(); it != stats.discons.end(); ++it)
- {
- numGames += it->second;
- }
- for(it =stats.desyncs.begin(); it != stats.desyncs.end(); ++it)
- {
- numGames += it->second;
- }
- numGames += GetAdditionalDisconnectsFromUserFile(stats.id);
-
- formatString.format(L"%d", numGames);
- GadgetStaticTextSetText(m_playerTotalDisconnects[netSlot], formatString);
- m_playerTotalDisconnects[netSlot]->winSetEnabledTextColors(houseColor, m_playerTotalDisconnects[netSlot]->winGetEnabledTextBorderColor());
- GadgetStaticTextSetText(m_playerSide[netSlot], slot->getApparentPlayerTemplateDisplayName() );
- m_playerSide[netSlot]->winSetEnabledTextColors(houseColor, m_playerSide[netSlot]->winGetEnabledTextBorderColor());
-
- if (slot->isAI())
- {
- if (m_progressBars[netSlot])
- m_progressBars[netSlot]->winHide(TRUE);
- if (m_playerTotalDisconnects[netSlot])
- m_playerTotalDisconnects[netSlot]->winHide(TRUE);
-// if (m_playerFavoriteFactions[netSlot])
-// m_playerFavoriteFactions[netSlot]->winHide(TRUE);
- if (m_playerWinLosses[netSlot])
- m_playerWinLosses[netSlot]->winHide(TRUE);
- if (m_playerRank[netSlot])
- m_playerRank[netSlot]->winHide(TRUE);
- if (m_playerOfficerMedal[netSlot])
- m_playerOfficerMedal[netSlot]->winHide(TRUE);
- }
-
- if (teamWin[netSlot])
- {
- AsciiString teamStr;
- teamStr.format("Team:%d", slot->getTeamNumber() + 1);
- if (slot->isAI() && slot->getTeamNumber() == -1)
- teamStr = "Team:AI";
- GadgetStaticTextSetText(teamWin[netSlot], TheGameText->fetch(teamStr));
- teamWin[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor());
- }
-
- m_playerLookup[i] = netSlot; // save our mapping so we can update progress correctly
-
- netSlot++;
- }
-
- for(i = netSlot; i < MAX_SLOTS; ++i)
- {
- m_playerWin[i]->winHide(TRUE);
- //m_playerNames[i]->winHide(TRUE);
- //m_playerSide[i]->winHide(TRUE);
- }
-
- if(m_mapPreview)
- {
- const MapMetaData *mmd = TheMapCache->findMap(game->getMap());
- Image *image = getMapPreviewImage(game->getMap());
- m_mapPreview->winSetUserData((void *)mmd);
-
- positionStartSpots( game, m_buttonMapStartPosition, m_mapPreview);
- updateMapStartSpots( game, m_buttonMapStartPosition, TRUE );
- //positionAdditionalImages((MapMetaData *)mmd, m_mapPreview, TRUE);
- if(image)
- {
- m_mapPreview->winSetStatus(WIN_STATUS_IMAGE);
- m_mapPreview->winSetEnabledImage(0, image);
- }
- else
- {
- m_mapPreview->winClearStatus(WIN_STATUS_IMAGE);
- }
- }
-
- TheGameLogic->initTimeOutValues();
-}
-
-void GameSpyLoadScreen::reset( void )
-{
- setLoadScreen(nullptr);
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_playerSide[i]= nullptr;
- }
-}
-
-void GameSpyLoadScreen::update( Int percent )
-{
- if(percent <= 100)
- TheNetwork->updateLoadProgress( percent );
- TheNetwork->liteupdate();
-
- //GadgetProgressBarSetProgress(m_progressBars[TheNetwork->getLocalPlayerID()], percent );
-
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
-
- // Do this last!
- LoadScreen::update( percent );
-}
-
-void GameSpyLoadScreen::processProgress(Int playerId, Int percentage)
-{
-
- if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1)
- {
- DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d", percentage, playerId));
- return;
- }
- //DEBUG_LOG(("Percentage %d was passed in for Player %d (in loadscreen position %d)", percentage, playerId, m_playerLookup[playerId]));
- if(m_progressBars[m_playerLookup[playerId]])
- GadgetProgressBarSetProgress(m_progressBars[m_playerLookup[playerId]], percentage );
-}
-
-// MapTransferLoadScreen Class //////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-MapTransferLoadScreen::MapTransferLoadScreen( void )
-{
- m_oldTimeout = 0;
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_progressText[i]= nullptr;
- m_playerLookup[i] = -1;
- m_oldProgress[i] = -1;
- }
- m_fileNameText = nullptr;
- m_timeoutText = nullptr;
-}
-
-MapTransferLoadScreen::~MapTransferLoadScreen( void )
-{
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_progressText[i]= nullptr;
- m_playerLookup[i] = -1;
- m_oldProgress[i] = -1;
- }
- m_fileNameText = nullptr;
- m_timeoutText = nullptr;
-}
-
-void MapTransferLoadScreen::init( GameInfo *game )
-{
- // create the layout of the load screen
- m_loadScreen = TheWindowManager->winCreateFromScript( "Menus/MapTransferScreen.wnd" );
- DEBUG_ASSERTCRASH(m_loadScreen, ("Can't initialize the map transfer loadscreen"));
- if (!m_loadScreen)
- return;
-
- m_loadScreen->winHide(FALSE);
- m_loadScreen->winBringToTop();
-
- DEBUG_ASSERTCRASH(TheNetwork, ("Where the Heck is the Network?!!!!"));
- DEBUG_LOG(("NumPlayers %d", TheNetwork->getNumPlayers()));
-
- AsciiString winName;
- Int i;
-
- // Load the Filename Text
- m_fileNameText = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "MapTransferScreen.wnd:StaticTextCurrentFile" ));
- DEBUG_ASSERTCRASH(m_fileNameText, ("Can't initialize the filename for the map transfer loadscreen"));
-
- // Load the Timeout Text
- m_timeoutText = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( "MapTransferScreen.wnd:StaticTextTimeout" ));
- DEBUG_ASSERTCRASH(m_timeoutText, ("Can't initialize the timeout for the map transfer loadscreen"));
-
- Int netSlot = 0;
- // Loop through and make the loadscreen look all good.
- for (i = 0; i < MAX_SLOTS; ++i)
- {
- // Load the Progress Bar
- winName.format( "MapTransferScreen.wnd:ProgressLoad%d",i);
- m_progressBars[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_progressBars[i], ("Can't initialize the progressbars for the map transfer loadscreen"));
- // set the progressbar to zero
- GadgetProgressBarSetProgress(m_progressBars[i], 0 );
-
- // Load the Player's name
- winName.format( "MapTransferScreen.wnd:StaticTextPlayer%d",i);
- m_playerNames[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_playerNames[i], ("Can't initialize the Names for the map transfer loadscreen"));
-
- // Load the Progress Text
- winName.format( "MapTransferScreen.wnd:StaticTextProgress%d",i);
- m_progressText[i] = TheWindowManager->winGetWindowFromId( m_loadScreen,TheNameKeyGenerator->nameToKey( winName ));
- DEBUG_ASSERTCRASH(m_progressText[i], ("Can't initialize the progress text for the map transfer loadscreen"));
-
- // get the slot man!
- GameSlot *slot = game->getSlot(i);
- if (!slot || !slot->isHuman())
- continue;
- Color houseColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor();
- GadgetProgressBarSetEnabledBarColor(m_progressBars[netSlot], houseColor );
-
- UnicodeString name = slot->getName();
- GadgetStaticTextSetText(m_playerNames[netSlot], name );
- m_playerNames[netSlot]->winSetEnabledTextColors(houseColor, m_playerNames[netSlot]->winGetEnabledTextBorderColor());
-
- GadgetStaticTextSetText(m_progressText[netSlot], UnicodeString::TheEmptyString );
- m_progressText[netSlot]->winSetEnabledTextColors(houseColor, m_progressText[netSlot]->winGetEnabledTextBorderColor());
-
- if ((i == 0 || (TheGameInfo->getConstSlot(i)->isHuman() && TheGameInfo->getConstSlot(i)->hasMap())) && m_progressBars[netSlot])
- m_progressBars[netSlot]->winHide(TRUE);
-
- m_playerLookup[i] = netSlot; // save our mapping so we can update progress correctly
-
- netSlot++;
- }
-
- for(i = netSlot; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i]->winHide(TRUE);
- m_playerNames[i]->winHide(TRUE);
- m_progressText[i]->winHide(TRUE);
- }
-}
-
-void MapTransferLoadScreen::reset( void )
-{
- setLoadScreen(nullptr);
- for(Int i = 0; i < MAX_SLOTS; ++i)
- {
- m_progressBars[i] = nullptr;
- m_playerNames[i] = nullptr;
- m_progressText[i]= nullptr;
- m_playerLookup[i] = -1;
- m_oldProgress[i] = -1;
- }
- m_fileNameText = nullptr;
- m_timeoutText = nullptr;
-}
-
-void MapTransferLoadScreen::update( Int percent )
-{
- if (TheNetwork)
- {
- TheNetwork->liteupdate();
- }
-
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString);
-
- // Do this last!
- LoadScreen::update( percent );
-}
-
-void MapTransferLoadScreen::processProgress(Int playerId, Int percentage, AsciiString stateStr)
-{
-
- if( percentage < 0 || percentage > 100 || playerId >= MAX_SLOTS || playerId < 0 || m_playerLookup[playerId] == -1)
- {
- DEBUG_ASSERTCRASH(FALSE, ("Percentage %d was passed in for Player %d", percentage, playerId));
- return;
- }
-
- if (m_oldProgress[playerId] == percentage)
- return;
- m_oldProgress[playerId] = percentage;
-
- Int translatedSlot = m_playerLookup[playerId];
- if(m_progressBars[translatedSlot])
- GadgetProgressBarSetProgress(m_progressBars[translatedSlot], percentage );
- if (m_progressText[translatedSlot])
- GadgetStaticTextSetText(m_progressText[translatedSlot], TheGameText->fetch(stateStr));
-}
-
-void MapTransferLoadScreen::processTimeout(Int secondsLeft)
-{
- if (m_oldTimeout == secondsLeft)
- return;
- m_oldTimeout = secondsLeft;
-
- if (m_timeoutText)
- {
- UnicodeString txt;
- txt.format(TheGameText->fetch("MapTransfer:Timeout"), (secondsLeft/60), (secondsLeft%60));
- GadgetStaticTextSetText(m_timeoutText, txt);
- }
-}
-
-void MapTransferLoadScreen::setCurrentFilename(AsciiString filename)
-{
- if (m_fileNameText)
- {
- UnicodeString txt;
- txt.translate(TheGameState->getMapLeafName(filename));
- txt.format(TheGameText->fetch("MapTransfer:CurrentFile"), txt.str());
- GadgetStaticTextSetText(m_fileNameText, txt);
- }
-}
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp
deleted file mode 100644
index 347addb6c90..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp
+++ /dev/null
@@ -1,1544 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: ProcessAnimateWindow.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Mar 2002
-//
-// Filename: ProcessAnimateWindow.cpp
-//
-// author: Chris Huybregts
-//
-// purpose: Holds all the process modules for the Animate Window Class
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/ProcessAnimateWindow.h"
-#include "GameClient/AnimateWindowManager.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/Display.h"
-//-----------------------------------------------------------------------------
-// DEFINES ////////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-static Real getDisplayWidthScaler()
-{
- return static_cast(TheDisplay->getWidth()) / DEFAULT_DISPLAY_WIDTH;
-}
-
-static Real getDisplayHeightScaler()
-{
- return static_cast(TheDisplay->getHeight()) / DEFAULT_DISPLAY_HEIGHT;
-}
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromRight PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromRight::ProcessAnimateWindowSlideFromRight( void )
-{
- m_maxVel.x = 0.0f; // top speed windows travel in x and y
- m_maxVel.y = 0.0f;
- m_slowDownThreshold = 0; // when windows get this close to their resting positions they start to slow down
-
- m_slowDownRatio = 0.67f; // how fast the windows slow down (smaller slows quicker)
- m_speedUpRatio = 2.0f - m_slowDownRatio; // how fast the windows speed up
-}
-
-//-----------------------------------------------------------------------------
-ProcessAnimateWindowSlideFromRight::~ProcessAnimateWindowSlideFromRight( void ) { }
-
-//-----------------------------------------------------------------------------
-void ProcessAnimateWindowSlideFromRight::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x *= -1;
- vel.y *= -1;
- animWin->setVel( vel );
- animWin->setFinished( FALSE );
-
-}
-
-//-----------------------------------------------------------------------------
-void ProcessAnimateWindowSlideFromRight::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- animWin->setFinished( FALSE );
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Right of the screen
- Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- startPos.x = curPos.x = restPos.x + travelDistance;
- startPos.y = curPos.y = restPos.y;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- // TheSuperHackers @bugfix tophroxx 31/01/2026 Scale movement by display size so that it looks
- // consistent regardless of the display resolution.
- const Real widthScaler = getDisplayWidthScaler();
- m_maxVel.x = -40 * widthScaler;
- m_slowDownThreshold = 80 * widthScaler;
-
- //Now initialize the velocities
- vel.x = m_maxVel.x;
- vel.y = 0.0f;
-
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-
-//-----------------------------------------------------------------------------
-Bool ProcessAnimateWindowSlideFromRight::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
- curPos.x += (Int)vel.x;
-
- if(curPos.x < endPos.x)
- {
- curPos.x = endPos.x;
- animWin->setFinished( TRUE );
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- if( curPos.x - endPos.x <= m_slowDownThreshold )
- {
- vel.x *= m_slowDownRatio;
- }
- if( vel.x >= -1.0f)
- vel.x = -1.0f;
- animWin->setVel(vel);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromRight::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D startPos = animWin->getStartPos();
- Coord2D vel = animWin->getVel();
- curPos.x += (Int)vel.x;
-
- if(curPos.x > startPos.x)
- {
- curPos.x = startPos.x;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
-
- ICoord2D endPos = animWin->getEndPos();
- if( curPos.x - endPos.x <= m_slowDownThreshold )
- {
- vel.x *= m_speedUpRatio;
- }
- else
- {
- vel.x = -m_maxVel.x;
- }
- if( vel.x > -m_maxVel.x)
- vel.x = -m_maxVel.x;
- animWin->setVel(vel);
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromLeft PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromLeft::ProcessAnimateWindowSlideFromLeft( void )
-{
- m_maxVel.x = 0.0f; // top speed windows travel in x and y
- m_maxVel.y = 0.0f;
- m_slowDownThreshold = 0; // when windows get this close to their resting positions they start to slow down
-
- m_slowDownRatio = 0.67f; // how fast the windows slow down (smaller slows quicker)
- m_speedUpRatio = 2.0f - m_slowDownRatio; // how fast the windows speed up
-}
-
-ProcessAnimateWindowSlideFromLeft::~ProcessAnimateWindowSlideFromLeft( void ) { }
-
-void ProcessAnimateWindowSlideFromLeft::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x *= -1;
- vel.y *= -1;
- animWin->setVel( vel );
-
-}
-
-void ProcessAnimateWindowSlideFromLeft::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Left of the screen
- Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- startPos.x = curPos.x = restPos.x - travelDistance;
- startPos.y = curPos.y = restPos.y;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- // TheSuperHackers @bugfix tophroxx 31/01/2026 Scale movement by display size so that it looks
- // consistent regardless of the display resolution.
- const Real widthScaler = getDisplayWidthScaler();
- m_maxVel.x = 40 * widthScaler;
- m_slowDownThreshold = 80 * widthScaler;
-
- //Now initialize the velocities
- vel = m_maxVel;
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-Bool ProcessAnimateWindowSlideFromLeft::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
- curPos.x += (Int)vel.x;
-
- if(curPos.x > endPos.x)
- {
- curPos.x = endPos.x;
- animWin->setFinished( TRUE );
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- if( endPos.x - curPos.x <= m_slowDownThreshold )
- {
- vel.x *= m_slowDownRatio;
- }
- if( vel.x < 1.0f)
- vel.x = 1.0f;
- animWin->setVel(vel);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromLeft::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D startPos = animWin->getStartPos();
- Coord2D vel = animWin->getVel();
- curPos.x += (Int)vel.x;
-
- if(curPos.x < startPos.x)
- {
- curPos.x = startPos.x;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
-
- ICoord2D endPos = animWin->getEndPos();
- if( endPos.x - curPos.x <= m_slowDownThreshold )
- {
- vel.x *= m_speedUpRatio;
- }
- else
- {
- vel.x = -m_maxVel.x;
- }
- if( vel.x < -m_maxVel.x)
- vel.x = -m_maxVel.x;
- animWin->setVel(vel);
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromTop PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromTop::ProcessAnimateWindowSlideFromTop( void )
-{
- m_maxVel.x = 0.0f; // top speed windows travel in x and y
- m_maxVel.y = 0.0f;
- m_slowDownThreshold = 0; // when windows get this close to their resting positions they start to slow down
-
- m_slowDownRatio = 0.67f; // how fast the windows slow down (smaller slows quicker)
- m_speedUpRatio = 2.0f - m_slowDownRatio; // how fast the windows speed up
-}
-
-ProcessAnimateWindowSlideFromTop::~ProcessAnimateWindowSlideFromTop( void ) { }
-
-void ProcessAnimateWindowSlideFromTop::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x *= -1;
- vel.y *= -1;
- animWin->setVel( vel );
-
-}
-
-void ProcessAnimateWindowSlideFromTop::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Top of the screen
- Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- startPos.x = curPos.x = restPos.x ;
- startPos.y = curPos.y = restPos.y - travelDistance;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- // TheSuperHackers @bugfix tophroxx 31/01/2026 Scale movement by display size so that it looks
- // consistent regardless of the display resolution.
- const Real heightScaler = getDisplayHeightScaler();
- m_maxVel.y = 40 * heightScaler;
- m_slowDownThreshold = 80 * heightScaler;
-
- //Now initialize the velocities
- vel = m_maxVel;
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-Bool ProcessAnimateWindowSlideFromTop::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
- curPos.y += (Int)vel.y;
-
- if(curPos.y > endPos.y)
- {
- curPos.y = endPos.y;
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setFinished( TRUE );
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- if( endPos.y - curPos.y <= m_slowDownThreshold )
- {
- vel.y *= m_slowDownRatio;
- }
- if( vel.y < 1.0f)
- vel.y = 1.0f;
- animWin->setVel(vel);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromTop::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D startPos = animWin->getStartPos();
- Coord2D vel = animWin->getVel();
- curPos.y += (Int)vel.y;
-
- if(curPos.y < startPos.y)
- {
- curPos.y = startPos.y;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
-
- ICoord2D endPos = animWin->getEndPos();
- if( endPos.y - curPos.y <= m_slowDownThreshold )
- {
- vel.y *= m_speedUpRatio;
- }
- else
- {
- vel.y = -m_maxVel.y;
- }
- if( vel.y < -m_maxVel.y)
- vel.y = -m_maxVel.y;
- animWin->setVel(vel);
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromBottom PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromBottom::ProcessAnimateWindowSlideFromBottom( void )
-{
- m_maxVel.x = 0.0f; // top speed windows travel in x and y
- m_maxVel.y = 0.0f;
- m_slowDownThreshold = 0; // when windows get this close to their resting positions they start to slow down
-
- m_slowDownRatio = 0.67f; // how fast the windows slow down (smaller slows quicker)
- m_speedUpRatio = 2.0f - m_slowDownRatio; // how fast the windows speed up
-}
-
-ProcessAnimateWindowSlideFromBottom::~ProcessAnimateWindowSlideFromBottom( void ) { }
-
-void ProcessAnimateWindowSlideFromBottom::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x *= -1;
- vel.y *= -1;
- animWin->setVel( vel );
-
-}
-
-
-void ProcessAnimateWindowSlideFromBottom::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Bottom of the screen
- Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- startPos.x = curPos.x = restPos.x;
- startPos.y = curPos.y = restPos.y + travelDistance;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- // TheSuperHackers @bugfix tophroxx 31/01/2026 Scale movement by display size so that it looks
- // consistent regardless of the display resolution.
- const Real heightScaler = getDisplayHeightScaler();
- m_maxVel.y = -40 * heightScaler;
- m_slowDownThreshold = 80 * heightScaler;
-
- //Now initialize the velocities
- vel = m_maxVel;
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-Bool ProcessAnimateWindowSlideFromBottom::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
- curPos.y += (Int)vel.y;
-
- if(curPos.y < endPos.y)
- {
- curPos.y = endPos.y;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- if( curPos.y - endPos.y <= m_slowDownThreshold )
- {
- vel.y *= m_slowDownRatio;
- }
- if( vel.y >= -1.0f)
- vel.y = -1.0f;
- animWin->setVel(vel);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromBottom::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D startPos = animWin->getStartPos();
- Coord2D vel = animWin->getVel();
- curPos.y += (Int)vel.y;
-
- if(curPos.y > startPos.y)
- {
- curPos.y = startPos.y;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
-
- ICoord2D endPos = animWin->getEndPos();
- if( curPos.y - endPos.y <= m_slowDownThreshold )
- {
- vel.y *= m_speedUpRatio;
- }
- else
- {
- vel.y = -m_maxVel.y;
- }
- if( vel.y > -m_maxVel.y)
- vel.y = -m_maxVel.y;
- animWin->setVel(vel);
- return FALSE;
-}
-
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromBottomTimed PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromBottomTimed::ProcessAnimateWindowSlideFromBottomTimed( void )
-{
- m_maxDuration = 1000;
-}
-
-ProcessAnimateWindowSlideFromBottomTimed::~ProcessAnimateWindowSlideFromBottomTimed( void ) { }
-
-void ProcessAnimateWindowSlideFromBottomTimed::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- restPos = animWin->getRestPos();
- startPos.x = restPos.x;
- curPos.y = startPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Bottom of the screen
- Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- endPos.x = curPos.x = restPos.x;
- endPos.y = restPos.y + travelDistance;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- UnsignedInt now = timeGetTime();
-
- DEBUG_LOG(("initReverseAnimateWindow at %d (%d->%d)", now, now, now + m_maxDuration));
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, now, now + m_maxDuration);
-}
-
-
-void ProcessAnimateWindowSlideFromBottomTimed::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Bottom of the screen
- Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- startPos.x = curPos.x = restPos.x;
- startPos.y = curPos.y = restPos.y + travelDistance;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- UnsignedInt now = timeGetTime();
- UnsignedInt delay = animWin->getDelay();
-
- DEBUG_LOG(("initAnimateWindow at %d (%d->%d)", now, now + delay, now + m_maxDuration + delay));
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, now + delay, now + m_maxDuration + delay);
-}
-
-Bool ProcessAnimateWindowSlideFromBottomTimed::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D startPos = animWin->getStartPos();
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
-
- UnsignedInt now = timeGetTime();
- UnsignedInt startTime = animWin->getStartTime();
- UnsignedInt endTime = animWin->getEndTime();
-
- if (now < startTime)
- return FALSE;
-
- Real percentDone = 1.0f - (Real)(endTime - now) / (Real)(m_maxDuration);
- if (now >= endTime)
- {
- curPos.y = endPos.y;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- DEBUG_LOG(("window finished animating at %d (%d->%d)", now, startTime, endTime));
- return TRUE;
- }
-
- curPos.y = startPos.y + percentDone*(endPos.y - startPos.y);
- DEBUG_LOG(("(%d,%d) -> (%d,%d) -> (%d,%d) at %g",
- startPos.x, startPos.y, curPos.x, curPos.y, endPos.x, endPos.y, percentDone));
-
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromBottomTimed::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
- return updateAnimateWindow(animWin);
-}
-
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSpiral PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSpiral::ProcessAnimateWindowSpiral( void )
-{
- m_maxR = TheDisplay->getWidth() / 2;
- m_deltaTheta = .33f;
-}
-
-//-----------------------------------------------------------------------------
-ProcessAnimateWindowSpiral::~ProcessAnimateWindowSpiral( void ) { }
-
-//-----------------------------------------------------------------------------
-void ProcessAnimateWindowSpiral::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x = 0;
- vel.y = 0;
- animWin->setVel( vel );
-
-}
-
-//-----------------------------------------------------------------------------
-void ProcessAnimateWindowSpiral::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- ICoord2D size = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- win->winGetSize(&size.x,&size.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
- //set the initial positions for the window. In this case, off the Bottom of the screen
- vel.x = 0;
- vel.y = m_maxR;
- startPos.x = curPos.x = (vel.y * cos(vel.x)) + endPos.x;
- startPos.y = curPos.y = (vel.y * sin(vel.x)) + endPos.y;
-
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-//-----------------------------------------------------------------------------
-Bool ProcessAnimateWindowSpiral::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
-
- curPos.x = (vel.y * cos(vel.x)) + endPos.x;
- curPos.y = (vel.y * sin(vel.x)) + endPos.y;
-
- vel.x = vel.x + m_deltaTheta;
- vel.y -=5;
-
- ICoord2D size;
- win->winGetSize(&size.x, &size.y);
- Int m_max = min(size.x/2, size.y/2);
-
- if(vel.y < m_max)
- {
- ICoord2D restPos = animWin->getRestPos();
- animWin->setFinished( TRUE );
- win->winSetPosition(restPos.x, restPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- animWin->setVel(vel);
- return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-Bool ProcessAnimateWindowSpiral::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
-
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
-
- curPos.x = (vel.y * cos(vel.x)) + endPos.x;
- curPos.y = (vel.y * sin(vel.x)) + endPos.y;
-
- vel.x = vel.x - m_deltaTheta;
- vel.y +=5;
-
- ICoord2D size;
- win->winGetSize(&size.x, &size.y);
-// Int m_max = min(size.x/2, size.y/2);
-
- if(vel.y > m_maxR)
- {
- //ICoord2D restPos = animWin->getRestPos();
- animWin->setFinished( TRUE );
- //win->winSetPosition(restPos.x, restPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- animWin->setVel(vel);
- return FALSE;
-}
-
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromTopFast PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromTopFast::ProcessAnimateWindowSlideFromTopFast( void )
-{
- m_maxVel.y = 60.0f; // top speed windows travel in x and y
- m_maxVel.x = 0.0f;
- m_slowDownThreshold = 40; // when windows get this close to their resting
- // positions they start to slow down
- m_slowDownRatio = 0.67f; // how fast the windows slow down (smaller slows quicker)
- m_speedUpRatio = 4.0f - m_slowDownRatio; // how fast the windows speed up
-
-}
-
-ProcessAnimateWindowSlideFromTopFast::~ProcessAnimateWindowSlideFromTopFast( void ) { }
-
-void ProcessAnimateWindowSlideFromTopFast::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x *= -1;
- vel.y *= -1;
- animWin->setVel( vel );
-
-}
-
-void ProcessAnimateWindowSlideFromTopFast::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
- ICoord2D size = {0,0};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- win->winGetSize(&size.x, &size.y);
-
- //set the initial positions for the window. In this case, off the Top of the screen
- //Int travelDistance = TheDisplay->getWidth();// / 4 * 3;
- startPos.x = curPos.x = restPos.x ;
- startPos.y = curPos.y = -size.y;//restPos.y - travelDistance;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- //Now initialize the velocities
- vel = m_maxVel;
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-Bool ProcessAnimateWindowSlideFromTopFast::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
- curPos.y += (Int)vel.y;
-
- if(curPos.y > endPos.y)
- {
- curPos.y = endPos.y;
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setFinished( TRUE );
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- if( endPos.y - curPos.y <= m_slowDownThreshold )
- {
- vel.y *= m_slowDownRatio;
- }
- if( vel.y < 1.0f)
- vel.y = 1.0f;
- animWin->setVel(vel);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromTopFast::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D startPos = animWin->getStartPos();
- Coord2D vel = animWin->getVel();
- curPos.y += (Int)vel.y;
-
- if(curPos.y < startPos.y)
- {
- curPos.y = startPos.y;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
-
- ICoord2D endPos = animWin->getEndPos();
- if( endPos.y - curPos.y <= m_slowDownThreshold )
- {
- vel.y *= m_speedUpRatio;
- }
- else
- {
- vel.y = -m_maxVel.y;
- }
- if( vel.y < -m_maxVel.y)
- vel.y = -m_maxVel.y;
- animWin->setVel(vel);
- return FALSE;
-}
-
-
-//-----------------------------------------------------------------------------
-// ProcessAnimateWindowSlideFromRightFast PUBLIC FUNCTIONS ////////////////////////
-//-----------------------------------------------------------------------------
-
-ProcessAnimateWindowSlideFromRightFast::ProcessAnimateWindowSlideFromRightFast( void )
-{
- m_maxVel.x = -80.0f; // top speed windows travel in x and y
- m_maxVel.y = 0.0f;
- m_slowDownThreshold = 60; // when windows get this close to their resting
- // positions they start to slow down
- m_slowDownRatio = 0.77f; // how fast the windows slow down (smaller slows quicker)
- m_speedUpRatio = 3.0f - m_slowDownRatio; // how fast the windows speed up
-
-}
-
-//-----------------------------------------------------------------------------
-ProcessAnimateWindowSlideFromRightFast::~ProcessAnimateWindowSlideFromRightFast( void ) { }
-
-//-----------------------------------------------------------------------------
-void ProcessAnimateWindowSlideFromRightFast::initReverseAnimateWindow( wnd::AnimateWindow *animWin, UnsignedInt maxDelay )
-{
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- if(animWin->getDelay() > 0)
- animWin->setStartTime(timeGetTime() + (maxDelay - animWin->getDelay()));
- Coord2D vel = animWin->getVel();
- vel.x *= -1;
- vel.y *= -1;
- animWin->setVel( vel );
- animWin->setFinished( FALSE );
- GameWindow * win = animWin->getGameWindow();
- ICoord2D pos, tempPos;
- win->winGetPosition(&pos.x, &pos.y);
- tempPos = animWin->getCurPos();
- tempPos.y = pos.y;
- animWin->setCurPos(tempPos);
-
- tempPos = animWin->getEndPos();
- tempPos.y = pos.y;
- animWin->setEndPos(tempPos);
-
- tempPos = animWin->getStartPos();
- tempPos.y = pos.y;
- animWin->setStartPos(tempPos);
-
-
-
-
-}
-
-//-----------------------------------------------------------------------------
-void ProcessAnimateWindowSlideFromRightFast::initAnimateWindow( wnd::AnimateWindow *animWin )
-{
- ICoord2D restPos = {0,0};
- ICoord2D startPos = {0,0};
- ICoord2D size = {0,0};
- ICoord2D curPos = {0,0};
- ICoord2D endPos = {0,0};
- Coord2D vel = {0.0f,0.0f};
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into initAnimateWindow as a null... bad bad bad!"));
- return;
- }
- animWin->setFinished( FALSE );
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return;
- }
- win->winGetPosition(&restPos.x, &restPos.y);
- win->winGetSize(&size.x, &size.y);
- endPos.x = restPos.x;
- endPos.y = restPos.y;
-
- //set the initial positions for the window. In this case, off the Right of the screen
- Int travelDistance = TheDisplay->getWidth() - restPos.x + size.x ;// / 4 * 3;
- startPos.x = curPos.x = restPos.x + travelDistance;
- startPos.y = curPos.y = restPos.y;
-
- //set the window's position to the new start positions.
- win->winSetPosition(startPos.x, startPos.y);
-
- //Now initialize the velocities
- vel.x = m_maxVel.x;
- vel.y = 0.0f;
-
-
- animWin->setAnimData(startPos, endPos, curPos, restPos, vel, timeGetTime() + animWin->getDelay(), 0);
-}
-
-
-//-----------------------------------------------------------------------------
-Bool ProcessAnimateWindowSlideFromRightFast::updateAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D endPos = animWin->getEndPos();
- Coord2D vel = animWin->getVel();
- curPos.x += (Int)vel.x;
-
- if(curPos.x < endPos.x)
- {
- curPos.x = endPos.x;
- animWin->setFinished( TRUE );
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
- if( curPos.x - endPos.x <= m_slowDownThreshold )
- {
- vel.x *= m_slowDownRatio;
- }
- if( vel.x >= -1.0f)
- vel.x = -1.0f;
- animWin->setVel(vel);
- return FALSE;
-}
-
-Bool ProcessAnimateWindowSlideFromRightFast::reverseAnimateWindow( wnd::AnimateWindow *animWin )
-{
-
- if(!animWin)
- {
- DEBUG_ASSERTCRASH( animWin, ("animWin was passed into updateAnimateWindow as a null... bad bad bad!"));
- return TRUE;
- }
-
- // if the window has finished animating into position, return
- if(animWin->isFinished())
- return TRUE;
-
- // if the window hasn't started animating...return that we're not finished
- if(timeGetTime() < animWin->getStartTime())
- return FALSE;
-
- // it's set that the window is passed in as it's current position being it's rest position
- // so save off the rest position
- GameWindow *win = animWin->getGameWindow();
- if(!win)
- {
- DEBUG_ASSERTCRASH( win, ("animWin contains a null for it's GameWindow... Whatup wit dat?"));
- return TRUE;
- }
-
- ICoord2D curPos = animWin->getCurPos();
- ICoord2D startPos = animWin->getStartPos();
- Coord2D vel = animWin->getVel();
- curPos.x += (Int)vel.x;
-
- if(curPos.x > startPos.x)
- {
- curPos.x = startPos.x;
- animWin->setFinished( TRUE );
- win->winSetPosition(curPos.x, curPos.y);
- return TRUE;
- }
- win->winSetPosition(curPos.x, curPos.y);
- animWin->setCurPos(curPos);
-
- ICoord2D endPos = animWin->getEndPos();
- if( curPos.x - endPos.x <= m_slowDownThreshold )
- {
- vel.x *= m_speedUpRatio;
- }
- else
- {
- vel.x = -m_maxVel.x;
- }
- if( vel.x > -m_maxVel.x)
- vel.x = -m_maxVel.x;
- animWin->setVel(vel);
- return FALSE;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp
deleted file mode 100644
index 1593115b371..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/WinInstanceData.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: WinInstanceData.cpp //////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: WinInstanceData.cpp
-//
-// Created: Colin Day, July 2001
-//
-// Desc: Game window instance data
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "GameClient/WinInstanceData.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/DisplayStringManager.h"
-#include "Common/Debug.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////
-
-// PRIVATE TYPES //////////////////////////////////////////////////////////////
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////
-
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-// WinInstanceData::WinInstanceData ===========================================
-//=============================================================================
-WinInstanceData::WinInstanceData( void )
-{
-
- // we don't allocate strings unless we need them
- m_text = nullptr;
- m_tooltip = nullptr;
- m_videoBuffer = nullptr;
- init();
-
-}
-
-// WinInstanceData::~WinInstanceData ==========================================
-//=============================================================================
-WinInstanceData::~WinInstanceData( void )
-{
-
- if( m_text )
- TheDisplayStringManager->freeDisplayString( m_text );
-
- if( m_tooltip )
- TheDisplayStringManager->freeDisplayString( m_tooltip );
-
- m_videoBuffer = nullptr; //Video Buffer needs to be clean up by the control that is in charge of the video.
-
-}
-
-// WinInstanceData::init ======================================================
-/** Set initial values for instance data if desired */
-//=============================================================================
-void WinInstanceData::init( void )
-{
- Int i;
-
- // init our draw data images/colors for the states
- for( i = 0; i < MAX_DRAW_DATA; i++ )
- {
-
- m_enabledDrawData[ i ].image = nullptr;
- m_enabledDrawData[ i ].color = WIN_COLOR_UNDEFINED;
- m_enabledDrawData[ i ].borderColor = WIN_COLOR_UNDEFINED;
-
- m_disabledDrawData[ i ].image = nullptr;
- m_disabledDrawData[ i ].color = WIN_COLOR_UNDEFINED;
- m_disabledDrawData[ i ].borderColor = WIN_COLOR_UNDEFINED;
-
- m_hiliteDrawData[ i ].image = nullptr;
- m_hiliteDrawData[ i ].color = WIN_COLOR_UNDEFINED;
- m_hiliteDrawData[ i ].borderColor = WIN_COLOR_UNDEFINED;
-
- }
-
- // initialize text colors
- m_enabledText.color = WIN_COLOR_UNDEFINED;
- m_enabledText.borderColor = WIN_COLOR_UNDEFINED;
- m_disabledText.color = WIN_COLOR_UNDEFINED;
- m_disabledText.borderColor = WIN_COLOR_UNDEFINED;
- m_hiliteText.color = WIN_COLOR_UNDEFINED;
- m_hiliteText.borderColor = WIN_COLOR_UNDEFINED;
-
- m_id = 0;
- m_state = 0;
- m_style = 0;
- m_status = WIN_STATUS_NONE;
- m_owner = nullptr;
- m_textLabelString.clear();
- m_tooltipString.clear();
- m_tooltipDelay = -1; ///< default value
- m_decoratedNameString.clear();
-
- m_imageOffset.x = 0;
- m_imageOffset.y = 0;
-
- // reset all data for the text display strings and font for window
- m_font = nullptr;
- if( m_text )
- {
-
- TheDisplayStringManager->freeDisplayString( m_text );
- m_text = nullptr;
-
- }
- if( m_tooltip )
- {
-
- TheDisplayStringManager->freeDisplayString( m_tooltip );
- m_tooltip = nullptr;
-
- }
-
- m_videoBuffer = nullptr;
-
-
-}
-
-// WinInstanceData::setTooltipText ============================================
-//=============================================================================
-void WinInstanceData::setTooltipText( UnicodeString tip )
-{
-
- // allocate a text tooltip string if needed
- if( m_tooltip == nullptr )
- m_tooltip = TheDisplayStringManager->newDisplayString();
- DEBUG_ASSERTCRASH( m_tooltip, ("no tooltip") );
-
- // set text
- m_tooltip->setText( tip );
-
-}
-
-// WinInstanceData:setText ====================================================
-/** Set the text for this window instance data */
-//=============================================================================
-void WinInstanceData::setText( UnicodeString text )
-{
-
- // allocate a text instance if needed
- if( m_text == nullptr )
- m_text = TheDisplayStringManager->newDisplayString();
- DEBUG_ASSERTCRASH( m_text, ("no text") );
-
- // set the text
- m_text->setText( text );
-
-}
-
-// WinInstanceData:setText ====================================================
-/** Set the text for this window instance data */
-//=============================================================================
-void WinInstanceData::setVideoBuffer( VideoBuffer * videoBuffer )
-{
- m_videoBuffer = videoBuffer;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
deleted file mode 100644
index 595fd760724..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: WindowLayout.cpp /////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, September 2001
-// Desc: Layouts for grouping windows together
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/WindowLayout.h"
-#include "GameClient/Shell.h"
-#include "GameClient/GameWindowManager.h"
-
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-WindowLayout::WindowLayout( void )
-{
- m_filenameString.set("EmptyLayout");
-
- m_windowList = nullptr;
- m_windowTail = nullptr;
- m_windowCount = 0;
-
- m_hidden = FALSE;
-
- m_init = nullptr;
- m_update = nullptr;
- m_shutdown = nullptr;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-WindowLayout::~WindowLayout( void )
-{
-
- //
- // it is the users responsibility to remove windows from the layout before destroying the
- // layout itself. This allows for maximum flexibility of the window layouts and you can
- // use them in any you see fit, as long as they are clean when they go away
- //
- DEBUG_ASSERTCRASH( m_windowList == nullptr, ("Window layout being destroyed still has window references") );
- DEBUG_ASSERTCRASH( m_windowTail == nullptr, ("Window layout being destroyed still has window references") );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Set the hidden/visible status of all the windows in this layout */
-//-------------------------------------------------------------------------------------------------
-void WindowLayout::hide( Bool hide )
-{
- GameWindow *window;
-
- // hide or unhide all windows in this layout
- for( window = m_windowList; window; window = window->winGetNextInLayout() )
- {
-
- window->winHide( hide );
-
- }
-
- // save the new visible state of the system
- m_hidden = hide;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Add window to this layout */
-//-------------------------------------------------------------------------------------------------
-void WindowLayout::addWindow( GameWindow *window )
-{
- GameWindow *win = findWindow( window );
-
- // only add window if window is not in this layout already
- if( win == nullptr )
- {
-
- DEBUG_ASSERTCRASH( window->winGetNextInLayout() == nullptr,
- ("NextInLayout should be null before adding") );
- DEBUG_ASSERTCRASH( window->winGetPrevInLayout() == nullptr,
- ("PrevInLayout should be null before adding") );
-
- window->winSetPrevInLayout( nullptr );
- window->winSetNextInLayout( m_windowList );
- if( m_windowList )
- m_windowList->winSetPrevInLayout( window );
- m_windowList = window;
-
- // set layout into window
- window->winSetLayout( this );
-
- // if no tail pointer, this is it
- if( m_windowTail == nullptr )
- m_windowTail = window;
-
- // we gots another window now
- m_windowCount++;
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Remove window from this layout */
-//-------------------------------------------------------------------------------------------------
-void WindowLayout::removeWindow( GameWindow *window )
-{
- GameWindow *win = findWindow( window );
-
- // can't remove window unless it's really part of this layout
- if( win )
- {
- GameWindow *prev, *next;
-
- prev = win->winGetPrevInLayout();
- next = win->winGetNextInLayout();
-
- if( next )
- next->winSetPrevInLayout( prev );
- if( prev )
- prev->winSetNextInLayout( next );
- else
- m_windowList = next;
-
- // set window as having no layout info
- win->winSetLayout( nullptr );
- win->winSetNextInLayout( nullptr );
- win->winSetPrevInLayout( nullptr );
-
- // if we removed the tail, set the new tail
- if( m_windowTail == win )
- m_windowTail = prev;
-
- // we lost one sir!
- m_windowCount--;
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Destroy all the windows in a layout */
-//-------------------------------------------------------------------------------------------------
-void WindowLayout::destroyWindows( void )
-{
- GameWindow *window;
-
- while( (window = getFirstWindow()) != nullptr )
- {
-
- // remove window from this layout
- removeWindow( window );
-
- // destroy window in window system
- TheWindowManager->winDestroy( window );
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Create the windows using the .wnd file script and load all windows into
- * this layout */
-//-------------------------------------------------------------------------------------------------
-Bool WindowLayout::load( AsciiString filename )
-{
-
- // sanity
- if( filename.isEmpty() )
- return FALSE;
-
- //
- // when we create new windows they are always placed on the top
- // of the window stack. The load layout from script will return the
- // FIRST window loaded from the script, if we traverse from the head of
- // the window list till we see that window returned from the layout
- // loader, that will be all the root windows loaded from the .wnd file
- //
- GameWindow *target;
- WindowLayoutInfo info;
-
- target = TheWindowManager->winCreateFromScript( filename, &info );
- if( target == nullptr )
- {
-
- DEBUG_ASSERTCRASH( target, ("WindowLayout::load - Failed to load layout") );
- DEBUG_LOG(( "WindowLayout::load - Unable to load layout file '%s'", filename.str() ));
- return FALSE;
-
- }
-
- //
- // add windows loaded from .wnd file to the layout, via info.windows.
- //
- std::list::iterator it;
- for (it = info.windows.begin(); it != info.windows.end(); ++it)
- {
- // add window to this layout
- addWindow( *it );
- }
-
- /* MDC - can't do this, as modal windows will be at the head...
- //
- // add windows loaded from .wnd file to the layout, note we start at
- // target and go backwards as the layout->addWindow() puts at top
- // of list and will therefore reverse the order
- //
- GameWindow *window;
- for( window = target; window; window = window->winGetPrev() )
- {
-
- // add window to this layout
- addWindow( window );
-
- }
- */
-
- // copy filename
- m_filenameString = filename;
-
- // assign script info to the layout
- setInit( info.init );
- setUpdate( info.update );
- setShutdown( info.shutdown );
-
- return TRUE; // success
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Bring all windows in this layout forward */
-//-------------------------------------------------------------------------------------------------
-void WindowLayout::bringForward( void )
-{
-
- //
- // loop through all our windows and bring each of them to the top of
- // the window stack, note that we are getting a prev pointer because the
- // action of bringing a window to the top of the stack does detach it
- // from the window list and the layout window list ... it is then
- // re-attached at the top. Also note, to preserve the ordering of
- // the windows we pull from the tail and add to the top
- //
- GameWindow *window, *prev;
- Int countLeft = m_windowCount;
-
- for( window = m_windowTail; countLeft; window = prev )
- {
-
- DEBUG_ASSERTCRASH( window, ("Must have window: m_windowCount is off") );
- prev = window->winGetPrevInLayout();
- window->winBringToTop();
- countLeft--;
-
- }
-
-}
-
-
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------------------------------------------------
-/** Find window within this layout */
-//-------------------------------------------------------------------------------------------------
-GameWindow *WindowLayout::findWindow( GameWindow *window )
-{
- GameWindow *win;
-
- for( win = m_windowList; win; win = win->winGetNextInLayout() )
- if( win == window )
- return win;
-
- return nullptr; // window not found
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GameText.cpp b/Generals/Code/GameEngine/Source/GameClient/GameText.cpp
deleted file mode 100644
index e0ecde33a31..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GameText.cpp
+++ /dev/null
@@ -1,1460 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-//----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright(C) 2001 - All Rights Reserved
-//
-//----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: GameText.cpp
-//
-// Created: 11/07/01
-//
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Includes
-//----------------------------------------------------------------------------
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/GameText.h"
-#include "Common/Language.h"
-#include "Common/Registry.h"
-#include "GameClient/LanguageFilter.h"
-#include "Common/Debug.h"
-#include "Common/UnicodeString.h"
-#include "Common/AsciiString.h"
-#include "Common/GlobalData.h"
-#include "Common/file.h"
-#include "Common/FileSystem.h"
-#include "Common/version.h"
-
-
-
-
-//----------------------------------------------------------------------------
-// Externals
-//----------------------------------------------------------------------------
-
-#if defined(RTS_DEBUG)
-Bool g_useStringFile = TRUE;
-#endif
-
-
-//----------------------------------------------------------------------------
-// Defines
-//----------------------------------------------------------------------------
-
-#define CSF_ID ( ('C'<<24) | ('S'<<16) | ('F'<<8) | (' ') )
-#define CSF_LABEL ( ('L'<<24) | ('B'<<16) | ('L'<<8) | (' ') )
-#define CSF_STRING ( ('S'<<24) | ('T'<<16) | ('R'<<8) | (' ') )
-#define CSF_STRINGWITHWAVE ( ('S'<<24) | ('T'<<16) | ('R'<<8) | ('W') )
-#define CSF_VERSION 3
-
-#define STRING_FILE 0
-#define CSF_FILE 1
-#define MAX_UITEXT_LENGTH (10*1024)
-//----------------------------------------------------------------------------
-// Private Types
-//----------------------------------------------------------------------------
-
-//===============================
-// StringInfo
-//===============================
-
-struct StringInfo
-{
- AsciiString label;
- UnicodeString text;
- AsciiString speech;
-};
-
-struct StringLookUp
-{
- AsciiString *label;
- StringInfo *info;
-};
-
-//===============================
-// CSFHeader
-//===============================
-
-struct CSFHeader
-{
- Int id;
- Int version;
- Int num_labels;
- Int num_strings;
- Int skip;
- Int langid;
-
-};
-
-//===============================
-// struct NoString
-//===============================
-
-struct NoString
-{
- struct NoString *next;
- UnicodeString text;
-};
-
-
-//===============================
-// GameTextManager
-//===============================
-
-class GameTextManager : public GameTextInterface
-{
- public:
-
- GameTextManager();
- virtual ~GameTextManager();
-
- virtual void init( void ); ///< Initializes the text system
- virtual void deinit( void ); ///< Shuts down the text system
- virtual void update( void ) {}; ///< update text manager
- virtual void reset( void ); ///< Resets the text system
-
- virtual UnicodeString fetch( const Char *label, Bool *exists = nullptr ); ///< Returns the associated labeled unicode text
- virtual UnicodeString fetch( AsciiString label, Bool *exists = nullptr ); ///< Returns the associated labeled unicode text
- virtual UnicodeString fetchFormat( const Char *label, ... );
- virtual UnicodeString fetchOrSubstitute( const Char *label, const WideChar *substituteText );
- virtual UnicodeString fetchOrSubstituteFormat( const Char *label, const WideChar *substituteFormat, ... );
- virtual UnicodeString fetchOrSubstituteFormatVA( const Char *label, const WideChar *substituteFormat, va_list args );
-
- virtual AsciiStringVec& getStringsWithLabelPrefix(AsciiString label);
-
- virtual void initMapStringFile( const AsciiString& filename );
-
- protected:
-
- Int m_textCount;
- Int m_maxLabelLen;
- Char m_buffer[MAX_UITEXT_LENGTH];
- Char m_buffer2[MAX_UITEXT_LENGTH];
- Char m_buffer3[MAX_UITEXT_LENGTH];
- WideChar m_tbuffer[MAX_UITEXT_LENGTH*2];
-
- StringInfo *m_stringInfo;
- StringLookUp *m_stringLUT;
- Bool m_initialized;
-#if defined(RTS_DEBUG)
- Bool m_jabberWockie;
- Bool m_munkee;
-#endif
- NoString *m_noStringList;
- Int m_useStringFile;
- LanguageID m_language;
- UnicodeString m_failed;
-
- StringInfo *m_mapStringInfo;
- StringLookUp *m_mapStringLUT;
- Int m_mapTextCount;
-
- /// m_asciiStringVec will be altered every time that getStringsWithLabelPrefix is called,
- /// so don't simply store a pointer to it.
- AsciiStringVec m_asciiStringVec;
-
- void stripSpaces ( WideChar *string );
- void removeLeadingAndTrailing ( Char *m_buffer );
- void readToEndOfQuote( File *file, Char *in, Char *out, Char *wavefile, Int maxBufLen );
- void reverseWord ( Char *file, Char *lp );
- void translateCopy( WideChar *outbuf, Char *inbuf );
- Bool getStringCount( const Char *filename, Int& textCount );
- Bool getCSFInfo ( const Char *filename );
- Bool parseCSF( const Char *filename );
- Bool parseStringFile( const char *filename );
- Bool parseMapStringFile( const char *filename );
- Bool readLine( char *buffer, Int max, File *file );
- Char readChar( File *file );
-};
-
-static int __cdecl compareLUT ( const void *, const void*);
-//----------------------------------------------------------------------------
-// Private Data
-//----------------------------------------------------------------------------
-
-
-
-//----------------------------------------------------------------------------
-// Public Data
-//----------------------------------------------------------------------------
-
-GameTextInterface *TheGameText = nullptr;
-
-//----------------------------------------------------------------------------
-// Private Prototypes
-//----------------------------------------------------------------------------
-
-
-
-//----------------------------------------------------------------------------
-// Private Functions
-//----------------------------------------------------------------------------
-
-
-
-//----------------------------------------------------------------------------
-// Public Functions
-//----------------------------------------------------------------------------
-
-//============================================================================
-// CreateGameTextInterface
-//============================================================================
-
-GameTextInterface* CreateGameTextInterface( void )
-{
- return NEW GameTextManager;
-}
-
-
-//============================================================================
-// GameTextManager::GameTextManager
-//============================================================================
-
-GameTextManager::GameTextManager()
-: m_textCount(0),
- m_maxLabelLen(0),
- m_stringInfo(nullptr),
- m_stringLUT(nullptr),
- m_initialized(FALSE),
- m_noStringList(nullptr),
-#if defined(RTS_DEBUG)
- m_jabberWockie(FALSE),
- m_munkee(FALSE),
- m_useStringFile(g_useStringFile),
-#else
- m_useStringFile(TRUE),
-#endif
- m_mapStringInfo(nullptr),
- m_mapStringLUT(nullptr),
- m_failed(L"***FATAL*** String Manager failed to initialize properly")
-{
- for(Int i=0; i < MAX_UITEXT_LENGTH; i++)
- {
- m_buffer[i] = 0;
- m_buffer2[i] = 0;
- m_buffer3[i] = 0;
- }
-}
-
-//============================================================================
-// GameTextManager::~GameTextManager
-//============================================================================
-
-GameTextManager::~GameTextManager()
-{
- deinit();
-}
-
-//============================================================================
-// GameTextManager::init
-//============================================================================
-
-extern const Char *g_strFile;
-extern const Char *g_csfFile;
-
-void GameTextManager::init( void )
-{
- AsciiString csfFile;
- csfFile.format(g_csfFile, GetRegistryLanguage().str());
- Int format;
-
- if ( m_initialized )
- {
- return;
- }
-
- m_initialized = TRUE;
-
- m_maxLabelLen = 0;
-#if defined(RTS_DEBUG)
- if(TheGlobalData)
- {
- m_jabberWockie = TheGlobalData->m_jabberOn;
- m_munkee = TheGlobalData->m_munkeeOn;
- }
-#endif
-
- if ( m_useStringFile && getStringCount( g_strFile, m_textCount ) )
- {
- format = STRING_FILE;
- }
- else if ( getCSFInfo ( csfFile.str() ) )
- {
- format = CSF_FILE;
- }
- else
- {
- return;
- }
-
- if( m_textCount == 0 )
- {
- return;
- }
-
- //Allocate StringInfo Array
-
- m_stringInfo = NEW StringInfo[m_textCount];
-
- if( m_stringInfo == nullptr )
- {
- deinit();
- return;
- }
-
- if ( format == STRING_FILE )
- {
- if( parseStringFile( g_strFile ) == FALSE )
- {
- deinit();
- return;
- }
- }
- else
- {
- if ( !parseCSF ( csfFile.str() ) )
- {
- deinit();
- return;
- }
- }
-
- m_stringLUT = NEW StringLookUp[m_textCount];
-
- StringLookUp *lut = m_stringLUT;
- StringInfo *info = m_stringInfo;
-
- for ( Int i = 0; i < m_textCount; i++ )
- {
- lut->info = info;
- lut->label = &info->label;
- lut++;
- info++;
- }
-
- qsort( m_stringLUT, m_textCount, sizeof(StringLookUp), compareLUT );
-
-}
-
-//============================================================================
-// GameTextManager::deinit
-//============================================================================
-
-void GameTextManager::deinit( void )
-{
-
- delete [] m_stringInfo;
- m_stringInfo = nullptr;
-
- delete [] m_stringLUT;
- m_stringLUT = nullptr;
-
- m_textCount = 0;
-
- NoString *noString = m_noStringList;
-
- DEBUG_LOG_RAW(("\n"));
- DEBUG_LOG(("*** Missing strings ***"));
- while ( noString )
- {
- DEBUG_LOG(("*** %ls ***", noString->text.str()));
- NoString *next = noString->next;
- delete noString;
- noString = next;
- }
- DEBUG_LOG(("*** End missing strings ***"));
- DEBUG_LOG_RAW(("\n"));
-
- m_noStringList = nullptr;
-
- m_initialized = FALSE;
-}
-
-//============================================================================
-// GameTextManager::reset
-//============================================================================
-
-void GameTextManager::reset( void )
-{
- delete [] m_mapStringInfo;
- m_mapStringInfo = nullptr;
-
- delete [] m_mapStringLUT;
- m_mapStringLUT = nullptr;
-}
-
-
-//============================================================================
-// GameTextManager::stripSpaces
-//============================================================================
-
-void GameTextManager::stripSpaces ( WideChar *string )
-{
- WideChar *str, *ptr;
- WideChar ch, last = 0;
- Int skipall = TRUE;
-
- str = ptr = string;
-
- while ( (ch = *ptr++) != 0 )
- {
- if ( ch == ' ' )
- {
- if ( last == ' ' || skipall )
- {
- continue;
- }
- }
-
- if ( ch == '\n' || ch == '\t' )
- {
- // remove last space
- if ( last == ' ' )
- {
- str--;
- }
-
- skipall = TRUE; // skip all spaces
- last = *str++ = ch;
- continue;
- }
-
- last = *str++ = ch;
- skipall = FALSE;
- }
-
- if ( last == ' ' )
- {
- str--;
- }
-
- *str = 0;
-}
-
-//============================================================================
-// GameTextManager::removeLeadingAndTrailing
-//============================================================================
-
-void GameTextManager::removeLeadingAndTrailing ( Char *buffer )
-{
- Char *first, *ptr;
- Char ch;
-
- ptr = first = buffer;
-
- while ( (ch = *first) != 0 && iswspace ( ch ))
- {
- first++;
- }
-
- while ( (*ptr++ = *first++) != 0 );
-
- ptr -= 2;
-
- while ( (ptr > buffer) && (ch = *ptr) != 0 && iswspace ( ch ) )
- {
- ptr--;
- }
-
- ptr++;
- *ptr = 0;
-}
-
-//============================================================================
-// GameTextManager::readToEndOfQuote
-//============================================================================
-
-void GameTextManager::readToEndOfQuote( File *file, Char *in, Char *out, Char *wavefile, Int maxBufLen )
-{
- Int slash = FALSE;
- Int state = 0;
- Int line_start = FALSE;
- Char ch;
- Int ccount = 0;
- Int len = 0;
- Int done = FALSE;
-
- while ( maxBufLen )
- {
- // get next Char
-
- if ( in )
- {
- if ( (ch = *in++) == 0 )
- {
- in = nullptr; // have exhausted the input m_buffer
- ch = readChar ( file );
- }
- }
- else
- {
- ch = readChar ( file );
- }
-
- if ( ch == EOF )
- {
- return ;
- }
-
- if ( ch == '\n' )
- {
- line_start = TRUE;
- slash = FALSE;
- ccount = 0;
- ch = ' ';
- }
- else if ( ch == '\\' && !slash)
- {
- slash = TRUE;
- }
- else if ( ch == '\\' && slash)
- {
- slash = FALSE;
- }
- else if ( ch == '"' && !slash )
- {
- break; // done
- }
- else
- {
- slash = FALSE;
- }
-
- if ( iswspace ( ch ))
- {
- ch = ' ';
- }
-
- *out++ = ch;
- maxBufLen--;
- }
-
- *out = 0;
-
- while ( !done )
- {
- // get next Char
-
- if ( in )
- {
- if ( (ch = *in++) == 0 )
- {
- in = nullptr; // have exhausted the input m_buffer
- ch = readChar ( file );
- }
- }
- else
- {
- ch = readChar ( file );
- }
-
- if ( ch == '\n' || ch == EOF )
- {
- break;
- }
-
- switch ( state )
- {
-
- case 0:
- if ( iswspace ( ch ) || ch == '=' )
- {
- break;
- }
-
- state = 1;
- FALLTHROUGH;
- case 1:
- if ( ( ch >= 'a' && ch <= 'z') || ( ch >= 'A' && ch <='Z') || (ch >= '0' && ch <= '9') || ch == '_' )
- {
- *wavefile++ = ch;
- len++;
- break;
- }
- state = 2;
- FALLTHROUGH;
- case 2:
- break;
- }
- }
-
- *wavefile = 0;
-
- if ( len )
- {
- if ( ( ch = *(wavefile-1)) >= '0' && ch <= '9' )
- {
- *wavefile++ = 'e';
- *wavefile = 0;
- }
- }
-
-}
-
-
-//============================================================================
-// GameTextManager::reverseWord
-//============================================================================
-
-void GameTextManager::reverseWord ( Char *file, Char *lp )
-{
- Int first = TRUE;
- Char f, l;
- Int ok = TRUE ;
-
- while ( ok )
- {
- if ( file >= lp )
- {
- return;
- }
-
- f = *file;
- l = *lp;
-
- if ( first )
- {
- if ( f >= 'A' && f <= 'Z' )
- {
- if ( l >= 'a' && l <= 'z' )
- {
- f = (f - 'A') + 'a';
- l = (l - 'a') + 'A';
- }
- }
-
- first = FALSE;
- }
-
- *lp-- = f;
- *file++ = l;
-
- }
-
-}
-
-//============================================================================
-// GameTextManager::translateCopy
-//============================================================================
-
-void GameTextManager::translateCopy( WideChar *outbuf, Char *inbuf )
-{
- Int slash = FALSE;
-
-#if defined(RTS_DEBUG)
- if ( m_jabberWockie )
- {
- static Char buffer[MAX_UITEXT_LENGTH*2];
- Char *firstLetter = nullptr, *lastLetter;
- Char *b = buffer;
- Int formatWord = FALSE;
- Char ch;
-
- while ( (ch = *inbuf++) != 0 )
- {
- if ( ! (( ch >= 'a' && ch <= 'z') || ( ch >= 'A' && ch <= 'Z' )))
- {
- if ( firstLetter )
- {
- if ( !formatWord )
- {
- lastLetter = b-1;
- reverseWord ( firstLetter, lastLetter );
- }
- firstLetter = nullptr;
- formatWord = FALSE;
- }
- *b++ = ch;
- if ( ch == '\\' )
- {
- *b++ = *inbuf++;
- }
- if ( ch == '%' )
- {
- while ( (ch = *inbuf++) != 0 && !( (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')))
- {
- *b++ = ch;
- }
- *b++ = ch;
- }
- }
- else
- {
- if ( !firstLetter )
- {
- firstLetter = b;
- }
-
- *b++ = ch;
-
- }
- }
-
- if ( firstLetter )
- {
- lastLetter = b-1;
- reverseWord ( firstLetter, lastLetter );
- }
-
- *b++ = 0;
- inbuf = buffer;
- }
- else if( m_munkee )
- {
- wcscpy(outbuf, L"Munkee");
- return;
- }
-#endif
-
- while( *inbuf != '\0' )
- {
- if( slash == TRUE )
- {
- slash = FALSE;
-
- switch( *inbuf )
- {
- // in case end of string is reached
- // should never happen!!!
- case '\0':
- return;
-
- case '\\':
- *outbuf++ = '\\';
- break;
-
- case '\'':
- *outbuf++ = '\'';
- break;
-
- case '\"':
- *outbuf++ = '\"';
- break;
-
- case '\?':
- *outbuf++ = '\?';
- break;
-
- case 't':
- *outbuf++ = '\t';
- break;
-
- case 'n':
- *outbuf++ = '\n';
- break;
-
- default:
- *outbuf++ = *inbuf & 0x00FF;
- break;
- }
- }
- else if( *inbuf != '\\' )
- {
- *outbuf++ = *inbuf & 0x00FF;
- }
- else
- slash = TRUE;
-
- inbuf++;
- }
- *outbuf= 0;
-}
-
-//============================================================================
-// GameTextManager::getStringCount
-//============================================================================
-
-Bool GameTextManager::getStringCount( const char *filename, Int& textCount )
-{
- Int ok = TRUE;
-
- textCount = 0;
-
- File *file;
- file = TheFileSystem->openFile(filename, File::READ | File::TEXT);
- DEBUG_LOG(("Looking in %s for string file", filename));
-
- if ( file == nullptr )
- {
- return FALSE;
- }
-
- while(ok)
- {
- if( !readLine( m_buffer, sizeof( m_buffer) -1, file ) )
- break;
- removeLeadingAndTrailing ( m_buffer );
-
- if( m_buffer[0] == '"' )
- {
- Int len = strlen(m_buffer);
- m_buffer[ len ] = '\n';
- m_buffer[ len+1] = 0;
- readToEndOfQuote( file, &m_buffer[1], m_buffer2, m_buffer3, MAX_UITEXT_LENGTH );
- }
- else if( stricmp( m_buffer, "END") == 0 )
- {
- textCount++;
- }
- }
-
- textCount += 500;
- file->close();
- file = nullptr;
- return TRUE;
-}
-
-//============================================================================
-// GameTextManager::getCSFInfo
-//============================================================================
-
-Bool GameTextManager::getCSFInfo ( const Char *filename )
-{
- CSFHeader header;
- Int ok = FALSE;
- File *file = TheFileSystem->openFile(filename, File::READ | File::BINARY);
- DEBUG_LOG(("Looking in %s for compiled string file", filename));
-
- if ( file != nullptr )
- {
- if ( file->read( &header, sizeof ( header )) == sizeof ( header ) )
- {
- if ( header.id == CSF_ID )
- {
- m_textCount = header.num_labels;
-
- if ( header.version >= 2 )
- {
- m_language = (LanguageID) header.langid;
- }
- else
- {
- m_language = LANGUAGE_ID_US;
- }
-
- ok = TRUE;
- }
- }
-
- file->close();
- file = nullptr;
- }
-
- return ok;
-}
-
-//============================================================================
-// GameTextManager::parseCSF
-//============================================================================
-
-Bool GameTextManager::parseCSF( const Char *filename )
-{
- File *file;
- Int id;
- Int len;
- Int listCount = 0;
- Bool ok = FALSE;
- CSFHeader header;
-
- file = TheFileSystem->openFile(filename, File::READ | File::BINARY);
-
- if ( file == nullptr )
- {
- return FALSE;
- }
-
- if ( file->read ( &header, sizeof ( CSFHeader)) != sizeof ( CSFHeader) )
- {
- return FALSE;
- }
-
- while( file->read ( &id, sizeof (id)) == sizeof ( id) )
- {
- Int num;
- Int num_strings;
-
- if ( id != CSF_LABEL )
- {
- goto quit;
- }
-
- file->read ( &num_strings, sizeof ( Int ));
-
- file->read ( &len, sizeof ( Int ) );
-
- if ( len )
- {
- file->read ( m_buffer, len );
- }
-
- m_buffer[len] = 0;
-
- m_stringInfo[listCount].label = m_buffer;
-
-
- if ( len > m_maxLabelLen )
- {
- m_maxLabelLen = len;
- }
-
- num = 0;
-
- while ( num < num_strings )
- {
- file->read ( &id, sizeof ( Int ) );
-
- if ( id != CSF_STRING && id != CSF_STRINGWITHWAVE )
- {
- goto quit;
- }
-
- file->read ( &len, sizeof ( Int ) );
-
- if ( len )
- {
- file->read ( m_tbuffer, len*sizeof(WideChar) );
- }
-
- if ( num == 0 )
- {
- // only use the first string found
- m_tbuffer[len] = 0;
-
- {
- WideChar *ptr;
-
- ptr = m_tbuffer;
-
- while ( *ptr )
- {
- *ptr = ~*ptr;
- ptr++;
- }
- }
-
- stripSpaces ( m_tbuffer );
- m_stringInfo[listCount].text = m_tbuffer;
- }
-
- if ( id == CSF_STRINGWITHWAVE )
- {
- file->read ( &len, sizeof ( Int ) );
- if ( len )
- {
- file->read ( m_buffer, len );
- }
- m_buffer[len] = 0;
-
- if ( num == 0 && len )
- {
- // only use the first string found
- m_stringInfo[listCount].speech = m_buffer;
- }
-
- }
-
- num++;
- }
-
- listCount++;
- }
-
- ok = TRUE;
-
-quit:
-
- file->close();
- file = nullptr;
-
- return ok;
-}
-
-
-//============================================================================
-// GameTextManager::parseStringFile
-//============================================================================
-
-Bool GameTextManager::parseStringFile( const char *filename )
-{
- Int listCount = 0;
- Int ok = TRUE;
-
- File *file = TheFileSystem->openFile(filename, File::READ | File::TEXT);
-
- if ( file == nullptr )
- {
- return FALSE;
- }
-
- while( ok )
- {
- Int len;
- if( !readLine( m_buffer, MAX_UITEXT_LENGTH, file ))
- {
- break;
- }
-
- removeLeadingAndTrailing ( m_buffer );
-
- if( ( *(unsigned short *)m_buffer == 0x2F2F) || !m_buffer[0]) // 0x2F2F is Hex for //
- continue;
-
- // make sure label is unique
-
- for ( Int i = 0; i < listCount; i++ )
- {
- if ( stricmp ( m_stringInfo[i].label.str(), m_buffer ) == 0)
- {
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' multiply defined!", m_buffer ));
- }
- }
-
- m_stringInfo[listCount].label = m_buffer;
- len = strlen ( m_buffer );
-
-
- if ( len > m_maxLabelLen )
- {
- m_maxLabelLen = len;
- }
-
- Bool readString = FALSE;
- while( ok )
- {
- if (!readLine ( m_buffer, sizeof(m_buffer)-1, file ))
- {
- DEBUG_ASSERTCRASH (FALSE, ("Unexpected end of string file"));
- ok = FALSE;
- goto quit;
- }
-
- removeLeadingAndTrailing ( m_buffer );
-
- if( m_buffer[0] == '"' )
- {
- len = strlen(m_buffer);
- m_buffer[ len ] = '\n';
- m_buffer[ len+1] = 0;
- readToEndOfQuote( file, &m_buffer[1], m_buffer2, m_buffer3, MAX_UITEXT_LENGTH );
-
-
- if ( readString )
- {
- // only one string per label allows
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
- }
- else
- {
- // Copy string into new home
- translateCopy( m_tbuffer, m_buffer2 );
- stripSpaces ( m_tbuffer );
-
- m_stringInfo[listCount].text = m_tbuffer ;
- m_stringInfo[listCount].speech = m_buffer3;
- readString = TRUE;
- }
- }
- else if ( stricmp ( m_buffer, "END" ) == 0)
- {
- break;
- }
- }
-
- listCount++;
- }
-
-quit:
-
- file->close();
- file = nullptr;
-
- return ok;
-}
-
-//============================================================================
-// GameTextManager::initMapStringFile
-//============================================================================
-
-void GameTextManager::initMapStringFile( const AsciiString& filename )
-{
- m_mapTextCount = 0;
- getStringCount( filename.str(), m_mapTextCount );
-
- m_mapStringInfo = NEW StringInfo[m_mapTextCount];
-
- parseMapStringFile( filename.str() );
-
- m_mapStringLUT = NEW StringLookUp[m_mapTextCount];
-
- StringLookUp *lut = m_mapStringLUT;
- StringInfo *info = m_mapStringInfo;
-
- for ( Int i = 0; i < m_mapTextCount; i++ )
- {
- lut->info = info;
- lut->label = &info->label;
- lut++;
- info++;
- }
-
- qsort( m_mapStringLUT, m_mapTextCount, sizeof(StringLookUp), compareLUT );
-}
-
-//============================================================================
-// GameTextManager::parseMapStringFile
-//============================================================================
-
-Bool GameTextManager::parseMapStringFile( const char *filename )
-{
- Int listCount = 0;
- Int ok = TRUE;
-
- File *file;
-
- file = TheFileSystem->openFile(filename, File::READ | File::TEXT);
- if ( file == nullptr )
- {
- return FALSE;
- }
-
- while( ok )
- {
- Int len;
- if( !readLine( m_buffer, MAX_UITEXT_LENGTH, file ))
- {
- break;
- }
-
- removeLeadingAndTrailing ( m_buffer );
-
- if( ( *(unsigned short *)m_buffer == 0x2F2F) || !m_buffer[0]) // 0x2F2F is Hex for //
- continue;
-
- // make sure label is unique
-
- for ( Int i = 0; i < listCount; i++ )
- {
- if ( stricmp ( m_mapStringInfo[i].label.str(), m_buffer ) == 0)
- {
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' multiply defined!", m_buffer ));
- }
- }
-
- m_mapStringInfo[listCount].label = m_buffer;
- len = strlen ( m_buffer );
-
-
- if ( len > m_maxLabelLen )
- {
- m_maxLabelLen = len;
- }
-
- Bool readString = FALSE;
- while( ok )
- {
- if (!readLine ( m_buffer, sizeof(m_buffer)-1, file ))
- {
- DEBUG_ASSERTCRASH (FALSE, ("Unexpected end of string file"));
- ok = FALSE;
- goto quit;
- }
-
- removeLeadingAndTrailing ( m_buffer );
-
- if( m_buffer[0] == '"' )
- {
- len = strlen(m_buffer);
- m_buffer[ len ] = '\n';
- m_buffer[ len+1] = 0;
- readToEndOfQuote( file, &m_buffer[1], m_buffer2, m_buffer3, MAX_UITEXT_LENGTH );
-
-
- if ( readString )
- {
- // only one string per label allowed
- DEBUG_ASSERTCRASH ( FALSE, ("String label '%s' has more than one string defined!", m_stringInfo[listCount].label.str()));
- }
- else
- {
- // Copy string into new home
- translateCopy( m_tbuffer, m_buffer2 );
- stripSpaces ( m_tbuffer );
-
- UnicodeString text = UnicodeString(m_tbuffer);
- if (TheLanguageFilter)
- TheLanguageFilter->filterLine(text);
-
- m_mapStringInfo[listCount].text = text;
- m_mapStringInfo[listCount].speech = m_buffer3;
- readString = TRUE;
- }
- }
- else if ( stricmp ( m_buffer, "END" ) == 0)
- {
- break;
- }
- }
-
- listCount++;
- }
-
-quit:
-
- file->close();
- file = nullptr;
-
- return ok;
-}
-
-//============================================================================
-// *GameTextManager::fetch
-//============================================================================
-
-UnicodeString GameTextManager::fetch( const Char *label, Bool *exists )
-{
- DEBUG_ASSERTCRASH ( m_initialized, ("String Manager has not been m_initialized") );
-
- if( m_stringInfo == nullptr )
- {
- if( exists )
- *exists = FALSE;
- return m_failed;
- }
-
- StringLookUp *lookUp;
- StringLookUp key;
- AsciiString lb;
- lb = label;
- key.info = nullptr;
- key.label = &lb;
-
- lookUp = (StringLookUp *) bsearch( &key, (void*) m_stringLUT, m_textCount, sizeof(StringLookUp), compareLUT );
-
- if ( lookUp == nullptr && m_mapStringLUT && m_mapTextCount )
- {
- lookUp = (StringLookUp *) bsearch( &key, (void*) m_mapStringLUT, m_mapTextCount, sizeof(StringLookUp), compareLUT );
- }
-
- if( lookUp == nullptr )
- {
-
- // string not found
- if( exists )
- *exists = FALSE;
-
- // See if we already have the missing string
- UnicodeString missingString;
- missingString.format(L"MISSING: '%hs'", label);
-
- NoString *noString = m_noStringList;
-
- while ( noString )
- {
- if (noString->text == missingString)
- return missingString;
-
- noString = noString->next;
- }
-
- //DEBUG_LOG(("*** MISSING:'%s' ***", label));
- // Remember file could have been altered at this point.
- noString = NEW NoString;
- noString->text = missingString;
- noString->next = m_noStringList;
- m_noStringList = noString;
- return noString->text;
- }
- if( exists )
- *exists = TRUE;
- return lookUp->info->text;
-}
-
-//============================================================================
-// *GameTextManager::fetch
-//============================================================================
-
-UnicodeString GameTextManager::fetch( AsciiString label, Bool *exists )
-{
- return fetch(label.str(), exists);
-}
-
-//============================================================================
-// *GameTextManager::fetchFormat
-//============================================================================
-
-UnicodeString GameTextManager::fetchFormat( const Char *label, ... )
-{
- Bool exists;
- UnicodeString str = fetch(label, &exists);
- if (exists)
- {
- UnicodeString strFormat;
-
- va_list args;
- va_start(args, label);
- strFormat.format_va(str.str(), args);
- va_end(args);
-
- str = strFormat;
- }
- return str;
-}
-
-//============================================================================
-// GameTextManager::fetchOrSubstitute
-//============================================================================
-
-UnicodeString GameTextManager::fetchOrSubstitute( const Char *label, const WideChar *substituteText )
-{
- Bool exists;
- UnicodeString str = fetch(label, &exists);
- if (!exists)
- str = substituteText;
- return str;
-}
-
-//============================================================================
-// GameTextManager::fetchOrSubstituteFormat
-//============================================================================
-
-UnicodeString GameTextManager::fetchOrSubstituteFormat( const Char *label, const WideChar *substituteFormat, ... )
-{
- va_list args;
- va_start(args, substituteFormat);
- UnicodeString str = fetchOrSubstituteFormatVA(label, substituteFormat, args);
- va_end(args);
-
- return str;
-}
-
-//============================================================================
-// GameTextManager::fetchOrSubstituteFormatVA
-//============================================================================
-
-UnicodeString GameTextManager::fetchOrSubstituteFormatVA( const Char *label, const WideChar *substituteFormat, va_list args )
-{
- Bool exists;
- UnicodeString str = fetch(label, &exists);
- if (exists)
- {
- UnicodeString strFormat;
- strFormat.format_va(strFormat.str(), args);
- str = strFormat;
- }
- else
- {
- str.format_va(substituteFormat, args);
- }
-
- return str;
-}
-
-//============================================================================
-// GameTextManager::getStringsWithLabelPrefix
-//============================================================================
-
-AsciiStringVec& GameTextManager::getStringsWithLabelPrefix(AsciiString label)
-{
- m_asciiStringVec.clear();
- if (m_stringLUT) {
- for (int i = 0; i < m_textCount; ++i) {
- if (strstr(m_stringLUT[i].label->str(), label.str()) == m_stringLUT[i].label->str()) {
- m_asciiStringVec.push_back(*m_stringLUT[i].label);
- }
- }
- }
- if (m_mapStringLUT) {
- for (int i = 0; i < m_mapTextCount; ++i) {
- if (strstr(m_mapStringLUT[i].label->str(), label.str()) == m_mapStringLUT[i].label->str()) {
- m_asciiStringVec.push_back(*m_mapStringLUT[i].label);
- }
- }
- }
- return m_asciiStringVec;
-}
-
-//============================================================================
-// GameTextManager::readLine
-//============================================================================
-
-Bool GameTextManager::readLine( char *buffer, Int max, File *file )
-{
- Int ok = FALSE;
-
- while ( max && file->read( buffer, 1 ) == 1 )
- {
- ok = TRUE;
-
- if ( *buffer == '\n' )
- {
- break;
- }
-
- buffer++;
- max--;
- }
-
- *buffer = 0;
-
- return ok;
-}
-
-//============================================================================
-// GameTextManager::readChar
-//============================================================================
-
-Char GameTextManager::readChar( File *file )
-{
- Char ch;
-
- if ( file->read( &ch, 1 ) == 1 )
- {
- return ch;
- }
-
- return 0;
-}
-
-//============================================================================
-// compareLUT
-//============================================================================
-
-static int __cdecl compareLUT ( const void *i1, const void*i2)
-{
- StringLookUp *lut1 = (StringLookUp*) i1;
- StringLookUp *lut2 = (StringLookUp*) i2;
-
- return stricmp( lut1->label->str(), lut2->label->str());
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp b/Generals/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp
deleted file mode 100644
index 63322480af8..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/GlobalLanguage.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GlobalLanguage.cpp /////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Aug 2002
-//
-// Filename: GlobalLanguage.cpp
-//
-// author: Chris Huybregts
-//
-// purpose: Contains the member functions for the language munkee
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-//-----------------------------------------------------------------------------
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// USER INCLUDES //////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-#include "PreRTS.h"
-
-#include "Common/AddonCompat.h"
-#include "Common/INI.h"
-#include "Common/Registry.h"
-#include "Common/FileSystem.h"
-#include "Common/UserPreferences.h"
-
-#include "GameClient/Display.h"
-#include "GameClient/GlobalLanguage.h"
-
-//-----------------------------------------------------------------------------
-// DEFINES ////////////////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-GlobalLanguage *TheGlobalLanguageData = nullptr; ///< The global language singleton
-
-static const LookupListRec ResolutionFontSizeMethodNames[] =
-{
- { "CLASSIC", GlobalLanguage::ResolutionFontSizeMethod_Classic },
- { "CLASSIC_NO_CEILING", GlobalLanguage::ResolutionFontSizeMethod_ClassicNoCeiling },
- { "STRICT", GlobalLanguage::ResolutionFontSizeMethod_Strict },
- { "BALANCED", GlobalLanguage::ResolutionFontSizeMethod_Balanced },
- { nullptr, 0 }
-};
-
-static const FieldParse TheGlobalLanguageDataFieldParseTable[] =
-{
- { "UnicodeFontName", INI::parseAsciiString,nullptr, offsetof( GlobalLanguage, m_unicodeFontName ) },
- //{ "UnicodeFontFileName", INI::parseAsciiString,nullptr, offsetof( GlobalLanguage, m_unicodeFontFileName ) },
- { "LocalFontFile", GlobalLanguage::parseFontFileName, nullptr, 0},
- { "MilitaryCaptionSpeed", INI::parseInt, nullptr, offsetof( GlobalLanguage, m_militaryCaptionSpeed ) },
- { "UseHardWordWrap", INI::parseBool, nullptr, offsetof( GlobalLanguage, m_useHardWrap) },
- { "ResolutionFontAdjustment", INI::parseReal, nullptr, offsetof( GlobalLanguage, m_resolutionFontSizeAdjustment) },
- { "ResolutionFontSizeMethod", INI::parseLookupList, ResolutionFontSizeMethodNames, offsetof( GlobalLanguage, m_resolutionFontSizeMethod) },
- { "CopyrightFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_copyrightFont ) },
- { "MessageFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_messageFont) },
- { "MilitaryCaptionTitleFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_militaryCaptionTitleFont) },
- { "MilitaryCaptionFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_militaryCaptionFont) },
- { "SuperweaponCountdownNormalFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_superweaponCountdownNormalFont) },
- { "SuperweaponCountdownReadyFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_superweaponCountdownReadyFont) },
- { "NamedTimerCountdownNormalFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_namedTimerCountdownNormalFont) },
- { "NamedTimerCountdownReadyFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_namedTimerCountdownReadyFont) },
- { "DrawableCaptionFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_drawableCaptionFont) },
- { "DefaultWindowFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_defaultWindowFont) },
- { "DefaultDisplayStringFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_defaultDisplayStringFont) },
- { "TooltipFontName", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_tooltipFontName) },
- { "NativeDebugDisplay", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_nativeDebugDisplay) },
- { "DrawGroupInfoFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_drawGroupInfoFont) },
- { "CreditsTitleFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_creditsTitleFont) },
- { "CreditsMinorTitleFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_creditsPositionFont) },
- { "CreditsNormalFont", GlobalLanguage::parseFontDesc, nullptr, offsetof( GlobalLanguage, m_creditsNormalFont) },
-
- { nullptr, nullptr, nullptr, 0 }
-};
-
-//-----------------------------------------------------------------------------
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-void INI::parseLanguageDefinition( INI *ini )
-{
- if( !TheGlobalLanguageData )
- {
- DEBUG_ASSERTCRASH(TheGlobalLanguageData, ("INI::parseLanguageDefinition - TheGlobalLanguage Data is not around, please create it before trying to parse the ini file."));
- return;
- }
- // parse the ini weapon definition
- ini->initFromINI( TheGlobalLanguageData, TheGlobalLanguageDataFieldParseTable );
-}
-
-GlobalLanguage::GlobalLanguage()
-{
- m_unicodeFontName.clear();
- m_unicodeFontFileName.clear();
- m_unicodeFontName.clear();
- m_militaryCaptionSpeed = 0;
- m_useHardWrap = FALSE;
- m_resolutionFontSizeAdjustment = 0.7f;
- m_resolutionFontSizeMethod = ResolutionFontSizeMethod_Default;
-
- m_userResolutionFontSizeAdjustment = -1.0f;
-}
-
-GlobalLanguage::~GlobalLanguage()
-{
- StringListIt it = m_localFonts.begin();
- while( it != m_localFonts.end())
- {
- AsciiString font = *it;
- RemoveFontResource(font.str());
- //SendMessage( HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
- ++it;
- }
-}
-
-void GlobalLanguage::init( void )
-{
- {
- AsciiString fname;
- fname.format("Data\\%s\\Language", GetRegistryLanguage().str());
-
- INI ini;
- ini.loadFileDirectory( fname, INI_LOAD_OVERWRITE, nullptr );
- }
-
- StringListIt it = m_localFonts.begin();
- while( it != m_localFonts.end())
- {
- AsciiString font = *it;
- if(AddFontResource(font.str()) == 0)
- {
- DEBUG_ASSERTCRASH(FALSE,("GlobalLanguage::init Failed to add font %s", font.str()));
- }
- else
- {
- //SendMessage( HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
- }
- ++it;
- }
-
- // override values with user preferences
- OptionPreferences optionPref;
- m_userResolutionFontSizeAdjustment = optionPref.getResolutionFontAdjustment();
-
-}
-void GlobalLanguage::reset( void ) {}
-
-
-void GlobalLanguage::parseFontDesc(INI *ini, void *instance, void *store, const void* userData)
-{
- FontDesc *fontDesc = (FontDesc *)store;
- fontDesc->name = ini->getNextQuotedAsciiString();
- fontDesc->size = ini->scanInt(ini->getNextToken());
- fontDesc->bold = ini->scanBool(ini->getNextToken());
-}
-
-void GlobalLanguage::parseFontFileName( INI *ini, void * instance, void *store, const void* userData )
-{
- GlobalLanguage *monkey = (GlobalLanguage *)instance;
- AsciiString asciiString = ini->getNextAsciiString();
- monkey->m_localFonts.push_front(asciiString);
-}
-
-float GlobalLanguage::getResolutionFontSizeAdjustment( void ) const
-{
- if (m_userResolutionFontSizeAdjustment >= 0.0f)
- return m_userResolutionFontSizeAdjustment;
- else
- return m_resolutionFontSizeAdjustment;
-}
-
-Int GlobalLanguage::adjustFontSize(Int theFontSize)
-{
- // TheSuperHackers @todo This function is called very often.
- // Therefore cache the adjustFactor on resolution change to not recompute it on every call.
- Real adjustFactor;
-
- switch (m_resolutionFontSizeMethod)
- {
- default:
- case ResolutionFontSizeMethod_Classic:
- {
- // TheSuperHackers @info The original font scaling for this game.
- // Useful for not breaking legacy Addons and Mods. Scales poorly with large resolutions.
- adjustFactor = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
- if (adjustFactor > 2.0f)
- adjustFactor = 2.0f;
- break;
- }
- case ResolutionFontSizeMethod_ClassicNoCeiling:
- {
- // TheSuperHackers @feature The original font scaling, but without ceiling.
- // Useful for not changing the original look of the game. Scales alright with large resolutions.
- adjustFactor = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
- break;
- }
- case ResolutionFontSizeMethod_Strict:
- {
- // TheSuperHackers @feature The strict method scales fonts based on the smallest screen
- // dimension so they scale independent of aspect ratio.
- const Real wScale = TheDisplay->getWidth() / (Real)DEFAULT_DISPLAY_WIDTH;
- const Real hScale = TheDisplay->getHeight() / (Real)DEFAULT_DISPLAY_HEIGHT;
- adjustFactor = min(wScale, hScale);
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
- break;
- }
- case ResolutionFontSizeMethod_Balanced:
- {
- // TheSuperHackers @feature The balanced method evenly weighs the display width and height
- // for a balanced rescale on non 4:3 resolutions. The aspect ratio scaling is clamped to
- // prevent oversizing.
- constexpr const Real maxAspect = 1.8f;
- constexpr const Real minAspect = 1.0f;
- Real w = TheDisplay->getWidth();
- Real h = TheDisplay->getHeight();
- const Real aspect = w / h;
- Real wScale = w / (Real)DEFAULT_DISPLAY_WIDTH;
- Real hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
-
- if (aspect > maxAspect)
- {
- // Recompute width at max aspect
- w = maxAspect * h;
- wScale = w / (Real)DEFAULT_DISPLAY_WIDTH;
- }
- else if (aspect < minAspect)
- {
- // Recompute height at min aspect
- h = minAspect * w;
- hScale = h / (Real)DEFAULT_DISPLAY_HEIGHT;
- }
- adjustFactor = (wScale + hScale) * 0.5f;
- adjustFactor = 1.0f + (adjustFactor - 1.0f) * getResolutionFontSizeAdjustment();
- break;
- }
- }
-
- if (adjustFactor < 1.0f)
- adjustFactor = 1.0f;
- Int pointSize = REAL_TO_INT_FLOOR(theFontSize*adjustFactor);
- return pointSize;
-}
-
-void GlobalLanguage::parseCustomDefinition()
-{
- if (addon::HasFullviewportDat())
- {
- // TheSuperHackers @tweak xezon 19/08/2025 Force the classic font size adjustment for the old
- // 'Control Bar Pro' Addons because they use manual font upscaling in higher resolution packages.
- m_resolutionFontSizeMethod = ResolutionFontSizeMethod_Classic;
- }
-}
-
-FontDesc::FontDesc(void)
-{
- name = "Arial Unicode MS"; ///.
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: GraphDraw.cpp ////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Electronic Arts Pacific.
-//
-// Confidential Information
-// Copyright (C) 2002 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// created: Aug 2002
-//
-// Filename: GraphDraw.cpp
-//
-// author: John McDonald
-//
-// purpose: Contains the functions to queue up and display a single graph for
-// each frame
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h"
-#include "GameClient/GraphDraw.h"
-
-#include "GameClient/Display.h"
-#include "GameClient/DisplayString.h"
-#include "GameClient/DisplayStringManager.h"
-
-#ifdef PERF_TIMERS
-
-//-------------------------------------------------------------------------------------------------
-GraphDraw::GraphDraw()
-{
- for (Int i = 0; i < MAX_GRAPH_VALUES; ++i) {
- m_displayStrings[i] = TheDisplayStringManager->newDisplayString();
- m_displayStrings[i]->setFont(TheFontLibrary->getFont("Courier", 10, false));
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-GraphDraw::~GraphDraw()
-{
- for (Int i = 0; i < MAX_GRAPH_VALUES; ++i) {
- TheDisplayStringManager->freeDisplayString(m_displayStrings[i]);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-void GraphDraw::addEntry(AsciiString str, Real val)
-{
- m_graphEntries.push_back(std::make_pair(str, val));
-}
-
-//-------------------------------------------------------------------------------------------------
-void GraphDraw::render()
-{
- Int width = TheDisplay->getWidth();
-
- // divide the width by two because we're going to use the left half of the screen for labels.
- //width /= 2;
-
- // give more to bars than labels. (srj)
- Int start = width * 0.33f;
- width -= start;
-
- Int height = TheDisplay->getHeight();
-
- Int totalCount = m_graphEntries.size();
- DEBUG_ASSERTCRASH(totalCount < MAX_GRAPH_VALUES, ("MAX_GRAPH_VALUES must be increased, not all labels will appear (max %d, cur %d).",MAX_GRAPH_VALUES,totalCount));
- DEBUG_ASSERTCRASH(BAR_HEIGHT * totalCount < height, ("BAR_HEIGHT must be reduced, as bars are being drawn off-screen."));
- VecGraphEntriesIt it;
-
- Int count = 0;
- for (it = m_graphEntries.begin(); it != m_graphEntries.end(); ++it) {
-
- if (count < MAX_GRAPH_VALUES) {
- // draw the label.
- UnicodeString uniStr;
- uniStr.translate(it->first);
-
- m_displayStrings[count]->setText(uniStr);
- m_displayStrings[count]->draw(5, count * BAR_HEIGHT, 0xFFFFFFFF, 0x00000000, 1, 1);
- }
-
- TheDisplay->drawFillRect(start, count * BAR_HEIGHT - (BAR_SPACE / 2), it->second / 100000.0f * width, BAR_HEIGHT - BAR_SPACE, 0x7FFFFFFF);
-
- ++count;
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-void GraphDraw::clear()
-{
- m_graphEntries.clear();
-}
-
-GraphDraw *TheGraphDraw = nullptr;
-
-#endif /* PERF_TIMERS */
diff --git a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp
index d9f53bbcb01..4a90702f645 100644
--- a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp
@@ -3111,7 +3111,7 @@ void InGameUI::setGUICommand( const CommandButton *command )
if( BitIsSet( command->getOptions(), COMMAND_OPTION_NEED_TARGET ) == FALSE )
{
- DEBUG_ASSERTCRASH( 0, ("setGUICommand: Command '%s' does not need additional user interaction",
+ DEBUG_CRASH( ("setGUICommand: Command '%s' does not need additional user interaction",
command->getName().str()) );
m_pendingGUICommand = nullptr;
m_mouseMode = MOUSEMODE_DEFAULT;
@@ -5668,7 +5668,7 @@ void InGameUI::selectNextIdleWorker( void )
if(m_idleWorkers[index].empty())
{
- DEBUG_ASSERTCRASH(FALSE, ("InGameUI::selectNextIdleWorker We're trying to select a worker when our list is empty for player %ls", player->getPlayerDisplayName().str()));
+ DEBUG_CRASH(("InGameUI::selectNextIdleWorker We're trying to select a worker when our list is empty for player %ls", player->getPlayerDisplayName().str()));
return;
}
Object *selectThisObject = nullptr;
diff --git a/Generals/Code/GameEngine/Source/GameClient/Input/Keyboard.cpp b/Generals/Code/GameEngine/Source/GameClient/Input/Keyboard.cpp
deleted file mode 100644
index e59437e8e4a..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/Input/Keyboard.cpp
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Keyboard.cpp /////////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, June 2001
-// Desc: Basic keyboard
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/Language.h"
-#include "Common/GameEngine.h"
-#include "Common/MessageStream.h"
-#include "GameClient/Keyboard.h"
-#include "GameClient/KeyDefs.h"
-
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
-Keyboard *TheKeyboard = nullptr;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** Given the state of the device, create messages from the input and
- * place them on the message stream */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::createStreamMessages( void )
-{
-
- // sanity
- if( TheMessageStream == nullptr )
- return;
-
- KeyboardIO *key = getFirstKey();
- GameMessage *msg = nullptr;
- while( key->key != KEY_NONE )
- {
-
- // add message to stream
- if( BitIsSet( key->state, KEY_STATE_DOWN ) )
- {
-
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_KEY_DOWN );
- DEBUG_ASSERTCRASH( msg, ("Unable to append key down message to stream") );
-
- }
- else if( BitIsSet( key->state, KEY_STATE_UP ) )
- {
-
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_KEY_UP );
- DEBUG_ASSERTCRASH( msg, ("Unable to append key up message to stream") );
-
- }
- else
- {
-
- DEBUG_CRASH(( "Unknown key state when creating msg stream" ));
-
- }
-
- // fill out message arguments
- if( msg )
- {
- msg->appendIntegerArgument( key->key );
- msg->appendIntegerArgument( key->state );
- }
-
- // next key please
- key->setUsed();
- key++;
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** update all our key state data */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::updateKeys( void )
-{
- Int index = 0;
-
- // get latest keys
- do
- {
- do
- {
-
- // get a single key
- getKey( &m_keys[ index ] );
-
- //
- // if we get back that our device was lost, we haven't been paying
- // attention to the keyboard, lets start over now, we only need to
- // do this reset once in this loop though just to be efficient
- //
- if( m_keys[ index ].key == KEY_LOST)
- {
-
- resetKeys();
- index = 0;
-
- }
-
- }
- while( m_keys[ index ].key == KEY_LOST );
- }
- while( m_keys[ index++ ].key != KEY_NONE );
-
- // update keyboard status array
- index = 0;
- while( m_keys[ index ].key != KEY_NONE )
- {
-
- /** @todo -- if we don't have focus, we could destroy all the keys retrieved
- here so that we don't process anything */
-
- m_keyStatus[ m_keys[ index ].key ].state = m_keys[ index ].state;
- m_keyStatus[ m_keys[ index ].key ].status = m_keys[ index ].status;
-
- // Update key down time for new key presses
- if( BitIsSet( m_keys[ index ].state, KEY_STATE_DOWN ) )
- {
- m_keyStatus[ m_keys[ index ].key ].keyDownTimeMsec = m_keys[ index ].keyDownTimeMsec;
- }
-
- // prevent ALT-TAB from causing a TAB event
- if( m_keys[ index ].key == KEY_TAB )
- {
- if( BitIsSet( m_keyStatus[ KEY_LALT ].state, KEY_STATE_DOWN ) ||
- BitIsSet( m_keyStatus[ KEY_RALT ].state, KEY_STATE_DOWN ) )
- {
- m_keys[index].status = KeyboardIO::STATUS_USED;
- }
- }
- else if( m_keys[ index ].key == KEY_CAPS ||
- m_keys[ index ].key == KEY_LCTRL ||
- m_keys[ index ].key == KEY_RCTRL ||
- m_keys[ index ].key == KEY_LSHIFT ||
- m_keys[ index ].key == KEY_RSHIFT ||
- m_keys[ index ].key == KEY_LALT ||
- m_keys[ index ].key == KEY_RALT )
-
- {
-
- //
- // this keeps our internal key state accurate event though we don't
- // use the returned translation ... kinda weird I think
- //
- translateKey( m_keys[ index ].key );
-
- }
-
- index++;
-
- }
-
- // check for key repeats
- checkKeyRepeat();
-
- if( m_modifiers )
- {
- index = 0;
- while( m_keys[ index ].key != KEY_NONE )
- {
-
- // set in the modifier data into the already existing up/down state
- BitSet( m_keys[ index ].state, m_modifiers );
-
- // next key
- index++;
-
- }
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** check key repeat timing, TRUE is returned if repeat is occurring */
-//-------------------------------------------------------------------------------------------------
-Bool Keyboard::checkKeyRepeat( void )
-{
- Bool retVal = FALSE;
- Int index = 0;
- Int key;
-
- /** @todo we shouldn't think about repeating any keys while we
- don't have the focus */
-// if( currentFocus == FOCUS_OUT )
-// return FALSE;
-
- // Find end of real keys for this frame
- while( m_keys[ index ].key != KEY_NONE )
- index++;
-
- // Scan Keyboard status array for first key down
- // long enough to repeat
- for( key = 0; key < ARRAY_SIZE(m_keyStatus); key++ )
- {
-
- if( BitIsSet( m_keyStatus[ key ].state, KEY_STATE_DOWN ) )
- {
-
- const UnsignedInt now = timeGetTime();
- const UnsignedInt keyDownTime = m_keyStatus[ key ].keyDownTimeMsec;
-
- // Unsigned subtraction handles wraparound correctly
- const UnsignedInt elapsedMsec = now - keyDownTime;
-
- if( elapsedMsec > Keyboard::KEY_REPEAT_DELAY_MSEC )
- {
- // Add key to this frame
- m_keys[ index ].key = (UnsignedByte)key;
- m_keys[ index ].state = KEY_STATE_DOWN | KEY_STATE_AUTOREPEAT; // note: not a bitset; this is an assignment
- m_keys[ index ].status = KeyboardIO::STATUS_UNUSED;
-
- // Set End Flag
- m_keys[ ++index ].key = KEY_NONE;
-
- // Set all keys as new to prevent multiple keys repeating
- for( index = 0; index< NUM_KEYS; index++ )
- m_keyStatus[ index ].keyDownTimeMsec = now;
-
- // Set repeated key so it will repeat again after the interval
- m_keyStatus[ key ].keyDownTimeMsec = now - (Keyboard::KEY_REPEAT_DELAY_MSEC + Keyboard::KEY_REPEAT_INTERVAL_MSEC);
-
- retVal = TRUE;
- break; // exit for key
-
- }
-
- }
-
- }
-
- return retVal;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Initialize the keyboard key-names array */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::initKeyNames( void )
-{
- Int i;
-
- #define _set_keyname_(k,s,s2,z) (m_keyNames[z].stdKey = k, m_keyNames[z].shifted = s, m_keyNames[z].shifted2 = s2)
-
- /*
- * Initialize the keyboard key-names array.
- */
- for( i = 0; i < ARRAY_SIZE(m_keyNames); i++ )
- {
-
- m_keyNames[ i ].stdKey = L'\0';
- m_keyNames[ i ].shifted = L'\0';
- m_keyNames[ i ].shifted2 = L'\0';
-
- }
-
- m_shift2Key = KEY_NONE;
-
- // generic to all languages
- _set_keyname_(L'\0', L'\0', L'\0', KEY_UP );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_DOWN );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_LEFT );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_RIGHT );
-
- _set_keyname_(L'\0', L'\0', L'\0', KEY_HOME );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_END );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_PGUP );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_PGDN );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_INS );
- _set_keyname_(L'\b', L'\b', L'\0', KEY_DEL );
-
- _set_keyname_(L'\b', L'\b', L'\0', KEY_BACKSPACE );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_ESC );
- _set_keyname_(L'\t', L'\t', L'\0', KEY_TAB );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_CAPS );
- _set_keyname_(L'\n', L'\n', L'\0', KEY_ENTER );
-
- _set_keyname_(L'\0', L'\0', L'\0', KEY_RALT );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_RCTRL );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_RSHIFT );
-
- _set_keyname_(L'\0', L'\0', L'\0', KEY_LALT );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_LCTRL );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_LSHIFT );
-
- _set_keyname_(L'\0', L'\0', L'\0', KEY_NUM );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_SCROLL );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_SYSREQ );
-
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F1 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F2 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F3 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F4 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F5 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F6 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F7 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F8 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F9 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F10 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F11 );
- _set_keyname_(L'\0', L'\0', L'\0', KEY_F12 );
-
- _set_keyname_(L'1', L'1', L'\0', KEY_KP1 );
- _set_keyname_(L'2', L'2', L'\0', KEY_KP2 );
- _set_keyname_(L'3', L'3', L'\0', KEY_KP3 );
- _set_keyname_(L'4', L'4', L'\0', KEY_KP4 );
- _set_keyname_(L'5', L'5', L'\0', KEY_KP5 );
- _set_keyname_(L'6', L'6', L'\0', KEY_KP6 );
- _set_keyname_(L'7', L'7', L'\0', KEY_KP7 );
- _set_keyname_(L'8', L'8', L'\0', KEY_KP8 );
- _set_keyname_(L'9', L'9', L'\0', KEY_KP9 );
- _set_keyname_(L'0', L'0', L'\0', KEY_KP0 );
-
- _set_keyname_(L' ', L' ', L'\0', KEY_SPACE );
-
- HKL kLayout = GetKeyboardLayout(0);
-
- Int low = (UnsignedInt)kLayout & 0xFFFF;
- LanguageID currentLanguage = OurLanguage;
- if(low == 0x040c
- || low == 0x080c
- || low == 0x0c0c
- || low == 0x100c
- || low == 0x140c)
- currentLanguage = LANGUAGE_ID_FRENCH;
-
- switch( currentLanguage )
- {
- case LANGUAGE_ID_US:
- case LANGUAGE_ID_JAPANESE:
- case LANGUAGE_ID_KOREAN:
- case LANGUAGE_ID_JABBER:
- case LANGUAGE_ID_UNKNOWN:
- case LANGUAGE_ID_SPANISH: // not localized
- _set_keyname_(L'-', L'-', L'\0', KEY_KPMINUS );
- _set_keyname_(L'+', L'+', L'\0', KEY_KPPLUS );
- _set_keyname_(L'\n', L'\n', L'\0', KEY_KPENTER );
- _set_keyname_(L'/', L'/', L'\0', KEY_KPSLASH );
- _set_keyname_(L'.', L'.', L'\0', KEY_KPDEL );
- _set_keyname_(L'*', L'*', L'\0', KEY_KPSTAR );
-
- _set_keyname_(L'a', L'A', L'\0', KEY_A );
- _set_keyname_(L'b', L'B', L'\0', KEY_B );
- _set_keyname_(L'c', L'C', L'\0', KEY_C );
- _set_keyname_(L'd', L'D', L'\0', KEY_D );
- _set_keyname_(L'e', L'E', L'\0', KEY_E );
- _set_keyname_(L'f', L'F', L'\0', KEY_F );
- _set_keyname_(L'g', L'G', L'\0', KEY_G );
- _set_keyname_(L'h', L'H', L'\0', KEY_H );
- _set_keyname_(L'i', L'I', L'\0', KEY_I );
- _set_keyname_(L'j', L'J', L'\0', KEY_J );
- _set_keyname_(L'k', L'K', L'\0', KEY_K );
- _set_keyname_(L'l', L'L', L'\0', KEY_L );
- _set_keyname_(L'm', L'M', L'\0', KEY_M );
- _set_keyname_(L'n', L'N', L'\0', KEY_N );
- _set_keyname_(L'o', L'O', L'\0', KEY_O );
- _set_keyname_(L'p', L'P', L'\0', KEY_P );
- _set_keyname_(L'q', L'Q', L'\0', KEY_Q );
- _set_keyname_(L'r', L'R', L'\0', KEY_R );
- _set_keyname_(L's', L'S', L'\0', KEY_S );
- _set_keyname_(L't', L'T', L'\0', KEY_T );
- _set_keyname_(L'u', L'U', L'\0', KEY_U );
- _set_keyname_(L'v', L'V', L'\0', KEY_V );
- _set_keyname_(L'w', L'W', L'\0', KEY_W );
- _set_keyname_(L'x', L'X', L'\0', KEY_X );
- _set_keyname_(L'y', L'Y', L'\0', KEY_Y );
- _set_keyname_(L'z', L'Z', L'\0', KEY_Z );
-
- _set_keyname_(L'1', L'!', L'\0', KEY_1 );
- _set_keyname_(L'2', L'@', L'\0', KEY_2 );
- _set_keyname_(L'3', L'#', L'\0', KEY_3 );
- _set_keyname_(L'4', L'$', L'\0', KEY_4 );
- _set_keyname_(L'5', L'%', L'\0', KEY_5 );
- _set_keyname_(L'6', L'^', L'\0', KEY_6 );
- _set_keyname_(L'7', L'&', L'\0', KEY_7 );
- _set_keyname_(L'8', L'*', L'\0', KEY_8 );
- _set_keyname_(L'9', L'(', L'\0', KEY_9 );
- _set_keyname_(L'0', L')', L'\0', KEY_0 );
-
- _set_keyname_(L',', L'<', L'\0', KEY_COMMA );
- _set_keyname_(L'.', L'>', L'\0', KEY_PERIOD );
- _set_keyname_(L'/', L'?', L'\0', KEY_SLASH );
-
- _set_keyname_(L'[', L'{', L'\0', KEY_LBRACKET );
- _set_keyname_(L']', L'}', L'\0', KEY_RBRACKET );
-
- _set_keyname_(L';', L':', L'\0', KEY_SEMICOLON );
- _set_keyname_(L'\'', L'\"', L'\0', KEY_APOSTROPHE );
- _set_keyname_(L'`', L'~', L'\0', KEY_TICK );
- _set_keyname_(L'\\', L'|', L'\0', KEY_BACKSLASH );
-
- _set_keyname_(L'-', L'_', L'\0', KEY_MINUS );
- _set_keyname_(L'=', L'+', L'\0', KEY_EQUAL );
-
- break;
-
- case LANGUAGE_ID_UK:
- _set_keyname_(L'-', L'-', L'\0', KEY_KPMINUS );
- _set_keyname_(L'+', L'+', L'\0', KEY_KPPLUS );
- _set_keyname_(L'\n', L'\n', L'\0', KEY_KPENTER );
- _set_keyname_(L'/', L'/', L'\0', KEY_KPSLASH );
- _set_keyname_(L'.', L'.', L'\0', KEY_KPDEL );
- _set_keyname_(L'*', L'*', L'\0', KEY_KPSTAR );
-
- _set_keyname_(L'a', L'A', L'\0', KEY_A );
- _set_keyname_(L'b', L'B', L'\0', KEY_B );
- _set_keyname_(L'c', L'C', L'\0', KEY_C );
- _set_keyname_(L'd', L'D', L'\0', KEY_D );
- _set_keyname_(L'e', L'E', L'\0', KEY_E );
- _set_keyname_(L'f', L'F', L'\0', KEY_F );
- _set_keyname_(L'g', L'G', L'\0', KEY_G );
- _set_keyname_(L'h', L'H', L'\0', KEY_H );
- _set_keyname_(L'i', L'I', L'\0', KEY_I );
- _set_keyname_(L'j', L'J', L'\0', KEY_J );
- _set_keyname_(L'k', L'K', L'\0', KEY_K );
- _set_keyname_(L'l', L'L', L'\0', KEY_L );
- _set_keyname_(L'm', L'M', L'\0', KEY_M );
- _set_keyname_(L'n', L'N', L'\0', KEY_N );
- _set_keyname_(L'o', L'O', L'\0', KEY_O );
- _set_keyname_(L'p', L'P', L'\0', KEY_P );
- _set_keyname_(L'q', L'Q', L'\0', KEY_Q );
- _set_keyname_(L'r', L'R', L'\0', KEY_R );
- _set_keyname_(L's', L'S', L'\0', KEY_S );
- _set_keyname_(L't', L'T', L'\0', KEY_T );
- _set_keyname_(L'u', L'U', L'\0', KEY_U );
- _set_keyname_(L'v', L'V', L'\0', KEY_V );
- _set_keyname_(L'w', L'W', L'\0', KEY_W );
- _set_keyname_(L'x', L'X', L'\0', KEY_X );
- _set_keyname_(L'y', L'Y', L'\0', KEY_Y );
- _set_keyname_(L'z', L'Z', L'\0', KEY_Z );
-
- _set_keyname_(L'1', L'!', L'\0', KEY_1 );
- _set_keyname_(L'2', L'\"', L'\0', KEY_2 );
- _set_keyname_(L'3', 0x00A3, L'\0', KEY_3 ); //£ GBP SIGN
- _set_keyname_(L'4', L'$', L'\x20ac', KEY_4 ); // € EUR SIGN
- _set_keyname_(L'5', L'%', L'\0', KEY_5 );
- _set_keyname_(L'6', L'^', L'\0', KEY_6 );
- _set_keyname_(L'7', L'&', L'\0', KEY_7 );
- _set_keyname_(L'8', L'*', L'\0', KEY_8 );
- _set_keyname_(L'9', L'(', L'\0', KEY_9 );
- _set_keyname_(L'0', L')', L'\0', KEY_0 );
-
- _set_keyname_(L',', L'<', L'\0', KEY_COMMA );
- _set_keyname_(L'.', L'>', L'\0', KEY_PERIOD );
- _set_keyname_(L'/', L'?', L'\0', KEY_SLASH );
-
- _set_keyname_(L'[', L'{', L'\0', KEY_LBRACKET );
- _set_keyname_(L']', L'}', L'\0', KEY_RBRACKET );
-
- _set_keyname_(L';', L':', L'\0', KEY_SEMICOLON );
- _set_keyname_(L'\'', L'@', L'\0', KEY_APOSTROPHE );
- _set_keyname_(L'`', 0x00AC, 0x00A6, KEY_TICK ); //¬¦ (not, broken bar)
- _set_keyname_(L'#', L'~', L'\0', KEY_BACKSLASH );
-
- _set_keyname_(L'-', L'_', L'\0', KEY_MINUS );
- _set_keyname_(L'=', L'+', L'\0', KEY_EQUAL );
-
- _set_keyname_(L'\\', L'|', L'\0', KEY_102 );
-
- m_shift2Key = KEY_RALT;
- break;
-
- case LANGUAGE_ID_GERMAN:
- _set_keyname_(L'-', L'-', L'\0', KEY_KPMINUS );
- _set_keyname_(L'+', L'+', L'\0', KEY_KPPLUS );
- _set_keyname_(L'\n', L'\n', L'\0', KEY_KPENTER );
- _set_keyname_(L'/', L'/', L'\0', KEY_KPSLASH );
- _set_keyname_(L',', L',', L'\0', KEY_KPDEL );
- _set_keyname_(L'*', L'*', L'\0', KEY_KPSTAR );
-
- _set_keyname_(L'a', L'A', L'\0', KEY_A );
- _set_keyname_(L'b', L'B', L'\0', KEY_B );
- _set_keyname_(L'c', L'C', L'\0', KEY_C );
- _set_keyname_(L'd', L'D', L'\0', KEY_D );
- _set_keyname_(L'e', L'E', L'\0', KEY_E );
- _set_keyname_(L'f', L'F', L'\0', KEY_F );
- _set_keyname_(L'g', L'G', L'\0', KEY_G );
- _set_keyname_(L'h', L'H', L'\0', KEY_H );
- _set_keyname_(L'i', L'I', L'\0', KEY_I );
- _set_keyname_(L'j', L'J', L'\0', KEY_J );
- _set_keyname_(L'k', L'K', L'\0', KEY_K );
- _set_keyname_(L'l', L'L', L'\0', KEY_L );
- _set_keyname_(L'm', L'M', 0x00B5, KEY_M ); //µ (micro)
- _set_keyname_(L'n', L'N', L'\0', KEY_N );
- _set_keyname_(L'o', L'O', L'\0', KEY_O );
- _set_keyname_(L'p', L'P', L'\0', KEY_P );
- _set_keyname_(L'q', L'Q', L'@', KEY_Q );
- _set_keyname_(L'r', L'R', L'\0', KEY_R );
- _set_keyname_(L's', L'S', L'\0', KEY_S );
- _set_keyname_(L't', L'T', L'\0', KEY_T );
- _set_keyname_(L'u', L'U', L'\0', KEY_U );
- _set_keyname_(L'v', L'V', L'\0', KEY_V );
- _set_keyname_(L'w', L'W', L'\0', KEY_W );
- _set_keyname_(L'x', L'X', L'\0', KEY_X );
- _set_keyname_(L'z', L'Z', L'\0', KEY_Y );
- _set_keyname_(L'y', L'Y', L'\0', KEY_Z );
-
- _set_keyname_(L'1', L'!', L'\0', KEY_1 );
- _set_keyname_(L'2', L'"', 0x00B2, KEY_2 ); //² (superscript 2)
- _set_keyname_(L'3', 0x00A7, 0x00B3, KEY_3 ); //§³ (section cubed)
- _set_keyname_(L'4', L'$', L'\0', KEY_4 );
- _set_keyname_(L'5', L'%', L'\0', KEY_5 );
- _set_keyname_(L'6', L'&', L'\0', KEY_6 );
- _set_keyname_(L'7', L'/', L'{', KEY_7 );
- _set_keyname_(L'8', L'(', L'[', KEY_8 );
- _set_keyname_(L'9', L')', L']', KEY_9 );
- _set_keyname_(L'0', L'=', L'}', KEY_0 );
-
- _set_keyname_(L',', L';', L'\0', KEY_COMMA );
- _set_keyname_(L'.', L':', L'\0', KEY_PERIOD );
- _set_keyname_(L'-', L'_', L'\0', KEY_SLASH );
-
- _set_keyname_(0x00FC, 0x00DC, L'\0', KEY_LBRACKET ); //üÜ (umlaut u)
- _set_keyname_(L'+', L'*', L'~', KEY_RBRACKET );
-
- _set_keyname_(0x00F6, 0x00D6, L'\0', KEY_SEMICOLON ); //öÖ (umlaut o)
- _set_keyname_(0x00E4, 0x00C4, L'\0', KEY_APOSTROPHE ); //äÄ (umlaut a)
- _set_keyname_(L'^', 0x00B0, L'\0', KEY_TICK ); //° (degree)
- _set_keyname_(L'#', L'\'', L'\0', KEY_BACKSLASH );
-
- _set_keyname_(0x00DF, L'?', L'\\', KEY_MINUS ); //ß (sharp s)
- _set_keyname_(0x00B4, L'`', L'\0', KEY_EQUAL ); //´ (acute)
-
- _set_keyname_(L'<', L'>', L'|', KEY_102 );
-
- m_shift2Key = KEY_RALT;
- break;
-
- case LANGUAGE_ID_FRENCH:
- _set_keyname_(L'-', L'-', L'\0', KEY_KPMINUS );
- _set_keyname_(L'+', L'+', L'\0', KEY_KPPLUS );
- _set_keyname_(L'\n', L'\n', L'\0', KEY_KPENTER );
- _set_keyname_(L'/', L'/', L'\0', KEY_KPSLASH );
- _set_keyname_(L'.', L'.', L'\0', KEY_KPDEL );
- _set_keyname_(L'*', L'*', L'\0', KEY_KPSTAR );
-
- _set_keyname_(L'q', L'Q', L'\0', KEY_A );
- _set_keyname_(L'b', L'B', L'\0', KEY_B );
- _set_keyname_(L'c', L'C', L'\0', KEY_C );
- _set_keyname_(L'd', L'D', L'\0', KEY_D );
- _set_keyname_(L'e', L'E', L'\0', KEY_E );
- _set_keyname_(L'f', L'F', L'\0', KEY_F );
- _set_keyname_(L'g', L'G', L'\0', KEY_G );
- _set_keyname_(L'h', L'H', L'\0', KEY_H );
- _set_keyname_(L'i', L'I', L'\0', KEY_I );
- _set_keyname_(L'j', L'J', L'\0', KEY_J );
- _set_keyname_(L'k', L'K', L'\0', KEY_K );
- _set_keyname_(L'l', L'L', L'\0', KEY_L );
- _set_keyname_(L',', L'?', L'\0', KEY_M );
- _set_keyname_(L'n', L'N', L'\0', KEY_N );
- _set_keyname_(L'o', L'O', L'\0', KEY_O );
- _set_keyname_(L'p', L'P', L'\0', KEY_P );
- _set_keyname_(L'a', L'A', L'\0', KEY_Q );
- _set_keyname_(L'r', L'R', L'\0', KEY_R );
- _set_keyname_(L's', L'S', L'\0', KEY_S );
- _set_keyname_(L't', L'T', L'\0', KEY_T );
- _set_keyname_(L'u', L'U', L'\0', KEY_U );
- _set_keyname_(L'v', L'V', L'\0', KEY_V );
- _set_keyname_(L'z', L'Z', L'\0', KEY_W );
- _set_keyname_(L'x', L'X', L'\0', KEY_X );
- _set_keyname_(L'y', L'Y', L'\0', KEY_Y );
- _set_keyname_(L'w', L'W', L'\0', KEY_Z );
-
- _set_keyname_(L'&', L'1', L'\0', KEY_1 );
- _set_keyname_(0x00E9, L'2', L'~', KEY_2 ); //é (acute)
- _set_keyname_(L'"', L'3', L'#', KEY_3 );
- _set_keyname_(L'\'', L'4', L'{', KEY_4 );
- _set_keyname_(L'(', L'5', L'[', KEY_5 );
- _set_keyname_(L'-', L'6', L'|', KEY_6 );
- _set_keyname_(0x00E8, L'7', L'`', KEY_7 ); //è (grave)
- _set_keyname_(L'_', L'8', L'\\', KEY_8 );
- _set_keyname_(0x00E7, L'9', L'\0', KEY_9 ); //ç (cedilla)
- _set_keyname_(0x00E0, L'0', L'@', KEY_0 ); //Ã (grave)
-
- _set_keyname_(L';', L'.', L'\0', KEY_COMMA );
- _set_keyname_(L':', L'/', L'\0', KEY_PERIOD );
- _set_keyname_(L'!', 0x00A7, L'\0', KEY_SLASH ); //§ (section)
-
- _set_keyname_(L'^', 0x00A8, L'\0', KEY_LBRACKET ); //¨ (diaeresis)
- _set_keyname_(L'$', 0x00A3, 0x00A4, KEY_RBRACKET ); //£¤ (pound currency)
-
- _set_keyname_(L'm', L'M', L'\0', KEY_SEMICOLON );
- _set_keyname_(0x00F9, L'%', L'\0', KEY_APOSTROPHE ); //ù (grave)
- _set_keyname_(0x00B2, L'\0', L'\0', KEY_TICK ); //² (superscript 2)
- _set_keyname_(L'*', 0x00B5, L'\0', KEY_BACKSLASH ); //µ (micro)
-
- _set_keyname_(L')', 0x00B0, L']', KEY_MINUS ); //° (degree)
- _set_keyname_(L'=', L'+', L'}', KEY_EQUAL );
-
- _set_keyname_(L'<', L'>', L'\0', KEY_102 );
-
- m_shift2Key = KEY_RALT;
- break;
-
- case LANGUAGE_ID_ITALIAN:
- _set_keyname_(L'-', L'-', L'\0', KEY_KPMINUS );
- _set_keyname_(L'+', L'+', L'\0', KEY_KPPLUS );
- _set_keyname_(L'\n', L'\n', L'\0', KEY_KPENTER );
- _set_keyname_(L'/', L'/', L'\0', KEY_KPSLASH );
- _set_keyname_(L'.', L'.', L'\0', KEY_KPDEL );
- _set_keyname_(L'*', L'*', L'\0', KEY_KPSTAR );
-
- _set_keyname_(L'a', L'A', L'\0', KEY_A );
- _set_keyname_(L'b', L'B', L'\0', KEY_B );
- _set_keyname_(L'c', L'C', L'\0', KEY_C );
- _set_keyname_(L'd', L'D', L'\0', KEY_D );
- _set_keyname_(L'e', L'E', L'\0', KEY_E );
- _set_keyname_(L'f', L'F', L'\0', KEY_F );
- _set_keyname_(L'g', L'G', L'\0', KEY_G );
- _set_keyname_(L'h', L'H', L'\0', KEY_H );
- _set_keyname_(L'i', L'I', L'\0', KEY_I );
- _set_keyname_(L'j', L'J', L'\0', KEY_J );
- _set_keyname_(L'k', L'K', L'\0', KEY_K );
- _set_keyname_(L'l', L'L', L'\0', KEY_L );
- _set_keyname_(L'm', L'M', L'\0', KEY_M );
- _set_keyname_(L'n', L'N', L'\0', KEY_N );
- _set_keyname_(L'o', L'O', L'\0', KEY_O );
- _set_keyname_(L'p', L'P', L'\0', KEY_P );
- _set_keyname_(L'q', L'Q', L'\0', KEY_Q );
- _set_keyname_(L'r', L'R', L'\0', KEY_R );
- _set_keyname_(L's', L'S', L'\0', KEY_S );
- _set_keyname_(L't', L'T', L'\0', KEY_T );
- _set_keyname_(L'u', L'U', L'\0', KEY_U );
- _set_keyname_(L'v', L'V', L'\0', KEY_V );
- _set_keyname_(L'w', L'W', L'\0', KEY_W );
- _set_keyname_(L'x', L'X', L'\0', KEY_X );
- _set_keyname_(L'y', L'Y', L'\0', KEY_Y );
- _set_keyname_(L'z', L'Z', L'\0', KEY_Z );
-
- _set_keyname_(L'1', L'!', L'\0', KEY_1 );
- _set_keyname_(L'2', L'"', L'\0', KEY_2 );
- _set_keyname_(L'3', 0x00A3, L'\0', KEY_3 ); //£ GBP SIGN
- _set_keyname_(L'4', L'$', L'\0', KEY_4 );
- _set_keyname_(L'5', L'%', L'\0', KEY_5 );
- _set_keyname_(L'6', L'&', L'\0', KEY_6 );
- _set_keyname_(L'7', L'/', L'\0', KEY_7 );
- _set_keyname_(L'8', L'(', L'\0', KEY_8 );
- _set_keyname_(L'9', L')', L'\0', KEY_9 );
- _set_keyname_(L'0', L'=', L'\0', KEY_0 );
-
- _set_keyname_(L',', L';', L'\0', KEY_COMMA );
- _set_keyname_(L'.', L':', L'\0', KEY_PERIOD );
- _set_keyname_(L'-', L'_', L'\0', KEY_SLASH );
-
- _set_keyname_(0x00E8, 0x00E9, L'[', KEY_LBRACKET ); //èé (grave acute)
- _set_keyname_(L'+', L'*', L']', KEY_RBRACKET );
-
- _set_keyname_(0x00F2, 0x00E7, L'@', KEY_SEMICOLON ); //òç (grave cedilla)
- _set_keyname_(0x00E0, 0x00B0, L'#', KEY_APOSTROPHE ); //à ° (grave degree)
- _set_keyname_(L'\\', L'|', L'\0', KEY_TICK );
- _set_keyname_(0x00F9, 0x00A7, L'\0', KEY_BACKSLASH ); //ù§ (grave section)
-
- _set_keyname_(L'\'', L'?', L'\0', KEY_MINUS );
- _set_keyname_(0x00EC, L'^', L'\0', KEY_EQUAL ); //ì (grave)
-
- _set_keyname_(L'<', L'>', L'\0', KEY_102 );
-
- m_shift2Key = KEY_RALT;
- break;
-
- }
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC PROTOTYPES //////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Keyboard::Keyboard( void )
-{
-
- memset( m_keys, 0, sizeof( m_keys ) );
- memset( m_keyStatus, 0, sizeof( m_keyStatus ) );
- m_modifiers = KEY_STATE_NONE;
- m_shift2Key = KEY_NONE;
-
- memset( m_keyNames, 0, sizeof( m_keyNames ) );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Keyboard::~Keyboard( void )
-{
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Initialize the keyboard */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::init( void )
-{
-
- // initialize the key names
- initKeyNames();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset keyboard system */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::reset( void )
-{
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Called once per frame to gather key data input */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::update( void )
-{
-
- // update the key data
- updateKeys();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset the state data for the keys, we likely want to do this when
- * we once again gain focus to our app from something like an alt tab */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::resetKeys( void )
-{
-
- // TheSuperHackers @fix Caball009 13/12/2025 Fix bug where game remains in waypoint mode
- // because the key up state for the alt key is not detected after alt tab.
- refreshAltKeys();
-
- memset( m_keys, 0, sizeof( m_keys ) );
- memset( m_keyStatus, 0, sizeof( m_keyStatus ) );
- m_modifiers = KEY_STATE_NONE;
- if( getCapsState() )
- {
- m_modifiers |= KEY_STATE_CAPSLOCK;
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-// Refresh the state of the alt keys, necessary after alt tab
-//-------------------------------------------------------------------------------------------------
-void Keyboard::refreshAltKeys() const
-{
- if (BitIsSet(m_keyStatus[KEY_LALT].state, KEY_STATE_DOWN))
- {
- GameMessage* msg = TheMessageStream->appendMessage(GameMessage::MSG_RAW_KEY_UP);
- msg->appendIntegerArgument(KEY_LALT);
- msg->appendIntegerArgument(KEY_STATE_UP);
- }
- if (BitIsSet(m_keyStatus[KEY_RALT].state, KEY_STATE_DOWN))
- {
- GameMessage* msg = TheMessageStream->appendMessage(GameMessage::MSG_RAW_KEY_UP);
- msg->appendIntegerArgument(KEY_RALT);
- msg->appendIntegerArgument(KEY_STATE_UP);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** get the first key in our current state of the keyboard */
-//-------------------------------------------------------------------------------------------------
-KeyboardIO *Keyboard::getFirstKey( void )
-{
- return &m_keys[ 0 ];
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-KeyboardIO *Keyboard::findKey( KeyDefType key, KeyboardIO::StatusType status )
-{
- for (KeyboardIO *io = getFirstKey(); io->key != KEY_NONE; ++io)
- {
- if (io->key == key && io->status == status)
- {
- return io;
- }
- }
- return nullptr;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** return the key status for the specified key */
-//-------------------------------------------------------------------------------------------------
-UnsignedByte Keyboard::getKeyStatusData( KeyDefType key )
-{
- return m_keyStatus[ key ].status;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Get the key state data as a Bool for the specified key */
-//-------------------------------------------------------------------------------------------------
-Bool Keyboard::getKeyStateBit( KeyDefType key, Int bit )
-{
- return (m_keyStatus[ key ].state & bit) ? 1 : 0;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** set the key status data */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::setKeyStatusData( KeyDefType key, KeyboardIO::StatusType data )
-{
- m_keyStatus[ key ].status = data;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** set the key state data */
-//-------------------------------------------------------------------------------------------------
-void Keyboard::setKeyStateData( KeyDefType key, UnsignedByte data )
-{
- m_keyStatus[ key ].state = data;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** This routine must be called with every character to
- * properly monitor the shift state. Takes a keycode as
- * input, and returns the UNICODE char representing the
- * character. */
-//-------------------------------------------------------------------------------------------------
-WideChar Keyboard::translateKey( WideChar keyCode )
-{
-
- if( keyCode > 0x00FF )
- return keyCode;
-
- UnsignedByte ubKeyCode = (UnsignedByte)keyCode;
- switch( ubKeyCode )
- {
-
- case KEY_CAPS:
- if( getKeyStatusData( KEY_CAPS ) == KeyboardIO::STATUS_UNUSED )
- {
- if( getKeyStateBit( KEY_CAPS, KEY_STATE_DOWN ) )
- {
- if( m_modifiers & KEY_STATE_CAPSLOCK )
- {
- // Toggle caplocks off
- m_modifiers &= ~KEY_STATE_CAPSLOCK;
- }
- else
- {
- // Toggle caplocks on
- m_modifiers |= KEY_STATE_CAPSLOCK;
- }
- }
-
- setKeyStatusData( KEY_CAPS, KeyboardIO::STATUS_USED );
- }
- return 0;
-
- case KEY_LSHIFT:
- if( getKeyStateBit( KEY_LSHIFT, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_LSHIFT;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_LSHIFT;
- }
- return 0;
-
- case KEY_RSHIFT:
- if( getKeyStateBit( KEY_RSHIFT, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_RSHIFT;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_RSHIFT;
- }
- return 0;
-
- case KEY_LCTRL:
- if( getKeyStateBit( KEY_LCTRL, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_LCONTROL;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_LCONTROL;
- }
- return 0;
-
- case KEY_RCTRL:
- if( getKeyStateBit( KEY_RCTRL, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_RCONTROL;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_RCONTROL;
- }
- return 0;
-
- case KEY_LALT:
- if( getKeyStateBit( KEY_LALT, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_LALT;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_LALT;
- }
- return 0;
-
- case KEY_RALT:
- if( getKeyStateBit( KEY_RALT, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_RALT;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_RALT;
- }
- return 0;
-
- default:
- if( ubKeyCode == m_shift2Key )
- {
- if( getKeyStateBit( m_shift2Key, KEY_STATE_DOWN ) )
- {
- m_modifiers |= KEY_STATE_SHIFT2;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_SHIFT2;
- }
- return 0;
- }
-
- if( m_modifiers & KEY_STATE_SHIFT2 )
- {
- return( m_keyNames[ ubKeyCode ].shifted2 );
- }
-
- if( isShift() || ( getCapsState() && iswalpha( m_keyNames[ ubKeyCode ].stdKey ) ) )
- {
- return( m_keyNames[ ubKeyCode ].shifted );
- }
-
- return( m_keyNames[ubKeyCode ].stdKey );
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** returns true if any shift state is pressed */
-//-------------------------------------------------------------------------------------------------
-Bool Keyboard::isShift()
-{
- if( m_modifiers & KEY_STATE_LSHIFT || m_modifiers & KEY_STATE_RSHIFT || m_modifiers & KEY_STATE_SHIFT2 )
- {
- return TRUE;
- }
- return FALSE;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** returns true if any control state is pressed */
-//-------------------------------------------------------------------------------------------------
-Bool Keyboard::isCtrl()
-{
- if( m_modifiers & KEY_STATE_LCONTROL || m_modifiers & KEY_STATE_RCONTROL )
- {
- return TRUE;
- }
- return FALSE;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** returns true if any shift state is pressed */
-//-------------------------------------------------------------------------------------------------
-Bool Keyboard::isAlt()
-{
- if( m_modifiers & KEY_STATE_LALT || m_modifiers & KEY_STATE_RALT )
- {
- return TRUE;
- }
- return FALSE;
-}
-
-
-WideChar Keyboard::getPrintableKey( KeyDefType key, Int state )
-{
- if((key < 0 || key >= ARRAY_SIZE(m_keyNames)) || ( state < 0 || state >= MAX_KEY_STATES))
- return L'\0';
- if(state == 0)
- return m_keyNames[key].stdKey;
- else if(state == 1)
- return m_keyNames[key].shifted;
- else
- return m_keyNames[key].shifted2;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/Input/Mouse.cpp b/Generals/Code/GameEngine/Source/GameClient/Input/Mouse.cpp
deleted file mode 100644
index 1ae52d75e0e..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/Input/Mouse.cpp
+++ /dev/null
@@ -1,1381 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Mouse.cpp ////////////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, June 2001
-// Desc: Basic mouse interactions
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/Debug.h"
-#include "Common/MessageStream.h"
-#include "Common/GameEngine.h"
-#include "Common/GlobalData.h"
-#include "Common/INI.h"
-#include "Common/UserPreferences.h"
-
-#include "GameClient/Display.h"
-#include "GameClient/DisplayStringManager.h"
-#include "GameClient/GameClient.h"
-#include "GameClient/GameText.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/InGameUI.h"
-#include "GameClient/Keyboard.h"
-#include "GameClient/Mouse.h"
-#include "GameClient/GlobalLanguage.h"
-
-#include "GameLogic/GameLogic.h"
-#include "GameLogic/ScriptEngine.h"
-
-
-// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
-Mouse *TheMouse = nullptr;
-
-const char *const Mouse::RedrawModeName[] = {
- "Mouse:Windows",
- "Mouse:W3D",
- "Mouse:Poly",
- "Mouse:DX8",
-};
-
-const char *const Mouse::CursorCaptureBlockReasonNames[] = {
- "CursorCaptureBlockReason_NoInit",
- "CursorCaptureBlockReason_Paused",
- "CursorCaptureBlockReason_Unfocused",
- "CursorCaptureBlockReason_CursorIsOutside",
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-static const FieldParse TheMouseCursorFieldParseTable[] =
-{
- { "CursorText", INI::parseAsciiString, nullptr, offsetof( CursorInfo, cursorText ) },
- { "CursorTextColor", INI::parseRGBAColorInt, nullptr, offsetof( CursorInfo, cursorTextColor ) },
- { "CursorTextDropColor", INI::parseRGBAColorInt, nullptr, offsetof( CursorInfo, cursorTextDropColor ) },
- { "W3DModel", INI::parseAsciiString, nullptr, offsetof( CursorInfo, W3DModelName ) },
- { "W3DAnim", INI::parseAsciiString, nullptr, offsetof( CursorInfo, W3DAnimName ) },
- { "W3DScale", INI::parseReal, nullptr, offsetof( CursorInfo, W3DScale ) },
- { "Loop", INI::parseBool, nullptr, offsetof( CursorInfo, loop ) },
- { "Image", INI::parseAsciiString, nullptr, offsetof( CursorInfo, imageName ) },
- { "Texture", INI::parseAsciiString, nullptr, offsetof( CursorInfo, textureName ) },
- { "HotSpot", INI::parseICoord2D, nullptr, offsetof( CursorInfo, hotSpotPosition ) },
- { "Frames", INI::parseInt, nullptr, offsetof( CursorInfo, numFrames ) },
- { "FPS", INI::parseReal, nullptr, offsetof( CursorInfo, fps)},
- { "Directions", INI::parseInt, nullptr, offsetof( CursorInfo, numDirections ) },
-};
-
-static const FieldParse TheMouseFieldParseTable[] =
-{
- { "TooltipFontName", INI::parseAsciiString,nullptr, offsetof( Mouse, m_tooltipFontName ) },
- { "TooltipFontSize", INI::parseInt, nullptr, offsetof( Mouse, m_tooltipFontSize ) },
- { "TooltipFontIsBold", INI::parseBool, nullptr, offsetof( Mouse, m_tooltipFontIsBold ) },
- { "TooltipAnimateBackground", INI::parseBool, nullptr, offsetof( Mouse, m_tooltipAnimateBackground ) },
- { "TooltipFillTime", INI::parseInt, nullptr, offsetof( Mouse, m_tooltipFillTime ) },
- { "TooltipDelayTime", INI::parseInt, nullptr, offsetof( Mouse, m_tooltipDelayTime ) },
- { "TooltipTextColor", INI::parseRGBAColorInt, nullptr, offsetof( Mouse, m_tooltipColorText ) },
- { "TooltipHighlightColor", INI::parseRGBAColorInt, nullptr, offsetof( Mouse, m_tooltipColorHighlight ) },
- { "TooltipShadowColor", INI::parseRGBAColorInt, nullptr, offsetof( Mouse, m_tooltipColorShadow ) },
- { "TooltipBackgroundColor", INI::parseRGBAColorInt, nullptr, offsetof( Mouse, m_tooltipColorBackground ) },
- { "TooltipBorderColor", INI::parseRGBAColorInt, nullptr, offsetof( Mouse, m_tooltipColorBorder ) },
- { "TooltipWidth", INI::parsePercentToReal,nullptr, offsetof( Mouse, m_tooltipWidth ) },
- { "CursorMode", INI::parseInt, nullptr, offsetof( Mouse, m_currentRedrawMode ) },
- { "UseTooltipAltTextColor", INI::parseBool, nullptr, offsetof( Mouse, m_useTooltipAltTextColor ) },
- { "UseTooltipAltBackColor", INI::parseBool, nullptr, offsetof( Mouse, m_useTooltipAltBackColor ) },
- { "AdjustTooltipAltColor", INI::parseBool, nullptr, offsetof( Mouse, m_adjustTooltipAltColor ) },
- { "OrthoCamera", INI::parseBool, nullptr, offsetof( Mouse, m_orthoCamera ) },
- { "OrthoZoom", INI::parseReal, nullptr, offsetof( Mouse, m_orthoZoom ) },
- { "DragTolerance", INI::parseUnsignedInt, nullptr, offsetof( Mouse, m_dragTolerance) },
- { "DragTolerance3D", INI::parseUnsignedInt, nullptr, offsetof( Mouse, m_dragTolerance3D) },
- { "DragToleranceMS", INI::parseUnsignedInt, nullptr, offsetof( Mouse, m_dragToleranceMS) },
-
-};
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** Move the mouse in either relative or absolute coords */
-//-------------------------------------------------------------------------------------------------
-void Mouse::moveMouse( Int x, Int y, Int relOrAbs )
-{
-
- if( relOrAbs == MOUSE_MOVE_RELATIVE )
- {
- m_currMouse.pos.x += x;
- m_currMouse.pos.y += y;
- }
- else
- {
- m_currMouse.pos.x = x;
- m_currMouse.pos.y = y;
- }
-
- if( m_currMouse.pos.x > m_maxX )
- m_currMouse.pos.x = m_maxX;
- else if( m_currMouse.pos.x < m_minX )
- m_currMouse.pos.x = m_minX;
-
- if( m_currMouse.pos.y > m_maxY )
- m_currMouse.pos.y = m_maxY;
- else if( m_currMouse.pos.y < m_minY )
- m_currMouse.pos.y = m_minY;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Get the current information for the mouse from the device */
-//-------------------------------------------------------------------------------------------------
-void Mouse::updateMouseData( )
-{
- static Bool busy = FALSE;
- Int index = 0;
- UnsignedByte result;
-
- // prevent reentrancy in the event we make this mouse multi-threaded
- if( busy == FALSE )
- {
-
- busy = TRUE;
-
- // Get latest mouse events from DirectX
- do
- {
- do
- {
- result = getMouseEvent( &m_mouseEvents[ index ], TRUE );
- }
- while( result == MOUSE_LOST );
- index++;
- }
- while( (result != MOUSE_NONE) &&
- (index < sizeof( m_mouseEvents ) / sizeof( MouseIO )) );
-
- busy = FALSE;
-
- }
-
- if( index > 0 )
- m_eventsThisFrame = index - 1;
- else
- m_eventsThisFrame = 0;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Combine mouse events into the main mouse variables */
-//-------------------------------------------------------------------------------------------------
-void Mouse::processMouseEvent( Int index )
-{
- Int movementType;
-
- m_currMouse.leftEvent = MOUSE_EVENT_NONE;
- m_currMouse.rightEvent = MOUSE_EVENT_NONE;
- m_currMouse.middleEvent = MOUSE_EVENT_NONE;
- m_currMouse.wheelPos = 0;
-
- // what type of movement commands are we setup for
- if( m_inputMovesAbsolute == TRUE )
- movementType = MOUSE_MOVE_ABSOLUTE;
- else
- movementType = MOUSE_MOVE_RELATIVE;
-
- // set the time of this event to the correct time
- m_currMouse.time = m_mouseEvents[ index ].time;
-
- if( index == 0 )
- checkForDrag();
-
- // add Mouse Position Changes to Master Position
- moveMouse( m_mouseEvents[ index ].pos.x,
- m_mouseEvents[ index ].pos.y,
- movementType );
-
- // Cumulate Wheel Adjustments
- m_currMouse.wheelPos += m_mouseEvents[ index ].wheelPos;
-
- // Check Left Mouse State
- if( m_mouseEvents[ index ].leftState != MBS_None )
- {
- if( m_currMouse.leftState != m_mouseEvents[ index ].leftState )
- {
- // State Change
- if( m_mouseEvents[ index ].leftState == MBS_Down )
- {
- // Mouse Down
- m_currMouse.leftEvent = GWM_LEFT_DOWN;
- m_currMouse.leftState = MBS_Down;
- }
- else if ( m_mouseEvents[ index ].leftState == MBS_DoubleClick )
- {
- // Mouse Double Click
- m_currMouse.leftEvent = GWM_LEFT_DOUBLE_CLICK;
- m_currMouse.leftState = MBS_DoubleClick;
- }
- else
- {
- // Mouse Up
- m_currMouse.leftEvent = GWM_LEFT_UP;
- m_currMouse.leftState = MBS_Up;
- }
- }
- }
- else if( m_currMouse.leftState != MBS_Up &&
- ( (m_prevMouse.leftEvent == GWM_LEFT_DOWN) ||
- (m_prevMouse.leftEvent == GWM_LEFT_DRAG) ) )
- {
- m_currMouse.leftEvent = GWM_LEFT_DRAG;
- }
-
- // Check Right Mouse State
- if( m_mouseEvents[ index ].rightState != MBS_None )
- {
- if( m_currMouse.rightState != m_mouseEvents[ index ].rightState )
- {
- // State Change
- if( m_mouseEvents[ index ].rightState == MBS_Down )
- {
- // Mouse Down
- m_currMouse.rightEvent = GWM_RIGHT_DOWN;
- m_currMouse.rightState = MBS_Down;
- }
- else if( m_mouseEvents[ index ].rightState == MBS_DoubleClick )
- {
- // Mouse Double Click
- m_currMouse.rightEvent = GWM_RIGHT_DOUBLE_CLICK;
- m_currMouse.rightState = MBS_DoubleClick;
- }
- else
- {
- // Mouse Up
- m_currMouse.rightEvent = GWM_RIGHT_UP;
- m_currMouse.rightState = MBS_Up;
- }
- }
- }
- else if( m_currMouse.rightState != MBS_Up &&
- ( (m_prevMouse.rightEvent == GWM_RIGHT_DOWN) ||
- (m_prevMouse.rightEvent == GWM_RIGHT_DRAG) ) )
- {
- m_currMouse.rightEvent = GWM_RIGHT_DRAG;
- }
-
- // Check Middle Mouse State
- if( m_mouseEvents[ index ].middleState != MBS_None )
- {
- if( m_currMouse.middleState != m_mouseEvents[index].middleState )
- {
- // State Change
- if( m_mouseEvents[index].middleState == MBS_Down )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DOWN;
- m_currMouse.middleState = MBS_Down;
- }
- else if( m_mouseEvents[index].middleState == MBS_DoubleClick )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DOUBLE_CLICK;
- m_currMouse.middleState = MBS_DoubleClick;
- }
- else
- {
- // Mouse Up
- m_currMouse.middleEvent = GWM_MIDDLE_UP;
- m_currMouse.middleState = MBS_Up;
- }
- }
- }
- else if( m_currMouse.middleState != MBS_Up &&
- ( (m_prevMouse.middleEvent == GWM_MIDDLE_DOWN) ||
- (m_prevMouse.middleEvent == GWM_MIDDLE_DRAG) ) )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DRAG;
- }
-
- m_currMouse.deltaPos.x = m_currMouse.pos.x - m_prevMouse.pos.x;
- m_currMouse.deltaPos.y = m_currMouse.pos.y - m_prevMouse.pos.y;
-// DEBUG_LOG(("Mouse dx %d, dy %d, index %d", m_currMouse.deltaPos.x, m_currMouse.deltaPos.y, index));
-// // check if mouse is still and flag tooltip
-// if( ((dx*dx) + (dy*dy)) < CURSOR_MOVE_TOL_SQ )
-// {
-// // cursor is still
-// //m_stillTime++;
-// Int delay = m_tooltipDelayTime;
-// if(m_tooltipDelay >= 0 )
-// delay = m_tooltipDelay;
-//
-// if( now - m_stillTime >= delay )
-// {
-// if (!m_displayTooltip)
-// {
-// m_highlightPos = 0;
-// m_highlightUpdateStart = timeGetTime();
-// }
-//
-// // display tooltip for current window
-// m_displayTooltip = TRUE;
-// }
-// }
-// else
-// {
-// // cursor moved
-// //m_stillTime = 0;
-// m_stillTime = now;
-// m_displayTooltip = FALSE;
-// }
-
-
- m_prevMouse = m_currMouse;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Check for mouse drag */
-//-------------------------------------------------------------------------------------------------
-void Mouse::checkForDrag( void )
-{
-
- if( m_currMouse.leftState &&
- ( (m_prevMouse.leftEvent == GWM_LEFT_DOWN) ||
- (m_prevMouse.leftEvent == GWM_LEFT_DRAG) ) )
- {
- m_currMouse.leftEvent = GWM_LEFT_DRAG;
- }
-
- if( m_currMouse.rightState &&
- ( (m_prevMouse.rightEvent == GWM_RIGHT_DOWN) ||
- (m_prevMouse.rightEvent == GWM_RIGHT_DRAG) ) )
- {
- m_currMouse.rightEvent = GWM_RIGHT_DRAG;
- }
-
- if( m_currMouse.middleState &&
- ( (m_prevMouse.middleEvent == GWM_MIDDLE_DOWN) ||
- (m_prevMouse.middleEvent == GWM_MIDDLE_DRAG) ) )
- {
- m_currMouse.middleEvent = GWM_MIDDLE_DRAG;
- }
-
-}
-
-
-//-------------------------------------------------------------------------------------------------
-/** Check for mouse click, using allowed drag forgiveness */
-//-------------------------------------------------------------------------------------------------
-Bool Mouse::isClick(const ICoord2D *anchor, const ICoord2D *dest, UnsignedInt previousMouseClick, UnsignedInt currentMouseClick)
-{
- ICoord2D delta;
- delta.x = anchor->x - dest->x;
- delta.y = anchor->y - dest->y;
-
-
- // if the mouse hasn't moved further than the tolerance distance
- // or the click took less than the tolerance duration
- if ( abs(delta.x) > m_dragTolerance
- || abs(delta.y) > m_dragTolerance
- || currentMouseClick - previousMouseClick > m_dragToleranceMS)
- {
- return FALSE;
- }
- return TRUE;
-}
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-CursorInfo::CursorInfo( void )
-{
-
- cursorName.clear();
- cursorText.clear();
- cursorTextColor.red = cursorTextColor.green = cursorTextColor.blue = 0;
- cursorTextDropColor.red = cursorTextDropColor.blue = cursorTextDropColor.green = 0;
-
- textureName.clear();
- imageName.clear();
- W3DModelName.clear();
- W3DAnimName.clear();
- W3DScale = 1.0f;
- loop = TRUE;
- //Assume hotspot is at the center of a 32x32 image.
- hotSpotPosition.x=16;
- hotSpotPosition.y=16;
- numFrames = 1; //assume no animation
- fps=20.0f;
- numDirections=1;
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Mouse::Mouse( void )
-{
- static_assert(ARRAY_SIZE(CursorCaptureBlockReasonNames) == CursorCaptureBlockReason_Count, "Incorrect array size");
- static_assert(ARRAY_SIZE(RedrawModeName) == RM_MAX, "Incorrect array size");
-
- // device info
- m_numButtons = 0;
- m_numAxes = 0;
- m_forceFeedback = FALSE;
-
- m_dragTolerance = 0;
- m_dragTolerance3D = 0;
- m_dragToleranceMS = 0;
- //m_tooltipString.clear(); // redundant
- m_displayTooltip = FALSE;
- m_tooltipDisplayString = nullptr;
- m_tooltipDelay = -1; // default value
- // initialize all the mouse io data
- memset( m_mouseEvents, 0, sizeof( m_mouseEvents ) );
- memset( &m_currMouse, 0, sizeof( m_currMouse ) );
- memset( &m_prevMouse, 0, sizeof( m_prevMouse ) );
-
- m_minX = 0;
- m_maxX = 0;
- m_minY = 0;
- m_maxY = 0;
- m_eventsThisFrame = 0;
-
- m_inputMovesAbsolute = FALSE;
-
- m_currentCursor = ARROW;
- if (TheGlobalData && TheGlobalData->m_winCursors)
- m_currentRedrawMode = RM_WINDOWS;
- else
- m_currentRedrawMode = RM_W3D;//RM_WINDOWS;
- m_visible = FALSE;
- m_isCursorCaptured = FALSE;
- m_tooltipFontName = "Times New Roman";
- m_tooltipFontSize = 12;
- m_tooltipFontIsBold = FALSE;
- m_tooltipAnimateBackground = TRUE;
- m_tooltipFillTime = 50;
- m_tooltipDelayTime = 50;
-
-#define setColor(x, r, g, b, a) { x.red = r; x.green = g; x.blue = b; x.alpha = a; }
- setColor(m_tooltipColorText, 220, 220, 220, 255);
- setColor(m_tooltipColorHighlight, 255, 255, 0, 255);
- setColor(m_tooltipColorShadow, 0, 0, 0, 255);
- setColor(m_tooltipColorBackground, 20, 20, 0, 127);
- setColor(m_tooltipColorBorder, 0, 0, 0, 255);
-#undef setColor
-
- m_tooltipWidth = 15.0f;
- m_lastTooltipWidth = 0.0f;
-
- m_useTooltipAltTextColor = FALSE;
- m_useTooltipAltBackColor = FALSE;
- m_adjustTooltipAltColor = FALSE;
-
- m_orthoCamera = FALSE;
- m_orthoZoom = 1.0f;
-
- m_isTooltipEmpty = TRUE;
-
- m_cursorTextDisplayString = nullptr;
- m_cursorTextColor.red = 255;
- m_cursorTextColor.green = 255;
- m_cursorTextColor.blue = 255;
- m_cursorTextColor.alpha = 255;
- m_cursorTextDropColor.red = 255;
- m_cursorTextDropColor.green = 255;
- m_cursorTextDropColor.blue = 255;
- m_cursorTextDropColor.alpha = 255;
-
- m_highlightPos = 0;
- m_highlightUpdateStart = 0;
- m_stillTime = 0;
- m_tooltipTextColor.red = 255;
- m_tooltipTextColor.green = 255;
- m_tooltipTextColor.blue = 255;
- m_tooltipTextColor.alpha = 255;
- m_tooltipBackColor.red = 0;
- m_tooltipBackColor.green = 0;
- m_tooltipBackColor.blue = 0;
- m_tooltipBackColor.alpha = 255;
-
- m_cursorCaptureMode = 0;
-
- m_captureBlockReasonBits = (1 << CursorCaptureBlockReason_NoInit);
- DEBUG_LOG(("Mouse::Mouse: m_blockCaptureReason=CursorCaptureBlockReason_NoInit"));
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Mouse::~Mouse( void )
-{
- if(m_tooltipDisplayString)
- TheDisplayStringManager->freeDisplayString(m_tooltipDisplayString);
- m_tooltipDisplayString = nullptr;
-
- if( m_cursorTextDisplayString )
- TheDisplayStringManager->freeDisplayString( m_cursorTextDisplayString );
- m_cursorTextDisplayString = nullptr;
-
-}
-
-/**Had to move this out of main init() because I need this data to properly initialize
-the Win32 version of the mouse (by preloading resources before D3D device is created).*/
-void Mouse::parseIni(void)
-{
- INI ini;
- ini.loadFileDirectory( "Data\\INI\\Mouse", INI_LOAD_OVERWRITE, nullptr );
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Initialize the mouse */
-//-------------------------------------------------------------------------------------------------
-void Mouse::init( void )
-{
- if (TheGlobalData && TheGlobalData->m_winCursors)
- m_currentRedrawMode = RM_WINDOWS;
-
- // device info
- m_numButtons = 2; // by default just have 2 buttons
- m_numAxes = 2; // by default a normal mouse moves in a 2d plane
- m_forceFeedback = FALSE;
- onResolutionChanged();
- m_tooltipString.clear(); // redundant
- m_displayTooltip = FALSE;
-
- // initialize all the mouse io data
- memset( m_mouseEvents, 0, sizeof( m_mouseEvents ) );
- memset( &m_currMouse, 0, sizeof( m_currMouse ) );
- memset( &m_prevMouse, 0, sizeof( m_prevMouse ) );
-
- m_minX = 0;
- m_maxX = 799;
- m_minY = 0;
- m_maxY = 599;
-
- m_inputMovesAbsolute = FALSE;
- m_eventsThisFrame = 0;
-
- m_currentCursor = ARROW;
-
- // allocate a new display string
- m_cursorTextDisplayString = TheDisplayStringManager->newDisplayString();
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Tell mouse system display resolution changed. */
-//-------------------------------------------------------------------------------------------------
-void Mouse::onResolutionChanged( void )
-{
- if(m_tooltipDisplayString)
- TheDisplayStringManager->freeDisplayString(m_tooltipDisplayString);
- m_tooltipDisplayString = nullptr;
-
- m_tooltipDisplayString = TheDisplayStringManager->newDisplayString();
-
- if (TheGlobalLanguageData && TheGlobalLanguageData->m_tooltipFontName.name.isNotEmpty())
- {
- m_tooltipDisplayString->setFont( TheFontLibrary->getFont(
- TheGlobalLanguageData->m_tooltipFontName.name,
- TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_tooltipFontName.size),
- TheGlobalLanguageData->m_tooltipFontName.bold) );
- }
- else
- {
- m_tooltipDisplayString->setFont( TheFontLibrary->getFont(
- m_tooltipFontName,
- TheGlobalLanguageData->adjustFontSize(m_tooltipFontSize),
- m_tooltipFontIsBold ) );
- }
-
- m_tooltipDisplayString->setWordWrap(120);
-
-}
-
-//-------------------------------------------------------------------------------------------------
-void Mouse::onGameModeChanged(GameMode prev, GameMode next)
-{
- refreshCursorCapture();
-}
-
-//-------------------------------------------------------------------------------------------------
-void Mouse::onGamePaused(Bool paused)
-{
- if (paused)
- {
- blockCapture(CursorCaptureBlockReason_Paused);
- }
- else
- {
- unblockCapture(CursorCaptureBlockReason_Paused);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset mouse system */
-//-------------------------------------------------------------------------------------------------
-void Mouse::reset( void )
-{
-
- ///@ todo Write Mouse::reset() if there needs to be anything here
-
- // reset the text of the cursor text
- if ( m_cursorTextDisplayString )
- m_cursorTextDisplayString->reset();
-
- blockCapture(CursorCaptureBlockReason_NoInit);
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Update the states of the mouse position and buttons */
-//-------------------------------------------------------------------------------------------------
-void Mouse::update( void )
-{
-
- // update the mouse data
- updateMouseData( );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Given the current state of this input device, turn the raw input
- * data into raw stream messages and place those messages on the stream.
- * NOTE that the click messages replace up messages in the mouse, so we
- * are going to propagate those click messages in addition to up messages */
-//-------------------------------------------------------------------------------------------------
-void Mouse::createStreamMessages( void )
-{
-
- // sanity
- if( TheMessageStream == nullptr )
- return; // no place to put messages
-
- GameMessage *msg = nullptr;
- UnsignedInt now = timeGetTime();
-
- // basic position messages are always created
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_POSITION );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
-
- Int delay = m_tooltipDelayTime;
- if(m_tooltipDelay >= 0 )
- delay = m_tooltipDelay;
- if( TheGlobalData->m_scriptDebug )
- {
- //No delay while scriptdebugging!
- delay = 0;
- }
-
- if( now - m_stillTime >= delay )
- {
- if (!m_displayTooltip)
- {
- m_highlightPos = 0;
- m_highlightUpdateStart = timeGetTime();
- }
-
- // display tooltip for current window
- m_displayTooltip = TRUE;
- }
- else
- {
- //DEBUG_LOG(("%d %d %d %d", TheGameClient->getFrame(), delay, now, m_stillTime));
- m_displayTooltip = FALSE;
- }
-
- for (Int i = 0; i < m_eventsThisFrame; ++i)
- {
- processMouseEvent(i);
- if (m_currMouse.deltaPos.x || m_currMouse.deltaPos.y)
- m_stillTime = now;
-
- // button messages
- msg = nullptr;
- switch( m_currMouse.leftEvent )
- {
-
- case GWM_LEFT_DOWN:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_DOWN );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_LEFT_DOUBLE_CLICK:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_LEFT_UP:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_BUTTON_UP );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_LEFT_DRAG:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_LEFT_DRAG );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendPixelArgument( m_currMouse.deltaPos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- break;
-
- }
-
- msg = nullptr;
- switch( m_currMouse.middleEvent )
- {
-
- //-------------------------------------------------------------------------
- case GWM_MIDDLE_DOWN:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_MIDDLE_DOUBLE_CLICK:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_MIDDLE_UP:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_BUTTON_UP );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_MIDDLE_DRAG:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_MIDDLE_DRAG );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendPixelArgument( m_currMouse.deltaPos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- break;
-
- }
-
- msg = nullptr;
- switch( m_currMouse.rightEvent )
- {
-
- //-------------------------------------------------------------------------
- case GWM_RIGHT_DOWN:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_RIGHT_DOUBLE_CLICK:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_RIGHT_UP:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_BUTTON_UP );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- msg->appendIntegerArgument( m_currMouse.time );
- break;
-
- case GWM_RIGHT_DRAG:
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_RIGHT_DRAG );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendPixelArgument( m_currMouse.deltaPos );
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- break;
-
- }
-
- // wheel pos
- msg = nullptr;
- if( m_currMouse.wheelPos != 0 )
- {
- msg = TheMessageStream->appendMessage( GameMessage::MSG_RAW_MOUSE_WHEEL );
- msg->appendPixelArgument( m_currMouse.pos );
- msg->appendIntegerArgument( m_currMouse.wheelPos / 120 ); // wheel delta
- msg->appendIntegerArgument( TheKeyboard->getModifierFlags() );
- }
-
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Set the string to display at the cursor for the tooltip */
-//-------------------------------------------------------------------------------------------------
-void Mouse::setCursorTooltip( UnicodeString tooltip, Int delay, const RGBColor *color, Real width )
-{
-
- //DEBUG_LOG(("%d Tooltip: %ls", TheGameClient->getFrame(), tooltip.str()));
-
- m_isTooltipEmpty = tooltip.isEmpty();
- m_tooltipDelay = delay;
-
- Bool forceRecalc = FALSE;
- if ( !tooltip.isEmpty() && width != m_lastTooltipWidth )
- {
- forceRecalc = TRUE;
- Int widthInPixels = (Int)(TheDisplay->getWidth()*m_tooltipWidth*width);
- if (widthInPixels < 10)
- {
- widthInPixels = 120;
- }
- else if (widthInPixels > TheDisplay->getWidth())
- {
- widthInPixels = TheDisplay->getWidth();
- }
- //DEBUG_LOG(("Setting tooltip width to %d pixels (%g%% of the normal tooltip width)", widthInPixels, width*100));
- m_tooltipDisplayString->setWordWrap( widthInPixels );
- m_lastTooltipWidth = width;
- }
-
- if (forceRecalc || (!m_isTooltipEmpty && tooltip.compare(m_tooltipDisplayString->getText())))
- {
- m_tooltipDisplayString->setText(tooltip);
- //DEBUG_LOG(("Tooltip: %ls", tooltip.str()));
- }
- if (color)
- {
- if (m_useTooltipAltTextColor)
- {
- if (m_adjustTooltipAltColor)
- {
- m_tooltipTextColor.red = REAL_TO_INT((color->red + 1.0f) * 255.0f / 2.0f);
- m_tooltipTextColor.green = REAL_TO_INT((color->green + 1.0f) * 255.0f / 2.0f);
- m_tooltipTextColor.blue = REAL_TO_INT((color->blue + 1.0f) * 255.0f / 2.0f);
- }
- else
- {
- m_tooltipTextColor.red = REAL_TO_INT(color->red * 255.0f);
- m_tooltipTextColor.green = REAL_TO_INT(color->green * 255.0f);
- m_tooltipTextColor.blue = REAL_TO_INT(color->blue * 255.0f);
- }
- m_tooltipTextColor.alpha = m_tooltipColorText.alpha;
- }
- if (m_useTooltipAltBackColor)
- {
- if (m_adjustTooltipAltColor)
- {
- m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f * 0.5f);
- m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f * 0.5f);
- m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f * 0.5f);
- }
- else
- {
- m_tooltipBackColor.red = REAL_TO_INT(color->red * 255.0f);
- m_tooltipBackColor.green = REAL_TO_INT(color->green * 255.0f);
- m_tooltipBackColor.blue = REAL_TO_INT(color->blue * 255.0f);
- }
- m_tooltipBackColor.alpha = m_tooltipColorBackground.alpha;
- }
- }
- else
- {
- m_tooltipTextColor = m_tooltipColorText;
- m_tooltipBackColor = m_tooltipColorBackground;
- }
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Set the text for the mouse cursor ... note that this is *NOT* the tooltip text we
- * can set to be at the mouse position */
-// ------------------------------------------------------------------------------------------------
-void Mouse::setMouseText( UnicodeString text,
- const RGBAColorInt *color,
- const RGBAColorInt *dropColor )
-{
-
- // sanity, if no display string has been created, get out of here
- if( m_cursorTextDisplayString == nullptr )
- return;
-
- // set the text into the cursor display string
- m_cursorTextDisplayString->setText( text );
-
- // save the colors to draw in
- if( color )
- m_cursorTextColor = *color;
- if( dropColor )
- m_cursorTextDropColor = *dropColor;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Move the mouse to the position */
-//-------------------------------------------------------------------------------------------------
-void Mouse::setPosition( Int x, Int y )
-{
-
- m_currMouse.pos.x = x;
- m_currMouse.pos.y = y;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** This default implementation of SetMouseLimits will just set the limiting
- * rectangle to be the width and height of the game display with the
- * origin in the upper left at (0,0). However, if the game is running
- * in a windowed mode then these limits should reflect the SCREEN
- * coordinates that the mouse is allowed to move in. Also, if the game is in
- * a window you may want to adjust for any title bar available in
- * the operating system. For system specific limits and windows etc,
- * just override this function in the device implementation of the mouse */
-//-------------------------------------------------------------------------------------------------
-void Mouse::setMouseLimits( void )
-{
-
- m_minX = 0;
- m_minY = 0;
- if( TheDisplay )
- {
-
- m_maxX = TheDisplay->getWidth();
- m_maxY = TheDisplay->getHeight();
-
- }
-
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::setCursorCaptureMode(CursorCaptureMode mode)
-{
- if (m_cursorCaptureMode != mode)
- {
- m_cursorCaptureMode = mode;
- refreshCursorCapture();
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::refreshCursorCapture()
-{
- if (canCapture())
- {
- capture();
- }
- else
- {
- releaseCapture();
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-Bool Mouse::isCursorCaptured()
-{
- return m_isCursorCaptured;
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::loseFocus()
-{
- // Free the cursor when losing window focus.
- blockCapture(CursorCaptureBlockReason_Unfocused);
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::regainFocus()
-{
- // Recapture the cursor when returning from desktop.
- unblockCapture(CursorCaptureBlockReason_Unfocused);
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::onCursorMovedOutside()
-{
- blockCapture(CursorCaptureBlockReadon_CursorIsOutside);
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::onCursorMovedInside()
-{
- unblockCapture(CursorCaptureBlockReadon_CursorIsOutside);
-}
-
-// ------------------------------------------------------------------------------------------------
-Bool Mouse::isCursorInside() const
-{
- return (m_captureBlockReasonBits & (1 << CursorCaptureBlockReadon_CursorIsOutside)) == 0;
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::initCapture()
-{
- OptionPreferences prefs;
- m_cursorCaptureMode = prefs.getCursorCaptureMode();
-
- unblockCapture(CursorCaptureBlockReason_NoInit);
-}
-
-// ------------------------------------------------------------------------------------------------
-Bool Mouse::canCapture() const
-{
- if (m_captureBlockReasonBits != 0)
- return false;
-
- DEBUG_ASSERTCRASH(TheDisplay != nullptr, ("The Display is null"));
- const Bool inInteractiveGame = TheGameLogic && TheGameLogic->isInInteractiveGame();
-
- if (TheDisplay->getWindowed())
- {
- if (inInteractiveGame)
- {
- if ((m_cursorCaptureMode & CursorCaptureMode_EnabledInWindowedGame) == 0)
- return false;
- }
- else
- {
- if ((m_cursorCaptureMode & CursorCaptureMode_EnabledInWindowedMenu) == 0)
- return false;
- }
- }
- else
- {
- if (inInteractiveGame)
- {
- if ((m_cursorCaptureMode & CursorCaptureMode_EnabledInFullscreenGame) == 0)
- return false;
- }
- else
- {
- if ((m_cursorCaptureMode & CursorCaptureMode_EnabledInFullscreenMenu) == 0)
- return false;
- }
- }
-
- return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::unblockCapture(CursorCaptureBlockReason reason)
-{
- Bool canCaptureBefore = canCapture();
- m_captureBlockReasonBits &= ~(1 << reason);
- Bool canCaptureNow = canCapture();
-
- if (canCaptureNow != canCaptureBefore)
- {
- DEBUG_ASSERTCRASH(canCaptureNow, ("Mouse::unblockCapture(%s): Unexpected logic", CursorCaptureBlockReasonNames[reason]));
- capture();
- }
-
- DEBUG_LOG(("Mouse::unblockCapture(%s): m_captureBlockReason=%u canCapture=%d",
- CursorCaptureBlockReasonNames[reason], m_captureBlockReasonBits, (Int)canCapture()));
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::blockCapture(CursorCaptureBlockReason reason)
-{
- Bool canCaptureBefore = canCapture();
- m_captureBlockReasonBits |= (1 << reason);
- Bool canCaptureNow = canCapture();
-
- if (canCaptureNow != canCaptureBefore)
- {
- DEBUG_ASSERTCRASH(!canCaptureNow, ("Mouse::blockCapture(%s): Unexpected logic", CursorCaptureBlockReasonNames[reason]));
- releaseCapture();
- }
-
- DEBUG_LOG(("Mouse::blockCapture(%s): m_captureBlockReason=%u canCapture=%d",
- CursorCaptureBlockReasonNames[reason], m_captureBlockReasonBits, (Int)canCapture()));
-}
-
-// ------------------------------------------------------------------------------------------------
-void Mouse::onCursorCaptured( Bool captured )
-{
- m_isCursorCaptured = captured;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Draw the mouse */
-//-------------------------------------------------------------------------------------------------
-void Mouse::draw( void )
-{
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void Mouse::resetTooltipDelay( void )
-{
- m_stillTime = timeGetTime();
- m_displayTooltip = FALSE;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Draw the mouse tooltip if one is set */
-//-------------------------------------------------------------------------------------------------
-void Mouse::drawTooltip( void )
-{
- if (TheScriptEngine->getFade()!=ScriptEngine::FADE_NONE) {
- return;
- }
-
- /// @todo: Still need to put in display logic so it puts the tool tips in a visible position on the edge of the screen
- if( m_displayTooltip && TheDisplay && m_tooltipDisplayString && (m_tooltipDisplayString->getTextLength() > 0) && !m_isTooltipEmpty)
- {
- Int width, xPos;
- Int height, yPos;
- m_tooltipDisplayString->getSize(&width,&height);
- xPos = m_currMouse.pos.x + 20;
- yPos = m_currMouse.pos.y;// + 20;
-
- if( xPos + width + 4 > m_maxX ) // +4 for spill
- {
- //xPos = m_maxX - width;
- xPos -= 20 + width;
- }
- if( yPos + height + 4 > m_maxY ) // +4 for spill
- {
- //yPos = m_maxY - height;
- yPos -= /*40 +*/ height;
- }
-
- Int boxWidth = (m_tooltipAnimateBackground)?(min(width, m_highlightPos)):width;
-
-#define GMC(x) GameMakeColor(x.red, x.green, x.blue, x.alpha)
-#define COLOR(x) GMC(m_tooltipColor##x)
- TheDisplay->drawFillRect(xPos, yPos, boxWidth + 2,height + 2, GMC(m_tooltipBackColor));//GameMakeColor(0,0,0,125));
- TheDisplay->drawOpenRect(xPos, yPos, boxWidth + 2,height + 2, 1.0, COLOR(Border));//GameMakeColor(20,20,20,255));
-
- // build clip rect
- IRegion2D clipRegion;
- clipRegion.lo.x = xPos+2;
- clipRegion.lo.y = yPos+1;
- clipRegion.hi.x = xPos+2+m_highlightPos;
- clipRegion.hi.y = yPos+1+height;
- m_tooltipDisplayString->setClipRegion(&clipRegion);
- m_tooltipDisplayString->draw(xPos +2, yPos +1, GMC(m_tooltipTextColor), COLOR(Shadow));//GameMakeColor(220,220,220,255),GameMakeColor(20,20,20,125));
-
- // highlight section
- const Int HIGHLIGHT_WIDTH = 15;
- clipRegion.lo.x = xPos+2+m_highlightPos-HIGHLIGHT_WIDTH;
- clipRegion.lo.y = yPos+1;
- clipRegion.hi.x = xPos+2+m_highlightPos;
- clipRegion.hi.y = yPos+1+height;
- m_tooltipDisplayString->setClipRegion(&clipRegion);
- m_tooltipDisplayString->draw(xPos +2, yPos +1, COLOR(Highlight), COLOR(Shadow));//GameMakeColor(255,255,0,255),GameMakeColor(20,20,20,125));
-
- // get ready for the next part of the anim
- if (m_highlightPos < width + HIGHLIGHT_WIDTH)
- {
- UnsignedInt now = timeGetTime();
- m_highlightPos = (width*(now-m_highlightUpdateStart))/m_tooltipFillTime;
- }
- }
-
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Draw the cursor text at the mouse position. Note that this is *NOT* the tooltip text */
-// ------------------------------------------------------------------------------------------------
-void Mouse::drawCursorText( void )
-{
-
- // sanity
- if( m_cursorTextDisplayString == nullptr )
- return;
-
- // get the colors to draw the text in an acceptable format
- Color color, dropColor;
- color = GameMakeColor( m_cursorTextColor.red,
- m_cursorTextColor.green,
- m_cursorTextColor.blue,
- m_cursorTextColor.alpha );
- dropColor = GameMakeColor( m_cursorTextDropColor.red,
- m_cursorTextDropColor.green,
- m_cursorTextDropColor.blue,
- m_cursorTextDropColor.alpha );
-
- // get the size of the text to draw
- Int width, height;
- m_cursorTextDisplayString->getSize( &width, &height );
-
- // draw the text around the cursor position
- Int x, y;
- x = m_currMouse.pos.x - width / 2;
- y = m_currMouse.pos.y - height / 2;
- m_cursorTextDisplayString->draw( x, y, color, dropColor );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-Int Mouse::getCursorIndex(const AsciiString& name)
-{
- if (name.isEmpty())
- return INVALID_MOUSE_CURSOR;
-
- /** @todo This is silly to have to define these names from INI in the code ...
- * that should be changed (CBD) */
- static const char *CursorININames[NUM_MOUSE_CURSORS] =
- {
- //"InvalidMouseCursor", // this entry is not actually a mouse cursor, but just a
- // reminder that it does exist
- "None",
- "Normal",
- "Arrow",
- "Scroll",
- "Target",
- "Move",
- "AttackMove",
- "AttackObj",
- "ForceAttackObj",
- "ForceAttackGround",
- "Build",
- "InvalidBuild",
- "GenericInvalid",
- "Select",
- "EnterFriendly",
- "EnterAggressive",
- "SetRallyPoint",
- "GetRepaired",
- "GetHealed",
- "DoRepair",
- "ResumeConstruction",
- "CaptureBuilding",
- "SnipeVehicle",
- "LaserGuidedMissiles",
- "TankHunterTNTAttack",
- "StabAttack",
- "PlaceRemoteCharge",
- "PlaceTimedCharge",
- "Defector",
-#ifdef ALLOW_DEMORALIZE
- "Demoralize",
-#endif
- "Dock",
-#ifdef ALLOW_SURRENDER
- "PickUpPrisoner",
- "ReturnToPrison",
-#endif
- "FireFlame",
-#ifdef ALLOW_SURRENDER
- "FireTranqDarts",
- "FireStunBullets",
-#endif
- "FireBomb",
- "PlaceBeacon",
- "DisguiseAsVehicle",
- "Waypoint",
- "OutRange",
- "StabAttackInvalid",
- "PlaceChargeInvalid",
- "Hack",
- "ParticleUplinkCannon",
-
- };
-
- for (Int i=0; icursorText.isEmpty() == FALSE )
- setMouseText( TheGameText->fetch( cursorInfo->cursorText.str() ),
- &(cursorInfo->cursorTextColor),
- &(cursorInfo->cursorTextDropColor) );
- else
- setMouseText( L"", nullptr, nullptr );
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Parse MouseCursor entry */
-//-------------------------------------------------------------------------------------------------
-void INI::parseMouseCursorDefinition( INI* ini )
-{
- const char *c;
- AsciiString name;
-
- // read the name
- c = ini->getNextToken();
- name.set( c );
-
- if( TheMouse )
- {
- Int index = TheMouse->getCursorIndex(name);
- if (index != Mouse::INVALID_MOUSE_CURSOR)
- {
- CursorInfo *cursorInfo = &(TheMouse->m_cursorInfo[index]);
- cursorInfo->cursorName = name;
-
- // parse the ini weapon definition
- ini->initFromINI( cursorInfo, TheMouseCursorFieldParseTable );
- }
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Parse MouseCursor entry */
-//-------------------------------------------------------------------------------------------------
-void INI::parseMouseDefinition( INI* ini )
-{
- if( TheMouse )
- {
- // parse the ini weapon definition
- ini->initFromINI( TheMouse, TheMouseFieldParseTable );
- }
-}
-
-
diff --git a/Generals/Code/GameEngine/Source/GameClient/LanguageFilter.cpp b/Generals/Code/GameEngine/Source/GameClient/LanguageFilter.cpp
deleted file mode 100644
index f2e0af373ad..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/LanguageFilter.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/LanguageFilter.h"
-#include "Common/FileSystem.h"
-#include "Common/file.h"
-
-
-
-LanguageFilter *TheLanguageFilter = nullptr;
-
-LanguageFilter::LanguageFilter()
-{
-}
-
-LanguageFilter::~LanguageFilter() {
- m_wordList.clear();
-}
-
-void LanguageFilter::init() {
- m_wordList.clear();
-
- // read in the file already.
- File *file1 = TheFileSystem->openFile(BadWordFileName, File::READ | File::BINARY);
- if (file1 == nullptr) {
- return;
- }
-
- wchar_t word[128];
- while (readWord(file1, word)) {
- Int wordLen = wcslen(word);
- if (wordLen == 0) {
- continue;
- }
- for (Int i = 0; i < wordLen; ++i) {
- word[i] = word[i] ^ LANGUAGE_XOR_KEY;
- }
- UnicodeString uniword(word);
- unHaxor(uniword);
- //DEBUG_LOG(("Just read %ls from the bad word file. Entered as %ls", word, uniword.str()));
- m_wordList[uniword] = true;
- }
-
- file1->close();
- file1 = nullptr;
-}
-
-void LanguageFilter::reset() {
- init();
-}
-
-void LanguageFilter::update() {
-}
-
-wchar_t ignoredChars[] = L"-_*'\"";
-
-void LanguageFilter::filterLine(UnicodeString &line)
-{
- WideChar *buf = NEW WideChar[line.getLength()+1];
- wcscpy(buf, line.str());
-
- UnicodeString newLine(line);
- UnicodeString token;
-
- while (newLine.nextToken(&token, L" ;,.!?:=\\/><`~()&^%#\n\t")) {
- wchar_t *pos = wcsstr(buf, token.str());
- if (pos == nullptr) {
- DEBUG_CRASH(("Couldn't find the token in its own string."));
- continue;
- }
-
- Int len = token.getLength(); // need to get the length of the original word, not the unhaxor'd word.
-
- unHaxor(token);
- LangMapIter iter = m_wordList.find(token);
- if (iter != m_wordList.end()) {
- DEBUG_LOG(("Found word %ls in bad word list. Token was %ls", (*iter).first.str(), token.str()));
- for (Int i = 0; i < len; ++i) {
- *pos = L'*';
- ++pos;
- }
- }
- }
-
- line.set(buf);
- delete[] buf;
-}
-
-void LanguageFilter::unHaxor(UnicodeString &word) {
- Int len = word.getLength();
- UnicodeString newWord;
- for (Int i = 0; i < len; ++i) {
- wchar_t c = word.getCharAt(i);
- if ((c == L'p') || (c == L'P')) {
- if (((i + 1) < len) && ((word.getCharAt(i+1) == L'h') || (word.getCharAt(i+1) == L'H'))) {
- newWord.concat(L'f');
- ++i; // skip the h
- } else {
- // not a problem at all.
- newWord.concat(c);
- }
- } else if (c == L'1') {
- newWord.concat(L'l');
- } else if (c == L'3') {
- newWord.concat(L'e');
- } else if (c == L'4') {
- newWord.concat(L'a');
- } else if (c == L'5') {
- newWord.concat(L's');
- } else if (c == L'6') {
- newWord.concat(L'b');
- } else if (c == L'7') {
- newWord.concat(L't');
- } else if (c == L'0') {
- newWord.concat(L'o');
- } else if (c == L'@') {
- newWord.concat(L'a');
- } else if (c == L'$') {
- newWord.concat(L's');
- } else if (c == L'+') {
- newWord.concat(L't');
- } else if (wcsrchr(ignoredChars, c) == nullptr) {
- newWord.concat(c);
- }
- }
- word.set(newWord);
-}
-
-// returning true means that there are more words in the file.
-Bool LanguageFilter::readWord(File *file1, WideChar *buf) {
- Int index = 0;
- Bool retval = TRUE;
- Int val = 0;
-
- WideChar c;
-
- val = file1->read(&c, sizeof(WideChar));
- if ((val == -1) || (val == 0)) {
- buf[index] = 0;
- return FALSE;
- }
- buf[index] = c;
-
- while (buf[index] != L' ') {
- ++index;
- val = file1->read(&c, sizeof(WideChar));
- if ((val == -1) || (val == 0)) {
- c = WEOF;
- }
-
- if ((c == WEOF) || (c == L' ')) {
- buf[index] = 0;
- if (c == WEOF) {
- retval = FALSE;
- }
- break;
- }
- buf[index] = c;
- }
- return retval;
-}
-
-LanguageFilter * createLanguageFilter()
-{
- return NEW LanguageFilter;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/Line2D.cpp b/Generals/Code/GameEngine/Source/GameClient/Line2D.cpp
deleted file mode 100644
index 30e558df9dc..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/Line2D.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Line2D.cpp ///////////////////////////////////////////////////////////////////////////////
-// Author: Colin Day, January 2002
-// Desc: Some helpful 2D stuff
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Lib/BaseType.h"
-#include "GameClient/Line2D.h"
-
-// PRIVATE ////////////////////////////////////////////////////////////////////////////////////////
-#define CLIP_LEFT 0x01
-#define CLIP_RIGHT 0x02
-#define CLIP_BOTTOM 0x04
-#define CLIP_TOP 0x08
-
-// PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
-
-
-// STATIC /////////////////////////////////////////////////////////////////////////////////////////
-const static Coord2D reallyFarPoint = { 1000000.0, 1000000.0 };
-
-//-------------------------------------------------------------------------------------------------
-/** Clip a line to the region provided. The source line runs from p1 to p2, and is clipped
- * using the clipRegion. The resulting line goes from c1 to c2
- *
- * Return values:
- * TRUE - Line is visible
- * FALSE - Line is not visible
- */
-//-------------------------------------------------------------------------------------------------
-Bool ClipLine2D( ICoord2D *p1, ICoord2D *p2, ICoord2D *c1, ICoord2D *c2,
- IRegion2D *clipRegion )
-{
- Int x1, y1, x2, y2;
- Int clipLeft;
- Int clipRight;
- Int clipTop;
- Int clipBottom;
- Int clipCode1;
- Int clipCode2;
- Int diff;
-
- // Use clip window that includes bottom right pixel
- clipLeft = clipRegion->lo.x;
- clipRight = clipRegion->hi.x;
- clipTop = clipRegion->lo.y;
- clipBottom = clipRegion->hi.y;
-/*
- clipLeft = gfxCurrentContext->clipRect1.left;
- clipRight = gfxCurrentContext->clipRect1.right;
- clipTop = gfxCurrentContext->clipRect1.top;
- clipBottom = gfxCurrentContext->clipRect1.bottom;
-
- x1 = *px1;
- y1 = *py1;
- x2 = *px2;
- y2 = *py2;
-*/
-
- x1 = p1->x;
- y1 = p1->y;
- x2 = p2->x;
- y2 = p2->y;
-
- // Test first point
- clipCode1 = 0;
-
- if (x1 < clipLeft)
- clipCode1 = CLIP_LEFT;
- else
- if (x1 > clipRight)
- clipCode1 = CLIP_RIGHT;
-
- if (y1 < clipTop)
- clipCode1 |= CLIP_TOP;
- else
- if (y1 > clipBottom)
- clipCode1 |= CLIP_BOTTOM;
-
-
- // Test second point
- clipCode2 = 0;
-
- if (x2 < clipLeft)
- clipCode2 = CLIP_LEFT;
- else
- if (x2 > clipRight)
- clipCode2 = CLIP_RIGHT;
-
- if (y2 < clipTop)
- clipCode2 |= CLIP_TOP;
- else
- if (y2 > clipBottom)
- clipCode2 |= CLIP_BOTTOM;
-
-
- // Both points inside window?
- if ((clipCode1 | clipCode2) == 0)
- {
-
- *c1 = *p1;
- *c2 = *p2;
- return TRUE;
-
- }
-
- // Both points outside window?
- if (clipCode1 & clipCode2)
- return FALSE;
-
- // First point outside window?
- if (clipCode1)
- {
- if (clipCode1 & CLIP_TOP)
- {
- if ((diff = (y2 - y1)) == 0)
- return FALSE;
- x1 += (x2 - x1) * (clipTop - y1) / diff;
- y1 = clipTop;
- }
- else
- if (clipCode1 & CLIP_BOTTOM)
- {
- if ((diff = (y2 - y1)) == 0)
- return FALSE;
- x1 += (x2 - x1) * (clipBottom - y1) / diff;
- y1 = clipBottom;
- }
-
- if (x1 > clipRight)
- {
- if ((diff = (x2 - x1)) == 0)
- return FALSE;
- y1 += (y2 - y1) * (clipRight - x1) / diff;
- x1 = clipRight;
- }
- else
- if (x1 < clipLeft)
- {
- if ((diff = (x2 - x1)) == 0)
- return FALSE;
- y1 += (y2 - y1) * (clipLeft - x1) / diff;
- x1 = clipLeft;
- }
- }
-
- // Second point outside window?
- if (clipCode2)
- {
- if (clipCode2 & CLIP_TOP)
- {
- if ((diff = (y2 - y1)) == 0)
- return FALSE;
- x2 += (x2 - x1) * (clipTop - y2) / diff;
- y2 = clipTop;
- }
- else
- if (clipCode2 & CLIP_BOTTOM)
- {
- if ((diff = (y2 - y1)) == 0)
- return FALSE;
- x2 += (x2 - x1) * (clipBottom - y2) / diff;
- y2 = clipBottom;
- }
-
- if (x2 > clipRight)
- {
- if ((diff = (x2 - x1)) == 0)
- return FALSE;
- y2 += (y2 - y1) * (clipRight - x2) / diff;
- x2 = clipRight;
- }
- else
- if (x2 < clipLeft)
- {
- if ((diff = (x2 - x1)) == 0)
- return FALSE;
- y2 += (y2 - y1) * (clipLeft - x2) / diff;
- x2 = clipLeft;
- }
- }
-
- c1->x = x1;
- c1->y = y1;
- c2->x = x2;
- c2->y = y2;
-
-/*
- *px1 = x1;
- *py1 = y1;
- *px2 = x2;
- *py2 = y2;
-*/
-
- // Line is visible
- return (x1 >= clipLeft && x1 <= clipRight &&
- y1 >= clipTop && y1 <= clipBottom &&
- x2 >= clipLeft && x2 <= clipRight &&
- y2 >= clipTop && y2 <= clipBottom);
-
-}
-
-
-// This solution uses the
-// http://www.faqs.org/faqs/graphics/algorithms-faq/
-// Subject 1.03
-Bool IntersectLine2D( const Coord2D *a, const Coord2D *b,
- const Coord2D *c, const Coord2D *d,
- Coord2D *intersection)
-{
- if (!a || !b || !c || !d) {
- // sanity. Lines that do not have endpoints do not intersect.
- return false;
- }
-
- Real r, s, denom;
-
- denom = ((b->x - a->x) * (d->y - c->y) - (b->y - a->y) * (d->x - c->x));
- if (denom == 0) {
- // the lines are parallel.
- return false;
- }
-
- r = ((a->y - c->y) * (d->x - c->x) - (a->x - c->x) * (d->y - c->y) ) / denom;
- s = ((a->y - c->y) * (b->x - a->x) - (a->x - c->x) * (b->y - a->y) ) / denom;
-
- if (0 <= r && r <= 1 && 0 <= s && s <= 1) {
- // The lines intersect.
- if (intersection) {
- intersection->x = a->x + r * (b->x - a->x);
- intersection->y = a->y + r * (b->y - a->y);
- }
-
- return true;
- }
-
- return false;
-}
-
-// determines whether a point lies within a rectangle. Doesn't determine whether the shape is
-// actually a rectangle or not.
-Bool PointInsideRect2D(const Coord2D *bl, const Coord2D *tl, const Coord2D *br, const Coord2D *tr,
- const Coord2D *inputPoint)
-{
- if (!(bl && br && tl && tr && inputPoint)) {
- return FALSE;
- }
-
- Real uVal;
- // we're actually only interested in if the U value is (0,1)
- ShortestDistancePointToSegment2D(bl, tl, inputPoint, nullptr, nullptr, &uVal);
- if (uVal <= 0.0f || uVal >= 1.0f) {
- return false;
- }
-
- ShortestDistancePointToSegment2D(bl, br, inputPoint, nullptr, nullptr, &uVal);
-
- return (uVal > 0.0f && uVal < 1.0f);
-}
-
-// convenience. Just prunes out the Z coordinate for a call to PointInsideRect2D
-Bool PointInsideRect3D(const Coord3D *bl, const Coord3D *tl, const Coord3D *br, const Coord3D *tr,
- const Coord3D *inputPoint)
-{
- Coord2D bl2d, tl2d, br2d, tr2d, pt;
- bl2d.x = bl->x;
- bl2d.y = bl->y;
- tl2d.x = tl->x;
- tl2d.y = tl->y;
- br2d.x = br->x;
- br2d.y = br->y;
- tr2d.x = tr->x;
- tr2d.y = tr->y;
-
- pt.x = inputPoint->x;
- pt.y = inputPoint->y;
-
- return PointInsideRect2D(&bl2d, &br2d, &tl2d, &tr2d, &pt);
-}
-
-
-// This function uses even-odd winding to determine whether a point is inside an area.
-Bool PointInsideArea2D(const Coord2D *ptToTest, const Coord2D *area, const Int numPointsInArea)
-{
- int numIntersections = 0;
- for (int i = 0; i < numPointsInArea; ++i) {
- if (IntersectLine2D(ptToTest, &reallyFarPoint, &area[i], &area[(i + 1) % numPointsInArea])) {
- ++numIntersections;
- }
- }
- return (numIntersections % 2 == 1);
-}
-
-// This function uses even-odd winding to determine whether a point is inside an area.
-Bool PointInsideArea2D( const Coord3D *ptToTest, const Coord3D *area, Int numPointsInArea)
-{
- int numIntersections = 0;
- Coord2D pt2D, area2D1, area2D2;
- pt2D.x = ptToTest->x;
- pt2D.y = ptToTest->y;
-
- for (int i = 0; i < numPointsInArea; ++i) {
- area2D1.x = area[i].x;
- area2D1.y = area[i].y;
- area2D2.x = area[(i + 1) % numPointsInArea].x;
- area2D2.y = area[(i + 1) % numPointsInArea].y;
- if (IntersectLine2D(&pt2D, &reallyFarPoint, &area2D1, &area2D2)) {
- ++numIntersections;
- }
- }
- return (numIntersections % 2 == 1);
-}
-
-///< Checks if a point is inside a perfect rectangle (top left and bottom right)
-Bool Coord3DInsideRect2D( const Coord3D *inputPoint, const Coord2D *tl, const Coord2D *br )
-{
- if( inputPoint->x >= tl->x && inputPoint->x <= br->x )
- {
- if( inputPoint->y >= tl->y && inputPoint->y <= br->y )
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-///< Scales a rect by a factor either growing or shrinking it.
-void ScaleRect2D( Coord2D *tl, Coord2D *br, Real scaleFactor )
-{
- scaleFactor = scaleFactor-1.0f; // We are starting with tl,br, so scaling it by 1 means adding 0 to it.
-
- Real deltaWidth = (br->x - tl->x) * scaleFactor * 0.5f;
- Real deltaHeight = (br->y - tl->y) * scaleFactor * 0.5f;
-
- tl->x -= deltaWidth;
- tl->y -= deltaHeight;
-
- br->x += deltaWidth;
- br->y += deltaHeight;
-}
-
-
-// Solution taken from http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
-void ShortestDistancePointToSegment2D( const Coord2D *a, const Coord2D *b, const Coord2D *pt,
- Real *outDistance, Coord2D *outPosition, Real *outU )
-{
- if (!a || !b || !pt) {
- return;
- }
-
- if (a->x == b->x && a->y == b->y) {
- // special case, its simply pt to pt.
- Coord2D segment;
- segment.x = pt->x - a->x;
- segment.y = pt->y - a->y;
- if (outDistance) {
- (*outDistance) = segment.length();
- }
-
- if (outPosition) {
- (*outPosition).x = a->x;
- (*outPosition).y = a->y;
- }
-
- if (outU) {
- (*outU) = 0.5;
- }
- return;
- }
-
- Coord2D segAB;
- segAB.x = b->x - a->x;
- segAB.y = b->y - a->y;
-
- // General case
- Real u = ((pt->x - a->x) * (b->x - a->x) + (pt->y - a->y) * (b->y - a->y)) /
- sqr(segAB.length());
-
- Coord2D intersectSegment;
-
- intersectSegment.x = a->x + u * (b->x - a->x);
- intersectSegment.y = a->y + u * (b->y - a->y);
-
-
- if (outPosition) {
- (*outPosition) = intersectSegment;
- }
-
- if (outDistance) {
- (*outDistance) = intersectSegment.length();
- }
-
- if (outU) {
- (*outU) = u;
- }
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
index 42932540419..e59897550b3 100644
--- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
@@ -1074,7 +1074,7 @@ GameMessage::Type CommandTranslator::issueAttackCommand( Drawable *target,
msgType = GameMessage::MSG_DO_ATTACK_OBJECT;
break;
default:
- DEBUG_ASSERTCRASH( 0, ("issueAttackCommand was passed in a GUICommandType type that isn't supported yet...") );
+ DEBUG_CRASH( ("issueAttackCommand was passed in a GUICommandType type that isn't supported yet...") );
return msgType;
}
@@ -3017,7 +3017,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
//-----------------------------------------------------------------------------------------
case GameMessage::MSG_META_DEPLOY:
#ifdef RTS_DEBUG
- DEBUG_ASSERTCRASH(FALSE, ("unimplemented meta command MSG_META_DEPLOY !"));
+ DEBUG_CRASH(("unimplemented meta command MSG_META_DEPLOY !"));
#endif
/// @todo srj implement me
disp = DESTROY_MESSAGE;
@@ -3026,7 +3026,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
//-----------------------------------------------------------------------------------------
case GameMessage::MSG_META_FOLLOW:
#ifdef RTS_DEBUG
- DEBUG_ASSERTCRASH(FALSE, ("unimplemented meta command MSG_META_FOLLOW !"));
+ DEBUG_CRASH(("unimplemented meta command MSG_META_FOLLOW !"));
#endif
/// @todo srj implement me
disp = DESTROY_MESSAGE;
diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp
index 673237bb23f..3fa40e099fe 100644
--- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp
@@ -191,7 +191,7 @@ static CommandStatus doFireWeaponCommand( const CommandButton *command, const IC
//This could be legit now -- think of firing a self destruct weapon
//-----------------------------------------------------------------
- //DEBUG_ASSERTCRASH( 0, ("doFireWeaponCommand: Command options say it doesn't need additional user input '%s'",
+ //DEBUG_CRASH( ("doFireWeaponCommand: Command options say it doesn't need additional user input '%s'",
// command->m_name.str()) );
//return COMMAND_COMPLETE;
diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
index ba15e942dc9..a1b6afcf5d9 100644
--- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
@@ -148,7 +148,7 @@ void HotKeyManager::addHotKey( GameWindow *win, const AsciiString& keyIn)
HotKeyMap::iterator it = m_hotKeyMap.find(key);
if( it != m_hotKeyMap.end() )
{
- DEBUG_ASSERTCRASH(FALSE,("Hotkey %s is already mapped to window %s, current window is %s", key.str(), it->second.m_win->winGetInstanceData()->m_decoratedNameString.str(), win->winGetInstanceData()->m_decoratedNameString.str()));
+ DEBUG_CRASH(("Hotkey %s is already mapped to window %s, current window is %s", key.str(), it->second.m_win->winGetInstanceData()->m_decoratedNameString.str(), win->winGetInstanceData()->m_decoratedNameString.str()));
return;
}
HotKey newHK;
diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp
index 01acfe4369d..67ea22be3d1 100644
--- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp
@@ -36,7 +36,7 @@
#include "Common/PlayerList.h"
#include "Common/Recorder.h"
#include "Common/StatsCollector.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameLogic/Object.h"
#include "GameLogic/PartitionManager.h"
#include "GameClient/Display.h"
diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp
index fb8302f8900..b2eed26c3f9 100644
--- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp
@@ -596,6 +596,7 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa
DrawableList drawablesThatWillSelect;
PickDrawableStruct pds;
pds.drawableListToFill = &drawablesThatWillSelect;
+ pds.isPointSelection = isPoint;
TheTacticalView->iterateDrawablesInRegion(&selectionRegion, addDrawableToList, &pds);
if (drawablesThatWillSelect.empty())
diff --git a/Generals/Code/GameEngine/Source/GameClient/RadiusDecal.cpp b/Generals/Code/GameEngine/Source/GameClient/RadiusDecal.cpp
deleted file mode 100644
index 645c8845b47..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/RadiusDecal.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// RadiusDecal.cpp ///////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#define DEFINE_SHADOW_NAMES
-
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/Xfer.h"
-#include "GameClient/RadiusDecal.h"
-#include "GameClient/Shadow.h"
-#include "GameLogic/GameLogic.h"
-
-
-// ------------------------------------------------------------------------------------------------
-RadiusDecalTemplate::RadiusDecalTemplate() :
- m_shadowType(SHADOW_ALPHA_DECAL),
- m_minOpacity(1.0f),
- m_maxOpacity(1.0f),
- m_opacityThrobTime(LOGICFRAMES_PER_SECOND),
- m_color(0),
- m_onlyVisibleToOwningPlayer(true),
- m_name(AsciiString::TheEmptyString)
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-void RadiusDecalTemplate::createRadiusDecal(const Coord3D& pos, Real radius, const Player* owningPlayer, RadiusDecal& result) const
-{
- result.clear();
-
- if (owningPlayer == nullptr)
- {
- DEBUG_CRASH(("You MUST specify a non-null owningPlayer to createRadiusDecal. (srj)"));
- return;
- }
-
- if (m_name.isEmpty() || radius <= 0.0f)
- return;
-
- // it is now considered nonEmpty, regardless of the state of m_decal, etc
- result.m_empty = false;
-
- if (!m_onlyVisibleToOwningPlayer ||
- owningPlayer->getPlayerIndex() == ThePlayerList->getLocalPlayer()->getPlayerIndex())
- {
- Shadow::ShadowTypeInfo decalInfo;
- decalInfo.allowUpdates = FALSE; // shadow texture will never update
- decalInfo.allowWorldAlign = TRUE; // shadow image will wrap around world objects
- decalInfo.m_type = m_shadowType;
- strlcpy(decalInfo.m_ShadowName, m_name.str(), ARRAY_SIZE(decalInfo.m_ShadowName)); // name of your texture
- decalInfo.m_sizeX = radius*2; // world space dimensions
- decalInfo.m_sizeY = radius*2; // world space dimensions
-
- result.m_decal = TheProjectedShadowManager->addDecal(&decalInfo);
- if (result.m_decal)
- {
- result.m_decal->setAngle(0.0f);
- result.m_decal->setColor(m_color == 0 ? owningPlayer->getPlayerColor() : m_color);
- result.m_decal->setPosition(pos.x, pos.y, pos.z);
- result.m_template = this;
- }
- else
- {
- DEBUG_CRASH(("Unable to add decal %s",decalInfo.m_ShadowName));
- }
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-void RadiusDecalTemplate::xferRadiusDecalTemplate( Xfer *xfer )
-{
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
-
- xfer->xferAsciiString(&m_name);
- xfer->xferUser(&m_shadowType, sizeof(m_shadowType));
- xfer->xferReal(&m_minOpacity);
- xfer->xferReal(&m_maxOpacity);
- xfer->xferUnsignedInt(&m_opacityThrobTime);
- xfer->xferColor(&m_color);
- xfer->xferBool(&m_onlyVisibleToOwningPlayer);
-}
-
-// ------------------------------------------------------------------------------------------------
-/*static*/ void RadiusDecalTemplate::parseRadiusDecalTemplate(INI* ini, void *instance, void * store, const void* /*userData*/)
-{
- static const FieldParse dataFieldParse[] =
- {
- { "Texture", INI::parseAsciiString, nullptr, offsetof( RadiusDecalTemplate, m_name ) },
- { "Style", INI::parseBitString32, TheShadowNames, offsetof( RadiusDecalTemplate, m_shadowType ) },
- { "OpacityMin", INI::parsePercentToReal, nullptr, offsetof( RadiusDecalTemplate, m_minOpacity ) },
- { "OpacityMax", INI::parsePercentToReal, nullptr, offsetof( RadiusDecalTemplate, m_maxOpacity) },
- { "OpacityThrobTime", INI::parseDurationUnsignedInt,nullptr, offsetof( RadiusDecalTemplate, m_opacityThrobTime ) },
- { "Color", INI::parseColorInt, nullptr, offsetof( RadiusDecalTemplate, m_color ) },
- { "OnlyVisibleToOwningPlayer", INI::parseBool, nullptr, offsetof( RadiusDecalTemplate, m_onlyVisibleToOwningPlayer ) },
- { nullptr, nullptr, nullptr, 0 }
- };
-
- ini->initFromINI(store, dataFieldParse);
-}
-
-// ------------------------------------------------------------------------------------------------
-RadiusDecal::RadiusDecal() :
- m_template(nullptr),
- m_decal(nullptr),
- m_empty(true)
-{
-}
-
-// ------------------------------------------------------------------------------------------------
-RadiusDecal::RadiusDecal(const RadiusDecal& that) :
- m_template(nullptr),
- m_decal(nullptr),
- m_empty(true)
-{
- DEBUG_CRASH(("not fully implemented"));
-}
-
-// ------------------------------------------------------------------------------------------------
-RadiusDecal& RadiusDecal::operator=(const RadiusDecal& that)
-{
- if (this != &that)
- {
- m_template = nullptr;
- if (m_decal)
- m_decal->release();
- m_decal = nullptr;
- m_empty = true;
- DEBUG_CRASH(("not fully implemented"));
- }
- return *this;
-}
-
-// ------------------------------------------------------------------------------------------------
-void RadiusDecal::xferRadiusDecal( Xfer *xfer )
-{
- /// @todo implement me
- if (xfer->getXferMode() == XFER_LOAD)
- {
- clear();
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-void RadiusDecal::clear()
-{
- m_template = nullptr;
- if (m_decal)
- {
- m_decal->release();
- }
- m_decal = nullptr;
- m_empty = true;
-}
-
-// ------------------------------------------------------------------------------------------------
-RadiusDecal::~RadiusDecal()
-{
- clear();
-}
-
-// ------------------------------------------------------------------------------------------------
-void RadiusDecal::update()
-{
- if (m_decal && m_template)
- {
- UnsignedInt now = TheGameLogic->getFrame();
- Real theta = (2*PI) * (Real)(now % m_template->m_opacityThrobTime) / (Real)m_template->m_opacityThrobTime;
- Real percent = 0.5f * (Sin(theta) + 1.0f);
- Int opac;
- if( TheGameLogic->getDrawIconUI() )
- {
- opac = REAL_TO_INT((m_template->m_minOpacity + percent * (m_template->m_maxOpacity - m_template->m_minOpacity)) * 255.0f);
- }
- else
- {
- //Scripts turned this off, so don't show them!
- opac = 0;
- }
- m_decal->setOpacity(opac);
- }
-}
-
-
-
-void RadiusDecal::setOpacity( Real o )
-{
- if (m_decal)
- {
- m_decal->setOpacity(REAL_TO_INT(255.0f * o));
- }
-}
-
-// ------------------------------------------------------------------------------------------------
-void RadiusDecal::setPosition(const Coord3D& pos)
-{
- if (m_decal)
- {
- m_decal->setPosition(pos.x, pos.y, pos.z); //world space position of center of decal
- }
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/SelectionInfo.cpp b/Generals/Code/GameEngine/Source/GameClient/SelectionInfo.cpp
deleted file mode 100644
index 38e75a017f2..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/SelectionInfo.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h"
-#include "GameClient/SelectionInfo.h"
-
-#include "Common/ActionManager.h"
-#include "GameLogic/Damage.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/ThingTemplate.h"
-
-#include "GameClient/CommandXlat.h"
-#include "GameClient/ControlBar.h"
-#include "GameClient/Drawable.h"
-#include "GameClient/GameClient.h"
-#include "GameClient/KeyDefs.h"
-
-
-//-------------------------------------------------------------------------------------------------
-SelectionInfo::SelectionInfo() :
- currentCountEnemies(0),
- currentCountCivilians(0),
- currentCountMine(0),
- currentCountMineInfantry(0),
- currentCountMineBuildings(0),
- currentCountFriends(0),
- newCountEnemies(0),
- newCountCivilians(0),
- newCountCrates(0),
- newCountMine(0),
- newCountMineBuildings(0),
- newCountFriends(0),
- newCountGarrisonableBuildings(0),
- selectEnemies(FALSE),
- selectCivilians(FALSE),
- selectMine(FALSE),
- selectMineBuildings(FALSE),
- selectFriends(FALSE)
-{ }
-
-//-------------------------------------------------------------------------------------------------
-PickDrawableStruct::PickDrawableStruct() : drawableListToFill(nullptr)
-{
- drawableListToFill = FALSE;
- forceAttackMode = TheInGameUI->isInForceAttackMode();
- UnsignedInt pickType = getPickTypesForContext(forceAttackMode);
- translatePickTypesToKindof(pickType, kindofsToMatch);
- if (!forceAttackMode)
- {
- kindofsToMatch.set(KINDOF_ALWAYS_SELECTABLE);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/**
- * Given a list of currently selected things and a list of things that are currently under
- * the selection (pointer or drag), generate some useful information about each.
- */
-extern Bool contextCommandForNewSelection(const DrawableList *currentlySelectedDrawables,
- const DrawableList *newlySelectedDrawables,
- SelectionInfo *outSelectionInfo,
- Bool selectionIsPoint)
-{
- if (!(currentlySelectedDrawables && newlySelectedDrawables && outSelectionInfo))
- return FALSE;
-
- Bool forceFire = TheInGameUI->isInForceAttackMode();
- Bool forceMove = TheInGameUI->isInForceMoveToMode();
-
- if (forceFire || forceMove) {
- return FALSE;
- }
-
-
- Player *localPlayer = ThePlayerList->getLocalPlayer();
- DrawableListCIt it;
- for (it = currentlySelectedDrawables->begin(); it != currentlySelectedDrawables->end(); ++it) {
- if (!(*it)) {
- continue;
- }
-
- Object *obj = (*it)->getObject();
- if (!obj) {
- continue;
- }
-
- if (obj->isLocallyControlled()) {
- ++outSelectionInfo->currentCountMine;
- if (obj->isKindOf(KINDOF_INFANTRY)) {
- ++outSelectionInfo->currentCountMineInfantry;
- } else if (obj->isKindOf(KINDOF_STRUCTURE)) {
- ++outSelectionInfo->currentCountMineBuildings;
- }
- } else {
- Relationship rel = localPlayer->getRelationship(obj->getTeam());
- if (rel == ALLIES) {
- ++outSelectionInfo->currentCountFriends;
- } else if (rel == ENEMIES) {
- ++outSelectionInfo->currentCountEnemies;
- } else if (rel == NEUTRAL) {
- ++outSelectionInfo->currentCountCivilians;
- }
- }
- }
-
- Drawable *newMine = nullptr;
- Drawable *newFriendly = nullptr;
- Drawable *newEnemy = nullptr;
- Drawable *newCivilian = nullptr;
-
- for (it = newlySelectedDrawables->begin(); it != newlySelectedDrawables->end(); ++it) {
- if (!(*it)) {
- continue;
- }
-
- Object *obj = (*it)->getObject();
- if (!obj) {
- continue;
- }
-
- if (TheActionManager->canPlayerGarrison(localPlayer, obj, CMD_FROM_PLAYER)) {
- ++outSelectionInfo->newCountGarrisonableBuildings;
- }
- if (obj->isKindOf(KINDOF_CRATE)) {
- ++outSelectionInfo->newCountCrates;
- }
-
- if (obj->isLocallyControlled()) {
- ++outSelectionInfo->newCountMine;
- newMine = *it;
- if (obj->isKindOf(KINDOF_STRUCTURE)) {
- ++outSelectionInfo->newCountMineBuildings;
- }
- } else {
- Relationship rel = localPlayer->getRelationship(obj->getTeam());
- if (rel == ALLIES) {
- newFriendly = *it;
- ++outSelectionInfo->newCountFriends;
- } else if (rel == ENEMIES) {
- newEnemy = *it;
- ++outSelectionInfo->newCountEnemies;
- } else if (rel == NEUTRAL) {
- newCivilian = *it;
- ++outSelectionInfo->newCountCivilians;
- }
- }
- }
-
- DEBUG_ASSERTCRASH(outSelectionInfo->currentCountEnemies <= 1, ("Selection bug. jkmcd"));
- DEBUG_ASSERTCRASH(outSelectionInfo->currentCountFriends <= 1, ("Selection bug. jkmcd"));
- DEBUG_ASSERTCRASH(outSelectionInfo->currentCountCivilians <= 1, ("Selection bug. jkmcd"));
-
- if (outSelectionInfo->currentCountEnemies > 0) {
- // If we have an enemy selected, there are no context sensitive commands
- return FALSE;
- }
-
- if (outSelectionInfo->currentCountFriends > 0) {
- return FALSE;
- }
-
- if (outSelectionInfo->currentCountCivilians > 0) {
- return FALSE;
- }
-
- if (TheGlobalData->m_useAlternateMouse) {
- // context sensitive commands never apply when selecting in alternate mouse mode
- return FALSE;
- }
-
- if (outSelectionInfo->currentCountMine > 0) {
- if (outSelectionInfo->newCountEnemies > 0) {
- if (outSelectionInfo->newCountEnemies == 1 && selectionIsPoint) {
- return TheGameClient->evaluateContextCommand(newEnemy, newEnemy->getPosition(), CommandTranslator::EVALUATE_ONLY) != GameMessage::MSG_INVALID;
- }
-
- return selectionIsPoint;
- }
-
- if (outSelectionInfo->newCountMine > 0) {
- if (outSelectionInfo->newCountMine == 1 && selectionIsPoint && !TheInGameUI->isInPreferSelectionMode()) {
- return TheGameClient->evaluateContextCommand(newMine, newMine->getPosition(), CommandTranslator::EVALUATE_ONLY) != GameMessage::MSG_INVALID;
- }
-
- return FALSE;
- }
-
- if (outSelectionInfo->newCountFriends > 0) {
- if (outSelectionInfo->newCountFriends == 1 && selectionIsPoint) {
- return TheGameClient->evaluateContextCommand(newFriendly, newFriendly->getPosition(), CommandTranslator::EVALUATE_ONLY) != GameMessage::MSG_INVALID;
- }
- return FALSE;
- }
-
- if (outSelectionInfo->currentCountMineInfantry > 0 && outSelectionInfo->newCountGarrisonableBuildings == 1) {
- return TRUE;
- }
-
- if (outSelectionInfo->newCountCivilians > 0) {
- if (outSelectionInfo->newCountCivilians == 1 && selectionIsPoint) {
- return TheGameClient->evaluateContextCommand(newCivilian, newCivilian->getPosition(), CommandTranslator::EVALUATE_ONLY) != GameMessage::MSG_INVALID;
- }
- return FALSE;
- }
-
- if (outSelectionInfo->newCountCrates > 0) {
- return (outSelectionInfo->newCountCrates == 1 && selectionIsPoint);
- }
- }
-
- if (outSelectionInfo->currentCountMine == 0) {
- return FALSE;
- }
-
- return selectionIsPoint;
-}
-
-//-------------------------------------------------------------------------------------------------
-UnsignedInt getPickTypesForContext( Bool forceAttackMode )
-{
- UnsignedInt types = PICK_TYPE_SELECTABLE;
-
- if (forceAttackMode)
- types |= PICK_TYPE_FORCEATTACKABLE;
-
- //
- // if we have a gui context command that allows for a shrubbery target then we want to
- // pick that type too (generally shrubbery aren't pickable cause it would get in
- // the way with movement and general selection)
- //
- const CommandButton *command = TheInGameUI->getGUICommand();
-
- if (command != nullptr) {
- if (BitIsSet( command->getOptions(), ALLOW_MINE_TARGET)) {
- types |= PICK_TYPE_MINES;
- }
-
- if (BitIsSet( command->getOptions(), ALLOW_SHRUBBERY_TARGET ) ) {
- types |= PICK_TYPE_SHRUBBERY;
- }
- } else {
- types |= getPickTypesForCurrentSelection(forceAttackMode);
- }
-
- return types;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-UnsignedInt getPickTypesForCurrentSelection( Bool forceAttackMode )
-{
- UnsignedInt retVal = 0;
- if (!TheInGameUI->areSelectedObjectsControllable()) {
- return retVal;
- }
-
- const DrawableList *allSelectedDrawables = TheInGameUI->getAllSelectedDrawables();
-
- for (DrawableListCIt cit = allSelectedDrawables->begin(); cit != allSelectedDrawables->end(); ++cit) {
- Drawable *draw = *cit;
- if (!draw) {
- continue;
- }
-
- Object *obj = draw->getObject();
- if (!obj) {
- continue;
- }
-
-// srj sez: thanks to new, area-effect disarming, we NO LONGER want to do this...
-// if (obj->hasWeaponToDealDamageType(DAMAGE_DISARM)) {
-// retVal |= PICK_TYPE_MINES;
-// }
-
- if (obj->hasWeaponToDealDamageType(DAMAGE_FLAME) && forceAttackMode ) {
- retVal |= PICK_TYPE_SHRUBBERY;
- }
-
- // For efficiency.
- if (BitIsSet(retVal, PICK_TYPE_MINES | PICK_TYPE_SHRUBBERY)) {
- break;
- }
- }
-
- return retVal;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-void translatePickTypesToKindof(UnsignedInt pickTypes, KindOfMaskType& outMask)
-{
- if (BitIsSet(pickTypes, PICK_TYPE_SELECTABLE)) {
- outMask.set(KINDOF_SELECTABLE);
- }
-
- if (BitIsSet(pickTypes, PICK_TYPE_SHRUBBERY)) {
- outMask.set(KINDOF_SHRUBBERY);
- }
-
- if (BitIsSet(pickTypes, PICK_TYPE_MINES)) {
- outMask.set(KINDOF_MINE);
- }
-
- if (BitIsSet(pickTypes, PICK_TYPE_FORCEATTACKABLE)) {
- outMask.set(KINDOF_FORCEATTACKABLE);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-// Given a drawable, add it to an stl list specified by userData.
-// Useful for iterateDrawablesInRegion.
-Bool addDrawableToList( Drawable *draw, void *userData )
-{
- PickDrawableStruct *pds = (PickDrawableStruct *) userData;
-#if defined(RTS_DEBUG)
- if (TheGlobalData->m_allowUnselectableSelection) {
- pds->drawableListToFill->push_back(draw);
- return TRUE;
- }
-#endif
-
- if (!pds->drawableListToFill)
- return FALSE;
-
-#if !RTS_GENERALS || !PRESERVE_RETAIL_BEHAVIOR
- // TheSuperHackers @info
- // In retail, drag-selecting allows the player to select stealthed objects and objects through the
- // fog. Some players exploit this bug to determine where an opponent's units are and consider this
- // an important feature and an advanced skill to pull off, so we must leave the exploit.
- if (draw->getFullyObscuredByShroud())
- return FALSE;
-
- if (draw->isDrawableEffectivelyHidden())
- return FALSE;
-#endif
-
- if (!draw->getTemplate()->isAnyKindOf(pds->kindofsToMatch))
- return FALSE;
-
- if (!draw->isSelectable())
- return FALSE;
-
- pds->drawableListToFill->push_back(draw);
- return TRUE;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/Statistics.cpp b/Generals/Code/GameEngine/Source/GameClient/Statistics.cpp
deleted file mode 100644
index 3290a581a96..00000000000
--- a/Generals/Code/GameEngine/Source/GameClient/Statistics.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Statistics.cpp
-/*---------------------------------------------------------------------------*/
-/* EA Pacific */
-/* Confidential Information */
-/* Copyright (C) 2001 - All Rights Reserved */
-/* DO NOT DISTRIBUTE */
-/*---------------------------------------------------------------------------*/
-/* Project: RTS3 */
-/* File name: Statistics.cpp */
-/* Created: John K. McDonald, Jr., 4/2/2002 */
-/* Desc: Statistical functions should live here */
-/* Revision History: */
-/* 4/2/2002 : Initial creation */
-/*---------------------------------------------------------------------------*/
-
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "GameClient/Statistics.h"
-
-// Solution taken from http://www.epanorama.net/documents/telecom/ulaw_alaw.html
-Real MuLaw(Real valueToRun, Real maxValueForVal, Real mu)
-{
- Real testVal = (valueToRun - maxValueForVal / 2) / (maxValueForVal / 2);
- return (sign(testVal) * log(1 + mu * fabs(testVal)) /
- log(1 + mu));
-}
-
-// from my head. jkmcd
-Real Normalize(Real valueToNormalize, Real minRange, Real maxRange)
-{
- return ((valueToNormalize - minRange) / (maxRange - minRange));
-}
-
-// from my head again. jkmcd
-Real NormalizeToRange(Real valueToNormalize, Real minRange, Real maxRange, Real outRangeMin, Real outRangeMax)
-{
- return (Normalize(valueToNormalize, minRange, maxRange) * (outRangeMax - outRangeMin)) + outRangeMin;
-}
diff --git a/Generals/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp b/Generals/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp
index 13a7f51a8d0..e34a44bbc06 100644
--- a/Generals/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp
+++ b/Generals/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp
@@ -171,7 +171,7 @@ Mission *Campaign::getMission( AsciiString missionName )
return mission;
++it;
}
- DEBUG_ASSERTCRASH(FALSE, ("getMission couldn't find %s", missionName.str()));
+ DEBUG_CRASH(("getMission couldn't find %s", missionName.str()));
return nullptr;
}
@@ -199,7 +199,7 @@ Mission *Campaign::getNextMission( Mission *current)
return mission;
++it;
}
-// DEBUG_ASSERTCRASH(FALSE, ("GetNextMission couldn't find %s", current->m_nextMission.str()));
+// DEBUG_CRASH(("GetNextMission couldn't find %s", current->m_nextMission.str()));
return nullptr;
}
@@ -362,10 +362,10 @@ void CampaignManager::parseMissionPart( INI* ini, void *instance, void *store, c
{ "UnitNames0", INI::parseAsciiString, nullptr, offsetof( Mission, m_unitNames[0] ) },
{ "UnitNames1", INI::parseAsciiString, nullptr, offsetof( Mission, m_unitNames[1] ) },
{ "UnitNames2", INI::parseAsciiString, nullptr, offsetof( Mission, m_unitNames[2] ) },
+ { "GeneralName", INI::parseAsciiString, nullptr, offsetof( Mission, m_generalName) },
{ "LocationNameLabel",INI::parseAsciiString, nullptr, offsetof( Mission, m_locationNameLabel ) },
{ "VoiceLength", INI::parseInt , nullptr, offsetof( Mission, m_voiceLength ) },
-
{ nullptr, nullptr, nullptr, 0 }
};
AsciiString name;
diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
index 2e2dc8822cd..0aef033c71b 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
@@ -1117,8 +1117,8 @@ void Pathfinder::forceCleanCells()
TheAudio->addAudioEvent(&TheAudio->getMiscAudio()->m_allCheerSound);
PathfindCellInfo::forceCleanPathFindCellInfos();
- m_openList = nullptr;
- m_closedList = nullptr;
+ m_openList.reset();
+ m_closedList.reset();
for (int j = 0; j <= m_extent.hi.y; ++j) {
for (int i = 0; i <= m_extent.hi.x; ++i) {
@@ -1665,70 +1665,67 @@ void PathfindCell::removeObstacle( Object *obstacle )
}
/// put self on "open" list in ascending cost order, return new list
-PathfindCell *PathfindCell::putOnSortedOpenList( PathfindCell *list )
+void PathfindCell::putOnSortedOpenList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
- DEBUG_ASSERTCRASH(m_info->m_closed==FALSE && m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
- if (list == nullptr)
+ DEBUG_ASSERTCRASH(m_info->m_closed == FALSE && m_info->m_open == FALSE, ("Serious error - Invalid flags. jba"));
+
+ // mark the newCell as being on the open list
+ m_info->m_open = true;
+ m_info->m_closed = false;
+
+ if (list.m_head == nullptr)
{
- list = this;
+ list.m_head = this;
m_info->m_prevOpen = nullptr;
m_info->m_nextOpen = nullptr;
+ return;
}
- else
- {
- // insertion sort
- PathfindCell *c, *lastCell = nullptr;
+
+ // insertion sort
+ PathfindCell* currentCell = list.m_head;
+ PathfindCell* previousCell = nullptr;
#if RETAIL_COMPATIBLE_PATHFINDING
- // TheSuperHackers @bugfix In the retail compatible pathfinding, on rare occasions, we get stuck in an infinite loop
- // External code should pickup on the bad behaviour and cleanup properly, but we need to explicitly break out here
- // The fixed pathfinding does not have this issue due to the proper cleanup of pathfindCells and their pathfindCellInfos
- UnsignedInt cellCount = 0;
- for (c = list; c && cellCount < PATHFIND_CELLS_PER_FRAME; c = c->getNextOpen())
- {
- cellCount++;
+ // TheSuperHackers @bugfix In the retail compatible pathfinding, on rare occasions, we get stuck in an infinite loop
+ // External code should pickup on the bad behaviour and cleanup properly, but we need to explicitly break out here
+ // The fixed pathfinding does not have this issue due to the proper cleanup of pathfindCells and their pathfindCellInfos
+ UnsignedInt cellCount = 0;
+ while (currentCell && cellCount < PATHFIND_CELLS_PER_FRAME && currentCell->m_info->m_totalCost <= m_info->m_totalCost)
+ {
+ cellCount++;
#else
- for (c = list; c; c = c->getNextOpen())
- {
+ while (currentCell && currentCell->m_info->m_totalCost <= m_info->m_totalCost)
+ {
#endif
- if (c->m_info->m_totalCost > m_info->m_totalCost)
- break;
-
- lastCell = c;
- }
+ previousCell = currentCell;
+ currentCell = currentCell->getNextOpen();
+ }
- if (c)
- {
- // insert just before "c"
- if (c->m_info->m_prevOpen)
- c->m_info->m_prevOpen->m_nextOpen = this->m_info;
- else
- list = this;
+ if (currentCell)
+ {
+ // insert just before "currentCell"
+ if (currentCell->m_info->m_prevOpen)
+ currentCell->m_info->m_prevOpen->m_nextOpen = this->m_info;
+ else
+ list.m_head = this;
- m_info->m_prevOpen = c->m_info->m_prevOpen;
- c->m_info->m_prevOpen = this->m_info;
+ m_info->m_prevOpen = currentCell->m_info->m_prevOpen;
+ currentCell->m_info->m_prevOpen = this->m_info;
- m_info->m_nextOpen = c->m_info;
+ m_info->m_nextOpen = currentCell->m_info;
- }
- else
- {
- // append after "lastCell" - end of list
- lastCell->m_info->m_nextOpen = this->m_info;
- m_info->m_prevOpen = lastCell->m_info;
- m_info->m_nextOpen = nullptr;
- }
}
-
- // mark newCell as being on open list
- m_info->m_open = true;
- m_info->m_closed = false;
-
- return list;
+ else
+ {
+ // append after "previousCell" - we are at the end of the list
+ previousCell->m_info->m_nextOpen = this->m_info;
+ m_info->m_prevOpen = previousCell->m_info;
+ m_info->m_nextOpen = nullptr;
+ }
}
/// remove self from "open" list
-PathfindCell *PathfindCell::removeFromOpenList( PathfindCell *list )
+void PathfindCell::removeFromOpenList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==FALSE && m_info->m_open==TRUE, ("Serious error - Invalid flags. jba"));
@@ -1738,25 +1735,24 @@ PathfindCell *PathfindCell::removeFromOpenList( PathfindCell *list )
if (m_info->m_prevOpen)
m_info->m_prevOpen->m_nextOpen = m_info->m_nextOpen;
else
- list = getNextOpen();
+ list.m_head = getNextOpen();
m_info->m_open = false;
m_info->m_nextOpen = nullptr;
m_info->m_prevOpen = nullptr;
- return list;
}
/// remove all cells from "open" list
-Int PathfindCell::releaseOpenList( PathfindCell *list )
+Int PathfindCell::releaseOpenList( PathfindCellList &list )
{
Int count = 0;
- while (list) {
+ while (list.m_head) {
count++;
- DEBUG_ASSERTCRASH(list->m_info, ("Has to have info."));
- DEBUG_ASSERTCRASH(list->m_info->m_closed==FALSE && list->m_info->m_open==TRUE, ("Serious error - Invalid flags. jba"));
- PathfindCell *cur = list;
- PathfindCellInfo *curInfo = list->m_info;
+ DEBUG_ASSERTCRASH(list.m_head->m_info, ("Has to have info."));
+ DEBUG_ASSERTCRASH(list.m_head->m_info->m_closed==FALSE && list.m_head->m_info->m_open==TRUE, ("Serious error - Invalid flags. jba"));
+ PathfindCell *cur = list.m_head;
+ PathfindCellInfo *curInfo = list.m_head->m_info;
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info This is only here to catch a crash point in the retail compatible pathfinding
@@ -1770,9 +1766,9 @@ Int PathfindCell::releaseOpenList( PathfindCell *list )
#endif
if (curInfo->m_nextOpen) {
- list = curInfo->m_nextOpen->m_cell;
+ list.m_head = curInfo->m_nextOpen->m_cell;
} else {
- list = nullptr;
+ list.m_head = nullptr;
}
DEBUG_ASSERTCRASH(cur == curInfo->m_cell, ("Bad backpointer in PathfindCellInfo"));
curInfo->m_nextOpen = nullptr;
@@ -1784,15 +1780,15 @@ Int PathfindCell::releaseOpenList( PathfindCell *list )
}
/// remove all cells from "closed" list
-Int PathfindCell::releaseClosedList( PathfindCell *list )
+Int PathfindCell::releaseClosedList( PathfindCellList &list )
{
Int count = 0;
- while (list) {
+ while (list.m_head) {
count++;
- DEBUG_ASSERTCRASH(list->m_info, ("Has to have info."));
- DEBUG_ASSERTCRASH(list->m_info->m_closed==TRUE && list->m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
- PathfindCell *cur = list;
- PathfindCellInfo *curInfo = list->m_info;
+ DEBUG_ASSERTCRASH(list.m_head->m_info, ("Has to have info."));
+ DEBUG_ASSERTCRASH(list.m_head->m_info->m_closed==TRUE && list.m_head->m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
+ PathfindCell *cur = list.m_head;
+ PathfindCellInfo *curInfo = list.m_head->m_info;
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info This is only here to catch a crash point in the retail compatible pathfinding
// One crash mode is where a cell has no PathfindCellInfo, resulting in a nullptr access and a crash.
@@ -1805,9 +1801,9 @@ Int PathfindCell::releaseClosedList( PathfindCell *list )
#endif
if (curInfo->m_nextOpen) {
- list = curInfo->m_nextOpen->m_cell;
+ list.m_head = curInfo->m_nextOpen->m_cell;
} else {
- list = nullptr;
+ list.m_head = nullptr;
}
DEBUG_ASSERTCRASH(cur == curInfo->m_cell, ("Bad backpointer in PathfindCellInfo"));
curInfo->m_nextOpen = nullptr;
@@ -1819,7 +1815,7 @@ Int PathfindCell::releaseClosedList( PathfindCell *list )
}
/// put self on "closed" list, return new list
-PathfindCell *PathfindCell::putOnClosedList( PathfindCell *list )
+void PathfindCell::putOnClosedList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==FALSE && m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
@@ -1830,18 +1826,17 @@ PathfindCell *PathfindCell::putOnClosedList( PathfindCell *list )
m_info->m_closed = TRUE;
m_info->m_prevOpen = nullptr;
- m_info->m_nextOpen = list?list->m_info:nullptr;
- if (list)
- list->m_info->m_prevOpen = this->m_info;
+ m_info->m_nextOpen = list.m_head ? list.m_head->m_info : nullptr;
+ if (list.m_head)
+ list.m_head->m_info->m_prevOpen = this->m_info;
- list = this;
+ list.m_head = this;
}
- return list;
}
/// remove self from "closed" list
-PathfindCell *PathfindCell::removeFromClosedList( PathfindCell *list )
+void PathfindCell::removeFromClosedList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==TRUE && m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
@@ -1851,13 +1846,12 @@ PathfindCell *PathfindCell::removeFromClosedList( PathfindCell *list )
if (m_info->m_prevOpen)
m_info->m_prevOpen->m_nextOpen = m_info->m_nextOpen;
else
- list = getNextOpen();
+ list.m_head = getNextOpen();
m_info->m_closed = false;
m_info->m_nextOpen = nullptr;
m_info->m_prevOpen = nullptr;
- return list;
}
/**
@@ -3654,8 +3648,8 @@ void Pathfinder::reset( void )
// reset the pathfind grid
m_extent.lo.x=m_extent.lo.y=m_extent.hi.x=m_extent.hi.y=0;
m_logicalExtent.lo.x=m_logicalExtent.lo.y=m_logicalExtent.hi.x=m_logicalExtent.hi.y=0;
- m_openList = nullptr;
- m_closedList = nullptr;
+ m_openList.reset();
+ m_closedList.reset();
m_ignoreObstacleID = INVALID_ID;
m_isTunneling = false;
@@ -4351,7 +4345,7 @@ void Pathfinder::debugShowSearch( Bool pathFound )
addIcon(nullptr, 0, 0, color); // erase.
}
- for( s = m_openList; s; s=s->getNextOpen() )
+ for( s = m_openList.getHead(); s; s=s->getNextOpen() )
{
// create objects to show path - they decay
RGBColor color;
@@ -4365,7 +4359,7 @@ void Pathfinder::debugShowSearch( Bool pathFound )
addIcon(&pos, PATHFIND_CELL_SIZE_F*.6f, 200, color);
}
- for( s = m_closedList; s; s=s->getNextOpen() )
+ for( s = m_closedList.getHead(); s; s=s->getNextOpen() )
{
// create objects to show path - they decay
RGBColor color;
@@ -4454,9 +4448,9 @@ Bool Pathfinder::validMovementTerrain( PathfindLayerEnum layer, const Locomotor*
//
void Pathfinder::cleanOpenAndClosedLists(void) {
Int count = 0;
- if (m_openList) {
+ if (!m_openList.empty()) {
count += PathfindCell::releaseOpenList(m_openList);
- m_openList = nullptr;
+ m_openList.reset();
}
#if RETAIL_COMPATIBLE_PATHFINDING
@@ -4469,9 +4463,9 @@ void Pathfinder::cleanOpenAndClosedLists(void) {
}
#endif
- if (m_closedList) {
+ if (!m_closedList.empty()) {
count += PathfindCell::releaseClosedList(m_closedList);
- m_closedList = nullptr;
+ m_closedList.reset();
}
#if RETAIL_COMPATIBLE_PATHFINDING
@@ -5579,7 +5573,7 @@ void Pathfinder::checkChangeLayers(PathfindCell *parentCell)
newCell->setCostSoFar(parentCell->getCostSoFar()); // same as parent cost
newCell->setTotalCost(parentCell->getTotalCost());
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
bool Pathfinder::checkCellOutsideExtents(ICoord2D& cell) {
@@ -5678,14 +5672,14 @@ struct ExamineCellsStruct
// if to was on closed list, remove it from the list
if (to->getClosed())
- d->thePathfinder->m_closedList = to->removeFromClosedList( d->thePathfinder->m_closedList );
+ to->removeFromClosedList( d->thePathfinder->m_closedList );
// if the to was already on the open list, remove it so it can be re-inserted in order
if (to->getOpen())
- d->thePathfinder->m_openList = to->removeFromOpenList( d->thePathfinder->m_openList );
+ to->removeFromOpenList( d->thePathfinder->m_openList );
// insert to in open list such that open list is sorted, smallest total path cost first
- d->thePathfinder->m_openList = to->putOnSortedOpenList( d->thePathfinder->m_openList );
+ to->putOnSortedOpenList( d->thePathfinder->m_openList );
}
return 0; // keep going
@@ -5912,14 +5906,14 @@ Int Pathfinder::examineNeighboringCells(PathfindCell *parentCell, PathfindCell *
// if newCell was on closed list, remove it from the list
if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
+ newCell->removeFromClosedList( m_closedList );
// if the newCell was already on the open list, remove it so it can be re-inserted in order
if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
+ newCell->removeFromOpenList( m_openList );
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
return cellCount;
}
@@ -5985,7 +5979,7 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
DEBUG_LOG(("Attempting pathfind to 0,0, generally a bug."));
return nullptr;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
if (m_isMapReady == false) {
return nullptr;
}
@@ -6097,10 +6091,19 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
parentCell->startPathfind(goalCell);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
Int cellCount = 0;
@@ -6108,11 +6111,11 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
if (parentCell == goalCell)
{
@@ -6155,7 +6158,7 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
@@ -6491,7 +6494,7 @@ struct GroundCellsStruct
to->setTotalCost(to->getCostSoFar() + costRemaining) ;
// insert to in open list such that open list is sorted, smallest total path cost first
- d->thePathfinder->m_openList = to->putOnSortedOpenList( d->thePathfinder->m_openList );
+ to->putOnSortedOpenList( d->thePathfinder->m_openList );
}
return 0; // keep going
@@ -6527,7 +6530,7 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
DEBUG_LOG(("Attempting pathfind to 0,0, generally a bug."));
return nullptr;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
if (m_isMapReady == false) {
return nullptr;
}
@@ -6620,10 +6623,19 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
parentCell->startPathfind(goalCell);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
// TheSuperHackers @fix helmutbuhler This was originally uninitialized and in the loop below.
#if RETAIL_COMPATIBLE_CRC
@@ -6635,11 +6647,11 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
// until goal is found.
//
Int cellCount = 0;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
if (parentCell == goalCell)
{
@@ -6672,7 +6684,7 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
@@ -6807,14 +6819,14 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
// if newCell was on closed list, remove it from the list
if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
+ newCell->removeFromClosedList( m_closedList );
// if the newCell was already on the open list, remove it so it can be re-inserted in order
if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
+ newCell->removeFromOpenList( m_openList );
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
}
// failure - goal cannot be reached
@@ -6932,14 +6944,14 @@ void Pathfinder::processHierarchicalCell( const ICoord2D &scanCell, const ICoord
if (!s_useFixedPathfinding)
{
if (!newCell->getClosed() && !newCell->getOpen()) {
- m_closedList = newCell->putOnClosedList(m_closedList);
+ newCell->putOnClosedList(m_closedList);
}
}
else
#endif
{
if (newCell->hasInfo() && !newCell->getClosed() && !newCell->getOpen()) {
- m_closedList = newCell->putOnClosedList(m_closedList);
+ newCell->putOnClosedList(m_closedList);
}
}
@@ -6958,7 +6970,7 @@ void Pathfinder::processHierarchicalCell( const ICoord2D &scanCell, const ICoord
adjNewCell->setTotalCost(adjNewCell->getCostSoFar()+remCost);
adjNewCell->setParentCellHierarchical(parentCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = adjNewCell->putOnSortedOpenList( m_openList );
+ adjNewCell->putOnSortedOpenList( m_openList );
}
}
@@ -7003,7 +7015,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
DEBUG_LOG(("Attempting pathfind to 0,0, generally a bug."));
return nullptr;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
if (m_isMapReady == false) {
return nullptr;
}
@@ -7060,7 +7072,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
parentCell->startPathfind(goalCell);
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
Int cellCount = 0;
@@ -7079,7 +7091,16 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
}
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
if (parentCell->getLayer()!=LAYER_GROUND) {
PathfindLayerEnum layer = parentCell->getLayer();
@@ -7092,8 +7113,8 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
PathfindCell *startCell = getCell(LAYER_GROUND, ndx.x, ndx.y);
if (cell && startCell) {
// Close parent cell;
- m_openList = parentCell->removeFromOpenList(m_openList);
- m_closedList = parentCell->putOnClosedList(m_closedList);
+ parentCell->removeFromOpenList(m_openList);
+ parentCell->putOnClosedList(m_closedList);
if (!startCell->allocateInfo(ndx)) {
// TheSuperHackers @info We need to forcefully cleanup dangling pathfinding cells if this failure condition is hit in retail
// Retail clients will crash beyond this point, but we attempt to recover by performing a full cleanup then enabling the fixed pathfinding codepath
@@ -7118,7 +7139,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
startCell->setTotalCost(remCost);
startCell->setParentCellHierarchical(parentCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = startCell->putOnSortedOpenList( m_openList );
+ startCell->putOnSortedOpenList( m_openList );
cellCount++;
if(!cell->allocateInfo(toNdx)) {
@@ -7143,7 +7164,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
cell->setTotalCost(remCost);
cell->setParentCellHierarchical(parentCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = cell->putOnSortedOpenList( m_openList );
+ cell->putOnSortedOpenList( m_openList );
}
}
@@ -7154,11 +7175,11 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
zoneStorageType parentZone;
if (parentCell->getLayer()==LAYER_GROUND) {
@@ -7242,7 +7263,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
}
startCell->setParentCellHierarchical(parentCell);
if (!startCell->getClosed() && !startCell->getOpen()) {
- m_closedList = startCell->putOnClosedList(m_closedList);
+ startCell->putOnClosedList(m_closedList);
}
}
if(!cell->allocateInfo(toNdx)) {
@@ -7271,7 +7292,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
cell->setTotalCost(cell->getCostSoFar()+remCost);
cell->setParentCellHierarchical(startCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = cell->putOnSortedOpenList( m_openList );
+ cell->putOnSortedOpenList( m_openList );
}
}
@@ -7340,7 +7361,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
Int i;
zoneStorageType examinedZones[PathfindZoneManager::ZONE_BLOCK_SIZE];
@@ -7699,251 +7720,6 @@ void Pathfinder::clip( Coord3D *from, Coord3D *to )
}
-Bool Pathfinder::pathDestination( Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest,
- PathfindLayerEnum layer, const Coord3D *groupDest)
-{
- //CRCDEBUG_LOG(("Pathfinder::pathDestination()"));
- if (m_isMapReady == false) return false;
-
- if (!obj) return false;
-
- Int cellCount = 0;
-
- Coord3D adjustTo = *groupDest;
- Coord3D *to = &adjustTo;
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
- // create unique "mark" values for open and closed cells for this pathfind invocation
-
- Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
-
- PathfindLayerEnum desiredLayer = TheTerrainLogic->getLayerForDestination(dest);
- // determine desired
- PathfindCell *desiredCell = getClippedCell( desiredLayer, dest );
- if (desiredCell == nullptr)
- return FALSE;
-
- PathfindLayerEnum goalLayer = TheTerrainLogic->getLayerForDestination(to);
- // determine goal cell
- PathfindCell *goalCell = getClippedCell( goalLayer, to );
- if (goalCell == nullptr)
- return FALSE;
-
-
- Bool isHuman = true;
- if (obj && obj->getControllingPlayer() && (obj->getControllingPlayer()->getPlayerType()==PLAYER_COMPUTER)) {
- isHuman = false; // computer gets to cheat.
- }
- Bool center;
- Int radius;
- getRadiusAndCenter(obj, radius, center);
-
- // determine start cell
- ICoord2D startCellNdx;
- worldToCell(dest, &startCellNdx);
- PathfindCell *parentCell = getCell( layer, startCellNdx.x, startCellNdx.y );
- if (parentCell == nullptr)
- return FALSE;
- ICoord2D pos2d;
- worldToCell(to, &pos2d);
- if (!goalCell->allocateInfo(pos2d)) {
- return FALSE;
- }
-
- if (parentCell!=goalCell) {
- if (!parentCell->allocateInfo(startCellNdx)) {
-#if RETAIL_COMPATIBLE_PATHFINDING
- if (!s_useFixedPathfinding) {
- desiredCell->releaseInfo();
- }
-#endif
- goalCell->releaseInfo();
- return FALSE;
- }
- }
-
- PathfindCell *closestCell = nullptr;
- Real closestDistanceSqr = FLT_MAX;
- Coord3D closestPos;
-
- if (validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), parentCell ) == false) {
- parentCell->releaseInfo();
- goalCell->releaseInfo();
- return FALSE;
- }
-
- parentCell->startPathfind(goalCell);
-
- // initialize "open" list to contain start cell
- m_openList = parentCell;
-
- // "closed" list is initially empty
- m_closedList = nullptr;
-
- //
- // Continue search until "open" list is empty, or
- // until goal is found.
- //
- while( m_openList != nullptr )
- {
- // take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
-
- Coord3D pos;
- // put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
- if (checkForAdjust(obj, locomotorSet, isHuman, parentCell->getXIndex(), parentCell->getYIndex(), parentCell->getLayer(),
- radius, center, &pos, groupDest)) {
- Int dx = IABS(goalCell->getXIndex()-parentCell->getXIndex());
- Int dy = IABS(goalCell->getYIndex()-parentCell->getYIndex());
- Real distSqr = dx*dx+dy*dy;
-
- if (distSqr < closestDistanceSqr) {
- closestCell = parentCell;
- closestDistanceSqr = distSqr;
- closestPos = pos;
- } else {
- continue;
- }
- } else {
- continue;
- }
-
- if (cellCount > MAX_CELL_COUNT) {
- continue;
- }
- // Check to see if we can change layers in this cell.
- checkChangeLayers(parentCell);
-
- // expand search to neighboring orthogonal cells
- static ICoord2D delta[] =
- {
- { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 },
- { 1, 1 }, { -1, 1 }, { -1, -1 }, { 1, -1 }
- };
- const Int numNeighbors = 8;
- const Int firstDiagonal = 4;
- ICoord2D newCellCoord;
- PathfindCell *newCell;
- const Int adjacent[5] = {0, 1, 2, 3, 0};
- Bool neighborFlags[8] = { 0 };
-
- UnsignedInt newCostSoFar = 0;
-
- for( int i=0; igetXIndex() + delta[i].x;
- newCellCoord.y = parentCell->getYIndex() + delta[i].y;
-
- // get the neighboring cell
- newCell = getCell(parentCell->getLayer(), newCellCoord.x, newCellCoord.y );
-
- // check if cell is on the map
- if (newCell == nullptr)
- continue;
-
- // check if this neighbor cell is already on the open (waiting to be tried)
- // or closed (already tried) lists
- Bool onList = false;
- if (newCell->hasInfo()) {
- if (newCell->getOpen() || newCell->getClosed())
- {
- // already on one of the lists
- onList = true;
- }
- }
- if (i>=firstDiagonal) {
- // make sure one of the adjacent sides is open.
- if (!neighborFlags[adjacent[i-4]] && !neighborFlags[adjacent[i-3]]) {
- continue;
- }
- }
-
- if (!validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), newCell, parentCell )) {
- continue;
- }
-
- neighborFlags[i] = true;
-
- if (!newCell->allocateInfo(newCellCoord)) {
- // Out of cells for pathing...
-#if RETAIL_COMPATIBLE_PATHFINDING
- if (s_useFixedPathfinding)
-#endif
- {
- cleanOpenAndClosedLists();
- goalCell->releaseInfo();
- }
- return cellCount;
- }
- cellCount++;
-
- newCostSoFar = newCell->costSoFar( parentCell );
- newCell->setBlockedByAlly(false);
-
- // check if this neighbor cell is already on the open (waiting to be tried)
- // or closed (already tried) lists
- if (onList)
- {
- // already on one of the lists - if existing costSoFar is less,
- // the new cell is on a longer path, so skip it
- if (newCell->getCostSoFar() <= newCostSoFar)
- continue;
- }
-
- // keep track of path we're building - point back to cell we moved here from
- newCell->setParentCell(parentCell) ;
-
- // store cost of this path
- newCell->setCostSoFar(newCostSoFar);
-
- Int costRemaining = 0;
- if (goalCell) {
- costRemaining = newCell->costToGoal( goalCell );
- }
-
- newCell->setTotalCost(newCell->getCostSoFar() + costRemaining) ;
-
- // if newCell was on closed list, remove it from the list
- if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
-
- // if the newCell was already on the open list, remove it so it can be re-inserted in order
- if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
-
- // insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
- }
- }
-
-#if defined(RTS_DEBUG)
- if (closestCell) {
- debugShowSearch(true);
- *dest = closestPos;
- } else {
- debugShowSearch(true);
- }
-#endif
- m_isTunneling = false;
-#if RETAIL_COMPATIBLE_PATHFINDING
- if (!s_useFixedPathfinding) {
- cleanOpenAndClosedLists();
- goalCell->releaseInfo();
- }
- else
-#endif
- {
- cleanOpenAndClosedLists();
- parentCell->releaseInfo();
- goalCell->releaseInfo();
- }
-
- return false;
-}
-
struct TightenPathStruct
{
Object *obj;
@@ -8005,7 +7781,7 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
Coord3D adjustTo = *rawTo;
Coord3D *to = &adjustTo;
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// create unique "mark" values for open and closed cells for this pathfind invocation
Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
@@ -8050,25 +7826,34 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
parentCell->startPathfind(goalCell);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
// put parent cell onto closed list - its evaluation is finished - Retail compatible behaviour
#if RETAIL_COMPATIBLE_PATHFINDING
if (!s_useFixedPathfinding) {
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
}
#endif
@@ -8090,7 +7875,7 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
if (s_useFixedPathfinding)
#endif
{
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
}
if (cellCount > MAX_CELL_COUNT) {
@@ -8193,16 +7978,16 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
// if newCell was on closed list, remove it from the list
if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
+ newCell->removeFromClosedList( m_closedList );
// if the newCell was already on the open list, remove it so it can be re-inserted in order
if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
+ newCell->removeFromOpenList( m_openList );
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHacker @info This is here to catch a retail pathfinding crash point and to recover from it
// A cell has gotten onto the open list without pathfinding info due to a danling m_open pointer on the previous listed cell so we need to force a cleanup
- if (!s_useFixedPathfinding && m_openList && !m_openList->hasInfo()) {
+ if (!s_useFixedPathfinding && m_openList.getHead() && !m_openList.getHead()->hasInfo()) {
s_useFixedPathfinding = true;
forceCleanCells();
return MAX_COST;
@@ -8210,7 +7995,7 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
#endif
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
}
@@ -8274,7 +8059,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
adjustTo.x += PATHFIND_CELL_SIZE_F/2;
adjustTo.y += PATHFIND_CELL_SIZE_F/2;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// create unique "mark" values for open and closed cells for this pathfind invocation
Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
@@ -8379,23 +8164,32 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
Real closestDistScreenSqr = FLT_MAX;
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
Int count = 0;
//
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
Real dx;
Real dy;
Real distSqr;
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
if (parentCell == goalCell)
{
@@ -8411,7 +8205,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
#ifdef INTENSE_DEBUG
Int count = 0;
PathfindCell *cur;
- for (cur = m_closedList; cur; cur=cur->getNextOpen()) {
+ for (cur = m_closedList.getHead(); cur; cur=cur->getNextOpen()) {
count++;
}
if (count>1000) {
@@ -8448,7 +8242,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
return path;
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
if (!m_isTunneling && checkDestination(obj, parentCell->getXIndex(), parentCell->getYIndex(), parentCell->getLayer(), radius, centerInCell)) {
if (!startedStuck || validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), parentCell )) {
dx = IABS(goalCell->getXIndex()-parentCell->getXIndex());
@@ -9849,7 +9643,7 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
Int radius;
getRadiusAndCenter(obj, radius, centerInCell);
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// determine start cell
ICoord2D startCellNdx;
@@ -9890,10 +9684,19 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
parentCell->startPathfind(nullptr);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -9905,11 +9708,11 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
boxHalfWidth += otherRadius*PATHFIND_CELL_SIZE_F;
if (otherCenter) boxHalfWidth+=PATHFIND_CELL_SIZE_F/2;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Region2D bounds;
Coord3D cellCenter;
@@ -9975,7 +9778,7 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
return newPath;
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
@@ -10026,7 +9829,7 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
m_zoneManager.setAllPassable();
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
enum {CELL_LIMIT = 2000}; // max cells to examine.
Int cellCount = 0;
@@ -10057,10 +9860,19 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
parentCell->startPathfind( nullptr);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -10141,11 +9953,11 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
return nullptr;
}
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Coord3D cellCenter;
adjustCoordToCell(parentCell->getXIndex(), parentCell->getYIndex(), centerInCell, cellCenter, parentCell->getLayer());
@@ -10189,7 +10001,7 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
return path;
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
if (cellCount < CELL_LIMIT) {
// Check to see if we can change layers in this cell.
@@ -10300,7 +10112,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
Int cellCount = 0;
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
Int attackDistance = weapon->getAttackDistance(obj, victim, victimPos);
attackDistance += 3*PATHFIND_CELL_SIZE;
@@ -10342,10 +10154,19 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
}
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -10362,11 +10183,11 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
checkLOS = true;
}
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Coord3D cellCenter;
adjustCoordToCell(parentCell->getXIndex(), parentCell->getYIndex(), centerInCell, cellCenter, parentCell->getLayer());
@@ -10406,7 +10227,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
#ifdef INTENSE_DEBUG
Int count = 0;
PathfindCell *cur;
- for (cur = m_closedList; cur; cur=cur->getNextOpen()) {
+ for (cur = m_closedList.getHead(); cur; cur=cur->getNextOpen()) {
count++;
}
if (count>1000) {
@@ -10458,7 +10279,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
if (cellCount < ATTACK_CELL_LIMIT) {
// Check to see if we can change layers in this cell.
@@ -10535,7 +10356,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
isHuman = false; // computer gets to cheat.
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// create unique "mark" values for open and closed cells for this pathfind invocation
m_zoneManager.setAllPassable();
@@ -10554,10 +10375,19 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
parentCell->startPathfind( nullptr);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -10566,11 +10396,11 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
Real farthestDistanceSqr = 0;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Coord3D cellCenter;
adjustCoordToCell(parentCell->getXIndex(), parentCell->getYIndex(), centerInCell, cellCenter, parentCell->getLayer());
@@ -10589,7 +10419,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
if (distSqr>repulsorDistSqr) {
ok = true;
}
- if (m_openList == nullptr && cellCount>0) {
+ if (m_openList.empty() && cellCount>0) {
ok = true; // exhausted the search space, just take the last cell.
}
if (distSqr > farthestDistanceSqr) {
@@ -10609,7 +10439,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
#ifdef INTENSE_DEBUG
Int count = 0;
PathfindCell *cur;
- for (cur = m_closedList; cur; cur=cur->getNextOpen()) {
+ for (cur = m_closedList.getHead(); cur; cur=cur->getNextOpen()) {
count++;
}
if (count>2000) {
@@ -10646,7 +10476,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp
index 94d9447cd1a..d506631a26a 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp
@@ -158,7 +158,7 @@ void PoisonedBehavior::startPoisonedEffects( const DamageInfo *damageInfo )
// We are going to take the damage dealt by the original poisoner every so often for a while.
m_poisonDamageAmount = damageInfo->out.m_actualDamageDealt;
-#if !RETAIL_COMPATIBLE_CRC
+#if !RETAIL_COMPATIBLE_CRC && !PRESERVE_RETAIL_BEHAVIOR
// TheSuperHackers @bugfix Stubbjax 03/09/2025 Allow poison damage to award xp to the poison source.
m_poisonSource = damageInfo->in.m_sourceID;
#endif
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp
index 411c4aaee6a..af57e479ecc 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp
@@ -984,6 +984,7 @@ void SpawnBehavior::crc( Xfer *xfer )
* Version Info:
* 1: Initial version
* 2: Added m_initialBurstTimesInited to the save. jba.
+ * 3: TheSuperHackers @bugfix Stubbjax 16/02/2026 Added m_initialBurstCountdown.
*/
// ------------------------------------------------------------------------------------------------
void SpawnBehavior::xfer( Xfer *xfer )
@@ -991,7 +992,11 @@ void SpawnBehavior::xfer( Xfer *xfer )
AsciiString name;
// version
+#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 2;
+#else
+ XferVersion currentVersion = 3;
+#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
@@ -1003,6 +1008,10 @@ void SpawnBehavior::xfer( Xfer *xfer )
xfer->xferBool(&m_initialBurstTimesInited);
}
+ if (version >= 3) {
+ xfer->xferUnsignedInt(&m_initialBurstCountdown);
+ }
+
// spawn template
name = m_spawnTemplate ? m_spawnTemplate->getName() : AsciiString::TheEmptyString;
xfer->xferAsciiString( &name );
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp
index 5b3b3eb3900..680456627c5 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp
@@ -50,6 +50,7 @@ CrateCollideModuleData::CrateCollideModuleData()
m_executeAnimationFades = TRUE;
m_isBuildingPickup = FALSE;
m_isHumanOnlyPickup = FALSE;
+ m_allowMultiPickup = (PRESERVE_RETAIL_BEHAVIOR != 0);
m_executeFX = nullptr;
m_pickupScience = SCIENCE_INVALID;
m_executionAnimationTemplate = AsciiString::TheEmptyString;
@@ -68,6 +69,7 @@ void CrateCollideModuleData::buildFieldParse(MultiIniFieldParse& p)
{ "ForbidOwnerPlayer", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_isForbidOwnerPlayer ) },
{ "BuildingPickup", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_isBuildingPickup ) },
{ "HumanOnly", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_isHumanOnlyPickup ) },
+ { "AllowMultiPickup", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_allowMultiPickup ) },
{ "PickupScience", INI::parseScience, nullptr, offsetof( CrateCollideModuleData, m_pickupScience ) },
{ "ExecuteFX", INI::parseFXList, nullptr, offsetof( CrateCollideModuleData, m_executeFX ) },
{ "ExecuteAnimation", INI::parseAsciiString, nullptr, offsetof( CrateCollideModuleData, m_executionAnimationTemplate ) },
@@ -164,7 +166,7 @@ Bool CrateCollide::isValidToExecute( const Object *other ) const
// TheSuperHackers @bugfix Stubbjax 09/02/2026 Prevent the crate from being collected multiple times in a single frame.
#if !RETAIL_COMPATIBLE_CRC
- if (getObject()->isDestroyed())
+ if (getObject()->isDestroyed() && !md->m_allowMultiPickup)
return FALSE;
#endif
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
index edcc8752856..fce643b3b3c 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
@@ -126,7 +126,6 @@ OpenContain::OpenContain( Thing *thing, const ModuleData* moduleData ) : UpdateM
m_containListSize = 0;
m_stealthUnitsContained = 0;
m_heroUnitsContained = 0;
- m_xferVersion = 1;
m_doorCloseCountdown = 0;
m_rallyPoint.zero();
@@ -1461,21 +1460,15 @@ void OpenContain::crc( Xfer *xfer )
/** Xfer method
* Version Info:
* 1: Initial version
- * 2: TheSuperHackers @tweak Serialize hero units contained count
*/
// ------------------------------------------------------------------------------------------------
void OpenContain::xfer( Xfer *xfer )
{
// version
-#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 1;
-#else
- XferVersion currentVersion = 2;
-#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
- m_xferVersion = version;
// extend base class
UpdateModule::xfer( xfer );
@@ -1549,18 +1542,12 @@ void OpenContain::xfer( Xfer *xfer )
xfer->xferUnsignedInt( &m_lastLoadSoundFrame );
// stealth units contained
- xfer->xferUnsignedInt( &m_stealthUnitsContained );
-
- // hero units contained
- if (version >= 2)
- {
- xfer->xferUnsignedInt( &m_heroUnitsContained );
- }
+ xfer->xferUnsignedInt( &m_stealthUnitsContained ); // TheSuperHackers @todo This is redundant information in xfer. Remove it.
// door close countdown
xfer->xferUnsignedInt( &m_doorCloseCountdown );
- // conditionstate
+ // condition state
m_conditionState.xfer( xfer );
// fire points
@@ -1660,6 +1647,9 @@ void OpenContain::loadPostProcess( void )
}
// turn the contained id list into actual object pointers in the contain list
+ m_containListSize = 0;
+ m_stealthUnitsContained = 0;
+ m_heroUnitsContained = 0;
Object *obj;
std::list::const_iterator idIt;
for( idIt = m_xferContainIDList.begin(); idIt != m_xferContainIDList.end(); ++idIt )
@@ -1678,7 +1668,7 @@ void OpenContain::loadPostProcess( void )
}
// put object on list
- m_containList.push_back( obj );
+ addToContainList( obj );
// remove this object from the world if we need to
if( isEnclosingContainerFor( obj ) )
@@ -1689,19 +1679,6 @@ void OpenContain::loadPostProcess( void )
}
- if (m_xferVersion < 2)
- {
- // Restore hero count by iterating hero objects for old save versions
- m_heroUnitsContained = 0;
- for( ContainedItemsList::const_iterator it = m_containList.begin(); it != m_containList.end(); ++it )
- {
- if( (*it)->isKindOf( KINDOF_HERO ) )
- {
- m_heroUnitsContained++;
- }
- }
- }
-
// sanity
DEBUG_ASSERTCRASH( m_containListSize == m_containList.size(),
("OpenContain::loadPostProcess - contain list count mismatch") );
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp
index 25dc54e39d8..4e701b2f330 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp
@@ -228,6 +228,16 @@ UnsignedInt TunnelContain::getContainCount() const
return 0;
}
+UnsignedInt TunnelContain::getHeroUnitsContained() const
+{
+ Player *owningPlayer = getObject()->getControllingPlayer();
+ if( owningPlayer && owningPlayer->getTunnelSystem() )
+ {
+ return owningPlayer->getTunnelSystem()->getHeroUnitsContained();
+ }
+ return 0;
+}
+
Int TunnelContain::getContainMax( void ) const
{
Player *owningPlayer = getObject()->getControllingPlayer();
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp
index 9eb5a639b41..0e0f31171b4 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp
@@ -91,7 +91,7 @@ void GrantUpgradeCreate::onCreate( void )
const UpgradeTemplate *upgradeTemplate = TheUpgradeCenter->findUpgrade( getGrantUpgradeCreateModuleData()->m_upgradeName );
if( !upgradeTemplate )
{
- DEBUG_ASSERTCRASH( 0, ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
+ DEBUG_CRASH( ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
return;
}
@@ -122,7 +122,7 @@ void GrantUpgradeCreate::onBuildComplete( void )
const UpgradeTemplate *upgradeTemplate = TheUpgradeCenter->findUpgrade( getGrantUpgradeCreateModuleData()->m_upgradeName );
if( !upgradeTemplate )
{
- DEBUG_ASSERTCRASH( 0, ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
+ DEBUG_CRASH( ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
return;
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp
index 737dd9cb2d9..cccd003766f 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp
@@ -76,7 +76,7 @@ void UpgradeDie::onDie( const DamageInfo *damageInfo )
}
else
{
- DEBUG_ASSERTCRASH( 0, ("Object %s just died, but is trying to free upgrade %s in it's producer %s%s",
+ DEBUG_CRASH( ("Object %s just died, but is trying to free upgrade %s in it's producer %s%s",
getObject()->getTemplate()->getName().str(),
getUpgradeDieModuleData()->m_upgradeName.str(),
producer->getTemplate()->getName().str(),
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp
index 5de09ce0203..0d96ef97a20 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp
@@ -3470,7 +3470,7 @@ void Object::crc( Xfer *xfer )
#if RETAIL_COMPATIBLE_CRC
tmp.format("m_objectUpgradesCompleted: %I64X, ", m_objectUpgradesCompleted);
#else
- tmp.format("m_objectUpgradesCompleted: %s, ", m_objectUpgradesCompleted.toHexString().c_str());
+ tmp.format("m_objectUpgradesCompleted: %s, ", m_objectUpgradesCompleted.toHexString().str());
#endif
logString.concat(tmp);
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp
index da1164dd2ff..8875411be31 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp
@@ -1206,7 +1206,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget
}
else
{
- DEBUG_ASSERTCRASH(FALSE,("A OCL with ContainInsideSourceObject failed the contain and is killing the new object."));
+ DEBUG_CRASH(("A OCL with ContainInsideSourceObject failed the contain and is killing the new object."));
// If we fail to contain it, we can't just leave it. Stillborn it.
TheGameLogic->destroyObject(obj);
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
index e170239d8e8..5651c4c7c62 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
@@ -4649,12 +4649,12 @@ void AIUpdateInterface::privateCommandButton( const CommandButton *commandButton
default:
if( owner->getName().isNotEmpty() )
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButton() -- unit %s ('%s'), command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButton() -- unit %s ('%s'), command %s not implemented.",
owner->getTemplate()->getName().str(), owner->getName().str(), commandButton->getTextLabel().str() ) );
}
else
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButton() -- unit %s, command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButton() -- unit %s, command %s not implemented.",
owner->getTemplate()->getName().str(), commandButton->getTextLabel().str() ) );
}
}
@@ -4702,12 +4702,12 @@ void AIUpdateInterface::privateCommandButtonPosition( const CommandButton *comma
default:
if( owner->getName().isNotEmpty() )
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButtonPosition() -- unit %s ('%s'), command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButtonPosition() -- unit %s ('%s'), command %s not implemented.",
owner->getTemplate()->getName().str(), owner->getName().str(), commandButton->getTextLabel().str() ) );
}
else
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButtonPosition() -- unit %s, command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButtonPosition() -- unit %s, command %s not implemented.",
owner->getTemplate()->getName().str(), commandButton->getTextLabel().str() ) );
}
break;
@@ -4769,7 +4769,7 @@ void AIUpdateInterface::privateCommandButtonObject( const CommandButton *command
targetNickname.format( "('%s')", obj->getName().str() );
}
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButtonPosition() -- unit %s %s, command %s at unit %s %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButtonPosition() -- unit %s %s, command %s at unit %s %s not implemented.",
myName.str(), myNickname.str(), commandButton->getTextLabel().str(), targetName.str(), targetNickname.str() ) );
}
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
index 399e6a73f04..a73da29c47d 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
@@ -1181,7 +1181,7 @@ void ChinookAIUpdate::aiDoCommand(const AICommandParms* parms)
{
const Real THRESH = 3.0f;
const Real THRESH_SQR = THRESH*THRESH;
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
const bool allowExit = true;
#else
// TheSuperHackers @bugfix Stubbjax 04/11/2025 Passengers are no longer all dumped in a single frame.
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp
index 29f62d3fa3e..2c8d141aba5 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp
@@ -825,7 +825,7 @@ StateReturnType DeliveringState::update() // Kick a dude out every so often
const WeaponTemplate *weaponTemplate = ai->getData()->m_visiblePayloadWeaponTemplate;
if( !weaponTemplate )
{
- DEBUG_ASSERTCRASH( 0, ("%s tried to fire missile %s via DeliverPayload, and is missing required weapon template in ObjectCreationList.ini entry.",
+ DEBUG_CRASH( ("%s tried to fire missile %s via DeliverPayload, and is missing required weapon template in ObjectCreationList.ini entry.",
owner->getTemplate()->getName().str(), payload->getTemplate()->getName().str() ) );
break;
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp
index fe43f98b5f3..61c1cc88bab 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp
@@ -1454,7 +1454,7 @@ void RailroadBehavior::FindPosByPathDistance( Coord3D *pos, const Real dist, con
}
- //DEBUG_ASSERTCRASH(FALSE,("Railroad could not find a position on the path!"));
+ //DEBUG_CRASH(("Railroad could not find a position on the path!"));
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp
index 0bc8f1ea66b..24620b7352d 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp
@@ -370,6 +370,10 @@ UpdateSleepTime BattlePlanUpdate::update()
{
//It's not centered, and not trying to center, so order it to center.
ai->aiIdle( CMD_FROM_AI );
+#if !RETAIL_COMPATIBLE_CRC
+ // TheSuperHackers @bugfix Stubbjax 19/02/2026 Prevent using the turret while it recenters.
+ enableTurret(false);
+#endif
recenterTurret();
m_centeringTurret = true;
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp
index bead95c4499..5c69b8f7121 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp
@@ -373,7 +373,7 @@ void DockUpdate::onExitReached( Object* docker )
// to continue moving to the exit position cause they are leaving after all
//
if( isDockOpen() )
- DEBUG_ASSERTCRASH( FALSE, ("Fiddle. Someone said goodbye to a dock when the dock didn't think it was talking to that someone."));
+ DEBUG_CRASH( ("Fiddle. Someone said goodbye to a dock when the dock didn't think it was talking to that someone."));
}
}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp
index 97f3c571571..16020c5bd12 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp
@@ -108,7 +108,7 @@ void FlammableUpdate::onDamage( DamageInfo *damageInfo )
m_flameDamageLimit = getFlammableUpdateModuleData()->m_flameDamageLimitData;
}
m_lastFlameDamageDealt = now;
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
m_flameSource = getObject()->getID();
#else
// TheSuperHackers @bugfix Stubbjax 03/09/2025 Allow flame damage to award xp to the flame source.
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp
index bb338ab0155..5eb29d8afec 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp
@@ -873,7 +873,7 @@ UpdateSleepTime ProductionUpdate::update( void )
{
// there is no exit interface, this is an error
- DEBUG_ASSERTCRASH( 0, ("Cannot create '%s', there is no ExitUpdate interface defined for producer object '%s'",
+ DEBUG_CRASH( ("Cannot create '%s', there is no ExitUpdate interface defined for producer object '%s'",
production->m_objectToProduce->getName().str(),
creationBuilding->getTemplate()->getName().str()) );
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp
index bd1ad198263..8551f1a6884 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp
@@ -1213,7 +1213,7 @@ void SpecialAbilityUpdate::triggerAbilityEffect()
StickyBombUpdate *update = (StickyBombUpdate*)charge->findUpdateModule( key_StickyBombUpdate );
if( !update )
{
- DEBUG_ASSERTCRASH( 0,
+ DEBUG_CRASH(
("Unit '%s' attempted to place %s on %s but the bomb requires a StickyBombUpdate module.",
object->getTemplate()->getName().str(),
charge->getTemplate()->getName().str(),
@@ -1419,7 +1419,7 @@ void SpecialAbilityUpdate::triggerAbilityEffect()
StickyBombUpdate *update = (StickyBombUpdate*)charge->findUpdateModule( key_StickyBombUpdate );
if( !update )
{
- DEBUG_ASSERTCRASH( 0,
+ DEBUG_CRASH(
("Unit '%s' attempted to place remote charge but the charge '%s' requires a StickyBombUpdate module.",
object->getTemplate()->getName().str(),
charge->getTemplate()->getName().str() ) );
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
index fb0d05880b5..0bc2cadb909 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
@@ -1094,7 +1094,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate
}
//-------------------------------------------------------------------------------------------------
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
void WeaponTemplate::trimOldHistoricDamage() const
{
UnsignedInt expirationDate = TheGameLogic->getFrame() - TheGlobalData->m_historicDamageLimit;
@@ -1157,7 +1157,7 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis
}
//-------------------------------------------------------------------------------------------------
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const
{
//
diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp
index 7779e98180e..f46bd40df2f 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp
@@ -92,10 +92,15 @@ class VictoryConditions : public VictoryConditionsInterface
Bool amIObserver( void ) { return m_isObserver;} ///< Am I an observer?( need this for scripts )
virtual UnsignedInt getEndFrame( void ) { return m_endFrame; } ///< on which frame was the game effectively over?
private:
+ Player* findFirstUndefeatedPlayer(); ///< Find the first player that has not been defeated.
+ void markAllianceVictorious(Player* victoriousPlayer); ///< Mark the victorious player and his allies as victorious.
+ Bool multipleAlliancesExist(void); ///< Are there multiple alliances still alive?
+
Player* m_players[MAX_PLAYER_COUNT];
Int m_localSlotNum;
UnsignedInt m_endFrame;
Bool m_isDefeated[MAX_PLAYER_COUNT];
+ Bool m_isVictorious[MAX_PLAYER_COUNT];
Bool m_localPlayerDefeated; ///< prevents condition from being signaled each frame
Bool m_singleAllianceRemaining; ///< prevents condition from being signaled each frame
Bool m_isObserver;
@@ -127,6 +132,7 @@ void VictoryConditions::reset( void )
{
m_players[i] = nullptr;
m_isDefeated[i] = false;
+ m_isVictorious[i] = false;
}
m_localSlotNum = -1;
@@ -139,42 +145,52 @@ void VictoryConditions::reset( void )
}
//-------------------------------------------------------------------------------------------------
-void VictoryConditions::update( void )
+Bool VictoryConditions::multipleAlliancesExist()
{
- if (!TheRecorder->isMultiplayer() || (m_localSlotNum < 0 && !m_isObserver))
- return;
+ Player* alive = nullptr;
- // Check for a single winning alliance
- if (!m_singleAllianceRemaining)
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
{
- Bool multipleAlliances = false;
- Player *alive = nullptr;
- Player *player;
- for (Int i=0; iisMultiplayer() || (m_localSlotNum < 0 && !m_isObserver))
+ return;
+
+ // Check for a single winning alliance
+ if (!m_singleAllianceRemaining)
+ {
+ if (!multipleAlliancesExist())
{
m_singleAllianceRemaining = true; // don't check again
m_endFrame = TheGameLogic->getFrame();
+
+ Player* victoriousPlayer = findFirstUndefeatedPlayer();
+
+ if (victoriousPlayer)
+ markAllianceVictorious(victoriousPlayer);
}
}
@@ -233,19 +249,50 @@ void VictoryConditions::update( void )
}
}
+//-------------------------------------------------------------------------------------------------
+Player* VictoryConditions::findFirstUndefeatedPlayer()
+{
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
+ {
+ Player* player = m_players[i];
+ if (player && !hasSinglePlayerBeenDefeated(player))
+ return player;
+ }
+
+ return nullptr;
+}
+
+// TheSuperHackers @bugfix Stubbjax 11/02/2026 This marks the player and any allies as victorious, including
+// defeated allies. This also ensures players retain their victorious status if their assets are destroyed
+// after the victory conditions are met (e.g. when quitting the game prior to the victory screen).
+//-------------------------------------------------------------------------------------------------
+void VictoryConditions::markAllianceVictorious(Player* victoriousPlayer)
+{
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
+ {
+ Player* player = m_players[i];
+ if (player == victoriousPlayer || (player && areAllies(player, victoriousPlayer)))
+ m_isVictorious[i] = true;
+ }
+}
+
//-------------------------------------------------------------------------------------------------
Bool VictoryConditions::hasAchievedVictory(Player *player)
{
if (!player)
return false;
- if (m_singleAllianceRemaining)
+ if (!m_singleAllianceRemaining)
+ return false;
+
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
{
- for (Int i=0; i= MAX_SLOTS)
{
- DEBUG_ASSERTCRASH(FALSE,("GameLogic::processProgressComplete, Invalid playerid was passed in %d", playerId));
+ DEBUG_CRASH(("GameLogic::processProgressComplete, Invalid playerid was passed in %d", playerId));
return;
}
if(m_progressComplete[playerId] == TRUE)
diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
index ef4e62d534e..bf155534481 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
@@ -1353,7 +1353,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData )
if( pu == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("MSG_QUEUE_UNIT_CREATE: Producer '%s' doesn't have a unit production interface",
+ DEBUG_CRASH( ("MSG_QUEUE_UNIT_CREATE: Producer '%s' doesn't have a unit production interface",
producer->getTemplate()->getName().str()) );
break;
diff --git a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp
index 20c5b1d915e..94d0e9d2daf 100644
--- a/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp
+++ b/Generals/Code/GameEngine/Source/GameNetwork/GameSpy.cpp
@@ -49,7 +49,7 @@
#include "Common/PlayerTemplate.h"
#include "Common/RandomValue.h"
#include "Common/GlobalData.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameLogic/ScriptEngine.h"
MutexClass TheGameSpyMutex;
diff --git a/Generals/Code/GameEngineDevice/CMakeLists.txt b/Generals/Code/GameEngineDevice/CMakeLists.txt
index a5c83215b7e..59678dbfcb8 100644
--- a/Generals/Code/GameEngineDevice/CMakeLists.txt
+++ b/Generals/Code/GameEngineDevice/CMakeLists.txt
@@ -46,7 +46,7 @@ set(GAMEENGINEDEVICE_SRC
Include/W3DDevice/GameClient/W3DGUICallbacks.h
Include/W3DDevice/GameClient/W3DInGameUI.h
Include/W3DDevice/GameClient/W3DMirror.h
- Include/W3DDevice/GameClient/W3DMouse.h
+# Include/W3DDevice/GameClient/W3DMouse.h
Include/W3DDevice/GameClient/W3DParticleSys.h
Include/W3DDevice/GameClient/W3DPoly.h
Include/W3DDevice/GameClient/W3DProjectedShadow.h
@@ -75,8 +75,8 @@ set(GAMEENGINEDEVICE_SRC
Include/Win32Device/Common/Win32GameEngine.h
# Include/Win32Device/Common/Win32LocalFile.h
# Include/Win32Device/Common/Win32LocalFileSystem.h
- Include/Win32Device/GameClient/Win32DIKeyboard.h
- Include/Win32Device/GameClient/Win32Mouse.h
+# Include/Win32Device/GameClient/Win32DIKeyboard.h
+# Include/Win32Device/GameClient/Win32Mouse.h
# Source/MilesAudioDevice/MilesAudioManager.cpp
# Source/VideoDevice/Bink/BinkVideoPlayer.cpp
Source/W3DDevice/Common/System/W3DFunctionLexicon.cpp
@@ -145,7 +145,7 @@ set(GAMEENGINEDEVICE_SRC
Source/W3DDevice/GameClient/W3DFileSystem.cpp
Source/W3DDevice/GameClient/W3DGameClient.cpp
Source/W3DDevice/GameClient/W3DInGameUI.cpp
- Source/W3DDevice/GameClient/W3DMouse.cpp
+# Source/W3DDevice/GameClient/W3DMouse.cpp
Source/W3DDevice/GameClient/W3DParticleSys.cpp
Source/W3DDevice/GameClient/W3DPoly.cpp
Source/W3DDevice/GameClient/W3DRoadBuffer.cpp
@@ -174,8 +174,8 @@ set(GAMEENGINEDEVICE_SRC
# Source/Win32Device/Common/Win32LocalFile.cpp
# Source/Win32Device/Common/Win32LocalFileSystem.cpp
Source/Win32Device/Common/Win32OSDisplay.cpp
- Source/Win32Device/GameClient/Win32DIKeyboard.cpp
- Source/Win32Device/GameClient/Win32Mouse.cpp
+# Source/Win32Device/GameClient/Win32DIKeyboard.cpp
+# Source/Win32Device/GameClient/Win32Mouse.cpp
)
add_library(g_gameenginedevice STATIC)
diff --git a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h
deleted file mode 100644
index bbb14f2b9a4..00000000000
--- a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: W3DMouse.h /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Win32Mouse.h
-//
-// Created: Mark Wilczynski, Jan 2002
-//
-// Desc: Interface for the mouse using W3D methods to display cursor.
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "Win32Device/GameClient/Win32Mouse.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-class CameraClass;
-class SurfaceClass;
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-// W3DMouse -----------------------------------------------------------------
-/** Mouse interface for when using only the Win32 messages and W3D for cursor */
-//-----------------------------------------------------------------------------
-class W3DMouse : public Win32Mouse
-{
-
-public:
-
- W3DMouse( void );
- virtual ~W3DMouse( void );
-
- virtual void init( void ); ///< init mouse, extend this functionality, do not replace
- virtual void reset( void ); ///< reset the system
-
- virtual void setCursor( MouseCursor cursor ); ///< set mouse cursor
- virtual void draw( void ); ///< draw the cursor or refresh the image
- virtual void setRedrawMode(RedrawMode mode); ///.
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Win32DIKeyboard.h ////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Win32DIKeyboard.h
-//
-// Created: Colin Day, June 2001
-//
-// Desc: Device implementation of the keyboard interface on Win32
-// using Microsoft Direct Input
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#ifndef DIRECTINPUT_VERSION
-# define DIRECTINPUT_VERSION 0x800
-#endif
-
-#include
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "GameClient/Keyboard.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-// class DirectInputKeyboard --------------------------------------------------
-/** Class for interfacing with the keyboard using direct input as the
- * implementation */
-//-----------------------------------------------------------------------------
-class DirectInputKeyboard : public Keyboard
-{
-
-public:
-
- DirectInputKeyboard( void );
- virtual ~DirectInputKeyboard( void );
-
- // extend methods from the base class
- virtual void init( void ); ///< initialize the keyboard, extending init functionality
- virtual void reset( void ); ///< Reset the keybaord system
- virtual void update( void ); ///< update call, extending update functionality
- virtual Bool getCapsState( void ); ///< get state of caps lock key, return TRUE if down
-
-protected:
-
- // extended methods from the base class
- virtual void getKey( KeyboardIO *key ); ///< get a single key event
-
- //-----------------------------------------------------------------------------------------------
-
- // new methods to this derived class
- void openKeyboard( void ); ///< create direct input keyboard
- void closeKeyboard( void ); ///< release direct input keyboard
-
- // direct input data members
- LPDIRECTINPUT8 m_pDirectInput; ///< pointer to direct input interface
- LPDIRECTINPUTDEVICE8 m_pKeyboardDevice; ///< pointer to keyboard device
-
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h b/Generals/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h
deleted file mode 100644
index 529d433daa0..00000000000
--- a/Generals/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-// FILE: Win32DIMouse.h ///////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Win32DIMouse.h
-//
-// Created: Colin Day, June 2001
-//
-// Desc: Win32 direct input implementation for the mouse
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-#ifndef DIRECTINPUT_VERSION
-# define DIRECTINPUT_VERSION 0x800
-#endif
-
-#include
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "GameClient/Mouse.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-
-// class DirectInputMouse -----------------------------------------------------
-/** Direct input implementation for the mouse device */
-//-----------------------------------------------------------------------------
-class DirectInputMouse : public Mouse
-{
-
-public:
-
- DirectInputMouse( void );
- virtual ~DirectInputMouse( void );
-
- // extended methods from base class
- virtual void init( void ); ///< initialize the direct input mouse, extending functionality
- virtual void reset( void ); ///< reset system
- virtual void update( void ); ///< update the mouse data, extending functionality
- virtual void setPosition( Int x, Int y ); ///< set position for mouse
-
- virtual void setMouseLimits( void ); ///< update the limit extents the mouse can move in
-
- virtual void setCursor( MouseCursor cursor ); ///< set mouse cursor
-
- virtual void capture( void ); ///< capture the mouse
- virtual void releaseCapture( void ); ///< release mouse capture
-
-protected:
-
- /// device implementation to get mouse event
- virtual UnsignedByte getMouseEvent( MouseIO *result, Bool flush );
-
- // new internal methods for our direct input implementation
- void openMouse( void ); ///< create the direct input mouse
- void closeMouse( void ); ///< close and release mouse resources
- /// map direct input mouse data to our own format
- void mapDirectInputMouse( MouseIO *mouse, DIDEVICEOBJECTDATA *mdat );
-
- // internal data members for our direct input mouse
- LPDIRECTINPUT8 m_pDirectInput; ///< pointer to direct input interface
- LPDIRECTINPUTDEVICE8 m_pMouseDevice; ///< pointer to mouse device
-
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h b/Generals/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h
deleted file mode 100644
index 2ba373ba1da..00000000000
--- a/Generals/Code/GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Win32Mouse.h /////////////////////////////////////////////////////////
-//-----------------------------------------------------------------------------
-//
-// Westwood Studios Pacific.
-//
-// Confidential Information
-// Copyright (C) 2001 - All Rights Reserved
-//
-//-----------------------------------------------------------------------------
-//
-// Project: RTS3
-//
-// File name: Win32Mouse.h
-//
-// Created: Colin Day, July 2001
-//
-// Desc: Interface for the mouse using only the Win32 messages
-//
-//-----------------------------------------------------------------------------
-///////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
-
-// USER INCLUDES //////////////////////////////////////////////////////////////
-#include "GameClient/Mouse.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////
-
-// TYPE DEFINES ///////////////////////////////////////////////////////////////
-enum { NO_TIME_FROM_WINDOWS = 0 };
-// Win32Mouse -----------------------------------------------------------------
-/** Mouse interface for when using only the Win32 messages */
-//-----------------------------------------------------------------------------
-class Win32Mouse : public Mouse
-{
-
-public:
-
- Win32Mouse( void );
- virtual ~Win32Mouse( void );
-
- virtual void init( void ); ///< init mouse, extend this functionality, do not replace
- virtual void reset( void ); ///< reset the system
- virtual void update( void ); ///< update
- virtual void initCursorResources(void); ///< load windows resources needed for 2d cursors.
-
- virtual void setCursor( MouseCursor cursor ); ///< set mouse cursor
-
- virtual void setVisibility(Bool visible);
-
- virtual void loseFocus();
- virtual void regainFocus();
-
- /// add an event from a win32 window procedure
- void addWin32Event( UINT msg, WPARAM wParam, LPARAM lParam, DWORD time );
-
-protected:
-
- virtual void capture( void ); ///< capture the mouse
- virtual void releaseCapture( void ); ///< release mouse capture
-
- /// get the next event available in the buffer
- virtual UnsignedByte getMouseEvent( MouseIO *result, Bool flush );
-
- /// translate a win32 mouse event to our own info
- void translateEvent( UnsignedInt eventIndex, MouseIO *result );
-
- struct Win32MouseEvent
- {
- UINT msg; ///< WM_* message
- WPARAM wParam; ///< WPARAM from the WM_* message
- LPARAM lParam; ///< LPARAM from the WM_* message
- DWORD time; ///< TIME from the WM_* message
- };
- /// this is our buffer of events that we receive via a WndProc message
- Win32MouseEvent m_eventBuffer[ Mouse::NUM_MOUSE_EVENTS ];
- UnsignedInt m_nextFreeIndex; ///< insert new events at this index
- UnsignedInt m_nextGetIndex; /** events retrieved through getMouseEvent
- will come from this index, then it will be
- incremented to the next index */
- MouseCursor m_currentWin32Cursor; ///< keep track of last cursor image sent to D3D.
- Int m_directionFrame; ///< current frame of directional cursor (from 0 points up).
- Bool m_lostFocus; ///< flag if window has lost focus and mouse should stop being updated.
-};
-
-// INLINING ///////////////////////////////////////////////////////////////////
-
-// EXTERNALS //////////////////////////////////////////////////////////////////
diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
index d88ce9e7bd2..f8a37d226bd 100644
--- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
+++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
@@ -727,7 +727,7 @@ void W3DDisplay::init( void )
WW3D::Shutdown();
WWMath::Shutdown();
throw ERROR_INVALID_D3D; //failed to initialize. User probably doesn't have DX 8.1
- DEBUG_ASSERTCRASH( 0, ("Unable to set render device") );
+ DEBUG_CRASH( ("Unable to set render device") );
return;
}
diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp
deleted file mode 100644
index 14eb611c1a1..00000000000
--- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: W3DMouse.cpp /////////////////////////////////////////////////////////////////////////////
-// Author: Mark W.
-// Desc: W3D Mouse cursor implementations
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-#include "Common/GameMemory.h"
-#include "WW3D2/dx8wrapper.h"
-#include "WW3D2/rendobj.h"
-#include "WW3D2/hanim.h"
-#include "WW3D2/camera.h"
-
-#include "assetmgr.h"
-
-#include "W3DDevice/Common/W3DConvert.h"
-#include "W3DDevice/GameClient/W3DMouse.h"
-#include "W3DDevice/GameClient/W3DDisplay.h"
-#include "W3DDevice/GameClient/W3DAssetManager.h"
-#include "W3DDevice/GameClient/W3DScene.h"
-#include "GameClient/Display.h"
-#include "GameClient/Image.h"
-#include "GameClient/InGameUI.h"
-#include "mutex.h"
-#include "thread.h"
-
-
-//Since there can't be more than 1 mouse, might as well keep these static.
-static CriticalSectionClass mutex;
-static Bool isThread;
-static TextureClass *cursorTextures[Mouse::NUM_MOUSE_CURSORS][MAX_2D_CURSOR_ANIM_FRAMES]; ///draw();
- isThread=FALSE;
- Switch_Thread();
- }
-}
-
-W3DMouse::W3DMouse( void )
-{
- // zero our event list
- for (Int i=0; iShowCursor(FALSE); //kill DX8 cursor
- Win32Mouse::setCursor(ARROW); //enable default windows cursor
- }
-
- freeD3DAssets();
- freeW3DAssets();
-
- thread.Stop();
-
-}
-
-void W3DMouse::initPolygonAssets(void)
-{
- CriticalSectionClass::LockClass m(mutex);
-
- //don't allow the mouse thread to initialize
- //wait for main app to do initialization.
- if (isThread)
- return;
-
- //Check if texture assets already loaded
- if (m_currentRedrawMode == RM_POLYGON && cursorImages[1] == nullptr)
- {
- for (Int i=0; ifindImageByName(m_cursorInfo[i].imageName);
- }
- }
-}
-
-void W3DMouse::freePolygonAssets(void)
-{
-
- for (Int i=0; i MAX_2D_CURSOR_ANIM_FRAMES)
- animFrames = MAX_2D_CURSOR_ANIM_FRAMES;
-
- m_currentFrames=0;
-
- if (animFrames == 1)
- { //single animation frame without trailing numbers
- snprintf(FrameName, ARRAY_SIZE(FrameName), "%s.tga", baseName);
- cursorTextures[cursor][0]= am->Get_Texture(FrameName);
- m_currentD3DSurface[0]=cursorTextures[cursor][0]->Get_Surface_Level();
- m_currentFrames = 1;
- }
- else
- for (Int i=0; iGet_Texture(FrameName)) != nullptr)
- { m_currentD3DSurface[m_currentFrames]=cursorTextures[cursor][i]->Get_Surface_Level();
- m_currentFrames++;
- }
- }
- return TRUE;
-}
-
-void W3DMouse::initD3DAssets(void)
-{
- //Nothing to do here unless we want to preload all possible cursors which would
- //probably not be practical for memory reasons.
-
- CriticalSectionClass::LockClass m(mutex);
-
- //don't allow the mouse thread to initialize
- //wait for main app to do initialization.
- if (isThread)
- return;
-
- WW3DAssetManager *am=WW3DAssetManager::Get_Instance();
-
- //Check if texture assets already loaded
- if (m_currentRedrawMode == RM_DX8 && cursorTextures[1] == nullptr && am)
- {
- for (Int i=0; iGet_Texture(m_cursorInfo[i].textureName.str());
- }
- }
-
- for (Int x = 0; x < MAX_2D_CURSOR_ANIM_FRAMES; x++)
- m_currentD3DSurface[x]=nullptr;
- }
-}
-
-void W3DMouse::freeD3DAssets(void)
-{
- //free pointers to texture surfaces.
- Int i=0;
- for (; iCreate_Render_Obj(m_cursorInfo[i].W3DModelName.str(), m_cursorInfo[i].W3DScale*m_orthoZoom, 0);
- else
- cursorModels[i] = W3DDisplay::m_assetManager->Create_Render_Obj(m_cursorInfo[i].W3DModelName.str(), m_cursorInfo[i].W3DScale, 0);
- if (cursorModels[i])
- {
- cursorModels[i]->Set_Position(Vector3(0.0f, 0.0f, -1.0f));
- //W3DDisplay::m_3DInterfaceScene->Add_Render_Object(cursorModels[i]);
- }
- }
- }
- }
- if ((cursorAnims[1] == nullptr && W3DDisplay::m_assetManager))
- {
- for (Int i=1; iGet_HAnim(m_cursorInfo[i].W3DAnimName.str());
- if (cursorAnims[i] && cursorModels[i])
- {
- cursorModels[i]->Set_Animation(cursorAnims[i], 0, (m_cursorInfo[i].loop) ? RenderObjClass::ANIM_MODE_LOOP : RenderObjClass::ANIM_MODE_ONCE);
- }
- }
- }
- }
-
- // create the camera
- m_camera = NEW_REF( CameraClass, () );
- m_camera->Set_Position( Vector3( 0, 1, 1 ) );
- Vector2 min = Vector2( -1, -1 );
- Vector2 max = Vector2( +1, +1 );
- m_camera->Set_View_Plane( min, max );
- m_camera->Set_Clip_Planes( 0.995f, 20.0f );
- if (m_orthoCamera)
- m_camera->Set_Projection_Type( CameraClass::ORTHO );
-}
-
-void W3DMouse::freeW3DAssets(void)
-{
-
- for (Int i=0; iRemove_Render_Object(cursorModels[i]);
- }
- REF_PTR_RELEASE(cursorModels[i]);
- REF_PTR_RELEASE(cursorAnims[i]);
- }
-
- REF_PTR_RELEASE(m_camera);
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Initialize our device */
-//-------------------------------------------------------------------------------------------------
-void W3DMouse::init( void )
-{
-
- //check if system already initialized and texture assets loaded.
- Win32Mouse::init();
- setCursor(ARROW); //set default starting cursor image
-
- WWASSERT(!thread.Is_Running());
-
-
- isThread=FALSE;
- if (m_currentRedrawMode == RM_DX8)
- thread.Execute();
- thread.Set_Priority(0);
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset */
-//-------------------------------------------------------------------------------------------------
-void W3DMouse::reset( void )
-{
-
- // extend
- Win32Mouse::reset();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Super basic simplistic cursor */
-//-------------------------------------------------------------------------------------------------
-void W3DMouse::setCursor( MouseCursor cursor )
-{
-
- CriticalSectionClass::LockClass m(mutex);
-
- m_directionFrame=0;
- if (m_currentRedrawMode == RM_WINDOWS)
- { //Windows default cursor needs to refreshed whenever we get a WM_SETCURSOR
- m_currentD3DCursor=NONE;
- m_currentW3DCursor=NONE;
- m_currentPolygonCursor=NONE;
- setCursorDirection(cursor);
- if (m_drawing) //only allow cursor to change when drawing the cursor (once per frame) to fix flickering.
- Win32Mouse::setCursor(cursor);
- m_currentCursor = cursor;
- return;
- }
-
- // extend
- Mouse::setCursor( cursor );
-
- // if we're already on this cursor ignore the rest of code to stop cursor flickering.
- if( m_currentCursor == cursor && m_currentD3DCursor == cursor)
- return;
-
- //make sure Windows didn't reset our cursor
- if (m_currentRedrawMode == RM_DX8)
- {
- SetCursor(nullptr); //Kill Windows Cursor
-
- LPDIRECT3DDEVICE8 m_pDev=DX8Wrapper::_Get_D3D_Device8();
- Bool doImageChange=FALSE;
-
- if (m_pDev != nullptr)
- {
- m_pDev->ShowCursor(FALSE); //disable DX8 cursor
- if (cursor != m_currentD3DCursor)
- { if (!isThread)
- { releaseD3DCursorTextures(m_currentD3DCursor);
- //Since this type of cursor is updated from a non-D3D thread, we need
- //to preallocate all surfaces in main thread.
- loadD3DCursorTextures(cursor);
- }
- }
- if (m_currentD3DSurface[0])
- doImageChange=TRUE;
- }
- //For DX8 Cursors, we continually set the image on every call even when
- //it didn't change. This is needed to prevent the cursor from flickering.
- if (doImageChange)
- {
- HRESULT res;
- m_currentHotSpot = m_cursorInfo[cursor].hotSpotPosition;
- m_currentFMS = m_cursorInfo[cursor].fps/1000.0f;
- m_currentAnimFrame = 0; //reset animation when cursor changes
- res = m_pDev->SetCursorProperties(m_currentHotSpot.x,m_currentHotSpot.y,m_currentD3DSurface[(Int)m_currentAnimFrame]->Peek_D3D_Surface());
- m_pDev->ShowCursor(TRUE); //Enable DX8 cursor
- m_currentD3DFrame=(Int)m_currentAnimFrame;
- m_currentD3DCursor = cursor;
- m_lastAnimTime=timeGetTime();
- }
- }
- else if (m_currentRedrawMode == RM_POLYGON)
- {
- SetCursor(nullptr); //Kill Windows Cursor
- m_currentD3DCursor=NONE;
- m_currentW3DCursor=NONE;
- m_currentPolygonCursor = cursor;
- m_currentHotSpot = m_cursorInfo[cursor].hotSpotPosition;
- }
- else if (m_currentRedrawMode == RM_W3D)
- {
- SetCursor(nullptr); //Kill Windows Cursor
- m_currentD3DCursor=NONE;
- m_currentPolygonCursor=NONE;
- if (cursor != m_currentW3DCursor)
- {
- // set the new model visible
- if (!cursorModels[1])
- initW3DAssets();
-
- if (cursorModels[1])
- {
- if (cursorModels[m_currentW3DCursor])
- {
- W3DDisplay::m_3DInterfaceScene->Remove_Render_Object(cursorModels[m_currentW3DCursor]);
- }
-
- m_currentW3DCursor=cursor;
-
- if (cursorModels[m_currentW3DCursor])
- {
- W3DDisplay::m_3DInterfaceScene->Add_Render_Object(cursorModels[m_currentW3DCursor]);
- if (m_cursorInfo[m_currentW3DCursor].loop == FALSE && cursorAnims[m_currentW3DCursor])
- {
- cursorModels[m_currentW3DCursor]->Set_Animation(cursorAnims[m_currentW3DCursor], 0, RenderObjClass::ANIM_MODE_ONCE);
- }
- }
- }
- }
- else
- {
- m_currentW3DCursor=cursor;
- }
- }
-
- // save current cursor
- m_currentCursor = cursor;
-
-}
-
-extern HWND ApplicationHWnd;
-
-void W3DMouse::draw(void)
-{
- CriticalSectionClass::LockClass m(mutex);
-
- m_drawing = TRUE;
-
- //make sure the correct cursor image is selected
- setCursor(m_currentCursor);
-
- if (m_currentRedrawMode == RM_DX8 && m_currentD3DCursor != NONE)
- {
- //called from update thread or rendering loop. Tells D3D where
- //to draw the mouse cursor.
- LPDIRECT3DDEVICE8 m_pDev=DX8Wrapper::_Get_D3D_Device8();
- if (m_pDev)
- { m_pDev->ShowCursor(TRUE); //Enable DX8 cursor
-
- if (TheDisplay && !TheDisplay->getWindowed())
- { //if we're full-screen, need to manually move cursor image
- POINT ptCursor;
-
- GetCursorPos( &ptCursor );
- ScreenToClient( ApplicationHWnd, &ptCursor );
- m_pDev->SetCursorPosition( ptCursor.x, ptCursor.y, D3DCURSOR_IMMEDIATE_UPDATE);
- }
- //Check if animated cursor and new frame
- if (m_currentFrames > 1)
- {
- Int msTime=timeGetTime();
- m_currentAnimFrame += (msTime-m_lastAnimTime) * m_currentFMS;
- m_currentAnimFrame=fmod(m_currentAnimFrame,m_currentFrames);
- m_lastAnimTime=msTime;
-
- if ((Int)m_currentAnimFrame != m_currentD3DFrame)
- {
- m_currentD3DFrame=(Int)m_currentAnimFrame;
- m_pDev->SetCursorProperties(m_currentHotSpot.x,m_currentHotSpot.y,m_currentD3DSurface[m_currentD3DFrame]->Peek_D3D_Surface());
- }
- }
- }
- }
- else if (m_currentRedrawMode == RM_POLYGON)
- {
- const Image *image=cursorImages[m_currentPolygonCursor];
- if (image)
- {
- TheDisplay->drawImage(image,m_currMouse.pos.x-m_currentHotSpot.x,m_currMouse.pos.y-m_currentHotSpot.y,
- m_currMouse.pos.x+image->getImageWidth()-m_currentHotSpot.x, m_currMouse.pos.y+image->getImageHeight()-m_currentHotSpot.y);
- }
- }
- else if (m_currentRedrawMode == RM_WINDOWS)
- {
- }
- else if (m_currentRedrawMode == RM_W3D)
- {
- if ( W3DDisplay::m_3DInterfaceScene && m_camera && m_visible)
- {
- if (cursorModels[m_currentW3DCursor])
- {
- Real xPercent = (1.0f - (TheDisplay->getWidth() - m_currMouse.pos.x) / (Real)TheDisplay->getWidth());
- Real yPercent = ((TheDisplay->getHeight() - m_currMouse.pos.y) / (Real)TheDisplay->getHeight());
-
- Real x, y, z = -1.0f;
-
- if (m_orthoCamera)
- {
- x = xPercent*2 - 1;
- y = yPercent*2;
- }
- else
- {
- //W3D Screen coordinates are -1 to 1, so we need to do some conversion:
- Real logX, logY;
- PixelScreenToW3DLogicalScreen(m_currMouse.pos.x - 0, m_currMouse.pos.y - 0, &logX, &logY, TheDisplay->getWidth(), TheDisplay->getHeight());
-
- Vector3 rayStart;
- Vector3 rayEnd;
- rayStart = m_camera->Get_Position(); //get camera location
- m_camera->Un_Project(rayEnd,Vector2(logX,logY)); //get world space point
- rayEnd -= rayStart; //vector camera to world space point
- rayEnd.Normalize(); //make unit vector
- rayEnd *= m_camera->Get_Depth(); //adjust length to reach far clip plane
- rayEnd += rayStart; //get point on far clip plane along ray from camera.
-
- x = Vector3::Find_X_At_Z(z, rayStart, rayEnd);
- y = Vector3::Find_Y_At_Z(z, rayStart, rayEnd);
- }
-
- Matrix3D tm(1);
- tm.Set_Translation(Vector3(x, y, z));
- Coord2D offset = {0, 0};
- if (TheInGameUI && TheInGameUI->isScrolling())
- {
- offset = TheInGameUI->getScrollAmount();
- offset.normalize();
- Real theta = atan2(-offset.y, offset.x);
- theta -= (Real)M_PI/2;
- tm.Rotate_Z(theta);
- }
- cursorModels[m_currentW3DCursor]->Set_Transform(tm);
-
- WW3D::Render( W3DDisplay::m_3DInterfaceScene, m_camera );
- }
- }
- }
-
- //@todo: In DX8 mode the mouse is drawn in another thread which isn't allowed
- //access to D3D so we can't do any drawing here.
- // draw the cursor text
- if (!isThread)
- drawCursorText();
-
- // draw tooltip text
- if (m_visible && !isThread)
- drawTooltip();
-
- m_drawing = FALSE;
-}
-
-void W3DMouse::setRedrawMode(RedrawMode mode)
-{
- MouseCursor cursor = getMouseCursor();
-
- //Turn off the previous cursor mode
- setCursor(NONE);
-
- m_currentRedrawMode=mode;
-
- switch (mode)
- {
- case RM_WINDOWS:
- { //Windows mouse doesn't need an update thread.
- if (thread.Is_Running())
- thread.Stop();
- freeD3DAssets(); //using Windows resources
- freeW3DAssets();
- freePolygonAssets();
- m_currentD3DCursor = NONE;
- m_currentW3DCursor = NONE;
- m_currentPolygonCursor = NONE;
- }
- break;
-
- case RM_W3D:
- { //Model mouse updated only at render time so doesn't
- //require thread.
- if (thread.Is_Running())
- thread.Stop();
- freeD3DAssets(); //using packed Image data, not textures.
- freePolygonAssets();
- m_currentD3DCursor = NONE;
- m_currentPolygonCursor = NONE;
- initW3DAssets();
- }
- break;
-
- case RM_POLYGON:
- { //Polygon mouse updated only at render time so doesn't
- //require thread.
- if (thread.Is_Running())
- thread.Stop();
- freeD3DAssets(); //using packed Image data, not textures.
- freeW3DAssets();
- m_currentD3DCursor = NONE;
- m_currentW3DCursor = NONE;
- m_currentPolygonCursor = NONE;
- initPolygonAssets();
- }
- break;
-
- case RM_DX8:
- { //this cursor type is drawn by DX8 and can be refreshed
- //independent of rendering rate. Uses another thread to do
- //position updates.
- initD3DAssets(); //make sure textures loaded.
- freeW3DAssets();
- freePolygonAssets();
- if (!thread.Is_Running())
- thread.Execute();
- m_currentW3DCursor = NONE;
- m_currentPolygonCursor = NONE;
- break;
- }
- }
-
- setCursor(NONE);
- setCursor(cursor);
-}
-
-void W3DMouse::setCursorDirection(MouseCursor cursor)
-{
- Coord2D offset = {0, 0};
- //Check if we have a directional cursor that needs different images for each direction
- if (m_cursorInfo[cursor].numDirections > 1 && TheInGameUI && TheInGameUI->isScrolling())
- {
- offset = TheInGameUI->getScrollAmount();
- if (offset.x || offset.y)
- {
- offset.normalize();
- Real theta = atan2(offset.y, offset.x);
- theta = fmod(theta+M_PI*2,M_PI*2);
- Int numDirections=m_cursorInfo[m_currentCursor].numDirections;
- //Figure out which of our predrawn cursor orientations best matches the
- //actual cursor direction. Frame 0 is assumed to point right and continue
- //clockwise.
- m_directionFrame=(Int)(theta/(2.0f*M_PI/(Real)numDirections)+0.5f);
- if (m_directionFrame >= numDirections)
- m_directionFrame = 0;
- }
- else
- {
- m_directionFrame=0;
- }
- }
- else
- m_directionFrame = 0;
-}
diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp
index 2d39c14e1f0..134927c8853 100644
--- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp
+++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp
@@ -1337,7 +1337,7 @@ void RTS3DScene::flushOccludedObjectsIntoStencil(RenderInfoClass & rinfo)
if ((lastPlayerObject[index]-&playerObjects[index][0]) >= MAX_VISIBLE_OCCLUDED_PLAYER_OBJECTS)
{
- DEBUG_ASSERTCRASH(FALSE,("Exceeded Maximum Number of potentially occluded models"));
+ DEBUG_CRASH(("Exceeded Maximum Number of potentially occluded models"));
continue;
}
diff --git a/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp b/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp
deleted file mode 100644
index d4915fd3f2c..00000000000
--- a/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Win32DIKeyboard.cpp //////////////////////////////////////////////////////////////////////
-// Created: Colin Day, June 2001
-// Desc: Device implementation of the keyboard interface on Win32
-// using Microsoft Direct Input
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include
-#include
-
-#include "Common/Debug.h"
-#include "Common/Language.h"
-#include "GameClient/KeyDefs.h"
-#include "GameClient/Keyboard.h"
-#include "Win32Device/GameClient/Win32DIKeyboard.h"
-#include "WinMain.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////////////////////////
-enum { KEYBOARD_BUFFER_SIZE = 256 };
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
-struct ErrorLookup
-{
- HRESULT error;
- const char *string;
-};
-static ErrorLookup errorLookup[] =
-{
-{ (HRESULT)DIERR_ACQUIRED, "DIERR_ACQUIRED" },
-{ (HRESULT)DIERR_ALREADYINITIALIZED, "DIERR_ALREADYINITIALIZED" },
-{ (HRESULT)DIERR_BADDRIVERVER, "DIERR_BADDRIVERVER" },
-{ (HRESULT)DIERR_BETADIRECTINPUTVERSION, "DIERR_BETADIRECTINPUTVERSION" },
-{ (HRESULT)DIERR_DEVICEFULL, "DIERR_DEVICEFULL" },
-{ (HRESULT)DIERR_DEVICENOTREG, "DIERR_DEVICENOTREG" },
-{ (HRESULT)DIERR_EFFECTPLAYING, "DIERR_EFFECTPLAYING" },
-{ (HRESULT)DIERR_GENERIC, "DIERR_GENERIC" },
-{ (HRESULT)DIERR_HANDLEEXISTS, "DIERR_HANDLEEXISTS" },
-{ (HRESULT)DIERR_HASEFFECTS, "DIERR_HASEFFECTS" },
-{ (HRESULT)DIERR_INCOMPLETEEFFECT, "DIERR_INCOMPLETEEFFECT" },
-{ (HRESULT)DIERR_INPUTLOST, "DIERR_INPUTLOST" },
-{ (HRESULT)DIERR_INVALIDPARAM, "DIERR_INVALIDPARAM" },
-{ (HRESULT)DIERR_MAPFILEFAIL, "DIERR_MAPFILEFAIL" },
-{ (HRESULT)DIERR_MOREDATA, "DIERR_MOREDATA" },
-{ (HRESULT)DIERR_NOAGGREGATION, "DIERR_NOAGGREGATION" },
-{ (HRESULT)DIERR_NOINTERFACE, "DIERR_NOINTERFACE" },
-{ (HRESULT)DIERR_NOTACQUIRED, "DIERR_NOTACQUIRED" },
-{ (HRESULT)DIERR_NOTBUFFERED, "DIERR_NOTBUFFERED" },
-{ (HRESULT)DIERR_NOTDOWNLOADED, "DIERR_NOTDOWNLOADED" },
-{ (HRESULT)DIERR_NOTEXCLUSIVEACQUIRED, "DIERR_NOTEXCLUSIVEACQUIRED" },
-{ (HRESULT)DIERR_NOTFOUND, "DIERR_NOTFOUND" },
-{ (HRESULT)DIERR_NOTINITIALIZED, "DIERR_NOTINITIALIZED" },
-{ (HRESULT)DIERR_OBJECTNOTFOUND, "DIERR_OBJECTNOTFOUND" },
-{ (HRESULT)DIERR_OLDDIRECTINPUTVERSION, "DIERR_OLDDIRECTINPUTVERSION" },
-{ (HRESULT)DIERR_OTHERAPPHASPRIO, "DIERR_OTHERAPPHASPRIO" },
-{ (HRESULT)DIERR_OUTOFMEMORY, "DIERR_OUTOFMEMORY" },
-{ (HRESULT)DIERR_READONLY, "DIERR_READONLY" },
-{ (HRESULT)DIERR_REPORTFULL, "DIERR_REPORTFULL" },
-{ (HRESULT)DIERR_UNPLUGGED, "DIERR_UNPLUGGED" },
-{ (HRESULT)DIERR_UNSUPPORTED, "DIERR_UNSUPPORTED" },
-{ 0, nullptr }
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** For debugging, prints the return code using direct input errors */
-//-------------------------------------------------------------------------------------------------
-static void printReturnCode( char *label, HRESULT hr )
-{
- ErrorLookup *error = errorLookup;
-
- while( error->string != nullptr )
- {
-
- if( error->error == hr )
- {
- DEBUG_LOG(( "%s: '%s' - '0x%08x'", label, error->string, hr ));
- break;
- }
- error++;
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** create our interface to the direct input keybard */
-//-------------------------------------------------------------------------------------------------
-void DirectInputKeyboard::openKeyboard( void )
-{
- HRESULT hr;
-
- // create our interface to direct input
- hr = DirectInput8Create( ApplicationHInstance,
- DIRECTINPUT_VERSION,
- IID_IDirectInput8,
- (void **)&m_pDirectInput,
- nullptr );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openKeyboard: DirectInputCreate failed" ));
- assert( 0 );
- closeKeyboard();
- return;
-
- }
-
- // obtain an interface to the system keyboard device
- hr = m_pDirectInput->CreateDevice( GUID_SysKeyboard,
- &m_pKeyboardDevice,
- nullptr );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openKeyboard: Unable to create keyboard device" ));
- assert( 0 );
- closeKeyboard();
- return;
-
- }
-
- // set the data format for the keyboard
- hr = m_pKeyboardDevice->SetDataFormat( &c_dfDIKeyboard );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openKeyboard: Unable to set data format for keyboard" ));
- assert( 0 );
- closeKeyboard();
- return;
-
- }
-
- /// @todo Check the cooperative level of keyboard for NT, 2000, DX8 etc ...
- // set the cooperative level for the keyboard, must be non-exclusive for
- // NT support, but we should check with the latest versions of DirectX
- // on 2000 etc
- //
- hr = m_pKeyboardDevice->SetCooperativeLevel( ApplicationHWnd,
- DISCL_FOREGROUND |
- DISCL_NONEXCLUSIVE );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openKeyboard: Unable to set cooperative level" ));
- assert( 0 );
- closeKeyboard();
- return;
-
- }
-
- // set the keyboard buffer size
- DIPROPDWORD prop;
- prop.diph.dwSize = sizeof( DIPROPDWORD );
- prop.diph.dwHeaderSize = sizeof( DIPROPHEADER );
- prop.diph.dwObj = 0;
- prop.diph.dwHow = DIPH_DEVICE;
- prop.dwData = KEYBOARD_BUFFER_SIZE;
- hr = m_pKeyboardDevice->SetProperty( DIPROP_BUFFERSIZE, &prop.diph );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openKeyboard: Unable to set keyboard buffer size property" ));
- assert( 0 );
- closeKeyboard();
- return;
-
- }
-
- // acquire the keyboard
- hr = m_pKeyboardDevice->Acquire();
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openKeyboard: Unable to acquire keyboard device" ));
- // Note - This can happen in windowed mode, and we can re-acquire later. So don't
- // close the keyboard. jba.
- // closeKeyboard();
- return;
-
- }
-
- DEBUG_LOG(( "OK - Keyboard initialized successfully." ));
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** close the direct input keyboard */
-//-------------------------------------------------------------------------------------------------
-void DirectInputKeyboard::closeKeyboard( void )
-{
-
- if( m_pKeyboardDevice )
- {
-
- m_pKeyboardDevice->Unacquire();
- m_pKeyboardDevice->Release();
- m_pKeyboardDevice = nullptr;
- DEBUG_LOG(( "OK - Keyboard deviced closed" ));
-
- }
- if( m_pDirectInput )
- {
-
- m_pDirectInput->Release();
- m_pDirectInput = nullptr;
- DEBUG_LOG(( "OK - Keyboard direct input interface closed" ));
-
- }
-
- DEBUG_LOG(( "OK - Keyboard shutdown complete" ));
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Get a single keyboard event from direct input */
-//-------------------------------------------------------------------------------------------------
-void DirectInputKeyboard::getKey( KeyboardIO *key )
-{
- static int errs = 0;
- DIDEVICEOBJECTDATA kbdat;
- DWORD num = 0;
-// int done = 0;
- HRESULT hr;
-
- assert( key );
- key->key = KEY_NONE;
-
- if( m_pKeyboardDevice )
- {
- // get 1 key, if available
- num = 1;
- hr = m_pKeyboardDevice->Acquire();
- if (hr == DI_OK || hr == S_FALSE)
- hr = m_pKeyboardDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ),
- &kbdat, &num, 0 );
- switch( hr )
- {
-
- // ----------------------------------------------------------------------
- case DI_OK:
- break;
-
- // ----------------------------------------------------------------------
- case DIERR_INPUTLOST:
- case DIERR_NOTACQUIRED:
-
- // if we lost focus, attempt to re-acquire
- hr = m_pKeyboardDevice->Acquire();
- switch( hr )
- {
-
- // ------------------------------------------------------------------
- //If an error occurs return KEY_NONE
- case DIERR_INVALIDPARAM:
- case DIERR_NOTINITIALIZED:
- case DIERR_OTHERAPPHASPRIO:
- break;
-
- // ------------------------------------------------------------------
- // If successful... tell system to loop back
- case DI_OK:
- case S_FALSE:
- {
-
- // this will tell the system to loop again
- key->key = KEY_LOST;
-
- break;
-
- }
-
- }
-
- return;
-
- // ----------------------------------------------------------------------
- default:
- return;
-
- }
-
- // no keys returned
- if( num == 0 )
- return;
-
- // set the key
- key->key = (UnsignedByte)(kbdat.dwOfs & 0xFF);
-
- //
- // state of key, note we are setting the key state here with an assignment
- // and not a bit set of the up/down state, this is the "start"
- // of building this "key"
- //
- if( kbdat.dwData & 0x0080 )
- {
- key->state = KEY_STATE_DOWN;
- key->keyDownTimeMsec = kbdat.dwTimeStamp;
- }
- else
- {
- key->state = KEY_STATE_UP;
- }
-
- // set status as unused (unprocessed)
- key->status = KeyboardIO::STATUS_UNUSED;
-
- }
-
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-DirectInputKeyboard::DirectInputKeyboard( void )
-{
-
- m_pDirectInput = nullptr;
- m_pKeyboardDevice = nullptr;
-
-
- if( GetKeyState( VK_CAPITAL ) & 0x01 )
- {
- m_modifiers |= KEY_STATE_CAPSLOCK;
- }
- else
- {
- m_modifiers &= ~KEY_STATE_CAPSLOCK;
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-DirectInputKeyboard::~DirectInputKeyboard( void )
-{
-
- // close keyboard and release all resource
- closeKeyboard();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** initialize the keyboard */
-//-------------------------------------------------------------------------------------------------
-void DirectInputKeyboard::init( void )
-{
-
- // extending functionality
- Keyboard::init();
-
- // open the direct input keyboard
- openKeyboard();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset keyboard system */
-//-------------------------------------------------------------------------------------------------
-void DirectInputKeyboard::reset( void )
-{
-
- // extend functionality
- Keyboard::reset();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** called once per frame to update the keyboard state */
-//-------------------------------------------------------------------------------------------------
-void DirectInputKeyboard::update( void )
-{
-
- // extending functionality
- Keyboard::update();
-
-/*
- // make sure the keyboard buffer is flushed
- if( m_pKeyboardDevice )
- {
- DWORD items = INFINITE;
-
- m_pKeyboardDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ),
- nullptr, &items, 0 );
-
- }
-*/
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Return TRUE if the caps lock key is down/hilighted */
-//-------------------------------------------------------------------------------------------------
-Bool DirectInputKeyboard::getCapsState( void )
-{
-
- return BitIsSet( GetKeyState( VK_CAPITAL ), 0X01);
-
-}
diff --git a/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp b/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp
deleted file mode 100644
index a4e10b857b2..00000000000
--- a/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-// FILE: Win32DIMouse.cpp /////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, June 2001
-// Desc: Win32 direct input implementation for the mouse
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include
-#include
-#include
-
-#include "Common/Debug.h"
-#include "GameClient/Display.h"
-#include "Win32Device/GameClient/Win32DIMouse.h"
-#include "WinMain.h"
-
-// DEFINES ////////////////////////////////////////////////////////////////////////////////////////
-enum { MOUSE_BUFFER_SIZE = 256, };
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** Create our direct input object, mouse device, and initialize it to the
- * data formats we want */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::openMouse( void )
-{
- HRESULT hr;
-
- // create our direct input device for mouse access
- hr = DirectInput8Create( ApplicationHInstance,
- DIRECTINPUT_VERSION,
- IID_IDirectInput8,
- (void **)&m_pDirectInput,
- nullptr );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openMouse: Unable to create direct input interface" ));
- assert( 0 );
- closeMouse();
- return;
-
- }
-
- // create a device for the system mouse
- hr = m_pDirectInput->CreateDevice( GUID_SysMouse, &m_pMouseDevice, nullptr );
- &m_pMouseDevice,
- nullptr );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openMouse: Unable to create mouse device" ));
- assert( 0 );
- closeMouse();
- return;
-
- }
-
- // set the data format for the mouse
- hr = m_pMouseDevice->SetDataFormat( &c_dfDIMouse );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openMouse: Unable to set mouse data format" ));
- assert( 0 );
- closeMouse();
- return;
-
- }
-
- // set the mouse cooperative level
- hr = m_pMouseDevice->SetCooperativeLevel( ApplicationHWnd,
- DISCL_NONEXCLUSIVE |
- DISCL_FOREGROUND );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openMouse: Unable to set coop level" ));
- assert( 0 );
- closeMouse();
- return;
-
- }
-
- // set the mouse buffer size
- DIPROPDWORD prop;
- prop.diph.dwSize = sizeof( DIPROPDWORD );
- prop.diph.dwHeaderSize = sizeof( DIPROPHEADER );
- prop.diph.dwObj = 0;
- prop.diph.dwHow = DIPH_DEVICE;
- prop.dwData = MOUSE_BUFFER_SIZE;
- hr = m_pMouseDevice->SetProperty( DIPROP_BUFFERSIZE, &prop.diph );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openMouse: Unable to set buffer property" ));
- assert( 0 );
- closeMouse();
- return;
-
- }
-
- // acquire the mouse
- hr = m_pMouseDevice->Acquire();
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "ERROR - openMouse: Unable to acquire mouse" ));
- assert( 0 );
- closeMouse();
- return;
-
- }
-
- // get some information about the mouse
- DIDEVCAPS diDevCaps;
-
- diDevCaps.dwSize = sizeof( DIDEVCAPS );
- hr = m_pMouseDevice->GetCapabilities( &diDevCaps );
- if( FAILED( hr ) )
- {
-
- DEBUG_LOG(( "WARNING - openMouse: Can't get capabilities of mouse for button setup" ));
-
- }
- else
- {
-
- // keep some data about the mouse we care about
- m_numButtons = (UnsignedByte)diDevCaps.dwButtons;
- m_numAxes = (UnsignedByte)diDevCaps.dwAxes;
- m_forceFeedback = BitIsSet( diDevCaps.dwFlags, DIDC_FORCEFEEDBACK );
-
- DEBUG_LOG(( "OK - Mouse info: Buttons = '%d', Force Feedback = '%s', Axes = '%d'",
- m_numButtons, m_forceFeedback ? "Yes" : "No", m_numAxes ));
-
- }
-
- DEBUG_LOG(( "OK - Mouse initialized successfully" ));
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Release any resources for our direct input mouse */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::closeMouse( void )
-{
-
- // release the mouse device
- if( m_pMouseDevice )
- {
-
- m_pMouseDevice->Unacquire();
- m_pMouseDevice->Release();
- m_pMouseDevice = nullptr;
- DEBUG_LOG(( "OK - Mouse device closed" ));
-
- }
-
- // release our direct input interface for the mouse
- if( m_pDirectInput )
- {
-
- m_pDirectInput->Release();
- m_pDirectInput = nullptr;
- DEBUG_LOG(( "OK - Mouse direct input interface closed" ));
-
- }
-
- DEBUG_LOG(( "OK - Mouse shutdown complete" ));
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Get a single mouse event from the device */
-//-------------------------------------------------------------------------------------------------
-UnsignedByte DirectInputMouse::getMouseEvent( MouseIO *result, Bool flush )
-{
- HRESULT hr;
- DIDEVICEOBJECTDATA mdat;
- UnsignedByte mouseResult = MOUSE_NONE;
- DWORD num;
-
- /* set these to defaults */
- result->leftState = result->middleState = result->rightState = FALSE;
- result->leftState = result->middleState = result->rightState = MBS_None;
- result->pos.x = result->pos.y = result->wheelPos = 0;
-
- if( m_pMouseDevice )
- {
-
- // get 1 event, if available
- num = 1;
- m_pMouseDevice->Poll();
- hr = m_pMouseDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ),
- &mdat,
- &num,
- 0 );
- switch( hr )
- {
-
- // ----------------------------------------------------------------------
- case DI_OK:
- {
- // nothing returned
- if( num != 0 )
- {
- mapDirectInputMouse( result, &mdat );
- mouseResult = MOUSE_OK;
- }
- break;
- }
-
- // ----------------------------------------------------------------------
- case DIERR_NOTACQUIRED:
- case DIERR_INPUTLOST:
- {
-
- // if we lost focus, attempt to re-acquire
- hr = m_pMouseDevice->Acquire();
- switch( hr )
- {
-
- // ------------------------------------------------------------------
- // If successful... tell system to loop back
- case DI_OK:
- case S_FALSE:
- mouseResult = MOUSE_LOST;
-
- // ------------------------------------------------------------------
- //If an error occurs return MOUSE_NONE
- case DIERR_INVALIDPARAM:
- case DIERR_NOTINITIALIZED:
- case DIERR_OTHERAPPHASPRIO:
- default:
- break;
-
- }
-
- break;
- }
-
- // ----------------------------------------------------------------------
- default:
-// DBGPRINTF(("GetMouseEvent: GetDeviceData Error: %X.\r\n", hr ));
- break;
-
- }
-
- }
-
- return mouseResult;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Map the direct input codes to our own mouse format */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::mapDirectInputMouse( MouseIO *mouse,
- DIDEVICEOBJECTDATA *mdat )
-{
-
- switch( mdat->dwOfs )
- {
- case DIMOFS_BUTTON0:
- mouse->leftState = (( mdat->dwData & 0x0080 ) ? MBS_Down : MBS_Up);
- break;
-
- case DIMOFS_BUTTON1:
- mouse->rightState = (( mdat->dwData & 0x0080 ) ? MBS_Down : MBS_Up);
- break;
-
- case DIMOFS_BUTTON2:
- mouse->middleState = (( mdat->dwData & 0x0080 ) ? MBS_Down : MBS_Up);
- break;
-
- case DIMOFS_BUTTON3:
- break;
-
- case DIMOFS_X:
- mouse->pos.x = mdat->dwData;
- break;
-
- case DIMOFS_Y:
- mouse->pos.y = mdat->dwData;
- break;
-
- case DIMOFS_Z:
- mouse->wheelPos = mdat->dwData;
- break;
- }
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-DirectInputMouse::DirectInputMouse( void )
-{
-
- m_pDirectInput = nullptr;
- m_pMouseDevice = nullptr;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-DirectInputMouse::~DirectInputMouse( void )
-{
-
- // release all mouse resources
- closeMouse();
-// ShowCursor( TRUE );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Initialize the direct input mouse device */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::init( void )
-{
- POINT p;
-
- // extending functionality from our base class
- Mouse::init();
-
- // open the mouse and create the direct input interfaces we need
- openMouse();
-
- // move the window mouse to the location we have initialized in our system
- p.x = m_currMouse.pos.x;
- p.y = m_currMouse.pos.y;
- ClientToScreen( ApplicationHWnd, &p );
- SetCursorPos( p.x, p.y );
-// ShowCursor( FALSE );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset direct input mouse */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::reset( void )
-{
-
- // extend
- Mouse::reset();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Update the mouse position and button data, this is called once per
- * frame in the engine. NOTE that this routine is extendion functionality
- * that we may need that is direct input specific, not replacing */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::update( void )
-{
-
- // extendion functionality from our base class
- Mouse::update();
-
- //
- // since we are currently using the windows cursor because it updates at
- // an independent rate of our application we will always just use the windows
- // mouse cursor position
- //
-
- /** @todo we need to really visit this system and possibly come up with
- our own multi-threaded cursor etc */
- POINT p;
- GetCursorPos( &p );
- ScreenToClient( ApplicationHWnd, &p );
- moveMouse( p.x, p.y, MOUSE_MOVE_ABSOLUTE );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Set the limits which the mouse is allowed to move around in. We
- * will limit it to the client area, and if we are windowed we will
- * allow for the mouse to move within the title bar at the top of
- * the window */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::setMouseLimits( void )
-{
-
- //
- // extending functionality, although we may overwrite the limits set
- // from the base class
- //
- Mouse::setMouseLimits();
-
- //
- // when running windowed we want to keep the mouse within the game
- // window cause it's annoying to mouse out of the window and click
- // on a background window.
- //
- if( TheDisplay && TheDisplay->getWindowed() == TRUE )
- {
- RECT windowRect;
-
- // get the window rect
- GetWindowRect( ApplicationHWnd, &windowRect );
-
- // keep the cursor clipped to these coords when running windowed
- ClipCursor( &windowRect );
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** set the cursor position for windows OS */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::setPosition( Int x, Int y )
-{
- POINT p;
-
- // extending functionality
- Mouse::setPosition( x, y );
-
- // set the windows cursor
- p.x = x;
- p.y = y;
- ClientToScreen( ApplicationHWnd, &p );
-
- // set the window mouse
- SetCursorPos( p.x, p.y );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Super basic simplistic cursor */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::setCursor( MouseCursor cursor )
-{
-
- // extend
- Mouse::setCursor( cursor );
-
- // if we're already on this cursor ignore
- if( m_currentCursor == cursor )
- return;
-
- switch( cursor )
- {
-
- case NONE:
- SetCursor( nullptr );
- break;
-
- case NORMAL:
- case ARROW:
- SetCursor( LoadCursor( nullptr, IDC_ARROW ) );
- break;
-
- case SCROLL:
- SetCursor( LoadCursor( nullptr, IDC_SIZEALL ) );
- break;
-
- case CROSS:
- SetCursor( LoadCursor( nullptr, IDC_CROSS ) );
- break;
-
- }
-
- // save current cursor
- m_currentCursor = cursor;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Capture the mouse to our application */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::capture( void )
-{
-
- SetCapture( ApplicationHWnd );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Release the mouse capture for our app window */
-//-------------------------------------------------------------------------------------------------
-void DirectInputMouse::releaseCapture( void )
-{
-
- ReleaseCapture();
-
-}
diff --git a/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp b/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp
deleted file mode 100644
index 87a760f00b8..00000000000
--- a/Generals/Code/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Win32Mouse.cpp ///////////////////////////////////////////////////////////////////////////
-// Created: Colin Day, July 2001
-// Desc: Interface for the mouse using only the Win32 messages
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#define WIN32_LEAN_AND_MEAN
-#include
-
-#include "Common/Debug.h"
-#include "Common/GlobalData.h"
-#include "Common/LocalFileSystem.h"
-#include "GameClient/GameClient.h"
-#include "Win32Device/GameClient/Win32Mouse.h"
-#include "WinMain.h"
-
-
-// EXTERN /////////////////////////////////////////////////////////////////////////////////////////
-extern Win32Mouse *TheWin32Mouse;
-
-HCURSOR cursorResources[Mouse::NUM_MOUSE_CURSORS][MAX_2D_CURSOR_DIRECTIONS];
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** Get a mouse event from the buffer if available, we need to translate
- * from the windows message meanings to our own internal mouse
- * structure */
-//-------------------------------------------------------------------------------------------------
-UnsignedByte Win32Mouse::getMouseEvent( MouseIO *result, Bool flush )
-{
-
- // if there is nothing here there is no event data to do
- if( m_eventBuffer[ m_nextGetIndex ].msg == 0 )
- return MOUSE_NONE;
-
- // translate the win32 mouse message to our own system
- translateEvent( m_nextGetIndex, result );
-
- // remove this event from the buffer by setting msg to zero
- m_eventBuffer[ m_nextGetIndex ].msg = 0;
-
- //
- // our next get index will now be advanced to the next index, wrapping at
- // the mad
- //
- m_nextGetIndex++;
- if( m_nextGetIndex >= Mouse::NUM_MOUSE_EVENTS )
- m_nextGetIndex = 0;
-
- // got event OK and all done with this one
- return MOUSE_OK;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Translate a win32 mouse event to our own event info */
-//-------------------------------------------------------------------------------------------------
-void Win32Mouse::translateEvent( UnsignedInt eventIndex, MouseIO *result )
-{
- UINT msg = m_eventBuffer[ eventIndex ].msg;
- WPARAM wParam = m_eventBuffer[ eventIndex ].wParam;
- LPARAM lParam = m_eventBuffer[ eventIndex ].lParam;
-
- // set these to defaults
- result->leftState = result->middleState = result->rightState = MBS_None;
- result->pos.x = result->pos.y = result->wheelPos = 0;
-
- // Time is the same for all events
- result->time = m_eventBuffer[ eventIndex ].time;
-
- switch( msg )
- {
-
- // ------------------------------------------------------------------------
- case WM_LBUTTONDOWN:
- {
-
- result->leftState = MBS_Down;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_LBUTTONUP:
- {
-
- result->leftState = MBS_Up;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_LBUTTONDBLCLK:
- {
-
- result->leftState = MBS_DoubleClick;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_MBUTTONDOWN:
- {
-
- result->middleState = MBS_Down;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_MBUTTONUP:
- {
-
- result->middleState = MBS_Up;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_MBUTTONDBLCLK:
- {
-
- result->middleState = MBS_DoubleClick;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_RBUTTONDOWN:
- {
-
- result->rightState = MBS_Down;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_RBUTTONUP:
- {
-
- result->rightState = MBS_Up;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_RBUTTONDBLCLK:
- {
-
- result->rightState = MBS_DoubleClick;
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case WM_MOUSEMOVE:
- {
-
- result->pos.x = LOWORD( lParam );
- result->pos.y = HIWORD( lParam );
- break;
-
- }
-
- // ------------------------------------------------------------------------
- case 0x020A: // WM_MOUSEWHEEL
- {
- POINT p;
-
- // translate the screen mouse position to be relative to the application window
- p.x = LOWORD( lParam );
- p.y = HIWORD( lParam );
- ScreenToClient( ApplicationHWnd, &p );
-
- // note the short cast here to keep signed information in tact
- result->wheelPos = (Short)HIWORD( wParam );
- result->pos.x = p.x;
- result->pos.y = p.y;
- break;
-
- }
-
- // ------------------------------------------------------------------------
- default:
- {
-
- DEBUG_CRASH(( "translateEvent: Unknown Win32 mouse event [%d,%d,%d]",
- msg, wParam, lParam ));
- return;
-
- }
-
- }
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Win32Mouse::Win32Mouse( void )
-{
-
- // zero our event list
- memset( &m_eventBuffer, 0, sizeof( m_eventBuffer ) );
-
- m_nextFreeIndex = 0;
- m_nextGetIndex = 0;
- m_currentWin32Cursor = NONE;
- for (Int i=0; i= Mouse::NUM_MOUSE_EVENTS )
- m_nextFreeIndex = 0;
-
-}
-
-extern HINSTANCE ApplicationHInstance;
-
-void Win32Mouse::setVisibility(Bool visible)
-{
- //Extend
- Mouse::setVisibility(visible);
- //Maybe need to set cursor to force hiding of some cursors.
- Win32Mouse::setCursor(getMouseCursor());
-}
-
-//-------------------------------------------------------------------------------------------------
-void Win32Mouse::loseFocus()
-{
- Mouse::loseFocus();
- m_lostFocus = true;
-}
-
-//-------------------------------------------------------------------------------------------------
-void Win32Mouse::regainFocus()
-{
- Mouse::regainFocus();
- m_lostFocus = false;
-}
-
-/**Preload all the cursors we may need during the game. This must be done before the D3D device
-is created to avoid cursor corruption on buggy ATI Radeon cards. */
-void Win32Mouse::initCursorResources(void)
-{
- for (Int cursor=FIRST_CURSOR; cursor 1)
- snprintf(resourcePath, ARRAY_SIZE(resourcePath), "data\\cursors\\%s%d.ANI",
- m_cursorInfo[cursor].textureName.str(), direction);
- else
- snprintf(resourcePath, ARRAY_SIZE(resourcePath), "data\\cursors\\%s.ANI",
- m_cursorInfo[cursor].textureName.str());
-
- // check for a MOD cursor.
- Bool loaded = FALSE;
- if (TheGlobalData->m_modDir.isNotEmpty())
- {
- AsciiString fname;
- if (m_cursorInfo[cursor].numDirections > 1)
- fname.format("%sdata\\cursors\\%s%d.ANI", TheGlobalData->m_modDir.str(), m_cursorInfo[cursor].textureName.str(), direction);
- else
- fname.format("%sdata\\cursors\\%s.ANI", TheGlobalData->m_modDir.str(), m_cursorInfo[cursor].textureName.str());
-
- if (TheLocalFileSystem->doesFileExist(fname.str()))
- {
- cursorResources[cursor][direction]=LoadCursorFromFile(fname.str());
- loaded = TRUE;
- }
- }
-
- if (!loaded)
- cursorResources[cursor][direction]=LoadCursorFromFile(resourcePath);
- DEBUG_ASSERTCRASH(cursorResources[cursor][direction], ("MissingCursor %s",resourcePath));
- }
- }
-// SetCursor(cursorResources[cursor][m_directionFrame]);
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Super basic simplistic cursor */
-//-------------------------------------------------------------------------------------------------
-void Win32Mouse::setCursor( MouseCursor cursor )
-{
- // extend
- Mouse::setCursor( cursor );
-
- if (m_lostFocus)
- return; //stop messing with mouse cursor if we don't have focus.
-
- if (cursor == NONE || !m_visible)
- SetCursor( nullptr );
- else
- {
- SetCursor(cursorResources[cursor][m_directionFrame]);
- }
-
- // save current cursor
- m_currentWin32Cursor=m_currentCursor = cursor;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Capture the mouse to our application */
-//-------------------------------------------------------------------------------------------------
-void Win32Mouse::capture( void )
-{
-
- RECT rect;
- ::GetClientRect(ApplicationHWnd, &rect);
-
- POINT leftTop;
- leftTop.x = rect.left;
- leftTop.y = rect.top;
-
- POINT rightBottom;
- rightBottom.x = rect.right;
- rightBottom.y = rect.bottom;
-
- ::ClientToScreen(ApplicationHWnd, &leftTop);
- ::ClientToScreen(ApplicationHWnd, &rightBottom);
-
- rect.left = leftTop.x;
- rect.top = leftTop.y;
- rect.right = rightBottom.x;
- rect.bottom = rightBottom.y;
-
- if (::ClipCursor(&rect))
- {
- onCursorCaptured(true);
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Release the mouse capture for our app window */
-//-------------------------------------------------------------------------------------------------
-void Win32Mouse::releaseCapture( void )
-{
-
- if (::ClipCursor(nullptr))
- {
- onCursorCaptured(false);
- }
-
-}
diff --git a/Generals/Code/Tools/WorldBuilder/CMakeLists.txt b/Generals/Code/Tools/WorldBuilder/CMakeLists.txt
index 263cc6fe32b..1a06312d23a 100644
--- a/Generals/Code/Tools/WorldBuilder/CMakeLists.txt
+++ b/Generals/Code/Tools/WorldBuilder/CMakeLists.txt
@@ -22,7 +22,6 @@ set(WORLDBUILDER_SRC
"src/EditGroup.cpp"
"src/EditObjectParameter.cpp"
"src/EditParameter.cpp"
- "src/EulaDialog.cpp"
"src/ExportScriptsOptions.cpp"
"src/EyedropperTool.cpp"
"src/FeatherOptions.cpp"
@@ -119,7 +118,6 @@ set(WORLDBUILDER_SRC
"include/EditGroup.h"
"include/EditObjectParameter.h"
"include/EditParameter.h"
- "include/euladialog.h"
"include/ExportScriptsOptions.h"
"include/EyedropperTool.h"
"include/FeatherOptions.h"
diff --git a/Generals/Code/Tools/WorldBuilder/include/euladialog.h b/Generals/Code/Tools/WorldBuilder/include/euladialog.h
deleted file mode 100644
index 6203df5b56e..00000000000
--- a/Generals/Code/Tools/WorldBuilder/include/euladialog.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-#pragma once
-
-// euladialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// EulaDialog dialog
-
-class EulaDialog : public CDialog
-{
-// Construction
-public:
- EulaDialog(CWnd* pParent = nullptr); // standard constructor
-
-// Dialog Data
- //{{AFX_DATA(EulaDialog)
- enum { IDD = IDD_EULA_AGREEMENT };
- // NOTE: the ClassWizard will add data members here
- //}}AFX_DATA
-
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(EulaDialog)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(EulaDialog)
- virtual BOOL OnInitDialog();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
diff --git a/Generals/Code/Tools/WorldBuilder/res/WorldBuilder.rc b/Generals/Code/Tools/WorldBuilder/res/WorldBuilder.rc
index a707c881b46..4755a373920 100644
--- a/Generals/Code/Tools/WorldBuilder/res/WorldBuilder.rc
+++ b/Generals/Code/Tools/WorldBuilder/res/WorldBuilder.rc
@@ -1729,17 +1729,6 @@ BEGIN
DEFPUSHBUTTON "Preview",IDC_PREVIEW,7,52,50,14
END
-IDD_EULA_AGREEMENT DIALOG DISCARDABLE 0, 0, 267, 289
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "EA TOOLS END USER LICENSE"
-FONT 8, "MS Sans Serif"
-BEGIN
- PUSHBUTTON "Cancel",IDCANCEL,210,268,50,14
- DEFPUSHBUTTON "Accept Terms",IDOK,154,268,50,14
- EDITTEXT IDC_EDIT1,17,18,230,246,ES_MULTILINE | ES_READONLY |
- WS_VSCROLL
-END
-
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
@@ -2238,14 +2227,6 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 66
END
-
- IDD_EULA_AGREEMENT, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 260
- TOPMARGIN, 7
- BOTTOMMARGIN, 282
- END
END
#endif // APSTUDIO_INVOKED
@@ -2723,11 +2704,6 @@ BEGIN
IDS_SINGLE_SELECTION_ONLY "Single Selection Only"
IDS_NO_UPGRADES "No Upgrades Available"
IDS_TEAMS_FIXED "All Teams have been fixed."
- IDS_EULA_AGREEMENT1 "Electronic Arts Inc, and its subsidiaries, affiliates and licensors (collectively, ""EA"") grants you a non- transferable license to download and use one copy of the software tool (""Tool""), other materials accompanying the tool, and the materials created with the tool (collectively the ""Tools & Materials"") solely for your personal noncommercial use in connection with EA products."
- IDS_EULA_AGREEMENT2 "\r\n\r\nEA and its Licensors own all of the rights in the Tools & Materials. You may not alter any of EA's trademarks or logos, or alter or remove any of EA's or its Licensor's trademark or copyright notices included in or with the Tools & Materials. Your right to use Tools & Materials is limited to the license grant above, and you may not otherwise copy, display, distribute, perform, publish, modify, or use any of the Tools & Materials. Without limiting the preceding sentence, you may not modify, reverse engineer, disassemble, license, transfer, distribute, create derivative works from, or sell the Tool, or use the Tools & Materials to further any commercial or unlawful purpose. Without limiting the foregoing, you may not use the Tools & Materials to sell advertising, to promote another product or business, or on any site that operates or promotes a server emulator."
- IDS_EULA_AGREEMENT3 "\r\n\r\nEA does not represent or warrant that you will be able to use any of the Tools & Materials. You expressly agree that your use of the Tools & Materials is at your sole risk. The Tools & Materials are provided on an ""as is,"" ""as available"" basis. EA disclaims all implied warranties and conditions, including without limitation any implied warranties of merchantability, fitness for a particular purpose, or non-infringement of third party rights. EA assumes no responsibility for any damages suffered by you. At EA's request, you agree to defend, indemnify and hold harmless EA from all liabilities, claims and expenses, including attorneys' fees, arising from any breach of this License by you and/or your use or misuse of the Tools & Materials."
- IDS_EULA_AGREEMENT4 "\r\n\r\nEA may make the Tools & Materials available at its site(s) located in the United States and/or Canada and/or the European Union. You are solely responsible for knowing and complying with all federal, state, and local laws that may apply to your use of Tools & Materials in your own locale. By downloading any Tools & Materials, you warrant that you are not located in any country, or exporting the Tools & Materials to any person or place, to which the United States and/or Canada and/or European Union or its member countries has embargoed goods."
- IDS_EULA_AGREEMENT5 "\r\n\r\nEA may terminate this License at any time. Upon termination, you must destroy or return to EA all Tools & Materials. This License is governed by United States Copyright and California law (without regard to conflicts of law), and is the entire agreement between EA and you regarding the Tools & Materials."
END
#endif // English (U.S.) resources
diff --git a/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp b/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp
index 68b57b89a67..664cdc9505f 100644
--- a/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp
+++ b/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp
@@ -1202,7 +1202,7 @@ Bool EditParameter::loadCommandButtons(CComboBox *pCombo, AsciiString match)
char buf[1024];
char *string;
char *token;
- char seps[] = " ,\t\n";
+ char seps[] = " ,\t\n\r";
fp->nextLine(buf, 1024);
string = buf;
diff --git a/Generals/Code/Tools/WorldBuilder/src/EulaDialog.cpp b/Generals/Code/Tools/WorldBuilder/src/EulaDialog.cpp
deleted file mode 100644
index 1ec06311360..00000000000
--- a/Generals/Code/Tools/WorldBuilder/src/EulaDialog.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-** Command & Conquer Generals(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-// EulaDialog.cpp : implementation file
-//
-
-#include "StdAfx.h"
-#include "WorldBuilder.h"
-#include "euladialog.h"
-
-#ifdef RTS_DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// EulaDialog dialog
-
-
-EulaDialog::EulaDialog(CWnd* pParent /*=nullptr*/)
- : CDialog(EulaDialog::IDD, pParent)
-{
- //{{AFX_DATA_INIT(EulaDialog)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
-}
-
-
-void EulaDialog::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(EulaDialog)
- // NOTE: the ClassWizard will add DDX and DDV calls here
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(EulaDialog, CDialog)
- //{{AFX_MSG_MAP(EulaDialog)
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// EulaDialog message handlers
-
-BOOL EulaDialog::OnInitDialog()
-{
- CDialog::OnInitDialog();
-
- CString theText;
- theText.LoadString( IDS_EULA_AGREEMENT1 );
-
- CString concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT2 );
- theText += concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT3 );
- theText += concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT4 );
- theText += concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT5 );
- theText += concatText;
-
- CWnd *theEditDialog = GetDlgItem( IDC_EDIT1 );
- if( theEditDialog )
- {
- theEditDialog->SetWindowText( theText );
- }
-
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
diff --git a/Generals/Code/Tools/WorldBuilder/src/ObjectOptions.cpp b/Generals/Code/Tools/WorldBuilder/src/ObjectOptions.cpp
index 4c6a369f38d..8ef7c88f13c 100644
--- a/Generals/Code/Tools/WorldBuilder/src/ObjectOptions.cpp
+++ b/Generals/Code/Tools/WorldBuilder/src/ObjectOptions.cpp
@@ -402,10 +402,11 @@ HTREEITEM ObjectOptions::_FindOrDont(const char* pLabel, HTREEITEM startPoint)
std::list itemsToEx;
itemsToEx.push_back(startPoint);
- while (itemsToEx.front()) {
+ while (!itemsToEx.empty()) {
char buffer[_MAX_PATH];
HTREEITEM hItem = itemsToEx.front();
itemsToEx.pop_front();
+ DEBUG_ASSERTCRASH(hItem != nullptr, ("Unexpected tree item pointer in ObjectOptions::_FindOrDont"));
if (!m_objectTreeView.ItemHasChildren(hItem)) {
TVITEM item;
diff --git a/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp b/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp
index 004cb722762..3209097a103 100644
--- a/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp
+++ b/Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp
@@ -21,7 +21,6 @@
#include "StdAfx.h"
#include "WorldBuilder.h"
-#include "euladialog.h"
#include "MainFrm.h"
#include "OpenMap.h"
#include "SplashScreen.h"
@@ -272,12 +271,6 @@ static LONG WINAPI UnHandledExceptionFilter(struct _EXCEPTION_POINTERS* e_info)
BOOL CWorldBuilderApp::InitInstance()
{
- EulaDialog eulaDialog;
- if( eulaDialog.DoModal() == IDCANCEL )
- {
- return FALSE;
- }
-
// initialization
SetUnhandledExceptionFilter(UnHandledExceptionFilter);
diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt
index 3c6fb910509..17cd6866f2f 100644
--- a/GeneralsMD/Code/GameEngine/CMakeLists.txt
+++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt
@@ -140,28 +140,28 @@ set(GAMEENGINE_SRC
Include/GameClient/AnimateWindowManager.h
Include/GameClient/CampaignManager.h
# Include/GameClient/ChallengeGenerals.h
- Include/GameClient/ClientInstance.h
+# Include/GameClient/ClientInstance.h
# Include/GameClient/ClientRandomValue.h
- Include/GameClient/Color.h
+# Include/GameClient/Color.h
Include/GameClient/CommandXlat.h
Include/GameClient/ControlBar.h
Include/GameClient/ControlBarResizer.h
Include/GameClient/ControlBarScheme.h
- Include/GameClient/Credits.h
+# Include/GameClient/Credits.h
Include/GameClient/DebugDisplay.h
Include/GameClient/Diplomacy.h
Include/GameClient/DisconnectMenu.h
Include/GameClient/Display.h
- Include/GameClient/DisplayString.h
- Include/GameClient/DisplayStringManager.h
+# Include/GameClient/DisplayString.h
+# Include/GameClient/DisplayStringManager.h
Include/GameClient/Drawable.h
Include/GameClient/DrawableInfo.h
- Include/GameClient/DrawGroupInfo.h
+# Include/GameClient/DrawGroupInfo.h
Include/GameClient/EstablishConnectionsMenu.h
Include/GameClient/Eva.h
Include/GameClient/ExtendedMessageBox.h
Include/GameClient/FontDesc.h
- Include/GameClient/FXList.h
+# Include/GameClient/FXList.h
Include/GameClient/Gadget.h
Include/GameClient/GadgetCheckBox.h
Include/GameClient/GadgetComboBox.h
@@ -174,29 +174,29 @@ set(GAMEENGINE_SRC
Include/GameClient/GadgetTabControl.h
Include/GameClient/GadgetTextEntry.h
Include/GameClient/GameClient.h
- Include/GameClient/GameFont.h
+# Include/GameClient/GameFont.h
Include/GameClient/GameInfoWindow.h
- Include/GameClient/GameText.h
- Include/GameClient/GameWindow.h
- Include/GameClient/GameWindowGlobal.h
+# Include/GameClient/GameText.h
+# Include/GameClient/GameWindow.h
+# Include/GameClient/GameWindowGlobal.h
Include/GameClient/GameWindowID.h
Include/GameClient/GameWindowManager.h
- Include/GameClient/GameWindowTransitions.h
- Include/GameClient/GlobalLanguage.h
- Include/GameClient/GraphDraw.h
+# Include/GameClient/GameWindowTransitions.h
+# Include/GameClient/GlobalLanguage.h
+# Include/GameClient/GraphDraw.h
Include/GameClient/GUICallbacks.h
Include/GameClient/GUICommandTranslator.h
- Include/GameClient/HeaderTemplate.h
+# Include/GameClient/HeaderTemplate.h
Include/GameClient/HintSpy.h
Include/GameClient/HotKey.h
Include/GameClient/Image.h
- Include/GameClient/IMEManager.h
+# Include/GameClient/IMEManager.h
Include/GameClient/InGameUI.h
- Include/GameClient/Keyboard.h
+# Include/GameClient/Keyboard.h
Include/GameClient/KeyDefs.h
- Include/GameClient/LanguageFilter.h
- Include/GameClient/Line2D.h
- Include/GameClient/LoadScreen.h
+# Include/GameClient/LanguageFilter.h
+# Include/GameClient/Line2D.h
+# Include/GameClient/LoadScreen.h
Include/GameClient/LookAtXlat.h
# Include/GameClient/MapUtil.h
Include/GameClient/MessageBox.h
@@ -205,14 +205,14 @@ set(GAMEENGINE_SRC
Include/GameClient/Module/BeaconClientUpdate.h
Include/GameClient/Module/SwayClientUpdate.h
Include/GameClient/Module/DynamicGeometryClientUpdate.h
- Include/GameClient/Mouse.h
+# Include/GameClient/Mouse.h
# Include/GameClient/ParabolicEase.h
# Include/GameClient/ParticleSys.h
Include/GameClient/PlaceEventTranslator.h
- Include/GameClient/ProcessAnimateWindow.h
- Include/GameClient/RadiusDecal.h
+# Include/GameClient/ProcessAnimateWindow.h
+# Include/GameClient/RadiusDecal.h
Include/GameClient/RayEffect.h
- Include/GameClient/SelectionInfo.h
+# Include/GameClient/SelectionInfo.h
Include/GameClient/SelectionXlat.h
Include/GameClient/Shadow.h
Include/GameClient/Shell.h
@@ -220,17 +220,17 @@ set(GAMEENGINE_SRC
Include/GameClient/ShellMenuScheme.h
# Include/GameClient/Smudge.h
# Include/GameClient/Snow.h
- Include/GameClient/Statistics.h
+# Include/GameClient/Statistics.h
# Include/GameClient/TerrainRoads.h
# Include/GameClient/TerrainVisual.h
Include/GameClient/TintStatus.h
# Include/GameClient/VideoPlayer.h
# Include/GameClient/View.h
# Include/GameClient/Water.h
- Include/GameClient/WindowLayout.h
+# Include/GameClient/WindowLayout.h
# Include/GameClient/WindowVideoManager.h
Include/GameClient/WindowXlat.h
- Include/GameClient/WinInstanceData.h
+# Include/GameClient/WinInstanceData.h
Include/GameLogic/AI.h
Include/GameLogic/AIDock.h
Include/GameLogic/AIGuard.h
@@ -711,25 +711,25 @@ set(GAMEENGINE_SRC
# Source/Common/UserPreferences.cpp
Source/Common/version.cpp
# Source/Common/WorkerProcess.cpp
- Source/GameClient/ClientInstance.cpp
- Source/GameClient/Color.cpp
- Source/GameClient/Credits.cpp
+# Source/GameClient/ClientInstance.cpp
+# Source/GameClient/Color.cpp
+# Source/GameClient/Credits.cpp
Source/GameClient/Display.cpp
- Source/GameClient/DisplayString.cpp
- Source/GameClient/DisplayStringManager.cpp
+# Source/GameClient/DisplayString.cpp
+# Source/GameClient/DisplayStringManager.cpp
Source/GameClient/Drawable.cpp
Source/GameClient/Drawable/Update/AnimatedParticleSysBoneClientUpdate.cpp
Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp
Source/GameClient/Drawable/Update/SwayClientUpdate.cpp
Source/GameClient/Drawable/Update/DynamicGeometryClientUpdate.cpp
- Source/GameClient/DrawGroupInfo.cpp
+# Source/GameClient/DrawGroupInfo.cpp
Source/GameClient/Eva.cpp
- Source/GameClient/FXList.cpp
+# Source/GameClient/FXList.cpp
Source/GameClient/GameClient.cpp
Source/GameClient/GameClientDispatch.cpp
- Source/GameClient/GameText.cpp
- Source/GameClient/GlobalLanguage.cpp
- Source/GameClient/GraphDraw.cpp
+# Source/GameClient/GameText.cpp
+# Source/GameClient/GlobalLanguage.cpp
+# Source/GameClient/GraphDraw.cpp
Source/GameClient/GUI/AnimateWindowManager.cpp
# Source/GameClient/GUI/ChallengeGenerals.cpp
Source/GameClient/GUI/ControlBar/ControlBar.cpp
@@ -757,12 +757,12 @@ set(GAMEENGINE_SRC
Source/GameClient/GUI/Gadget/GadgetTabControl.cpp
Source/GameClient/GUI/Gadget/GadgetTextEntry.cpp
Source/GameClient/GUI/Gadget/GadgetVerticalSlider.cpp
- Source/GameClient/GUI/GameFont.cpp
- Source/GameClient/GUI/GameWindow.cpp
- Source/GameClient/GUI/GameWindowGlobal.cpp
+# Source/GameClient/GUI/GameFont.cpp
+# Source/GameClient/GUI/GameWindow.cpp
+# Source/GameClient/GUI/GameWindowGlobal.cpp
Source/GameClient/GUI/GameWindowManager.cpp
Source/GameClient/GUI/GameWindowManagerScript.cpp
- Source/GameClient/GUI/GameWindowTransitions.cpp
+# Source/GameClient/GUI/GameWindowTransitions.cpp
Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp
Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
@@ -815,20 +815,20 @@ set(GAMEENGINE_SRC
Source/GameClient/GUI/GUICallbacks/Menus/WOLWelcomeMenu.cpp
Source/GameClient/GUI/GUICallbacks/MessageBox.cpp
Source/GameClient/GUI/GUICallbacks/ReplayControls.cpp
- Source/GameClient/GUI/HeaderTemplate.cpp
- Source/GameClient/GUI/IMEManager.cpp
- Source/GameClient/GUI/LoadScreen.cpp
- Source/GameClient/GUI/ProcessAnimateWindow.cpp
+# Source/GameClient/GUI/HeaderTemplate.cpp
+# Source/GameClient/GUI/IMEManager.cpp
+# Source/GameClient/GUI/LoadScreen.cpp
+# Source/GameClient/GUI/ProcessAnimateWindow.cpp
Source/GameClient/GUI/Shell/Shell.cpp
Source/GameClient/GUI/Shell/ShellMenuScheme.cpp
- Source/GameClient/GUI/WindowLayout.cpp
+# Source/GameClient/GUI/WindowLayout.cpp
# Source/GameClient/GUI/WindowVideoManager.cpp
- Source/GameClient/GUI/WinInstanceData.cpp
+# Source/GameClient/GUI/WinInstanceData.cpp
Source/GameClient/InGameUI.cpp
- Source/GameClient/Input/Keyboard.cpp
- Source/GameClient/Input/Mouse.cpp
- Source/GameClient/LanguageFilter.cpp
- Source/GameClient/Line2D.cpp
+# Source/GameClient/Input/Keyboard.cpp
+# Source/GameClient/Input/Mouse.cpp
+# Source/GameClient/LanguageFilter.cpp
+# Source/GameClient/Line2D.cpp
# Source/GameClient/MapUtil.cpp
Source/GameClient/MessageStream/CommandXlat.cpp
Source/GameClient/MessageStream/GUICommandTranslator.cpp
@@ -840,10 +840,10 @@ set(GAMEENGINE_SRC
Source/GameClient/MessageStream/SelectionXlat.cpp
Source/GameClient/MessageStream/WindowXlat.cpp
# Source/GameClient/ParabolicEase.cpp
- Source/GameClient/RadiusDecal.cpp
- Source/GameClient/SelectionInfo.cpp
+# Source/GameClient/RadiusDecal.cpp
+# Source/GameClient/SelectionInfo.cpp
# Source/GameClient/Snow.cpp
- Source/GameClient/Statistics.cpp
+# Source/GameClient/Statistics.cpp
Source/GameClient/System/Anim2D.cpp
Source/GameClient/System/CampaignManager.cpp
# "Source/GameClient/System/Debug Displayers/AudioDebugDisplay.cpp"
diff --git a/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h b/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h
index e1e4236531b..53e3be17edb 100644
--- a/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h
+++ b/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h
@@ -44,6 +44,7 @@ class TunnelTracker : public MemoryPoolObject,
// contain list access
void iterateContained( ContainIterateFunc func, void *userData, Bool reverse );
UnsignedInt getContainCount() const { return m_containListSize; }
+ UnsignedInt getHeroUnitsContained() const { return m_heroUnitsContained; }
Int getContainMax() const;
const ContainedItemsList* getContainedItemsList() const { return &m_containList; }
void swapContainedItemsList(ContainedItemsList& newList);
@@ -85,6 +86,7 @@ class TunnelTracker : public MemoryPoolObject,
ContainedItemsList m_containList; ///< the contained object pointers list
std::list< ObjectID > m_xferContainList;///< for loading of m_containList during post processing
Int m_containListSize; ///< size of the contain list
+ UnsignedInt m_heroUnitsContained; ///< cached hero count
UnsignedInt m_tunnelCount; ///< How many tunnels have registered so we know when we should kill our contain list
UnsignedInt m_framesForFullHeal; ///< How many frames it takes to fully heal a unit
Bool m_needsFullHealTimeUpdate; ///< Set to true when needing to recalc full heal time to batch the operation
diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/ClientInstance.h b/GeneralsMD/Code/GameEngine/Include/GameClient/ClientInstance.h
deleted file mode 100644
index 1f1ada1daca..00000000000
--- a/GeneralsMD/Code/GameEngine/Include/GameClient/ClientInstance.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 TheSuperHackers
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-#include "Lib/BaseType.h"
-
-namespace rts
-{
-
-// TheSuperHackers @feature Adds support for launching multiple game clients and keeping track of their instance id.
-
-class ClientInstance
-{
-public:
- // Can be called N times, but is initialized just once.
- static bool initialize();
-
- static bool isInitialized();
-
- static bool isMultiInstance();
-
- // Change multi instance on runtime. Must be called before initialize.
- static void setMultiInstance(bool v);
-
- // Skips using the primary instance. Must be called before initialize.
- // Useful when the new process is not meant to collide with another normal Generals process.
- static void skipPrimaryInstance();
-
- // Returns the instance index of this game client. Starts at 0.
- static UnsignedInt getInstanceIndex();
-
- // Returns the instance id of this game client. Starts at 1.
- static UnsignedInt getInstanceId();
-
- // Returns the instance name of the first game client.
- static const char* getFirstInstanceName();
-
-private:
- static HANDLE s_mutexHandle;
- static UnsignedInt s_instanceIndex;
- static Bool s_isMultiInstance;
-};
-
-} // namespace rts
diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h
index 16f89017e60..5edb6851a9e 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h
+++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/AIPathfind.h
@@ -248,6 +248,24 @@ class PathfindCellInfo
UnsignedInt m_closed:1; ///< place for marking this cell as on the closed list
};
+// TheSuperHackers @info The PathfindCellList class acts as a new management class for the pathfindcell open and closed lists
+class PathfindCellList
+{
+ friend class PathfindCell;
+
+public:
+ PathfindCellList() : m_head(nullptr) {}
+
+ void reset(PathfindCell* newHead = nullptr) { m_head = newHead; }
+
+ PathfindCell* getHead() const { return m_head; }
+
+ Bool empty() const { return m_head == nullptr; }
+
+private:
+ PathfindCell* m_head;
+};
+
/**
* This represents one cell in the pathfinding grid.
* These cells categorize the world into idealized cellular states,
@@ -308,23 +326,23 @@ class PathfindCell
UnsignedInt costSoFar( PathfindCell *parent );
- /// put self on "open" list in ascending cost order, return new list
- PathfindCell *putOnSortedOpenList( PathfindCell *list );
+ /// put self on "open" list in ascending cost order
+ void putOnSortedOpenList( PathfindCellList &list );
/// remove self from "open" list
- PathfindCell *removeFromOpenList( PathfindCell *list );
+ void removeFromOpenList( PathfindCellList &list );
/// put self on "closed" list, return new list
- PathfindCell *putOnClosedList( PathfindCell *list );
+ void putOnClosedList( PathfindCellList &list );
/// remove self from "closed" list
- PathfindCell *removeFromClosedList( PathfindCell *list );
+ void removeFromClosedList( PathfindCellList &list );
/// remove all cells from closed list.
- static Int releaseClosedList( PathfindCell *list );
+ static Int releaseClosedList( PathfindCellList &list );
/// remove all cells from closed list.
- static Int releaseOpenList( PathfindCell *list );
+ static Int releaseOpenList( PathfindCellList &list );
inline PathfindCell *getNextOpen(void) {return m_info->m_nextOpen?m_info->m_nextOpen->m_cell: nullptr;}
@@ -785,9 +803,6 @@ class Pathfinder : PathfindServicesInterface, public Snapshot
Bool centerInCell, Int radius, const ICoord2D &startCellNdx,
const Object *obj, Int attackDistance);
- Bool pathDestination( Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest,
- PathfindLayerEnum layer, const Coord3D *groupDest); ///< Checks cost between given locations
-
Int checkPathCost(Object *obj, const LocomotorSet& locomotorSet, const Coord3D *from,
const Coord3D *to);
@@ -861,8 +876,8 @@ class Pathfinder : PathfindServicesInterface, public Snapshot
IRegion2D m_extent; ///< Grid extent limits
IRegion2D m_logicalExtent; ///< Logical grid extent limits
- PathfindCell *m_openList; ///< Cells ready to be explored
- PathfindCell *m_closedList; ///< Cells already explored
+ PathfindCellList m_openList; ///< Cells ready to be explored
+ PathfindCellList m_closedList; ///< Cells already explored
Bool m_isMapReady; ///< True if all cells of map have been classified
Bool m_isTunneling; ///< True if path started in an obstacle
diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h
index afbc94212cb..3146748568c 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h
+++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/CrateCollide.h
@@ -49,6 +49,7 @@ class CrateCollideModuleData : public CollideModuleData
Bool m_isBuildingPickup; ///< This crate can be picked up by a Building (bypassing AI requirement)
Bool m_isHumanOnlyPickup; ///< Can this crate only be picked up by a human player? (Mission thing)
Bool m_isAllowPickAboveTerrain; ///< Can this crate only be picked when on the ground´?
+ Bool m_allowMultiPickup; ///< Can this crate be picked up by multiple objects on the same frame?
ScienceType m_pickupScience; ///< Can only be picked up by a unit whose player has this science
FXList *m_executeFX; ///< FXList to play when activated
diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h
index 88891946681..221032336be 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h
+++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h
@@ -60,7 +60,7 @@ enum HordeActionType CPP_11(: Int)
HORDEACTION_COUNT,
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
HORDEACTION_DEFAULT = HORDEACTION_HORDE,
#else
HORDEACTION_DEFAULT = HORDEACTION_HORDE_FIXED, ///< Does not change unmodified retail game behavior, because all its horde update modules explicitly set Action = HORDE.
diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/OpenContain.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/OpenContain.h
index 1b48c5b4c4c..408b4eff654 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/OpenContain.h
+++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/OpenContain.h
@@ -271,7 +271,6 @@ class OpenContain : public UpdateModule,
ObjectEnterExitMap m_objectEnterExitInfo;
UnsignedInt m_stealthUnitsContained; ///< number of stealth units that can't be seen by enemy players.
UnsignedInt m_heroUnitsContained; ///< cached hero count
- XferVersion m_xferVersion; ///< version of loaded save file for loadPostProcess
Int m_whichExitPath; ///< Cycles from 1 to n and is used only in modules whose data has numberOfExitPaths > 1.
UnsignedInt m_doorCloseCountdown; ///< When should I shut my door.
diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h
index 3741eea95fc..17eeb97588e 100644
--- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h
+++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h
@@ -112,6 +112,7 @@ class TunnelContain : public OpenContain, public CreateModuleInterface
// contain list access
virtual void iterateContained( ContainIterateFunc func, void *userData, Bool reverse );
virtual UnsignedInt getContainCount() const;
+ virtual UnsignedInt getHeroUnitsContained() const;
virtual Int getContainMax( void ) const;
virtual const ContainedItemsList* getContainedItemsList() const;
virtual UnsignedInt getFullTimeForHeal(void) const; ///< Returns the time in frames until a contained object becomes fully healed
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp
index 661caa280af..09c9258d8c7 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/CommandLine.cpp
@@ -780,7 +780,6 @@ Int parseNoShaders(char *args[], int)
return 1;
}
-#if defined(RTS_DEBUG)
Int parseNoLogo(char *args[], int)
{
TheWritableGlobalData->m_playIntro = FALSE;
@@ -789,14 +788,6 @@ Int parseNoLogo(char *args[], int)
return 1;
}
-#endif
-
-Int parseNoSizzle( char *args[], int )
-{
- TheWritableGlobalData->m_playSizzle = FALSE;
-
- return 1;
-}
Int parseShellMap(char *args[], int num)
{
@@ -823,13 +814,7 @@ Int parseWinCursors(char *args[], int num)
Int parseQuickStart( char *args[], int num )
{
-#if defined(RTS_DEBUG)
- parseNoLogo( args, num );
-#else
- //Kris: Patch 1.01 -- Allow release builds to skip the sizzle video, but still force the EA logo to show up.
- //This is for legal reasons.
- parseNoSizzle( args, num );
-#endif
+ parseNoLogo( args, num );
parseNoShellMap( args, num );
parseNoWindowAnimation( args, num );
return 1;
@@ -1168,7 +1153,9 @@ static CommandLineParam paramsForStartup[] =
// These Params are parsed during Engine Init before INI data is loaded
static CommandLineParam paramsForEngineInit[] =
{
+ { "-nologo", parseNoLogo }, // TheSuperHackers @tweak Is now available in Release builds.
{ "-noshellmap", parseNoShellMap },
+ { "-noShellAnim", parseNoWindowAnimation }, // TheSuperHackers @tweak Is now available in Release builds.
{ "-xres", parseXRes },
{ "-yres", parseYRes },
{ "-fullVersion", parseFullVersion },
@@ -1294,9 +1281,7 @@ static CommandLineParam paramsForEngineInit[] =
{ "-noshadowvolumes", parseNoShadows },
{ "-nofx", parseNoFX },
{ "-ignoresync", parseSync },
- { "-nologo", parseNoLogo },
{ "-shellmap", parseShellMap },
- { "-noShellAnim", parseNoWindowAnimation },
{ "-winCursors", parseWinCursors },
{ "-constantDebug", parseConstantDebug },
{ "-seed", parseSeed },
@@ -1307,7 +1292,6 @@ static CommandLineParam paramsForEngineInit[] =
{ "-updateImages", parseUpdateImages },
{ "-showTeamDot", parseShowTeamDot },
{ "-extraLogging", parseExtraLogging },
-
#endif
#ifdef DEBUG_LOGGING
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
index d15235b9a73..fccf1aaccd1 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
@@ -64,7 +64,7 @@
#include "Common/SpecialPower.h"
#include "Common/TerrainTypes.h"
#include "Common/Upgrade.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/Xfer.h"
#include "Common/XferCRC.h"
#include "Common/GameLOD.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GameLOD.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GameLOD.cpp
index 371926ead13..a6bd251b2c0 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/GameLOD.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/GameLOD.cpp
@@ -36,7 +36,7 @@
#include "Common/GameLOD.h"
#include "GameClient/TerrainVisual.h"
#include "GameClient/GameClient.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#define DEFINE_PARTICLE_SYSTEM_NAMES
#include "GameClient/ParticleSys.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp b/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
index e598eb617e0..8f35ce38912 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp
@@ -47,7 +47,7 @@
#include "Common/GameAudio.h"
#include "Common/INI.h"
#include "Common/Registry.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
#include "GameLogic/AI.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp b/GeneralsMD/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp
index ed7840d7bd5..94f9b93a75b 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/INI/INIMultiplayer.cpp
@@ -43,7 +43,7 @@ void INI::parseMultiplayerSettingsDefinition( INI* ini )
//
if( ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES )
{
- DEBUG_ASSERTCRASH(false, ("Creating an override of MultiplayerSettings!"));
+ DEBUG_CRASH(("Creating an override of MultiplayerSettings!"));
}
}
else
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/ActionManager.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/ActionManager.cpp
index a216d810cc3..bc95bb067f2 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/ActionManager.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/ActionManager.cpp
@@ -504,7 +504,7 @@ Bool ActionManager::canResumeConstructionOf( const Object *obj,
// in the future)
//
Object *builder = TheGameLogic->findObjectByID( objectBeingConstructed->getBuilderID() );
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
if( builder )
#else
// TheSuperHackers @bugfix Stubbjax 18/11/2025 Allow scaffold to be immediately resumed after builder death.
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp
index c17c8042416..789a5a16344 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp
@@ -2567,7 +2567,12 @@ void Player::doBountyForKill(const Object* killer, const Object* victim)
return;
Int costToBuild = victim->getTemplate()->calcCostToBuild(victim->getControllingPlayer());
+#if RETAIL_COMPATIBLE_CRC
Int bounty = REAL_TO_INT_CEIL(costToBuild * m_cashBountyPercent);
+#else
+ // TheSuperHackers @bugfix Stubbjax 20/02/2026 Subtract epsilon to ensure bounty is rounded up correctly.
+ Int bounty = ceil((costToBuild * m_cashBountyPercent) - WWMATH_EPSILON);
+#endif
if( bounty )
{
@@ -4106,7 +4111,7 @@ void Player::removeKindOfProductionCostChange( KindOfMaskType kindOf, Real perce
}
++it;
}
- DEBUG_ASSERTCRASH(FALSE, ("removeKindOfProductionCostChange was called with kindOf=%d and percent=%f. We could not find the entry in the list with these variables. CLH.",kindOf, percent));
+ DEBUG_CRASH(("removeKindOfProductionCostChange was called with kindOf=%d and percent=%f. We could not find the entry in the list with these variables. CLH.",kindOf, percent));
}
//-------------------------------------------------------------------------------------------------
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp
index 888551dd259..47b210d6f61 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp
@@ -52,6 +52,7 @@ TunnelTracker::TunnelTracker()
{
m_tunnelCount = 0;
m_containListSize = 0;
+ m_heroUnitsContained = 0;
m_curNemesisID = INVALID_ID;
m_nemesisTimestamp = 0;
m_framesForFullHeal = 0;
@@ -187,6 +188,11 @@ void TunnelTracker::addToContainList( Object *obj )
{
m_containList.push_back(obj);
++m_containListSize;
+
+ if (obj->isKindOf(KINDOF_HERO))
+ {
+ ++m_heroUnitsContained;
+ }
}
// ------------------------------------------------------------------------
@@ -199,6 +205,12 @@ void TunnelTracker::removeFromContain( Object *obj, Bool exposeStealthUnits )
// note that this invalidates the iterator!
m_containList.erase(it);
--m_containListSize;
+
+ if (obj->isKindOf(KINDOF_HERO))
+ {
+ DEBUG_ASSERTCRASH(m_heroUnitsContained > 0, ("TunnelTracker::removeFromContain - Removing hero but hero count is %d", m_heroUnitsContained));
+ --m_heroUnitsContained;
+ }
}
}
@@ -433,6 +445,8 @@ void TunnelTracker::loadPostProcess( void )
}
// translate each object ids on the xferContainList into real object pointers in the contain list
+ m_containListSize = 0;
+ m_heroUnitsContained = 0;
Object *obj;
std::list< ObjectID >::const_iterator it;
for( it = m_xferContainList.begin(); it != m_xferContainList.end(); ++it )
@@ -448,7 +462,7 @@ void TunnelTracker::loadPostProcess( void )
}
// push on the back of the contain list
- m_containList.push_back( obj );
+ addToContainList( obj );
// Crap. This is in OpenContain as a fix, but not here.
{
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp
index 74cf54750cd..0f85ac2a4ff 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/Recorder.cpp
@@ -45,7 +45,7 @@
#include "GameLogic/GameLogic.h"
#include "Common/RandomValue.h"
#include "Common/CRCDebug.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
constexpr const char s_genrep[] = "GENREP";
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp
index da17e45fd25..f31e71a2c95 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp
@@ -656,7 +656,7 @@ void BuildAssistant::iterateFootprint( const ThingTemplate *build,
else
{
- DEBUG_ASSERTCRASH( 0, ("iterateFootprint: Undefined geometry '%d' for '%s'",
+ DEBUG_CRASH( ("iterateFootprint: Undefined geometry '%d' for '%s'",
build->getTemplateGeometryInfo().getGeomType(), build->getName().str()) );
return;
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingTemplate.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingTemplate.cpp
index f70ecd0d730..6388e807070 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingTemplate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/ThingTemplate.cpp
@@ -239,6 +239,11 @@ const FieldParse ThingTemplate::s_objectFieldParseTable[] =
{ "RemoveModule", ThingTemplate::parseRemoveModule, nullptr, 0 },
{ "ReplaceModule", ThingTemplate::parseReplaceModule, nullptr, 0 },
{ "InheritableModule", ThingTemplate::parseInheritableModule, nullptr, 0 },
+ { "OcclusionDelay", INI::parseDurationUnsignedInt, nullptr, offsetof( ThingTemplate, m_occlusionDelay ) },
+ { "AddModule", ThingTemplate::parseAddModule, nullptr, 0 },
+ { "RemoveModule", ThingTemplate::parseRemoveModule, nullptr, 0 },
+ { "ReplaceModule", ThingTemplate::parseReplaceModule, nullptr, 0 },
+ { "InheritableModule", ThingTemplate::parseInheritableModule, nullptr, 0 },
{ "OverrideableByLikeKind", ThingTemplate::OverrideableByLikeKind, nullptr, 0 },
@@ -575,7 +580,7 @@ void ThingTemplate::parseModuleName(INI* ini, void *instance, void* store, const
{
// if (self->getName().compare("GLAVehicleQuadCannon"))
-// DEBUG_ASSERTCRASH( FALSE, ("WE ARE CLEARING DEFAULT MODULES FROM A QUAD CANNON.") );
+// DEBUG_CRASH( ("WE ARE CLEARING DEFAULT MODULES FROM A QUAD CANNON.") );
self->m_behaviorModuleInfo.clearCopiedFromDefaultEntries(interfaceMask, tokenStr, self );
self->m_drawModuleInfo.clearCopiedFromDefaultEntries(interfaceMask, tokenStr, self );
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/ClientInstance.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/ClientInstance.cpp
deleted file mode 100644
index 7b06108866a..00000000000
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/ClientInstance.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 TheSuperHackers
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-#include "PreRTS.h"
-#include "GameClient/ClientInstance.h"
-
-#define GENERALS_GUID "685EAFF2-3216-4265-B047-251C5F4B82F3"
-
-namespace rts
-{
-HANDLE ClientInstance::s_mutexHandle = nullptr;
-UnsignedInt ClientInstance::s_instanceIndex = 0;
-
-#if defined(RTS_MULTI_INSTANCE)
-Bool ClientInstance::s_isMultiInstance = true;
-#else
-Bool ClientInstance::s_isMultiInstance = false;
-#endif
-
-bool ClientInstance::initialize()
-{
- if (isInitialized())
- {
- return true;
- }
-
- // Create a mutex with a unique name to Generals in order to determine if our app is already running.
- // WARNING: DO NOT use this number for any other application except Generals.
- while (true)
- {
- if (isMultiInstance())
- {
- std::string guidStr = getFirstInstanceName();
- if (s_instanceIndex > 0u)
- {
- char idStr[33];
- itoa(s_instanceIndex, idStr, 10);
- guidStr.push_back('-');
- guidStr.append(idStr);
- }
- s_mutexHandle = CreateMutex(nullptr, FALSE, guidStr.c_str());
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- {
- if (s_mutexHandle != nullptr)
- {
- CloseHandle(s_mutexHandle);
- s_mutexHandle = nullptr;
- }
- // Try again with a new instance.
- ++s_instanceIndex;
- continue;
- }
- }
- else
- {
- s_mutexHandle = CreateMutex(nullptr, FALSE, getFirstInstanceName());
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- {
- if (s_mutexHandle != nullptr)
- {
- CloseHandle(s_mutexHandle);
- s_mutexHandle = nullptr;
- }
- return false;
- }
- }
- break;
- }
-
- return true;
-}
-
-bool ClientInstance::isInitialized()
-{
- return s_mutexHandle != nullptr;
-}
-
-bool ClientInstance::isMultiInstance()
-{
- return s_isMultiInstance;
-}
-
-void ClientInstance::setMultiInstance(bool v)
-{
- if (isInitialized())
- {
- DEBUG_CRASH(("ClientInstance::setMultiInstance(%d) - cannot set multi instance after initialization", (int)v));
- return;
- }
- s_isMultiInstance = v;
-}
-
-void ClientInstance::skipPrimaryInstance()
-{
- if (isInitialized())
- {
- DEBUG_CRASH(("ClientInstance::skipPrimaryInstance() - cannot skip primary instance after initialization"));
- return;
- }
- s_instanceIndex = 1;
-}
-
-UnsignedInt ClientInstance::getInstanceIndex()
-{
- DEBUG_ASSERTLOG(isInitialized(), ("ClientInstance::isInitialized() failed"));
- return s_instanceIndex;
-}
-
-UnsignedInt ClientInstance::getInstanceId()
-{
- return getInstanceIndex() + 1;
-}
-
-const char* ClientInstance::getFirstInstanceName()
-{
- return GENERALS_GUID;
-}
-
-} // namespace rts
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp
index 3a3021f18c2..4152649ddc3 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBar.cpp
@@ -2415,7 +2415,7 @@ void ControlBar::switchToContext( ControlBarContext context, Drawable *draw )
default:
{
- DEBUG_ASSERTCRASH( 0, ("ControlBar::switchToContext, unknown context '%d'", context) );
+ DEBUG_CRASH( ("ControlBar::switchToContext, unknown context '%d'", context) );
break;
}
@@ -2476,7 +2476,7 @@ void ControlBar::setControlCommand( GameWindow *button, const CommandButton *com
if( button->winGetInputFunc() != GadgetPushButtonInput )
{
- DEBUG_ASSERTCRASH( 0, ("setControlCommand: Window is not a button") );
+ DEBUG_CRASH( ("setControlCommand: Window is not a button") );
return;
}
@@ -2485,7 +2485,7 @@ void ControlBar::setControlCommand( GameWindow *button, const CommandButton *com
if( commandButton == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("setControlCommand: null commandButton passed in") );
+ DEBUG_CRASH( ("setControlCommand: null commandButton passed in") );
return;
}
@@ -2587,7 +2587,7 @@ void ControlBar::setControlCommand( const AsciiString& buttonWindowName, GameWin
if( win == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("setControlCommand: Unable to find window '%s'", buttonWindowName.str()) );
+ DEBUG_CRASH( ("setControlCommand: Unable to find window '%s'", buttonWindowName.str()) );
return;
}
@@ -3069,7 +3069,7 @@ void ControlBar::switchControlBarStage( ControlBarStages stage )
setHiddenControlBar();
break;
default:
- DEBUG_ASSERTCRASH(FALSE,("ControlBar::switchControlBarStage we were passed in a stage that's not supported %d", stage));
+ DEBUG_CRASH(("ControlBar::switchControlBarStage we were passed in a stage that's not supported %d", stage));
}
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp
index bd43b6eb64c..fa8650e9289 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommand.cpp
@@ -94,7 +94,7 @@ void ControlBar::populateInvDataCallback( Object *obj, void *userData )
if( data->currIndex > data->maxIndex )
{
- DEBUG_ASSERTCRASH( 0, ("There is not enough GUI slots to hold the # of items inside a '%s'",
+ DEBUG_CRASH( ("There is not enough GUI slots to hold the # of items inside a '%s'",
data->transport->getTemplate()->getName().str()) );
return;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
index 1f404271984..487c922a938 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarCommandProcessing.cpp
@@ -425,7 +425,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
}
else if (cmt != CANMAKE_OK)
{
- DEBUG_ASSERTCRASH( 0, ("Cannot create '%s' because the factory object '%s' returns false for canMakeUnit",
+ DEBUG_CRASH( ("Cannot create '%s' because the factory object '%s' returns false for canMakeUnit",
whatToBuild->getName().str(),
factory->getTemplate()->getName().str()) );
break;
@@ -438,7 +438,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
if( pu == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("Cannot create '%s' because the factory object '%s' is not capable of producing units",
+ DEBUG_CRASH( ("Cannot create '%s' because the factory object '%s' is not capable of producing units",
whatToBuild->getName().str(),
factory->getTemplate()->getName().str()) );
break;
@@ -472,7 +472,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
if( i == MAX_BUILD_QUEUE_BUTTONS )
{
- DEBUG_ASSERTCRASH( 0, ("Control not found in build queue data") );
+ DEBUG_CRASH( ("Control not found in build queue data") );
break;
}
@@ -596,7 +596,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
if( i == MAX_BUILD_QUEUE_BUTTONS )
{
- DEBUG_ASSERTCRASH( 0, ("Control not found in build queue data") );
+ DEBUG_CRASH( ("Control not found in build queue data") );
break;
}
@@ -901,7 +901,7 @@ CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
//---------------------------------------------------------------------------------------------
default:
- DEBUG_ASSERTCRASH( 0, ("Unknown command '%d'", commandButton->getCommandType()) );
+ DEBUG_CRASH( ("Unknown command '%d'", commandButton->getCommandType()) );
return CBC_COMMAND_NOT_USED;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp
index d3ef6a5c231..d3593738155 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarResizer.cpp
@@ -117,7 +117,7 @@ ResizerWindow *ControlBarResizer::findResizerWindow( AsciiString name )
ResizerWindow *rWin = *it;
if( !rWin )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::findResizerWindow"));
+ DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::findResizerWindow"));
it++;
continue;
}
@@ -160,7 +160,7 @@ void ControlBarResizer::sizeWindowsDefault( void )
ResizerWindow *rWin = *it;
if( !rWin )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
+ DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
it++;
continue;
}
@@ -187,7 +187,7 @@ void ControlBarResizer::sizeWindowsAlt( void )
ResizerWindow *rWin = *it;
if( !rWin )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
+ DEBUG_CRASH(("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
it++;
continue;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp
index beaab2afbb4..cfbb25f78a8 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/ControlBar/ControlBarScheme.cpp
@@ -671,7 +671,7 @@ void ControlBarScheme::addAnimation( ControlBarSchemeAnimation *schemeAnim )
{
if( !schemeAnim )
{
- DEBUG_ASSERTCRASH(FALSE,("Trying to add a null animation to the controlbarscheme"));
+ DEBUG_CRASH(("Trying to add a null animation to the controlbarscheme"));
return;
}
m_animations.push_back( schemeAnim );
@@ -684,13 +684,13 @@ void ControlBarScheme::addImage( ControlBarSchemeImage *schemeImage )
{
if( !schemeImage )
{
- DEBUG_ASSERTCRASH(FALSE,("Trying to add a null image to the controlbarscheme"));
+ DEBUG_CRASH(("Trying to add a null image to the controlbarscheme"));
return;
}
if(schemeImage->m_layer < 0 || schemeImage->m_layer >= MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS)
{
- DEBUG_ASSERTCRASH(FALSE,("SchemeImage %s attempted to be added to layer %d which is not Between to %d, %d",
+ DEBUG_CRASH(("SchemeImage %s attempted to be added to layer %d which is not Between to %d, %d",
schemeImage->m_name.str(), schemeImage->m_layer, 0, MAX_CONTROL_BAR_SCHEME_IMAGE_LAYERS));
// bring the foobar to the front so we make it obvious that something's wrong
schemeImage->m_layer = 0;
@@ -713,7 +713,7 @@ void ControlBarScheme::updateAnim (ControlBarSchemeAnimation * anim)
}
default:
{
- DEBUG_ASSERTCRASH(FALSE,("We tried to animate but not animate function was found %d", anim->m_animType));
+ DEBUG_CRASH(("We tried to animate but not animate function was found %d", anim->m_animType));
}
}
}
@@ -730,7 +730,7 @@ void ControlBarScheme::update( void )
ControlBarSchemeAnimation *anim = *it;
if( !anim )
{
- DEBUG_ASSERTCRASH(FALSE,("THere's no Animation in the ControlBarSchemeAnimationList:m_animations"));
+ DEBUG_CRASH(("THere's no Animation in the ControlBarSchemeAnimationList:m_animations"));
return;
}
updateAnim( anim );
@@ -752,7 +752,7 @@ void ControlBarScheme::drawForeground( Coord2D multi, ICoord2D offset )
ControlBarSchemeImage *schemeImage = *it;
if( !schemeImage )
{
- DEBUG_ASSERTCRASH(FALSE,("There is no ControlBarSchemeImage found in the m_layer list"));
+ DEBUG_CRASH(("There is no ControlBarSchemeImage found in the m_layer list"));
it++;
continue;
}
@@ -789,7 +789,7 @@ void ControlBarScheme::drawBackground( Coord2D multi, ICoord2D offset )
ControlBarSchemeImage *schemeImage = *it;
if( !schemeImage )
{
- DEBUG_ASSERTCRASH(FALSE,("There is no ControlBarSchemeImage found in the m_layer list"));
+ DEBUG_CRASH(("There is no ControlBarSchemeImage found in the m_layer list"));
it++;
continue;
}
@@ -912,7 +912,7 @@ ControlBarScheme *ControlBarSchemeManager::newControlBarScheme( AsciiString name
ControlBarScheme *cbScheme = findControlBarScheme(name);
if(cbScheme)
{
- DEBUG_ASSERTCRASH(false,("We're overwriting a previous control bar scheme %s",name.str()));
+ DEBUG_CRASH(("We're overwriting a previous control bar scheme %s",name.str()));
cbScheme->reset();
cbScheme->m_name.set( name );
cbScheme->m_name.toLower();
@@ -923,7 +923,7 @@ ControlBarScheme *ControlBarSchemeManager::newControlBarScheme( AsciiString name
if( !cbScheme || name.isEmpty() )
{
- DEBUG_ASSERTCRASH(FALSE,("Could not create controlbar %s", name.str()));
+ DEBUG_CRASH(("Could not create controlbar %s", name.str()));
return nullptr;
}
@@ -950,7 +950,7 @@ ControlBarScheme *ControlBarSchemeManager::findControlBarScheme( AsciiString nam
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
return nullptr;
}
if(CBScheme->m_name.compareNoCase( name ) == 0)
@@ -970,7 +970,7 @@ void ControlBarSchemeManager::preloadAssets( TimeOfDay timeOfDay )
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
continue;
}
@@ -1024,7 +1024,7 @@ void ControlBarSchemeManager::init( void )
// }
if( m_schemeList.empty() )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList that was just read from the INI file"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList that was just read from the INI file"));
return;
}
@@ -1046,7 +1046,7 @@ void ControlBarSchemeManager::setControlBarScheme(AsciiString schemeName)
}
else
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
m_currentScheme = nullptr;
}
if(m_currentScheme)
@@ -1105,7 +1105,7 @@ void ControlBarSchemeManager::setControlBarSchemeByPlayerTemplate( const PlayerT
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
it++;
continue;
}
@@ -1173,7 +1173,7 @@ void ControlBarSchemeManager::setControlBarSchemeByPlayer(Player *p)
ControlBarScheme *CBScheme = *it;
if( !CBScheme )
{
- DEBUG_ASSERTCRASH(FALSE,("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
+ DEBUG_CRASH(("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"));
it++;
continue;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
index 5f1768e7268..ba149ea390a 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp
@@ -612,7 +612,7 @@ void ControlBar::populateBuildTooltipLayout( const CommandButton *commandButton,
}
else
{
- DEBUG_ASSERTCRASH(FALSE, ("ControlBar::populateBuildTooltipLayout We attempted to call the popup tooltip on a game window that has yet to be hand coded in as this fuction was/is designed for only buttons but has been hacked to work with GameWindows."));
+ DEBUG_CRASH(("ControlBar::populateBuildTooltipLayout We attempted to call the popup tooltip on a game window that has yet to be hand coded in as this fuction was/is designed for only buttons but has been hacked to work with GameWindows."));
return;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp
index 3a623cfa1d8..1d8c22b71e1 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/ExtendedMessageBox.cpp
@@ -123,7 +123,7 @@ static GameWindow *gogoExMessageBox(Int x, Int y, Int width, Int height, Unsigne
//we shouldn't have button OK and Yes on the same dialog
if((buttonFlags & (MSG_BOX_OK | MSG_BOX_YES)) == (MSG_BOX_OK | MSG_BOX_YES) )
{
- DEBUG_ASSERTCRASH(false, ("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
+ DEBUG_CRASH(("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
}
//Position the OK button if we have one
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp
index b2c3d41dd19..47f048373ed 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/DifficultySelect.cpp
@@ -51,7 +51,7 @@
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/WindowLayout.h"
#include "GameClient/Gadget.h"
#include "GameClient/Shell.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp
index 23e7aa351d0..58faebaf87d 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/LanLobbyMenu.cpp
@@ -40,7 +40,7 @@
#include "Common/Player.h"
#include "Common/PlayerTemplate.h"
#include "Common/QuotedPrintable.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/ClientInstance.h"
#include "GameClient/GameText.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp
index 600dabd2c69..31f532b8182 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MainMenu.cpp
@@ -38,7 +38,7 @@
#include "Common/GlobalData.h"
#include "Common/NameKeyGenerator.h"
#include "Common/RandomValue.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/version.h"
#include "Common/GameLOD.h"
#include "GameClient/AnimateWindowManager.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp
index 067f60a824b..25d8690576d 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/MapSelectMenu.cpp
@@ -33,7 +33,7 @@
#include "Common/GameEngine.h"
#include "Common/MessageStream.h"
#include "Common/RandomValue.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameLogic/GameLogic.h"
#include "GameLogic/ScriptEngine.h"
#include "GameClient/AnimateWindowManager.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp
index f8d6b3856e4..7c9c462f9b9 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/NetworkDirectConnect.cpp
@@ -34,7 +34,7 @@
#include "gamespy/peer/peer.h"
#include "Common/QuotedPrintable.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/WindowLayout.h"
#include "GameClient/Gadget.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
index ea926bd987d..4dd6af1e1a5 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp
@@ -36,7 +36,7 @@
#include "Common/AudioSettings.h"
#include "Common/GameAudio.h"
#include "Common/GameEngine.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "Common/GameLOD.h"
#include "Common/Recorder.h"
#include "Common/Registry.h"
@@ -215,800 +215,6 @@ extern void DoResolutionDialog();
static Bool ignoreSelected = FALSE;
WindowLayout *OptionsLayout = nullptr;
-
-OptionPreferences::OptionPreferences( void )
-{
- loadFromIniFile();
-}
-
-OptionPreferences::~OptionPreferences()
-{
-}
-
-Bool OptionPreferences::loadFromIniFile()
-{
- if (rts::ClientInstance::getInstanceId() > 1u)
- {
- AsciiString fname;
- fname.format("Options_Instance%.2u.ini", rts::ClientInstance::getInstanceId());
- return load(fname);
- }
-
- return load("Options.ini");
-}
-
-Int OptionPreferences::getCampaignDifficulty(void)
-{
- OptionPreferences::const_iterator it = find("CampaignDifficulty");
- if (it == end())
- return TheScriptEngine->getGlobalDifficulty();
-
- Int factor = atoi(it->second.str());
- if (factor < DIFFICULTY_EASY)
- factor = DIFFICULTY_EASY;
- if (factor > DIFFICULTY_HARD)
- factor = DIFFICULTY_HARD;
-
- return factor;
-}
-
-void OptionPreferences::setCampaignDifficulty( Int diff )
-{
- AsciiString prefString;
- prefString.format("%d", diff );
- (*this)["CampaignDifficulty"] = prefString;
-}
-
-UnsignedInt OptionPreferences::getLANIPAddress(void)
-{
- AsciiString selectedIP = (*this)["IPAddress"];
- IPEnumeration IPs;
- EnumeratedIP *IPlist = IPs.getAddresses();
- while (IPlist)
- {
- if (selectedIP.compareNoCase(IPlist->getIPstring()) == 0)
- {
- return IPlist->getIP();
- }
- IPlist = IPlist->getNext();
- }
- return TheGlobalData->m_defaultIP;
-}
-
-void OptionPreferences::setLANIPAddress( AsciiString IP )
-{
- (*this)["IPAddress"] = IP;
-}
-
-void OptionPreferences::setLANIPAddress( UnsignedInt IP )
-{
- AsciiString tmp;
- tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP));
- (*this)["IPAddress"] = tmp;
-}
-
-UnsignedInt OptionPreferences::getOnlineIPAddress(void)
-{
- AsciiString selectedIP = (*this)["GameSpyIPAddress"];
- IPEnumeration IPs;
- EnumeratedIP *IPlist = IPs.getAddresses();
- while (IPlist)
- {
- if (selectedIP.compareNoCase(IPlist->getIPstring()) == 0)
- {
- return IPlist->getIP();
- }
- IPlist = IPlist->getNext();
- }
- return TheGlobalData->m_defaultIP;
-}
-
-void OptionPreferences::setOnlineIPAddress( AsciiString IP )
-{
- (*this)["GameSpyIPAddress"] = IP;
-}
-
-void OptionPreferences::setOnlineIPAddress( UnsignedInt IP )
-{
- AsciiString tmp;
- tmp.format("%d.%d.%d.%d", PRINTF_IP_AS_4_INTS(IP));
- (*this)["GameSpyIPAddress"] = tmp;
-}
-
-Bool OptionPreferences::getArchiveReplaysEnabled() const
-{
- OptionPreferences::const_iterator it = find("ArchiveReplays");
- if (it == end())
- return FALSE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getAlternateMouseModeEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseAlternateMouse");
- if (it == end())
- return TheGlobalData->m_useAlternateMouse;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getRetaliationModeEnabled(void)
-{
- OptionPreferences::const_iterator it = find("Retaliation");
- if (it == end())
- return TheGlobalData->m_clientRetaliationModeEnabled;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getDoubleClickAttackMoveEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseDoubleClickAttackMove");
- if( it == end() )
- return TheGlobalData->m_doubleClickAttackMove;
-
- if( stricmp( it->second.str(), "yes" ) == 0 )
- return TRUE;
-
- return FALSE;
-}
-
-Real OptionPreferences::getScrollFactor(void)
-{
- OptionPreferences::const_iterator it = find("ScrollFactor");
- if (it == end())
- return TheGlobalData->m_keyboardDefaultScrollFactor;
-
- Int factor = atoi(it->second.str());
-
- // TheSuperHackers @tweak xezon 11/07/2025
- // No longer caps the upper limit to 100, because the options setting can go beyond that.
- // No longer caps the lower limit to 0, because that would mean standstill.
- if (factor < 1)
- factor = 1;
-
- return factor/100.0f;
-}
-
-Bool OptionPreferences::getDrawScrollAnchor(void)
-{
- OptionPreferences::const_iterator it = find("DrawScrollAnchor");
- // TheSuperHackers @info this default is based on the same variable within InGameUi.ini
- if (it == end())
- return FALSE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getMoveScrollAnchor(void)
-{
- OptionPreferences::const_iterator it = find("MoveScrollAnchor");
- // TheSuperHackers @info this default is based on the same variable within InGameUi.ini
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInWindowedGame() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInWindowedGame");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInWindowedGame) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInWindowedMenu() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInWindowedMenu");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInWindowedMenu) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInFullscreenGame() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInFullscreenGame");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInFullscreenGame) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getCursorCaptureEnabledInFullscreenMenu() const
-{
- OptionPreferences::const_iterator it = find("CursorCaptureEnabledInFullscreenMenu");
- if (it == end())
- return (CursorCaptureMode_Default & CursorCaptureMode_EnabledInFullscreenMenu) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-CursorCaptureMode OptionPreferences::getCursorCaptureMode() const
-{
- CursorCaptureMode mode = 0;
- mode |= getCursorCaptureEnabledInWindowedGame() ? CursorCaptureMode_EnabledInWindowedGame : 0;
- mode |= getCursorCaptureEnabledInWindowedMenu() ? CursorCaptureMode_EnabledInWindowedMenu : 0;
- mode |= getCursorCaptureEnabledInFullscreenGame() ? CursorCaptureMode_EnabledInFullscreenGame : 0;
- mode |= getCursorCaptureEnabledInFullscreenMenu() ? CursorCaptureMode_EnabledInFullscreenMenu : 0;
- return mode;
-}
-
-Bool OptionPreferences::getScreenEdgeScrollEnabledInWindowedApp() const
-{
- OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInWindowedApp");
- if (it == end())
- return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Bool OptionPreferences::getScreenEdgeScrollEnabledInFullscreenApp() const
-{
- OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInFullscreenApp");
- if (it == end())
- return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp) != 0;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-ScreenEdgeScrollMode OptionPreferences::getScreenEdgeScrollMode() const
-{
- ScreenEdgeScrollMode mode = 0;
- mode |= getScreenEdgeScrollEnabledInWindowedApp() ? ScreenEdgeScrollMode_EnabledInWindowedApp : 0;
- mode |= getScreenEdgeScrollEnabledInFullscreenApp() ? ScreenEdgeScrollMode_EnabledInFullscreenApp : 0;
- return mode;
-}
-
-Bool OptionPreferences::usesSystemMapDir(void)
-{
- OptionPreferences::const_iterator it = find("UseSystemMapDir");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::saveCameraInReplays(void)
-{
- OptionPreferences::const_iterator it = find("SaveCameraInReplays");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::useCameraInReplays(void)
-{
- OptionPreferences::const_iterator it = find("UseCameraInReplays");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getPlayerObserverEnabled() const
-{
- OptionPreferences::const_iterator it = find("PlayerObserverEnabled");
- if (it == end())
- return TRUE;
-
- if (stricmp(it->second.str(), "yes") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-Int OptionPreferences::getIdealStaticGameDetail(void)
-{
- OptionPreferences::const_iterator it = find("IdealStaticGameLOD");
- if (it == end())
- return STATIC_GAME_LOD_UNKNOWN;
-
- return TheGameLODManager->getStaticGameLODIndex(it->second);
-}
-
-Int OptionPreferences::getStaticGameDetail(void)
-{
- OptionPreferences::const_iterator it = find("StaticGameLOD");
- if (it == end())
- return TheGameLODManager->getStaticLODLevel();
-
- return TheGameLODManager->getStaticGameLODIndex(it->second);
-}
-
-Bool OptionPreferences::getSendDelay(void)
-{
- OptionPreferences::const_iterator it = find("SendDelay");
- if (it == end())
- return TheGlobalData->m_firewallSendDelay;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Int OptionPreferences::getFirewallBehavior()
-{
- OptionPreferences::const_iterator it = find("FirewallBehavior");
- if (it == end())
- return TheGlobalData->m_firewallBehavior;
-
- Int behavior = atoi(it->second.str());
- if (behavior < 0)
- {
- behavior = 0;
- }
- return behavior;
-}
-
-Short OptionPreferences::getFirewallPortAllocationDelta()
-{
- OptionPreferences::const_iterator it = find("FirewallPortAllocationDelta");
- if (it == end()) {
- return TheGlobalData->m_firewallPortAllocationDelta;
- }
-
- Short delta = atoi(it->second.str());
- return delta;
-}
-
-UnsignedShort OptionPreferences::getFirewallPortOverride()
-{
- OptionPreferences::const_iterator it = find("FirewallPortOverride");
- if (it == end()) {
- return TheGlobalData->m_firewallPortOverride;
- }
-
- Int override = atoi(it->second.str());
- if (override < 0 || override > 65535)
- override = 0;
- return override;
-}
-
-Bool OptionPreferences::getFirewallNeedToRefresh()
-{
- OptionPreferences::const_iterator it = find("FirewallNeedToRefresh");
- if (it == end()) {
- return FALSE;
- }
-
- Bool retval = FALSE;
- AsciiString str = it->second;
- if (str.compareNoCase("TRUE") == 0) {
- retval = TRUE;
- }
- return retval;
-}
-
-AsciiString OptionPreferences::getPreferred3DProvider(void)
-{
- OptionPreferences::const_iterator it = find("3DAudioProvider");
- if (it == end())
- return TheAudio->getAudioSettings()->m_preferred3DProvider[MAX_HW_PROVIDERS];
- return it->second;
-}
-
-AsciiString OptionPreferences::getSpeakerType(void)
-{
- OptionPreferences::const_iterator it = find("SpeakerType");
- if (it == end())
- return TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getAudioSettings()->m_defaultSpeakerType2D);
- return it->second;
-}
-
-Real OptionPreferences::getSoundVolume(void)
-{
- OptionPreferences::const_iterator it = find("SFXVolume");
- if (it == end())
- {
- Real relative = TheAudio->getAudioSettings()->m_relative2DVolume;
- if( relative < 0 )
- {
- Real scale = 1.0f + relative;
- return TheAudio->getAudioSettings()->m_defaultSoundVolume * 100.0f * scale;
- }
- return TheAudio->getAudioSettings()->m_defaultSoundVolume * 100.0f;
- }
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Real OptionPreferences::get3DSoundVolume(void)
-{
- OptionPreferences::const_iterator it = find("SFX3DVolume");
- if (it == end())
- {
- Real relative = TheAudio->getAudioSettings()->m_relative2DVolume;
- if( relative > 0 )
- {
- Real scale = 1.0f - relative;
- return TheAudio->getAudioSettings()->m_default3DSoundVolume * 100.0f * scale;
- }
- return TheAudio->getAudioSettings()->m_default3DSoundVolume * 100.0f;
- }
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Real OptionPreferences::getSpeechVolume(void)
-{
- OptionPreferences::const_iterator it = find("VoiceVolume");
- if (it == end())
- return TheAudio->getAudioSettings()->m_defaultSpeechVolume * 100.0f;
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Bool OptionPreferences::getCloudShadowsEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseCloudMap");
- if (it == end())
- return TheGlobalData->m_useCloudMap;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getLightmapEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseLightMap");
- if (it == end())
- return TheGlobalData->m_useLightMap;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getSmoothWaterEnabled(void)
-{
- OptionPreferences::const_iterator it = find("ShowSoftWaterEdge");
- if (it == end())
- return TheGlobalData->m_showSoftWaterEdge;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getTreesEnabled(void)
-{
- OptionPreferences::const_iterator it = find("ShowTrees");
- if (it == end())
- return TheGlobalData->m_useTrees;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getExtraAnimationsDisabled(void)
-{
- OptionPreferences::const_iterator it = find("ExtraAnimations");
- if (it == end())
- return TheGlobalData->m_useDrawModuleLOD;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return FALSE; //we are enabling extra animations, so disabled LOD
- }
- return TRUE;
-}
-
-Bool OptionPreferences::getUseHeatEffects(void)
-{
- OptionPreferences::const_iterator it = find("HeatEffects");
- if (it == end())
- return TheGlobalData->m_useHeatEffects;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getDynamicLODEnabled(void)
-{
- OptionPreferences::const_iterator it = find("DynamicLOD");
- if (it == end())
- return TheGlobalData->m_enableDynamicLOD;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getFPSLimitEnabled(void)
-{
- OptionPreferences::const_iterator it = find("FPSLimit");
- if (it == end())
- return TheGlobalData->m_useFpsLimit;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::get3DShadowsEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseShadowVolumes");
- if (it == end())
- return TheGlobalData->m_useShadowVolumes;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::get2DShadowsEnabled(void)
-{
- OptionPreferences::const_iterator it = find("UseShadowDecals");
- if (it == end())
- return TheGlobalData->m_useShadowDecals;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Bool OptionPreferences::getBuildingOcclusionEnabled(void)
-{
- OptionPreferences::const_iterator it = find("BuildingOcclusion");
- if (it == end())
- return TheGlobalData->m_enableBehindBuildingMarkers;
-
- if (stricmp(it->second.str(), "yes") == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-Int OptionPreferences::getParticleCap(void)
-{
- OptionPreferences::const_iterator it = find("MaxParticleCount");
- if (it == end())
- return TheGlobalData->m_maxParticleCount;
-
- Int factor = (Int) atoi(it->second.str());
- if (factor < 100) //clamp to at least 100 particles.
- factor = 100;
-
- return factor;
-}
-
-Int OptionPreferences::getTextureReduction(void)
-{
- OptionPreferences::const_iterator it = find("TextureReduction");
- if (it == end())
- return -1; //unknown texture reduction
-
- Int factor = (Int) atoi(it->second.str());
- if (factor > 2) //clamp it.
- factor=2;
- return factor;
-}
-
-Real OptionPreferences::getGammaValue(void)
-{
- OptionPreferences::const_iterator it = find("Gamma");
- if (it == end())
- return 50.0f;
-
- Real gamma = (Real) atoi(it->second.str());
- return gamma;
-}
-
-void OptionPreferences::getResolution(Int *xres, Int *yres)
-{
- *xres = TheGlobalData->m_xResolution;
- *yres = TheGlobalData->m_yResolution;
-
- OptionPreferences::const_iterator it = find("Resolution");
- if (it == end())
- return;
-
- Int selectedXRes,selectedYRes;
- if (sscanf(it->second.str(),"%d%d", &selectedXRes, &selectedYRes) != 2)
- return;
-
- *xres=selectedXRes;
- *yres=selectedYRes;
-}
-
-Real OptionPreferences::getMusicVolume(void)
-{
- OptionPreferences::const_iterator it = find("MusicVolume");
- if (it == end())
- return TheAudio->getAudioSettings()->m_defaultMusicVolume * 100.0f;
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- {
- volume = 0.0f;
- }
- return volume;
-}
-
-Real OptionPreferences::getMoneyTransactionVolume(void) const
-{
- OptionPreferences::const_iterator it = find("MoneyTransactionVolume");
- if (it == end())
- return TheAudio->getAudioSettings()->m_defaultMoneyTransactionVolume * 100.0f;
-
- Real volume = (Real) atof(it->second.str());
- if (volume < 0.0f)
- volume = 0.0f;
-
- return volume;
-}
-
-Int OptionPreferences::getNetworkLatencyFontSize(void)
-{
- OptionPreferences::const_iterator it = find("NetworkLatencyFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getRenderFpsFontSize(void)
-{
- OptionPreferences::const_iterator it = find("RenderFpsFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getSystemTimeFontSize(void)
-{
- OptionPreferences::const_iterator it = find("SystemTimeFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getGameTimeFontSize(void)
-{
- OptionPreferences::const_iterator it = find("GameTimeFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Int OptionPreferences::getPlayerInfoListFontSize(void)
-{
- OptionPreferences::const_iterator it = find("PlayerInfoListFontSize");
- if (it == end())
- return 8;
-
- Int fontSize = atoi(it->second.str());
- if (fontSize < 0)
- {
- fontSize = 0;
- }
- return fontSize;
-}
-
-Real OptionPreferences::getResolutionFontAdjustment(void)
-{
- OptionPreferences::const_iterator it = find("ResolutionFontAdjustment");
- if (it == end())
- return -1.0f;
-
- Real fontScale = (Real)atof(it->second.str()) / 100.0f;
- if (fontScale < 0.0f)
- {
- fontScale = -1.0f;
- }
- return fontScale;
-}
-
-Bool OptionPreferences::getShowMoneyPerMinute(void) const
-{
- OptionPreferences::const_iterator it = find("ShowMoneyPerMinute");
- if (it == end())
- return TheGlobalData->m_showMoneyPerMinute;
-
- if (stricmp(it->second.str(), "yes") == 0)
- {
- return TRUE;
- }
- return FALSE;
-}
-
static OptionPreferences *pref = nullptr;
static void setDefaults( void )
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp
index 58e2183df2a..19a69d5221d 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/QuitMenu.cpp
@@ -200,6 +200,11 @@ static void restartMissionMenu()
Int gameMode = TheGameLogic->getGameMode();
AsciiString mapName = TheGlobalData->m_mapName;
+ // TheSuperHackers @bugfix Caball009 07/02/2026 Reuse the previous seed value for the new skirmish match to prevent mismatches.
+ // Campaign, challenge, and skirmish single-player scenarios all use GAME_SINGLE_PLAYER and are expected to use 0 as seed value.
+ DEBUG_ASSERTCRASH((TheSkirmishGameInfo != nullptr) == (gameMode == GAME_SKIRMISH), ("Unexpected game mode on map / mission restart"));
+ const Int seed = TheSkirmishGameInfo ? TheSkirmishGameInfo->getSeed() : 0;
+
//
// if the map name was from a save game it will have "Save/" at the front of it,
// we want to go back to the original pristine map string for the map name when restarting
@@ -238,11 +243,8 @@ static void restartMissionMenu()
TheScriptEngine->getGlobalDifficulty(),
rankPointsStartedWith)
);
- //if (TheGlobalData->m_fixedSeed >= 0)
- //InitRandom(TheGlobalData->m_fixedSeed);
- InitRandom(0);
- //else
- // InitGameLogicRandom(GameClientRandomValue(0, INT_MAX - 1));
+
+ InitRandom(seed);
}
//TheTransitionHandler->remove("QuitFull"); //KRISMORNESS ADD
//quitMenuLayout = nullptr; //KRISMORNESS ADD
@@ -371,7 +373,7 @@ void ToggleQuitMenu()
// load the quit menu from the layout file if needed
if( quitMenuLayout == nullptr )
{
- DEBUG_ASSERTCRASH(FALSE, ("Could not load a quit menu layout"));
+ DEBUG_CRASH(("Could not load a quit menu layout"));
isVisible = FALSE;
TheInGameUI->setQuitMenuVisible(FALSE);
return;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp
index 5e06baddf45..a6923d75c8f 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/ScoreScreen.cpp
@@ -1423,7 +1423,7 @@ void populatePlayerInfo( Player *player, Int pos)
ScoreKeeper *scoreKpr = player->getScoreKeeper();
if(!scoreKpr)
{
- DEBUG_ASSERTCRASH(FALSE,("Player %s does not have a scoreKeeper", player->getPlayerDisplayName().str()));
+ DEBUG_CRASH(("Player %s does not have a scoreKeeper", player->getPlayerDisplayName().str()));
return;
}
AsciiString winName;
@@ -1858,36 +1858,7 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
if (TheNetwork->sawCRCMismatch())
{
++stats.desyncs[ptIdx];
- }
- else if (gameEndedInDisconnect)
- {
- ++stats.discons[ptIdx];
- }
- else if (TheVictoryConditions->isLocalAlliedDefeat() || !TheVictoryConditions->getEndFrame())
- {
- ++stats.losses[ptIdx];
- }
- else
- {
- ++stats.wins[ptIdx];
- }
-
- ScoreKeeper *s = player->getScoreKeeper();
- stats.buildingsBuilt[ptIdx] += s->getTotalBuildingsBuilt();
- stats.buildingsKilled[ptIdx] += s->getTotalBuildingsDestroyed();
- stats.buildingsLost[ptIdx] += s->getTotalBuildingsLost();
-
- if (TheGameSpyGame->isQMGame())
- {
- stats.QMGames[ptIdx]++;
- }
- else
- {
- stats.customGames[ptIdx]++;
- }
- if (TheNetwork->sawCRCMismatch())
- {
stats.lossesInARow = 0;
stats.desyncsInARow++;
stats.disconsInARow = 0;
@@ -1896,6 +1867,8 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
}
else if (gameEndedInDisconnect)
{
+ ++stats.discons[ptIdx];
+
stats.lossesInARow = 0;
stats.desyncsInARow = 0;
stats.disconsInARow++;
@@ -1904,6 +1877,8 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
}
else if (TheVictoryConditions->isLocalAlliedVictory())
{
+ ++stats.wins[ptIdx];
+
stats.lossesInARow = 0;
stats.desyncsInARow = 0;
stats.disconsInARow = 0;
@@ -1912,6 +1887,8 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
}
else
{
+ ++stats.losses[ptIdx];
+
stats.lossesInARow++;
stats.desyncsInARow = 0;
stats.disconsInARow = 0;
@@ -1919,6 +1896,20 @@ winName.format("ScoreScreen.wnd:StaticTextScore%d", pos);
stats.maxLossesInARow = max(stats.lossesInARow, stats.maxLossesInARow);
}
+ ScoreKeeper *s = player->getScoreKeeper();
+ stats.buildingsBuilt[ptIdx] += s->getTotalBuildingsBuilt();
+ stats.buildingsKilled[ptIdx] += s->getTotalBuildingsDestroyed();
+ stats.buildingsLost[ptIdx] += s->getTotalBuildingsLost();
+
+ if (TheGameSpyGame->isQMGame())
+ {
+ stats.QMGames[ptIdx]++;
+ }
+ else
+ {
+ stats.customGames[ptIdx]++;
+ }
+
stats.earnings[ptIdx] += s->getTotalMoneyEarned();
stats.duration[ptIdx] += TheGameLogic->getFrame() / LOGICFRAMES_PER_SECOND / 60; // in minutes
stats.games[ptIdx]++;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp
index cbfee81c6ce..1f58fc91bbe 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/SkirmishGameOptionsMenu.cpp
@@ -264,7 +264,7 @@ Int SkirmishPreferences::getPreferredFaction(void)
Bool SkirmishPreferences::usesSystemMapDir(void)
{
- OptionPreferences::const_iterator it = find("UseSystemMapDir");
+ SkirmishPreferences::const_iterator it = find("UseSystemMapDir");
if (it == end())
return TRUE;
@@ -431,7 +431,6 @@ void reallyDoStart( void )
TheWritableGlobalData->m_mapName = TheSkirmishGameInfo->getMap();
TheSkirmishGameInfo->startGame(0);
- InitGameLogicRandom(TheSkirmishGameInfo->getSeed());
Bool isSkirmish = TRUE;
const MapMetaData *md = TheMapCache->findMap(TheSkirmishGameInfo->getMap());
@@ -442,6 +441,8 @@ void reallyDoStart( void )
if (isSkirmish)
{
+ InitGameLogicRandom(TheSkirmishGameInfo->getSeed());
+
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
msg->appendIntegerArgument(GAME_SKIRMISH);
msg->appendIntegerArgument(DIFFICULTY_NORMAL); // not really used; just specified so we can add the game speed last
@@ -450,6 +451,8 @@ void reallyDoStart( void )
}
else
{
+ InitGameLogicRandom(0);
+
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
msg->appendIntegerArgument(GAME_SINGLE_PLAYER);
msg->appendIntegerArgument(DIFFICULTY_NORMAL); // not really used; just specified so we can add the game speed last
@@ -747,7 +750,7 @@ void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPosition
}
else
{
- DEBUG_ASSERTCRASH(FALSE,("positionStartSpots:: someone messed with the map cash. We couldn't find waypoint <%s> in map <%s>", waypointName.str(),lowerMap.str()));
+ DEBUG_CRASH(("positionStartSpots:: someone messed with the map cash. We couldn't find waypoint <%s> in map <%s>", waypointName.str(),lowerMap.str()));
}
}
// hide the rest
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp
index 88e4f9a0071..d2d31ef13d4 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp
@@ -188,7 +188,7 @@ void InitBuddyControls(Int type)
case BUDDY_WINDOW_WELCOME_SCREEN:
break;
default:
- DEBUG_ASSERTCRASH(FALSE, ("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either"));
+ DEBUG_CRASH(("Well, you really shouldn't have gotten here, if you really care about GUI Bugs, search for this string, you you don't care, call chris (who probably doesn't care either"));
}
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp
index b95da7fa6f6..73753997a1d 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLGameSetupMenu.cpp
@@ -32,8 +32,9 @@
#include "Common/GameEngine.h"
#include "Common/GameState.h"
-#include "GameClient/GameText.h"
#include "Common/MultiplayerSettings.h"
+#include "Common/OptionPreferences.h"
+#include "GameClient/GameText.h"
#include "Common/PlayerTemplate.h"
#include "Common/CustomMatchPreferences.h"
#include "GameClient/AnimateWindowManager.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp
index 994e1dcf461..eb77b5b9911 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLoginMenu.cpp
@@ -39,7 +39,7 @@
#include "Common/GameSpyMiscPreferences.h"
#include "Common/QuotedPrintable.h"
#include "Common/Registry.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/ClientInstance.h"
#include "GameClient/WindowLayout.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp
index b4cf7680526..7e19b5679fc 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp
@@ -35,6 +35,7 @@
#include "Common/QuickmatchPreferences.h"
#include "Common/LadderPreferences.h"
#include "Common/MultiplayerSettings.h"
+#include "Common/OptionPreferences.h"
#include "Common/PlayerTemplate.h"
#include "GameClient/AnimateWindowManager.h"
#include "GameClient/WindowLayout.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp
index 627ff843de6..be4a4cc1932 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetComboBox.cpp
@@ -395,7 +395,7 @@ WindowMsgHandledType GadgetComboBoxSystem( GameWindow *window, UnsignedInt msg,
GadgetListBoxGetSelected(comboData->listBox, (Int *)mData2);
else
{
- DEBUG_ASSERTCRASH(0,("We don't have a listbox as part of the combo box"));
+ DEBUG_CRASH(("We don't have a listbox as part of the combo box"));
*(Int *)mData2 = -1;
}
break;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp
index e9c4be80025..8688129b035 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Gadget/GadgetListBox.cpp
@@ -344,7 +344,7 @@ static Int addImageEntry( const Image *image, Color color, Int row, Int column,
if( column >= list->columns || row >= list->listLength )
{
- DEBUG_ASSERTCRASH(false, ("Tried to add Image to Listbox at invalid position"));
+ DEBUG_CRASH(("Tried to add Image to Listbox at invalid position"));
return -1;
}
@@ -447,7 +447,7 @@ static Int addEntry( UnicodeString *string, Int color, Int row, Int column, Game
// make sure our params are good
if( column >= list->columns || row >= list->listLength )
{
- DEBUG_ASSERTCRASH(false, ("Tried to add text to Listbox at invalid position"));
+ DEBUG_CRASH(("Tried to add text to Listbox at invalid position"));
return -1;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
index 50441562cc0..357f54d0c06 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
@@ -1704,7 +1704,7 @@ GameWindow *GameWindowManager::gogoMessageBox(Int x, Int y, Int width, Int heigh
//we shouldn't have button OK and Yes on the same dialog
if((buttonFlags & (MSG_BOX_OK | MSG_BOX_YES)) == (MSG_BOX_OK | MSG_BOX_YES) )
{
- DEBUG_ASSERTCRASH(false, ("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
+ DEBUG_CRASH(("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
}
//Position the OK button if we have one
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
index 9e8ea622eb2..f7083553219 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp
@@ -113,7 +113,7 @@ void FlashTransition::update( Int frame )
m_drawState = -1;
if(frame < FLASHTRANSITION_START || frame > FLASHTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("FlashTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("FlashTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -269,7 +269,7 @@ void ButtonFlashTransition::update( Int frame )
m_drawState = -1;
if(frame < BUTTONFLASHTRANSITION_START || frame > BUTTONFLASHTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ButtonFlashTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ButtonFlashTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -642,7 +642,7 @@ void FadeTransition::update( Int frame )
m_drawState = -1;
if(frame < FADETRANSITION_START || frame > FADETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("FadeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("FadeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -785,7 +785,7 @@ void ScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < SCALEUPTRANSITION_START || frame > SCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -908,7 +908,7 @@ void ScoreScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < SCORESCALEUPTRANSITION_START || frame > SCORESCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ScoreScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ScoreScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1039,7 +1039,7 @@ void MainMenuScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < MAINMENUSCALEUPTRANSITION_START || frame > MAINMENUSCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("MainMenuScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("MainMenuScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1158,7 +1158,7 @@ void MainMenuMediumScaleUpTransition::update( Int frame )
m_drawState = -1;
if(frame < MAINMENUMEDIUMSCALEUPTRANSITION_START || frame > MAINMENUMEDIUMSCALEUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("MainMenuMediumScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("MainMenuMediumScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1277,7 +1277,7 @@ void MainMenuSmallScaleDownTransition::update( Int frame )
m_drawState = -1;
if(frame < MAINMENUSMALLSCALEDOWNTRANSITION_START || frame > MAINMENUSMALLSCALEDOWNTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("MainMenuSmallScaleDownTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("MainMenuSmallScaleDownTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1382,7 +1382,7 @@ void TextTypeTransition::update( Int frame )
m_drawState = -1;
if(frame < TEXTTYPETRANSITION_START || frame > TEXTTYPETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("TextTypeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("TextTypeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1521,7 +1521,7 @@ void CountUpTransition::update( Int frame )
m_drawState = -1;
if(frame < COUNTUPTRANSITION_START || frame > COUNTUPTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("CountUpTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("CountUpTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1638,7 +1638,7 @@ void ScreenFadeTransition::update( Int frame )
m_drawState = -1;
if(frame < SCREENFADETRANSITION_START || frame > SCREENFADETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ScreenFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ScreenFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1731,7 +1731,7 @@ void ControlBarArrowTransition::update( Int frame )
m_drawState = -1;
if(frame < CONTROLBARARROWTRANSITION_START || frame > CONTROLBARARROWTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ControlBarArrowTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ControlBarArrowTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1826,7 +1826,7 @@ void FullFadeTransition::update( Int frame )
m_drawState = -1;
if(frame < FULLFADETRANSITION_START || frame > FULLFADETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("FullFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("FullFadeTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -1927,7 +1927,7 @@ void TextOnFrameTransition::update( Int frame )
{
if(frame < TEXTONFRAMETRANSITION_START || frame > TEXTONFRAMETRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("TextOnFrameTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("TextOnFrameTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
@@ -2001,7 +2001,7 @@ void ReverseSoundTransition::update( Int frame )
{
if(frame < REVERSESOUNDTRANSITION_START || frame > REVERSESOUNDTRANSITION_END)
{
- DEBUG_ASSERTCRASH(FALSE, ("ReverseSoundTransition::update - Frame is out of the range the this update can handle %d", frame));
+ DEBUG_CRASH(("ReverseSoundTransition::update - Frame is out of the range the this update can handle %d", frame));
return;
}
switch (frame) {
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp
index 1aee4fbe475..263f4b451b1 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp
@@ -3262,7 +3262,7 @@ void InGameUI::setGUICommand( const CommandButton *command )
if( BitIsSet( command->getOptions(), COMMAND_OPTION_NEED_TARGET ) == FALSE )
{
- DEBUG_ASSERTCRASH( 0, ("setGUICommand: Command '%s' does not need additional user interaction",
+ DEBUG_CRASH( ("setGUICommand: Command '%s' does not need additional user interaction",
command->getName().str()) );
m_pendingGUICommand = nullptr;
m_mouseMode = MOUSEMODE_DEFAULT;
@@ -5939,7 +5939,7 @@ void InGameUI::selectNextIdleWorker( void )
if(m_idleWorkers[index].empty())
{
- DEBUG_ASSERTCRASH(FALSE, ("InGameUI::selectNextIdleWorker We're trying to select a worker when our list is empty for player %ls", player->getPlayerDisplayName().str()));
+ DEBUG_CRASH(("InGameUI::selectNextIdleWorker We're trying to select a worker when our list is empty for player %ls", player->getPlayerDisplayName().str()));
return;
}
Object *selectThisObject = nullptr;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
index e9036a6c9f0..6765f8121cb 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
@@ -1147,7 +1147,7 @@ GameMessage::Type CommandTranslator::issueAttackCommand( Drawable *target,
msgType = GameMessage::MSG_DO_ATTACK_OBJECT;
break;
default:
- DEBUG_ASSERTCRASH( 0, ("issueAttackCommand was passed in a GUICommandType type that isn't supported yet...") );
+ DEBUG_CRASH( ("issueAttackCommand was passed in a GUICommandType type that isn't supported yet...") );
return msgType;
}
@@ -3178,7 +3178,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
//-----------------------------------------------------------------------------------------
case GameMessage::MSG_META_DEPLOY:
#ifdef RTS_DEBUG
- DEBUG_ASSERTCRASH(FALSE, ("unimplemented meta command MSG_META_DEPLOY !"));
+ DEBUG_CRASH(("unimplemented meta command MSG_META_DEPLOY !"));
#endif
/// @todo srj implement me
disp = DESTROY_MESSAGE;
@@ -3187,7 +3187,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
//-----------------------------------------------------------------------------------------
case GameMessage::MSG_META_FOLLOW:
#ifdef RTS_DEBUG
- DEBUG_ASSERTCRASH(FALSE, ("unimplemented meta command MSG_META_FOLLOW !"));
+ DEBUG_CRASH(("unimplemented meta command MSG_META_FOLLOW !"));
#endif
/// @todo srj implement me
disp = DESTROY_MESSAGE;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp
index b97895d35ac..d37d7f51dec 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/GUICommandTranslator.cpp
@@ -191,7 +191,7 @@ static CommandStatus doFireWeaponCommand( const CommandButton *command, const IC
//This could be legit now -- think of firing a self destruct weapon
//-----------------------------------------------------------------
- //DEBUG_ASSERTCRASH( 0, ("doFireWeaponCommand: Command options say it doesn't need additional user input '%s'",
+ //DEBUG_CRASH( ("doFireWeaponCommand: Command options say it doesn't need additional user input '%s'",
// command->m_name.str()) );
//return COMMAND_COMPLETE;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
index 651512e4436..78f09e3564e 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/HotKey.cpp
@@ -148,7 +148,7 @@ void HotKeyManager::addHotKey( GameWindow *win, const AsciiString& keyIn)
HotKeyMap::iterator it = m_hotKeyMap.find(key);
if( it != m_hotKeyMap.end() )
{
- DEBUG_ASSERTCRASH(FALSE,("Hotkey %s is already mapped to window %s, current window is %s", key.str(), it->second.m_win->winGetInstanceData()->m_decoratedNameString.str(), win->winGetInstanceData()->m_decoratedNameString.str()));
+ DEBUG_CRASH(("Hotkey %s is already mapped to window %s, current window is %s", key.str(), it->second.m_win->winGetInstanceData()->m_decoratedNameString.str(), win->winGetInstanceData()->m_decoratedNameString.str()));
return;
}
HotKey newHK;
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp
index c35c4199eac..913bc49f6ed 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp
@@ -36,7 +36,7 @@
#include "Common/PlayerList.h"
#include "Common/Recorder.h"
#include "Common/StatsCollector.h"
-#include "Common/UserPreferences.h"
+#include "Common/OptionPreferences.h"
#include "GameLogic/Object.h"
#include "GameLogic/PartitionManager.h"
#include "GameClient/Display.h"
diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp
index f9b2863a2c3..60a97b85fad 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameClient/System/CampaignManager.cpp
@@ -178,7 +178,7 @@ Mission *Campaign::getMission( AsciiString missionName )
return mission;
++it;
}
- DEBUG_ASSERTCRASH(FALSE, ("getMission couldn't find %s", missionName.str()));
+ DEBUG_CRASH(("getMission couldn't find %s", missionName.str()));
return nullptr;
}
@@ -206,7 +206,7 @@ Mission *Campaign::getNextMission( Mission *current)
return mission;
++it;
}
-// DEBUG_ASSERTCRASH(FALSE, ("GetNextMission couldn't find %s", current->m_nextMission.str()));
+// DEBUG_CRASH(("GetNextMission couldn't find %s", current->m_nextMission.str()));
return nullptr;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
index f6fcd7b3303..0a5b6248227 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
@@ -1134,8 +1134,8 @@ void Pathfinder::forceCleanCells()
TheAudio->addAudioEvent(&TheAudio->getMiscAudio()->m_allCheerSound);
PathfindCellInfo::forceCleanPathFindCellInfos();
- m_openList = nullptr;
- m_closedList = nullptr;
+ m_openList.reset();
+ m_closedList.reset();
for (int j = 0; j <= m_extent.hi.y; ++j) {
for (int i = 0; i <= m_extent.hi.x; ++i) {
@@ -1684,70 +1684,67 @@ Bool PathfindCell::removeObstacle( Object *obstacle )
}
/// put self on "open" list in ascending cost order, return new list
-PathfindCell *PathfindCell::putOnSortedOpenList( PathfindCell *list )
+void PathfindCell::putOnSortedOpenList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==FALSE && m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
- if (list == nullptr)
+
+ // mark the newCell as being on the open list
+ m_info->m_open = true;
+ m_info->m_closed = false;
+
+ if (list.m_head == nullptr)
{
- list = this;
+ list.m_head = this;
m_info->m_prevOpen = nullptr;
m_info->m_nextOpen = nullptr;
+ return;
}
- else
- {
+
// insertion sort
- PathfindCell *c, *lastCell = nullptr;
+ PathfindCell* currentCell = list.m_head;
+ PathfindCell* previousCell = nullptr;
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @bugfix In the retail compatible pathfinding, on rare occasions, we get stuck in an infinite loop
// External code should pickup on the bad behaviour and cleanup properly, but we need to explicitly break out here
// The fixed pathfinding does not have this issue due to the proper cleanup of pathfindCells and their pathfindCellInfos
UnsignedInt cellCount = 0;
- for (c = list; c && cellCount < PATHFIND_CELLS_PER_FRAME; c = c->getNextOpen())
+ while (currentCell && cellCount < PATHFIND_CELLS_PER_FRAME && currentCell->m_info->m_totalCost <= m_info->m_totalCost)
{
cellCount++;
#else
- for (c = list; c; c = c->getNextOpen())
+ while (currentCell && currentCell->m_info->m_totalCost <= m_info->m_totalCost)
{
#endif
- if (c->m_info->m_totalCost > m_info->m_totalCost)
- break;
-
- lastCell = c;
+ previousCell = currentCell;
+ currentCell = currentCell->getNextOpen();
}
- if (c)
+ if (currentCell)
{
- // insert just before "c"
- if (c->m_info->m_prevOpen)
- c->m_info->m_prevOpen->m_nextOpen = this->m_info;
+ // insert just before "currentCell"
+ if (currentCell->m_info->m_prevOpen)
+ currentCell->m_info->m_prevOpen->m_nextOpen = this->m_info;
else
- list = this;
+ list.m_head = this;
- m_info->m_prevOpen = c->m_info->m_prevOpen;
- c->m_info->m_prevOpen = this->m_info;
+ m_info->m_prevOpen = currentCell->m_info->m_prevOpen;
+ currentCell->m_info->m_prevOpen = this->m_info;
- m_info->m_nextOpen = c->m_info;
+ m_info->m_nextOpen = currentCell->m_info;
}
else
{
- // append after "lastCell" - end of list
- lastCell->m_info->m_nextOpen = this->m_info;
- m_info->m_prevOpen = lastCell->m_info;
+ // append after "previousCell" - we are at the end of the list
+ previousCell->m_info->m_nextOpen = this->m_info;
+ m_info->m_prevOpen = previousCell->m_info;
m_info->m_nextOpen = nullptr;
}
}
- // mark newCell as being on open list
- m_info->m_open = true;
- m_info->m_closed = false;
-
- return list;
-}
-
/// remove self from "open" list
-PathfindCell *PathfindCell::removeFromOpenList( PathfindCell *list )
+void PathfindCell::removeFromOpenList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==FALSE && m_info->m_open==TRUE, ("Serious error - Invalid flags. jba"));
@@ -1757,25 +1754,24 @@ PathfindCell *PathfindCell::removeFromOpenList( PathfindCell *list )
if (m_info->m_prevOpen)
m_info->m_prevOpen->m_nextOpen = m_info->m_nextOpen;
else
- list = getNextOpen();
+ list.m_head = getNextOpen();
m_info->m_open = false;
m_info->m_nextOpen = nullptr;
m_info->m_prevOpen = nullptr;
- return list;
}
/// remove all cells from "open" list
-Int PathfindCell::releaseOpenList( PathfindCell *list )
+Int PathfindCell::releaseOpenList( PathfindCellList &list )
{
Int count = 0;
- while (list) {
+ while (list.m_head) {
count++;
- DEBUG_ASSERTCRASH(list->m_info, ("Has to have info."));
- DEBUG_ASSERTCRASH(list->m_info->m_closed==FALSE && list->m_info->m_open==TRUE, ("Serious error - Invalid flags. jba"));
- PathfindCell *cur = list;
- PathfindCellInfo *curInfo = list->m_info;
+ DEBUG_ASSERTCRASH(list.m_head->m_info, ("Has to have info."));
+ DEBUG_ASSERTCRASH(list.m_head->m_info->m_closed==FALSE && list.m_head->m_info->m_open==TRUE, ("Serious error - Invalid flags. jba"));
+ PathfindCell *cur = list.m_head;
+ PathfindCellInfo *curInfo = list.m_head->m_info;
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info This is only here to catch a crash point in the retail compatible pathfinding
@@ -1789,9 +1785,9 @@ Int PathfindCell::releaseOpenList( PathfindCell *list )
#endif
if (curInfo->m_nextOpen) {
- list = curInfo->m_nextOpen->m_cell;
+ list.m_head = curInfo->m_nextOpen->m_cell;
} else {
- list = nullptr;
+ list.m_head = nullptr;
}
DEBUG_ASSERTCRASH(cur == curInfo->m_cell, ("Bad backpointer in PathfindCellInfo"));
curInfo->m_nextOpen = nullptr;
@@ -1803,15 +1799,15 @@ Int PathfindCell::releaseOpenList( PathfindCell *list )
}
/// remove all cells from "closed" list
-Int PathfindCell::releaseClosedList( PathfindCell *list )
+Int PathfindCell::releaseClosedList( PathfindCellList &list )
{
Int count = 0;
- while (list) {
+ while (list.m_head) {
count++;
- DEBUG_ASSERTCRASH(list->m_info, ("Has to have info."));
- DEBUG_ASSERTCRASH(list->m_info->m_closed==TRUE && list->m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
- PathfindCell *cur = list;
- PathfindCellInfo *curInfo = list->m_info;
+ DEBUG_ASSERTCRASH(list.m_head->m_info, ("Has to have info."));
+ DEBUG_ASSERTCRASH(list.m_head->m_info->m_closed==TRUE && list.m_head->m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
+ PathfindCell *cur = list.m_head;
+ PathfindCellInfo *curInfo = list.m_head->m_info;
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info This is only here to catch a crash point in the retail compatible pathfinding
// One crash mode is where a cell has no PathfindCellInfo, resulting in a nullptr access and a crash.
@@ -1824,9 +1820,9 @@ Int PathfindCell::releaseClosedList( PathfindCell *list )
#endif
if (curInfo->m_nextOpen) {
- list = curInfo->m_nextOpen->m_cell;
+ list.m_head = curInfo->m_nextOpen->m_cell;
} else {
- list = nullptr;
+ list.m_head = nullptr;
}
DEBUG_ASSERTCRASH(cur == curInfo->m_cell, ("Bad backpointer in PathfindCellInfo"));
curInfo->m_nextOpen = nullptr;
@@ -1838,7 +1834,7 @@ Int PathfindCell::releaseClosedList( PathfindCell *list )
}
/// put self on "closed" list, return new list
-PathfindCell *PathfindCell::putOnClosedList( PathfindCell *list )
+void PathfindCell::putOnClosedList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==FALSE && m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
@@ -1849,18 +1845,17 @@ PathfindCell *PathfindCell::putOnClosedList( PathfindCell *list )
m_info->m_closed = TRUE;
m_info->m_prevOpen = nullptr;
- m_info->m_nextOpen = list?list->m_info:nullptr;
- if (list)
- list->m_info->m_prevOpen = this->m_info;
+ m_info->m_nextOpen = list.m_head ? list.m_head->m_info : nullptr;
+ if (list.m_head)
+ list.m_head->m_info->m_prevOpen = this->m_info;
- list = this;
+ list.m_head = this;
}
- return list;
}
/// remove self from "closed" list
-PathfindCell *PathfindCell::removeFromClosedList( PathfindCell *list )
+void PathfindCell::removeFromClosedList( PathfindCellList &list )
{
DEBUG_ASSERTCRASH(m_info, ("Has to have info."));
DEBUG_ASSERTCRASH(m_info->m_closed==TRUE && m_info->m_open==FALSE, ("Serious error - Invalid flags. jba"));
@@ -1870,13 +1865,12 @@ PathfindCell *PathfindCell::removeFromClosedList( PathfindCell *list )
if (m_info->m_prevOpen)
m_info->m_prevOpen->m_nextOpen = m_info->m_nextOpen;
else
- list = getNextOpen();
+ list.m_head = getNextOpen();
m_info->m_closed = false;
m_info->m_nextOpen = nullptr;
m_info->m_prevOpen = nullptr;
- return list;
}
/**
@@ -3884,8 +3878,8 @@ void Pathfinder::reset( void )
// reset the pathfind grid
m_extent.lo.x=m_extent.lo.y=m_extent.hi.x=m_extent.hi.y=0;
m_logicalExtent.lo.x=m_logicalExtent.lo.y=m_logicalExtent.hi.x=m_logicalExtent.hi.y=0;
- m_openList = nullptr;
- m_closedList = nullptr;
+ m_openList.reset();
+ m_closedList.reset();
m_ignoreObstacleID = INVALID_ID;
m_isTunneling = false;
@@ -4721,7 +4715,7 @@ void Pathfinder::debugShowSearch( Bool pathFound )
addIcon(nullptr, 0, 0, color); // erase.
}
- for( s = m_openList; s; s=s->getNextOpen() )
+ for( s = m_openList.getHead(); s; s=s->getNextOpen() )
{
// create objects to show path - they decay
RGBColor color;
@@ -4735,7 +4729,7 @@ void Pathfinder::debugShowSearch( Bool pathFound )
addIcon(&pos, PATHFIND_CELL_SIZE_F*.6f, 200, color);
}
- for( s = m_closedList; s; s=s->getNextOpen() )
+ for( s = m_closedList.getHead(); s; s=s->getNextOpen() )
{
// create objects to show path - they decay
RGBColor color;
@@ -4831,9 +4825,9 @@ Bool Pathfinder::validMovementTerrain( PathfindLayerEnum layer, const Locomotor*
//
void Pathfinder::cleanOpenAndClosedLists(void) {
Int count = 0;
- if (m_openList) {
+ if (!m_openList.empty()) {
count += PathfindCell::releaseOpenList(m_openList);
- m_openList = nullptr;
+ m_openList.reset();
}
#if RETAIL_COMPATIBLE_PATHFINDING
@@ -4846,9 +4840,9 @@ void Pathfinder::cleanOpenAndClosedLists(void) {
}
#endif
- if (m_closedList) {
+ if (!m_closedList.empty()) {
count += PathfindCell::releaseClosedList(m_closedList);
- m_closedList = nullptr;
+ m_closedList.reset();
}
#if RETAIL_COMPATIBLE_PATHFINDING
@@ -5979,7 +5973,7 @@ void Pathfinder::checkChangeLayers(PathfindCell *parentCell)
newCell->setCostSoFar(parentCell->getCostSoFar()); // same as parent cost
newCell->setTotalCost(parentCell->getTotalCost());
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
bool Pathfinder::checkCellOutsideExtents(ICoord2D& cell) {
@@ -6078,14 +6072,14 @@ struct ExamineCellsStruct
// if to was on closed list, remove it from the list
if (to->getClosed())
- d->thePathfinder->m_closedList = to->removeFromClosedList( d->thePathfinder->m_closedList );
+ to->removeFromClosedList( d->thePathfinder->m_closedList );
// if the to was already on the open list, remove it so it can be re-inserted in order
if (to->getOpen())
- d->thePathfinder->m_openList = to->removeFromOpenList( d->thePathfinder->m_openList );
+ to->removeFromOpenList( d->thePathfinder->m_openList );
// insert to in open list such that open list is sorted, smallest total path cost first
- d->thePathfinder->m_openList = to->putOnSortedOpenList( d->thePathfinder->m_openList );
+ to->putOnSortedOpenList( d->thePathfinder->m_openList );
}
return 0; // keep going
@@ -6312,14 +6306,14 @@ Int Pathfinder::examineNeighboringCells(PathfindCell *parentCell, PathfindCell *
// if newCell was on closed list, remove it from the list
if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
+ newCell->removeFromClosedList( m_closedList );
// if the newCell was already on the open list, remove it so it can be re-inserted in order
if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
+ newCell->removeFromOpenList( m_openList );
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
return cellCount;
}
@@ -6385,7 +6379,7 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
DEBUG_LOG(("Attempting pathfind to 0,0, generally a bug."));
return nullptr;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
if (m_isMapReady == false) {
return nullptr;
}
@@ -6497,10 +6491,19 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
parentCell->startPathfind(goalCell);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
Int cellCount = 0;
@@ -6508,11 +6511,11 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
if (parentCell == goalCell)
{
@@ -6555,7 +6558,7 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
@@ -6917,7 +6920,7 @@ struct GroundCellsStruct
to->setTotalCost(to->getCostSoFar() + costRemaining) ;
// insert to in open list such that open list is sorted, smallest total path cost first
- d->thePathfinder->m_openList = to->putOnSortedOpenList( d->thePathfinder->m_openList );
+ to->putOnSortedOpenList( d->thePathfinder->m_openList );
}
return 0; // keep going
@@ -6953,7 +6956,7 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
DEBUG_LOG(("Attempting pathfind to 0,0, generally a bug."));
return nullptr;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
if (m_isMapReady == false) {
return nullptr;
}
@@ -7046,10 +7049,19 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
parentCell->startPathfind(goalCell);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
// TheSuperHackers @fix helmutbuhler This was originally uninitialized and in the loop below.
#if RETAIL_COMPATIBLE_CRC
@@ -7061,11 +7073,11 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
// until goal is found.
//
Int cellCount = 0;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
if (parentCell == goalCell)
{
@@ -7098,7 +7110,7 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
@@ -7233,14 +7245,14 @@ Path *Pathfinder::findGroundPath( const Coord3D *from,
// if newCell was on closed list, remove it from the list
if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
+ newCell->removeFromClosedList( m_closedList );
// if the newCell was already on the open list, remove it so it can be re-inserted in order
if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
+ newCell->removeFromOpenList( m_openList );
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
}
// failure - goal cannot be reached
@@ -7368,14 +7380,14 @@ void Pathfinder::processHierarchicalCell( const ICoord2D &scanCell, const ICoord
if (!s_useFixedPathfinding)
{
if (!newCell->getClosed() && !newCell->getOpen()) {
- m_closedList = newCell->putOnClosedList(m_closedList);
+ newCell->putOnClosedList(m_closedList);
}
}
else
#endif
{
if (newCell->hasInfo() && !newCell->getClosed() && !newCell->getOpen()) {
- m_closedList = newCell->putOnClosedList(m_closedList);
+ newCell->putOnClosedList(m_closedList);
}
}
@@ -7397,7 +7409,7 @@ void Pathfinder::processHierarchicalCell( const ICoord2D &scanCell, const ICoord
adjNewCell->setTotalCost(adjNewCell->getCostSoFar()+remCost);
adjNewCell->setParentCellHierarchical(parentCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = adjNewCell->putOnSortedOpenList( m_openList );
+ adjNewCell->putOnSortedOpenList( m_openList );
}
}
@@ -7443,7 +7455,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
DEBUG_LOG(("Attempting pathfind to 0,0, generally a bug."));
return nullptr;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
if (m_isMapReady == false) {
return nullptr;
}
@@ -7500,7 +7512,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
parentCell->startPathfind(goalCell);
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
Int cellCount = 0;
@@ -7519,7 +7531,16 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
}
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
if (parentCell->getLayer()!=LAYER_GROUND) {
PathfindLayerEnum layer = parentCell->getLayer();
@@ -7532,8 +7553,8 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
PathfindCell *startCell = getCell(LAYER_GROUND, ndx.x, ndx.y);
if (cell && startCell) {
// Close parent cell;
- m_openList = parentCell->removeFromOpenList(m_openList);
- m_closedList = parentCell->putOnClosedList(m_closedList);
+ parentCell->removeFromOpenList(m_openList);
+ parentCell->putOnClosedList(m_closedList);
if (!startCell->allocateInfo(ndx)) {
// TheSuperHackers @info We need to forcefully cleanup dangling pathfinding cells if this failure condition is hit in retail
// Retail clients will crash beyond this point, but we attempt to recover by performing a full cleanup then enabling the fixed pathfinding codepath
@@ -7558,7 +7579,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
startCell->setTotalCost(remCost);
startCell->setParentCellHierarchical(parentCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = startCell->putOnSortedOpenList( m_openList );
+ startCell->putOnSortedOpenList( m_openList );
cellCount++;
if(!cell->allocateInfo(toNdx)) {
@@ -7583,7 +7604,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
cell->setTotalCost(remCost);
cell->setParentCellHierarchical(parentCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = cell->putOnSortedOpenList( m_openList );
+ cell->putOnSortedOpenList( m_openList );
}
}
@@ -7594,11 +7615,11 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
zoneStorageType parentZone;
if (parentCell->getLayer()==LAYER_GROUND) {
@@ -7682,7 +7703,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
}
startCell->setParentCellHierarchical(parentCell);
if (!startCell->getClosed() && !startCell->getOpen()) {
- m_closedList = startCell->putOnClosedList(m_closedList);
+ startCell->putOnClosedList(m_closedList);
}
}
if(!cell->allocateInfo(toNdx)) {
@@ -7711,7 +7732,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
cell->setTotalCost(cell->getCostSoFar()+remCost);
cell->setParentCellHierarchical(startCell);
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = cell->putOnSortedOpenList( m_openList );
+ cell->putOnSortedOpenList( m_openList );
}
}
@@ -7780,7 +7801,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
Int i;
zoneStorageType examinedZones[PathfindZoneManager::ZONE_BLOCK_SIZE];
@@ -8201,250 +8222,250 @@ void Pathfinder::clip( Coord3D *from, Coord3D *to )
}
-Bool Pathfinder::pathDestination( Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest,
- PathfindLayerEnum layer, const Coord3D *groupDest)
-{
- //CRCDEBUG_LOG(("Pathfinder::pathDestination()"));
- if (m_isMapReady == false) return false;
-
- if (!obj) return false;
-
- Int cellCount = 0;
-
- Coord3D adjustTo = *groupDest;
- Coord3D *to = &adjustTo;
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
- // create unique "mark" values for open and closed cells for this pathfind invocation
-
- Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
-
- PathfindLayerEnum desiredLayer = TheTerrainLogic->getLayerForDestination(dest);
- // determine desired
- PathfindCell *desiredCell = getClippedCell( desiredLayer, dest );
- if (desiredCell == nullptr)
- return FALSE;
-
- PathfindLayerEnum goalLayer = TheTerrainLogic->getLayerForDestination(to);
- // determine goal cell
- PathfindCell *goalCell = getClippedCell( goalLayer, to );
- if (goalCell == nullptr)
- return FALSE;
-
-
- Bool isHuman = true;
- if (obj && obj->getControllingPlayer() && (obj->getControllingPlayer()->getPlayerType()==PLAYER_COMPUTER)) {
- isHuman = false; // computer gets to cheat.
- }
- Bool center;
- Int radius;
- getRadiusAndCenter(obj, radius, center);
-
- // determine start cell
- ICoord2D startCellNdx;
- worldToCell(dest, &startCellNdx);
- PathfindCell *parentCell = getCell( layer, startCellNdx.x, startCellNdx.y );
- if (parentCell == nullptr)
- return FALSE;
- ICoord2D pos2d;
- worldToCell(to, &pos2d);
- if (!goalCell->allocateInfo(pos2d)) {
- return FALSE;
- }
-
- if (parentCell!=goalCell) {
- if (!parentCell->allocateInfo(startCellNdx)) {
-#if RETAIL_COMPATIBLE_PATHFINDING
- if (!s_useFixedPathfinding) {
- desiredCell->releaseInfo();
- }
-#endif
- goalCell->releaseInfo();
- return FALSE;
- }
- }
-
- PathfindCell *closestCell = nullptr;
- Real closestDistanceSqr = FLT_MAX;
- Coord3D closestPos;
-
- if (validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), locomotorSet.getRequiredWaterLevel(), parentCell ) == false) {
- parentCell->releaseInfo();
- goalCell->releaseInfo();
- return FALSE;
- }
-
- parentCell->startPathfind(goalCell);
-
- // initialize "open" list to contain start cell
- m_openList = parentCell;
-
- // "closed" list is initially empty
- m_closedList = nullptr;
-
- //
- // Continue search until "open" list is empty, or
- // until goal is found.
- //
- while( m_openList != nullptr )
- {
- // take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
-
- Coord3D pos;
- // put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
- if (checkForAdjust(obj, locomotorSet, isHuman, parentCell->getXIndex(), parentCell->getYIndex(), parentCell->getLayer(),
- radius, center, &pos, groupDest)) {
- Int dx = IABS(goalCell->getXIndex()-parentCell->getXIndex());
- Int dy = IABS(goalCell->getYIndex()-parentCell->getYIndex());
- Real distSqr = dx*dx+dy*dy;
-
- if (distSqr < closestDistanceSqr) {
- closestCell = parentCell;
- closestDistanceSqr = distSqr;
- closestPos = pos;
- } else {
- continue;
- }
- } else {
- continue;
- }
-
- if (cellCount > MAX_CELL_COUNT) {
- continue;
- }
- // Check to see if we can change layers in this cell.
- checkChangeLayers(parentCell);
-
- // expand search to neighboring orthogonal cells
- static ICoord2D delta[] =
- {
- { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 },
- { 1, 1 }, { -1, 1 }, { -1, -1 }, { 1, -1 }
- };
- const Int numNeighbors = 8;
- const Int firstDiagonal = 4;
- ICoord2D newCellCoord;
- PathfindCell *newCell;
- const Int adjacent[5] = {0, 1, 2, 3, 0};
- Bool neighborFlags[8] = { 0 };
-
- UnsignedInt newCostSoFar = 0;
-
- for( int i=0; igetXIndex() + delta[i].x;
- newCellCoord.y = parentCell->getYIndex() + delta[i].y;
-
- // get the neighboring cell
- newCell = getCell(parentCell->getLayer(), newCellCoord.x, newCellCoord.y );
-
- // check if cell is on the map
- if (newCell == nullptr)
- continue;
-
- // check if this neighbor cell is already on the open (waiting to be tried)
- // or closed (already tried) lists
- Bool onList = false;
- if (newCell->hasInfo()) {
- if (newCell->getOpen() || newCell->getClosed())
- {
- // already on one of the lists
- onList = true;
- }
- }
- if (i>=firstDiagonal) {
- // make sure one of the adjacent sides is open.
- if (!neighborFlags[adjacent[i-4]] && !neighborFlags[adjacent[i-3]]) {
- continue;
- }
- }
-
- if (!validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), locomotorSet.getRequiredWaterLevel(), newCell, parentCell )) {
- continue;
- }
-
- neighborFlags[i] = true;
-
- if (!newCell->allocateInfo(newCellCoord)) {
- // Out of cells for pathing...
-#if RETAIL_COMPATIBLE_PATHFINDING
- if (s_useFixedPathfinding)
-#endif
- {
- cleanOpenAndClosedLists();
- goalCell->releaseInfo();
- }
- return cellCount;
- }
- cellCount++;
-
- newCostSoFar = newCell->costSoFar( parentCell );
- newCell->setBlockedByAlly(false);
-
- // check if this neighbor cell is already on the open (waiting to be tried)
- // or closed (already tried) lists
- if (onList)
- {
- // already on one of the lists - if existing costSoFar is less,
- // the new cell is on a longer path, so skip it
- if (newCell->getCostSoFar() <= newCostSoFar)
- continue;
- }
-
- // keep track of path we're building - point back to cell we moved here from
- newCell->setParentCell(parentCell) ;
-
- // store cost of this path
- newCell->setCostSoFar(newCostSoFar);
-
- Int costRemaining = 0;
- if (goalCell) {
- costRemaining = newCell->costToGoal( goalCell );
- }
-
- newCell->setTotalCost(newCell->getCostSoFar() + costRemaining) ;
-
- // if newCell was on closed list, remove it from the list
- if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
-
- // if the newCell was already on the open list, remove it so it can be re-inserted in order
- if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
-
- // insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
- }
- }
-
-#if defined(RTS_DEBUG)
- if (closestCell) {
- debugShowSearch(true);
- *dest = closestPos;
- } else {
- debugShowSearch(true);
- }
-#endif
- m_isTunneling = false;
-#if RETAIL_COMPATIBLE_PATHFINDING
- if (!s_useFixedPathfinding) {
- cleanOpenAndClosedLists();
- goalCell->releaseInfo();
- }
- else
-#endif
- {
- cleanOpenAndClosedLists();
- parentCell->releaseInfo();
- goalCell->releaseInfo();
- }
-
- return false;
-}
+//Bool Pathfinder::pathDestination( Object *obj, const LocomotorSet& locomotorSet, Coord3D *dest,
+// PathfindLayerEnum layer, const Coord3D *groupDest)
+//{
+// //CRCDEBUG_LOG(("Pathfinder::pathDestination()"));
+// if (m_isMapReady == false) return false;
+//
+// if (!obj) return false;
+//
+// Int cellCount = 0;
+//
+// Coord3D adjustTo = *groupDest;
+// Coord3D *to = &adjustTo;
+// DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+// // create unique "mark" values for open and closed cells for this pathfind invocation
+//
+// Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
+//
+// PathfindLayerEnum desiredLayer = TheTerrainLogic->getLayerForDestination(dest);
+// // determine desired
+// PathfindCell *desiredCell = getClippedCell( desiredLayer, dest );
+// if (desiredCell == nullptr)
+// return FALSE;
+//
+// PathfindLayerEnum goalLayer = TheTerrainLogic->getLayerForDestination(to);
+// // determine goal cell
+// PathfindCell *goalCell = getClippedCell( goalLayer, to );
+// if (goalCell == nullptr)
+// return FALSE;
+//
+//
+// Bool isHuman = true;
+// if (obj && obj->getControllingPlayer() && (obj->getControllingPlayer()->getPlayerType()==PLAYER_COMPUTER)) {
+// isHuman = false; // computer gets to cheat.
+// }
+// Bool center;
+// Int radius;
+// getRadiusAndCenter(obj, radius, center);
+//
+// // determine start cell
+// ICoord2D startCellNdx;
+// worldToCell(dest, &startCellNdx);
+// PathfindCell *parentCell = getCell( layer, startCellNdx.x, startCellNdx.y );
+// if (parentCell == nullptr)
+// return FALSE;
+// ICoord2D pos2d;
+// worldToCell(to, &pos2d);
+// if (!goalCell->allocateInfo(pos2d)) {
+// return FALSE;
+// }
+//
+// if (parentCell!=goalCell) {
+// if (!parentCell->allocateInfo(startCellNdx)) {
+//#if RETAIL_COMPATIBLE_PATHFINDING
+// if (!s_useFixedPathfinding) {
+// desiredCell->releaseInfo();
+// }
+//#endif
+// goalCell->releaseInfo();
+// return FALSE;
+// }
+// }
+//
+// PathfindCell *closestCell = nullptr;
+// Real closestDistanceSqr = FLT_MAX;
+// Coord3D closestPos;
+//
+// if (validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), locomotorSet.getRequiredWaterLevel(), parentCell ) == false) {
+// parentCell->releaseInfo();
+// goalCell->releaseInfo();
+// return FALSE;
+// }
+//
+// parentCell->startPathfind(goalCell);
+//
+// // initialize "open" list to contain start cell
+// m_openList = parentCell;
+//
+// // "closed" list is initially empty
+// m_closedList = nullptr;
+//
+// //
+// // Continue search until "open" list is empty, or
+// // until goal is found.
+// //
+// while( m_openList != nullptr )
+// {
+// // take head cell off of open list - it has lowest estimated total path cost
+// parentCell = m_openList;
+// m_openList = parentCell->removeFromOpenList(m_openList);
+//
+// Coord3D pos;
+// // put parent cell onto closed list - its evaluation is finished
+// m_closedList = parentCell->putOnClosedList( m_closedList );
+// if (checkForAdjust(obj, locomotorSet, isHuman, parentCell->getXIndex(), parentCell->getYIndex(), parentCell->getLayer(),
+// radius, center, &pos, groupDest)) {
+// Int dx = IABS(goalCell->getXIndex()-parentCell->getXIndex());
+// Int dy = IABS(goalCell->getYIndex()-parentCell->getYIndex());
+// Real distSqr = dx*dx+dy*dy;
+//
+// if (distSqr < closestDistanceSqr) {
+// closestCell = parentCell;
+// closestDistanceSqr = distSqr;
+// closestPos = pos;
+// } else {
+// continue;
+// }
+// } else {
+// continue;
+// }
+//
+// if (cellCount > MAX_CELL_COUNT) {
+// continue;
+// }
+// // Check to see if we can change layers in this cell.
+// checkChangeLayers(parentCell);
+//
+// // expand search to neighboring orthogonal cells
+// static ICoord2D delta[] =
+// {
+// { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 },
+// { 1, 1 }, { -1, 1 }, { -1, -1 }, { 1, -1 }
+// };
+// const Int numNeighbors = 8;
+// const Int firstDiagonal = 4;
+// ICoord2D newCellCoord;
+// PathfindCell *newCell;
+// const Int adjacent[5] = {0, 1, 2, 3, 0};
+// Bool neighborFlags[8] = { 0 };
+//
+// UnsignedInt newCostSoFar = 0;
+//
+// for( int i=0; igetXIndex() + delta[i].x;
+// newCellCoord.y = parentCell->getYIndex() + delta[i].y;
+//
+// // get the neighboring cell
+// newCell = getCell(parentCell->getLayer(), newCellCoord.x, newCellCoord.y );
+//
+// // check if cell is on the map
+// if (newCell == nullptr)
+// continue;
+//
+// // check if this neighbor cell is already on the open (waiting to be tried)
+// // or closed (already tried) lists
+// Bool onList = false;
+// if (newCell->hasInfo()) {
+// if (newCell->getOpen() || newCell->getClosed())
+// {
+// // already on one of the lists
+// onList = true;
+// }
+// }
+// if (i>=firstDiagonal) {
+// // make sure one of the adjacent sides is open.
+// if (!neighborFlags[adjacent[i-4]] && !neighborFlags[adjacent[i-3]]) {
+// continue;
+// }
+// }
+//
+// if (!validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), locomotorSet.getRequiredWaterLevel(), newCell, parentCell )) {
+// continue;
+// }
+//
+// neighborFlags[i] = true;
+//
+// if (!newCell->allocateInfo(newCellCoord)) {
+// // Out of cells for pathing...
+//#if RETAIL_COMPATIBLE_PATHFINDING
+// if (s_useFixedPathfinding)
+//#endif
+// {
+// cleanOpenAndClosedLists();
+// goalCell->releaseInfo();
+// }
+// return cellCount;
+// }
+// cellCount++;
+//
+// newCostSoFar = newCell->costSoFar( parentCell );
+// newCell->setBlockedByAlly(false);
+//
+// // check if this neighbor cell is already on the open (waiting to be tried)
+// // or closed (already tried) lists
+// if (onList)
+// {
+// // already on one of the lists - if existing costSoFar is less,
+// // the new cell is on a longer path, so skip it
+// if (newCell->getCostSoFar() <= newCostSoFar)
+// continue;
+// }
+//
+// // keep track of path we're building - point back to cell we moved here from
+// newCell->setParentCell(parentCell) ;
+//
+// // store cost of this path
+// newCell->setCostSoFar(newCostSoFar);
+//
+// Int costRemaining = 0;
+// if (goalCell) {
+// costRemaining = newCell->costToGoal( goalCell );
+// }
+//
+// newCell->setTotalCost(newCell->getCostSoFar() + costRemaining) ;
+//
+// // if newCell was on closed list, remove it from the list
+// if (newCell->getClosed())
+// m_closedList = newCell->removeFromClosedList( m_closedList );
+//
+// // if the newCell was already on the open list, remove it so it can be re-inserted in order
+// if (newCell->getOpen())
+// m_openList = newCell->removeFromOpenList( m_openList );
+//
+// // insert newCell in open list such that open list is sorted, smallest total path cost first
+// m_openList = newCell->putOnSortedOpenList( m_openList );
+// }
+// }
+//
+//#if defined(RTS_DEBUG)
+// if (closestCell) {
+// debugShowSearch(true);
+// *dest = closestPos;
+// } else {
+// debugShowSearch(true);
+// }
+//#endif
+// m_isTunneling = false;
+//#if RETAIL_COMPATIBLE_PATHFINDING
+// if (!s_useFixedPathfinding) {
+// cleanOpenAndClosedLists();
+// goalCell->releaseInfo();
+// }
+// else
+//#endif
+// {
+// cleanOpenAndClosedLists();
+// parentCell->releaseInfo();
+// goalCell->releaseInfo();
+// }
+//
+// return false;
+//}
struct TightenPathStruct
{
@@ -8507,7 +8528,7 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
Coord3D adjustTo = *rawTo;
Coord3D *to = &adjustTo;
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// create unique "mark" values for open and closed cells for this pathfind invocation
Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
@@ -8552,25 +8573,34 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
parentCell->startPathfind(goalCell);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
// until goal is found.
//
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
// put parent cell onto closed list - its evaluation is finished - Retail compatible behaviour
#if RETAIL_COMPATIBLE_PATHFINDING
if (!s_useFixedPathfinding) {
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
}
#endif
@@ -8592,7 +8622,7 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
if (s_useFixedPathfinding)
#endif
{
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
}
if (cellCount > MAX_CELL_COUNT) {
@@ -8695,16 +8725,16 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
// if newCell was on closed list, remove it from the list
if (newCell->getClosed())
- m_closedList = newCell->removeFromClosedList( m_closedList );
+ newCell->removeFromClosedList( m_closedList );
// if the newCell was already on the open list, remove it so it can be re-inserted in order
if (newCell->getOpen())
- m_openList = newCell->removeFromOpenList( m_openList );
+ newCell->removeFromOpenList( m_openList );
#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHacker @info This is here to catch a retail pathfinding crash point and to recover from it
// A cell has gotten onto the open list without pathfinding info due to a danling m_open pointer on the previous listed cell so we need to force a cleanup
- if (!s_useFixedPathfinding && m_openList && !m_openList->hasInfo()) {
+ if (!s_useFixedPathfinding && m_openList.getHead() && !m_openList.getHead()->hasInfo()) {
s_useFixedPathfinding = true;
forceCleanCells();
return MAX_COST;
@@ -8712,7 +8742,7 @@ Int Pathfinder::checkPathCost(Object *obj, const LocomotorSet& locomotorSet, con
#endif
// insert newCell in open list such that open list is sorted, smallest total path cost first
- m_openList = newCell->putOnSortedOpenList( m_openList );
+ newCell->putOnSortedOpenList( m_openList );
}
}
@@ -8776,7 +8806,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
adjustTo.x += PATHFIND_CELL_SIZE_F/2;
adjustTo.y += PATHFIND_CELL_SIZE_F/2;
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// create unique "mark" values for open and closed cells for this pathfind invocation
Bool isCrusher = obj ? obj->getCrusherLevel() > 0 : false;
@@ -8881,24 +8911,33 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
Real closestDistScreenSqr = FLT_MAX;
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
Int count = 0;
//
// Continue search until "open" list is empty, or
// until goal is found.
//
Bool foundGoal = false;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
Real dx;
Real dy;
Real distSqr;
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
if (parentCell == goalCell)
{
@@ -8916,7 +8955,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
#ifdef INTENSE_DEBUG
Int count = 0;
PathfindCell *cur;
- for (cur = m_closedList; cur; cur=cur->getNextOpen()) {
+ for (cur = m_closedList.getHead(); cur; cur=cur->getNextOpen()) {
count++;
}
if (count>1000) {
@@ -8953,7 +8992,7 @@ Path *Pathfinder::findClosestPath( Object *obj, const LocomotorSet& locomotorSet
return path;
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
if (!m_isTunneling && checkDestination(obj, parentCell->getXIndex(), parentCell->getYIndex(), parentCell->getLayer(), radius, centerInCell)) {
if (!startedStuck || validMovementPosition( isCrusher, locomotorSet.getValidSurfaces(), locomotorSet.getRequiredWaterLevel(), parentCell )) {
dx = IABS(goalCell->getXIndex()-parentCell->getXIndex());
@@ -10386,7 +10425,7 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
Int radius;
getRadiusAndCenter(obj, radius, centerInCell);
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// determine start cell
ICoord2D startCellNdx;
@@ -10427,10 +10466,19 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
parentCell->startPathfind(nullptr);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -10442,11 +10490,11 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
boxHalfWidth += otherRadius*PATHFIND_CELL_SIZE_F;
if (otherCenter) boxHalfWidth+=PATHFIND_CELL_SIZE_F/2;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Region2D bounds;
Coord3D cellCenter;
@@ -10512,7 +10560,7 @@ Path *Pathfinder::getMoveAwayFromPath(Object* obj, Object *otherObj,
return newPath;
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
@@ -10563,7 +10611,7 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
m_zoneManager.setAllPassable();
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
enum {CELL_LIMIT = 2000}; // max cells to examine.
Int cellCount = 0;
@@ -10594,10 +10642,19 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
parentCell->startPathfind( nullptr);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -10678,11 +10735,11 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
return nullptr;
}
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Coord3D cellCenter;
adjustCoordToCell(parentCell->getXIndex(), parentCell->getYIndex(), centerInCell, cellCenter, parentCell->getLayer());
@@ -10726,7 +10783,7 @@ Path *Pathfinder::patchPath( const Object *obj, const LocomotorSet& locomotorSet
return path;
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
if (cellCount < CELL_LIMIT) {
// Check to see if we can change layers in this cell.
@@ -10836,7 +10893,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
Int cellCount = 0;
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
Int attackDistance = weapon->getAttackDistance(obj, victim, victimPos);
attackDistance += 3*PATHFIND_CELL_SIZE;
@@ -10878,10 +10935,19 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
}
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -10898,11 +10964,11 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
checkLOS = true;
}
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Coord3D cellCenter;
adjustCoordToCell(parentCell->getXIndex(), parentCell->getYIndex(), centerInCell, cellCenter, parentCell->getLayer());
@@ -10942,7 +11008,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
#ifdef INTENSE_DEBUG
Int count = 0;
PathfindCell *cur;
- for (cur = m_closedList; cur; cur=cur->getNextOpen()) {
+ for (cur = m_closedList.getHead(); cur; cur=cur->getNextOpen()) {
count++;
}
if (count>1000) {
@@ -10961,7 +11027,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
debugShowSearch(true);
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// construct and return path
if (obj->isKindOf(KINDOF_VEHICLE)) {
// Strip backwards.
@@ -11051,7 +11117,7 @@ Path *Pathfinder::findAttackPath( const Object *obj, const LocomotorSet& locomot
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
if (cellCount < ATTACK_CELL_LIMIT) {
// Check to see if we can change layers in this cell.
@@ -11128,7 +11194,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
isHuman = false; // computer gets to cheat.
}
- DEBUG_ASSERTCRASH(m_openList== nullptr && m_closedList == nullptr, ("Dangling lists."));
+ DEBUG_ASSERTCRASH(m_openList.empty() && m_closedList.empty(), ("Dangling lists."));
// create unique "mark" values for open and closed cells for this pathfind invocation
m_zoneManager.setAllPassable();
@@ -11147,10 +11213,19 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
parentCell->startPathfind( nullptr);
// initialize "open" list to contain start cell
- m_openList = parentCell;
+#if RETAIL_COMPATIBLE_PATHFINDING
+ if (!s_useFixedPathfinding) {
+ m_openList.reset(parentCell);
+ }
+ else
+#endif
+ {
+ m_openList.reset();
+ parentCell->putOnSortedOpenList(m_openList);
+ }
// "closed" list is initially empty
- m_closedList = nullptr;
+ m_closedList.reset();
//
// Continue search until "open" list is empty, or
@@ -11159,11 +11234,11 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
Real farthestDistanceSqr = 0;
- while( m_openList != nullptr )
+ while( !m_openList.empty() )
{
// take head cell off of open list - it has lowest estimated total path cost
- parentCell = m_openList;
- m_openList = parentCell->removeFromOpenList(m_openList);
+ parentCell = m_openList.getHead();
+ parentCell->removeFromOpenList(m_openList);
Coord3D cellCenter;
adjustCoordToCell(parentCell->getXIndex(), parentCell->getYIndex(), centerInCell, cellCenter, parentCell->getLayer());
@@ -11182,7 +11257,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
if (distSqr>repulsorDistSqr) {
ok = true;
}
- if (m_openList == nullptr && cellCount>0) {
+ if (m_openList.empty() && cellCount>0) {
ok = true; // exhausted the search space, just take the last cell.
}
if (distSqr > farthestDistanceSqr) {
@@ -11202,7 +11277,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
#ifdef INTENSE_DEBUG
Int count = 0;
PathfindCell *cur;
- for (cur = m_closedList; cur; cur=cur->getNextOpen()) {
+ for (cur = m_closedList.getHead(); cur; cur=cur->getNextOpen()) {
count++;
}
if (count>2000) {
@@ -11239,7 +11314,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor
}
// put parent cell onto closed list - its evaluation is finished
- m_closedList = parentCell->putOnClosedList( m_closedList );
+ parentCell->putOnClosedList( m_closedList );
// Check to see if we can change layers in this cell.
checkChangeLayers(parentCell);
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BunkerBusterBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BunkerBusterBehavior.cpp
index b575f638605..3f331184785 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BunkerBusterBehavior.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BunkerBusterBehavior.cpp
@@ -165,6 +165,13 @@ UpdateSleepTime BunkerBusterBehavior::update( void )
// ------------------------------------------------------------------------------------------------
void BunkerBusterBehavior::onDie( const DamageInfo *damageInfo )
{
+#if !RETAIL_COMPATIBLE_CRC
+ // TheSuperHackers @bugfix Stubbjax 17/02/2026 Only bust the bunker if the missile kills itself
+ // by reaching its destination and not when killed via external sources such as a zap from a PDL.
+ if (!getObject()->testStatus(OBJECT_STATUS_MISSILE_KILLING_SELF))
+ return;
+#endif
+
// do what we came here to do!
bustTheBunker();
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp
index 5739b01d220..be1b2989d19 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PoisonedBehavior.cpp
@@ -161,7 +161,7 @@ void PoisonedBehavior::startPoisonedEffects( const DamageInfo *damageInfo )
// We are going to take the damage dealt by the original poisoner every so often for a while.
m_poisonDamageAmount = damageInfo->out.m_actualDamageDealt;
-#if !RETAIL_COMPATIBLE_CRC
+#if !RETAIL_COMPATIBLE_CRC && !PRESERVE_RETAIL_BEHAVIOR
// TheSuperHackers @bugfix Stubbjax 03/09/2025 Allow poison damage to award xp to the poison source.
m_poisonSource = damageInfo->in.m_sourceID;
#endif
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp
index 940a788aaed..11a019584c6 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SpawnBehavior.cpp
@@ -1069,6 +1069,7 @@ void SpawnBehavior::crc( Xfer *xfer )
* Version Info:
* 1: Initial version
* 2: Added m_initialBurstTimesInited to the save. jba.
+ * 3: TheSuperHackers @bugfix Stubbjax 16/02/2026 Added m_initialBurstCountdown.
*/
// ------------------------------------------------------------------------------------------------
void SpawnBehavior::xfer( Xfer *xfer )
@@ -1076,7 +1077,11 @@ void SpawnBehavior::xfer( Xfer *xfer )
AsciiString name;
// version
+#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 2;
+#else
+ XferVersion currentVersion = 3;
+#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
@@ -1088,6 +1093,10 @@ void SpawnBehavior::xfer( Xfer *xfer )
xfer->xferBool(&m_initialBurstTimesInited);
}
+ if (version >= 3) {
+ xfer->xferUnsignedInt(&m_initialBurstCountdown);
+ }
+
// spawn template
name = m_spawnTemplate ? m_spawnTemplate->getName() : AsciiString::TheEmptyString;
xfer->xferAsciiString( &name );
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Body/UndeadBody.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Body/UndeadBody.cpp
index 94326258dfe..1bfda3b74cb 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Body/UndeadBody.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Body/UndeadBody.cpp
@@ -81,7 +81,7 @@ void UndeadBody::attemptDamage( DamageInfo *damageInfo )
if( damageInfo->in.m_damageType != DAMAGE_UNRESISTABLE
&& !m_isSecondLife
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
&& damageInfo->in.m_amount >= getHealth()
#else
// TheSuperHackers @bugfix Stubbjax 20/09/2025 Battle Buses now correctly apply damage modifiers when calculating lethal damage
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp
index ddc48f4abff..c648d4bdfa6 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp
@@ -55,6 +55,7 @@ CrateCollideModuleData::CrateCollideModuleData()
m_isBuildingPickup = FALSE;
m_isHumanOnlyPickup = FALSE;
m_isAllowPickAboveTerrain = FALSE;
+ m_allowMultiPickup = FALSE; // (PRESERVE_RETAIL_BEHAVIOR != 0);
m_executeFX = nullptr;
m_pickupScience = SCIENCE_INVALID;
m_executionAnimationTemplate = AsciiString::TheEmptyString;
@@ -75,6 +76,7 @@ void CrateCollideModuleData::buildFieldParse(MultiIniFieldParse& p)
{ "BuildingPickup", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_isBuildingPickup ) },
{ "HumanOnly", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_isHumanOnlyPickup ) },
{ "AllowPickAboveTerrain", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_isAllowPickAboveTerrain ) },
+ { "AllowMultiPickup", INI::parseBool, nullptr, offsetof( CrateCollideModuleData, m_allowMultiPickup ) },
{ "PickupScience", INI::parseScience, nullptr, offsetof( CrateCollideModuleData, m_pickupScience ) },
{ "ExecuteFX", INI::parseFXList, nullptr, offsetof( CrateCollideModuleData, m_executeFX ) },
{ "ExecuteAnimation", INI::parseAsciiString, nullptr, offsetof( CrateCollideModuleData, m_executionAnimationTemplate ) },
@@ -172,7 +174,7 @@ Bool CrateCollide::isValidToExecute( const Object *other ) const
// TheSuperHackers @bugfix Stubbjax 09/02/2026 Prevent the crate from being collected multiple times in a single frame.
#if !RETAIL_COMPATIBLE_CRC
- if (getObject()->isDestroyed())
+ if (getObject()->isDestroyed() && !md->m_allowMultiPickup)
return FALSE;
#endif
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
index 205aef85e50..14edb8435b8 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp
@@ -131,7 +131,6 @@ OpenContain::OpenContain( Thing *thing, const ModuleData* moduleData ) : UpdateM
m_containListSize = 0;
m_stealthUnitsContained = 0;
m_heroUnitsContained = 0;
- m_xferVersion = 1;
m_doorCloseCountdown = 0;
m_rallyPoint.zero();
@@ -1705,21 +1704,15 @@ void OpenContain::crc( Xfer *xfer )
* Version Info:
* 1: Initial version
* 2: Added m_passengerAllowedToFire
- * 3: TheSuperHackers @tweak Serialize hero units contained count
*/
// ------------------------------------------------------------------------------------------------
void OpenContain::xfer( Xfer *xfer )
{
// version
-#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 2;
-#else
- XferVersion currentVersion = 3;
-#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
- m_xferVersion = version;
// extend base class
UpdateModule::xfer( xfer );
@@ -1793,18 +1786,12 @@ void OpenContain::xfer( Xfer *xfer )
xfer->xferUnsignedInt( &m_lastLoadSoundFrame );
// stealth units contained
- xfer->xferUnsignedInt( &m_stealthUnitsContained );
-
- // hero units contained
- if (version >= 3)
- {
- xfer->xferUnsignedInt( &m_heroUnitsContained );
- }
+ xfer->xferUnsignedInt( &m_stealthUnitsContained ); // TheSuperHackers @todo This is redundant information in xfer. Remove it.
// door close countdown
xfer->xferUnsignedInt( &m_doorCloseCountdown );
- // conditionstate
+ // condition state
m_conditionState.xfer( xfer );
// fire points
@@ -1911,6 +1898,9 @@ void OpenContain::loadPostProcess( void )
}
// turn the contained id list into actual object pointers in the contain list
+ m_containListSize = 0;
+ m_stealthUnitsContained = 0;
+ m_heroUnitsContained = 0;
Object *obj;
std::list::const_iterator idIt;
for( idIt = m_xferContainIDList.begin(); idIt != m_xferContainIDList.end(); ++idIt )
@@ -1929,7 +1919,7 @@ void OpenContain::loadPostProcess( void )
}
// put object on list
- m_containList.push_back( obj );
+ addToContainList( obj );
// remove this object from the world if we need to
if( isEnclosingContainerFor( obj ) )
@@ -1940,19 +1930,6 @@ void OpenContain::loadPostProcess( void )
}
- if (m_xferVersion < 3)
- {
- // Restore hero count by iterating hero objects for old save versions
- m_heroUnitsContained = 0;
- for( ContainedItemsList::const_iterator it = m_containList.begin(); it != m_containList.end(); ++it )
- {
- if( (*it)->isKindOf( KINDOF_HERO ) )
- {
- m_heroUnitsContained++;
- }
- }
- }
-
// sanity
DEBUG_ASSERTCRASH( m_containListSize == m_containList.size(),
("OpenContain::loadPostProcess - contain list count mismatch") );
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp
index b822682febd..4246fe6c403 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp
@@ -305,6 +305,16 @@ UnsignedInt TunnelContain::getContainCount() const
return 0;
}
+UnsignedInt TunnelContain::getHeroUnitsContained() const
+{
+ Player *owningPlayer = getObject()->getControllingPlayer();
+ if( owningPlayer && owningPlayer->getTunnelSystem() )
+ {
+ return owningPlayer->getTunnelSystem()->getHeroUnitsContained();
+ }
+ return 0;
+}
+
Int TunnelContain::getContainMax( void ) const
{
Player *owningPlayer = getObject()->getControllingPlayer();
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp
index 9c566821e6c..b85613f8c22 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Create/GrantUpgradeCreate.cpp
@@ -91,7 +91,7 @@ void GrantUpgradeCreate::onCreate( void )
const UpgradeTemplate *upgradeTemplate = TheUpgradeCenter->findUpgrade( getGrantUpgradeCreateModuleData()->m_upgradeName );
if( !upgradeTemplate )
{
- DEBUG_ASSERTCRASH( 0, ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
+ DEBUG_CRASH( ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
return;
}
@@ -124,7 +124,7 @@ void GrantUpgradeCreate::onBuildComplete( void )
const UpgradeTemplate *upgradeTemplate = TheUpgradeCenter->findUpgrade( getGrantUpgradeCreateModuleData()->m_upgradeName );
if( !upgradeTemplate )
{
- DEBUG_ASSERTCRASH( 0, ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
+ DEBUG_CRASH( ("GrantUpdateCreate for %s can't find upgrade template %s.", getObject()->getName().str(), getGrantUpgradeCreateModuleData()->m_upgradeName.str() ) );
return;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp
index f94b69a5db0..d81b3b308f9 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Die/UpgradeDie.cpp
@@ -76,7 +76,7 @@ void UpgradeDie::onDie( const DamageInfo *damageInfo )
}
else
{
- DEBUG_ASSERTCRASH( 0, ("Object %s just died, but is trying to free upgrade %s in it's producer %s%s",
+ DEBUG_CRASH( ("Object %s just died, but is trying to free upgrade %s in it's producer %s%s",
getObject()->getTemplate()->getName().str(),
getUpgradeDieModuleData()->m_upgradeName.str(),
producer->getTemplate()->getName().str(),
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp
index 13afae19b94..5e4aec8208d 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp
@@ -1266,7 +1266,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget
}
else
{
- DEBUG_ASSERTCRASH(FALSE,("A OCL with ContainInsideSourceObject failed the contain and is killing the new object."));
+ DEBUG_CRASH(("A OCL with ContainInsideSourceObject failed the contain and is killing the new object."));
// If we fail to contain it, we can't just leave it. Stillborn it.
TheGameLogic->destroyObject(obj);
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
index 830c0e67f91..6d4a7d49e47 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
@@ -5145,12 +5145,12 @@ void AIUpdateInterface::privateCommandButton( const CommandButton *commandButton
default:
if( owner->getName().isNotEmpty() )
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButton() -- unit %s ('%s'), command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButton() -- unit %s ('%s'), command %s not implemented.",
owner->getTemplate()->getName().str(), owner->getName().str(), commandButton->getTextLabel().str() ) );
}
else
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButton() -- unit %s, command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButton() -- unit %s, command %s not implemented.",
owner->getTemplate()->getName().str(), commandButton->getTextLabel().str() ) );
}
}
@@ -5198,12 +5198,12 @@ void AIUpdateInterface::privateCommandButtonPosition( const CommandButton *comma
default:
if( owner->getName().isNotEmpty() )
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButtonPosition() -- unit %s ('%s'), command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButtonPosition() -- unit %s ('%s'), command %s not implemented.",
owner->getTemplate()->getName().str(), owner->getName().str(), commandButton->getTextLabel().str() ) );
}
else
{
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButtonPosition() -- unit %s, command %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButtonPosition() -- unit %s, command %s not implemented.",
owner->getTemplate()->getName().str(), commandButton->getTextLabel().str() ) );
}
break;
@@ -5265,7 +5265,7 @@ void AIUpdateInterface::privateCommandButtonObject( const CommandButton *command
targetNickname.format( "('%s')", obj->getName().str() );
}
- DEBUG_ASSERTCRASH( 0, ("AIUpdate::privateCommandButtonPosition() -- unit %s %s, command %s at unit %s %s not implemented.",
+ DEBUG_CRASH( ("AIUpdate::privateCommandButtonPosition() -- unit %s %s, command %s at unit %s %s not implemented.",
myName.str(), myNickname.str(), commandButton->getTextLabel().str(), targetName.str(), targetNickname.str() ) );
}
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
index ce85c769e0c..4962896d635 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp
@@ -1316,7 +1316,7 @@ void ChinookAIUpdate::aiDoCommand(const AICommandParms* parms)
{
const Real THRESH = 3.0f;
const Real THRESH_SQR = THRESH*THRESH;
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
const bool allowExit = true;
#else
// TheSuperHackers @bugfix Stubbjax 04/11/2025 Passengers are no longer all dumped in a single frame.
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp
index b3424e0a466..eee98cc06cc 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp
@@ -851,7 +851,7 @@ StateReturnType DeliveringState::update() // Kick a dude out every so often
const WeaponTemplate *weaponTemplate = ai->getData()->m_visiblePayloadWeaponTemplate;
if( !weaponTemplate )
{
- DEBUG_ASSERTCRASH( 0, ("%s tried to fire missile %s via DeliverPayload, and is missing required weapon template in ObjectCreationList.ini entry.",
+ DEBUG_CRASH( ("%s tried to fire missile %s via DeliverPayload, and is missing required weapon template in ObjectCreationList.ini entry.",
owner->getTemplate()->getName().str(), payload->getTemplate()->getName().str() ) );
break;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp
index 06edb9fa6b5..1ce0c4ef4df 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp
@@ -1499,7 +1499,7 @@ void RailroadBehavior::FindPosByPathDistance( Coord3D *pos, const Real dist, con
}
- //DEBUG_ASSERTCRASH(FALSE,("Railroad could not find a position on the path!"));
+ //DEBUG_CRASH(("Railroad could not find a position on the path!"));
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp
index f03815d2d24..fb6004f4fa8 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/BattlePlanUpdate.cpp
@@ -372,6 +372,10 @@ UpdateSleepTime BattlePlanUpdate::update()
{
//It's not centered, and not trying to center, so order it to center.
ai->aiIdle( CMD_FROM_AI );
+#if !RETAIL_COMPATIBLE_CRC
+ // TheSuperHackers @bugfix Stubbjax 19/02/2026 Prevent using the turret while it recenters.
+ enableTurret(false);
+#endif
recenterTurret();
m_centeringTurret = true;
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp
index 86299d46ad2..5bf329c4b22 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/DockUpdate.cpp
@@ -373,7 +373,7 @@ void DockUpdate::onExitReached( Object* docker )
// to continue moving to the exit position cause they are leaving after all
//
if( isDockOpen() )
- DEBUG_ASSERTCRASH( FALSE, ("Fiddle. Someone said goodbye to a dock when the dock didn't think it was talking to that someone."));
+ DEBUG_CRASH( ("Fiddle. Someone said goodbye to a dock when the dock didn't think it was talking to that someone."));
}
}
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp
index 174474eab41..f4082c05643 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FlammableUpdate.cpp
@@ -108,7 +108,7 @@ void FlammableUpdate::onDamage( DamageInfo *damageInfo )
m_flameDamageLimit = getFlammableUpdateModuleData()->m_flameDamageLimitData;
}
m_lastFlameDamageDealt = now;
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
m_flameSource = getObject()->getID();
#else
// TheSuperHackers @bugfix Stubbjax 03/09/2025 Allow flame damage to award xp to the flame source.
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp
index e854f2c9306..0e0d4b2a4b9 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp
@@ -876,7 +876,7 @@ UpdateSleepTime ProductionUpdate::update( void )
{
// there is no exit interface, this is an error
- DEBUG_ASSERTCRASH( 0, ("Cannot create '%s', there is no ExitUpdate interface defined for producer object '%s'",
+ DEBUG_CRASH( ("Cannot create '%s', there is no ExitUpdate interface defined for producer object '%s'",
production->m_objectToProduce->getName().str(),
creationBuilding->getTemplate()->getName().str()) );
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp
index eb17ff3ea41..e521ffa50f0 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpecialAbilityUpdate.cpp
@@ -1350,7 +1350,7 @@ void SpecialAbilityUpdate::triggerAbilityEffect()
StickyBombUpdate *update = (StickyBombUpdate*)charge->findUpdateModule( key_StickyBombUpdate );
if( !update )
{
- DEBUG_ASSERTCRASH( 0,
+ DEBUG_CRASH(
("Unit '%s' attempted to place %s on %s but the bomb requires a StickyBombUpdate module.",
object->getTemplate()->getName().str(),
charge->getTemplate()->getName().str(),
@@ -1575,7 +1575,7 @@ void SpecialAbilityUpdate::triggerAbilityEffect()
StickyBombUpdate *update = (StickyBombUpdate*)charge->findUpdateModule( key_StickyBombUpdate );
if( !update )
{
- DEBUG_ASSERTCRASH( 0,
+ DEBUG_CRASH(
("Unit '%s' attempted to place remote charge but the charge '%s' requires a StickyBombUpdate module.",
object->getTemplate()->getName().str(),
charge->getTemplate()->getName().str() ) );
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
index cbb42f7897d..14487fbe287 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
@@ -1313,7 +1313,7 @@ void WeaponTemplate::createPreAttackFX
}
}
//-------------------------------------------------------------------------------------------------
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
void WeaponTemplate::trimOldHistoricDamage() const
{
UnsignedInt expirationDate = TheGameLogic->getFrame() - TheGlobalData->m_historicDamageLimit;
@@ -1376,7 +1376,7 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis
}
//-------------------------------------------------------------------------------------------------
-#if RETAIL_COMPATIBLE_CRC
+#if RETAIL_COMPATIBLE_CRC || PRESERVE_RETAIL_BEHAVIOR
void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const
{
//
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp
index ae5a84d361e..6451e686c68 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/VictoryConditions.cpp
@@ -93,10 +93,15 @@ class VictoryConditions : public VictoryConditionsInterface
Bool amIObserver( void ) { return m_isObserver;} ///< Am I an observer?( need this for scripts )
virtual UnsignedInt getEndFrame( void ) { return m_endFrame; } ///< on which frame was the game effectively over?
private:
+ Player* findFirstUndefeatedPlayer(); ///< Find the first player that has not been defeated.
+ void markAllianceVictorious(Player* victoriousPlayer); ///< Mark the victorious player and his allies as victorious.
+ Bool multipleAlliancesExist(void); ///< Are there multiple alliances still alive?
+
Player* m_players[MAX_PLAYER_COUNT];
Int m_localSlotNum;
UnsignedInt m_endFrame;
Bool m_isDefeated[MAX_PLAYER_COUNT];
+ Bool m_isVictorious[MAX_PLAYER_COUNT];
Bool m_localPlayerDefeated; ///< prevents condition from being signaled each frame
Bool m_singleAllianceRemaining; ///< prevents condition from being signaled each frame
Bool m_isObserver;
@@ -128,6 +133,7 @@ void VictoryConditions::reset( void )
{
m_players[i] = nullptr;
m_isDefeated[i] = false;
+ m_isVictorious[i] = false;
}
m_localSlotNum = -1;
@@ -140,42 +146,52 @@ void VictoryConditions::reset( void )
}
//-------------------------------------------------------------------------------------------------
-void VictoryConditions::update( void )
+Bool VictoryConditions::multipleAlliancesExist()
{
- if (!TheRecorder->isMultiplayer() || (m_localSlotNum < 0 && !m_isObserver))
- return;
+ Player* alive = nullptr;
- // Check for a single winning alliance
- if (!m_singleAllianceRemaining)
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
{
- Bool multipleAlliances = false;
- Player *alive = nullptr;
- Player *player;
- for (Int i=0; iisMultiplayer() || (m_localSlotNum < 0 && !m_isObserver))
+ return;
+
+ // Check for a single winning alliance
+ if (!m_singleAllianceRemaining)
+ {
+ if (!multipleAlliancesExist())
{
m_singleAllianceRemaining = true; // don't check again
m_endFrame = TheGameLogic->getFrame();
+
+ Player* victoriousPlayer = findFirstUndefeatedPlayer();
+
+ if (victoriousPlayer)
+ markAllianceVictorious(victoriousPlayer);
}
}
@@ -235,19 +251,50 @@ void VictoryConditions::update( void )
}
}
+//-------------------------------------------------------------------------------------------------
+Player* VictoryConditions::findFirstUndefeatedPlayer()
+{
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
+ {
+ Player* player = m_players[i];
+ if (player && !hasSinglePlayerBeenDefeated(player))
+ return player;
+ }
+
+ return nullptr;
+}
+
+// TheSuperHackers @bugfix Stubbjax 11/02/2026 This marks the player and any allies as victorious, including
+// defeated allies. This also ensures players retain their victorious status if their assets are destroyed
+// after the victory conditions are met (e.g. when quitting the game prior to the victory screen).
+//-------------------------------------------------------------------------------------------------
+void VictoryConditions::markAllianceVictorious(Player* victoriousPlayer)
+{
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
+ {
+ Player* player = m_players[i];
+ if (player == victoriousPlayer || (player && areAllies(player, victoriousPlayer)))
+ m_isVictorious[i] = true;
+ }
+}
+
//-------------------------------------------------------------------------------------------------
Bool VictoryConditions::hasAchievedVictory(Player *player)
{
if (!player)
return false;
- if (m_singleAllianceRemaining)
+ if (!m_singleAllianceRemaining)
+ return false;
+
+ for (Int i = 0; i < MAX_PLAYER_COUNT; ++i)
{
- for (Int i=0; i= MAX_SLOTS)
{
- DEBUG_ASSERTCRASH(FALSE,("GameLogic::processProgressComplete, Invalid playerid was passed in %d", playerId));
+ DEBUG_CRASH(("GameLogic::processProgressComplete, Invalid playerid was passed in %d", playerId));
return;
}
if(m_progressComplete[playerId] == TRUE)
diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
index 73474aa6a5d..a1dadf86a91 100644
--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
+++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogicDispatch.cpp
@@ -1396,7 +1396,7 @@ void GameLogic::logicMessageDispatcher( GameMessage *msg, void *userData )
if( pu == nullptr )
{
- DEBUG_ASSERTCRASH( 0, ("MSG_QUEUE_UNIT_CREATE: Producer '%s' doesn't have a unit production interface",
+ DEBUG_CRASH( ("MSG_QUEUE_UNIT_CREATE: Producer '%s' doesn't have a unit production interface",
producer->getTemplate()->getName().str()) );
break;
diff --git a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt
index 7d4293df90d..ae8ddb9ac79 100644
--- a/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt
+++ b/GeneralsMD/Code/GameEngineDevice/CMakeLists.txt
@@ -54,7 +54,7 @@ set(GAMEENGINEDEVICE_SRC
Include/W3DDevice/GameClient/W3DGUICallbacks.h
Include/W3DDevice/GameClient/W3DInGameUI.h
Include/W3DDevice/GameClient/W3DMirror.h
- Include/W3DDevice/GameClient/W3DMouse.h
+# Include/W3DDevice/GameClient/W3DMouse.h
Include/W3DDevice/GameClient/W3DParticleSys.h
Include/W3DDevice/GameClient/W3DPoly.h
Include/W3DDevice/GameClient/W3DProjectedShadow.h
@@ -87,9 +87,9 @@ set(GAMEENGINEDEVICE_SRC
Include/Win32Device/Common/Win32GameEngine.h
# Include/Win32Device/Common/Win32LocalFile.h
# Include/Win32Device/Common/Win32LocalFileSystem.h
- Include/Win32Device/GameClient/Win32DIKeyboard.h
- Include/Win32Device/GameClient/Win32DIMouse.h
- Include/Win32Device/GameClient/Win32Mouse.h
+# Include/Win32Device/GameClient/Win32DIKeyboard.h
+# Include/Win32Device/GameClient/Win32DIMouse.h
+# Include/Win32Device/GameClient/Win32Mouse.h
# Source/MilesAudioDevice/MilesAudioManager.cpp
# Source/VideoDevice/Bink/BinkVideoPlayer.cpp
Source/W3DDevice/Common/System/W3DFunctionLexicon.cpp
@@ -158,7 +158,7 @@ set(GAMEENGINEDEVICE_SRC
Source/W3DDevice/GameClient/W3DFileSystem.cpp
Source/W3DDevice/GameClient/W3DGameClient.cpp
Source/W3DDevice/GameClient/W3DInGameUI.cpp
- Source/W3DDevice/GameClient/W3DMouse.cpp
+# Source/W3DDevice/GameClient/W3DMouse.cpp
Source/W3DDevice/GameClient/W3DParticleSys.cpp
Source/W3DDevice/GameClient/W3DPoly.cpp
# Source/W3DDevice/GameClient/W3DPropBuffer.cpp
@@ -189,9 +189,9 @@ set(GAMEENGINEDEVICE_SRC
# Source/Win32Device/Common/Win32LocalFile.cpp
# Source/Win32Device/Common/Win32LocalFileSystem.cpp
Source/Win32Device/Common/Win32OSDisplay.cpp
- Source/Win32Device/GameClient/Win32DIKeyboard.cpp
- #Source/Win32Device/GameClient/Win32DIMouse.cpp
- Source/Win32Device/GameClient/Win32Mouse.cpp
+# Source/Win32Device/GameClient/Win32DIKeyboard.cpp
+# #Source/Win32Device/GameClient/Win32DIMouse.cpp
+# Source/Win32Device/GameClient/Win32Mouse.cpp
)
add_library(z_gameenginedevice STATIC)
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
index a2a6e45cd2d..c45a9f1d917 100644
--- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
+++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
@@ -778,7 +778,7 @@ void W3DDisplay::init( void )
WW3D::Shutdown();
WWMath::Shutdown();
throw ERROR_INVALID_D3D; //failed to initialize. User probably doesn't have DX 8.1
- DEBUG_ASSERTCRASH( 0, ("Unable to set render device") );
+ DEBUG_CRASH( ("Unable to set render device") );
return;
}
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp
index 248bba08706..4a56e2cb750 100644
--- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp
+++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScene.cpp
@@ -1385,7 +1385,7 @@ void RTS3DScene::flushOccludedObjectsIntoStencil(RenderInfoClass & rinfo)
if ((lastPlayerObject[index]-&playerObjects[index][0]) >= MAX_VISIBLE_OCCLUDED_PLAYER_OBJECTS)
{
- DEBUG_ASSERTCRASH(FALSE,("Exceeded Maximum Number of potentially occluded models"));
+ DEBUG_CRASH(("Exceeded Maximum Number of potentially occluded models"));
continue;
}
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt b/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt
index c6e309238db..317b8dffd65 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt
+++ b/GeneralsMD/Code/Tools/WorldBuilder/CMakeLists.txt
@@ -22,7 +22,6 @@ set(WORLDBUILDER_SRC
"src/EditGroup.cpp"
"src/EditObjectParameter.cpp"
"src/EditParameter.cpp"
- "src/EulaDialog.cpp"
"src/ExportScriptsOptions.cpp"
"src/EyedropperTool.cpp"
"src/FeatherOptions.cpp"
@@ -122,7 +121,6 @@ set(WORLDBUILDER_SRC
"include/EditGroup.h"
"include/EditObjectParameter.h"
"include/EditParameter.h"
- "include/euladialog.h"
"include/ExportScriptsOptions.h"
"include/EyedropperTool.h"
"include/FeatherOptions.h"
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/include/euladialog.h b/GeneralsMD/Code/Tools/WorldBuilder/include/euladialog.h
deleted file mode 100644
index e7fa8b4745d..00000000000
--- a/GeneralsMD/Code/Tools/WorldBuilder/include/euladialog.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-#pragma once
-
-// euladialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// EulaDialog dialog
-
-class EulaDialog : public CDialog
-{
-// Construction
-public:
- EulaDialog(CWnd* pParent = nullptr); // standard constructor
-
-// Dialog Data
- //{{AFX_DATA(EulaDialog)
- enum { IDD = IDD_EULA_AGREEMENT };
- // NOTE: the ClassWizard will add data members here
- //}}AFX_DATA
-
-
-// Overrides
- // ClassWizard generated virtual function overrides
- //{{AFX_VIRTUAL(EulaDialog)
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
- //}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
- // Generated message map functions
- //{{AFX_MSG(EulaDialog)
- virtual BOOL OnInitDialog();
- //}}AFX_MSG
- DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/res/WorldBuilder.rc b/GeneralsMD/Code/Tools/WorldBuilder/res/WorldBuilder.rc
index ef28eed189c..6cbb57e5ac1 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/res/WorldBuilder.rc
+++ b/GeneralsMD/Code/Tools/WorldBuilder/res/WorldBuilder.rc
@@ -1693,17 +1693,6 @@ BEGIN
BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,40,51,95,14
END
-IDD_EULA_AGREEMENT DIALOG DISCARDABLE 0, 0, 267, 289
-STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
-CAPTION "EA TOOLS END USER LICENSE"
-FONT 8, "MS Sans Serif"
-BEGIN
- PUSHBUTTON "Cancel",IDCANCEL,210,268,50,14
- DEFPUSHBUTTON "Accept Terms",IDOK,154,268,50,14
- EDITTEXT IDC_EDIT1,17,18,230,246,ES_MULTILINE | ES_READONLY |
- WS_VSCROLL
-END
-
IDD_TeamObjectProperties DIALOG DISCARDABLE 0, 0, 213, 327
STYLE DS_MODALFRAME | WS_CHILD | WS_DISABLED | WS_CAPTION | WS_SYSMENU
CAPTION "Common Object Properties"
@@ -2366,14 +2355,6 @@ BEGIN
BOTTOMMARGIN, 88
END
- IDD_EULA_AGREEMENT, DIALOG
- BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 260
- TOPMARGIN, 7
- BOTTOMMARGIN, 282
- END
-
IDD_TeamObjectProperties, DIALOG
BEGIN
BOTTOMMARGIN, 321
@@ -2795,11 +2776,6 @@ BEGIN
IDS_SINGLE_SELECTION_ONLY "Single Selection Only"
IDS_NO_UPGRADES "No Upgrades Available"
IDS_TEAMS_FIXED "One or more teams have been fixed. Please save and re-open the file."
- IDS_EULA_AGREEMENT1 "Electronic Arts Inc, and its subsidiaries, affiliates and licensors (collectively, ""EA"") grants you a non- transferable license to download and use one copy of the software tool (""Tool""), other materials accompanying the tool, and the materials created with the tool (collectively the ""Tools & Materials"") solely for your personal noncommercial use in connection with EA products."
- IDS_EULA_AGREEMENT2 "\r\n\r\nEA and its Licensors own all of the rights in the Tools & Materials. You may not alter any of EA's trademarks or logos, or alter or remove any of EA's or its Licensor's trademark or copyright notices included in or with the Tools & Materials. Your right to use Tools & Materials is limited to the license grant above, and you may not otherwise copy, display, distribute, perform, publish, modify, or use any of the Tools & Materials. Without limiting the preceding sentence, you may not modify, reverse engineer, disassemble, license, transfer, distribute, create derivative works from, or sell the Tool, or use the Tools & Materials to further any commercial or unlawful purpose. Without limiting the foregoing, you may not use the Tools & Materials to sell advertising, to promote another product or business, or on any site that operates or promotes a server emulator."
- IDS_EULA_AGREEMENT3 "\r\n\r\nEA does not represent or warrant that you will be able to use any of the Tools & Materials. You expressly agree that your use of the Tools & Materials is at your sole risk. The Tools & Materials are provided on an ""as is,"" ""as available"" basis. EA disclaims all implied warranties and conditions, including without limitation any implied warranties of merchantability, fitness for a particular purpose, or non-infringement of third party rights. EA assumes no responsibility for any damages suffered by you. At EA's request, you agree to defend, indemnify and hold harmless EA from all liabilities, claims and expenses, including attorneys' fees, arising from any breach of this License by you and/or your use or misuse of the Tools & Materials."
- IDS_EULA_AGREEMENT4 "\r\n\r\nEA may make the Tools & Materials available at its site(s) located in the United States and/or Canada and/or the European Union. You are solely responsible for knowing and complying with all federal, state, and local laws that may apply to your use of Tools & Materials in your own locale. By downloading any Tools & Materials, you warrant that you are not located in any country, or exporting the Tools & Materials to any person or place, to which the United States and/or Canada and/or European Union or its member countries has embargoed goods."
- IDS_EULA_AGREEMENT5 "\r\n\r\nEA may terminate this License at any time. Upon termination, you must destroy or return to EA all Tools & Materials. This License is governed by United States Copyright and California law (without regard to conflicts of law), and is the entire agreement between EA and you regarding the Tools & Materials."
IDS_MAPOBJECT_PROPS_TITLE "Object Properties"
IDS_NO_PROBLEMS "No problems were detected."
IDS_DUPLICATE_TEAM_REMOVED "Duplicate instance of team ""%s"" removed."
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp
index 809e6d63685..d9189705eae 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp
+++ b/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp
@@ -1238,7 +1238,7 @@ Bool EditParameter::loadCommandButtons(CComboBox *pCombo, AsciiString match)
char buf[1024];
char *string;
char *token;
- char seps[] = " ,\t\n";
+ char seps[] = " ,\t\n\r";
fp->nextLine(buf, 1024);
string = buf;
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/EulaDialog.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/EulaDialog.cpp
deleted file mode 100644
index 0814e7f5a5d..00000000000
--- a/GeneralsMD/Code/Tools/WorldBuilder/src/EulaDialog.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-** Command & Conquer Generals Zero Hour(tm)
-** Copyright 2025 Electronic Arts Inc.
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-*/
-
-// EulaDialog.cpp : implementation file
-//
-
-#include "StdAfx.h"
-#include "WorldBuilder.h"
-#include "euladialog.h"
-
-#ifdef RTS_DEBUG
-#define new DEBUG_NEW
-#undef THIS_FILE
-static char THIS_FILE[] = __FILE__;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// EulaDialog dialog
-
-
-EulaDialog::EulaDialog(CWnd* pParent /*=nullptr*/)
- : CDialog(EulaDialog::IDD, pParent)
-{
- //{{AFX_DATA_INIT(EulaDialog)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
-}
-
-
-void EulaDialog::DoDataExchange(CDataExchange* pDX)
-{
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(EulaDialog)
- // NOTE: the ClassWizard will add DDX and DDV calls here
- //}}AFX_DATA_MAP
-}
-
-
-BEGIN_MESSAGE_MAP(EulaDialog, CDialog)
- //{{AFX_MSG_MAP(EulaDialog)
- //}}AFX_MSG_MAP
-END_MESSAGE_MAP()
-
-/////////////////////////////////////////////////////////////////////////////
-// EulaDialog message handlers
-
-BOOL EulaDialog::OnInitDialog()
-{
- CDialog::OnInitDialog();
-
- CString theText;
- theText.LoadString( IDS_EULA_AGREEMENT1 );
-
- CString concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT2 );
- theText += concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT3 );
- theText += concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT4 );
- theText += concatText;
- concatText.LoadString( IDS_EULA_AGREEMENT5 );
- theText += concatText;
-
- CWnd *theEditDialog = GetDlgItem( IDC_EDIT1 );
- if( theEditDialog )
- {
- theEditDialog->SetWindowText( theText );
- }
-
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
-}
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/ObjectOptions.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/ObjectOptions.cpp
index c15e1d3657d..dcc8db44aa0 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/src/ObjectOptions.cpp
+++ b/GeneralsMD/Code/Tools/WorldBuilder/src/ObjectOptions.cpp
@@ -402,10 +402,11 @@ HTREEITEM ObjectOptions::_FindOrDont(const char* pLabel, HTREEITEM startPoint)
std::list itemsToEx;
itemsToEx.push_back(startPoint);
- while (itemsToEx.front()) {
+ while (!itemsToEx.empty()) {
char buffer[_MAX_PATH];
HTREEITEM hItem = itemsToEx.front();
itemsToEx.pop_front();
+ DEBUG_ASSERTCRASH(hItem != nullptr, ("Unexpected tree item pointer in ObjectOptions::_FindOrDont"));
if (!m_objectTreeView.ItemHasChildren(hItem)) {
TVITEM item;
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp
index 5d4a3dd0cc8..fc390fb0f27 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp
+++ b/GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp
@@ -21,7 +21,6 @@
#include "StdAfx.h"
#include "WorldBuilder.h"
-#include "euladialog.h"
#include "MainFrm.h"
#include "OpenMap.h"
#include "SplashScreen.h"
@@ -275,14 +274,6 @@ static LONG WINAPI UnHandledExceptionFilter(struct _EXCEPTION_POINTERS* e_info)
BOOL CWorldBuilderApp::InitInstance()
{
-//#ifdef RTS_RELEASE
- EulaDialog eulaDialog;
- if( eulaDialog.DoModal() == IDCANCEL )
- {
- return FALSE;
- }
-//#endif
-
ApplicationHWnd = GetDesktopWindow();
// initialization
diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp
index 6bdee1e0e3f..3abebcc0823 100644
--- a/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp
+++ b/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp
@@ -29,6 +29,7 @@
#include "intersec.h"
#include "W3DDevice/GameClient/W3DAssetManager.h"
#include "W3DDevice/GameClient/Module/W3DModelDraw.h"
+#include "W3DDevice/GameClient/Module/W3DTreeDraw.h"
#include "agg_def.h"
#include "part_ldr.h"
#include "hanim.h"
@@ -1118,6 +1119,14 @@ AsciiString WbView3d::getBestModelName(const ThingTemplate* tt, const ModelCondi
{
return md->getBestModelNameForWB(c);
}
+
+ // TheSuperHackers @bugfix ViTeXFTW 15/02/2026 Fix tree objects not showing a preview in
+ // WB object placer. The W3DTreeDraw module stores its model name differently from W3DModelDraw.
+ const W3DTreeDrawModuleData* treeData = mdd ? mdd->getAsW3DTreeDrawModuleData() : nullptr;
+ if (treeData)
+ {
+ return treeData->m_modelName;
+ }
}
}
// removing this crash as sounds can (and should) have no model - jkmcd
diff --git a/scripts/cpp/unify_move_files.py b/scripts/cpp/unify_move_files.py
index 4d7f61f7d00..009fe4f7dab 100644
--- a/scripts/cpp/unify_move_files.py
+++ b/scripts/cpp/unify_move_files.py
@@ -344,6 +344,71 @@ def main():
#unify_move_file(Game.ZEROHOUR, "GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DOverlordAircraftDraw.cpp", Game.CORE, "GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DOverlordAircraftDraw.cpp")
#unify_move_file(Game.ZEROHOUR, "GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DOverlordTruckDraw.cpp", Game.CORE, "GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DOverlordTruckDraw.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/Mouse.h", Game.CORE, "GameEngine/Include/GameClient/Mouse.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/Input/Mouse.cpp", Game.CORE, "GameEngine/Source/GameClient/Input/Mouse.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/Keyboard.h", Game.CORE, "GameEngine/Include/GameClient/Keyboard.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/Input/Keyboard.cpp", Game.CORE, "GameEngine/Source/GameClient/Input/Keyboard.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h", Game.CORE, "GameEngineDevice/Include/W3DDevice/GameClient/W3DMouse.h")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp", Game.CORE, "GameEngineDevice/Source/W3DDevice/GameClient/W3DMouse.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Include/Win32Device/GameClient/Win32DIKeyboard.h", Game.CORE, "GameEngineDevice/Include/Win32Device/GameClient/Win32DIKeyboard.h")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h", Game.CORE, "GameEngineDevice/Include/Win32Device/GameClient/Win32DIMouse.h")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h", Game.CORE, "GameEngineDevice/Include/Win32Device/GameClient/Win32Mouse.h")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp", Game.CORE, "GameEngineDevice/Source/Win32Device/GameClient/Win32DIKeyboard.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp", Game.CORE, "GameEngineDevice/Source/Win32Device/GameClient/Win32DIMouse.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp", Game.CORE, "GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp")
+
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameFont.h", Game.CORE, "GameEngine/Include/GameClient/GameFont.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameWindow.h", Game.CORE, "GameEngine/Include/GameClient/GameWindow.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameWindowGlobal.h", Game.CORE, "GameEngine/Include/GameClient/GameWindowGlobal.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameWindowTransitions.h", Game.CORE, "GameEngine/Include/GameClient/GameWindowTransitions.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/HeaderTemplate.h", Game.CORE, "GameEngine/Include/GameClient/HeaderTemplate.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/IMEManager.h", Game.CORE, "GameEngine/Include/GameClient/IMEManager.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/LoadScreen.h", Game.CORE, "GameEngine/Include/GameClient/LoadScreen.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/ProcessAnimateWindow.h", Game.CORE, "GameEngine/Include/GameClient/ProcessAnimateWindow.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/WindowLayout.h", Game.CORE, "GameEngine/Include/GameClient/WindowLayout.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/WinInstanceData.h", Game.CORE, "GameEngine/Include/GameClient/WinInstanceData.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameFont.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameFont.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameWindow.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameWindow.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameWindowGlobal.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameWindowTransitions.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/HeaderTemplate.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/IMEManager.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/IMEManager.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/LoadScreen.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/LoadScreen.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/ProcessAnimateWindow.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/WindowLayout.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/WindowLayout.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/WinInstanceData.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/WinInstanceData.cpp")
+
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/ClientInstance.h", Game.CORE, "GameEngine/Include/GameClient/ClientInstance.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/Color.h", Game.CORE, "GameEngine/Include/GameClient/Color.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/Credits.h", Game.CORE, "GameEngine/Include/GameClient/Credits.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/DisplayString.h", Game.CORE, "GameEngine/Include/GameClient/DisplayString.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/DisplayStringManager.h", Game.CORE, "GameEngine/Include/GameClient/DisplayStringManager.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/DrawGroupInfo.h", Game.CORE, "GameEngine/Include/GameClient/DrawGroupInfo.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/FXList.h", Game.CORE, "GameEngine/Include/GameClient/FXList.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameText.h", Game.CORE, "GameEngine/Include/GameClient/GameText.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GlobalLanguage.h", Game.CORE, "GameEngine/Include/GameClient/GlobalLanguage.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GraphDraw.h", Game.CORE, "GameEngine/Include/GameClient/GraphDraw.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/LanguageFilter.h", Game.CORE, "GameEngine/Include/GameClient/LanguageFilter.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/Line2D.h", Game.CORE, "GameEngine/Include/GameClient/Line2D.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/RadiusDecal.h", Game.CORE, "GameEngine/Include/GameClient/RadiusDecal.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/SelectionInfo.h", Game.CORE, "GameEngine/Include/GameClient/SelectionInfo.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/Statistics.h", Game.CORE, "GameEngine/Include/GameClient/Statistics.h")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/ClientInstance.cpp", Game.CORE, "GameEngine/Source/GameClient/ClientInstance.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/Color.cpp", Game.CORE, "GameEngine/Source/GameClient/Color.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/Credits.cpp", Game.CORE, "GameEngine/Source/GameClient/Credits.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/DisplayString.cpp", Game.CORE, "GameEngine/Source/GameClient/DisplayString.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/DisplayStringManager.cpp", Game.CORE, "GameEngine/Source/GameClient/DisplayStringManager.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/DrawGroupInfo.cpp", Game.CORE, "GameEngine/Source/GameClient/DrawGroupInfo.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/FXList.cpp", Game.CORE, "GameEngine/Source/GameClient/FXList.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GameText.cpp", Game.CORE, "GameEngine/Source/GameClient/GameText.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GlobalLanguage.cpp", Game.CORE, "GameEngine/Source/GameClient/GlobalLanguage.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GraphDraw.cpp", Game.CORE, "GameEngine/Source/GameClient/GraphDraw.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/LanguageFilter.cpp", Game.CORE, "GameEngine/Source/GameClient/LanguageFilter.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/Line2D.cpp", Game.CORE, "GameEngine/Source/GameClient/Line2D.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/RadiusDecal.cpp", Game.CORE, "GameEngine/Source/GameClient/RadiusDecal.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/SelectionInfo.cpp", Game.CORE, "GameEngine/Source/GameClient/SelectionInfo.cpp")
+ #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/Statistics.cpp", Game.CORE, "GameEngine/Source/GameClient/Statistics.cpp")
+
return
diff --git a/scripts/docker-build.sh b/scripts/docker-build.sh
index 46acd855bdf..b6c9e54d170 100755
--- a/scripts/docker-build.sh
+++ b/scripts/docker-build.sh
@@ -128,6 +128,17 @@ build_docker_image() {
print_success "Docker image ready"
}
+fix_compile_commands() {
+ local fix_script="$SCRIPT_DIR/fix_compile_commands.py"
+ if [[ -f "$fix_script" ]] && command -v python3 &>/dev/null; then
+ # Only run if compile_commands.json exists in the build dir
+ if [[ -f "$BUILD_DIR/compile_commands.json" ]]; then
+ print_info "Fixing compile_commands.json for host environment..."
+ python3 "$fix_script" || print_warning "Failed to fix compile_commands.json"
+ fi
+ fi
+}
+
run_build() {
local force_cmake="$1"
local target="$2"
@@ -266,6 +277,7 @@ build_docker_image
run_build "$FORCE_CMAKE" "$TARGET" "$INTERACTIVE"
if [[ "$INTERACTIVE" != "true" ]]; then
+ fix_compile_commands
list_outputs
echo ""
diff --git a/scripts/fix_compile_commands.py b/scripts/fix_compile_commands.py
new file mode 100755
index 00000000000..9db4e3d1e25
--- /dev/null
+++ b/scripts/fix_compile_commands.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+# Copyright 2026 TheSuperHackers
+#
+# This file is part of Command & Conquer: Generals and Command & Conquer: Zero Hour.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+Compile commands fixer for Linux development.
+
+This script makes the compile_commands.json generated by the Docker build
+usable on the Linux host by:
+- Rewriting container paths (/build/cnc) to host absolute paths.
+- Converting Windows backslashes to forward slashes.
+- Stripping Wine drive letters (Z:).
+"""
+
+import json
+import os
+import sys
+
+def fix_path(path, root_dir):
+ # Normalize path separators
+ path = path.replace('\\', '/')
+
+ # Remove drive letter if present
+ if len(path) > 1 and path[1] == ':':
+ path = path[2:]
+
+ # Replace the container mount point with the host root directory
+ # The container mounts the project at /build/cnc
+ if path.startswith('/build/cnc'):
+ return os.path.join(root_dir, path[len('/build/cnc'):].lstrip('/'))
+
+ return path
+
+def main():
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ project_root = os.path.dirname(script_dir)
+
+ build_dir = os.path.join(project_root, 'build', 'docker')
+ input_file = os.path.join(build_dir, 'compile_commands.json')
+ output_file = os.path.join(project_root, 'compile_commands.json')
+
+ if not os.path.exists(input_file):
+ print(f"Error: {input_file} not found. Please run the docker build first.")
+ sys.exit(1)
+
+ print(f"Reading from: {input_file}")
+
+ with open(input_file, 'r') as f:
+ data = json.load(f)
+
+ for entry in data:
+ # Fix directory
+ if 'directory' in entry:
+ entry['directory'] = fix_path(entry['directory'], project_root)
+
+ # Fix file
+ if 'file' in entry:
+ entry['file'] = fix_path(entry['file'], project_root)
+
+ # Fix command
+ if 'command' in entry:
+ command = entry['command']
+
+ # Normalize to forward slashes.
+ command = command.replace('\\', '/')
+
+ # Replace container path with host project root.
+ command = command.replace('/build/cnc', project_root)
+
+ # Handle potential drive letter artifacts from Wine (Z:/build/cnc).
+ command = command.replace('Z:/build/cnc', project_root)
+ command = command.replace('z:/build/cnc', project_root)
+
+ # Strip remaining drive letters from tools (e.g., Z:/build/tools/...).
+ command = command.replace('Z:', '')
+ command = command.replace('z:', '')
+
+ entry['command'] = command
+
+ print(f"Writing to: {output_file}")
+ with open(output_file, 'w') as f:
+ json.dump(data, f, indent=2)
+
+ print("Done. compile_commands.json is now ready for use.")
+
+if __name__ == '__main__':
+ main()