RADAR.CPP (83699B)
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\radar.cpv 2.17 16 Oct 1995 16:49:28 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 : RADAR.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 12/15/94 * 28 * * 29 * Last Update : November 17, 1995 [PWG] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * Get_Multi_Color -- Get the multi color offset number * 34 * RadarClass::AI -- Processes radar input (non-tactical). * 35 * RadarClass::Cell_On_Radar -- Determines if a cell is currently visible on radar. * 36 * RadarClass::Click_Cell_Calc -- Determines what cell the pixel coordinate is over. * 37 * RadarClass::Click_In_Radar -- Check to see if a click is in radar map * 38 * RadarClass::Click_In_Radar -- Converts a radar click into cell X and Y coordinate. * 39 * RadarClass::Draw_It -- Displays the radar map of the terrain. * 40 * RadarClass::Draw_Names -- draws players' names on the radar map * 41 * RadarClass::Init_Clear -- Sets the radar map to a known state * 42 * RadarClass::Map_Cell -- Updates radar map when a cell becomes mapped. * 43 * RadarClass::One_Time -- Handles one time processing for the radar map. * 44 * RadarClass::Player_Names -- toggles the Player-Names mode of the radar map * 45 * RadarClass::Plot_Radar_Pixel -- Updates the radar map with a terrain pixel. * 46 * RadarClass::RadarClass -- Default constructor for RadarClass object. * 47 * RadarClass::Radar_Activate -- Controls radar activation. * 48 * RadarClass::Radar_Anim -- Renders current frame of radar animation * 49 * RadarClass::Radar_Cursor -- Adjust the position of the radar map cursor. * 50 * RadarClass::Radar_Pixel -- Mark a cell to be rerendered on the radar map. * 51 * RadarClass::Radar_Position -- Returns with the current position of the radar map. * 52 * RadarClass::Refresh_Cells -- Intercepts refresh request and updates radar if needed * 53 * RadarClass::Render_Infantry -- Displays objects on the radar map. * 54 * RadarClass::Render_Overlay -- Renders an icon for given overlay * 55 * RadarClass::Render_Terrain -- Render the terrain over the given cell * 56 * RadarClass::Set_Map_Dimensions -- Sets the tactical map dimensions. * 57 * RadarClass::Set_Radar_Position -- Sets the radar map coordinates. * 58 * RadarClass::Set_Radar_Position -- Sets the radar position to center around specified cell.* 59 * RadarClass::Set_Tactical_Position -- Called when setting the tactical display position. * 60 * RadarClass::Set_Tactical_Position -- Called when setting the tactical display position. * 61 * RadarClass::TacticalClass::Action -- I/O function for the radar map. * 62 * RadarClass::Zoom_Mode(void) -- Handles toggling zoom on the map * 63 * RadarClass::Set_Tactical_Position -- Sets the map's tactical position and adjusts radar to* 64 * RadarClass::Coord_To_Radar_Pixel -- Converts a coordinate to a radar pixel position * 65 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 66 67 #include "function.h" 68 #include <stdlib.h> 69 70 //void const * RadarClass::CoverShape; 71 RadarClass::TacticalClass RadarClass::RadarButton; 72 73 void const * RadarClass::RadarAnim = NULL; 74 75 static bool FullRedraw = false; 76 77 #define _MAX_NAME 13 78 79 static GraphicBufferClass _IconStage(3,3); 80 static GraphicBufferClass _TileStage(24,24); 81 82 /*********************************************************************************************** 83 * RadarClass::RadarClass -- Default constructor for RadarClass object. * 84 * * 85 * This default constructor merely sets the radar specific values to default settings. The * 86 * radar must be deliberately activated in order for it to be displayed. * 87 * * 88 * INPUT: none * 89 * * 90 * OUTPUT: none * 91 * * 92 * WARNINGS: none * 93 * * 94 * HISTORY: * 95 * 12/16/1994 JLB : Created. * 96 *=============================================================================================*/ 97 RadarClass::RadarClass(void) 98 { 99 IsZoomed = true; 100 IsRadarActive = false; 101 IsToRedraw = false; 102 RadarCursorRedraw = false; 103 PixelPtr = 0; 104 SpecialRadarFrame = 0; 105 IsPlayerNames = false; 106 } 107 108 109 /*********************************************************************************************** 110 * RadarClass::One_Time -- Handles one time processing for the radar map. * 111 * * 112 * This routine handles any one time processing required in order for the radar map to * 113 * function. This actually only requires an allocation of the radar staging buffer. This * 114 * buffer is needed for those cases where the radar area of the page is being destroyed * 115 * and it needs to be destroyed. * 116 * * 117 * INPUT: none * 118 * * 119 * OUTPUT: none * 120 * * 121 * WARNINGS: Be sure to call this routine only ONCE. * 122 * * 123 * HISTORY: * 124 * 12/22/1994 JLB : Created. * 125 *=============================================================================================*/ 126 void RadarClass::One_Time(void) 127 { 128 int factor = Get_Resolution_Factor(); 129 RadWidth = 80 << factor; 130 RadHeight = 70 << factor; 131 RadX = SeenBuff.Get_Width() - RadWidth; 132 RadY = Map.Get_Tab_Height() - (1 << factor); 133 RadPWidth = 64 << factor; 134 RadPHeight = 64 << factor; 135 if ( factor ) { 136 RadOffX = 16; 137 RadOffY = 7; 138 RadIWidth = 128; 139 RadIHeight = 128; 140 } else { 141 RadOffX = 4 << factor; 142 RadOffY = 1 << factor; 143 RadIWidth = 72 << factor; 144 RadIHeight = 69 << factor; 145 } 146 147 DisplayClass::One_Time(); 148 RadarButton.X = RadX+RadOffX; 149 RadarButton.Y = RadY+RadOffY; 150 RadarButton.Width = RadIWidth; 151 RadarButton.Height = RadIHeight; 152 } 153 154 155 /*********************************************************************************************** 156 * RadarClass::Init_Clear -- Sets the radar map to a known state. * 157 * * 158 * This routine is used to initialize the radar map at the start of the scenario. It * 159 * sets the radar map position and starts it in the disabled state. * 160 * * 161 * INPUT: theater -- The theater that the scenario is starting (unused by this routine). * 162 * * 163 * OUTPUT: none * 164 * * 165 * WARNINGS: none * 166 * * 167 * HISTORY: * 168 * 12/22/1994 JLB : Created. * 169 *=============================================================================================*/ 170 void RadarClass::Init_Clear(void) 171 { 172 DisplayClass::Init_Clear(); 173 IsRadarActive = false; 174 IsToRedraw = true; 175 RadarCursorRedraw = true; 176 IsRadarActivating = false; 177 IsRadarDeactivating = false; 178 DoesRadarExist = false; 179 PixelPtr = 0; 180 IsPlayerNames = false; 181 182 /* 183 ** If we have a valid map lets make sure that we set it correctly 184 */ 185 if (MapCellWidth || MapCellHeight) { 186 IsZoomed = false; 187 Zoom_Mode(Coord_Cell(Map.TacticalCoord)); 188 } 189 } 190 191 192 /*********************************************************************************************** 193 * RadarClass::Radar_Activate -- Controls radar activation. * 194 * * 195 * Use this routine to turn the radar map on or off. * 196 * * 197 * INPUT: control -- What to do with the radar map: * 198 * 0 = Turn radar off. * 199 * 1 = Turn radar on. * 200 * 2 = Remove Radar Gadgets * 201 * 3 = Add Radar Gadgets * 202 * 4 = Remove radar. * 203 * -1= Toggle radar on or off. * 204 * * 205 * OUTPUT: bool; Was the radar map already on? * 206 * * 207 * WARNINGS: none * 208 * * 209 * HISTORY: * 210 * 12/11/1994 JLB : Created. * 211 *=============================================================================================*/ 212 bool RadarClass::Radar_Activate(int control) 213 { 214 bool old = IsRadarActive; 215 216 switch (control) { 217 218 /* 219 ** Toggle the state of the radar map on or off. 220 */ 221 case -1: 222 { 223 int temp = (IsRadarActive == false); 224 if (temp) { 225 Radar_Activate(1); 226 } else { 227 Radar_Activate(0); 228 } 229 } 230 break; 231 232 /* 233 ** Turn the radar map off properly. 234 */ 235 case 0: 236 if (Map.IsSidebarActive) { 237 if (IsRadarActive && !IsRadarDeactivating) { 238 // Sound_Effect(VOC_RADAR_OFF); // MBL 07.20.2020: These are never being sent to the client, so handled there; Disabling here for good measure. 239 IsRadarDeactivating = true; 240 IsRadarActive = false; 241 if (IsRadarActivating == true) { 242 IsRadarActivating = false; 243 } else { 244 RadarAnimFrame = RADAR_ACTIVATED_FRAME; 245 } 246 } 247 } else { 248 Radar_Activate(2); 249 } 250 return(old); 251 252 case 1: 253 if (Map.IsSidebarActive) { 254 if (!IsRadarActivating && !IsRadarActive) { 255 // Sound_Effect(VOC_RADAR_ON); // MBL 07.20.2020: These are never being sent to the client, so handled there; Disabling here for good measure. 256 IsRadarActivating = true; 257 if (IsRadarDeactivating == true) { 258 IsRadarDeactivating = false; 259 } else { 260 if (DoesRadarExist) { 261 RadarAnimFrame = MAX_RADAR_FRAMES; 262 } else { 263 RadarAnimFrame = 0; 264 } 265 } 266 } 267 } else { 268 Radar_Activate(3); 269 } 270 return(old); 271 272 case 2: 273 if (GameToPlay==GAME_NORMAL) { 274 Map.Zoom.Disable(); 275 } 276 IsRadarActive = false; 277 IsRadarActivating = false; 278 IsRadarDeactivating = false; 279 break; 280 281 case 3: 282 if (GameToPlay==GAME_NORMAL) { 283 Map.Zoom.Enable(); 284 } 285 IsRadarActive = true; 286 IsRadarActivating = false; 287 IsRadarDeactivating = false; 288 break; 289 290 case 4: 291 IsRadarActive = false; 292 IsRadarActivating = false; 293 IsRadarDeactivating = false; 294 DoesRadarExist = false; 295 Flag_To_Redraw(false); 296 IsToRedraw = true; 297 break; 298 } 299 300 if (IsRadarActive != old) { 301 IsToRedraw = true; 302 Flag_To_Redraw(false); 303 } 304 FullRedraw = IsRadarActive; 305 return(old); 306 } 307 308 309 /*********************************************************************************************** 310 * RadarClass::Draw_It -- Displays the radar map of the terrain. * 311 * * 312 * This is used to display the radar map that appears in the lower * 313 * right corner. The main changes to this map are the vehicles and * 314 * structure pixels. * 315 * * 316 * INPUT: none * 317 * * 318 * OUTPUT: none * 319 * * 320 * WARNINGS: none * 321 * * 322 * HISTORY: * 323 * 04/24/1991 JLB : Created. * 324 * 05/08/1994 JLB : Converted to member function. * 325 *=============================================================================================*/ 326 void RadarClass::Draw_It(bool forced) 327 { 328 DisplayClass::Draw_It(forced); 329 // if (!In_Debugger) while (!HidPage.Lock()) {} 330 331 #if (0) // Legacy radar rendering not used. ST - 2/26/2020 3:53PM 332 333 /* 334 ** Don't perform any rendering if none is requested. 335 */ 336 if (!forced && !IsToRedraw && !FullRedraw) return; 337 338 static HousesType _house = HOUSE_NONE; 339 if (PlayerPtr->ActLike != _house) { 340 char name[_MAX_NAME + _MAX_EXT]; 341 342 if (Special.IsJurassic && AreThingiesEnabled) { 343 strcpy(name, "RADAR.JP"); 344 } else { 345 _makepath(name, NULL, NULL, "RADAR", HouseTypeClass::As_Reference(PlayerPtr->ActLike).Suffix); 346 } 347 RadarAnim = Hires_Retrieve(name); 348 _house = PlayerPtr->ActLike; 349 } 350 351 /* 352 ** If in player name mode, just draw player names 353 */ 354 if (IsPlayerNames) { 355 Draw_Names(); 356 IsToRedraw = false; 357 return; 358 } 359 360 if (IsRadarActivating || IsRadarDeactivating) { 361 Radar_Anim(); 362 IsToRedraw = false; 363 return; 364 } 365 366 if (Map.IsSidebarActive) { 367 if (IsRadarActive) { 368 369 //HidPage.Lock(); 370 // ST 8/13/96 2:24PM 371 //forced = true; 372 /* 373 ** If only a few of the radar pixels need to be redrawn, then find and redraw 374 ** only these. 375 */ 376 if (!forced && IsToRedraw && !FullRedraw) { 377 IsToRedraw = false; 378 379 if (PixelPtr) { 380 381 /* 382 ** Render all pixels in the "to redraw" stack. 383 */ 384 for (unsigned int index = 0; index < PixelPtr; index++) { 385 CELL cell = PixelStack[index]; 386 if (Cell_On_Radar(cell)) { 387 (*this)[cell].IsPlot = false; 388 Plot_Radar_Pixel(cell); 389 RadarCursorRedraw |= (*this)[cell].IsRadarCursor; 390 } 391 } 392 393 394 /* 395 ** Refill the stack if there is pending pixels yet to be plotted. 396 ** This should only process in sections for speed reasons 397 */ 398 399 if (PixelPtr == PIXELSTACK) { 400 PixelPtr = 0; 401 402 for (int y = 0; y < MapCellHeight; y++) { 403 for (int x = 0; x < MapCellWidth; x++) { 404 CELL cell = XY_Cell(MapCellX + x, MapCellY + y); 405 if (Cell_On_Radar(cell)) { 406 407 if ((*this)[cell].IsPlot) { 408 PixelStack[PixelPtr++] = cell; 409 IsToRedraw = true; 410 if (PixelPtr == PIXELSTACK) break; 411 } 412 } 413 } 414 if (PixelPtr == PIXELSTACK) break; 415 } 416 } else { 417 PixelPtr = 0; 418 } 419 } 420 421 Radar_Cursor(RadarCursorRedraw); 422 423 } else { 424 GraphicViewPortClass *oldpage = Set_Logic_Page(HidPage); 425 // if (LogicPage->Lock()) { 426 CC_Draw_Shape(RadarAnim, RADAR_ACTIVATED_FRAME, RadX, RadY+1, WINDOW_MAIN, SHAPE_NORMAL); 427 if (BaseX || BaseY) { 428 LogicPage->Fill_Rect( RadX + RadOffX, 429 RadY + RadOffY, 430 RadX + RadOffX + RadIWidth - 1, 431 RadY + RadOffY + RadIHeight - 1, 432 DKGREY); 433 } else { 434 LogicPage->Fill_Rect( RadX + RadOffX, 435 RadY + RadOffY, 436 RadX + RadOffX + RadIWidth - 1, 437 RadY + RadOffY + RadIHeight - 1, 438 BLACK); 439 } 440 441 /* 442 ** Draw the entire radar map. 443 */ 444 for (int index = 0; index < MAP_CELL_TOTAL; index++) { 445 Plot_Radar_Pixel(index); 446 } 447 Radar_Cursor(true); 448 FullRedraw = false; 449 IsToRedraw = false; 450 LogicPage->Unlock(); 451 if (oldpage == &SeenBuff) { 452 Hide_Mouse(); 453 LogicPage->Blit(SeenBuff, RadX, RadY, RadX, RadY, RadWidth, RadHeight); 454 Show_Mouse(); 455 } 456 457 // Set_Logic_Page(oldpage); 458 459 // } 460 461 } 462 463 } else { 464 465 /* 466 ** If the radar is not active, then only draw the cover plate if forced to do so. 467 */ 468 // if (forced) { 469 int val = (DoesRadarExist) ? MAX_RADAR_FRAMES : 0; 470 CC_Draw_Shape(RadarAnim, val, RadX, RadY + 1, WINDOW_MAIN, SHAPE_NORMAL); 471 FullRedraw = false; 472 IsToRedraw = false; 473 // } 474 } 475 476 //HidPage.Unlock(); 477 // Map.Activator.Draw_Me(true); 478 } 479 #endif 480 } 481 482 /*************************************************************************** 483 * RadarClass::Render_Terrain -- Render the terrain over the given cell * 484 * * 485 * INPUT: * 486 * * 487 * OUTPUT: * 488 * * 489 * WARNINGS: * 490 * * 491 * HISTORY: * 492 * 04/12/1995 PWG : Created. * 493 *=========================================================================*/ 494 void RadarClass::Render_Terrain(CELL cell, int x, int y, int size) 495 { 496 TerrainClass *list[4]; 497 int listidx = 0; 498 int lp,lp2; 499 500 501 ObjectClass *obj = Map[cell].Cell_Occupier(); 502 503 /* 504 ** If the cell is occupied by a terrain type, add it to the sortable 505 ** list. 506 */ 507 if (obj && obj->What_Am_I() == RTTI_TERRAIN) 508 list[listidx++] = (TerrainClass *)obj; 509 510 /* 511 ** Now loop through all the occupiers and add them to the list if they 512 ** are terrain type. 513 */ 514 for (lp = 0; lp < 3; lp ++) { 515 obj = Map[cell].Overlapper[lp]; 516 if (obj && obj->What_Am_I() == RTTI_TERRAIN) 517 list[listidx++] = (TerrainClass *)obj; 518 } 519 520 /* 521 ** If there are no entrys in our list then just get out. 522 */ 523 if (!listidx) return; 524 525 /* 526 ** If there is terrain in this cell then draw a dark pixel to 527 ** represent it. 528 */ 529 if (size == 1) { 530 LogicPage->Put_Pixel(x, y, 60); 531 return; 532 } 533 534 /* 535 ** Sort the list by its sort Y value so that we can render in the proper 536 ** order. 537 */ 538 for (lp = 0; lp < listidx - 1; lp ++) { 539 for (lp2 = lp + 1; lp2 < listidx; lp2++) { 540 if (list[lp]->Sort_Y() > list[lp2]->Sort_Y()) { 541 TerrainClass *terrain = list[lp]; 542 list[lp] = list[lp2]; 543 list[lp2] = terrain; 544 } 545 } 546 } 547 548 /* 549 ** loop through the list and take care of rendering the correct icon. 550 */ 551 for (lp = 0; lp < listidx; lp ++) { 552 unsigned char *icon = list[lp]->Radar_Icon(cell); 553 if (!icon) continue; 554 555 Buffer_To_Page(0, 0, 3, 3, icon, _IconStage); 556 _IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, ZoomFactor, ZoomFactor, TRUE, (char *)&FadingBrighten[0]); 557 } 558 } 559 560 561 /*********************************************************************************************** 562 * RadarClass::Render_Infantry -- Displays objects on the radar map. * 563 * * 564 * This routine will display an object imagery at the location specified according to the * 565 * condition of the specified cell. * 566 * * 567 * INPUT: cell -- The cell to use as reference when drawing the radar pixel. * 568 * * 569 * x,y -- The pixel coordinate to render the radar "pixel" at. * 570 * * 571 * size -- The size of the "pixel". When zoomed in, this value will be "3". * 572 * * 573 * OUTPUT: none * 574 * * 575 * WARNINGS: none * 576 * * 577 * HISTORY: * 578 * 08/17/1995 JLB : Created. * 579 *=============================================================================================*/ 580 void RadarClass::Render_Infantry(CELL cell, int x, int y, int size) 581 { 582 ObjectClass *obj; 583 int xoff,yoff; 584 585 obj = (ObjectClass *)Map[cell].Cell_Occupier(); 586 while (obj) { 587 if (obj->Is_Techno() && (((TechnoClass *)obj)->Cloak != CLOAKED || ((TechnoClass *)obj)->House->Is_Ally(PlayerPtr))) { 588 switch (obj->What_Am_I()) { 589 case RTTI_INFANTRY: 590 { 591 //int divisor = 255 / ZoomFactor; 592 int divisor = 86; 593 if ( ZoomFactor >= 3 ) { 594 xoff = Coord_XLepton(obj->Coord) / divisor; 595 yoff = Coord_YLepton(obj->Coord) / divisor; 596 if ( ZoomFactor >= 6 ) { 597 xoff<<=1; 598 yoff<<=1; 599 } 600 } else { 601 xoff = 0; 602 yoff = 0; 603 } 604 LogicPage->Put_Pixel(x+xoff, y+yoff, ((InfantryClass *)obj)->House->Class->BrightColor); 605 } 606 break; 607 608 case RTTI_UNIT: 609 case RTTI_AIRCRAFT: 610 // PWG: Slowdown? 611 //if (LogicPage->Lock()){ 612 Fat_Put_Pixel(x, y, ((UnitClass *)obj)->House->Class->BrightColor, size, *LogicPage); 613 //LogicPage->Unlock(); 614 //} 615 break; 616 } 617 } 618 obj = obj->Next; 619 } 620 } 621 622 623 /*************************************************************************** 624 * RadarClass::Render_Overlay -- Renders an icon for given overlay * 625 * * 626 * INPUT: * 627 * * 628 * OUTPUT: * 629 * * 630 * WARNINGS: * 631 * * 632 * HISTORY: * 633 * 04/18/1995 PWG : Created. * 634 *=========================================================================*/ 635 void RadarClass::Render_Overlay(CELL cell, int x, int y, int size) 636 { 637 OverlayType overlay = (*this)[cell].Overlay; 638 if (overlay != OVERLAY_NONE) { 639 OverlayTypeClass const * otype = &OverlayTypeClass::As_Reference(overlay); 640 641 if (otype->IsRadarVisible) { 642 unsigned char *icon = otype->Radar_Icon((*this)[cell].OverlayData); 643 if (!icon) return; 644 Buffer_To_Page(0, 0, 3, 3, icon, _IconStage); 645 if (otype->IsTiberium) { 646 _IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingGreen[0]); 647 } else { 648 _IconStage.Scale(*LogicPage, 0, 0, x, y, 3, 3, size, size, TRUE, (char *)&FadingBrighten[0]); 649 } 650 } 651 } 652 } 653 654 655 /*************************************************************************** 656 * RadarClass::Zoom_Mode -- Handles toggling zoom on the map * 657 * * 658 * INPUT: none * 659 * * 660 * OUTPUT: none * 661 * * 662 * HISTORY: * 663 * 05/29/1995 PWG : Created. * 664 *=========================================================================*/ 665 void RadarClass::Zoom_Mode(CELL cell) 666 { 667 int map_c_width; 668 int map_c_height; 669 /* 670 ** Set all of the initial zoom mode variables to the correct 671 ** setting. 672 */ 673 IsZoomed = !IsZoomed; 674 BaseX = 0; 675 BaseY = 0; 676 677 /* 678 ** Figure out exactly what size we need to zoom the map to. 679 */ 680 if ( !IsZoomed ) { 681 int xfactor = RadIWidth / MapCellWidth; 682 int yfactor = RadIHeight / MapCellHeight; 683 ZoomFactor = MIN(xfactor,yfactor); 684 map_c_width = MapCellWidth; 685 map_c_height = MapCellHeight; 686 } else { 687 ZoomFactor = 6; 688 map_c_width = RadIWidth / ZoomFactor; 689 map_c_height = RadIHeight / ZoomFactor; 690 } 691 692 /* 693 ** Make sure we do not show more cell then are on the map. 694 */ 695 map_c_width = MIN(map_c_width, 62); 696 map_c_height = MIN(map_c_height, 62); 697 698 /* 699 ** Find the amount of remainder because this will let us calculate 700 ** how to center the thing. 701 */ 702 int rem_x = RadIWidth - (map_c_width * ZoomFactor); 703 int rem_y = RadIHeight - (map_c_height * ZoomFactor); 704 705 /* 706 ** Finally mark the map so it shows just as much as it is supposed 707 ** to. 708 */ 709 BaseX = rem_x / 2; 710 BaseY = rem_y / 2; 711 RadarCellWidth = map_c_width; 712 RadarCellHeight = map_c_height; 713 RadarWidth = RadIWidth - rem_x; 714 RadarHeight = RadIWidth - rem_y; 715 716 /* 717 ** Set the radar position to the current cell. 718 */ 719 Set_Radar_Position(cell); 720 721 /* 722 ** When zoom mode changes then we need to redraw the radar 723 ** area. 724 */ 725 IsToRedraw = true; 726 727 /* 728 ** Notify the map that we need to redraw a portion 729 */ 730 Flag_To_Redraw(false); 731 732 /* 733 ** Since we have made a vast change we must redraw everything 734 */ 735 FullRedraw = true; 736 } 737 738 739 /*********************************************************************************************** 740 * RadarClass::Plot_Radar_Pixel -- Updates the radar map with a terrain pixel. * 741 * * 742 * This will update the radar map with a pixel. It is used to display * 743 * vehicle positions on the radar map. * 744 * * 745 * INPUT: unit -- Pointer to unit to render at the given position. If * 746 * NULL is passed in, then the underlying terrain is * 747 * displayed instead. * 748 * * 749 * pos -- Position on the map to update. * 750 * * 751 * OUTPUT: none * 752 * * 753 * WARNINGS: This routine does NOT hide the mouse. It is up to you to * 754 * do so. * 755 * * 756 * HISTORY: * 757 * 06/04/1991 JLB : Created. * 758 * 06/21/1991 JLB : Large blips for units & buildings. * 759 * 02/14/1994 JLB : Revamped. * 760 * 04/17/1995 PWG : Created. * 761 * 04/18/1995 PWG : Created. * 762 *=============================================================================================*/ 763 void RadarClass::Plot_Radar_Pixel(CELL cell) 764 { 765 if (cell == -1) cell = 1; 766 767 int x,y; // Coordinate of cell location. 768 769 /* 770 ** Perform any clipping on the cell coordinate. 771 */ 772 if (!IsRadarActive || (unsigned)cell > MAP_CELL_TOTAL) return; 773 774 if (!In_Radar(cell) || !Cell_On_Radar(cell)) { 775 return; 776 } 777 778 /* 779 ** If we are zoomed in then calculate the pixel based off of the portion 780 ** of the map the radar is viewing. 781 */ 782 x = Cell_X(cell) - RadarX; 783 y = Cell_Y(cell) - RadarY; 784 785 if (LogicPage->Lock()) { 786 CellClass * cellptr = &(*this)[cell]; 787 x = RadX + RadOffX + BaseX + (x * ZoomFactor); 788 y = RadY + RadOffY + BaseY + (y * ZoomFactor); 789 790 /* 791 ** Determine what (if any) vehicle or unit should be rendered in this blip. 792 */ 793 int color=TBLACK; // Color of the pixel to plot. 794 if ((*this)[cell].IsVisible || Debug_Unshroud) { 795 color = cellptr->Cell_Color(true); 796 } else { 797 color = BLACK; 798 } 799 800 // ST 8/13/96 2:24PM 801 //if (cellptr->IsRadarCursor){ 802 // color = WHITE; 803 //} 804 805 /* 806 ** If no color override occurs for this cell, then render the underlying 807 ** terrain. 808 */ 809 if (color == TBLACK) { 810 if (ZoomFactor > 1) { 811 void const *ptr; 812 long offset; 813 int icon; 814 815 if (cellptr->TType != TEMPLATE_NONE) { 816 ptr = TemplateTypeClass::As_Reference(cellptr->TType).Get_Image_Data(); 817 icon = cellptr->TIcon; 818 } else { 819 ptr = TemplateTypeClass::As_Reference(TEMPLATE_CLEAR1).Get_Image_Data(); 820 icon = cellptr->Clear_Icon(); 821 } 822 823 /* 824 ** Convert the logical icon number into the actual icon number. 825 */ 826 Mem_Copy(Add_Long_To_Pointer((void *)ptr, 28), &offset, sizeof(offset)); 827 Mem_Copy(Add_Long_To_Pointer((void *)ptr, offset+icon), &icon, sizeof(char)); 828 icon &= 0x00FF; 829 830 Mem_Copy(Add_Long_To_Pointer((void *)ptr, 12), &offset, sizeof(offset)); 831 ptr = Add_Long_To_Pointer((void *)ptr, offset + icon*(24*24)); 832 833 unsigned char * data = (unsigned char *)ptr; 834 Buffer_To_Page(0, 0, 24, 24, data, _TileStage); 835 _TileStage.Scale(*LogicPage, 0, 0, x, y, 24, 24, ZoomFactor, ZoomFactor, TRUE); 836 837 } else { 838 if (LogicPage->Lock()){ 839 Fat_Put_Pixel(x, y, cellptr->Cell_Color(false), ZoomFactor, *LogicPage); 840 LogicPage->Unlock(); 841 } 842 } 843 } else { 844 if (LogicPage->Lock()){ 845 Fat_Put_Pixel(x, y, color, ZoomFactor, *LogicPage); 846 LogicPage->Unlock(); 847 } 848 } 849 if (color != BLACK) { 850 Render_Overlay(cell, x, y, ZoomFactor); 851 Render_Terrain(cell, x, y, ZoomFactor); 852 Render_Infantry(cell, x, y, ZoomFactor); 853 } 854 LogicPage->Unlock(); 855 } 856 } 857 858 859 /*********************************************************************************************** 860 * RadarClass::Radar_Pixel -- Mark a cell to be rerendered on the radar map. * 861 * * 862 * This routine is used to inform the system that a pixel needs to be * 863 * rerendered on the radar map. The pixel(s) will be rendered the * 864 * next time the map is refreshed. * 865 * * 866 * INPUT: cell -- The map cell to be rerendered. * 867 * * 868 * OUTPUT: none * 869 * * 870 * WARNINGS: none * 871 * * 872 * HISTORY: * 873 * 07/12/1992 JLB : Created. * 874 * 05/08/1994 JLB : Converted to member function. * 875 *=============================================================================================*/ 876 void RadarClass::Radar_Pixel(CELL cell) 877 { 878 if (IsRadarActive && Map.IsSidebarActive && Cell_On_Radar(cell)) { 879 IsToRedraw = true; 880 (*this)[cell].IsPlot = true; 881 if (PixelPtr < PIXELSTACK) { 882 PixelStack[PixelPtr++] = cell; 883 } 884 } 885 } 886 887 888 /*********************************************************************************************** 889 * RadarClass::Click_In_Radar -- Converts a radar click into cell X and Y coordinate. * 890 * * 891 * This routine will examine the X and Y coordinate and convert them into the X and Y * 892 * cell coordinate value that cooresponds to the location. * 893 * * 894 * INPUT: x,y -- The X and Y moouse coordinate already normalized to the radar upper left * 895 * corner. * 896 * * 897 * OUTPUT: Returns with success rating in addition, the X and Y values will now hold the * 898 * cell coordinates of the cell the pixel offsets indicated. * 899 * Result 1 = click was in radar region * 900 * Result 0 = click was outside radar region completly * 901 * Result-1 = click in radar area but not on clickable reagion of radar. * 902 * * 903 * WARNINGS: none * 904 * * 905 * HISTORY: * 906 * 05/30/1995 PWG : Created. * 907 * 07/16/1995 JLB : Recognizes when sidebar is closed now. * 908 *=============================================================================================*/ 909 int RadarClass::Click_In_Radar(int &ptr_x, int &ptr_y, bool change) 910 { 911 int x = ptr_x; 912 int y = ptr_y; 913 914 /* 915 ** If radar is not active the click could have been on a radar point 916 */ 917 if (!IsRadarActive || !Map.IsSidebarActive) return(0); 918 919 x -= (RadX + RadOffX); 920 y -= (RadY + RadOffY); 921 if (x < RadIWidth && y < RadIHeight) { 922 x -= BaseX; 923 y -= BaseY; 924 925 if ((unsigned)x < RadarWidth && (unsigned)y < RadarHeight) { 926 x = RadarX + (x / ZoomFactor); 927 y = RadarY + (y / ZoomFactor); 928 if (change) { 929 ptr_x = x; 930 ptr_y = y; 931 } 932 return(1); 933 } 934 return(-1); 935 } 936 return(0); 937 } 938 939 940 /*********************************************************************************************** 941 * RadarClass::Click_Cell_Calc -- Determines what cell the pixel coordinate is over. * 942 * * 943 * This routine will examine the pixel coordinate provided and determine what cell it * 944 * represents. If the radar map is not active or the coordinates are not positioned over * 945 * the radar map, then it will fall into the base class corresponding routine. * 946 * * 947 * INPUT: x,y -- The pixel coordinate to convert into a cell number. * 948 * * 949 * OUTPUT: Returns with the cell number that the coordinate is over or -1 if not over any * 950 * cell. * 951 * * 952 * WARNINGS: none * 953 * * 954 * HISTORY: * 955 * 12/22/1994 JLB : Created. * 956 *=============================================================================================*/ 957 CELL RadarClass::Click_Cell_Calc(int x, int y) 958 { 959 int result = Click_In_Radar(x, y, true); 960 switch (result) { 961 case 1: 962 return(XY_Cell(x, y)); 963 964 case -1: 965 return(-1); 966 } 967 return(DisplayClass::Click_Cell_Calc(x, y)); 968 } 969 970 971 /*********************************************************************************************** 972 * RadarClass::Map_Cell -- Updates radar map when a cell becomes mapped. * 973 * * 974 * This routine will update the radar map if a cell becomes mapped. * 975 * * 976 * INPUT: cell -- The cell that is being mapped. * 977 * * 978 * house -- The house that is doing the mapping. * 979 * * 980 * OUTPUT: bool; Was the cell mapped (for the first time) by this routine? * 981 * * 982 * WARNINGS: none * 983 * * 984 * HISTORY: * 985 * 12/22/1994 JLB : Created. * 986 *=============================================================================================*/ 987 bool RadarClass::Map_Cell(CELL cell, HouseClass * house, bool and_for_allies) 988 { 989 if (DisplayClass::Map_Cell(cell, house, and_for_allies)) { 990 Radar_Pixel(cell); 991 return(true); 992 } 993 return(false); 994 } 995 996 void RadarClass::Cursor_Cell(CELL cell, int value) 997 { 998 int temp = (*this)[cell].IsRadarCursor; 999 1000 /* 1001 ** If this cell is not on the radar don't botther doing anything. 1002 */ 1003 if (In_Radar(cell) && temp != value) { 1004 /* 1005 ** Record the new state of this cell. 1006 */ 1007 (*this)[cell].IsRadarCursor = value; 1008 1009 /* 1010 ** If we are erasing then erase the cell. 1011 */ 1012 ////// ST 8/13/96 2:23PM 1013 if (value == FALSE) { 1014 Plot_Radar_Pixel(cell); 1015 ////// 1016 } 1017 } 1018 } 1019 1020 void RadarClass::Mark_Radar(int x1, int y1, int x2, int y2, int value, int barlen) 1021 { 1022 int x, y; 1023 /* 1024 ** First step is to convert pixel coordinates back to a CellX and CellY. 1025 */ 1026 x1 = RadarX + (x1 / ZoomFactor); 1027 y1 = RadarY + (y1 / ZoomFactor); 1028 x2 = RadarX + (x2 / ZoomFactor); 1029 y2 = RadarY + (y2 / ZoomFactor); 1030 1031 /* 1032 ** Now we need to convert the Pixel length to a cell length. 1033 */ 1034 barlen = (barlen / ZoomFactor)+1; 1035 1036 /* 1037 ** Now lets loop through and mark the map with the proper value. 1038 */ 1039 for (int lp = 0; lp <= barlen; lp++) { 1040 /* 1041 ** Do Horizontal action to upper and lower left corners. 1042 */ 1043 x = x1 + lp; 1044 Cursor_Cell(XY_Cell(x,y1), value); 1045 Cursor_Cell(XY_Cell(x,y2), value); 1046 /* 1047 ** Do Horizontal Action to upper and lower right corners 1048 */ 1049 x = x2 - lp; 1050 Cursor_Cell(XY_Cell(x,y1), value); 1051 Cursor_Cell(XY_Cell(x,y2), value); 1052 /* 1053 ** Do Vertical Action to left and right upper corners 1054 */ 1055 y = y1 + lp; 1056 Cursor_Cell(XY_Cell(x1,y), value); 1057 Cursor_Cell(XY_Cell(x2,y), value); 1058 1059 /* 1060 ** Do Vertical action to left and right lower corners. 1061 */ 1062 y = y2 - lp; 1063 Cursor_Cell(XY_Cell(x1,y), value); 1064 Cursor_Cell(XY_Cell(x2,y), value); 1065 } 1066 } 1067 1068 1069 1070 /*********************************************************************************************** 1071 * RadarClass::Cell_XY_To_Radar_Pixel-- Adjust the position of the radar map cursor. * 1072 * * 1073 * This routine will adjust the location (and visibility) of the radar * 1074 * map cursor. It handles all restoration, drawing, and flashing. * 1075 * * 1076 * INPUT: pos - Cell position for the cursor. If the value is -1 then * 1077 * the cursor will be hidden. If the value is equal to * 1078 * the last value passed in then cursor flashing will * 1079 * be maintained. * 1080 * * 1081 * OUTPUT: none * 1082 * * 1083 * WARNINGS: none * 1084 * * 1085 * HISTORY: * 1086 * 05/22/1991 JLB : Created. * 1087 * 11/17/1995 PWG : Created. * 1088 *=============================================================================================*/ 1089 void RadarClass::Cell_XY_To_Radar_Pixel(int cellx, int celly, int &x, int &y) 1090 { 1091 x = (cellx - RadarX) * ZoomFactor; 1092 y = (celly - RadarY) * ZoomFactor; 1093 } 1094 1095 /*********************************************************************************************** 1096 * RadarClass::Radar_Cursor -- Adjust the position of the radar map cursor. * 1097 * * 1098 * This routine will adjust the location (and visibility) of the radar * 1099 * map cursor. It handles all restoration, drawing, and flashing. * 1100 * * 1101 * INPUT: pos - Cell position for the cursor. If the value is -1 then * 1102 * the cursor will be hidden. If the value is equal to * 1103 * the last value passed in then cursor flashing will * 1104 * be maintained. * 1105 * * 1106 * OUTPUT: none * 1107 * * 1108 * WARNINGS: none * 1109 * * 1110 * HISTORY: * 1111 * 05/22/1991 JLB : Created. * 1112 * 11/17/1995 PWG : Created. * 1113 *=============================================================================================*/ 1114 //#pragma argsused 1115 void RadarClass::Radar_Cursor(int forced) 1116 { 1117 static int _last_pos = -1; 1118 static int _last_frame = -1; 1119 GraphicViewPortClass *oldpage; 1120 int x1, y1, x2, y2; 1121 /* 1122 ** figure out these function calls as we will need to call them multiple times. 1123 */ 1124 int tac_cell = Coord_Cell(TacticalCoord); 1125 int tac_cell_x = Cell_X(tac_cell); 1126 int tac_cell_y = Cell_Y(tac_cell); 1127 int barlen = 6; 1128 /* 1129 ** If the current tactical cell is invalid or we haven't moved and we are not forced to redraw then 1130 ** just skip the redraw process. 1131 */ 1132 if (tac_cell != -1 && _last_pos == tac_cell && _last_frame == SpecialRadarFrame && !forced) return; 1133 1134 if ( _last_pos != -1 ) { 1135 /* 1136 ** The first thing we need to do is take care of erasing the last radar cell position. We do this 1137 ** by converting to pixel coordinates, then adjusting for the pixel coords for the current frame and 1138 ** finally taking care of calling the erase procedure which will convert the pixel coordinates back 1139 ** to the cells that need to be redraw. 1140 **/ 1141 int last_cell_x = Cell_X(_last_pos); 1142 int last_cell_y = Cell_Y(_last_pos); 1143 1144 Cell_XY_To_Radar_Pixel(last_cell_x, last_cell_y, x1, y1); 1145 Cell_XY_To_Radar_Pixel(last_cell_x + Lepton_To_Cell(TacLeptonWidth), last_cell_y + Lepton_To_Cell(TacLeptonHeight), x2, y2); 1146 x2--; 1147 y2--; 1148 1149 /* 1150 ** Adjust the current coordinates based on the last animation frame. 1151 */ 1152 x1-= _last_frame; 1153 y1-= _last_frame; 1154 x2+= _last_frame; 1155 y2+= _last_frame; 1156 /* 1157 ** Finally mark the map (actually remove the marks that indicate the radar cursor was there 1158 */ 1159 Mark_Radar(x1, y1, x2, y2, FALSE, barlen); 1160 } 1161 1162 1163 /* 1164 ** find the upper left and lower right corners of the radar cursor. Remember to adjust x2 and y2 back 1165 ** by one pixel as they will not be pointing to the right value otherwise. They point one cell ahead 1166 ** of where they should. 1167 */ 1168 Cell_XY_To_Radar_Pixel(tac_cell_x, tac_cell_y, x1, y1); 1169 Cell_XY_To_Radar_Pixel(tac_cell_x + Lepton_To_Cell(TacLeptonWidth), tac_cell_y + Lepton_To_Cell(TacLeptonHeight), x2, y2); 1170 x2--; 1171 y2--; 1172 1173 /* 1174 ** Adjust the coordinates based on the current frame of radar animation. 1175 */ 1176 x1-= SpecialRadarFrame; 1177 y1-= SpecialRadarFrame; 1178 x2+= SpecialRadarFrame; 1179 y2+= SpecialRadarFrame; 1180 1181 Mark_Radar(x1, y1, x2, y2, TRUE, barlen); 1182 1183 /* 1184 ** setup a graphic view port class so we can write all the pixels relative 1185 ** to 0,0 rather than relative to full screen coordinates. 1186 */ 1187 oldpage = Set_Logic_Page(HidPage); 1188 GraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(), 1189 RadX + RadOffX + BaseX + LogicPage->Get_XPos(), 1190 RadY + RadOffY + BaseY + LogicPage->Get_YPos(), 1191 RadarWidth, 1192 RadarHeight); 1193 1194 draw_window.Draw_Line(x1, y1, x1 + barlen, y1, LTGREEN); 1195 draw_window.Draw_Line(x1, y1, x1, y1 + barlen, LTGREEN); 1196 1197 // Draw upper right hand corner 1198 draw_window.Draw_Line(x2 - barlen, y1, x2, y1, LTGREEN); 1199 draw_window.Draw_Line(x2, y1, x2, y1 + barlen, LTGREEN); 1200 1201 // Draw lower left hand corner 1202 draw_window.Draw_Line(x1, y2 - barlen, x1, y2, LTGREEN); 1203 draw_window.Draw_Line(x1, y2, x1 + barlen, y2, LTGREEN); 1204 1205 // Draw lower right hand corner 1206 draw_window.Draw_Line(x2, y2 - barlen, x2, y2, LTGREEN); 1207 draw_window.Draw_Line(x2 - barlen, y2, x2, y2, LTGREEN); 1208 #if(0) 1209 draw_window.Draw_Rect(x1, y1, x2, y2, WHITE); 1210 #endif 1211 1212 #if(FALSE) 1213 if (oldpage == &SeenBuff) { 1214 Hide_Mouse(); 1215 HidPage.Blit( SeenBuff, 1216 (int)(RadX + RadOffX + BaseX), 1217 (int)(RadY + RadOffY + BaseY), 1218 (int)(RadX + RadOffX + BaseX), 1219 (int)(RadY + RadOffY + BaseY), 1220 (int)draw_window.Get_Width(), 1221 (int)draw_window.Get_Height(), 1222 (BOOL)FALSE); 1223 1224 Show_Mouse(); 1225 } 1226 #endif 1227 Set_Logic_Page(oldpage); 1228 _last_pos = tac_cell; 1229 _last_frame = SpecialRadarFrame; 1230 RadarCursorRedraw = FALSE; 1231 } 1232 1233 1234 /*************************************************************************** 1235 * RadarClass::Radar_Anim -- Renders current frame of radar animation * 1236 * * 1237 * * 1238 * * 1239 * INPUT: * 1240 * * 1241 * OUTPUT: * 1242 * * 1243 * WARNINGS: * 1244 * * 1245 * HISTORY: * 1246 * 04/19/1995 PWG : Created. * 1247 *=========================================================================*/ 1248 void RadarClass::Radar_Anim(void) 1249 { 1250 /* 1251 ** Do nothing if we're in player-name mode 1252 */ 1253 if (IsPlayerNames) 1254 return; 1255 1256 if (!Map.IsSidebarActive) return; 1257 1258 GraphicViewPortClass *oldpage= Set_Logic_Page(HidPage); 1259 GraphicViewPortClass draw_window(LogicPage->Get_Graphic_Buffer(), 1260 RadX + RadOffX + LogicPage->Get_XPos(), 1261 RadY + RadOffY + LogicPage->Get_YPos(), 1262 RadIWidth, 1263 RadIHeight); 1264 1265 Draw_Box(RadX+RadOffX-1, RadY+RadOffY-1, RadIWidth+2, RadIHeight+2, BOXSTYLE_RAISED, true); 1266 draw_window.Clear(); 1267 CC_Draw_Shape(RadarAnim, RadarAnimFrame, RadX, RadY+1, WINDOW_MAIN, SHAPE_NORMAL); 1268 1269 Flag_To_Redraw(false); 1270 Set_Logic_Page(oldpage); 1271 } 1272 1273 1274 /*********************************************************************************************** 1275 * RadarClass::AI -- Processes radar input (non-tactical). * 1276 * * 1277 * This routine intercepts any player input that concerns the radar map, but not those * 1278 * areas that represent the tactical map. These are handled by the tactical map AI * 1279 * processor. Primarily, this routine handles the little buttons that border the radar * 1280 * map. * 1281 * * 1282 * INPUT: input -- The player input code. * 1283 * * 1284 * x,y -- Mouse coordinate parameters to use. * 1285 * * 1286 * OUTPUT: none * 1287 * * 1288 * WARNINGS: none * 1289 * * 1290 * HISTORY: * 1291 * 12/23/1994 JLB : Created. * 1292 * 12/26/1994 JLB : Moves tactical map with click or drag. * 1293 * 12/31/1994 JLB : Uses mouse coordinate parameters. * 1294 *=============================================================================================*/ 1295 void RadarClass::AI(KeyNumType & input, int x, int y) 1296 { 1297 /* 1298 ** Check to see if we need to animate the radar cursor 1299 */ 1300 if (IsRadarActive && Map.IsSidebarActive && SpecialRadarFrame) { 1301 SpecialRadarFrame--; 1302 RadarCursorRedraw = TRUE; 1303 IsToRedraw = TRUE; 1304 Flag_To_Redraw(FALSE); 1305 } 1306 1307 /* 1308 ** Check goes here to see if there is enough power to run the radar 1309 */ 1310 if (IsRadarActivating) { 1311 if (!DoesRadarExist) { 1312 RadarAnimFrame++; 1313 if (RadarAnimFrame < RADAR_ACTIVATED_FRAME) { 1314 IsToRedraw = true; 1315 Flag_To_Redraw(false); 1316 } else { 1317 DoesRadarExist = true; 1318 Radar_Activate(3); 1319 } 1320 } else { 1321 RadarAnimFrame--; 1322 if (RadarAnimFrame > RADAR_ACTIVATED_FRAME) { 1323 IsToRedraw = true; 1324 Flag_To_Redraw(false); 1325 } else { 1326 Radar_Activate(3); 1327 } 1328 } 1329 } 1330 if (IsRadarDeactivating) { 1331 RadarAnimFrame++; 1332 if (RadarAnimFrame == MAX_RADAR_FRAMES) { 1333 IsRadarDeactivating = false; 1334 } else { 1335 IsToRedraw = true; 1336 Flag_To_Redraw(false); 1337 } 1338 } 1339 1340 DisplayClass::AI(input, x, y); 1341 } 1342 1343 1344 /*********************************************************************************************** 1345 * RadarClass::TacticalClass::Action -- I/O function for the radar map. * 1346 * * 1347 * This is the main action function for handling player I/O on the radar map. It processes * 1348 * mouse clicks as well as mouse moves. * 1349 * * 1350 * INPUT: flags -- The event flags that trigger this function call. * 1351 * * 1352 * key -- Reference the keyboard event that applies to the trigger event. * 1353 * * 1354 * OUTPUT: Should further processing of the input list be aborted? * 1355 * * 1356 * WARNINGS: none * 1357 * * 1358 * HISTORY: * 1359 * 05/08/1995 JLB : Created. * 1360 *=============================================================================================*/ 1361 int RadarClass::TacticalClass::Action(unsigned flags, KeyNumType & key) 1362 { 1363 CELL cell; // cell num click happened over 1364 int x,y; // Sub cell pixel coordinates. 1365 int cellx,celly; // Sub cell pixel coordinates. 1366 bool shadow; // is the cell in shadow or not 1367 ObjectClass *object = 0; // what object is in the cell 1368 ActionType action = ACTION_NONE; // Action possible with currently selected object. 1369 1370 /* 1371 ** Force any help label to disappear when the mouse is held over the 1372 ** radar map. 1373 */ 1374 if (Map.IsSidebarActive) { 1375 Map.Help_Text(TXT_NONE); 1376 } 1377 1378 if (!Map.IsRadarActive) { 1379 if (Map.IsSidebarActive) { 1380 Map.Override_Mouse_Shape(MOUSE_NORMAL, true); 1381 } 1382 return(false); 1383 } 1384 1385 /* 1386 ** Disable processing if the player names are up 1387 */ 1388 if (Map.Is_Player_Names()) { 1389 GadgetClass::Action(0, key); 1390 return(true); 1391 } 1392 1393 /* 1394 ** Set some working variables that depend on the mouse position. For the press 1395 ** or release event, special mouse queuing storage variables are used. Other 1396 ** events must use the current mouse position globals. 1397 */ 1398 if (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) { 1399 x = _Kbd->MouseQX; 1400 y = _Kbd->MouseQY; 1401 } else { 1402 x = Get_Mouse_X(); 1403 y = Get_Mouse_Y(); 1404 } 1405 1406 int result = Map.RadarClass::Click_In_Radar(x, y, false); 1407 1408 if (result == 1) { 1409 cell = Map.RadarClass::Click_Cell_Calc(x, y); 1410 if (cell != -1) { 1411 //using function for IsVisible so we have different results for different players - JAS 2019/09/30 1412 shadow = (!Map[cell].Is_Visible(PlayerPtr) && !Debug_Unshroud); 1413 cellx = 12; 1414 celly = 12; 1415 1416 /* 1417 ** Determine the object that the mouse is currently over. 1418 */ 1419 if (!shadow) { 1420 object = Map.Cell_Object(cell, cellx, celly); 1421 } 1422 1423 /* 1424 ** If there is a currently selected object, then the action to perform if 1425 ** the left mouse button were clicked must be determined. 1426 */ 1427 if (CurrentObject.Count()) { 1428 if (object) { 1429 action = CurrentObject[0]->What_Action(object); 1430 } else { 1431 action = CurrentObject[0]->What_Action(cell); 1432 } 1433 1434 /* 1435 ** If this is not a valid radar map action then we are not going to do 1436 ** anything. 1437 */ 1438 switch (action) { 1439 case ACTION_MOVE: 1440 case ACTION_NOMOVE: 1441 case ACTION_ATTACK: 1442 case ACTION_ENTER: 1443 case ACTION_CAPTURE: 1444 case ACTION_SABOTAGE: 1445 break; 1446 1447 default: 1448 action = ACTION_NONE; 1449 object = NULL; 1450 break; 1451 } 1452 1453 /* 1454 ** On the radar map the only reason we would want the normal cursor to 1455 ** appear is if we were over one of our own selected units. Otherwise 1456 ** we can't move there. 1457 **/ 1458 if (action == ACTION_NONE) { 1459 if (object && object->Is_Selected_By_Player()) { 1460 object = NULL; 1461 } else { 1462 action = ACTION_NOMOVE; 1463 } 1464 } 1465 1466 /* 1467 ** A right mouse button press toggles the zoom mode. 1468 */ 1469 if (flags & RIGHTPRESS) { 1470 Map.Mouse_Right_Press(); 1471 } 1472 1473 /* 1474 ** When the mouse buttons aren't pressed, only the mouse cursor shape is processed. 1475 ** The shape changes depending on what object the mouse is currently over and what 1476 ** object is currently selected. 1477 */ 1478 if (flags & LEFTUP) { 1479 Map.Mouse_Left_Up(shadow, object, action, true); 1480 } 1481 1482 /* 1483 ** Normal actions occur when the mouse button is released. The press event is 1484 ** intercepted and possible rubber-band mode is flagged. 1485 */ 1486 if (flags & LEFTPRESS) { 1487 Map.Mouse_Left_Release(cell, cellx, celly, object, action, true); 1488 } 1489 1490 } else { 1491 1492 Map.Set_Default_Mouse(MOUSE_RADAR_CURSOR, !Map.IsZoomed); 1493 1494 if (flags & LEFTPRESS) { 1495 1496 cell = Map.RadarClass::Click_Cell_Calc(x, y); 1497 if (cell != -1) { 1498 int cellx = Cell_X(cell); 1499 int celly = Cell_Y(cell); 1500 cellx -= Lepton_To_Cell(Map.TacLeptonWidth) / 2; 1501 cellx = MAX(cellx, Map.MapCellX); 1502 celly -= Lepton_To_Cell(Map.TacLeptonHeight) / 2; 1503 celly = MAX(celly, Map.MapCellY); 1504 cell = XY_Cell(cellx, celly); 1505 shadow = (!Map[cell].Is_Visible(PlayerPtr) && !Debug_Unshroud); 1506 Map.Set_Tactical_Position(Cell_Coord(cell)); 1507 cell = Coord_Cell(Map.DesiredTacticalCoord); 1508 Map.DisplayClass::IsToRedraw = true; 1509 //Map.Flag_To_Redraw(false); 1510 Map.Flag_To_Redraw(true); 1511 Map.SpecialRadarFrame = 4; 1512 } 1513 } 1514 1515 /* 1516 ** A right mouse button press toggles the zoom mode. 1517 */ 1518 if (flags & RIGHTPRESS) { 1519 Map.Zoom_Mode(cell); 1520 } 1521 } 1522 } 1523 } 1524 if (result == -1) { 1525 Map.Override_Mouse_Shape(MOUSE_NORMAL, true); 1526 } 1527 GadgetClass::Action(0, key); 1528 return(true); 1529 } 1530 1531 1532 /*********************************************************************************************** 1533 * RadarClass::Refresh_Cells -- Intercepts refresh request and updates radar if needed * 1534 * * 1535 * This routine intercepts the refresh cells request and if it detects that the sidebar * 1536 * should be rerendered, it flags the radar map to redraw during the next draw operation. * 1537 * * 1538 * INPUT: cell -- The origin cell that the refresh cell offset list is based upon. * 1539 * * 1540 * list -- Pointer to the list of offsets from the origin cell that specifies the * 1541 * cells to be flagged for redraw. If the list starts with the special * 1542 * code to refresh the sidebar, then this routine recognizes it and flags * 1543 * the radar map to be redrawn accordingly. * 1544 * * 1545 * OUTPUT: none * 1546 * * 1547 * WARNINGS: none * 1548 * * 1549 * HISTORY: * 1550 * 01/01/1995 JLB : Created. * 1551 *=============================================================================================*/ 1552 void RadarClass::Refresh_Cells(CELL cell, short const *list) 1553 { 1554 if (*list == REFRESH_SIDEBAR) { 1555 IsToRedraw = true; 1556 Flag_To_Redraw(false); 1557 } 1558 DisplayClass::Refresh_Cells(cell, list); 1559 } 1560 1561 1562 /*********************************************************************************************** 1563 * RadarClass::Set_Radar_Position -- Sets the radar position to center around specified cell. * 1564 * * 1565 * This routine will try to center the radar map around the cell position specified. * 1566 * * 1567 * INPUT: cell -- The cell to try and position the radar map around. * 1568 * * 1569 * OUTPUT: none * 1570 * * 1571 * WARNINGS: none * 1572 * * 1573 * HISTORY: * 1574 * 05/08/1995 JLB : Created. * 1575 *=============================================================================================*/ 1576 void RadarClass::Set_Radar_Position(CELL cell) 1577 { 1578 int oldx, oldy; 1579 int newx, newy; 1580 int newcell; 1581 1582 if (ZoomFactor != 1) { 1583 #if(FALSE) 1584 oldx = (Cell_X(cell) - MapCellX) - (RadarCellWidth / 2); 1585 oldy = (Cell_Y(cell) - MapCellY) - (RadarCellHeight / 2); 1586 #else 1587 oldx = (Cell_X(cell) - MapCellX); 1588 oldy = (Cell_Y(cell) - MapCellY); 1589 #endif 1590 } else { 1591 oldx = 0; 1592 oldy = 0; 1593 } 1594 1595 Confine_Rect(&oldx, &oldy, RadarCellWidth, RadarCellHeight, MapCellWidth, MapCellHeight); 1596 1597 newx = oldx + MapCellX; 1598 newy = oldy + MapCellY; 1599 newcell = XY_Cell(newx, newy); 1600 1601 if (RadarCell != newcell) { 1602 int forced = FALSE; 1603 int xmod = newx; 1604 int ymod = newy; 1605 1606 int radx = (Cell_X(RadarCell)) - xmod; 1607 int rady = (Cell_Y(RadarCell)) - ymod; 1608 1609 RadarX = newx; 1610 RadarY = newy; 1611 RadarCell = newcell; 1612 1613 if (Map.IsSidebarActive&& Map.IsRadarActive) { 1614 int radw = RadarCellWidth-ABS(radx); // Replicable width. 1615 int radh = RadarCellHeight-ABS(rady); // Replicable height. 1616 1617 if (radw < 1) forced = true; 1618 if (radh < 1) forced = true; 1619 1620 if (!forced && (radw != RadarWidth || radh != RadarHeight)) { 1621 /* 1622 ** Blit the section that is actually overlapping. 1623 */ 1624 if (OverlappedVideoBlits || !HidPage.Get_IsDirectDraw()){ 1625 HidPage.Blit(HidPage, 1626 (((radx < 0) ? -radx : 0) * ZoomFactor) + RadX + RadOffX + BaseX, 1627 (((rady < 0) ? -rady : 0) * ZoomFactor) + RadY + RadOffY + BaseY, 1628 (((radx < 0) ? 0 : radx) * ZoomFactor) + RadX+ RadOffX + BaseX, 1629 (((rady < 0) ? 0 : rady) * ZoomFactor) + RadY + RadOffY + BaseY, 1630 radw * ZoomFactor, 1631 radh * ZoomFactor); 1632 }else{ 1633 /* 1634 ** System does not support overlapped blitting of video surfaces. 1635 ** Blit it in 2 stages using an intermediate buffer. 1636 */ 1637 GraphicBufferClass temp_surface; 1638 temp_surface.Init((RadarWidth + 16) & 0xfffffff0, 1639 (RadarHeight + 16) & 0xfffffff0, 1640 NULL, 0, (GBC_Enum) GBC_VIDEOMEM); 1641 1642 HidPage.Blit(temp_surface, (((radx < 0) ? -radx : 0) * ZoomFactor) + RadX + RadOffX + BaseX, 1643 (((rady < 0) ? -rady : 0) * ZoomFactor) + RadY + RadOffY + BaseY, 1644 0, 1645 0, 1646 RadarWidth, 1647 RadarHeight); 1648 1649 temp_surface.Blit (HidPage,0, 1650 0, 1651 (((radx < 0) ? 0 : radx) * ZoomFactor) + RadX + RadOffX + BaseX, 1652 (((rady < 0) ? 0 : rady) * ZoomFactor) + RadY + RadOffY + BaseY, 1653 radw * ZoomFactor, 1654 radh * ZoomFactor); 1655 } 1656 1657 /* 1658 ** Now we need to flag the section of the map that is going to redraw. 1659 */ 1660 if ( radx != 0 ) { 1661 int min; 1662 int max; 1663 if ( radx < 0 ) { // this mean regen the right edge 1664 min = radw; 1665 max = radw+ABS(radx); 1666 } else { // this mean regen the left edge 1667 min = 0; 1668 max = radx; 1669 } 1670 for (int x = min; x < max; x++ ) { 1671 for (unsigned int y = 0; y < RadarCellHeight; y++ ) { 1672 Radar_Pixel(XY_Cell(newx + x, newy + y)); 1673 } 1674 } 1675 } 1676 if ( newy != 0 ) { 1677 int min; 1678 int max; 1679 if ( rady < 0 ) { // this mean regen the bottom edge 1680 min = radh; 1681 max = radh+ABS(rady); 1682 } else { // this mean regen the top edge 1683 min = 0; 1684 max = rady; 1685 } 1686 for (int y = min; y < max; y++ ) { 1687 for ( unsigned int x = 0; x < RadarCellWidth; x++ ) { 1688 Radar_Pixel(XY_Cell(newx + x, newy + y)); 1689 } 1690 } 1691 } 1692 } 1693 } 1694 RadarCursorRedraw = IsRadarActive; 1695 IsToRedraw = IsRadarActive; 1696 Flag_To_Redraw(false); 1697 if (ZoomFactor > 4) { 1698 FullRedraw = forced; 1699 } 1700 } else { 1701 RadarCursorRedraw = IsRadarActive; 1702 IsToRedraw = IsRadarActive; 1703 Flag_To_Redraw(false); 1704 } 1705 } 1706 1707 1708 /*********************************************************************************************** 1709 * RadarClass::Radar_Position -- Returns with the current position of the radar map. * 1710 * * 1711 * This returns the cell number of the upper left corner of the radar map. * 1712 * * 1713 * INPUT: none * 1714 * * 1715 * OUTPUT: Returns with the radar map upper left corner cell position. * 1716 * * 1717 * WARNINGS: none * 1718 * * 1719 * HISTORY: * 1720 * 05/08/1995 JLB : Created. * 1721 *=============================================================================================*/ 1722 CELL RadarClass::Radar_Position(void) 1723 { 1724 return(RadarCell); 1725 } 1726 1727 1728 /*********************************************************************************************** 1729 * RadarClass::Set_Map_Dimensions -- Sets the tactical map dimensions. * 1730 * * 1731 * This routine is called when the tactical map changes its dimensions. This occurs when * 1732 * the tactical map moves and when the sidebar pops on or off. * 1733 * * 1734 * INPUT: x,y -- The cell coordinate of the upper left corner of the tactical map. * 1735 * * 1736 * w,y -- The cell width and height of the tactical map. * 1737 * * 1738 * OUTPUT: none * 1739 * * 1740 * WARNINGS: none * 1741 * * 1742 * HISTORY: * 1743 * 05/08/1995 JLB : Created. * 1744 *=============================================================================================*/ 1745 void RadarClass::Set_Map_Dimensions(int x, int y, int w, int h) 1746 { 1747 Set_Radar_Position(XY_Cell(x, y)); 1748 DisplayClass::Set_Map_Dimensions(x, y, w, h); 1749 } 1750 1751 1752 /*********************************************************************************************** 1753 * RadarClass::Set_Tactical_Position -- Sets the map's tactical position and adjusts radar to * 1754 * * 1755 * This routine is called when the tactical map is to change position. The radar map might * 1756 * be adjusted as well by this routine. * 1757 * * 1758 * INPUT: coord -- The new coordinate to use for the upper left corner of the tactical * 1759 * map. * 1760 * * 1761 * OUTPUT: none * 1762 * * 1763 * WARNINGS: none * 1764 * * 1765 * HISTORY: * 1766 * 08/17/1995 JLB : Created. * 1767 *=============================================================================================*/ 1768 void RadarClass::Set_Tactical_Position(COORDINATE coord) 1769 { 1770 DisplayClass::Set_Tactical_Position(coord); 1771 Set_Radar_Position(Coord_Cell(DesiredTacticalCoord)); 1772 } 1773 1774 1775 /*********************************************************************************************** 1776 * RadarClass::Cell_On_Radar -- Determines if a cell is currently visible on radar. * 1777 * * 1778 * This routine will examine the specified cell number and return whether it is visible * 1779 * on the radar map. This depends on the radar map position. * 1780 * * 1781 * INPUT: cell -- The cell number to check. * 1782 * * 1783 * OUTPUT: Is the specified cell visible on the radar map currently? * 1784 * * 1785 * WARNINGS: none * 1786 * * 1787 * HISTORY: * 1788 * 05/03/1995 JLB : Created. * 1789 *=============================================================================================*/ 1790 bool RadarClass::Cell_On_Radar(CELL cell) 1791 { 1792 if ((unsigned)cell > MAP_CELL_TOTAL) 1793 return(false); 1794 1795 int x = Cell_X(cell) - RadarX; 1796 int y = Cell_Y(cell) - RadarY; 1797 return (!((unsigned)x >= RadarCellWidth || (unsigned)y >= RadarCellHeight)); 1798 1799 // if (!IsZoomed) { 1800 // return(true); 1801 // } 1802 // return(!(((Cell_X(cell) - RadarX) > RadarCellWidth) || ((Cell_Y(cell) - RadarY) > RadarCellHeight))); 1803 } 1804 1805 /*********************************************************************************************** 1806 * RadarClass::Player_Names -- toggles the Player-Names mode of the radar map * 1807 * * 1808 * INPUT: * 1809 * on true = turn on; false = turn off * 1810 * * 1811 * OUTPUT: * 1812 * none. * 1813 * * 1814 * WARNINGS: * 1815 * none. * 1816 * * 1817 * HISTORY: * 1818 * 06/07/1995 BRR : Created. * 1819 *=============================================================================================*/ 1820 void RadarClass::Player_Names(bool on) 1821 { 1822 IsPlayerNames = on; 1823 IsToRedraw = true; 1824 if (on) { 1825 Flag_To_Redraw(true); 1826 // Flag_To_Redraw(false); 1827 } else { 1828 Flag_To_Redraw(true); // force drawing of the plate 1829 } 1830 } 1831 1832 1833 /*********************************************************************************************** 1834 * Draw_Names -- draws players' names on the radar map * 1835 * * 1836 * INPUT: * 1837 * none. * 1838 * * 1839 * OUTPUT: * 1840 * none. * 1841 * * 1842 * WARNINGS: * 1843 * none. * 1844 * * 1845 * HISTORY: * 1846 * 06/07/1995 BRR : Created. * 1847 *=============================================================================================*/ 1848 void RadarClass::Draw_Names(void) 1849 { 1850 int c_idx; 1851 HousesType house; 1852 HouseClass *ptr; 1853 int y; 1854 char txt[40]; 1855 unsigned char id; 1856 int i; 1857 HousesType h; 1858 int kills; 1859 int color; 1860 TextPrintType style; 1861 int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2; 1862 1863 /* 1864 ** Do nothing if the sidebar isn't there 1865 */ 1866 if (!Map.IsSidebarActive) { 1867 return; 1868 } 1869 1870 CC_Draw_Shape(RadarAnim, RADAR_ACTIVATED_FRAME, RadX, RadY+1, WINDOW_MAIN, SHAPE_NORMAL); 1871 LogicPage->Fill_Rect( RadX + RadOffX, 1872 RadY + RadOffY, 1873 RadX + RadOffX + RadIWidth - 1, 1874 RadY + RadOffY + RadIHeight - 1, 1875 BLACK); 1876 1877 y = RadY + RadOffY; 1878 1879 Fancy_Text_Print (TXT_NAME_COLON, RadX + RadOffX, y, LTGREY, TBLACK, 1880 TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW); 1881 1882 1883 Fancy_Text_Print (TXT_KILLS_COLON, RadX + RadOffX + RadIWidth - 2, y, 1884 LTGREY, TBLACK, TPF_RIGHT | TPF_6PT_GRAD | TPF_NOSHADOW | TPF_USE_GRAD_PAL); 1885 1886 y += 6*factor+1; 1887 1888 LogicPage->Draw_Line(RadX + RadOffX, y, 1889 RadX + RadOffX + RadIWidth - 1, y, LTGREY); 1890 1891 y += 2*factor; 1892 1893 for (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + MPlayerMax); house++) { 1894 ptr = HouseClass::As_Pointer(house); 1895 1896 if (!ptr) 1897 continue; 1898 1899 /* 1900 ** Decode this house's color 1901 */ 1902 c_idx = ptr->RemapColor; 1903 1904 if (ptr->IsDefeated) { 1905 color = GREY; 1906 style = TPF_6PT_GRAD | TPF_NOSHADOW | TPF_USE_GRAD_PAL; 1907 } else { 1908 color = MPlayerTColors[c_idx]; 1909 style = TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW; 1910 } 1911 1912 /* 1913 ** Initialize our message 1914 */ 1915 txt[0] = 0; 1916 1917 /* 1918 ** If the house is non-human, generate the message 1919 */ 1920 if (!ptr->IsHuman) { 1921 sprintf(txt,"%s", Text_String(TXT_COMPUTER)); 1922 } else { 1923 1924 /* 1925 ** For a human house: 1926 ** - Compute the multiplayer ID for this house 1927 ** - find the name for this player 1928 */ 1929 id = Build_MPlayerID (c_idx,ptr->ActLike); 1930 for (i = 0; i < MPlayerCount; i++) { 1931 if (id == MPlayerID[i]) { 1932 sprintf(txt,"%s",MPlayerNames[i]); 1933 break; 1934 } 1935 } 1936 } 1937 1938 /* 1939 ** Print the player name, and the # of kills 1940 */ 1941 if (strlen(txt)) { 1942 if (strlen(txt) > 9) { 1943 txt[9] = '.'; 1944 txt[10] = '\0'; 1945 } 1946 Fancy_Text_Print (txt, RadX + RadOffX, y, color, BLACK, style); 1947 1948 kills = 0; 1949 for (h = HOUSE_FIRST; h < HOUSE_COUNT; h++) { 1950 kills += ptr->UnitsKilled[h]; 1951 kills += ptr->BuildingsKilled[h]; 1952 } 1953 sprintf(txt, "%2d", kills); 1954 Fancy_Text_Print (txt, RadX + RadOffX + RadIWidth - 2, y, 1955 color, BLACK, style | TPF_RIGHT); 1956 1957 y += 6*factor+1; 1958 1959 } 1960 } 1961 }