diff --git a/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h b/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h index c370ac5b3c0..6496fb891bb 100644 --- a/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h +++ b/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h @@ -48,6 +48,7 @@ #define K_TRIGGERS_VERSION_1 1 #define K_TRIGGERS_VERSION_2 2 // Added m_isWaterArea #define K_TRIGGERS_VERSION_3 3 // Added m_isRiver & m_riverStart +#define K_TRIGGERS_VERSION_4 4 // Added layer name. #define K_LIGHTING_VERSION_1 1 #define K_LIGHTING_VERSION_2 2 // Added 2 additional global lights for objects. #define K_LIGHTING_VERSION_3 3 // Added 2 additional global lights for terrain. diff --git a/Generals/Code/GameEngine/Include/GameLogic/PolygonTrigger.h b/Generals/Code/GameEngine/Include/GameLogic/PolygonTrigger.h index d3e133834fc..7a908e7d1ec 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/PolygonTrigger.h +++ b/Generals/Code/GameEngine/Include/GameLogic/PolygonTrigger.h @@ -81,6 +81,11 @@ class PolygonTrigger : public MemoryPoolObject, Bool m_exportWithScripts; Bool m_isWaterArea; ///< Used to specify water areas in the map. Bool m_isRiver; ///< Used to specify that a water area is a river. +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + AsciiString m_layerName; ///< Used to specify the layer in the World Builder. + Bool m_shouldRender; + Bool m_selected; +#endif static PolygonTrigger* ThePolygonTriggerListPtr; static Int s_currentID; ///< Current id for new triggers. @@ -116,6 +121,17 @@ class PolygonTrigger : public MemoryPoolObject, void deletePoint(Int ndx); void setTriggerName(AsciiString name) {m_triggerName = name;}; +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + void setLayerName(AsciiString name) {m_layerName = name;}; + AsciiString getLayerName() const {return m_layerName;} + + void setShouldRender(Bool toggle) {m_shouldRender = toggle;} + Bool getShouldRender() {return m_shouldRender;} + + void setSelected(Bool toggle) {m_selected = toggle;} + Bool getSelected() {return m_selected;} +#endif + void getCenterPoint(Coord3D* pOutCoord) const; Real getRadius() const; diff --git a/Generals/Code/GameEngine/Include/GameLogic/TerrainLogic.h b/Generals/Code/GameEngine/Include/GameLogic/TerrainLogic.h index ad1db103499..c362afecf1f 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/TerrainLogic.h +++ b/Generals/Code/GameEngine/Include/GameLogic/TerrainLogic.h @@ -312,6 +312,9 @@ class TerrainLogic : public Snapshot, void setActiveBoundary(Int newActiveBoundary); void flattenTerrain(Object *obj); ///< Flatten the terrain under a building. +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + void createCraterInTerrain(Object *obj); ///< Flatten the terrain under a building. +#endif protected: diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp index 6cea7c6227a..869825775b3 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp @@ -48,6 +48,10 @@ m_numPoints(0), m_sizePoints(0), m_exportWithScripts(false), m_isWaterArea(false), +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) +m_shouldRender(true), +m_selected(false), +#endif m_isRiver(FALSE), m_riverStart(0) { @@ -140,6 +144,9 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu Bool isRiver; Int riverStart; AsciiString triggerName; +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + AsciiString layerName; +#endif // Remove any existing polygon triggers, if any. PolygonTrigger::deleteTriggers(); // just in case. PolygonTrigger *pPrevTrig = nullptr; @@ -148,6 +155,11 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu while (count>0) { count--; triggerName = file.readAsciiString(); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + if (info->version >= K_TRIGGERS_VERSION_4) { + layerName = file.readAsciiString(); + } +#endif triggerID = file.readInt(); isWater = false; if (info->version >= K_TRIGGERS_VERSION_2) { @@ -163,6 +175,11 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu numPoints = file.readInt(); PolygonTrigger *pTrig = newInstance(PolygonTrigger)(numPoints+1); pTrig->setTriggerName(triggerName); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + if (info->version >= K_TRIGGERS_VERSION_4) { + pTrig->setLayerName(layerName); + } +#endif pTrig->setWaterArea(isWater); pTrig->setRiver(isRiver); pTrig->setRiverStart(riverStart); @@ -177,6 +194,14 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu loc.z = file.readInt(); pTrig->addPoint(loc); } +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + if (numPoints<2) { + DEBUG_LOG(("Deleting polygon trigger '%s' with %d points.", + pTrig->getTriggerName().str(), numPoints)); + deleteInstance(pTrig); + continue; + } +#endif if (pPrevTrig) { pPrevTrig->setNextPoly(pTrig); } else { @@ -224,7 +249,11 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu */ void PolygonTrigger::WritePolygonTriggersDataChunk(DataChunkOutput &chunkWriter) { +#if RTS_GENERALS && RETAIL_COMPATIBLE_CRC chunkWriter.openDataChunk("PolygonTriggers", K_TRIGGERS_VERSION_3); +#else + chunkWriter.openDataChunk("PolygonTriggers", K_TRIGGERS_VERSION_4); +#endif PolygonTrigger *pTrig; Int count = 0; @@ -234,6 +263,9 @@ void PolygonTrigger::WritePolygonTriggersDataChunk(DataChunkOutput &chunkWriter) chunkWriter.writeInt(count); for (pTrig=PolygonTrigger::getFirstPolygonTrigger(); pTrig; pTrig = pTrig->getNext()) { chunkWriter.writeAsciiString(pTrig->getTriggerName()); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + chunkWriter.writeAsciiString(pTrig->getLayerName()); +#endif chunkWriter.writeInt(pTrig->getID()); chunkWriter.writeByte(pTrig->isWaterArea()); chunkWriter.writeByte(pTrig->isRiver()); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp index 93bb5693832..88679b2bc53 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp @@ -429,13 +429,29 @@ static AsciiString static_readPlayerNames[MAX_PLAYER_COUNT]; * Input: DataChunkInput * */ +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) +#define K_PLAYERS_NAMES_FOR_SCRIPTS_VERSION_1 1 +#define K_PLAYERS_NAMES_FOR_SCRIPTS_VERSION_2 2 +#endif + static Bool ParsePlayersDataChunk(DataChunkInput &file, DataChunkInfo *info, void *userData) { +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + Int readDicts = 0; + if (info->version >= K_PLAYERS_NAMES_FOR_SCRIPTS_VERSION_2) { + readDicts = file.readInt(); + } +#endif Int numNames = file.readInt(); Int i; for (i=0; i=MAX_PLAYER_COUNT) break; static_readPlayerNames[i] = file.readAsciiString(); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) + if (readDicts) { + Dict sideDict = file.readDict(); + } +#endif } DEBUG_ASSERTCRASH(file.atEndOfChunk(), ("Unexpected data left over.")); return true; @@ -1121,7 +1137,11 @@ void TeamsInfoRec::addTeam(const Dict* d) TEAM_ALLOC_CHUNK = 8 ///< how many teams to alloc at a time }; +#if RTS_GENERALS && RETAIL_COMPATIBLE_CRC DEBUG_ASSERTCRASH(m_numTeams < 1024, ("hmm, seems like an awful lot of teams...")); +#else + DEBUG_ASSERTCRASH(m_numTeams < 2048, ("%d teams have been allocated (so far). This seems excessive.", m_numTeams )); +#endif if (m_numTeams >= m_numTeamsAllocated) { // pool[]ify diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp index 00386047267..2545c2956ce 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp @@ -2384,7 +2384,7 @@ void TerrainLogic::setWaterHeight( const WaterHandle *water, Real height, Real d Coord3D center; center.x = affectedRegion.lo.x + affectedRegion.width() / 2.0f; center.y = affectedRegion.lo.y + affectedRegion.height() / 2.0f; - center.z = 0.0f; // irrelavant + center.z = 0.0f; // irrelevant // the max radius to scan around us is the diagonal of the bounding region Real maxDist = sqrt( affectedRegion.width() * affectedRegion.width() + @@ -2866,6 +2866,57 @@ void TerrainLogic::flattenTerrain(Object *obj) } +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) +// ------------------------------------------------------------------------------------------------ +/** Dig a deep circular gorge into the terrain beneath an object. */ +// ------------------------------------------------------------------------------------------------ +void TerrainLogic::createCraterInTerrain(Object *obj) +{ + if (obj->getGeometryInfo().getIsSmall()) + return; + + const Coord3D *pos = obj->getPosition(); + Real radius = obj->getGeometryInfo().getMajorRadius(); + + if ( radius <= 0.0f ) + return; // sanity + + ICoord2D iMin, iMax; + iMin.x = REAL_TO_INT_FLOOR( ( pos->x - radius ) / MAP_XY_FACTOR ); + iMin.y = REAL_TO_INT_FLOOR( ( pos->y - radius ) / MAP_XY_FACTOR ); + iMax.x = REAL_TO_INT_FLOOR( ( pos->x + radius ) / MAP_XY_FACTOR ); + iMax.y = REAL_TO_INT_FLOOR( ( pos->y + radius ) / MAP_XY_FACTOR ); + + Real deltaX, deltaY; + + for (Int i = iMin.x; i <= iMax.x; i++ ) + { + for ( Int j=0; j <= iMax.y; j++ ) + { + deltaX = ( i * MAP_XY_FACTOR ) - pos->x; + deltaY = ( j * MAP_XY_FACTOR ) - pos->y; + + Real distance = sqrt( sqr( deltaX ) + sqr( deltaY ) ); + + if ( distance < radius ) //inside circle + { + ICoord2D gridPos; + gridPos.x = i; + gridPos.y = j; + + + Real displacementAmount = radius * (1.0f - distance / radius ); + + Int targetHeight = MAX( 1, TheTerrainVisual->getRawMapHeight( &gridPos ) - displacementAmount ); + + TheTerrainVisual->setRawMapHeight( &gridPos, targetHeight ); + } + } + } + +} +#endif + // ------------------------------------------------------------------------------------------------ /** CRC */ // ------------------------------------------------------------------------------------------------ diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/PolygonTrigger.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/PolygonTrigger.h index d618de16a06..1d2acf9152d 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/PolygonTrigger.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/PolygonTrigger.h @@ -81,9 +81,11 @@ class PolygonTrigger : public MemoryPoolObject, Bool m_exportWithScripts; Bool m_isWaterArea; ///< Used to specify water areas in the map. Bool m_isRiver; ///< Used to specify that a water area is a river. +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) AsciiString m_layerName; ///< Used to specify the layer in the World Builder. Bool m_shouldRender; Bool m_selected; +#endif static PolygonTrigger* ThePolygonTriggerListPtr; static Int s_currentID; ///< Current id for new triggers. @@ -119,6 +121,7 @@ class PolygonTrigger : public MemoryPoolObject, void deletePoint(Int ndx); void setTriggerName(AsciiString name) {m_triggerName = name;}; +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) void setLayerName(AsciiString name) {m_layerName = name;}; AsciiString getLayerName() const {return m_layerName;} @@ -127,6 +130,7 @@ class PolygonTrigger : public MemoryPoolObject, void setSelected(Bool toggle) {m_selected = toggle;} Bool getSelected() {return m_selected;} +#endif void getCenterPoint(Coord3D* pOutCoord) const; Real getRadius() const; diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/TerrainLogic.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/TerrainLogic.h index 90dda7f2411..d3654a946ee 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/TerrainLogic.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/TerrainLogic.h @@ -312,7 +312,9 @@ class TerrainLogic : public Snapshot, void setActiveBoundary(Int newActiveBoundary); void flattenTerrain(Object *obj); ///< Flatten the terrain under a building. +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) void createCraterInTerrain(Object *obj); ///< Flatten the terrain under a building. +#endif protected: diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp index 4f19ee9cfc2..340edda9abc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp @@ -48,8 +48,10 @@ m_numPoints(0), m_sizePoints(0), m_exportWithScripts(false), m_isWaterArea(false), +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) m_shouldRender(true), m_selected(false), +#endif m_isRiver(FALSE), m_riverStart(0) { @@ -142,7 +144,9 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu Bool isRiver; Int riverStart; AsciiString triggerName; +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) AsciiString layerName; +#endif // Remove any existing polygon triggers, if any. PolygonTrigger::deleteTriggers(); // just in case. PolygonTrigger *pPrevTrig = nullptr; @@ -151,9 +155,11 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu while (count>0) { count--; triggerName = file.readAsciiString(); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) if (info->version >= K_TRIGGERS_VERSION_4) { layerName = file.readAsciiString(); } +#endif triggerID = file.readInt(); isWater = false; if (info->version >= K_TRIGGERS_VERSION_2) { @@ -169,9 +175,11 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu numPoints = file.readInt(); PolygonTrigger *pTrig = newInstance(PolygonTrigger)(numPoints+1); pTrig->setTriggerName(triggerName); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) if (info->version >= K_TRIGGERS_VERSION_4) { pTrig->setLayerName(layerName); } +#endif pTrig->setWaterArea(isWater); pTrig->setRiver(isRiver); pTrig->setRiverStart(riverStart); @@ -186,12 +194,14 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu loc.z = file.readInt(); pTrig->addPoint(loc); } +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) if (numPoints<2) { DEBUG_LOG(("Deleting polygon trigger '%s' with %d points.", pTrig->getTriggerName().str(), numPoints)); deleteInstance(pTrig); continue; } +#endif if (pPrevTrig) { pPrevTrig->setNextPoly(pTrig); } else { @@ -239,7 +249,11 @@ Bool PolygonTrigger::ParsePolygonTriggersDataChunk(DataChunkInput &file, DataChu */ void PolygonTrigger::WritePolygonTriggersDataChunk(DataChunkOutput &chunkWriter) { +#if RTS_GENERALS && RETAIL_COMPATIBLE_CRC + chunkWriter.openDataChunk("PolygonTriggers", K_TRIGGERS_VERSION_3); +#else chunkWriter.openDataChunk("PolygonTriggers", K_TRIGGERS_VERSION_4); +#endif PolygonTrigger *pTrig; Int count = 0; @@ -249,7 +263,9 @@ void PolygonTrigger::WritePolygonTriggersDataChunk(DataChunkOutput &chunkWriter) chunkWriter.writeInt(count); for (pTrig=PolygonTrigger::getFirstPolygonTrigger(); pTrig; pTrig = pTrig->getNext()) { chunkWriter.writeAsciiString(pTrig->getTriggerName()); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) chunkWriter.writeAsciiString(pTrig->getLayerName()); +#endif chunkWriter.writeInt(pTrig->getID()); chunkWriter.writeByte(pTrig->isWaterArea()); chunkWriter.writeByte(pTrig->isRiver()); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp index b2c05e49597..7590e64a86b 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/SidesList.cpp @@ -429,23 +429,29 @@ static AsciiString static_readPlayerNames[MAX_PLAYER_COUNT]; * Input: DataChunkInput * */ +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) #define K_PLAYERS_NAMES_FOR_SCRIPTS_VERSION_1 1 #define K_PLAYERS_NAMES_FOR_SCRIPTS_VERSION_2 2 +#endif static Bool ParsePlayersDataChunk(DataChunkInput &file, DataChunkInfo *info, void *userData) { +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) Int readDicts = 0; if (info->version >= K_PLAYERS_NAMES_FOR_SCRIPTS_VERSION_2) { readDicts = file.readInt(); } +#endif Int numNames = file.readInt(); Int i; for (i=0; i=MAX_PLAYER_COUNT) break; static_readPlayerNames[i] = file.readAsciiString(); +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) if (readDicts) { Dict sideDict = file.readDict(); } +#endif } DEBUG_ASSERTCRASH(file.atEndOfChunk(), ("Unexpected data left over.")); return true; @@ -1131,7 +1137,11 @@ void TeamsInfoRec::addTeam(const Dict* d) TEAM_ALLOC_CHUNK = 8 ///< how many teams to alloc at a time }; +#if RTS_GENERALS && RETAIL_COMPATIBLE_CRC + DEBUG_ASSERTCRASH(m_numTeams < 1024, ("hmm, seems like an awful lot of teams...")); +#else DEBUG_ASSERTCRASH(m_numTeams < 2048, ("%d teams have been allocated (so far). This seems excessive.", m_numTeams )); +#endif if (m_numTeams >= m_numTeamsAllocated) { // pool[]ify diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp index 5a3d16f86ae..286573d7b70 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp @@ -2866,8 +2866,7 @@ void TerrainLogic::flattenTerrain(Object *obj) } - - +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) // ------------------------------------------------------------------------------------------------ /** Dig a deep circular gorge into the terrain beneath an object. */ // ------------------------------------------------------------------------------------------------ @@ -2916,12 +2915,7 @@ void TerrainLogic::createCraterInTerrain(Object *obj) } } - - - - - - +#endif // ------------------------------------------------------------------------------------------------ /** CRC */