OVERLAY.CPP (21680B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: F:\projects\c&c\vcs\code\overlay.cpv 2.17 16 Oct 1995 16:50:44 JOE_BOSTIC $ */ 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : OVERLAY.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : May 17, 1994 * 28 * * 29 * Last Update : July 24, 1995 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * OverlayClass::Read_INI -- Reads the overlay data from an INI file. * 34 * OverlayClass::Write_INI -- Writes the overlay data to an INI file. * 35 * OverlayClass::delete -- Returns a overlay object to the pool. * 36 * OverlayClass::Init -- Resets the overlay object system. * 37 * OverlayClass::new -- Allocates a overlay object from pool * 38 * OverlayClass::OverlayClass -- Overlay object constructor. * 39 * OverlayClass::Mark -- Marks the overlay down on the map. * 40 * OverlayClass::Validate -- validates overlay * 41 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 42 43 #include "function.h" 44 #include "overlay.h" 45 46 /* 47 ** This contains the value of the Virtual Function Table Pointer 48 */ 49 void * OverlayClass::VTable; 50 51 HousesType OverlayClass::ToOwn = HOUSE_NONE; 52 53 OverlayClass::OverlayClass(void) : Class(0) {ToOwn = HOUSE_NONE;}; 54 55 56 /*********************************************************************************************** 57 * OverlayClass::Validate -- validates overlay * 58 * * 59 * INPUT: * 60 * none. * 61 * * 62 * OUTPUT: * 63 * 1 = ok, 0 = error * 64 * * 65 * WARNINGS: * 66 * none. * 67 * * 68 * HISTORY: * 69 * 08/09/1995 BRR : Created. * 70 *=============================================================================================*/ 71 #ifdef CHEAT_KEYS 72 int OverlayClass::Validate(void) const 73 { 74 int num; 75 76 num = Overlays.ID(this); 77 if (num < 0 || num >= OVERLAY_MAX) { 78 Validate_Error("OVERLAY"); 79 return (0); 80 } 81 else 82 return (1); 83 } 84 #else 85 #define Validate() 86 #endif 87 88 89 /*********************************************************************************************** 90 * OverlayClass::Init -- Resets the overlay object system. * 91 * * 92 * This routine resets the overlay object system. It is called * 93 * prior to loading a new scenario. * 94 * * 95 * INPUT: none * 96 * * 97 * OUTPUT: none * 98 * * 99 * WARNINGS: none * 100 * * 101 * HISTORY: * 102 * 05/24/1994 JLB : Created. * 103 *=============================================================================================*/ 104 void OverlayClass::Init(void) 105 { 106 OverlayClass *ptr; 107 108 Overlays.Free_All(); 109 110 ptr = new OverlayClass(); 111 VTable = ((void **)(((char *)ptr) + sizeof(AbstractClass) - 4))[0]; 112 delete ptr; 113 } 114 115 116 /*********************************************************************************************** 117 * OverlayClass::new -- Allocates a overlay object from pool * 118 * * 119 * This routine is used to allocate a overlay object from the * 120 * overlay object pool. * 121 * * 122 * INPUT: size -- The size of a overlay object (not used). * 123 * * 124 * OUTPUT: Returns with a pointer to an available overlay object. * 125 * * 126 * WARNINGS: none * 127 * * 128 * HISTORY: * 129 * 05/17/1994 JLB : Created. * 130 *=============================================================================================*/ 131 void * OverlayClass::operator new(size_t ) 132 { 133 void * ptr = Overlays.Allocate(); 134 if (ptr) { 135 ((OverlayClass *)ptr)->Set_Active(); 136 } 137 return(ptr); 138 } 139 140 141 /*********************************************************************************************** 142 * OverlayClass::delete -- Returns a overlay object to the pool. * 143 * * 144 * This routine will return a overlay object to the overlay object * 145 * pool. A overlay so returned is available for allocation again. * 146 * * 147 * INPUT: ptr -- Pointer to the object to be returned. * 148 * * 149 * OUTPUT: none * 150 * * 151 * WARNINGS: none * 152 * * 153 * HISTORY: * 154 * 05/17/1994 JLB : Created. * 155 *=============================================================================================*/ 156 void OverlayClass::operator delete(void *ptr) 157 { 158 if (ptr) { 159 ((OverlayClass *)ptr)->IsActive = false; 160 } 161 Overlays.Free((OverlayClass *)ptr); 162 163 //Map.Validate(); 164 } 165 166 167 /*********************************************************************************************** 168 * OverlayClass::OverlayClass -- Overlay object constructor. * 169 * * 170 * This is the constructor for a overlay object. * 171 * * 172 * INPUT: type -- The overlay object this is to become. * 173 * * 174 * pos -- The position on the map to place the object. * 175 * * 176 * OUTPUT: none * 177 * * 178 * WARNINGS: none * 179 * * 180 * HISTORY: * 181 * 05/17/1994 JLB : Created. * 182 *=============================================================================================*/ 183 OverlayClass::OverlayClass(OverlayType type, CELL pos, HousesType house) : 184 Class(&OverlayTypeClass::As_Reference(type)) 185 { 186 if (pos != -1) { 187 ToOwn = house; 188 Unlimbo(Cell_Coord(pos)); 189 ToOwn = HOUSE_NONE; 190 } 191 } 192 193 194 /*********************************************************************************************** 195 * OverlayClass::Mark -- Marks the overlay down on the map. * 196 * * 197 * This routine will place the overlay onto the map. The overlay object is deleted by this * 198 * operation. The map is updated to reflect the presence of the overlay. * 199 * * 200 * INPUT: mark -- The type of marking to perform. Only MARK_DOWN is supported. * 201 * * 202 * OUTPUT: bool; Was the overlay successfully marked? Failure occurs if it is not being * 203 * marked down. * 204 * * 205 * WARNINGS: none * 206 * * 207 * HISTORY: * 208 * 09/24/1994 JLB : Created. * 209 * 12/23/1994 JLB : Checks low level legality before proceeding. * 210 *=============================================================================================*/ 211 bool OverlayClass::Mark(MarkType mark) 212 { 213 Validate(); 214 if (ObjectClass::Mark(mark)) { 215 if (mark == MARK_DOWN) { 216 CELL cell = Coord_Cell(Coord); 217 CellClass * cellptr = &Map[cell]; 218 219 /* 220 ** Road placement occurs in two steps. First the foundation is placed, but only 221 ** on buildable terrain. Second, the road is completed, but only if the foundation 222 ** was previously placed. 223 */ 224 if (*this == OVERLAY_ROAD) { 225 if ((cellptr->Overlay == OVERLAY_ROAD && cellptr->OverlayData == 0) || 226 (cellptr->Overlay == OVERLAY_NONE && cellptr->Is_Generally_Clear())) { 227 228 if (cellptr->Overlay == OVERLAY_ROAD) { 229 cellptr->OverlayData = 1; 230 } else { 231 cellptr->OverlayData = 0; 232 } 233 cellptr->Overlay = Class->Type; 234 cellptr->Redraw_Objects(); 235 } 236 } else { 237 238 /* 239 ** Walls have special logic when they are marked down. 240 */ 241 if (Class->IsWall) { 242 if (cellptr->Is_Generally_Clear() && cellptr->Overlay != OVERLAY_FLAG_SPOT) { 243 cellptr->Overlay = Class->Type; 244 cellptr->OverlayData = 0; 245 cellptr->Redraw_Objects(); 246 cellptr->Wall_Update(); 247 248 /* 249 ** Flag ownership of the cell if the 'global' ownership flag indicates that this 250 ** is necessary for the overlay. 251 */ 252 if (ToOwn != HOUSE_NONE) { 253 cellptr->Owner = ToOwn; 254 } 255 256 } else { 257 Delete_This(); 258 return(false); 259 } 260 } else { 261 if ((cellptr->Overlay == OVERLAY_NONE || cellptr->Overlay == OVERLAY_SQUISH) && !cellptr->Cell_Terrain() && Ground[cellptr->Land_Type()].Build) { 262 263 /* 264 ** Increment the global crate counter. This is used to regulate 265 ** the crate generation. 266 */ 267 if (Class->IsCrate) CrateCount++; 268 269 /* 270 ** Don't show the squish unless the gross flag is active. 271 */ 272 if (!Special.IsGross && Class->Type != OVERLAY_SQUISH) { 273 cellptr->Overlay = Class->Type; 274 cellptr->OverlayData = 0; 275 } 276 cellptr->Redraw_Objects(); 277 if (Class->Land == LAND_TIBERIUM) { 278 cellptr->OverlayData = 1; 279 cellptr->Tiberium_Adjust(); 280 } else { 281 if (*this == OVERLAY_CONCRETE) { 282 CELL newcell; 283 284 /* 285 ** Smudges go away when concrete is laid down. 286 */ 287 cellptr->Smudge = SMUDGE_NONE; 288 cellptr->SmudgeData = 0; 289 cellptr->Concrete_Calc(); 290 291 /* 292 ** Possibly add concrete to adjacent cells depending on whether this 293 ** concrete is in an odd or even row. 294 */ 295 if (Cell_X(cell) & 0x01) { 296 newcell = Adjacent_Cell((CELL)(cellptr->Cell_Number()), FACING_W); 297 } else { 298 newcell = Adjacent_Cell((CELL)(cellptr->Cell_Number()), FACING_E); 299 } 300 if (Map[newcell].Overlay != OVERLAY_CONCRETE) { 301 Class->Create_And_Place(newcell); 302 } 303 304 /* 305 ** The display attributes must be recalculated for all adjacent 306 ** cells since their shape can be altered by the presence of 307 ** concrete at this location. 308 */ 309 static FacingType _face[4] = {FACING_N, FACING_E, FACING_S, FACING_W}; 310 311 for (int index = 0; index < (sizeof(_face)/sizeof(_face[0])); index++) { 312 CellClass * adjcell = cellptr->Adjacent_Cell(_face[index]); 313 if (adjcell) adjcell->Concrete_Calc(); 314 } 315 } 316 } 317 } 318 } 319 320 /* 321 ** ***** Is this really needed? 322 */ 323 cellptr->Recalc_Attributes(); 324 } 325 Delete_This(); 326 return(true); 327 } 328 } 329 return(false); 330 } 331 332 333 /*********************************************************************************************** 334 * OverlayClass::Read_INI -- Reads the overlay data from an INI file. * 335 * * 336 * This routine is used to load a scenario's overlay data. The overlay objects are read * 337 * from the INI file and then created on the map. * 338 * * 339 * INPUT: buffer -- Pointer to the INI file staging buffer. * 340 * * 341 * OUTPUT: none * 342 * * 343 * WARNINGS: none * 344 * * 345 * HISTORY: * 346 * 09/01/1994 JLB : Created. * 347 * 07/24/1995 JLB : Specifically forbid manual crates in multiplayer scenarios. * 348 *=============================================================================================*/ 349 void OverlayClass::Read_INI(char *buffer) 350 { 351 char *tbuffer; 352 int len; // Length of data in buffer. 353 char buf[128]; 354 355 len = strlen(buffer) + 2; 356 tbuffer = buffer + len; 357 358 WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-len, buffer); 359 while (*tbuffer != '\0') { 360 CELL cell; 361 OverlayType classid; 362 363 cell = atoi(tbuffer); 364 WWGetPrivateProfileString(INI_Name(), tbuffer, NULL, buf, sizeof(buf)-1, buffer); 365 classid = OverlayTypeClass::From_Name(strtok(buf, ",\n\r")); 366 367 /* 368 ** Don't allow placement of crates in the multiplayer scenarios. 369 */ 370 if (classid != OVERLAY_NONE && (GameToPlay == GAME_NORMAL || !OverlayTypeClass::As_Reference(classid).IsCrate)) { 371 372 /* 373 ** Don't allow placement of overlays on the top or bottom rows of 374 ** the map. 375 */ 376 if (cell >= MAP_CELL_W && cell <= MAP_CELL_TOTAL - MAP_CELL_W) { 377 new OverlayClass(classid, cell); 378 } 379 } 380 tbuffer += strlen(tbuffer)+1; 381 } 382 } 383 384 385 /*********************************************************************************************** 386 * OverlayClass::Write_INI -- Writes the overlay data to an INI file. * 387 * * 388 * This is used to output the overlay data to a scenario INI file. Typically, this is * 389 * only used by the scenario editor. * 390 * * 391 * INPUT: buffer -- Pointer to the INI file staging buffer. * 392 * * 393 * OUTPUT: none * 394 * * 395 * WARNINGS: none * 396 * * 397 * HISTORY: * 398 * 09/01/1994 JLB : Created. * 399 *=============================================================================================*/ 400 void OverlayClass::Write_INI(char *buffer) 401 { 402 int index; 403 char uname[10]; 404 char buf[128]; 405 char *tbuffer; // Accumulation buffer of unit IDs. 406 407 /* 408 ** First, clear out all existing unit data from the ini file. 409 */ 410 tbuffer = buffer + strlen(buffer) + 2; 411 WWGetPrivateProfileString(INI_Name(), NULL, NULL, tbuffer, ShapeBufferSize-strlen(buffer), buffer); 412 while (*tbuffer != '\0') { 413 WWWritePrivateProfileString(INI_Name(), tbuffer, NULL, buffer); 414 tbuffer += strlen(tbuffer)+1; 415 } 416 417 /* 418 ** Write the unit data out. 419 */ 420 for (index = 0; index < MAP_CELL_TOTAL; index++) { 421 CellClass * cellptr = &Map[index]; 422 423 if (cellptr->Overlay != OVERLAY_NONE) { 424 sprintf(uname, "%03d", index); 425 sprintf(buf, "%s", OverlayTypeClass::As_Reference(cellptr->Overlay).IniName); 426 WWWritePrivateProfileString(INI_Name(), uname, buf, buffer); 427 } 428 } 429 }