diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt
index 1b8148e289..faebd73f6c 100644
--- a/Core/GameEngine/CMakeLists.txt
+++ b/Core/GameEngine/CMakeLists.txt
@@ -81,7 +81,7 @@ set(GAMEENGINE_SRC
# Include/Common/Money.h
# Include/Common/MultiplayerSettings.h
# Include/Common/NameKeyGenerator.h
-# Include/Common/ObjectStatusTypes.h
+ Include/Common/ObjectStatusTypes.h
# Include/Common/OSDisplay.h
# Include/Common/Overridable.h
# Include/Common/Override.h
@@ -94,7 +94,7 @@ set(GAMEENGINE_SRC
# Include/Common/ProductionPrerequisite.h
# Include/Common/QuickmatchPreferences.h
# Include/Common/QuotedPrintable.h
-# Include/Common/Radar.h
+ Include/Common/Radar.h
Include/Common/RAMFile.h
Include/Common/RandomValue.h
# Include/Common/Recorder.h
@@ -660,9 +660,9 @@ set(GAMEENGINE_SRC
# Source/Common/System/List.cpp
Source/Common/System/LocalFile.cpp
Source/Common/System/LocalFileSystem.cpp
-# Source/Common/System/ObjectStatusTypes.cpp
+ Source/Common/System/ObjectStatusTypes.cpp
# Source/Common/System/QuotedPrintable.cpp
-# Source/Common/System/Radar.cpp
+ Source/Common/System/Radar.cpp
Source/Common/System/RAMFile.cpp
# Source/Common/System/registry.cpp
# Source/Common/System/SaveGame/GameState.cpp
diff --git a/GeneralsMD/Code/GameEngine/Include/Common/ObjectStatusTypes.h b/Core/GameEngine/Include/Common/ObjectStatusTypes.h
similarity index 97%
rename from GeneralsMD/Code/GameEngine/Include/Common/ObjectStatusTypes.h
rename to Core/GameEngine/Include/Common/ObjectStatusTypes.h
index df19b3743e..affa254c9e 100644
--- a/GeneralsMD/Code/GameEngine/Include/Common/ObjectStatusTypes.h
+++ b/Core/GameEngine/Include/Common/ObjectStatusTypes.h
@@ -70,6 +70,9 @@ enum ObjectStatusTypes CPP_11(: Int)
OBJECT_STATUS_NO_ATTACK_FROM_AI, ///< attacking this object may not be done from commandSource == CMD_FROM_AI
OBJECT_STATUS_IGNORING_STEALTH, ///< temporarily ignoring all stealth bits. (used only for some special-case mine clearing stuff.)
OBJECT_STATUS_IS_CARBOMB, ///< Object is now a carbomb.
+
+ // TheSuperHackers @info New statuses added in Zero Hour
+ // Note: Loading old save games that do not track these flags in objects will not recover them. Expect logic bugs.
OBJECT_STATUS_DECK_HEIGHT_OFFSET, ///< Object factors deck height on top of ground altitude.
OBJECT_STATUS_RIDER1,
OBJECT_STATUS_RIDER2,
diff --git a/Generals/Code/GameEngine/Include/Common/Radar.h b/Core/GameEngine/Include/Common/Radar.h
similarity index 99%
rename from Generals/Code/GameEngine/Include/Common/Radar.h
rename to Core/GameEngine/Include/Common/Radar.h
index 902cc24392..83f779247c 100644
--- a/Generals/Code/GameEngine/Include/Common/Radar.h
+++ b/Core/GameEngine/Include/Common/Radar.h
@@ -1,5 +1,5 @@
/*
-** Command & Conquer Generals(tm)
+** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/ObjectStatusTypes.cpp b/Core/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
similarity index 97%
rename from GeneralsMD/Code/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
rename to Core/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
index 8b07bbc5a9..ab689ad343 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
+++ b/Core/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
@@ -64,6 +64,7 @@ const char* const ObjectStatusMaskType::s_bitNameList[] =
"NO_ATTACK_FROM_AI",
"IGNORING_STEALTH",
"IS_CARBOMB",
+ // TheSuperHackers @info New statuses added in Zero Hour
"DECK_HEIGHT_OFFSET",
"STATUS_RIDER1",
"STATUS_RIDER2",
diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/Radar.cpp b/Core/GameEngine/Source/Common/System/Radar.cpp
similarity index 99%
rename from GeneralsMD/Code/GameEngine/Source/Common/System/Radar.cpp
rename to Core/GameEngine/Source/Common/System/Radar.cpp
index 22e79e4b6a..8883f247e0 100644
--- a/GeneralsMD/Code/GameEngine/Source/Common/System/Radar.cpp
+++ b/Core/GameEngine/Source/Common/System/Radar.cpp
@@ -362,15 +362,15 @@ void Radar::newMap( TerrainLogic *terrain )
m_waterAverageZ = 0.0f;
Coord3D worldPoint;
- // since we're averaging let's skip every second sample...
- worldPoint.y=0;
+ // since we're averaging let's skip every second sample...
+ worldPoint.y=0;
for( y = 0; y < RADAR_CELL_HEIGHT; y+=2, worldPoint.y+=2.0*m_ySample )
- {
- worldPoint.x=0;
- for( x = 0; x < RADAR_CELL_WIDTH; x+=2, worldPoint.x+=2.0*m_xSample )
+ {
+ worldPoint.x=0;
+ for( x = 0; x < RADAR_CELL_WIDTH; x+=2, worldPoint.x+=2.0*m_xSample )
{
// don't use this, we don't really need the
- // Z position by this function... radarToWorld( &radarPoint, &worldPoint );
+ // Z position by this function... radarToWorld( &radarPoint, &worldPoint );
// and this is done by isUnderwater anyway: z = terrain->getGroundHeight( worldPoint.x, worldPoint.y );
Real z,waterZ;
if( terrain->isUnderwater( worldPoint.x, worldPoint.y, &waterZ, &z ) )
@@ -383,9 +383,8 @@ void Radar::newMap( TerrainLogic *terrain )
m_terrainAverageZ += z;
terrainSamples++;
}
-
}
- }
+ }
// avoid divide by zeros
if( terrainSamples == 0 )
@@ -436,7 +435,7 @@ RadarObjectType Radar::addObject( Object *obj )
//Because we have support for disguised units pretending to be units from another
//team, we need to intercept it here and make sure it's rendered appropriately
//based on which client is rendering it.
- StealthUpdate *update = obj->getStealth();
+ StealthUpdate *update = obj->getStealth();
if( update )
{
if( update->isDisguised() )
@@ -1506,7 +1505,7 @@ void Radar::xfer( Xfer *xfer )
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
-
+
if (version <= 1)
{
const Int localPlayerIndex = ThePlayerList->getLocalPlayer()->getPlayerIndex();
diff --git a/Core/GameEngineDevice/CMakeLists.txt b/Core/GameEngineDevice/CMakeLists.txt
index 404c1eb60e..1de9abd7d9 100644
--- a/Core/GameEngineDevice/CMakeLists.txt
+++ b/Core/GameEngineDevice/CMakeLists.txt
@@ -4,7 +4,7 @@ set(GAMEENGINEDEVICE_SRC
# Include/W3DDevice/Common/W3DConvert.h
# Include/W3DDevice/Common/W3DFunctionLexicon.h
# Include/W3DDevice/Common/W3DModuleFactory.h
-# Include/W3DDevice/Common/W3DRadar.h
+ Include/W3DDevice/Common/W3DRadar.h
# Include/W3DDevice/Common/W3DThingFactory.h
# Include/W3DDevice/GameClient/BaseHeightMap.h
# Include/W3DDevice/GameClient/camerashakesystem.h
@@ -93,7 +93,7 @@ set(GAMEENGINEDEVICE_SRC
Source/MilesAudioDevice/MilesAudioManager.cpp
Source/VideoDevice/Bink/BinkVideoPlayer.cpp
# Source/W3DDevice/Common/System/W3DFunctionLexicon.cpp
-# Source/W3DDevice/Common/System/W3DRadar.cpp
+ Source/W3DDevice/Common/System/W3DRadar.cpp
# Source/W3DDevice/Common/Thing/W3DModuleFactory.cpp
# Source/W3DDevice/Common/Thing/W3DThingFactory.cpp
# Source/W3DDevice/Common/W3DConvert.cpp
diff --git a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h b/Core/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h
similarity index 100%
rename from GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h
rename to Core/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h
diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp b/Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
similarity index 99%
rename from GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
rename to Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
index 7516211b1c..be576da841 100644
--- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
+++ b/Core/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
@@ -890,8 +890,8 @@ void W3DRadar::init( void )
DEBUG_ASSERTCRASH( m_overlayTexture, ("W3DRadar: Unable to allocate overlay texture") );
// set filter type for the overlay texture, try it and see if you like it, I don't ;)
-// m_overlayTexture->Set_Min_Filter( TextureClass::FILTER_TYPE_NONE );
-// m_overlayTexture->Set_Mag_Filter( TextureClass::FILTER_TYPE_NONE );
+// m_overlayTexture->Set_Min_Filter( TextureFilterClass::FILTER_TYPE_NONE );
+// m_overlayTexture->Set_Mag_Filter( TextureFilterClass::FILTER_TYPE_NONE );
// allocate our shroud texture
m_shroudTexture = MSGNEW("TextureClass") TextureClass( m_textureWidth, m_textureHeight,
@@ -1136,7 +1136,7 @@ void W3DRadar::buildTerrainTexture( TerrainLogic *terrain )
radarToWorld2D( &radarPoint, &worldPoint );
// get color for this Z and add to our sample color
- Real underwaterZ;
+ Real underwaterZ;
if( terrain->isUnderwater( worldPoint.x, worldPoint.y, NULL, &underwaterZ ) )
{
// this is our "color" for water
@@ -1544,7 +1544,7 @@ void W3DRadar::refreshObjects()
// they are godlike and can see everything)
//
if( obj->getRadarPriority() == RADAR_PRIORITY_LOCAL_UNIT_ONLY &&
- obj->getControllingPlayer() != player &&
+ obj->getControllingPlayer() != player &&
player->isPlayerActive() )
continue;
diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt
index a9395f9b12..01912ede6e 100644
--- a/Generals/Code/GameEngine/CMakeLists.txt
+++ b/Generals/Code/GameEngine/CMakeLists.txt
@@ -74,7 +74,7 @@ set(GAMEENGINE_SRC
Include/Common/Money.h
Include/Common/MultiplayerSettings.h
Include/Common/NameKeyGenerator.h
- Include/Common/ObjectStatusTypes.h
+# Include/Common/ObjectStatusTypes.h
Include/Common/OSDisplay.h
Include/Common/Overridable.h
Include/Common/Override.h
@@ -87,7 +87,7 @@ set(GAMEENGINE_SRC
Include/Common/ProductionPrerequisite.h
Include/Common/QuickmatchPreferences.h
Include/Common/QuotedPrintable.h
- Include/Common/Radar.h
+# Include/Common/Radar.h
# Include/Common/RAMFile.h
# Include/Common/RandomValue.h
Include/Common/Recorder.h
@@ -610,9 +610,9 @@ set(GAMEENGINE_SRC
# Source/Common/System/LocalFile.cpp
# Source/Common/System/LocalFileSystem.cpp
#Source/Common/System/MemoryInit.cpp
- Source/Common/System/ObjectStatusTypes.cpp
+# Source/Common/System/ObjectStatusTypes.cpp
Source/Common/System/QuotedPrintable.cpp
- Source/Common/System/Radar.cpp
+# Source/Common/System/Radar.cpp
# Source/Common/System/RAMFile.cpp
Source/Common/System/registry.cpp
Source/Common/System/SaveGame/GameState.cpp
diff --git a/Generals/Code/GameEngine/Include/Common/ObjectStatusTypes.h b/Generals/Code/GameEngine/Include/Common/ObjectStatusTypes.h
deleted file mode 100644
index f443ad0ac7..0000000000
--- a/Generals/Code/GameEngine/Include/Common/ObjectStatusTypes.h
+++ /dev/null
@@ -1,124 +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: ObjectStatusTypes.h /////////////////////////////////////////////////////////////////////////
-// Author: Kris, May 2003
-// Desc: Object status types that are stackable using the BitSet system. Used to be ObjectStatusBits
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "Common/BitFlags.h"
-#include "Common/BitFlagsIO.h"
-
-//-------------------------------------------------------------------------------------------------
-/** Object status types */
-//-------------------------------------------------------------------------------------------------
-enum ObjectStatusTypes CPP_11(: Int)
-{
- //These are saved. Do not insert or remove any!
-
- OBJECT_STATUS_NONE, ///< no status bit
- OBJECT_STATUS_DESTROYED, ///< has been destroyed, pending delete
- OBJECT_STATUS_CAN_ATTACK, ///< used by garrissoned buildings, is OR'ed with KINDOF_CAN_ATTACK in isAbleToAttack()
- OBJECT_STATUS_UNDER_CONSTRUCTION, ///< object is being constructed and is not yet complete
- OBJECT_STATUS_UNSELECTABLE, ///< This is a negative condition since these statuses are overrides. ie their presence forces the condition, but their absence means nothing
- OBJECT_STATUS_NO_COLLISIONS, ///< object should be ignored for object-object collisions (but not object-ground); used for thing like collapsing parachutes that are intangible
- OBJECT_STATUS_NO_ATTACK, ///< Absolute override to being able to attack
- OBJECT_STATUS_AIRBORNE_TARGET, ///< InTheAir as far as AntiAir weapons are concerned only.
- OBJECT_STATUS_PARACHUTING, ///< object is on a parachute
- OBJECT_STATUS_REPULSOR, ///< object repulses "KINDOF_CAN_BE_REPULSED" objects.
- OBJECT_STATUS_HIJACKED, ///< unit is in the possesion of an enemy criminal, call the authorities
- OBJECT_STATUS_AFLAME, ///< This object is on fire.
- OBJECT_STATUS_BURNED, ///< This object has already burned as much as it can.
- OBJECT_STATUS_WET, ///< object has been soaked with water
- OBJECT_STATUS_IS_FIRING_WEAPON, ///< Object is firing a weapon, now. Not true for special attacks. --Lorenzen
- OBJECT_STATUS_BRAKING, ///< Object is braking, and subverts the physics.
- OBJECT_STATUS_STEALTHED, ///< Object is currently "stealthed"
- OBJECT_STATUS_DETECTED, ///< Object is in range of a stealth-detector unit (meaningless if STEALTHED not set)
- OBJECT_STATUS_CAN_STEALTH, ///< Object has ability to stealth allowing the stealth update module to run.
- OBJECT_STATUS_SOLD, ///< Object is being sold
- OBJECT_STATUS_UNDERGOING_REPAIR, ///< Object is awaiting/undergoing a repair order that has been issued
- OBJECT_STATUS_RECONSTRUCTING, ///< Reconstructing
- OBJECT_STATUS_MASKED, ///< Masked objects are not selectable and targetable by players or AI
- OBJECT_STATUS_IS_ATTACKING, ///< Object is in the general Attack state (incl. aim, approach, etc.). Note that IS_FIRING_WEAPON and IS_AIMING_WEAPON is a subset of this!
- OBJECT_STATUS_IS_USING_ABILITY, ///< Object is in the process of preparing or firing a special ability.
- OBJECT_STATUS_IS_AIMING_WEAPON, ///< Object is aiming a weapon, now. Not true for special attacks.
- OBJECT_STATUS_NO_ATTACK_FROM_AI, ///< attacking this object may not be done from commandSource == CMD_FROM_AI
- OBJECT_STATUS_IGNORING_STEALTH, ///< temporarily ignoring all stealth bits. (used only for some special-case mine clearing stuff.)
- OBJECT_STATUS_IS_CARBOMB, ///< Object is now a carbomb.
- // add more status types here and don't forget to add to the string table ObjectStatusMaskType::s_bitNameList[]
-
- OBJECT_STATUS_COUNT
-
-};
-
-typedef BitFlags ObjectStatusMaskType;
-
-#define MAKE_OBJECT_STATUS_MASK(k) ObjectStatusMaskType(ObjectStatusMaskType::kInit, (k))
-#define MAKE_OBJECT_STATUS_MASK2(k,a) ObjectStatusMaskType(ObjectStatusMaskType::kInit, (k), (a))
-#define MAKE_OBJECT_STATUS_MASK3(k,a,b) ObjectStatusMaskType(ObjectStatusMaskType::kInit, (k), (a), (b))
-#define MAKE_OBJECT_STATUS_MASK4(k,a,b,c) ObjectStatusMaskType(ObjectStatusMaskType::kInit, (k), (a), (b), (c))
-#define MAKE_OBJECT_STATUS_MASK5(k,a,b,c,d) ObjectStatusMaskType(ObjectStatusMaskType::kInit, (k), (a), (b), (c), (d))
-
-inline Bool TEST_OBJECT_STATUS_MASK( const ObjectStatusMaskType& m, ObjectStatusTypes t )
-{
- return m.test( t );
-}
-
-inline Bool TEST_OBJECT_STATUS_MASK_ANY( const ObjectStatusMaskType& m, const ObjectStatusMaskType& mask )
-{
- return m.anyIntersectionWith( mask );
-}
-
-inline Bool TEST_OBJECT_STATUS_MASK_MULTI( const ObjectStatusMaskType& m, const ObjectStatusMaskType& mustBeSet, const ObjectStatusMaskType& mustBeClear )
-{
- return m.testSetAndClear( mustBeSet, mustBeClear );
-}
-
-inline Bool OBJECT_STATUS_MASK_ANY_SET( const ObjectStatusMaskType& m)
-{
- return m.any();
-}
-
-inline void CLEAR_OBJECT_STATUS_MASK( ObjectStatusMaskType& m )
-{
- m.clear();
-}
-
-inline void SET_ALL_OBJECT_STATUS_MASK_BITS( ObjectStatusMaskType& m )
-{
- m.clear( );
- m.flip( );
-}
-
-inline void FLIP_OBJECT_STATUS_MASK( ObjectStatusMaskType& m )
-{
- m.flip();
-}
-
-// defined in Common/System/ObjectStatusTypes.cpp
-extern ObjectStatusMaskType OBJECT_STATUS_MASK_NONE; // inits to all zeroes
diff --git a/Generals/Code/GameEngine/Source/Common/System/ObjectStatusTypes.cpp b/Generals/Code/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
deleted file mode 100644
index 01dff2c26b..0000000000
--- a/Generals/Code/GameEngine/Source/Common/System/ObjectStatusTypes.cpp
+++ /dev/null
@@ -1,71 +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: ObjectStatusTypes.cpp ////////////////////////////////////////////////////////////////////
-// Author: Kris, May 2003
-// Desc: Object status types that are stackable using the BitSet system. Used to be ObjectStatusBits
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "PreRTS.h"
-
-#include "Common/ObjectStatusTypes.h"
-#include "Common/BitFlagsIO.h"
-
-template<>
-const char* const ObjectStatusMaskType::s_bitNameList[] =
-{
- "NONE",
- "DESTROYED",
- "CAN_ATTACK",
- "UNDER_CONSTRUCTION",
- "UNSELECTABLE",
- "NO_COLLISIONS",
- "NO_ATTACK",
- "AIRBORNE_TARGET",
- "PARACHUTING",
- "REPULSOR",
- "HIJACKED",
- "AFLAME",
- "BURNED",
- "WET",
- "IS_FIRING_WEAPON",
- "IS_BRAKING",
- "STEALTHED",
- "DETECTED",
- "CAN_STEALTH",
- "SOLD",
- "UNDERGOING_REPAIR",
- "RECONSTRUCTING",
- "MASKED",
- "IS_ATTACKING",
- "USING_ABILITY",
- "IS_AIMING_WEAPON",
- "NO_ATTACK_FROM_AI",
- "IGNORING_STEALTH",
- "IS_CARBOMB",
- NULL
-};
-static_assert(ARRAY_SIZE(ObjectStatusMaskType::s_bitNameList) == ObjectStatusMaskType::NumBits + 1, "Incorrect array size");
-
-ObjectStatusMaskType OBJECT_STATUS_MASK_NONE; // inits to all zeroes
diff --git a/Generals/Code/GameEngine/Source/Common/System/Radar.cpp b/Generals/Code/GameEngine/Source/Common/System/Radar.cpp
deleted file mode 100644
index 5c33ab13ed..0000000000
--- a/Generals/Code/GameEngine/Source/Common/System/Radar.cpp
+++ /dev/null
@@ -1,1606 +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: Radar.cpp ////////////////////////////////////////////////////////////////////////////////
-// Author: Colin Day, January 2002
-// Desc: Radar logic implementation
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
-
-#include "Common/GameAudio.h"
-#include "Common/GameState.h"
-#include "Common/GameUtility.h"
-#include "Common/MiscAudio.h"
-#include "Common/Radar.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-#include "Common/ThingTemplate.h"
-#include "Common/GlobalData.h"
-#include "Common/Xfer.h"
-
-#include "GameClient/Drawable.h"
-#include "GameClient/Eva.h"
-#include "GameClient/GameWindowManager.h"
-#include "GameClient/InGameUI.h"
-#include "GameClient/ControlBar.h"
-
-#include "GameLogic/GameLogic.h"
-#include "GameLogic/Object.h"
-#include "GameLogic/PartitionManager.h"
-#include "GameLogic/TerrainLogic.h"
-#include "GameLogic/Module/ContainModule.h"
-#include "GameLogic/Module/StealthUpdate.h"
-
-
-// GLOBALS ////////////////////////////////////////////////////////////////////////////////////////
-Radar *TheRadar = NULL; ///< the radar global singleton
-
-// PRIVATE ////////////////////////////////////////////////////////////////////////////////////////
-#define RADAR_QUEUE_TERRAIN_REFRESH_DELAY (LOGICFRAMES_PER_SECOND * 3.0f)
-
-//-------------------------------------------------------------------------------------------------
-/** Delete list resources used by the radar and return them to the memory pools */
-//-------------------------------------------------------------------------------------------------
-void Radar::deleteListResources( void )
-{
- RadarObject *nextObject;
-
- // delete entries from the local object list
- while( m_localObjectList )
- {
-
- // get next object
- nextObject = m_localObjectList->friend_getNext();
-
- // remove radar data from object
- m_localObjectList->friend_getObject()->friend_setRadarData( NULL );
-
- // delete the head of the list
- deleteInstance(m_localObjectList);
-
- // set head of the list to the next object
- m_localObjectList = nextObject;
-
- }
-
- // delete entries from the regular object list
- while( m_objectList )
- {
-
- // get next object
- nextObject = m_objectList->friend_getNext();
-
- // remove radar data from object
- m_objectList->friend_getObject()->friend_setRadarData( NULL );
-
- // delete the head of the list
- deleteInstance(m_objectList);
-
- // set head of the list to the next object
- m_objectList = nextObject;
-
- }
-
- Object *obj;
- for( obj = TheGameLogic->getFirstObject(); obj; obj = obj->getNextObject() )
- {
-
- DEBUG_ASSERTCRASH( obj->friend_getRadarData() == NULL, ("oops") );
-
- }
-
-}
-
-// PUBLIC METHODS /////////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-RadarObject::RadarObject( void )
-{
-
- m_object = NULL;
- m_next = NULL;
- m_color = GameMakeColor( 255, 255, 255, 255 );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-RadarObject::~RadarObject( void )
-{
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Bool RadarObject::isTemporarilyHidden() const
-{
- return isTemporarilyHidden(m_object);
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Bool RadarObject::isTemporarilyHidden(const Object* obj)
-{
- Drawable* draw = obj->getDrawable();
- if (draw == NULL || draw->getStealthLook() == STEALTHLOOK_INVISIBLE || draw->isDrawableEffectivelyHidden())
- return true;
-
- return false;
-}
-
-// ------------------------------------------------------------------------------------------------
-/** CRC */
-// ------------------------------------------------------------------------------------------------
-void RadarObject::crc( Xfer *xfer )
-{
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Xfer method
- * Version Info:
- * 1: Initial version */
-// ------------------------------------------------------------------------------------------------
-void RadarObject::xfer( Xfer *xfer )
-{
-
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
-
- // object id
- ObjectID objectID = m_object ? m_object->getID() : INVALID_ID;
- xfer->xferObjectID( &objectID );
- if( xfer->getXferMode() == XFER_LOAD )
- {
-
- // find the object and save
- m_object = TheGameLogic->findObjectByID( objectID );
- if( m_object == NULL )
- {
-
- DEBUG_CRASH(( "RadarObject::xfer - Unable to find object for radar data" ));
- throw SC_INVALID_DATA;
-
- }
-
- // tell the object we now have some radar data
- m_object->friend_setRadarData( this );
-
- }
-
- // color
- xfer->xferColor( &m_color );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Load post process */
-// ------------------------------------------------------------------------------------------------
-void RadarObject::loadPostProcess( void )
-{
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Radar::Radar( void )
-{
-
- m_radarWindow = NULL;
- m_objectList = NULL;
- m_localObjectList = NULL;
- 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;
- m_waterAverageZ = 0.0f;
- m_xSample = 0.0f;
- m_ySample = 0.0f;
- m_mapExtent.lo.x = 0.0f;
- m_mapExtent.lo.y = 0.0f;
- m_mapExtent.lo.z = 0.0f;
- m_mapExtent.hi.x = 0.0f;
- m_mapExtent.hi.y = 0.0f;
- m_mapExtent.hi.z = 0.0f;
- m_queueTerrainRefreshFrame = 0;
-
- // clear the radar events
- clearAllEvents();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-Radar::~Radar( void )
-{
-
- // delete list resources
- deleteListResources();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Clear all radar events */
-//-------------------------------------------------------------------------------------------------
-void Radar::clearAllEvents( void )
-{
-
- // set next free index to the first one
- m_nextFreeRadarEvent = 0;
- m_lastRadarEvent = -1;
-
- // zero out all data
- for( Int i = 0; i < MAX_RADAR_EVENTS; ++i )
- {
-
- m_event[ i ].type = RADAR_EVENT_INVALID;
- m_event[ i ].active = FALSE;
- m_event[ i ].createFrame = 0;
- m_event[ i ].dieFrame = 0;
- m_event[ i ].fadeFrame = 0;
- m_event[ i ].color1.red = 0;
- m_event[ i ].color1.green = 0;
- m_event[ i ].color1.blue = 0;
- m_event[ i ].color2.red = 0;
- m_event[ i ].color2.green = 0;
- m_event[ i ].color2.blue = 0;
- m_event[ i ].worldLoc.x = 0.0f;
- m_event[ i ].worldLoc.y = 0.0f;
- m_event[ i ].worldLoc.z = 0.0f;
- m_event[ i ].radarLoc.x = 0;
- m_event[ i ].radarLoc.y = 0;
- m_event[ i ].soundPlayed = FALSE;
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset radar data */
-//-------------------------------------------------------------------------------------------------
-void Radar::reset( void )
-{
-
- // delete list resources
- deleteListResources();
-
- // clear all events
- clearAllEvents();
-
- // TheSuperHackers @todo Reset m_radarHidden?
- //std::fill(m_radarHidden, m_radarHidden + ARRAY_SIZE(m_radarHidden), false);
-
- // stop forcing the radar on
- std::fill(m_radarForceOn, m_radarForceOn + ARRAY_SIZE(m_radarForceOn), false);
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Radar per frame update */
-//-------------------------------------------------------------------------------------------------
-void Radar::update( void )
-{
- Int i;
- UnsignedInt thisFrame = TheGameLogic->getFrame();
-
- //
- // traverse the radar event list, if an event has a creationFrame it means that it
- // exists ... check to see if it's time for that event to die and if so, just clear
- // out the active status
- //
- for( i = 0; i < MAX_RADAR_EVENTS; i++ )
- {
-
- if( m_event[ i ].active == TRUE && m_event[ i ].createFrame &&
- thisFrame > m_event[ i ].dieFrame )
- m_event[ i ].active = FALSE;
-
- }
-
- // see if we should refresh the terrain
- if( m_queueTerrainRefreshFrame != 0 &&
- TheGameLogic->getFrame() - m_queueTerrainRefreshFrame > RADAR_QUEUE_TERRAIN_REFRESH_DELAY )
- {
-
- // refresh the terrain
- refreshTerrain( TheTerrainLogic );
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset the radar for the new map data being given to it */
-//-------------------------------------------------------------------------------------------------
-void Radar::newMap( TerrainLogic *terrain )
-{
-
- // keep a pointer for our radar window
- Int id = NAMEKEY( "ControlBar.wnd:LeftHUD" );
- m_radarWindow = TheWindowManager->winGetWindowFromId( NULL, id );
- DEBUG_ASSERTCRASH( m_radarWindow, ("Radar::newMap - Unable to find radar game window") );
-
- // reset all the data in the radar
- reset();
-
- // get the extents of the new map
- terrain->getExtent( &m_mapExtent );
-
- // we will sample at these intervals across the map
- m_xSample = m_mapExtent.width() / RADAR_CELL_WIDTH;
- m_ySample = m_mapExtent.height() / RADAR_CELL_HEIGHT;
-
- // find the "middle" height for the terrain (most used value) and water table
- Int x, y, z;
- Int terrainSamples = 0, waterSamples = 0;
-
- m_terrainAverageZ = 0.0f;
- m_waterAverageZ = 0.0f;
- ICoord2D radarPoint;
- Coord3D worldPoint;
- for( y = 0; y < RADAR_CELL_HEIGHT; y++ )
- for( x = 0; x < RADAR_CELL_WIDTH; x++ )
- {
-
- radarPoint.x = x;
- radarPoint.y = y;
- radarToWorld( &radarPoint, &worldPoint );
- z = terrain->getGroundHeight( worldPoint.x, worldPoint.y );
- Real waterZ;
- if( terrain->isUnderwater( worldPoint.x, worldPoint.y, &waterZ ) )
- {
- m_waterAverageZ += z;
- waterSamples++;
- }
- else
- {
- m_terrainAverageZ += z;
- terrainSamples++;
- }
-
- }
-
- // avoid divide by zeros
- if( terrainSamples == 0 )
- terrainSamples = 1;
- if( waterSamples == 0 )
- waterSamples = 1;
-
- // compute averages
- m_terrainAverageZ = m_terrainAverageZ / INT_TO_REAL( terrainSamples );
- m_waterAverageZ = m_waterAverageZ / INT_TO_REAL( waterSamples );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Add an object to the radar list. The object will be sorted in the list to be grouped
- * using it's radar priority */
-//-------------------------------------------------------------------------------------------------
-RadarObjectType Radar::addObject( Object *obj )
-{
-
- // get the radar priority for this object
- RadarPriorityType newPriority = obj->getRadarPriority();
- if( isPriorityVisible( newPriority ) == FALSE )
- return RadarObjectType_None;
-
- // if this object is on the radar, remove it in favor of the new add
- RadarObject **list;
- RadarObject *newObj;
-
- // sanity
- DEBUG_ASSERTCRASH( obj->friend_getRadarData() == NULL,
- ("Radar: addObject - non NULL radar data for '%s'",
- obj->getTemplate()->getName().str()) );
-
- // allocate a new object
- newObj = newInstance(RadarObject);
-
- // set the object data
- newObj->friend_setObject( obj );
-
- // set color for this object on the radar
- const Player *player = obj->getControllingPlayer();
- Player *clientPlayer = rts::getObservedOrLocalPlayer();
- Bool useIndicatorColor = true;
-
- if( obj->isKindOf( KINDOF_DISGUISER ) )
- {
- //Because we have support for disguised units pretending to be units from another
- //team, we need to intercept it here and make sure it's rendered appropriately
- //based on which client is rendering it.
- StealthUpdate *update = obj->getStealth();
- if( update )
- {
- if( update->isDisguised() )
- {
- Player *disguisedPlayer = ThePlayerList->getNthPlayer( update->getDisguisedPlayerIndex() );
- if( player->getRelationship( clientPlayer->getDefaultTeam() ) != ALLIES && clientPlayer->isPlayerActive() )
- {
- //Neutrals and enemies will see this disguised unit as the team it's disguised as.
- player = disguisedPlayer;
- if( player )
- useIndicatorColor = false;
- }
- //Otherwise, the color will show up as the team it really belongs to (already set above).
- }
- }
- }
-
- if( obj->getContain() )
- {
- // To handle Stealth garrison, ask containers what color they are drawing with to the local player.
- // Local is okay because radar display is not synced.
- player = obj->getContain()->getApparentControllingPlayer( clientPlayer );
- if( player )
- useIndicatorColor = false;
- }
-
- if( useIndicatorColor || (player == NULL) )
- {
- newObj->setColor( obj->getIndicatorColor() );
- }
- else
- {
- newObj->setColor( player->getPlayerColor() );
- }
-
- // set a chunk of radar data in the object
- obj->friend_setRadarData( newObj );
-
- RadarObjectType objectType;
- //
- // we will put this on either the local object list for objects that belong to the
- // local player, or on the regular object list for all other objects
- //
- if( obj->isLocallyControlled() )
- {
- list = &m_localObjectList;
- objectType = RadarObjectType_Local;
- }
- else
- {
- list = &m_objectList;
- objectType = RadarObjectType_Regular;
- }
-
- // link object to master list at the head of it's priority section
- if( *list == NULL )
- *list = newObj; // trivial case, an empty list
- else
- {
- RadarPriorityType prevPriority, currPriority;
- RadarObject *currObject, *prevObject, *nextObject;
-
- prevObject = NULL;
- prevPriority = RADAR_PRIORITY_INVALID;
- for( currObject = *list; currObject; currObject = nextObject )
- {
-
- // get the next object
- nextObject = currObject->friend_getNext();
-
- // get the priority of this entry in the list (currPriority)
- currPriority = currObject->friend_getObject()->getRadarPriority();
-
- //
- // if there is no previous object, or the previous priority is less than the
- // our new priority, and the current object in the list has a priority
- // higher than our equal to our own we need to be inserted here
- //
- if( (prevObject == NULL || prevPriority < newPriority ) &&
- (currPriority >= newPriority) )
- {
-
- // insert into the list just ahead of currObject
- if( prevObject )
- {
-
- // the new entry next points to what the previous one used to point to
- newObj->friend_setNext( prevObject->friend_getNext() );
-
- // the previous one next now points to the new entry
- prevObject->friend_setNext( newObj );
-
- }
- else
- {
-
- // the new object next points to the current object
- newObj->friend_setNext( currObject );
-
- // new list head is now newObj
- *list = newObj;
-
- }
-
- break; // exit for, stop the insert
-
- }
- else if( nextObject == NULL )
- {
-
- // at the end of the list, put object here
- currObject->friend_setNext( newObj );
-
- }
-
- // our current object is now the previous object
- prevObject = currObject;
- prevPriority = currPriority;
-
- }
-
- }
-
- return objectType;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Try to delete an object from a specific list */
-//-------------------------------------------------------------------------------------------------
-Bool Radar::deleteFromList( Object *obj, RadarObject **list )
-{
- RadarObject *radarObject, *prevObject = NULL;
-
- // find the object in list
- for( radarObject = *list; radarObject; radarObject = radarObject->friend_getNext() )
- {
-
- if( radarObject->friend_getObject() == obj )
- {
-
- // unlink the object from list
- if( prevObject == NULL )
- *list = radarObject->friend_getNext(); // removing head of list
- else
- prevObject->friend_setNext( radarObject->friend_getNext() );
-
- // set the object radar data to NULL
- obj->friend_setRadarData( NULL );
-
- // delete the object instance
- deleteInstance(radarObject);
-
- // all done, object found and deleted
- return TRUE;
-
- }
-
- // save this object as previous one encountered in the list
- prevObject = radarObject;
-
- }
-
- // object was not found in this list
- return FALSE;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Remove an object from the radar, the object may reside in any list */
-//-------------------------------------------------------------------------------------------------
-RadarObjectType Radar::removeObject( Object *obj )
-{
-
- // sanity
- if( obj->friend_getRadarData() == NULL )
- return RadarObjectType_None;
-
- if( deleteFromList( obj, &m_localObjectList ) == TRUE )
- return RadarObjectType_Local;
- else if( deleteFromList( obj, &m_objectList ) == TRUE )
- return RadarObjectType_Regular;
- else
- {
-
- // sanity
- DEBUG_ASSERTCRASH( 0, ("Radar: Tried to remove object '%s' which was not found",
- obj->getTemplate()->getName().str()) );
- return RadarObjectType_None;
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Translate a 2D spot on the radar (from (0,0) to (RADAR_CELL_WIDTH,RADAR_CELL_HEIGHT)
- * to a 3D spot in the world. Does not determine Z value!
- * Return TRUE if the radar points translates to a valid world position
- * Return FALSE if the radar point is not a valid world position */
-//-------------------------------------------------------------------------------------------------
-Bool Radar::radarToWorld2D( const ICoord2D *radar, Coord3D *world )
-{
- Int x, y;
-
- // sanity
- if( radar == NULL || world == NULL )
- return FALSE;
-
- // get the coords
- x = radar->x;
- y = radar->y;
-
- // more sanity
- if( x < 0 )
- x = 0;
- if( x >= RADAR_CELL_WIDTH )
- x = RADAR_CELL_WIDTH - 1;
- if( y < 0 )
- y = 0;
- if( y >= RADAR_CELL_HEIGHT )
- y = RADAR_CELL_HEIGHT - 1;
-
- // translate to world
- world->x = x * m_xSample;
- world->y = y * m_ySample;
- return TRUE;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Translate a 2D spot on the radar (from (0,0) to (RADAR_CELL_WIDTH,RADAR_CELL_HEIGHT)
- * to a 3D spot in the world on the terrain
- * Return TRUE if the radar points translates to a valid world position
- * Return FALSE if the radar point is not a valid world position */
-//-------------------------------------------------------------------------------------------------
-Bool Radar::radarToWorld( const ICoord2D *radar, Coord3D *world )
-{
- if (!radarToWorld2D(radar,world))
- return FALSE;
-
- // find the terrain height here
- world->z = TheTerrainLogic->getGroundHeight( world->x, world->y );
-
- return TRUE; // valid translation
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Translate a point in the world to the 2D radar (x,y)
- * Return TRUE if the world point successfully translates to a radar point
- * Return FALSE if world point is a bogus off the map position */
-//-------------------------------------------------------------------------------------------------
-Bool Radar::worldToRadar( const Coord3D *world, ICoord2D *radar )
-{
-
- // sanity
- if( world == NULL || radar == NULL )
- return FALSE;
-
- // sanity check the world position
-// if( world->x < m_mapExtent.lo.x || world->x > m_mapExtent.hi.x ||
-// world->y < m_mapExtent.lo.y || world->y > m_mapExtent.hi.y )
-// return FALSE;
- // This is actually an insanity check. Nobody uses the return value, so this just leaves garbage in the
- // return pointer. The reason the question gets asked is there are 60 partition cells to 128 radar cells
- // (for example), and the radar wants to draw a horizontal line. This line ends up three pixels long
- // at the right side, so the radar gives up and doesn't draw the middle one.
- // We bind to on radar anyway, and we only ask if we are on radar, so don't intentionally add edge weirdness.
-
- // convert
- radar->x = world->x / m_xSample;
- radar->y = world->y / m_ySample;
-
- // keep it in bounds
- if( radar->x < 0 )
- radar->x = 0;
- if( radar->x >= RADAR_CELL_WIDTH )
- radar->x = RADAR_CELL_WIDTH - 1;
- if( radar->y < 0 )
- radar->y = 0;
- if( radar->y >= RADAR_CELL_HEIGHT )
- radar->y = RADAR_CELL_HEIGHT - 1;
-
- return TRUE; // valid translation
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Translate an actual pixel location (relative pixel with (0,0) being the top left of
- * the radar area) to the "logical" radar coords that would cover the entire area of display
- * on the screen. This is needed because some maps are "long" or "tall" and need a translation
- * to any radar image that has been scaled to preserve the map aspect ratio */
-// ------------------------------------------------------------------------------------------------
-Bool Radar::localPixelToRadar( const ICoord2D *pixel, ICoord2D *radar )
-{
-
- // sanity
- if( pixel == NULL || radar == NULL )
- return FALSE;
-
- // get window size of the radar
- ICoord2D size;
- m_radarWindow->winGetSize( &size.x, &size.y );
-
- //
- // act like we're going to draw and find the aspect ratio adjusted points of the
- // terrain radar positions
- //
- ICoord2D start = { 0, 0 };
- ICoord2D ul, lr;
- findDrawPositions( start.x, start.y, size.x, size.y, &ul, &lr );
-
- // get the scaled width and height
- Int scaledWidth = lr.x - ul.x;
- Int scaledHeight = lr.y - ul.y;
-
- // if the pixel is outsize of the adjusted radar area there are no logical coords
- if( pixel->x < ul.x || pixel->x > lr.x ||
- pixel->y < ul.y || pixel->y > lr.y )
- return FALSE;
-
- if( scaledWidth >= scaledHeight )
- {
-
- // just normal conversion from full stretched to radar cells
- radar->x = (pixel->x - ul.x)* RADAR_CELL_WIDTH / scaledWidth;
-
- // conversion for scaled Y direction in map
- radar->y = REAL_TO_INT( ((pixel->y - ul.y) / INT_TO_REAL( scaledHeight )) * size.y );
-
- //
- // radar->y now refers to a point that was "as if" the map was square, translate to radar
- // note that y is inverted to have the radar align with the world (+x = right, -y = down)
- //
- radar->y = (size.y - radar->y) * RADAR_CELL_HEIGHT / size.y;
-
-
- }
- else
- {
-
- // conversion for scaled Y direction in map
- radar->x = REAL_TO_INT( ((pixel->x - ul.x) / INT_TO_REAL( scaledWidth )) * size.x );
-
- // radar->x now refers to a point that was "as if" the map was square, translate to radar
- radar->x = radar->x * RADAR_CELL_WIDTH / size.x;
-
- //
- // just normal conversion from full stretched to radar cells, note that y is inverted
- // to have the radar align with the world (+x = right, -y = down)
- //
- radar->y = (size.y - pixel->y) * RADAR_CELL_HEIGHT / size.y;
-
- }
-
- return TRUE;
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Translate a screen mouse position to world coords if the screen position is within
- * the radar window and that spot in the radar corresponds to a point in the world */
-// ------------------------------------------------------------------------------------------------
-Bool Radar::screenPixelToWorld( const ICoord2D *pixel, Coord3D *world )
-{
-
- // sanity
- if( pixel == NULL || world == NULL )
- return FALSE;
-
- // if we have no radar window can't do the conversion
- if( m_radarWindow == NULL )
- return FALSE;
-
- // translate pixel coords to local pixel coords relative to the radar window
- ICoord2D localPixel;
- ICoord2D screenPos;
- m_radarWindow->winGetScreenPosition( &screenPos.x, &screenPos.y );
- localPixel.x = pixel->x - screenPos.x;
- localPixel.y = pixel->y - screenPos.y;
-
- // translate local pixel to radar
- ICoord2D radar;
- if( localPixelToRadar( &localPixel, &radar ) == FALSE )
- return FALSE;
-
- // translate radar to world
- return radarToWorld( &radar, world );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Given the pixel coordinates, see if there is an object that is exactly in this
- * spot represented on the radar */
-// ------------------------------------------------------------------------------------------------
-Object *Radar::objectUnderRadarPixel( const ICoord2D *pixel )
-{
-
- // sanity
- if( pixel == NULL )
- return NULL;
-
- // convert pixel location to radar logical radar location
- ICoord2D radar;
- if( localPixelToRadar( pixel, &radar ) == FALSE )
- return NULL;
-
- // object we will return
- Object *obj = NULL;
-
- //
- // scan the objects on the radar list and return any object that maps its world location
- // to the radar location
- //
-
- // search the local object list
- obj = searchListForRadarLocationMatch( m_localObjectList, &radar );
-
- // search all other objects if not found
- if( obj == NULL )
- obj = searchListForRadarLocationMatch( m_objectList, &radar );
-
- // return the object found (if any)
- return obj;
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Search the object list for an object that maps to the given logical radar coords */
-// ------------------------------------------------------------------------------------------------
-Object *Radar::searchListForRadarLocationMatch( RadarObject *listHead, ICoord2D *radarMatch )
-{
-
- // sanity
- if( listHead == NULL || radarMatch == NULL )
- return NULL;
-
- // scan the list
- RadarObject *radarObject;
- ICoord2D radar;
- for( radarObject = listHead; radarObject; radarObject = radarObject->friend_getNext() )
- {
-
- // get object
- Object *obj = radarObject->friend_getObject();
-
- // sanity
- if( obj == NULL )
- {
-
- DEBUG_CRASH(( "Radar::searchListForRadarLocationMatch - NULL object encountered in list" ));
- continue;
-
- }
-
- // convert object position to logical radar
- worldToRadar( obj->getPosition(), &radar );
-
- // see if this matches our match radar location
- if( radar.x >= radarMatch->x - 1 &&
- radar.x <= radarMatch->x + 1 &&
- radar.y >= radarMatch->y - 1 &&
- radar.y <= radarMatch->y + 1 )
- return obj;
-
- }
-
- // no match found
- return NULL;
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Given the RELATIVE SCREEN start X and Y, the width and height of the area to draw the whole
- * radar in, compute what the upper left (ul) and lower right (lr) local coordinates are
- * that represent the actual terrain image part of the radar that will preserve the
- * aspect ratio of the map */
-// ------------------------------------------------------------------------------------------------
-void Radar::findDrawPositions( Int startX, Int startY, Int width, Int height,
- ICoord2D *ul, ICoord2D *lr )
-{
-
- Real ratioWidth;
- Real ratioHeight;
- Coord2D radar;
- ratioWidth = m_mapExtent.width()/(width * 1.0f);
- ratioHeight = m_mapExtent.height()/(height* 1.0f);
-
- if( ratioWidth >= ratioHeight)
- {
- radar.x = m_mapExtent.width() / ratioWidth;
- radar.y = m_mapExtent.height()/ ratioWidth;
- ul->x = 0;
- ul->y = (height - radar.y) / 2.0f;
- lr->x = radar.x;
- lr->y = height - ul->y;
- }
- else
- {
- radar.x = m_mapExtent.width() / ratioHeight;
- radar.y = m_mapExtent.height()/ ratioHeight;
- ul->x = (width - radar.x ) / 2.0f;
- ul->y = 0;
- lr->x = width - ul->x;
- lr->y = radar.y;
- }
-/*
-
- if( m_mapExtent.width() > m_mapExtent.height() )
- {
-
- //
- // +---------------+
- // | |
- // | |
- // +---------------+
- // | map area |
- // +---------------+
- // | |
- // | |
- // +---------------+
- //
- ul->x = 0;
- ul->y = (height - (m_mapExtent.height() / m_mapExtent.width() * height)) / 2.0f;
- lr->x = width;
- lr->y = height - ul->y;
-
- }
- else if( m_mapExtent.height() > m_mapExtent.width() )
- {
-
- // +-----+---+-----+
- // | | m | |
- // | | a | |
- // | | p | |
- // | | | |
- // | | a | |
- // | | r | |
- // | | e | |
- // | | a | |
- // +-----+---+-----+
- //
-
- ul->x = (width - (m_mapExtent.width() / m_mapExtent.height() * width)) / 2.0f;
- ul->y = 0;
- lr->x = width - ul->x;
- lr->y = height;
-
- }
- else
- {
-
- ul->x = 0;
- ul->y = 0;
- lr->x = width;
- lr->y = height;
-
- }
-*/
-
- // make them pixel positions
- ul->x += startX;
- ul->y += startY;
- lr->x += startX;
- lr->y += startY;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Radar color lookup table */
-//-------------------------------------------------------------------------------------------------
-struct RadarColorLookup
-{
- RadarEventType event;
- RGBAColorInt color1;
- RGBAColorInt color2;
-};
-static RadarColorLookup radarColorLookupTable[] =
-{
- /* Radar Event Color 1 Color 2 */
- { RADAR_EVENT_CONSTRUCTION, { 128, 128, 255, 255 }, { 128, 255, 255, 255 } },
- { RADAR_EVENT_UPGRADE, { 128, 0, 64, 255 }, { 255, 185, 220, 255 } },
- { RADAR_EVENT_UNDER_ATTACK, { 255, 0, 0, 255 }, { 255, 128, 128, 255 } },
- { RADAR_EVENT_INFORMATION, { 255, 255, 0, 255 }, { 255, 255, 128, 255 } },
- { RADAR_EVENT_BEACON_PULSE, { 255, 255, 0, 255 }, { 255, 255, 128, 255 } },
- { RADAR_EVENT_INFILTRATION, { 0, 255, 255, 255 }, { 128, 255, 255, 255 } },
- { RADAR_EVENT_BATTLE_PLAN, { 255, 255, 255, 255 }, { 255, 255, 255, 255 } },
- { RADAR_EVENT_STEALTH_DISCOVERED, { 0, 255, 0, 255 }, { 0, 128, 0, 255 } },
- { RADAR_EVENT_STEALTH_NEUTRALIZED, { 0, 255, 0, 255 }, { 0, 128, 0, 255 } },
- { RADAR_EVENT_FAKE, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
- { RADAR_EVENT_INVALID, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }
-};
-
-//-------------------------------------------------------------------------------------------------
-/** Create a new radar event */
-//-------------------------------------------------------------------------------------------------
-void Radar::createEvent( const Coord3D *world, RadarEventType type, Real secondsToLive )
-{
-
- // sanity
- if( world == NULL )
- return;
-
- // lookup the colors we are to used based on the event
- RGBAColorInt color[ 2 ];
- Int i = 0;
- for( ; radarColorLookupTable[ i ].event != RADAR_EVENT_INVALID; ++i )
- {
-
- if( radarColorLookupTable[ i ].event == type )
- {
-
- color[ 0 ] = radarColorLookupTable[ i ].color1;
- color[ 1 ] = radarColorLookupTable[ i ].color2;
- break;
-
- }
-
- }
-
- // check for no match found in color table
- if( radarColorLookupTable[ i ].event == RADAR_EVENT_INVALID )
- {
- static RGBAColorInt color1 = { 255, 255, 255, 255 };
- static RGBAColorInt color2 = { 255, 255, 255, 255 };
-
- DEBUG_CRASH(( "Radar::createEvent - Event not found in color table, using default colors" ));
- color[ 0 ] = color1;
- color[ 1 ] = color2;
-
- }
-
- // call the internal method to create the event with these colors
- internalCreateEvent( world, type, secondsToLive, &color[ 0 ], &color[ 1 ] );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Create radar event using a specific colors from the player */
-// ------------------------------------------------------------------------------------------------
-void Radar::createPlayerEvent( Player *player, const Coord3D *world,
- RadarEventType type, Real secondsToLive )
-{
-
- // sanity
- if( player == NULL || world == NULL )
- return;
-
- // figure out the two colors we should use
- Color c;
- UnsignedByte r, g, b, a;
- RGBAColorInt color[ 2 ];
-
- // color 1
- c = player->getPlayerColor();
- GameGetColorComponents( c, &r, &g, &b, &a );
- color[ 0 ].red = r;
- color[ 0 ].green = g;
- color[ 0 ].blue = b;
- color[ 0 ].alpha = a;
-
- // the second will be a darker color 1
- Real darkScale = 0.75f;
- color[ 1 ] = color[ 0 ];
- color[ 1 ].red -= REAL_TO_INT( color[ 0 ].red * darkScale );
- if( color[ 1 ].red < 0 )
- color[ 1 ].red = 0;
- color[ 1 ].green -= REAL_TO_INT( color[ 0 ].green * darkScale );
- if( color[ 1 ].green < 0 )
- color[ 1 ].green = 0;
- color[ 1 ].blue -= REAL_TO_INT( color[ 0 ].blue * darkScale );
- if( color[ 1 ].blue < 0 )
- color[ 1 ].blue = 0;
-
- // create the events using these colors
- internalCreateEvent( world, type, secondsToLive, &color[ 0 ], &color[ 1 ] );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Create a new radar event */
-//-------------------------------------------------------------------------------------------------
-void Radar::internalCreateEvent( const Coord3D *world, RadarEventType type, Real secondsToLive,
- const RGBAColorInt *color1, const RGBAColorInt *color2 )
-{
- static Real secondsBeforeDieToFade = 0.5f; ///< this many seconds before we hit the die frame we start to fade away
-
- // sanity
- if( world == NULL || color1 == NULL || color2 == NULL )
- return;
-
- // translate the world coord to radar coords
- ICoord2D radar;
- worldToRadar( world, &radar );
-
- // add to the list of radar events
- m_event[ m_nextFreeRadarEvent ].type = type;
- m_event[ m_nextFreeRadarEvent ].active = TRUE;
- m_event[ m_nextFreeRadarEvent ].createFrame = TheGameLogic->getFrame();
- m_event[ m_nextFreeRadarEvent ].dieFrame = TheGameLogic->getFrame() + LOGICFRAMES_PER_SECOND * secondsToLive;
- m_event[ m_nextFreeRadarEvent ].fadeFrame = m_event[ m_nextFreeRadarEvent ].dieFrame - LOGICFRAMES_PER_SECOND * secondsBeforeDieToFade;
- m_event[ m_nextFreeRadarEvent ].color1 = *color1;
- m_event[ m_nextFreeRadarEvent ].color2 = *color2;
- m_event[ m_nextFreeRadarEvent ].worldLoc = *world;
- m_event[ m_nextFreeRadarEvent ].radarLoc = radar;
- m_event[ m_nextFreeRadarEvent ].soundPlayed = FALSE;
-
- // record the index of this, our "last" radar event.
- if ( type != RADAR_EVENT_BEACON_PULSE )
- m_lastRadarEvent = m_nextFreeRadarEvent;
-
- //
- // increment the next radar event index, wrapping to the beginning. If we ever have so many
- // events that they fill up the buffer the oldest ones will just drop off, eh ... should be fine.
- //
- m_nextFreeRadarEvent++;
- if( m_nextFreeRadarEvent >= MAX_RADAR_EVENTS )
- m_nextFreeRadarEvent = 0;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Get the last event position, if any.
- * Returns TRUE if event was found
- * Returns FALSE if there is no "last event" */
-//-------------------------------------------------------------------------------------------------
-Bool Radar::getLastEventLoc( Coord3D *eventPos )
-{
-
- // if we have an index for the last event, one was present
- if( m_lastRadarEvent != -1 )
- {
-
- if( eventPos )
- *eventPos = m_event[ m_lastRadarEvent ].worldLoc;
- return TRUE;
-
- }
-
- return FALSE; // no last event
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Try to create a radar event for "we're under attack". This will be called every time
- * actual damage is dealt to an object that the player owns that shows up on the radar.
- * We don't want to create under attack events every time we are damaged and we also want
- * to limit them based on time and local area of other recent attack events */
-// ------------------------------------------------------------------------------------------------
-void Radar::tryUnderAttackEvent( const Object *obj )
-{
-
- // sanity
- if( obj == NULL )
- return;
-
- // try to create the event
- Bool eventCreated = tryEvent( RADAR_EVENT_UNDER_ATTACK, obj->getPosition() );
-
- // if event created, do some more feedback
- if( eventCreated )
- {
-
- TheControlBar->triggerRadarAttackGlow();
- //
- ///@todo Should make an INI data driven table for radar event strings, and audio events
- //
- // UI feedback for being under attack (note that we display these messages and audio
- // queues even if we don't have a radar)
- //
- Player *player = rts::getObservedOrLocalPlayer();
-
- // create a message for the attack event
- if( obj->isKindOf( KINDOF_INFANTRY ) || obj->isKindOf( KINDOF_VEHICLE ) )
- {
- AudioEventRTS unitAttackSound;
- if( obj->isKindOf(KINDOF_HARVESTER) )
- {
- // display special message
- TheInGameUI->message( "RADAR:HarvesterUnderAttack" );
-
- // play special audio event
- unitAttackSound = TheAudio->getMiscAudio()->m_radarHarvesterUnderAttackSound;
- }
- else
- {
- // display message
- TheInGameUI->message( "RADAR:UnitUnderAttack" );
-
- // play audio event
- unitAttackSound = TheAudio->getMiscAudio()->m_radarStructureUnderAttackSound;
- }
- unitAttackSound.setPlayerIndex(player->getPlayerIndex());
- TheAudio->addAudioEvent( &unitAttackSound );
-
- }
- else if( obj->isKindOf( KINDOF_STRUCTURE ) && obj->isKindOf( KINDOF_MP_COUNT_FOR_VICTORY ) )
- {
- // play EVA. If its our object, play Base under attack.
- if (obj->getControllingPlayer()->isLocalPlayer())
- TheEva->setShouldPlay(EVA_BaseUnderAttack);
- else if (player->getRelationship(obj->getTeam()) == ALLIES)
- TheEva->setShouldPlay(EVA_AllyUnderAttack);
-
- // display message
- TheInGameUI->message( "RADAR:StructureUnderAttack" );
-
- // play audio event
- static AudioEventRTS structureAttackSound = TheAudio->getMiscAudio()->m_radarStructureUnderAttackSound;
- structureAttackSound.setPlayerIndex(player->getPlayerIndex());
- TheAudio->addAudioEvent( &structureAttackSound );
-
- }
- else
- {
-
- // display message
- TheInGameUI->message( "RADAR:UnderAttack" );
-
- // play audio event
- static AudioEventRTS underAttackSound = TheAudio->getMiscAudio()->m_radarStructureUnderAttackSound;
- underAttackSound.setPlayerIndex(player->getPlayerIndex());
- TheAudio->addAudioEvent( &underAttackSound );
-
- }
-
- }
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Try to create a radar event for "infiltration".
- This happens whenever a unit is hijacked, defected, converted to carbomb, hacked, or
- otherwise snuck into */
-// ------------------------------------------------------------------------------------------------
-void Radar::tryInfiltrationEvent( const Object *obj )
-{
-
- //Sanity!
- if( !obj )
- {
- return;
- }
-
- Player *player = rts::getObservedOrLocalPlayer();
-
- // We should only be warned against infiltrations that are taking place against us.
- if( obj->getControllingPlayer() != player )
- return;
-
- // create the radar event
- createEvent( obj->getPosition(), RADAR_EVENT_INFILTRATION );
-
- //
- ///@todo Should make an INI data driven table for radar event strings, and audio events
- //
- // UI feedback for being under attack (note that we display these messages and audio
- // queues even if we don't have a radar)
- //
-
- // display message
- TheInGameUI->message( "RADAR:Infiltration" );
-
- // play audio event
- static AudioEventRTS infiltrationWarningSound = TheAudio->getMiscAudio()->m_radarInfiltrationSound;
- infiltrationWarningSound.setPlayerIndex(player->getPlayerIndex());
- TheAudio->addAudioEvent( &infiltrationWarningSound );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-Bool Radar::tryEvent( RadarEventType event, const Coord3D *pos )
-{
-
- // sanity
- if( event <= RADAR_EVENT_INVALID || event >= RADAR_EVENT_NUM_EVENTS || pos == NULL )
- return FALSE;
-
- // see if there was an event of this type within the given range within the given time
- UnsignedInt currentFrame = TheGameLogic->getFrame();
- const Real closeEnoughDistanceSq = 250.0f * 250.0f;
- const UnsignedInt framesBetweenEvents = LOGICFRAMES_PER_SECOND * 10;
- //
-
- // see if there was any matching radar event within range of this one
- // that wasn't too long ago, if there was we won't create another and get outta here
- //
- for( Int i = 0; i < MAX_RADAR_EVENTS; ++i )
- {
-
- // only pay attention to under attack events
- if( m_event[ i ].type == event )
- {
-
- // get distance from our new event location to this event location in 2D
- Real distSquared = m_event[ i ].worldLoc.x - pos->x * m_event[ i ].worldLoc.x - pos->x +
- m_event[ i ].worldLoc.y - pos->y * m_event[ i ].worldLoc.y - pos->y;
-
- if( distSquared <= closeEnoughDistanceSq )
- {
-
- // finally only reject making a new event of this existing one is "recent enough"
- if( currentFrame - m_event[ i ].createFrame < framesBetweenEvents )
- return FALSE; // reject it
-
- }
-
- }
-
- }
-
- // if we got here then we want to create a new event
- createEvent( pos, event );
-
- // return TRUE for successfully created event
- return TRUE;
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void Radar::refreshTerrain( TerrainLogic *terrain )
-{
-
- // no future queue is valid now
- m_queueTerrainRefreshFrame = 0;
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Queue a refresh of the radar terrain, we have this so that if there is code that
- * rapidly needs to refresh the radar, it should use this so we aren't continually
- * rebuilding the radar graphic because that process is slow. If you need to update
- * the terrain on the radar immediately use refreshTerrain() */
-// ------------------------------------------------------------------------------------------------
-void Radar::queueTerrainRefresh( void )
-{
-
- //
- // we just simply overwrite the frame we have recorded for a radar refresh. If there was
- // already one there, it's simply just forgotten and whatever changes we wanted to see
- // with that refresh will have to wait until enough time has passed to show these
- // changes as well. why you ask ... well, because if we're calling this in close enough
- // proximity for us to overwrite something, we're changing the terrain features
- // quite often and can't afford the expense of rebuilding the radar visual
- //
- m_queueTerrainRefreshFrame = TheGameLogic->getFrame();
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** CRC */
-// ------------------------------------------------------------------------------------------------
-void Radar::crc( Xfer *xfer )
-{
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Xfer a radar object list given the head pointer as a parameter
- * Version Info;
- * 1: Initial version */
-// ------------------------------------------------------------------------------------------------
-static void xferRadarObjectList( Xfer *xfer, RadarObject **head )
-{
- RadarObject *radarObject;
-
- // sanity
- DEBUG_ASSERTCRASH( head != NULL, ("xferRadarObjectList - Invalid parameters" ));
-
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
-
- // write could of objects in list
- UnsignedShort count = 0;
- for( radarObject = *head; radarObject; radarObject = radarObject->friend_getNext() )
- count++;
- xfer->xferUnsignedShort( &count );
-
- // xfer the list data
- if( xfer->getXferMode() == XFER_SAVE )
- {
-
- // save each object
- for( radarObject = *head; radarObject; radarObject = radarObject->friend_getNext() )
- {
-
- // save this object
- xfer->xferSnapshot( radarObject );
-
- }
-
- }
- else
- {
-
- // the list should be empty at this point as we are loading it as a whole
- if( *head != NULL )
- {
-#if 1
- // srj sez: yeah, it SHOULD be, but a few rogue things come into existence (via their ctor) preloaded
- // with stuff (eg, "CabooseFullOfTerrorists"). we immediately destroy 'em, but they don't go away just yet.
- // so just ignore 'em if possible.
- for( radarObject = *head; radarObject; radarObject = radarObject->friend_getNext() )
- {
- if (!radarObject->friend_getObject()->isDestroyed())
- {
- DEBUG_CRASH(( "xferRadarObjectList - List head should be NULL, or contain only destroyed objects" ));
- throw SC_INVALID_DATA;
- }
- }
-#else
- DEBUG_CRASH(( "xferRadarObjectList - List head should be NULL, but isn't" ));
- throw SC_INVALID_DATA;
-#endif
- }
-
- // read each element
- for( UnsignedShort i = 0; i < count; ++i )
- {
-
- // alloate a new radar object
- radarObject = newInstance(RadarObject);
-
- // link to the end of the list
- if( *head == NULL )
- *head = radarObject;
- else
- {
-
- RadarObject *other;
- for( other = *head; other->friend_getNext() != NULL; other = other->friend_getNext() )
- {
- }
-
- // set the end of the list to point to the new object
- other->friend_setNext( radarObject );
-
- }
-
- // load the data
- xfer->xferSnapshot( radarObject );
-
- }
-
- }
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Xfer Method
- * Version Info:
- * 1: Initial version
- * 2: TheSuperHackers @tweak Serialize m_radarHidden, m_radarForceOn for each player
- */
-// ------------------------------------------------------------------------------------------------
-void Radar::xfer( Xfer *xfer )
-{
-
- // version
-#if RETAIL_COMPATIBLE_XFER_SAVE
- XferVersion currentVersion = 1;
-#else
- XferVersion currentVersion = 2;
-#endif
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
-
-
- if (version <= 1)
- {
- const Int localPlayerIndex = ThePlayerList->getLocalPlayer()->getPlayerIndex();
- Bool value;
-
- // radar hidden
- value = m_radarHidden[localPlayerIndex];
- xfer->xferBool( &value );
- m_radarHidden[localPlayerIndex] = value;
-
- // radar force on
- value = m_radarForceOn[localPlayerIndex];
- xfer->xferBool( &value );
- m_radarForceOn[localPlayerIndex] = value;
- }
- else
- {
- static_assert(sizeof(m_radarHidden) == 16, "Increase version if size changes");
- xfer->xferUser(&m_radarHidden, sizeof(m_radarHidden));
-
- static_assert(sizeof(m_radarForceOn) == 16, "Increase version if size changes");
- xfer->xferUser(&m_radarForceOn, sizeof(m_radarForceOn));
- }
-
- // save our local object list
- xferRadarObjectList( xfer, &m_localObjectList );
-
- // save the regular object list
- xferRadarObjectList( xfer, &m_objectList );
-
- // save the radar event count and data
- UnsignedShort eventCountVerify = MAX_RADAR_EVENTS;
- UnsignedShort eventCount = eventCountVerify;
- xfer->xferUnsignedShort( &eventCount );
- if( eventCount != eventCountVerify )
- {
-
- DEBUG_CRASH(( "Radar::xfer - size of MAX_RADAR_EVENTS has changed, you must version this xfer method to accomodate the new array size. Was '%d' and is now '%d'",
- eventCount, eventCountVerify ));
- throw SC_INVALID_DATA;
-
- }
- for( UnsignedShort i = 0; i < eventCount; ++i )
- {
-
- // xfer event data
- xfer->xferUser( &m_event[ i ].type, sizeof( RadarEventType ) );
- xfer->xferBool( &m_event[ i ].active );
- xfer->xferUnsignedInt( &m_event[ i ].createFrame );
- xfer->xferUnsignedInt( &m_event[ i ].dieFrame );
- xfer->xferUnsignedInt( &m_event[ i ].fadeFrame );
- xfer->xferRGBAColorInt( &m_event[ i ].color1 );
- xfer->xferRGBAColorInt( &m_event[ i ].color2 );
- xfer->xferCoord3D( &m_event[ i ].worldLoc );
- xfer->xferICoord2D( &m_event[ i ].radarLoc );
- xfer->xferBool( &m_event[ i ].soundPlayed );
-
- }
-
- // next event index
- xfer->xferInt( &m_nextFreeRadarEvent );
-
- // last event index
- xfer->xferInt( &m_lastRadarEvent );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Load post process */
-// ------------------------------------------------------------------------------------------------
-void Radar::loadPostProcess( void )
-{
-
- //
- // refresh the radar texture now that all the objects (specifically bridges) have
- // been loaded with their correct damage states from save game file
- //
- refreshTerrain( TheTerrainLogic );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-/** Is the priority type passed in a "visible" one that can show up on the radar */
-// ------------------------------------------------------------------------------------------------
-Bool Radar::isPriorityVisible( RadarPriorityType priority )
-{
-
- switch( priority )
- {
-
- case RADAR_PRIORITY_INVALID:
- case RADAR_PRIORITY_NOT_ON_RADAR:
- return FALSE;
-
- default:
- return TRUE;
-
- }
-
-}
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp
index c14a6d30cc..168f12307c 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp
@@ -2143,7 +2143,12 @@ Bool TerrainLogic::isUnderwater( Real x, Real y, Real *waterZ, Real *terrainZ )
// if no water here, no height, no nuttin
if( waterHandle == NULL )
+ {
+ // but we have to return the terrain Z if requested!
+ if (terrainZ)
+ *terrainZ=getGroundHeight(x,y);
return FALSE;
+ }
//
// if this water handle is a grid water use the grid height function, otherwise look into
diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp
index af3dc0064e..a1f767a712 100644
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp
+++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp
@@ -744,6 +744,7 @@ void StealthUpdate::changeVisualDisguise()
FXList::doFXPos( data->m_disguiseFX, self->getPosition() );
m_disguised = true;
+ self->setStatus( MAKE_OBJECT_STATUS_MASK( OBJECT_STATUS_DISGUISED ) );
}
else if( m_disguiseAsPlayerIndex != -1 )
{
@@ -809,6 +810,7 @@ void StealthUpdate::changeVisualDisguise()
FXList::doFXPos( data->m_disguiseRevealFX, self->getPosition() );
m_disguised = false;
+ self->clearStatus( MAKE_OBJECT_STATUS_MASK( OBJECT_STATUS_DISGUISED ) );
}
//Reset the radar (determines color on add)
diff --git a/Generals/Code/GameEngineDevice/CMakeLists.txt b/Generals/Code/GameEngineDevice/CMakeLists.txt
index 63a78b15a4..0f26cbd753 100644
--- a/Generals/Code/GameEngineDevice/CMakeLists.txt
+++ b/Generals/Code/GameEngineDevice/CMakeLists.txt
@@ -4,7 +4,7 @@ set(GAMEENGINEDEVICE_SRC
Include/W3DDevice/Common/W3DConvert.h
Include/W3DDevice/Common/W3DFunctionLexicon.h
Include/W3DDevice/Common/W3DModuleFactory.h
- Include/W3DDevice/Common/W3DRadar.h
+# Include/W3DDevice/Common/W3DRadar.h
Include/W3DDevice/Common/W3DThingFactory.h
Include/W3DDevice/GameClient/HeightMap.h
Include/W3DDevice/GameClient/Module/W3DDebrisDraw.h
@@ -81,7 +81,7 @@ set(GAMEENGINEDEVICE_SRC
# Source/MilesAudioDevice/MilesAudioManager.cpp
# Source/VideoDevice/Bink/BinkVideoPlayer.cpp
Source/W3DDevice/Common/System/W3DFunctionLexicon.cpp
- Source/W3DDevice/Common/System/W3DRadar.cpp
+# Source/W3DDevice/Common/System/W3DRadar.cpp
Source/W3DDevice/Common/Thing/W3DModuleFactory.cpp
Source/W3DDevice/Common/Thing/W3DThingFactory.cpp
Source/W3DDevice/Common/W3DConvert.cpp
diff --git a/Generals/Code/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h b/Generals/Code/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h
deleted file mode 100644
index 2a4f0b554e..0000000000
--- a/Generals/Code/GameEngineDevice/Include/W3DDevice/Common/W3DRadar.h
+++ /dev/null
@@ -1,126 +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: W3DRadar.h ///////////////////////////////////////////////////////////////////////////////
-// Author: Colin Day, January 2002
-// Desc: W3D radar implementation, this has the necessary device dependent drawing
-// necessary for the radar
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "Common/Radar.h"
-#include "WW3D2/ww3dformat.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
-class TextureClass;
-class TerrainLogic;
-
-// PROTOTYPES /////////////////////////////////////////////////////////////////////////////////////
-//-------------------------------------------------------------------------------------------------
-/** W3D radar class. This has the device specific implementation of the radar such as
- * the drawing routines */
-//-------------------------------------------------------------------------------------------------
-class W3DRadar : public Radar
-{
-
-public:
-
- W3DRadar( void );
- ~W3DRadar( void );
-
- virtual void xfer( Xfer *xfer );
-
- virtual void init( void ); ///< subsystem init
- virtual void update( void ); ///< subsystem update
- virtual void reset( void ); ///< subsystem reset
-
- virtual RadarObjectType addObject( Object *obj ); ///< add object to radar
- virtual RadarObjectType removeObject( Object *obj ); ///< remove object from radar
-
- virtual void newMap( TerrainLogic *terrain ); ///< reset radar for new map
-
- virtual void draw( Int pixelX, Int pixelY, Int width, Int height ); ///< draw the radar
-
- virtual void clearShroud();
- virtual void setShroudLevel(Int x, Int y, CellShroudStatus setting);
-
- virtual void refreshTerrain( TerrainLogic *terrain );
- virtual void refreshObjects();
-
-protected:
-
- void drawSingleBeaconEvent( Int pixelX, Int pixelY, Int width, Int height, Int index );
- void drawSingleGenericEvent( Int pixelX, Int pixelY, Int width, Int height, Int index );
-
- void initializeTextureFormats( void ); ///< find format to use for the radar texture
- void deleteResources( void ); ///< delete resources used
- void drawEvents( Int pixelX, Int pixelY, Int width, Int height); ///< draw all of the radar events
- void drawHeroIcon( Int pixelX, Int pixelY, Int width, Int height, const Coord3D *pos ); //< draw a hero icon
- void drawViewBox( Int pixelX, Int pixelY, Int width, Int height ); ///< draw view box
- void buildTerrainTexture( TerrainLogic *terrain ); ///< create the terrain texture of the radar
- void drawIcons( Int pixelX, Int pixelY, Int width, Int height ); ///< draw all of the radar icons
- void updateObjectTexture(TextureClass *texture);
- void renderObjectList( const RadarObject *listHead, TextureClass *texture, Bool calcHero = FALSE ); ///< render an object list to the texture
- void interpolateColorForHeight( RGBColor *color,
- Real height,
- Real hiZ,
- Real midZ,
- Real loZ ); ///< "shade" color according to height value
- void reconstructViewBox( void ); ///< remake the view box
- void radarToPixel( const ICoord2D *radar, ICoord2D *pixel,
- Int radarUpperLeftX, Int radarUpperLeftY,
- Int radarWidth, Int radarHeight ); ///< convert radar coord to pixel location
-
- WW3DFormat m_terrainTextureFormat; ///< format to use for terrain texture
- Image *m_terrainImage; ///< terrain image abstraction for drawing
- TextureClass *m_terrainTexture; ///< terrain background texture
-
- WW3DFormat m_overlayTextureFormat; ///< format to use for overlay texture
- Image *m_overlayImage; ///< overlay image abstraction for drawing
- TextureClass *m_overlayTexture; ///< overlay texture
-
- WW3DFormat m_shroudTextureFormat; ///< format to use for shroud texture
- Image *m_shroudImage; ///< shroud image abstraction for drawing
- TextureClass *m_shroudTexture; ///< shroud texture
-
- Int m_textureWidth; ///< width for all radar textures
- Int m_textureHeight; ///< height for all radar textures
-
- //
- // we want to keep a flag that tells us when to reconstruct the view box, we want
- // to reconstruct the box on map change, and when the camera changes height
- // or orientation. We want to avoid making the view box every frame because
- // the 4 points visible on the edge of the screen will "jitter" unevenly as we
- // translate real world coords to integer radar spots
- //
- Bool m_reconstructViewBox; ///< true when we need to reconstruct the box
- Real m_viewAngle; ///< camera angle used for the view box we have
- Real m_viewZoom; ///< camera zoom used for the view box we have
- ICoord2D m_viewBox[ 4 ]; ///< radar cell points for the 4 corners of view box
-
- std::vector m_cachedHeroObjectList; //< cache of hero objects for drawing icons in radar overlay
-};
diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
deleted file mode 100644
index 1c7d5dcab9..0000000000
--- a/Generals/Code/GameEngineDevice/Source/W3DDevice/Common/System/W3DRadar.cpp
+++ /dev/null
@@ -1,1640 +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: W3DRadar.cpp /////////////////////////////////////////////////////////////////////////////
-// Author: Colin Day, January 2002
-// Desc: W3D radar implementation, this has the necessary device dependent drawing
-// necessary for the radar
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "Common/AudioEventRTS.h"
-#include "Common/Debug.h"
-#include "Common/GlobalData.h"
-#include "Common/GameUtility.h"
-#include "Common/Player.h"
-#include "Common/PlayerList.h"
-
-#include "GameLogic/TerrainLogic.h"
-#include "GameLogic/GameLogic.h"
-#include "GameLogic/Object.h"
-
-#include "GameLogic/Module/StealthUpdate.h"
-
-#include "GameClient/Color.h"
-#include "GameClient/ControlBar.h"
-#include "GameClient/Display.h"
-#include "GameClient/GameClient.h"
-#include "GameClient/GameWindow.h"
-#include "GameClient/Image.h"
-#include "GameClient/Line2D.h"
-#include "GameClient/TerrainVisual.h"
-#include "GameClient/Water.h"
-#include "W3DDevice/Common/W3DRadar.h"
-#include "W3DDevice/GameClient/HeightMap.h"
-#include "W3DDevice/GameClient/W3DShroud.h"
-#include "WW3D2/texture.h"
-#include "WW3D2/dx8caps.h"
-
-
-
-// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
-enum { OVERLAY_REFRESH_RATE = 6 }; ///< over updates once this many frames
-
-//-------------------------------------------------------------------------------------------------
-/** Is the point legal, that is, inside the resolution of the radar cells */
-//-------------------------------------------------------------------------------------------------
-inline Bool legalRadarPoint( Int px, Int py )
-{
-
- if( px < 0 || py < 0 || px >= RADAR_CELL_WIDTH || py >= RADAR_CELL_HEIGHT )
- return FALSE;
-
- return TRUE;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-static WW3DFormat findFormat(const WW3DFormat formats[])
-{
- for( Int i = 0; formats[ i ] != WW3D_FORMAT_UNKNOWN; i++ )
- {
-
- if( DX8Wrapper::Get_Current_Caps()->Support_Texture_Format( formats[ i ] ) )
- {
-
- return formats[ i ];
-
- }
-
- }
- DEBUG_CRASH(("WW3DRadar: No appropriate texture format") );
- return WW3D_FORMAT_UNKNOWN;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Find the texture format we're going to use for the radar. The texture format must
- * be supported by the hardware. The "more preferred" formats appear at the top of
- * the format tables in order from most preferred to least preferred */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::initializeTextureFormats( void )
-{
- const WW3DFormat terrainFormats[] =
- {
- WW3D_FORMAT_R8G8B8,
- WW3D_FORMAT_X8R8G8B8,
- WW3D_FORMAT_R5G6B5,
- WW3D_FORMAT_X1R5G5B5,
- WW3D_FORMAT_UNKNOWN // keep this one last
- };
- const WW3DFormat overlayFormats[] =
- {
- WW3D_FORMAT_A8R8G8B8,
- WW3D_FORMAT_A4R4G4B4,
- WW3D_FORMAT_UNKNOWN // keep this one last
- };
- const WW3DFormat shroudFormats[] =
- {
- WW3D_FORMAT_A8R8G8B8,
- WW3D_FORMAT_A4R4G4B4,
- WW3D_FORMAT_UNKNOWN // keep this one last
- };
-
- // find a format for the terrain texture
- m_terrainTextureFormat = findFormat(terrainFormats);
-
- // find a format for the overlay texture
- m_overlayTextureFormat = findFormat(overlayFormats);
-
- // find a format for the shroud texture
- m_shroudTextureFormat = findFormat(shroudFormats);
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Delete resources used specifically in this W3D radar implemetation */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::deleteResources( void )
-{
-
- //
- // delete terrain resources used
- //
- if( m_terrainTexture )
- m_terrainTexture->Release_Ref();
- m_terrainTexture = NULL;
-
- deleteInstance(m_terrainImage);
- m_terrainImage = NULL;
-
- //
- // delete overlay resources used
- //
- if( m_overlayTexture )
- m_overlayTexture->Release_Ref();
- m_overlayTexture = NULL;
-
- deleteInstance(m_overlayImage);
- m_overlayImage = NULL;
-
- //
- // delete shroud resources used
- //
- if( m_shroudTexture )
- m_shroudTexture->Release_Ref();
- m_shroudTexture = NULL;
-
- deleteInstance(m_shroudImage);
- m_shroudImage = NULL;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reconstruct the view box given the current camera settings */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::reconstructViewBox( void )
-{
- Coord3D world[ 4 ];
- ICoord2D radar[ 4 ];
- Int i;
-
- // get the 4 points of the view corners in the 3D world at the average Z height in the map
- TheTacticalView->getScreenCornerWorldPointsAtZ( &world[ 0 ],
- &world[ 1 ],
- &world[ 2 ],
- &world[ 3 ],
- getTerrainAverageZ() );
-
- // convert each of the 4 points in the world to radar cell positions
- for( i = 0; i < 4; i++ )
- {
-
- // first convert to radar cells
- radar[ i ].x = world[ i ].x / (m_mapExtent.width() / RADAR_CELL_WIDTH);
- radar[ i ].y = world[ i ].y / (m_mapExtent.height() / RADAR_CELL_HEIGHT);
-
- //
- // store these points in the view box array which contains a first position
- // of (0,0) and then offsets for each additional entry point
- //
- if( i == 0 )
- {
-
- m_viewBox[ i ].x = 0;
- m_viewBox[ i ].y = 0;
-
- }
- else
- {
-
- m_viewBox[ i ].x = radar[ i ].x - radar[ i - 1 ].x;
- m_viewBox[ i ].y = radar[ i ].y - radar[ i - 1 ].y;
-
- }
-
- }
-
- //
- // save the camera settings for this view box, we will need to make it again only
- // if some of these change
- //
- m_viewAngle = TheTacticalView->getAngle();
- Coord3D pos;
- TheTacticalView->getPosition( &pos );
- m_viewZoom = TheTacticalView->getZoom();
- m_reconstructViewBox = FALSE;
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Convert radar position to actual pixel coord */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::radarToPixel( const ICoord2D *radar, ICoord2D *pixel,
- Int radarUpperLeftX, Int radarUpperLeftY,
- Int radarWidth, Int radarHeight )
-{
-
- // sanity
- if( radar == NULL || pixel == NULL )
- return;
-
- pixel->x = (radar->x * radarWidth / RADAR_CELL_WIDTH) + radarUpperLeftX;
- // note the "inverted" y here to orient the way our world looks with +x=right and -y=down
- pixel->y = ((RADAR_CELL_HEIGHT - 1 - radar->y) * radarHeight / RADAR_CELL_HEIGHT) + radarUpperLeftY;
-
-}
-
-
-//-------------------------------------------------------------------------------------------------
-/** Draw a hero icon at a position, given radar box upper left location and dimensions. */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::drawHeroIcon( Int pixelX, Int pixelY, Int width, Int height, const Coord3D *pos )
-{
- // get the hero icon image
- static const Image *image = (Image *)TheMappedImageCollection->findImageByName("HeroReticle");
- if (image != NULL)
- {
- // convert world to radar coords
- ICoord2D ulRadar;
- ulRadar.x = pos->x / (m_mapExtent.width() / RADAR_CELL_WIDTH);
- ulRadar.y = pos->y / (m_mapExtent.height() / RADAR_CELL_HEIGHT);
-
- // convert radar to screen coords
- ICoord2D offsetScreen;
- radarToPixel( &ulRadar, &offsetScreen, pixelX, pixelY, width, height );
-
- // shift from an upper left to a center focus for the icon
- int iconWidth = image->getImageWidth();
- int iconHeight = image->getImageHeight();
- offsetScreen.x -= (iconWidth / 2) - 1;
- offsetScreen.y -= iconHeight / 2;
-
- // draw the icon
- TheDisplay->drawImage( image, offsetScreen.x , offsetScreen.y, offsetScreen.x + iconWidth, offsetScreen.y + iconHeight );
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Draw a "box" into the texture passed in that represents the viewable area for
- * the tactical display into the game world */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::drawViewBox( Int pixelX, Int pixelY, Int width, Int height )
-{
- ICoord2D ulScreen;
- ICoord2D ulRadar;
- Coord3D ulWorld;
- ICoord2D ulStart = { 0, 0 };
- ICoord2D start, end;
- ICoord2D clipStart, clipEnd;
- Real lineWidth = 1.0f;
- Color topColor = GameMakeColor( 225, 225, 0, 255 );
- Color bottomColor = GameMakeColor( 158, 158, 0, 255 );
-
- //
- // setup the clipping region ... note that this clipping region is not over just the
- // radar image area ... it's in the WHOLE window available for the radar
- //
- IRegion2D clipRegion;
- ICoord2D radarWindowSize, radarWindowScreenPos;
- m_radarWindow->winGetSize( &radarWindowSize.x, &radarWindowSize.y );
- m_radarWindow->winGetScreenPosition( &radarWindowScreenPos.x, &radarWindowScreenPos.y );
- clipRegion.lo.x = radarWindowScreenPos.x;
- clipRegion.lo.y = radarWindowScreenPos.y;
- clipRegion.hi.x = radarWindowScreenPos.x + radarWindowSize.x;
- clipRegion.hi.y = radarWindowScreenPos.y + radarWindowSize.y;
-
- // convert top left of screen into world position
- TheTacticalView->getOrigin( &ulScreen.x, &ulScreen.y );
- TheTacticalView->screenToWorldAtZ( &ulScreen, &ulWorld, getTerrainAverageZ() );
-
- // convert world to radar coords
- ulRadar.x = ulWorld.x / (m_mapExtent.width() / RADAR_CELL_WIDTH);
- ulRadar.y = ulWorld.y / (m_mapExtent.height() / RADAR_CELL_HEIGHT);
-
- //
- // convert radar point to actual pixel coords on the screen, shifted
- // into position on the radar for where the radar is drawn and the size of the
- // area that the radar is drawn in
- //
- radarToPixel( &ulRadar, &ulStart, pixelX, pixelY, width, height );
-
- //
- // using our view box offset array, convert each of those radar cell offset points
- // into screen pixels and draw the box. The view box array is setup with the
- // first index containing (0,0) (the point we just converted in theory), with cell
- // offsets to each of the other corners in the following order
- // (upper left, upper right, lower right, lower left)
- //
- ICoord2D radar;
-
- // top line
- start = ulStart;
- radar.x = ulRadar.x + m_viewBox[ 1 ].x;
- radar.y = ulRadar.y + m_viewBox[ 1 ].y;
- radarToPixel( &radar, &end, pixelX, pixelY, width, height );
- if( ClipLine2D( &start, &end, &clipStart, &clipEnd, &clipRegion ) )
- TheDisplay->drawLine( clipStart.x, clipStart.y, clipEnd.x, clipEnd.y,
- lineWidth, topColor );
-
- // right line
- start = end;
- radar.x += m_viewBox[ 2 ].x;
- radar.y += m_viewBox[ 2 ].y;
- radarToPixel( &radar, &end, pixelX, pixelY, width, height );
- if( ClipLine2D( &start, &end, &clipStart, &clipEnd, &clipRegion ) )
- TheDisplay->drawLine( clipStart.x, clipStart.y, clipEnd.x, clipEnd.y,
- lineWidth, topColor, bottomColor );
-
- // bottom line
- start = end;
- radar.x += m_viewBox[ 3 ].x;
- radar.y += m_viewBox[ 3 ].y;
- radarToPixel( &radar, &end, pixelX, pixelY, width, height );
- if( ClipLine2D( &start, &end, &clipStart, &clipEnd, &clipRegion ) )
- TheDisplay->drawLine( clipStart.x, clipStart.y, clipEnd.x, clipEnd.y,
- lineWidth, bottomColor );
-
- // left line
- start = end;
- end = ulStart;
- if( ClipLine2D( &start, &end, &clipStart, &clipEnd, &clipRegion ) )
- TheDisplay->drawLine( clipStart.x, clipStart.y, clipEnd.x, clipEnd.y,
- lineWidth, bottomColor, topColor );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void W3DRadar::drawSingleBeaconEvent( Int pixelX, Int pixelY, Int width, Int height, Int index )
-{
- RadarEvent *event = &(m_event[index]);
- ICoord2D tri[ 3 ];
- ICoord2D start, end;
- Real angle, addAngle;
- Color startColor, endColor;
- Real lineWidth = 1.0f;
- UnsignedInt currentFrame = TheGameLogic->getFrame();
- UnsignedInt frameDiff; // frames the event has been alive for
- Real maxEventSize = width / 10.0f; // max size of the event marker
- Int minEventSize = 6; // min size of the event marker
- Int eventSize; // current size of a marker to draw
- const Real TIME_FROM_FULL_SIZE_TO_SMALL_SIZE = LOGICFRAMES_PER_SECOND * 1.5;
- Real totalAnglesToSpin = 2.0f * PI; ///< spin around this many angles going from big to small
- UnsignedByte r, g, b, a;
-
- // setup screen clipping region
- IRegion2D clipRegion;
- clipRegion.lo.x = pixelX;
- clipRegion.lo.y = pixelY;
- clipRegion.hi.x = pixelX + width;
- clipRegion.hi.y = pixelY + height;
-
- // get the difference in frame from the current frame to the frame we were created on
- frameDiff = currentFrame - event->createFrame;
-
- // compute the size of the event marker, it is largest when it starts and smallest at the end
- eventSize = REAL_TO_INT( maxEventSize * ( 1.0f - frameDiff / TIME_FROM_FULL_SIZE_TO_SMALL_SIZE) );
-
- // we never let the event size get too small
- if( eventSize < minEventSize )
- eventSize = minEventSize;
-
- // compute how much "angle" we will add to each point to make it rotate as it's getting small
- addAngle = -totalAnglesToSpin * (frameDiff / TIME_FROM_FULL_SIZE_TO_SMALL_SIZE);
-
- // create a triangle around the event
- angle = 0.0f - addAngle;
- tri[ 0 ].x = REAL_TO_INT( (DOUBLE_TO_REAL( Cos( angle ) ) * eventSize) + event->radarLoc.x );
- tri[ 0 ].y = REAL_TO_INT( (DOUBLE_TO_REAL( Sin( angle ) ) * eventSize) + event->radarLoc.y );
-
- angle = 2.0f * PI / 3.0f - addAngle;
- tri[ 1 ].x = REAL_TO_INT( (DOUBLE_TO_REAL( Cos( angle ) ) * eventSize) + event->radarLoc.x );
- tri[ 1 ].y = REAL_TO_INT( (DOUBLE_TO_REAL( Sin( angle ) ) * eventSize) + event->radarLoc.y );
-
- angle = -2.0f * PI / 3.0f - addAngle;
- tri[ 2 ].x = REAL_TO_INT( (DOUBLE_TO_REAL( Cos( angle ) ) * eventSize) + event->radarLoc.x );
- tri[ 2 ].y = REAL_TO_INT( (DOUBLE_TO_REAL( Sin( angle ) ) * eventSize) + event->radarLoc.y );
-
- // translate radar coords to screen coords
- radarToPixel( &tri[ 0 ], &tri[ 0 ], pixelX, pixelY, width, height );
- radarToPixel( &tri[ 1 ], &tri[ 1 ], pixelX, pixelY, width, height );
- radarToPixel( &tri[ 2 ], &tri[ 2 ], pixelX, pixelY, width, height );
-
- //
- // make the colors we're going to use, when we're at our smallest size we will start to
- // fade the alpha away to transparent so that at our lifetime frame we are completely gone
- //
-
- // color 1 ------------------
- r = event->color1.red;
- g = event->color1.green;
- b = event->color1.blue;
- a = event->color1.alpha;
- if( currentFrame > event->fadeFrame )
- {
-
- a = REAL_TO_UNSIGNEDBYTE( (Real)a * (1.0f - (Real)(currentFrame - event->fadeFrame) /
- (Real)(event->dieFrame - event->fadeFrame) ) );
-
- }
- startColor = GameMakeColor( r, g, b, a );
-
- // color 2 ------------------
- r = event->color2.red;
- g = event->color2.green;
- b = event->color2.blue;
- a = event->color2.alpha;
- if( currentFrame > event->fadeFrame )
- {
-
- a = REAL_TO_UNSIGNEDBYTE( (Real)a * (1.0f - (Real)(currentFrame - event->fadeFrame) /
- (Real)(event->dieFrame - event->fadeFrame) ) );
-
- }
- endColor = GameMakeColor( r, g, b, a );
-
- // draw the lines
- if( ClipLine2D( &tri[ 0 ], &tri[ 1 ], &start, &end, &clipRegion ) )
- TheDisplay->drawLine( start.x, start.y, end.x, end.y, lineWidth, startColor, endColor );
- if( ClipLine2D( &tri[ 1 ], &tri[ 2 ], &start, &end, &clipRegion ) )
- TheDisplay->drawLine( start.x, start.y, end.x, end.y, lineWidth, startColor, endColor );
- if( ClipLine2D( &tri[ 2 ], &tri[ 0 ], &start, &end, &clipRegion ) )
- TheDisplay->drawLine( start.x, start.y, end.x, end.y, lineWidth, startColor, endColor );
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void W3DRadar::drawSingleGenericEvent( Int pixelX, Int pixelY, Int width, Int height, Int index )
-{
- RadarEvent *event = &(m_event[index]);
- ICoord2D tri[ 3 ];
- ICoord2D start, end;
- Real angle, addAngle;
- Color startColor, endColor;
- Real lineWidth = 1.0f;
- UnsignedInt currentFrame = TheGameLogic->getFrame();
- UnsignedInt frameDiff; // frames the event has been alive for
- Real maxEventSize = width / 2.0f; // max size of the event marker
- Int minEventSize = 6; // min size of the event marker
- Int eventSize; // current size of a marker to draw
- const Real TIME_FROM_FULL_SIZE_TO_SMALL_SIZE = LOGICFRAMES_PER_SECOND * 1.5;
- Real totalAnglesToSpin = 2.0f * PI; ///< spin around this many angles going from big to small
- UnsignedByte r, g, b, a;
-
- // setup screen clipping region
- IRegion2D clipRegion;
- clipRegion.lo.x = pixelX;
- clipRegion.lo.y = pixelY;
- clipRegion.hi.x = pixelX + width;
- clipRegion.hi.y = pixelY + height;
-
- // get the difference in frame from the current frame to the frame we were created on
- frameDiff = currentFrame - event->createFrame;
-
- // compute the size of the event marker, it is largest when it starts and smallest at the end
- eventSize = REAL_TO_INT( maxEventSize * ( 1.0f - frameDiff / TIME_FROM_FULL_SIZE_TO_SMALL_SIZE) );
-
- // we never let the event size get too small
- if( eventSize < minEventSize )
- eventSize = minEventSize;
-
- // compute how much "angle" we will add to each point to make it rotate as it's getting small
- addAngle = totalAnglesToSpin * (frameDiff / TIME_FROM_FULL_SIZE_TO_SMALL_SIZE);
-
- // create a triangle around the event
- angle = 0.0f - addAngle;
- tri[ 0 ].x = REAL_TO_INT( (DOUBLE_TO_REAL( Cos( angle ) ) * eventSize) + event->radarLoc.x );
- tri[ 0 ].y = REAL_TO_INT( (DOUBLE_TO_REAL( Sin( angle ) ) * eventSize) + event->radarLoc.y );
-
- angle = 2.0f * PI / 3.0f - addAngle;
- tri[ 1 ].x = REAL_TO_INT( (DOUBLE_TO_REAL( Cos( angle ) ) * eventSize) + event->radarLoc.x );
- tri[ 1 ].y = REAL_TO_INT( (DOUBLE_TO_REAL( Sin( angle ) ) * eventSize) + event->radarLoc.y );
-
- angle = -2.0f * PI / 3.0f - addAngle;
- tri[ 2 ].x = REAL_TO_INT( (DOUBLE_TO_REAL( Cos( angle ) ) * eventSize) + event->radarLoc.x );
- tri[ 2 ].y = REAL_TO_INT( (DOUBLE_TO_REAL( Sin( angle ) ) * eventSize) + event->radarLoc.y );
-
- // translate radar coords to screen coords
- radarToPixel( &tri[ 0 ], &tri[ 0 ], pixelX, pixelY, width, height );
- radarToPixel( &tri[ 1 ], &tri[ 1 ], pixelX, pixelY, width, height );
- radarToPixel( &tri[ 2 ], &tri[ 2 ], pixelX, pixelY, width, height );
-
- //
- // make the colors we're going to use, when we're at our smallest size we will start to
- // fade the alpha away to transparent so that at our lifetime frame we are completely gone
- //
-
- // color 1 ------------------
- r = event->color1.red;
- g = event->color1.green;
- b = event->color1.blue;
- a = event->color1.alpha;
- if( currentFrame > event->fadeFrame )
- {
-
- a = REAL_TO_UNSIGNEDBYTE( (Real)a * (1.0f - (Real)(currentFrame - event->fadeFrame) /
- (Real)(event->dieFrame - event->fadeFrame) ) );
-
- }
- startColor = GameMakeColor( r, g, b, a );
-
- // color 2 ------------------
- r = event->color2.red;
- g = event->color2.green;
- b = event->color2.blue;
- a = event->color2.alpha;
- if( currentFrame > event->fadeFrame )
- {
-
- a = REAL_TO_UNSIGNEDBYTE( (Real)a * (1.0f - (Real)(currentFrame - event->fadeFrame) /
- (Real)(event->dieFrame - event->fadeFrame) ) );
-
- }
- endColor = GameMakeColor( r, g, b, a );
-
- // draw the lines
- if( ClipLine2D( &tri[ 0 ], &tri[ 1 ], &start, &end, &clipRegion ) )
- TheDisplay->drawLine( start.x, start.y, end.x, end.y, lineWidth, startColor, endColor );
- if( ClipLine2D( &tri[ 1 ], &tri[ 2 ], &start, &end, &clipRegion ) )
- TheDisplay->drawLine( start.x, start.y, end.x, end.y, lineWidth, startColor, endColor );
- if( ClipLine2D( &tri[ 2 ], &tri[ 0 ], &start, &end, &clipRegion ) )
- TheDisplay->drawLine( start.x, start.y, end.x, end.y, lineWidth, startColor, endColor );
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Draw all the radar events */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::drawEvents( Int pixelX, Int pixelY, Int width, Int height )
-{
- Int i;
-
- for( i = 0; i < MAX_RADAR_EVENTS; i++ )
- {
-
- // only 'active' events actually have something to draw
- if( m_event[ i ].active == TRUE && m_event[ i ].type != RADAR_EVENT_FAKE )
- {
-
- // if we haven't played the sound for this event, do it now that we can see it
- if( m_event[ i ].soundPlayed == FALSE && m_event[i].type != RADAR_EVENT_BEACON_PULSE )
- {
- static AudioEventRTS eventSound("RadarEvent");
- TheAudio->addAudioEvent( &eventSound );
-
- }
-
- m_event[ i ].soundPlayed = TRUE;
-
- if ( m_event[ i ].type == RADAR_EVENT_BEACON_PULSE )
- drawSingleBeaconEvent( pixelX, pixelY, width, height, i );
- else
- drawSingleGenericEvent( pixelX, pixelY, width, height, i );
-
- }
-
- }
-
-}
-
-
-//-------------------------------------------------------------------------------------------------
-/** Draw all the radar icons */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::drawIcons( Int pixelX, Int pixelY, Int width, Int height )
-{
- // draw the hero icons
- std::vector::const_iterator iter = m_cachedHeroObjectList.begin();
- while (iter != m_cachedHeroObjectList.end())
- {
- drawHeroIcon( pixelX, pixelY, width, height, (*iter)->getPosition() );
- ++iter;
- }
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::updateObjectTexture(TextureClass *texture)
-{
- // reset the overlay texture
- SurfaceClass *surface = texture->Get_Surface_Level();
- surface->Clear();
- REF_PTR_RELEASE(surface);
-
- // rebuild the object overlay
- renderObjectList( getObjectList(), texture );
- renderObjectList( getLocalObjectList(), texture, TRUE );
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Render an object list into the texture passed in */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::renderObjectList( const RadarObject *listHead, TextureClass *texture, Bool calcHero )
-{
-
- // sanity
- if( listHead == NULL || texture == NULL )
- return;
-
- // get surface for texture to render into
- SurfaceClass *surface = texture->Get_Surface_Level();
-
- // loop through all objects and draw
- ICoord2D radarPoint;
-
- Player *player = rts::getObservedOrLocalPlayer();
- const Int playerIndex = player->getPlayerIndex();
-
- if( calcHero )
- {
- // clear all entries from the cached hero object list
- m_cachedHeroObjectList.clear();
- }
-
- for( const RadarObject *rObj = listHead; rObj; rObj = rObj->friend_getNext() )
- {
-
- if (rObj->isTemporarilyHidden())
- continue;
-
- // get object
- const Object *obj = rObj->friend_getObject();
-
- // check for shrouded status
- if (obj->getShroudedStatus(playerIndex) > OBJECTSHROUD_PARTIAL_CLEAR)
- continue; //object is fogged or shrouded, don't render it.
-
- //
- // objects with a local only unit priority will only appear on the radar if they
- // are controlled by the local player, or if the local player is an observer (cause
- // they are godlike and can see everything)
- //
- if( obj->getRadarPriority() == RADAR_PRIORITY_LOCAL_UNIT_ONLY &&
- obj->getControllingPlayer() != player &&
- player->isPlayerActive() )
- continue;
-
- // get object position
- const Coord3D *pos = obj->getPosition();
-
- // compute object position as a radar blip
- radarPoint.x = pos->x / (m_mapExtent.width() / RADAR_CELL_WIDTH);
- radarPoint.y = pos->y / (m_mapExtent.height() / RADAR_CELL_HEIGHT);
-
- // get the color we're going to draw in
- Color c = rObj->getColor();
-
-
-
- // adjust the alpha for stealth units so they "fade/blink" on the radar for the controller
- // if( obj->getRadarPriority() == RADAR_PRIORITY_LOCAL_UNIT_ONLY )
- // ML-- What the heck is this? local-only and neutral-observer-viewed units are stealthy?? Since when?
- // Now it twinkles for any stealthed object, whether locally controlled or neutral-observer-viewed
- if( obj->testStatus( OBJECT_STATUS_STEALTHED ) )
- {
- StealthUpdate* stealth = obj->getStealth();
- if( !stealth )
- continue;
-
- if ( TheControlBar->getCurrentlyViewedPlayerRelationship(obj->getTeam()) == ENEMIES )
- if( !obj->testStatus( OBJECT_STATUS_DETECTED ) && !stealth->isDisguised() )
- continue;
-
- UnsignedByte r, g, b, a;
- GameGetColorComponents( c, &r, &g, &b, &a );
-
- const UnsignedInt framesForTransition = LOGICFRAMES_PER_SECOND;
- const UnsignedByte minAlpha = 32;
-
- Real alphaScale = INT_TO_REAL(TheGameLogic->getFrame() % framesForTransition) / (framesForTransition / 2.0f);
- if( alphaScale > 0.0f )
- a = REAL_TO_UNSIGNEDBYTE( ((alphaScale - 1.0f) * (255.0f - minAlpha)) + minAlpha );
- else
- a = REAL_TO_UNSIGNEDBYTE( (alphaScale * (255.0f - minAlpha)) + minAlpha );
- c = GameMakeColor( r, g, b, a );
-
- }
-
- // cache hero objects for drawing in icon layer
- if( calcHero && obj->isHero() )
- {
- m_cachedHeroObjectList.push_back(obj);
- }
-
- // draw the blip, but make sure the points are legal
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- radarPoint.y++;
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- radarPoint.x++;
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- radarPoint.y--;
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- }
- REF_PTR_RELEASE(surface);
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Shade the color passed in using the height parameter to lighten and darken it. Colors
- * will be interpolated using the value "height" across the range from loZ to hiZ. The
- * midZ is the "middle" point, height values above it will be lightened, while
- * lower ones are darkened. */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::interpolateColorForHeight( RGBColor *color,
- Real height,
- Real hiZ,
- Real midZ,
- Real loZ )
-{
- const Real howBright = 0.95f; // bigger is brighter (0.0 to 1.0)
- const Real howDark = 0.60f; // bigger is darker (0.0 to 1.0)
-
- // sanity on map height (flat maps bomb)
- if (hiZ == midZ)
- hiZ = midZ+0.1f;
- if (midZ == loZ)
- loZ = midZ-0.1f;
- if (hiZ == loZ)
- hiZ = loZ+0.2f;
-
- Real t;
- RGBColor colorTarget;
-
- // if "over" the middle height, interpolate lighter
- if( height >= midZ )
- {
-
- // how far are we from the middleZ towards the hi Z
- t = (height - midZ) / (hiZ - midZ);
-
- // compute what our "lightest" color possible we want to use is
- colorTarget.red = color->red + (1.0f - color->red) * howBright;
- colorTarget.green = color->green + (1.0f - color->green) * howBright;
- colorTarget.blue = color->blue + (1.0f - color->blue) * howBright;
-
- }
- else // interpolate darker
- {
-
- // how far are we from the middleZ towards the low Z
- t = (midZ - height) / (midZ - loZ);
-
- // compute what the "darkest" color possible we want to use is
- colorTarget.red = color->red + (0.0f - color->red) * howDark;
- colorTarget.green = color->green + (0.0f - color->green) * howDark;
- colorTarget.blue = color->blue + (0.0f - color->blue) * howDark;
-
- }
-
- // interpolate toward the target color
- color->red = color->red + (colorTarget.red - color->red) * t;
- color->green = color->green + (colorTarget.green - color->green) * t;
- color->blue = color->blue + (colorTarget.blue - color->blue) * t;
-
- // keep the color real
- if( color->red < 0.0f )
- color->red = 0.0f;
- if( color->red > 1.0f )
- color->red = 1.0f;
- if( color->green < 0.0f )
- color->green = 0.0f;
- if( color->green > 1.0f )
- color->green = 1.0f;
- if( color->blue < 0.0f )
- color->blue = 0.0f;
- if( color->blue > 1.0f )
- color->blue = 1.0f;
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// PUBLIC METHODS /////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-W3DRadar::W3DRadar( void )
-{
-
- m_terrainTextureFormat = WW3D_FORMAT_UNKNOWN;
- m_terrainImage = NULL;
- m_terrainTexture = NULL;
-
- m_overlayTextureFormat = WW3D_FORMAT_UNKNOWN;
- m_overlayImage = NULL;
- m_overlayTexture = NULL;
-
- m_shroudTextureFormat = WW3D_FORMAT_UNKNOWN;
- m_shroudImage = NULL;
- m_shroudTexture = NULL;
-
- m_textureWidth = RADAR_CELL_WIDTH;
- m_textureHeight = RADAR_CELL_HEIGHT;
-
- m_reconstructViewBox = TRUE;
- m_viewAngle = 0.0f;
- m_viewZoom = 0.0f;
- for( Int i = 0; i < 4; i++ )
- {
-
- m_viewBox[ i ].x = 0;
- m_viewBox[ i ].y = 0;
-
- }
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-W3DRadar::~W3DRadar( void )
-{
-
- // delete resources used for the W3D radar
- deleteResources();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::xfer( Xfer *xfer )
-{
- Radar::xfer(xfer);
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Radar initialization */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::init( void )
-{
- ICoord2D size;
- Region2D uv;
-
- // extending functionality
- Radar::init();
-
- // gather specific texture format information
- initializeTextureFormats();
-
- // allocate our terrain texture
- // poolify
- m_terrainTexture = MSGNEW("TextureClass") TextureClass( m_textureWidth, m_textureHeight,
- m_terrainTextureFormat, MIP_LEVELS_1 );
- DEBUG_ASSERTCRASH( m_terrainTexture, ("W3DRadar: Unable to allocate terrain texture") );
-
- // allocate our overlay texture
- m_overlayTexture = MSGNEW("TextureClass") TextureClass( m_textureWidth, m_textureHeight,
- m_overlayTextureFormat, MIP_LEVELS_1 );
- DEBUG_ASSERTCRASH( m_overlayTexture, ("W3DRadar: Unable to allocate overlay texture") );
-
- // set filter type for the overlay texture, try it and see if you like it, I don't ;)
-// m_overlayTexture->Set_Min_Filter( TextureFilterClass::FILTER_TYPE_NONE );
-// m_overlayTexture->Set_Mag_Filter( TextureFilterClass::FILTER_TYPE_NONE );
-
- // allocate our shroud texture
- m_shroudTexture = MSGNEW("TextureClass") TextureClass( m_textureWidth, m_textureHeight,
- m_shroudTextureFormat, MIP_LEVELS_1 );
- DEBUG_ASSERTCRASH( m_shroudTexture, ("W3DRadar: Unable to allocate shroud texture") );
- m_shroudTexture->Get_Filter().Set_Min_Filter( TextureFilterClass::FILTER_TYPE_DEFAULT );
- m_shroudTexture->Get_Filter().Set_Mag_Filter( TextureFilterClass::FILTER_TYPE_DEFAULT );
-
- //
- // create images used for rendering and set them up with the textures
- //
-
- //
- // the terrain image, note the UV coords change it from (0,0) in the upper left
- // to (0,0) in the lower left cause that's how we are initially oriented in the
- // world (positive X to the right and positive Y up)
- //
- m_terrainImage = newInstance(Image);
- uv.lo.x = 0.0f;
- uv.lo.y = 1.0f;
- uv.hi.x = 1.0f;
- uv.hi.y = 0.0f;
- m_terrainImage->setStatus( IMAGE_STATUS_RAW_TEXTURE );
- m_terrainImage->setRawTextureData( m_terrainTexture );
- m_terrainImage->setUV( &uv );
- m_terrainImage->setTextureWidth( m_textureWidth );
- m_terrainImage->setTextureHeight( m_textureHeight );
- size.x = m_textureWidth;
- size.y = m_textureHeight;
- m_terrainImage->setImageSize( &size );
-
- // the overlay image
- m_overlayImage = newInstance(Image);
- uv.lo.x = 0.0f;
- uv.lo.y = 1.0f;
- uv.hi.x = 1.0f;
- uv.hi.y = 0.0f;
- m_overlayImage->setStatus( IMAGE_STATUS_RAW_TEXTURE );
- m_overlayImage->setRawTextureData( m_overlayTexture );
- m_overlayImage->setUV( &uv );
- m_overlayImage->setTextureWidth( m_textureWidth );
- m_overlayImage->setTextureHeight( m_textureHeight );
- size.x = m_textureWidth;
- size.y = m_textureHeight;
- m_overlayImage->setImageSize( &size );
-
- // the shroud image
- m_shroudImage = newInstance(Image);
- uv.lo.x = 0.0f;
- uv.lo.y = 1.0f;
- uv.hi.x = 1.0f;
- uv.hi.y = 0.0f;
- m_shroudImage->setStatus( IMAGE_STATUS_RAW_TEXTURE );
- m_shroudImage->setRawTextureData( m_shroudTexture );
- m_shroudImage->setUV( &uv );
- m_shroudImage->setTextureWidth( m_textureWidth );
- m_shroudImage->setTextureHeight( m_textureHeight );
- size.x = m_textureWidth;
- size.y = m_textureHeight;
- m_shroudImage->setImageSize( &size );
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset the radar to the initial empty state ready for new data */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::reset( void )
-{
-
- // extending functionality, call base class
- Radar::reset();
-
- m_cachedHeroObjectList.clear();
-
- // clear our texture data, but do not delete the resources
- SurfaceClass *surface;
-
- surface = m_terrainTexture->Get_Surface_Level();
- if( surface )
- {
- surface->Clear();
- REF_PTR_RELEASE(surface);
- }
-
- surface = m_overlayTexture->Get_Surface_Level();
- if( surface )
- {
- surface->Clear();
- REF_PTR_RELEASE(surface);
- }
-
- // don't call Clear(); that wips to transparent. do this instead.
- //gs Dude, it's called CLEARshroud. It needs to clear the shroud.
- clearShroud();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Update */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::update( void )
-{
-
- // extend base class
- Radar::update();
-
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-RadarObjectType W3DRadar::addObject( Object* obj )
-{
- RadarObjectType addedType = Radar::addObject(obj);
-
- if (addedType == RadarObjectType_Local)
- {
- if (obj->isHero() && !RadarObject::isTemporarilyHidden(obj))
- {
- m_cachedHeroObjectList.push_back(obj);
- }
- }
-
- return addedType;
-}
-
-//-------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-RadarObjectType W3DRadar::removeObject( Object* obj )
-{
- RadarObjectType removedType = Radar::removeObject(obj);
-
- if (removedType == RadarObjectType_Local)
- {
- stl::find_and_erase_unordered(m_cachedHeroObjectList, obj);
- }
-
- return removedType;
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Reset the radar for the new map data being given to it */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::newMap( TerrainLogic *terrain )
-{
-
- //
- // extending functionality, call the base class ... this will cause a reset of the
- // system which will clear out our textures but not free them
- //
- Radar::newMap( terrain );
-
- // sanity
- if( terrain == NULL )
- return;
-
- // build terrain texture
- buildTerrainTexture( terrain );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void W3DRadar::buildTerrainTexture( TerrainLogic *terrain )
-{
- SurfaceClass *surface;
- RGBColor waterColor;
-
- // we will want to reconstruct our new view box now
- m_reconstructViewBox = TRUE;
-
- // setup our water color
- waterColor.red = TheWaterTransparency->m_radarColor.red;
- waterColor.green = TheWaterTransparency->m_radarColor.green;
- waterColor.blue = TheWaterTransparency->m_radarColor.blue;
-
- // get the terrain surface to draw in
- surface = m_terrainTexture->Get_Surface_Level();
- DEBUG_ASSERTCRASH( surface, ("W3DRadar: Can't get surface for terrain texture") );
-
- // build the terrain
- RGBColor sampleColor;
- RGBColor color;
- Int i, j, samples;
- Int x, y, z;
- ICoord2D radarPoint;
- Coord3D worldPoint;
- Bridge *bridge;
- for( y = 0; y < m_textureHeight; y++ )
- {
-
- for( x = 0; x < m_textureWidth; x++ )
- {
-
- // what point are we inspecting
- radarPoint.x = x;
- radarPoint.y = y;
- radarToWorld( &radarPoint, &worldPoint );
-
- // get height of the terrain at this sample point
- z = terrain->getGroundHeight( worldPoint.x, worldPoint.y );
-
- // check to see if this point is part of a working bridge
- Bool workingBridge = FALSE;
- bridge = TheTerrainLogic->findBridgeAt( &worldPoint );
- if( bridge != NULL )
- {
- Object *obj = TheGameLogic->findObjectByID( bridge->peekBridgeInfo()->bridgeObjectID );
-
- if( obj )
- {
- BodyModuleInterface *body = obj->getBodyModule();
-
- if( body->getDamageState() != BODY_RUBBLE )
- workingBridge = TRUE;
-
- }
-
- }
-
- // create a color based on the Z height of the map
- Real waterZ;
- if( workingBridge == FALSE && terrain->isUnderwater( worldPoint.x, worldPoint.y, &waterZ ) )
- {
- const Int waterSamplesAway = 1; // how many "tiles" from the center tile we will sample away
- // to average a color for the tile color
-
- sampleColor.red = sampleColor.green = sampleColor.blue = 0.0f;
- samples = 0;
-
- for( j = y - waterSamplesAway; j <= y + waterSamplesAway; j++ )
- {
-
- if( j >= 0 && j < m_textureHeight )
- {
-
- for( i = x - waterSamplesAway; i <= x + waterSamplesAway; i++ )
- {
-
- if( i >= 0 && i < m_textureWidth )
- {
-
- // the the world point we are concerned with
- radarPoint.x = i;
- radarPoint.y = j;
- radarToWorld( &radarPoint, &worldPoint );
-
- // get Z at this sample height
- Real underwaterZ = terrain->getGroundHeight( worldPoint.x, worldPoint.y );
-
- // get color for this Z and add to our sample color
- if( terrain->isUnderwater( worldPoint.x, worldPoint.y ) )
- {
-
- // this is our "color" for water
- color = waterColor;
-
- // interpolate the water color for height in the water table
- interpolateColorForHeight( &color, underwaterZ, waterZ,
- waterZ,
- m_mapExtent.lo.z );
-
- // add color to our samples
- sampleColor.red += color.red;
- sampleColor.green += color.green;
- sampleColor.blue += color.blue;
- samples++;
-
- }
-
- }
-
- }
-
- }
-
- }
-
- // prevent divide by zeros
- if( samples == 0 )
- samples = 1;
-
- // set the color to an average of the colors read
- color.red = sampleColor.red / (Real)samples;
- color.green = sampleColor.green / (Real)samples;
- color.blue = sampleColor.blue / (Real)samples;
-
- }
- else // regular terrain ...
- {
- const Int samplesAway = 1; // how many "tiles" from the center tile we will sample away
- // to average a color for the tile color
-
- sampleColor.red = sampleColor.green = sampleColor.blue = 0.0f;
- samples = 0;
-
- for( j = y - samplesAway; j <= y + samplesAway; j++ )
- {
-
- if( j >= 0 && j < m_textureHeight )
- {
-
- for( i = x - samplesAway; i <= x + samplesAway; i++ )
- {
-
- if( i >= 0 && i < m_textureWidth )
- {
-
- // the the world point we are concerned with
- radarPoint.x = i;
- radarPoint.y = j;
- radarToWorld( &radarPoint, &worldPoint );
-
- // get the color we're going to use here
- if( workingBridge )
- {
- AsciiString bridgeTName = bridge->getBridgeTemplateName();
- TerrainRoadType *bridgeTemplate = TheTerrainRoads->findBridge( bridgeTName );
-
- // sanity
- DEBUG_ASSERTCRASH( bridgeTemplate, ("W3DRadar::buildTerrainTexture - Can't find bridge template for '%s'", bridgeTName.str()) );
-
- // use bridge color
- if ( bridgeTemplate )
- color = bridgeTemplate->getRadarColor();
- else
- color.setFromInt(0xffffffff);
- //
- // we won't use the height of the terrain at this sample point, we will
- // instead use the height for the entire bridge
- //
- Real bridgeHeight = (bridge->peekBridgeInfo()->fromLeft.z +
- bridge->peekBridgeInfo()->fromRight.z +
- bridge->peekBridgeInfo()->toLeft.z +
- bridge->peekBridgeInfo()->toRight.z) / 4.0f;
-
- // interpolate the color, but use the bridge height, not the terrain height
- interpolateColorForHeight( &color, bridgeHeight,
- getTerrainAverageZ(),
- m_mapExtent.hi.z, m_mapExtent.lo.z );
-
- }
- else
- {
-
- // get the color at this point
- TheTerrainVisual->getTerrainColorAt( worldPoint.x, worldPoint.y, &color );
-
- // interpolate the color for height
- interpolateColorForHeight( &color, z, getTerrainAverageZ(),
- m_mapExtent.hi.z, m_mapExtent.lo.z );
-
- }
-
- // add color to our samples
- sampleColor.red += color.red;
- sampleColor.green += color.green;
- sampleColor.blue += color.blue;
- samples++;
-
- }
-
- }
-
- }
-
- }
-
- // prevent divide by zeros
- if( samples == 0 )
- samples = 1;
-
- // set the color to an average of the colors read
- color.red = sampleColor.red / (Real)samples;
- color.green = sampleColor.green / (Real)samples;
- color.blue = sampleColor.blue / (Real)samples;
-
- }
-
- //
- // draw the pixel for the terrain at this point, note that because of the orientation
- // of our world we draw it with positive y in the "up" direction
- //
- // FYI: I tried making this faster by pulling out all the code inside DrawPixel
- // and locking only once ... but it made absolutely *no* performance difference,
- // the sampling and interpolation algorithm for generating pretty looking terrain
- // and water for the radar is just, well, expensive.
- //
- surface->DrawPixel( x, y, GameMakeColor( color.red * 255,
- color.green * 255,
- color.blue * 255,
- 255 ) );
-
- }
-
- }
-
- // all done with the surface
- REF_PTR_RELEASE(surface);
-
-}
-
-// ------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::clearShroud()
-{
-#if ENABLE_CONFIGURABLE_SHROUD
- if (!TheGlobalData->m_shroudOn)
- return;
-#endif
-
- SurfaceClass *surface = m_shroudTexture->Get_Surface_Level();
-
- // fill to clear, shroud will make black. Don't want to make something black that logic can't clear
- unsigned int color = GameMakeColor( 0, 0, 0, 0 );
- for( Int y = 0; y < m_textureHeight; y++ )
- {
- surface->DrawHLine(y, 0, m_textureWidth-1, color);
- }
- REF_PTR_RELEASE(surface);
-}
-
-// ------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::setShroudLevel(Int shroudX, Int shroudY, CellShroudStatus setting)
-{
-#if ENABLE_CONFIGURABLE_SHROUD
- if (!TheGlobalData->m_shroudOn)
- return;
-#endif
-
- W3DShroud* shroud = TheTerrainRenderObject ? TheTerrainRenderObject->getShroud() : NULL;
- if (!shroud)
- return;
-
- SurfaceClass* surface = m_shroudTexture->Get_Surface_Level();
- DEBUG_ASSERTCRASH( surface, ("W3DRadar: Can't get surface for Shroud texture") );
-
- Int mapMinX = shroudX * shroud->getCellWidth();
- Int mapMinY = shroudY * shroud->getCellHeight();
- Int mapMaxX = (shroudX+1) * shroud->getCellWidth();
- Int mapMaxY = (shroudY+1) * shroud->getCellHeight();
-
- ICoord2D radarPoint;
- Coord3D worldPoint;
-
- worldPoint.x = mapMinX;
- worldPoint.y = mapMinY;
- worldToRadar( &worldPoint, &radarPoint );
- Int radarMinX = radarPoint.x;
- Int radarMinY = radarPoint.y;
-
- worldPoint.x = mapMaxX;
- worldPoint.y = mapMaxY;
- worldToRadar( &worldPoint, &radarPoint );
- Int radarMaxX = radarPoint.x;
- Int radarMaxY = radarPoint.y;
-
-/*
- Int radarMinX = REAL_TO_INT_FLOOR(mapMinX / getXSample());
- Int radarMinY = REAL_TO_INT_FLOOR(mapMinY / getYSample());
- Int radarMaxX = REAL_TO_INT_CEIL(mapMaxX / getXSample());
- Int radarMaxY = REAL_TO_INT_CEIL(mapMaxY / getYSample());
-*/
-
- /// @todo srj -- this really needs to smooth the display!
-
- //Logic is saying shroud. We can add alpha levels here in client if needed.
- // W3DShroud is a 0-255 alpha byte. Logic shroud is a double reference count.
- Int alpha;
- if( setting == CELLSHROUD_SHROUDED )
- alpha = 255;
- else if( setting == CELLSHROUD_FOGGED )
- alpha = 127;///< @todo placeholder to get feedback on logic work while graphic side being decided
- else
- alpha = 0;
-
- for( Int y = radarMinY; y <= radarMaxY; y++ )
- {
- for( Int x = radarMinX; x <= radarMaxX; x++ )
- {
- if( legalRadarPoint( x, y ) )
- surface->DrawPixel( x, y, GameMakeColor( 0, 0, 0, alpha ) );
- }
- }
- REF_PTR_RELEASE(surface);
-}
-
-//-------------------------------------------------------------------------------------------------
-/** Actually draw the radar at the screen coordinates provided
- * NOTE about how drawing works: The radar images are computed at samples across the
- * map and are built into a "square" texture area. At the time of drawing and computing
- * radar<->world coords we consider the "ratio" of width to height of the map dimensions
- * so that when we draw we preserve the aspect ratio of the map and don't squish it in
- * any direction that would cause the map to be distorted. Extra blank space is drawn
- * around the radar images to keep the whole radar area covered when the map displayed
- * is "long" or "tall" */
-//-------------------------------------------------------------------------------------------------
-void W3DRadar::draw( Int pixelX, Int pixelY, Int width, Int height )
-{
- // if the local player does not have a radar then we can't draw anything
- if( !rts::localPlayerHasRadar() )
- return;
-
- //
- // given a upper left corner at pixelX|Y and a width and height to draw into, figure out
- // where we should start and end the image so that the final drawn image has the
- // same ratio as the map and isn't stretched or distorted
- //
- ICoord2D ul, lr;
- findDrawPositions( pixelX, pixelY, width, height, &ul, &lr );
-
- Int scaledWidth = lr.x - ul.x;
- Int scaledHeight = lr.y - ul.y;
-
- // draw black border areas where we need map
- Color fillColor = GameMakeColor( 0, 0, 0, 255 );
- Color lineColor = GameMakeColor( 50, 50, 50, 255 );
- if( m_mapExtent.width()/width >= m_mapExtent.height()/height )
- {
-
- // draw horizontal bars at top and bottom
- TheDisplay->drawFillRect( pixelX, pixelY, width, ul.y - pixelY - 1, fillColor );
- TheDisplay->drawFillRect( pixelX, lr.y + 1, width, pixelY + height - lr.y - 1, fillColor);
- TheDisplay->drawLine(pixelX, ul.y, pixelX + width, ul.y, 1, lineColor);
- TheDisplay->drawLine(pixelX, lr.y + 1, pixelX + width, lr.y + 1, 1, lineColor);
-
- }
- else
- {
-
- // draw vertical bars to the left and right
- TheDisplay->drawFillRect( pixelX, pixelY, ul.x - pixelX - 1, height, fillColor );
- TheDisplay->drawFillRect( lr.x + 1, pixelY, width - (lr.x - pixelX) - 1, height, fillColor );
- TheDisplay->drawLine(ul.x, pixelY, ul.x, pixelY + height, 1, lineColor);
- TheDisplay->drawLine(lr.x + 1, pixelY, lr.x + 1, pixelY + height, 1, lineColor);
-
- }
-
- // draw the terrain texture
- TheDisplay->drawImage( m_terrainImage, ul.x, ul.y, lr.x, lr.y );
-
- // refresh the overlay texture once every so many frames
- if( TheGameClient->getFrame() % OVERLAY_REFRESH_RATE == 0 )
- {
- updateObjectTexture(m_overlayTexture);
- }
-
- // draw the overlay image
- TheDisplay->drawImage( m_overlayImage, ul.x, ul.y, lr.x, lr.y );
-
- // draw the shroud image
-#if ENABLE_CONFIGURABLE_SHROUD
- if( TheGlobalData->m_shroudOn )
-#else
- if (true)
-#endif
- {
- TheDisplay->drawImage( m_shroudImage, ul.x, ul.y, lr.x, lr.y );
- }
-
- // draw any icons
- drawIcons( ul.x, ul.y, scaledWidth, scaledHeight );
-
- // draw any radar events
- drawEvents( ul.x, ul.y, scaledWidth, scaledHeight );
-
- // see if we need to reconstruct the view box
- if( TheTacticalView->getZoom() != m_viewZoom )
- m_reconstructViewBox = TRUE;
- if( TheTacticalView->getAngle() != m_viewAngle )
- m_reconstructViewBox = TRUE;
-
- if( m_reconstructViewBox == TRUE )
- reconstructViewBox();
-
- // draw the view region on top of the radar reconstructing if necessary
- drawViewBox( ul.x, ul.y, scaledWidth, scaledHeight );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void W3DRadar::refreshTerrain( TerrainLogic *terrain )
-{
-
- // extend base class
- Radar::refreshTerrain( terrain );
-
- // rebuild the entire terrain texture
- buildTerrainTexture( terrain );
-
-}
-
-// ------------------------------------------------------------------------------------------------
-// ------------------------------------------------------------------------------------------------
-void W3DRadar::refreshObjects()
-{
- if constexpr (OVERLAY_REFRESH_RATE > 1)
- {
- if (m_overlayTexture != NULL)
- {
- updateObjectTexture(m_overlayTexture);
- }
- }
-}
-
-
-
-///The following is an "archive" of an attempt to foil the mapshroud hack... saved for later, since it is too close to release to try it
-
-
-/*
- *
- void W3DRadar::renderObjectList( const RadarObject *listHead, TextureClass *texture )
-{
-
- // sanity
- if( listHead == NULL || texture == NULL )
- return;
-
- // get surface for texture to render into
- SurfaceClass *surface = texture->Get_Surface_Level();
-
- // loop through all objects and draw
- ICoord2D radarPoint;
-
- Player *player = rts::getObservedOrLocalPlayer();
- const Int playerIndex = player->getPlayerIndex();
-
- UnsignedByte minAlpha = 8;
-
- for( const RadarObject *rObj = listHead; rObj; rObj = rObj->friend_getNext() )
- {
- UnsignedByte h = (UnsignedByte)(rObj->isTemporarilyHidden());
- if ( h )
- continue;
-
- UnsignedByte a = 0;
-
- // get object
- const Object *obj = rObj->friend_getObject();
- UnsignedByte r = 1; // all decoys
-
- // get the color we're going to draw in
- UnsignedInt c = 0xfe000000;// this is a decoy
- c |= (UnsignedInt)( obj->testStatus( OBJECT_STATUS_STEALTHED ) );//so is this
-
- // check for shrouded status
- UnsignedByte k = (UnsignedByte)(obj->getShroudedStatus(playerIndex) > OBJECTSHROUD_PARTIAL_CLEAR);
- if ( k || a)
- continue; //object is fogged or shrouded, don't render it.
-
- //
- // objects with a local only unit priority will only appear on the radar if they
- // are controlled by the local player, or if the local player is an observer (cause
- // they are godlike and can see everything)
- //
- if( obj->getRadarPriority() == RADAR_PRIORITY_LOCAL_UNIT_ONLY &&
- obj->getControllingPlayer() != player &&
- player->isPlayerActive() )
- continue;
-
- UnsignedByte g = c|a;
- UnsignedByte b = h|a;
- // get object position
- const Coord3D *pos = obj->getPosition();
-
- // compute object position as a radar blip
- radarPoint.x = pos->x / (m_mapExtent.width() / RADAR_CELL_WIDTH);
- radarPoint.y = pos->y / (m_mapExtent.height() / RADAR_CELL_HEIGHT);
-
-
- const UnsignedInt framesForTransition = LOGICFRAMES_PER_SECOND;
-
-
-
- // adjust the alpha for stealth units so they "fade/blink" on the radar for the controller
- // if( obj->getRadarPriority() == RADAR_PRIORITY_LOCAL_UNIT_ONLY )
- // ML-- What the heck is this? local-only and neutral-observier-viewed units are stealthy?? Since when?
- // Now it twinkles for any stealthed object, whether locally controlled or neutral-observier-viewed
- c = rObj->getColor();
-
- if( g & r )
- {
- Real alphaScale = INT_TO_REAL(TheGameLogic->getFrame() % framesForTransition) / (framesForTransition * 0.5f);
- minAlpha <<= 2; // decoy
-
- if ( ( obj->isLocallyControlled() == (Bool)a ) // another decoy, comparing the return of this non-inline with a local
- && !obj->testStatus( OBJECT_STATUS_DISGUISED )
- && !obj->testStatus( OBJECT_STATUS_DETECTED )
- && ++a != 0 // The trick is that this increment does not occur unless all three above conditions are true
- && minAlpha == 32 // tricksy hobbit decoy
- && c != 0 ) // ditto
- {
- g = (UnsignedByte)(rObj->getColor());
- continue;
- }
-
- a |= k | b;
- GameGetColorComponentsWithCheatSpy( c, &r, &g, &b, &a );//this function does not touch the low order bit in 'a'
-
-
- if( alphaScale > 0.0f )
- a = REAL_TO_UNSIGNEDBYTE( ((alphaScale - 1.0f) * (255.0f - minAlpha)) + minAlpha );
- else
- a = REAL_TO_UNSIGNEDBYTE( (alphaScale * (255.0f - minAlpha)) + minAlpha );
- c = GameMakeColor( r, g, b, a );
-
- }
-
-
-
-
- // draw the blip, but make sure the points are legal
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- radarPoint.x++;
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- radarPoint.y++;
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
- radarPoint.x--;
- if( legalRadarPoint( radarPoint.x, radarPoint.y ) )
- surface->DrawPixel( radarPoint.x, radarPoint.y, c );
-
-
-
-
- }
- REF_PTR_RELEASE(surface);
-
-}
-
-
- *
- */
diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt
index b45d8684f7..07e074e4c3 100644
--- a/GeneralsMD/Code/GameEngine/CMakeLists.txt
+++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt
@@ -77,7 +77,7 @@ set(GAMEENGINE_SRC
Include/Common/Money.h
Include/Common/MultiplayerSettings.h
Include/Common/NameKeyGenerator.h
- Include/Common/ObjectStatusTypes.h
+# Include/Common/ObjectStatusTypes.h
Include/Common/OSDisplay.h
Include/Common/Overridable.h
Include/Common/Override.h
@@ -90,7 +90,7 @@ set(GAMEENGINE_SRC
Include/Common/ProductionPrerequisite.h
Include/Common/QuickmatchPreferences.h
Include/Common/QuotedPrintable.h
- Include/Common/Radar.h
+# Include/Common/Radar.h
# Include/Common/RAMFile.h
# Include/Common/RandomValue.h
Include/Common/Recorder.h
@@ -652,9 +652,9 @@ set(GAMEENGINE_SRC
# Source/Common/System/LocalFile.cpp
# Source/Common/System/LocalFileSystem.cpp
#Source/Common/System/MemoryInit.cpp
- Source/Common/System/ObjectStatusTypes.cpp
+# Source/Common/System/ObjectStatusTypes.cpp
Source/Common/System/QuotedPrintable.cpp
- Source/Common/System/Radar.cpp
+# Source/Common/System/Radar.cpp
# Source/Common/System/RAMFile.cpp
Source/Common/System/registry.cpp
Source/Common/System/SaveGame/GameState.cpp
diff --git a/GeneralsMD/Code/GameEngine/Include/Common/Radar.h b/GeneralsMD/Code/GameEngine/Include/Common/Radar.h
deleted file mode 100644
index bfa7a008e2..0000000000
--- a/GeneralsMD/Code/GameEngine/Include/Common/Radar.h
+++ /dev/null
@@ -1,312 +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 .
-*/
-
-////////////////////////////////////////////////////////////////////////////////
-// //
-// (c) 2001-2003 Electronic Arts Inc. //
-// //
-////////////////////////////////////////////////////////////////////////////////
-
-// FILE: Radar.h //////////////////////////////////////////////////////////////////////////////////
-// Author: Colin Day, January 2002
-// Desc: Logical radar implementation
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
-#include "Lib/BaseType.h"
-#include "Common/SubsystemInterface.h"
-#include "Common/GameMemory.h"
-#include "GameClient/Display.h" // for ShroudLevel
-#include "GameClient/Color.h"
-
-// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
-class GameWindow;
-class Object;
-class Player;
-class TerrainLogic;
-
-// GLOBAL /////////////////////////////////////////////////////////////////////////////////////////
-//
-// the following is used for the resolution of the radar "cells" ... this is how accurate
-// the radar is and also reflects directly the size of the image we build ... which with
-// WW3D must be a square power of two as well
-//
-enum
-{
- RADAR_CELL_WIDTH = 128, // radar created at this horz resolution
- RADAR_CELL_HEIGHT = 128 // radar created at this vert resolution
-};
-
-//-------------------------------------------------------------------------------------------------
-/** These event types determine the colors radar events happen in to make it easier for us
- * to play events with a consistent color scheme */
-//-------------------------------------------------------------------------------------------------
-enum RadarEventType CPP_11(: Int)
-{
- RADAR_EVENT_INVALID = 0,
- RADAR_EVENT_CONSTRUCTION,
- RADAR_EVENT_UPGRADE,
- RADAR_EVENT_UNDER_ATTACK,
- RADAR_EVENT_INFORMATION,
- RADAR_EVENT_BEACON_PULSE,
- RADAR_EVENT_INFILTRATION, //for defection, hijacking, hacking, carbombing, and other sneaks
- RADAR_EVENT_BATTLE_PLAN,
- RADAR_EVENT_STEALTH_DISCOVERED, // we discovered a stealth unit
- RADAR_EVENT_STEALTH_NEUTRALIZED, // our stealth unit has been revealed
- RADAR_EVENT_FAKE, //Internally creates a radar event, but doesn't notify the player (unit lost
- //for example, so we can use the spacebar to jump to the event).
-
- RADAR_EVENT_NUM_EVENTS
-
-};
-
-enum RadarObjectType CPP_11(: Int)
-{
- RadarObjectType_None = 0,
- RadarObjectType_Regular,
- RadarObjectType_Local,
-};
-
-// PROTOTYPES /////////////////////////////////////////////////////////////////////////////////////
-
-//-------------------------------------------------------------------------------------------------
-/** Radar objects are objects that are on the radar, go figure :) */
-//-------------------------------------------------------------------------------------------------
-class RadarObject : public MemoryPoolObject,
- public Snapshot
-{
-
- MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( RadarObject, "RadarObject" )
-
-public:
-
- RadarObject( void );
- // destructor prototype defined by memory pool glue
-
- // color management
- void setColor( Color c ) { m_color = c; }
- inline Color getColor( void ) const { return m_color; }
-
- inline void friend_setObject( Object *obj ) { m_object = obj; }
- inline Object *friend_getObject( void ) { return m_object; }
- inline const Object *friend_getObject( void ) const { return m_object; }
-
- inline void friend_setNext( RadarObject *next ) { m_next = next; }
- inline RadarObject *friend_getNext( void ) { return m_next; }
- inline const RadarObject *friend_getNext( void ) const { return m_next; }
-
- Bool isTemporarilyHidden() const;
- static Bool isTemporarilyHidden(const Object* obj);
-
-protected:
-
- // snapshot methods
- virtual void crc( Xfer *xfer );
- virtual void xfer( Xfer *xfer );
- virtual void loadPostProcess( void );
-
- Object *m_object; ///< the object
- RadarObject *m_next; ///< next radar object
- Color m_color; ///< color to draw for this object on the radar
-
-};
-
-//-------------------------------------------------------------------------------------------------
-/** Radar priorities. Keep this in sync with the priority names list below */
-//-------------------------------------------------------------------------------------------------
-enum RadarPriorityType CPP_11(: Int)
-{
- RADAR_PRIORITY_INVALID, // a priority that has not been set (in general it won't show up on the radar)
- RADAR_PRIORITY_NOT_ON_RADAR, // object specifically forbidden from being on the radar
- RADAR_PRIORITY_STRUCTURE, // structure level drawing priority
- RADAR_PRIORITY_UNIT, // unit level drawing priority
- RADAR_PRIORITY_LOCAL_UNIT_ONLY, // unit priority, but only on the radar if controlled by the local player
-
- RADAR_PRIORITY_NUM_PRIORITIES
-};
-#ifdef DEFINE_RADAR_PRIORITY_NAMES
-static const char *const RadarPriorityNames[] =
-{
- "INVALID", // a priority that has not been set (in general it won't show up on the radar)
- "NOT_ON_RADAR", // object specifically forbidden from being on the radar
- "STRUCTURE", // structure level drawing priority
- "UNIT", // unit level drawing priority
- "LOCAL_UNIT_ONLY", // unit priority, but only on the radar if controlled by the local player
-
- NULL
-};
-static_assert(ARRAY_SIZE(RadarPriorityNames) == RADAR_PRIORITY_NUM_PRIORITIES + 1, "Incorrect array size");
-#endif // DEFINE_RADAR_PRIOTITY_NAMES
-
-//-------------------------------------------------------------------------------------------------
-/** Interface for the radar */
-//-------------------------------------------------------------------------------------------------
-class Radar : public Snapshot,
- public SubsystemInterface
-{
-
-public:
-
- Radar( void );
- virtual ~Radar( void );
-
- virtual void init( void ) { } ///< subsystem initialization
- virtual void reset( void ); ///< subsystem reset
- virtual void update( void ); ///< subsystem per frame update
-
- // is the game window parameter the radar window
- Bool isRadarWindow( GameWindow *window ) { return (m_radarWindow == window) && (m_radarWindow != NULL); }
-
- Bool radarToWorld( const ICoord2D *radar, Coord3D *world ); ///< radar point to world point on terrain
- Bool radarToWorld2D( const ICoord2D *radar, Coord3D *world ); ///< radar point to world point (x,y only!)
- Bool worldToRadar( const Coord3D *world, ICoord2D *radar ); ///< translate world point to radar (x,y)
- Bool localPixelToRadar( const ICoord2D *pixel, ICoord2D *radar ); ///< translate pixel (with UL of radar being (0,0)) to logical radar coordinates
- Bool screenPixelToWorld( const ICoord2D *pixel, Coord3D *world ); ///< translate pixel (with UL of the screen being (0,0)) to world position in the world
- Object *objectUnderRadarPixel( const ICoord2D *pixel ); ///< return the object (if any) represented by the pixel coordinates passed in
- void findDrawPositions( Int startX, Int startY, Int width, Int height,
- ICoord2D *ul, ICoord2D *lr ); ///< make translation for screen area of radar square to scaled aspect ratio preserving points inside the radar area
-
- // priority inquiry
- static Bool isPriorityVisible( RadarPriorityType priority ); ///< is the priority passed in a "visible" one on the radar
-
- // radar events
- void createEvent( const Coord3D *world, RadarEventType type, Real secondsToLive = 4.0f ); ///< create radar event at location in world
- void createPlayerEvent( Player *player, const Coord3D *world, RadarEventType type, Real secondsToLive = 4.0f ); ///< create radar event using player colors
-
- Bool getLastEventLoc( Coord3D *eventPos ); ///< get last event loc (if any)
- void tryUnderAttackEvent( const Object *obj ); ///< try to make an "under attack" event if it's the proper time
- void tryInfiltrationEvent( const Object *obj ); ///< try to make an "infiltration" event if it's the proper time
- Bool tryEvent( RadarEventType event, const Coord3D *pos ); ///< try to make a "stealth" event
-
- // adding and removing objects from the radar
- virtual RadarObjectType addObject( Object *obj ); ///< add object to radar
- virtual RadarObjectType removeObject( Object *obj ); ///< remove object from radar
-
- // radar options
- void hide( Int playerIndex, Bool hide ) { m_radarHidden[playerIndex] = hide; } ///< hide/show the radar
- Bool isRadarHidden( Int playerIndex ) { return m_radarHidden[playerIndex]; } ///< is radar hidden
- // other radar option methods here like the ability to show a certain
- // team, show buildings, show units at all, etc
-
- // forcing the radar on/off regardless of player situation
- void forceOn( Int playerIndex, Bool force ) { m_radarForceOn[playerIndex] = force; } ///< force the radar to be on
- Bool isRadarForced( Int playerIndex ) { return m_radarForceOn[playerIndex]; } ///< is radar forced on?
-
- /// refresh the water values for the radar
- virtual void refreshTerrain( TerrainLogic *terrain );
-
- /// refresh the radar when the state of world objects changes drastically
- virtual void refreshObjects() {};
-
- /// queue a refresh of the terrain at the next available time
- virtual void queueTerrainRefresh( void );
-
- virtual void newMap( TerrainLogic *terrain ); ///< reset radar for new map
-
- virtual void draw( Int pixelX, Int pixelY, Int width, Int height ) = 0; ///< draw the radar
-
- /// empty the entire shroud
- virtual void clearShroud() = 0;
-
- /// set the shroud level at shroud cell x,y
- virtual void setShroudLevel( Int x, Int y, CellShroudStatus setting ) = 0;
-
-protected:
-
- // snapshot methods
- virtual void crc( Xfer *xfer );
- virtual void xfer( Xfer *xfer );
- virtual void loadPostProcess( void );
-
- /// internal method for creating a radar event with specific colors
- void internalCreateEvent( const Coord3D *world, RadarEventType type, Real secondsToLive,
- const RGBAColorInt *color1, const RGBAColorInt *color2 );
-
- void deleteListResources( void ); ///< delete list radar resources used
- Bool deleteFromList( Object *obj, RadarObject **list ); ///< try to remove object from specific list
-
- inline Real getTerrainAverageZ() const { return m_terrainAverageZ; }
- inline Real getWaterAverageZ() const { return m_waterAverageZ; }
- inline const RadarObject* getObjectList() const { return m_objectList; }
- inline const RadarObject* getLocalObjectList() const { return m_localObjectList; }
-
- void clearAllEvents( void ); ///< remove all radar events in progress
-
- // search the object list for an object that maps to the given logical radar coordinates
- Object *searchListForRadarLocationMatch( RadarObject *listHead, ICoord2D *radarMatch );
-
- Bool m_radarHidden[MAX_PLAYER_COUNT]; ///< true when radar is not visible
- Bool m_radarForceOn[MAX_PLAYER_COUNT]; ///< true when radar is forced to be on
- RadarObject *m_objectList; ///< list of objects in the radar
- RadarObject *m_localObjectList; /** list of objects for the local player, sorted
- * in exactly the same priority as the regular
- * object list for all other objects */
-// typedef std::list