BASE.CPP (27917B)
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\base.cpv 1.9 16 Oct 1995 16:48:56 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 : BASE.CPP * 24 * * 25 * Programmer : Bill Randolph * 26 * * 27 * Start Date : 03/27/95 * 28 * * 29 * Last Update : March 27, 1995 * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * BaseClass::Get_Building -- Returns ptr to the built building for the given node * 34 * BaseClass::Get_Node -- Returns ptr to the node corresponding to given object * 35 * BaseClass::Is_Built -- Tells if given item in the list has been built yet * 36 * BaseClass::Is_Node -- Tells if the given building is part of our base list * 37 * BaseClass::Load -- loads from a saved game file * 38 * BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built * 39 * BaseClass::Read_INI -- INI reading routine * 40 * BaseClass::Save -- saves to a saved game file * 41 * BaseClass::Write_INI -- INI writing routine * 42 * BaseNodeClass::operator != -- inequality operator * 43 * BaseNodeClass::operator == -- equality operator * 44 * BaseNodeClass::operator > -- greater-than operator * 45 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 46 47 #include "function.h" 48 49 50 /*********************************************************************************************** 51 * BaseNodeClass::operator == -- equality operator * 52 * * 53 * INPUT: * 54 * node node to test against * 55 * * 56 * OUTPUT: * 57 * true = equal, false = not equal * 58 * * 59 * WARNINGS: * 60 * none. * 61 * * 62 * HISTORY: * 63 * 03/24/1995 BRR : Created. * 64 *=============================================================================================*/ 65 int BaseNodeClass::operator == (BaseNodeClass const & node) 66 { 67 return(Type == node.Type && Coord == node.Coord); 68 } 69 70 71 /*********************************************************************************************** 72 * BaseNodeClass::operator != -- inequality operator * 73 * * 74 * INPUT: * 75 * node node to test against * 76 * * 77 * OUTPUT: * 78 * comparison result * 79 * * 80 * WARNINGS: * 81 * none. * 82 * * 83 * HISTORY: * 84 * 03/24/1995 BRR : Created. * 85 *=============================================================================================*/ 86 int BaseNodeClass::operator !=(BaseNodeClass const & node) 87 { 88 return(Type != node.Type || Coord != node.Coord); 89 } 90 91 92 /*********************************************************************************************** 93 * BaseNodeClass::operator > -- greater-than operator * 94 * * 95 * INPUT: * 96 * node node to test against * 97 * * 98 * OUTPUT: * 99 * comparison result * 100 * * 101 * WARNINGS: * 102 * none. * 103 * * 104 * HISTORY: * 105 * 03/24/1995 BRR : Created. * 106 *=============================================================================================*/ 107 int BaseNodeClass::operator > (BaseNodeClass const & ) 108 { 109 return(true); 110 } 111 112 113 /*********************************************************************************************** 114 * BaseClass::Read_INI -- INI reading routine * 115 * * 116 * INI entry format: * 117 * BLDG=COORD * 118 * BLDG=COORD * 119 * ... * 120 * * 121 * INPUT: * 122 * buffer pointer to loaded INI file * 123 * * 124 * OUTPUT: * 125 * none. * 126 * * 127 * WARNINGS: * 128 * This routines assumes there is only one base defined for the scenario. * 129 * * 130 * HISTORY: * 131 * 03/24/1995 BRR : Created. * 132 *=============================================================================================*/ 133 void BaseClass::Read_INI(char *buffer) 134 { 135 char buf[128]; 136 char uname[10]; 137 BaseNodeClass node; // node to add to list 138 139 /* 140 ** First, determine the house of the human player, and set the Base's house 141 ** accordingly. 142 */ 143 WWGetPrivateProfileString("BASIC", "Player", "GoodGuy", buf, 20, buffer); 144 if (HouseTypeClass::From_Name(buf) == HOUSE_GOOD) { 145 House = HOUSE_BAD; 146 } else { 147 House = HOUSE_GOOD; 148 } 149 150 /* 151 ** Read the number of buildings that will go into the base node list 152 */ 153 int count = WWGetPrivateProfileInt (INI_Name(),"Count",0,buffer); 154 155 /* 156 ** Read each entry in turn, in the same order they were written out. 157 */ 158 for (int i = 0; i < count; i++) { 159 160 /* 161 ** Get an INI entry 162 */ 163 sprintf(uname,"%03d",i); 164 WWGetPrivateProfileString(INI_Name(), uname, NULL, buf, sizeof(buf)-1, buffer); 165 166 /* 167 ** Set the node's building type 168 */ 169 node.Type = BuildingTypeClass::From_Name(strtok(buf,",")); 170 171 /* 172 ** Read & set the node's coordinate 173 */ 174 node.Coord = atol(strtok(NULL,",")); 175 176 /* 177 ** Add this node to the Base's list 178 */ 179 Nodes.Add(node); 180 } 181 } 182 183 184 /*********************************************************************************************** 185 * BaseClass::Write_INI -- INI writing routine * 186 * * 187 * INI entry format: * 188 * BLDG=COORD * 189 * BLDG=COORD * 190 * ... * 191 * * 192 * INPUT: * 193 * buffer pointer to loaded INI file staging area * 194 * * 195 * OUTPUT: * 196 * none. * 197 * * 198 * WARNINGS: * 199 * This routines assumes there is only one base defined for the scenario. * 200 * * 201 * HISTORY: * 202 * 03/24/1995 BRR : Created. * 203 *=============================================================================================*/ 204 void BaseClass::Write_INI(char *buffer) 205 { 206 char buf[128]; 207 char uname[10]; 208 209 /* 210 ** Clear out all existing teamtype data from the INI file. 211 */ 212 WWWritePrivateProfileString(INI_Name(), NULL, NULL, buffer); 213 214 /* 215 ** Save the # of buildings in the Nodes list. This is essential because 216 ** they must be read in the same order they were created, so "000" must be 217 ** read first, etc. 218 */ 219 WWWritePrivateProfileInt (INI_Name(),"Count",Nodes.Count(),buffer); 220 221 /* 222 ** Write each entry into the INI 223 */ 224 for (int i = 0; i < Nodes.Count(); i++) { 225 sprintf(uname,"%03d",i); 226 sprintf(buf,"%s,%d", 227 BuildingTypeClass::As_Reference(Nodes[i].Type).IniName, 228 Nodes[i].Coord); 229 230 WWWritePrivateProfileString(INI_Name(), uname, buf, buffer); 231 } 232 } 233 234 235 /*********************************************************************************************** 236 * BaseClass::Load -- loads from a saved game file * 237 * * 238 * INPUT: * 239 * file open file * 240 * * 241 * OUTPUT: * 242 * true = success, false = failure * 243 * * 244 * WARNINGS: * 245 * none. * 246 * * 247 * HISTORY: * 248 * 03/24/1995 BRR : Created. * 249 *=============================================================================================*/ 250 bool BaseClass::Load(FileClass &file) 251 { 252 int num_struct; 253 int i; 254 BaseNodeClass node; 255 256 /* 257 ** Read in & check the size of this class 258 */ 259 if (file.Read(&i, sizeof(i)) != sizeof(i)) { 260 return(false); 261 } 262 263 if (i != sizeof(*this)) { 264 return(false); 265 } 266 267 /* 268 ** Read in the House & the number of structures in the base 269 */ 270 if (file.Read(&House,sizeof(House)) != sizeof(House)) { 271 return(false); 272 } 273 274 if (file.Read(&num_struct,sizeof(num_struct)) != sizeof(num_struct)) { 275 return(false); 276 } 277 278 /* 279 ** Read each node entry & add it to the list 280 */ 281 for (i = 0; i < num_struct; i++) { 282 if (file.Read(&node,sizeof(node)) != sizeof(node)) { 283 return(false); 284 } 285 Nodes.Add(node); 286 } 287 288 return(true); 289 } 290 291 292 /*********************************************************************************************** 293 * BaseClass::Save -- saves to a saved game file * 294 * * 295 * INPUT: * 296 * file open file * 297 * * 298 * OUTPUT: * 299 * true = success, false = failure * 300 * * 301 * WARNINGS: * 302 * none. * 303 * * 304 * HISTORY: * 305 * 03/24/1995 BRR : Created. * 306 *=============================================================================================*/ 307 bool BaseClass::Save(FileClass &file) 308 { 309 int num_struct; 310 int i; 311 BaseNodeClass node; 312 313 /* 314 ** Write the size of this class 315 */ 316 i = sizeof(*this); 317 if (file.Write(&i,sizeof(i)) != sizeof(i)) { 318 return(false); 319 } 320 321 /* 322 ** Write the House & the number of structures in the base 323 */ 324 if (file.Write(&House,sizeof(House)) != sizeof(House)) { 325 return(false); 326 } 327 328 num_struct = Nodes.Count(); 329 if (file.Write(&num_struct,sizeof(num_struct)) != sizeof(num_struct)) { 330 return(false); 331 } 332 333 /* 334 ** Write each node entry 335 */ 336 for (i = 0; i < num_struct; i++) { 337 node = Nodes[i]; 338 if (file.Write(&node,sizeof(node)) != sizeof(node)) { 339 return(false); 340 } 341 } 342 343 return(true); 344 } 345 346 347 /*********************************************************************************************** 348 * BaseClass::Is_Built -- Tells if given item in the list has been built yet * 349 * * 350 * INPUT: * 351 * index index into base list * 352 * * 353 * OUTPUT: * 354 * true = yes, false = no * 355 * * 356 * WARNINGS: * 357 * none. * 358 * * 359 * HISTORY: * 360 * 03/24/1995 BRR : Created. * 361 *=============================================================================================*/ 362 bool BaseClass::Is_Built(int index) 363 { 364 if (Get_Building(index) != NULL) { 365 return(true); 366 } else { 367 return(false); 368 } 369 } 370 371 372 /*********************************************************************************************** 373 * BaseClass::Get_Building -- Returns ptr to the built building for the given node * 374 * * 375 * INPUT: * 376 * obj pointer to building to test * 377 * * 378 * OUTPUT: * 379 * ptr to already-built building, NULL if none * 380 * * 381 * WARNINGS: * 382 * none. * 383 * * 384 * HISTORY: * 385 * 03/24/1995 BRR : Created. * 386 *=============================================================================================*/ 387 BuildingClass * BaseClass::Get_Building(int index) 388 { 389 BuildingClass *bldg; 390 ObjectClass *obj[4]; 391 392 /* 393 ** Check the location on the map where this building should be; if it's 394 ** there, return a pointer to it. 395 */ 396 CELL cell = Coord_Cell(Nodes[index].Coord); 397 398 obj[0] = Map[cell].Cell_Building(); 399 obj[1] = Map[cell].Overlapper[0]; 400 obj[2] = Map[cell].Overlapper[1]; 401 obj[3] = Map[cell].Overlapper[2]; 402 403 bldg = NULL; 404 for (int i = 0; i < 4; i++) { 405 if (obj[i] && 406 obj[i]->Coord == Nodes[index].Coord && 407 obj[i]->What_Am_I() == RTTI_BUILDING && 408 ((BuildingClass *)obj[i])->Class->Type == Nodes[index].Type) { 409 410 bldg = (BuildingClass *)obj[i]; 411 break; 412 } 413 } 414 415 return(bldg); 416 } 417 418 419 /*********************************************************************************************** 420 * BaseClass::Is_Node -- Tells if the given building is part of our base list * 421 * * 422 * INPUT: * 423 * obj pointer to building to test * 424 * * 425 * OUTPUT: * 426 * true = building is a node in the list, false = isn't * 427 * * 428 * WARNINGS: * 429 * none. * 430 * * 431 * HISTORY: * 432 * 03/24/1995 BRR : Created. * 433 *=============================================================================================*/ 434 bool BaseClass::Is_Node(BuildingClass *obj) 435 { 436 if (Get_Node(obj) != NULL) { 437 return(true); 438 } else { 439 return(false); 440 } 441 } 442 443 444 /*********************************************************************************************** 445 * BaseClass::Get_Node -- Returns ptr to the node corresponding to given object * 446 * * 447 * INPUT: * 448 * obj pointer to building to test * 449 * * 450 * OUTPUT: * 451 * ptr to node * 452 * * 453 * WARNINGS: * 454 * none. * 455 * * 456 * HISTORY: * 457 * 03/24/1995 BRR : Created. * 458 *=============================================================================================*/ 459 BaseNodeClass * BaseClass::Get_Node(BuildingClass *obj) 460 { 461 for (int i = 0; i < Nodes.Count(); i++) { 462 if (obj->Class->Type == Nodes[i].Type && obj->Coord == Nodes[i].Coord) { 463 return(&Nodes[i]); 464 } 465 } 466 return(NULL); 467 } 468 469 470 /*********************************************************************************************** 471 * BaseClass::Next_Buildable -- returns ptr to the next node that needs to be built * 472 * * 473 * If 'type' is not NONE, returns ptr to the next "hole" in the list of the given type. * 474 * Otherwise, returns ptr to the next hole in the list of any type. * 475 * * 476 * INPUT: * 477 * type type of building to check for * 478 * * 479 * OUTPUT: * 480 * ptr to a BaseNodeClass, NULL if none * 481 * * 482 * WARNINGS: * 483 * none. * 484 * * 485 * HISTORY: * 486 * 03/24/1995 BRR : Created. * 487 *=============================================================================================*/ 488 BaseNodeClass * BaseClass::Next_Buildable(StructType type) 489 { 490 /* 491 ** Loop through all node entries, returning a pointer to the first 492 ** un-built one that matches the requested type. 493 */ 494 for (int i = 0; i < Nodes.Count(); i++) { 495 496 /* 497 ** For STRUCT_NONE, return the first hole found 498 */ 499 if (type == STRUCT_NONE) { 500 if (!Is_Built(i)) { 501 return(&Nodes[i]); 502 } 503 504 } else { 505 506 /* 507 ** For a "real" building type, return the first hold for that type 508 */ 509 if (Nodes[i].Type==type && !Is_Built(i)) { 510 return(&Nodes[i]); 511 } 512 } 513 } 514 515 516 // If no entry could be found, then create a fake one that will allow 517 // placement of the building. Make it static and reuse the next time this 518 // routine is called. 519 520 return(NULL); 521 }