/* This file is part of Warzone 2100. Copyright (C) 1999-2004 Eidos Interactive Copyright (C) 2005-2007 Warzone Resurrection Project Warzone 2100 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Warzone 2100 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Warzone 2100; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Display.c * * Display routines. * */ #include "lib/framework/frame.h" #include "display.h" #include "map.h" #include "disp2d.h" #include "loop.h" #include "atmos.h" // temporary only for here #include "csnap.h" /* Includes direct access to render library */ #include "lib/ivis_common/piedef.h" #include "lib/ivis_common/piestate.h" // FIXME Direct iVis implementation include! #include "lib/ivis_common/rendmode.h" //#include "ivisheap.h"//make a call for this #include "lib/ivis_common/tex.h"//make a call for this #include "component.h" #include "display3d.h" #include "resource.h" #include "hci.h" #include "text.h" #include "edit3d.h" #include "geometry.h" #include "lib/gamelib/gtime.h" #include "lib/sound/audio.h" #include "audio_id.h" #include "radar.h" #include "miscimd.h" #include "lighting.h" #include "lib/framework/fractions.h" #include "console.h" #include "order.h" #include "wrappers.h" #include "power.h" #include "map.h" #include "keymap.h" #include "intimage.h" #include "mechanics.h" #include "ingameop.h" #include "oprint.h" #include "warcam.h" #include "keybind.h" #include "keymap.h" #include "projectile.h" #include "message.h" #include "effects.h" #include "lib/script/script.h" #include "scripttabs.h" #include "scriptextern.h" #include "scriptcb.h" #include "target.h" #include "drive.h" #include "cmddroid.h" #include "gateway.h" #include "selection.h" #include "transporter.h" #include "intorder.h" #include "lib/ivis_common/pieclip.h" // ffs am #include "multiplay.h" #define SHAKE_TIME (1500) #define TD_SCROLL_DIV 2 //#define TEST_EFFECT // Kick off an effect when left mouse button pressed. #define pi 3.141592657 struct _dragBox dragBox3D,wallDrag; // control whether the scroll is limited to visible tiles //#define VISIBLE_SCROLL #define POSSIBLE_SELECTIONS 13 #define POSSIBLE_TARGETS 23 UDWORD arnMPointers[POSSIBLE_TARGETS][POSSIBLE_SELECTIONS] = { // empty terrain tile {IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE, IDC_BOMB,IDC_NOTPOSSIBLE,IDC_MOVE,IDC_MOVE}, // resource tile {IDC_BUILD,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE,IDC_MOVE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE}, // impassible tile {IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE}, // river tile {IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_BRIDGE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE}, // trench tile {IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_BRIDGE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE}, // damaged friendly structure {IDC_FIX,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_MOVE,IDC_MOVE, IDC_GUARD,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_DEST,IDC_MOVE}, // undamaged friendly structure {IDC_NOTPOSSIBLE,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_MOVE,IDC_MOVE, IDC_GUARD,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_DEST,IDC_MOVE}, // partially built friendly structure {IDC_BUILD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_MOVE,IDC_MOVE, IDC_GUARD,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_DEST,IDC_MOVE}, // friendly repair facility {IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR, IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR, IDC_NOTPOSSIBLE,IDC_DEST,IDC_SEEKREPAIR}, // friendly damagedrepair facility {IDC_FIX,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR, IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR,IDC_SEEKREPAIR, IDC_NOTPOSSIBLE,IDC_DEST,IDC_SEEKREPAIR}, // enemy structure {IDC_MOVE,IDC_ATTACK,IDC_ATTACK,IDC_ATTACK,IDC_LOCKON,IDC_JAM,IDC_ATTACK, IDC_ATTACK,IDC_ATTACK,IDC_BOMB,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_MOVE}, // transport {IDC_EMBARK,IDC_EMBARK,IDC_EMBARK,IDC_EMBARK,IDC_EMBARK,IDC_EMBARK,IDC_EMBARK, IDC_EMBARK,IDC_EMBARK,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_EMBARK}, // friendly droid {IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT, IDC_SELECT,IDC_SELECT,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_SELECT}, // damaged friendly droid {IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT, IDC_PICKUP,IDC_SELECT,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_FIX}, // enemy droid {IDC_MOVE,IDC_ATTACK,IDC_ATTACK,IDC_ATTACK,IDC_LOCKON,IDC_JAM,IDC_MOVE, IDC_MOVE,IDC_ATTACK,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_MOVE}, // command droid {IDC_SELECT,IDC_ATTACH,IDC_ATTACH,IDC_ATTACH,IDC_ATTACH,IDC_ATTACH,IDC_ATTACH, IDC_ATTACH,IDC_SELECT,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_ATTACH}, // artefact {IDC_PICKUP,IDC_PICKUP,IDC_PICKUP,IDC_PICKUP,IDC_PICKUP,IDC_PICKUP,IDC_PICKUP, IDC_PICKUP,IDC_PICKUP,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_PICKUP,IDC_PICKUP}, // feature that can be damaged ie attacked {IDC_NOTPOSSIBLE,IDC_ATTACK,IDC_ATTACK,IDC_ATTACK,IDC_LOCKON,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_ATTACK,IDC_ATTACK,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE}, // sensor droid {IDC_SELECT,IDC_GUARD,IDC_LOCKON,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT, IDC_SELECT,IDC_SELECT,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_FIX}, // wrecked building feature {IDC_DEST,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE, IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE}, // construction droid {IDC_SELECT,IDC_GUARD,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT,IDC_SELECT, IDC_SELECT,IDC_SELECT,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_FIX}, // sensor structure {IDC_BUILD,IDC_GUARD,IDC_LOCKON,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_MOVE,IDC_MOVE, IDC_GUARD,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_DEST,IDC_MOVE}, // damaged sensor structure. {IDC_FIX,IDC_GUARD,IDC_LOCKON,IDC_GUARD,IDC_GUARD,IDC_GUARD,IDC_MOVE,IDC_MOVE, IDC_GUARD,IDC_NOTPOSSIBLE,IDC_NOTPOSSIBLE,IDC_DEST,IDC_MOVE}, }; UWORD MPointerImageIDs[]={ IMAGE_CURSOR_DEST, // IDC_DEST IMAGE_CURSOR_DEFAULT, // IDC_SIGHT IMAGE_CURSOR_DEFAULT, // IDC_TARGET IMAGE_CURSOR_DEFAULT, // IDC_LARROW IMAGE_CURSOR_DEFAULT, // IDC_RARROW IMAGE_CURSOR_DEFAULT, // IDC_DARROW IMAGE_CURSOR_DEFAULT, // IDC_UARROW IMAGE_CURSOR_DEFAULT, // IDC_DEFAULT IMAGE_CURSOR_DEFAULT, // IDC_EDGEOFMAP IMAGE_CURSOR_ATTACH, // IDC_ATTACH IMAGE_CURSOR_ATTACK, // IDC_ATTACK IMAGE_CURSOR_DEFAULT, // IDC_BOMB IMAGE_CURSOR_BRIDGE, // IDC_BRIDGE IMAGE_CURSOR_BUILD, // IDC_BUILD IMAGE_CURSOR_EMBARK, // IDC_EMBARK IMAGE_CURSOR_FIX, // IDC_FIX IMAGE_CURSOR_GUARD, // IDC_GUARD IMAGE_CURSOR_ECM, // IDC_JAM IMAGE_CURSOR_LOCKON, // IDC_LOCKON IMAGE_CURSOR_DEFAULT, // IDC_MENU IMAGE_CURSOR_MOVE, // IDC_MOVE IMAGE_CURSOR_NOTPOS, // IDC_NOTPOSSIBLE IMAGE_CURSOR_PICKUP, // IDC_PICKUP IMAGE_CURSOR_REPAIR, // IDC_SEEKREPAIR IMAGE_CURSOR_SELECT, // IDC_SELECT }; UDWORD scroll_speed_accel=800; // acceleration on scrolling. Game Option. BOOL buildingDamaged(STRUCTURE *psStructure); static BOOL repairDroidSelected(UDWORD player); //static DROID *constructorDroidSelected(UDWORD player); static BOOL vtolDroidSelected(UDWORD player); static BOOL anyDroidSelected(UDWORD player); static BOOL cyborgDroidSelected(UDWORD player); //static BOOL ctrlShiftDown(void); static BOOL bInvertMouse = TRUE; static BOOL bDrawShadows = TRUE; //BOOL widgetsOn=TRUE; //FALSE; //BOOL forceWidgetsOn = FALSE; SELECTION_TYPE establishSelection(UDWORD selectedPlayer); void dealWithLMB( void ); void dealWithLMBDClick( void ); void dealWithRMB( void ); BOOL mouseInBox(SDWORD x0, SDWORD y0, SDWORD x1, SDWORD y1); BASE_OBJECT *mouseTarget( void ); OBJECT_POSITION * checkMouseLoc(void); /* Mouse x and y - no point checking them more than once per frame */ SDWORD mX = OFF_SCREEN, mY = OFF_SCREEN; BOOL bInstantRadarJump = FALSE; BOOL rotActive = FALSE; SDWORD desiredPitch = 340; UDWORD currentFrame; static UDWORD StartOfLastFrame; SDWORD rotX; SDWORD rotY; UDWORD worldAngle; UDWORD rotInitial; UDWORD rotInitialUp; UDWORD xMoved,yMoved; //DROID *psSelected3D = NULL; BOOL gameStats = FALSE; STRUCTURE *psBuilding; BOOL mouseAtEdge = FALSE; /* Will be used to do diagonal scroll */ BOOL mouseAtBottom,mouseAtTop,mouseAtRight,mouseAtLeft; SDWORD direction = 0; BOOL edgeOfMap = FALSE; UDWORD scrollRefTime; float scrollAccel; float scrollSpeedLeftRight; //use two directions and add them because its simple float scrollStepLeftRight; float scrollSpeedUpDown; float scrollStepUpDown; BOOL noDrag3D; BOOL mouseOverRadar = FALSE; BOOL mouseOverConsole = FALSE; BOOL ignoreOrder = FALSE; BOOL ignoreRMBC = TRUE; /* Hackety hack hack hack */ /* Has the big blue droid been added to the world? */ BOOL bigBlueInWorld = FALSE; BOOL missionComplete = FALSE; UWORD RadarZoomLevel = 0; int gammaValue = 20; DROID *psSelectedVtol; DROID *psDominantSelected; BOOL CheckScrollLimits(void); /* Hackety hack hack hack */ SDWORD screenShakeTable[100] = { -2,-2,-3,-4,-3,-3,-5,-4,-4,-4, -4,-5,-5,-5,-5,-7,-5,-6,-8,-6, -7,-8,-6,-4,-8,-7,-7,-7,-6,-5, -6,-5,-2,-5,-6,-3,-5,-3,-2,-4, -5,-3,-2,-0,1,2,2,1,0,0, 0,1,1,3,2,1,0,2,3,4, 4,2,6,4,5,3,7,7,3,6, 4,7,9,10,9,8,6,4,7,5, 5,4,6,2,4,5,3,3,2,1, 1,0,-1,-1,-2,-1,1,0,1,0 }; PALETTEENTRY gamePalette[255]; // another game palette (yawn) #define TESTLEVEL_ID (0) #define METAKEY_DOWN (keyDown(KEY_LALT) OR keyDown(KEY_RALT) OR keyDown(KEY_LSHIFT) OR keyDown(KEY_RSHIFT) ) static BOOL bScreenShakeActive = FALSE; static UDWORD screenShakeStarted; static UDWORD screenShakeLength; //used to determine is a weapon droid is assigned to a sensor tower or sensor droid static BOOL bSensorAssigned; //used to determine if the player has selected a Las Sat structure static BOOL bLasSatStruct; // Local prototypes static MOUSE_TARGET itemUnderMouse(BASE_OBJECT **ppObjUnderCursor); BOOL bShakingPermitted = TRUE; void setRadarJump(BOOL val) { bInstantRadarJump = val; } BOOL getRadarJumpStatus( void ) { return(bInstantRadarJump); } BOOL getShakeStatus( void ) { return(bShakingPermitted); } BOOL getInvertMouseStatus( void ) { return(bInvertMouse); } void setInvertMouseStatus( BOOL val ) { bInvertMouse = val; } BOOL getDrawShadows( void ) { return(bDrawShadows); } void setDrawShadows( BOOL val ) { bDrawShadows = val; } void setShakeStatus( BOOL val ) { bShakingPermitted = val; } void shakeStart(void) { if(bShakingPermitted) { if(!bScreenShakeActive) { bScreenShakeActive = TRUE; screenShakeStarted = gameTime; screenShakeLength = SHAKE_TIME;//1500; } } } void shakeStop(void) { bScreenShakeActive = FALSE; player.r.z = 0; } void shakeUpdate(void) { UDWORD screenShakePercentage; /* Check if we're shaking the screen or not */ if(bScreenShakeActive) { // screenShakePercentage = (((gameTime-screenShakeStarted)<<8) / screenShakeLength) * 100; screenShakePercentage = PERCENT(gameTime2-screenShakeStarted,screenShakeLength); // screenShakePercentage = screenShakePercentage >> 8; if(screenShakePercentage<100) { player.r.z = 0 + DEG(screenShakeTable[screenShakePercentage]); } if(gameTime>(screenShakeStarted+screenShakeLength)) { bScreenShakeActive = FALSE; player.r.z = 0; } } else { if(!getWarCamStatus()) { player.r.z = 0; } } } BOOL LoadLevelGraphics(UBYTE LevelNumber) { (void)LevelNumber; return TRUE; } /* Initialise the display system */ BOOL dispInitialise(void) { /* UBYTE *pFileData, *pImageData; UDWORD fileSize, width,height; UDWORD i;*/ /* Build the transparency table that's used for the rgb filter rectangle plotter in ivis */ iV_SetTransFilter(TRANS_BLUE,0); // set the table. iV_SetTransFilter(TRANS_BRITE,1); // set the other table. iV_SetTransFilter(TINT_BLUE,2); // set the other other table. iV_SetTransFilter(TINT_DEEPBLUE,3); // set the other other table. // screenSetTextColour(0xff,0xff,0xff); noDrag3D = FALSE; RadarZoomLevel = 0; return TRUE; } /* Tidy up after a mode change */ BOOL dispModeChange() { return TRUE; } BOOL bRadarDragging = FALSE; void ProcessRadarInput(void) { SDWORD PosX,PosY; int x = mouseX(); int y = mouseY(); UDWORD temp1,temp2; /* Only allow jump-to-area-of-map if radar is on-screen */ mouseOverRadar = FALSE; if(radarOnScreen AND getHQExists(selectedPlayer)) { if(CoordInRadar(x,y)) { mouseOverRadar = TRUE; if (mousePressed(MOUSE_LMB)) { if(driveModeActive()) { driveProcessRadarInput(x,y); } else { /* If we're tracking a droid, then cancel that */ // if(getWarCamStatus() == TRUE) // { // camToggleStatus(); // } CalcRadarPosition(x,y,(UDWORD *)&PosX,(UDWORD *)&PosY); if(mouseOverRadar) { // requestRadarTrack(PosX*TILE_UNITS,PosY*TILE_UNITS); // MARKER // Send all droids to that location orderSelectedLoc(selectedPlayer, (PosX*TILE_UNITS)+TILE_UNITS/2, (PosY*TILE_UNITS)+TILE_UNITS/2); } // setViewPos(PosX,PosY); CheckScrollLimits(); audio_PlayTrack( ID_SOUND_MESSAGEEND ); } } if(mouseDrag(MOUSE_RMB,&temp1,&temp2) AND !rotActive) { CalcRadarPosition(x,y,(UDWORD*)&PosX,(UDWORD*)&PosY); setViewPos(PosX,PosY,TRUE); bRadarDragging = TRUE; if(keyDown(KEY_LCTRL) OR keyDown(KEY_RCTRL)) { player.r.y = 0; } } else if (mousePressed(MOUSE_RMB)) { #ifdef RADAR_POSITION_AT_ZOOM CalcRadarPosition(x,y,&PosX,&PosY); setViewPos(PosX,PosY,TRUE); CheckScrollLimits(); #endif /* RadarZoomLevel++; if(RadarZoomLevel > MAX_RADARZOOM) { RadarZoomLevel = 0; } SetRadarZoom(RadarZoomLevel); audio_PlayTrack( ID_SOUND_BUTTON_CLICK_5 ); */ CalcRadarPosition(x,y,(UDWORD*)&PosX,(UDWORD*)&PosY); if(bInstantRadarJump) { /* Go instantly */ setViewPos(PosX,PosY,TRUE); } else { /* Pan to it */ requestRadarTrack(PosX*TILE_UNITS,PosY*TILE_UNITS); } } } } } // reset the input state void resetInput(void) { rotActive = FALSE; dragBox3D.status = DRAG_INACTIVE; wallDrag.status = DRAG_INACTIVE; } /* Process the user input. This just processes the key input and jumping around the radar*/ //BOOL processInput(void) void processInput(void) { UDWORD x,y; BOOL mOverR = FALSE; int WheelZoomIterator; x = mouseX(); y = mouseY(); if(radarOnScreen AND getHQExists(selectedPlayer)) { if(CoordInRadar(x,y)) { mOverR = TRUE; } } StartOfLastFrame=currentFrame; currentFrame=frameGetFrameNumber(); psBuilding = NULL; mouseAtEdge = FALSE; ResetMouseBoundryConditions(); edgeOfMap = FALSE; ignoreRMBC = FALSE; mX = mouseX(); mY = mouseY(); /* Process all of our key mappings */ // keyProcessMappings(); // done later - see below. // if(mousePressed(MOUSE_LMB) AND getRadarTrackingStatus() AND !mOverR) if(mousePressed(MOUSE_LMB) AND !mOverR AND getRadarTrackingStatus()) { camToggleStatus(); } // if(mousePressed(MOUSE_RMB) AND getRadarTrackingStatus() AND !mOverR) if(mousePressed(MOUSE_LMB) AND !mOverR AND getRadarTrackingStatus()) { camToggleStatus(); } if(mousePressed(MOUSE_WUP)) { /* CTRL+WheelUp makes game speed up */ if(keyDown(KEY_LCTRL)) { kf_SpeedUp(); } else { /* Decide if radar or world zoom in */ if(mOverR) { kf_RadarZoomIn(); } else { for (WheelZoomIterator=0;WheelZoomIterator<10;WheelZoomIterator++) kf_ZoomIn(); } } } if(mousePressed(MOUSE_WDN)) { /* CTRL+WheelDown makes game slow down */ if(keyDown(KEY_LCTRL)) { kf_SlowDown(); } else { /* Decide if radar or world zoom out */ if(mOverR) { kf_RadarZoomOut(); } else { for (WheelZoomIterator=0;WheelZoomIterator<10;WheelZoomIterator++) kf_ZoomOut(); } } } if(intMode != INT_DESIGN) { if(bAllowOtherKeyPresses) { /* Run all standard mappings */ keyProcessMappings(FALSE); } else { kf_SendTextMessage(); // process multiplayer chat message. } } else { /* Only process the function keys */ keyProcessMappings(TRUE); } /* Allow the user to clear the console if need be */ mouseOverConsole = mouseOverConsoleBox(); if(mouseOverConsole AND mousePressed(MOUSE_LMB)) { setConsolePermanence(FALSE,TRUE); } /* if(keyDown(KEY_F1)) { theSun.x+=64; initLighting(); } if(keyDown(KEY_F2)) { theSun.x-=64; initLighting(); } if(keyDown(KEY_F3)) { theSun.y+=64; initLighting(); } if(keyDown(KEY_F4)) { theSun.y-=64; initLighting(); } if(keyDown(KEY_F5)) { theSun.z+=64; initLighting(); } if(keyDown(KEY_F6)) { theSun.z-=64; initLighting(); } */ } ////don't want to do any of these whilst in the Intelligence Screen //void processMouseClickInput(void) //{ // UDWORD dragX,dragY,i; // SELECTION_TYPE selection; // MOUSE_TARGET item; // BOOL OverRadar = mouseOverRadar; // // /* Have we tried to click on something - only used to signal to display3d.c */ // if (mouseDown(MOUSE_LMB)) // { // selectAttempt = TRUE; // } // // if(mouseDown(MOUSE_RMB) AND rotActive) // { // if(abs(mX-rotX)>8) // { // if(mXtype == REF_WALL || (((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_DEFENSE)) { wallDrag.x2 = mouseTileX; wallDrag.y2 = mouseTileY; wallDrag.status = DRAG_RELEASED; } } } /* Only clear if shift isn't down - this is for the drag selection box for units*/ if(!keyDown(KEY_LCTRL) AND !keyDown(KEY_RCTRL) AND !keyDown(KEY_LSHIFT) AND !keyDown(KEY_RSHIFT) AND wallDrag.status==DRAG_INACTIVE) { clearSelection(); } dragBox3D.status = DRAG_RELEASED; dragBox3D.x2 = mX; dragBox3D.y2 = mY; } else { dragBox3D.status = DRAG_INACTIVE; wallDrag.status = DRAG_INACTIVE; } } } void CheckStartWallDrag(void) { if(driveModeActive()) { return; } if(mousePressed(MOUSE_LMB)) { /* Store away the details if we're building */ // You can start dragging walls from invalid locations so check for // BUILD3D_POS or BUILD3D_VALID, used tojust check for BUILD3D_VALID. if( (buildState == BUILD3D_POS) || (buildState == BUILD3D_VALID) ) { //if(((STRUCTURE_STATS *)sBuildDetails.psStats)->type >= REF_WALLH AND // ((STRUCTURE_STATS *)sBuildDetails.psStats)->type <= REF_WALLV) if( (((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_WALL) || (((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_DEFENSE) ) { wallDrag.x1 = wallDrag.x2 = mouseTileX; wallDrag.y1 = wallDrag.y2 = mouseTileY; wallDrag.status = DRAG_PLACING; debug( LOG_NEVER, "Start Wall Drag\n" ); } } else if (intBuildSelectMode())//if we were in build select mode { //uhoh no place to build here audio_PlayTrack(ID_SOUND_BUILD_FAIL); } } } //BOOL CheckFinishedWallDrag(void) - misleading name - sorry Paul! //this function is called when a location has been chosen to place a structure or a DP BOOL CheckFinishedFindPosition(void) { BOOL OverRadar = OverRadarAndNotDragging(); // if(driveModeActive()) { // return FALSE; // } // if (buildState == BUILD3D_VALID) // { /* Do not let the player position buildings 'under' the radar */ if(mouseReleased(MOUSE_LMB) AND !OverRadar) { if (buildState == BUILD3D_VALID) { if ( ((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_WALL || (((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_DEFENSE)) { int dx,dy; wallDrag.x2 = mouseTileX; wallDrag.y2 = mouseTileY; dx = abs(mouseTileX - wallDrag.x1); dy = abs(mouseTileY - wallDrag.y1); if(dx >= dy) { wallDrag.y2 = wallDrag.y1; } else if(dx < dy) { wallDrag.x2 = wallDrag.x1; } wallDrag.status = DRAG_RELEASED; } debug( LOG_NEVER, "BUILD3D_FINISHED\n" ); buildState = BUILD3D_FINISHED; return TRUE; } else { //uhoh no place to build here // audio_PlayTrack(ID_SOUND_BUILD_FAIL); } } // } return FALSE; } void HandleDrag(void) { BOOL OverRadar = mouseOverRadar; UDWORD dragX,dragY; if(driveModeActive()) { if(mouseDown(MOUSE_LMB)) { if(buildState == BUILD3D_VALID) { if( ((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_WALL || (((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_DEFENSE)) { int dx,dy; wallDrag.x2 = mouseTileX; wallDrag.y2 = mouseTileY; dx = abs(mouseTileX - wallDrag.x1); dy = abs(mouseTileY - wallDrag.y1); if(dx >= dy) { wallDrag.y2 = wallDrag.y1; } else if(dx < dy) { wallDrag.x2 = wallDrag.x1; } wallDrag.status = DRAG_DRAGGING; } } } return; } if(mouseDrag(MOUSE_LMB,&dragX,&dragY) AND !OverRadar AND !mouseDown(MOUSE_RMB)) { dragBox3D.x1 = dragX; dragBox3D.x2 = mX; dragBox3D.y1 = dragY; dragBox3D.y2 = mY; if(buildState == BUILD3D_VALID) { if( ((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_WALL || (((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_DEFENSE)) { int dx,dy; wallDrag.x2 = mouseTileX; wallDrag.y2 = mouseTileY; dx = abs(mouseTileX - wallDrag.x1); dy = abs(mouseTileY - wallDrag.y1); if(dx >= dy) { wallDrag.y2 = wallDrag.y1; } else if(dx < dy) { wallDrag.x2 = wallDrag.x1; } wallDrag.status = DRAG_DRAGGING; } } dragBox3D.status = DRAG_DRAGGING; } } static UDWORD CurrentItemUnderMouse; UDWORD getTargetType(void) { return CurrentItemUnderMouse; } //don't want to do any of these whilst in the Intelligence Screen void processMouseClickInput(void) { UDWORD i; SELECTION_TYPE selection; MOUSE_TARGET item=MT_NOTARGET; BOOL OverRadar = OverRadarAndNotDragging(); // These four functions were embedded in this function but I moved them out for readability. In the // absense of any comments I had a guess as to there use and named them accordingly PD 28/05/98. //ignoreOrder = CheckFinishedWallDrag(); - this name is misleading since called for all Structures AB ignoreOrder = CheckFinishedFindPosition(); CheckStartWallDrag(); HandleDrag(); CheckFinishedDrag(); // if ((mouseReleased(MOUSE_LMB) /*|| keyPressed(KEY_RCTRL)*/) AND !OverRadar AND dragBox3D.status!=DRAG_RELEASED AND !ignoreOrder AND !mouseOverConsole AND !bDisplayMultiJoiningStatus) { dealWithLMB(); } if (mouseDClicked(MOUSE_LMB)) { dealWithLMBDClick(); } if(driveModeActive() && !driveTacticalActive()) { driveProcessAquireButton(); } else { if(!driveModeActive()) { if(mouseReleased(MOUSE_RMB) AND !rotActive AND !ignoreRMBC) { // clearSelection(); // psSelected3D = NULL; dragBox3D.status = DRAG_INACTIVE; // Pretty sure we wan't set walldrag status here aswell. wallDrag.status = DRAG_INACTIVE; // printf("Cancel Wall Drag\n"); bRadarDragging = FALSE; dealWithRMB(); // Why? if(getWarCamStatus()) { camToggleStatus(); } } if(!mouseDrag(MOUSE_RMB,(UDWORD*)&rotX,(UDWORD*)&rotY) AND bRadarDragging) { bRadarDragging = FALSE; } /* Right mouse click kills a building placement */ if( mouseReleased(MOUSE_RMB) AND (buildState == BUILD3D_POS OR buildState == BUILD3D_VALID)) { /* Stop the placement */ kill3DBuilding(); bRadarDragging = FALSE; } if(mouseDrag(MOUSE_RMB,(UDWORD *)&rotX,(UDWORD *)&rotY) AND !rotActive AND !bRadarDragging) { rotInitial = player.r.y; rotInitialUp = player.r.x; xMoved = 0; yMoved = 0; rotActive = TRUE; } } } selection = establishSelection(selectedPlayer); ASSERT( selection<=POSSIBLE_SELECTIONS,"Weirdy selection!" ); if((selection != SC_INVALID) && !gamePaused()) { BASE_OBJECT *ObjUnderMouse; item = itemUnderMouse(&ObjUnderMouse); ASSERT( itemplayer) && aiCheckAlliances(selectedPlayer,ObjUnderMouse->player)) { item = MT_NOTARGET; } if(item != MT_NOTARGET) { // exceptions to the lookup table. if (ctrlShiftDown() && (ObjUnderMouse != NULL) && (ObjUnderMouse->player == selectedPlayer) && (ObjUnderMouse->type == OBJ_DROID)) { item = MT_OWNDROID; } else if ((keyDown(KEY_LALT) || keyDown(KEY_RALT)) && (ObjUnderMouse != NULL) && (ObjUnderMouse->player == selectedPlayer)) { if (selection == SC_DROID_REPAIR) { item = MT_OWNDROIDDAM; } else { // attacking own unit item = MT_ENEMYDROID; } } //in multiPlayer can only put cyborgs onto a Transporter else if (bMultiPlayer AND item == MT_TRANDROID) { if (!cyborgDroidSelected(selectedPlayer)) { item = MT_BLOCKING; } } else if (selection==SC_DROID_CONSTRUCT) { // We don't allow the build cursor under certain circumstances .... // can't build if res extractors arent available. if (item == MT_RESOURCE) { for(i=0;(itype == OBJ_STRUCTURE))// check if struct { if(buildingDamaged((STRUCTURE *)ObjUnderMouse)) { item = MT_OWNSTRDAM; // replace guard/sense with usual icons. }else{ item = MT_OWNSTROK; } } } } else if (item == MT_SENSOR AND selection == SC_DROID_INDIRECT AND (keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT))) { selection = SC_DROID_SENSOR; } // check the type of sensor for indirect weapons else if ((item == MT_SENSOR OR item == MT_SENSORSTRUCT OR item == MT_SENSORSTRUCTDAM) AND selection == SC_DROID_INDIRECT ) { if (!droidSensorDroidWeapon(ObjUnderMouse, psDominantSelected)) { item = MT_BLOCKING; } } //check for VTOL droids being assigned to a sensor droid/structure else if ( (item == MT_SENSOR OR item == MT_SENSORSTRUCT OR item == MT_SENSORSTRUCTDAM) AND selection == SC_DROID_DIRECT AND vtolDroidSelected((UBYTE)selectedPlayer)) { // NB. psSelectedVtol was set by vtolDroidSelected - yes I know its horrible, but it // only smells as much as the rest of display.c so I don't feel so bad if (droidSensorDroidWeapon(ObjUnderMouse, psSelectedVtol)) { selection = SC_DROID_INDIRECT; } else { item = MT_BLOCKING; } } //vtols cannot pick up artifacts else if (item == MT_ARTIFACT AND selection == SC_DROID_DIRECT AND vtolDroidSelected((UBYTE)selectedPlayer)) { item = MT_BLOCKING; } //VTOL's can't be moved to empty terrain /* else if (vtolDroidSelected((UBYTE)selectedPlayer) AND item == MT_TERRAIN AND selection == SC_DROID_DIRECT) { item = MT_BLOCKING; }*/ //in multiPlayer Transporters can be moved around the terrain - and repaired if (bMultiPlayer AND selection == SC_DROID_TRANSPORTER AND ( item == MT_TERRAIN OR item == MT_REPAIR)) { //change to standard droid selection selection = SC_DROID_INDIRECT; } else if (item == MT_TERRAIN AND TERRAIN_TYPE(mapTile(mouseTileX,mouseTileY)) == TER_CLIFFFACE) { item = MT_BLOCKING; } frameSetCursorFromRes((WORD)arnMPointers[item][selection]); } } else { //exceptions, exceptions...AB 10/06/99 if (bMultiPlayer AND bLasSatStruct) { BASE_OBJECT *ObjUnderMouse; item = itemUnderMouse(&ObjUnderMouse); ASSERT( item BOUNDARY_X/2) { bRetardScroll = TRUE; } } /* Scroll right */ if (keyDown(KEY_RIGHTARROW) OR (mX>(SDWORD)(DISP_WIDTH-BOUNDARY_X))) { mouseAtRight = TRUE; mouseAtEdge = TRUE; if(!keyDown(KEY_RIGHTARROW) AND mX<(SDWORD)(DISP_WIDTH-(BOUNDARY_X/2))) { bRetardScroll = TRUE; } } /* Scroll up */ if (keyDown(KEY_UPARROW) OR (mYBOUNDARY_Y/2) { bRetardScroll = TRUE; } } /* Scroll down */ if (keyDown(KEY_DOWNARROW) OR (mY>(SDWORD)(DISP_HEIGHT-BOUNDARY_Y))) { mouseAtTop = TRUE; mouseAtEdge = TRUE; if(!keyDown(KEY_DOWNARROW) AND mY<(SDWORD)(DISP_HEIGHT-(BOUNDARY_Y/2))) { bRetardScroll = TRUE; } } } else { /* Scroll left */ if ((mX BOUNDARY_X/2) { bRetardScroll = TRUE; } } /* Scroll right */ if ((mX>(SDWORD)(DISP_WIDTH-BOUNDARY_X))) { mouseAtRight = TRUE; mouseAtEdge = TRUE; if(!keyDown(KEY_RIGHTARROW) AND mX<(SDWORD)(DISP_WIDTH-(BOUNDARY_X/2))) { bRetardScroll = TRUE; } } /* Scroll up */ if ((mYBOUNDARY_Y/2) { bRetardScroll = TRUE; } } /* Scroll down */ if ((mY>(SDWORD)(DISP_HEIGHT-BOUNDARY_Y))) { mouseAtTop = TRUE; mouseAtEdge = TRUE; if(!keyDown(KEY_DOWNARROW) AND mY<(SDWORD)(DISP_HEIGHT-(BOUNDARY_Y/2))) { bRetardScroll = TRUE; } } } /* Time to update scroll - change to should be time */ //scrollAccel = (float)SCROLL_SPEED_ACCEL * (float)(gameTime - scrollRefTime)/(float)GAME_TICKS_PER_SEC; timeDiff = SDL_GetTicks() - scrollRefTime; //WHEN its fixed - you can uncomment it! //if(bRetardScroll AND FALSE) //temp until fixed //{ // timeDiff/=2; //} /* Store reference time */ scrollRefTime = SDL_GetTicks(); if (timeDiff > GTIME_MAXFRAME) { timeDiff = GTIME_MAXFRAME; } scrollAccel = (float)scroll_speed_accel * (float)(timeDiff) / (float)GAME_TICKS_PER_SEC; if(mouseAtLeft) { if(scrollSpeedLeftRight>0) scrollSpeedLeftRight = (float)0.0; scrollSpeedLeftRight -= scrollAccel; if(scrollSpeedLeftRight < -(float)MAX_SCROLL_SPEED) { scrollSpeedLeftRight = -(float)MAX_SCROLL_SPEED; } } else if(mouseAtRight) { if(scrollSpeedLeftRight<0) scrollSpeedLeftRight = (float)0.0; scrollSpeedLeftRight += scrollAccel; if(scrollSpeedLeftRight > (float)MAX_SCROLL_SPEED) { scrollSpeedLeftRight = (float)MAX_SCROLL_SPEED; } } else // not at left or right so retard the scroll { if(scrollSpeedLeftRight > 2*scrollAccel) { scrollSpeedLeftRight -= 2*scrollAccel; } else if(scrollSpeedLeftRight < -2*scrollAccel) { scrollSpeedLeftRight += 2*scrollAccel; } else { scrollSpeedLeftRight = (float)0.0; } } if(mouseAtBottom)//its at the top?? { if(scrollSpeedUpDown<0) scrollSpeedUpDown = (float)0.0; scrollSpeedUpDown += scrollAccel; if(scrollSpeedUpDown > (float)MAX_SCROLL_SPEED) { scrollSpeedUpDown = (float)MAX_SCROLL_SPEED; } } else if(mouseAtTop)//its at the bottom?? { if(scrollSpeedUpDown>0) scrollSpeedUpDown = (float)0.0; scrollSpeedUpDown -= scrollAccel; if(scrollSpeedUpDown < -(float)MAX_SCROLL_SPEED) { scrollSpeedUpDown = -(float)MAX_SCROLL_SPEED; } } else // not at top or bottom so retard the scroll { if(scrollSpeedUpDown > scrollAccel) { scrollSpeedUpDown -= 2*scrollAccel; } else if(scrollSpeedUpDown < -scrollAccel) { scrollSpeedUpDown += 2*scrollAccel; } else { scrollSpeedUpDown = (float)0.0; } } // scrool speeds updated in proportion to frame time calculate how far to step in each direction //scrollStepLeftRight = scrollSpeedLeftRight * (float)(gameTime - scrollRefTime)/(float)GAME_TICKS_PER_SEC; scrollStepLeftRight = scrollSpeedLeftRight * (float)(timeDiff) / (float)GAME_TICKS_PER_SEC; //scrollStepUpDown = scrollSpeedUpDown * (float)(gameTime - scrollRefTime)/(float)GAME_TICKS_PER_SEC; scrollStepUpDown = scrollSpeedUpDown * (float)(timeDiff) / (float)GAME_TICKS_PER_SEC; /* Get angle vector to scroll along */ worldAngle = (UDWORD) ((UDWORD)player.r.y/DEG_1)%360; direction = (360) - worldAngle; /* Convert to radians */ radians = (((float)pi/180)*(direction)); cosine = (float)cos(radians); sine = (float)sin(radians); /* Get x component of movement */ xDif = ROUND(cosine * scrollStepLeftRight + sine * scrollStepUpDown); /* Get y component of movement */ yDif = ROUND(sine * scrollStepLeftRight - cosine * scrollStepUpDown); /* Adjust player's position by these components */ #ifdef VISIBLE_SCROLL newx = player.p.x + xDif; newy = player.p.z + yDif; if (mapTile((((VISIBLE_XTILES/2)<> TILE_SHIFT, (((VISIBLE_YTILES/2)<> TILE_SHIFT)->tileVisBits & (1 << selectedPlayer)) { player.p.x = newx; player.p.z = newy; } else { if (player.p.x >> TILE_SHIFT != newx >> TILE_SHIFT) { scrollSpeedLeftRight = 0; } else { player.p.x = newx; } if (player.p.z >> TILE_SHIFT != newy >> TILE_SHIFT) { scrollSpeedUpDown = 0; } else { player.p.z = newy; } } #else player.p.x += xDif; player.p.z += yDif; #endif edgeOfMap = CheckScrollLimits(); mouseAtLeft = FALSE; mouseAtRight = FALSE; mouseAtTop = FALSE; mouseAtBottom = FALSE; //end of scroll code return; } // Check a coordinate is within the scroll limits, uses object type coords ie UWORDs. // Returns TRUE if edge hit. // BOOL CheckObjInScrollLimits(UWORD *xPos,UWORD *zPos) { SDWORD xp = ((SWORD)(*xPos)) - VISIBLE_XTILES*TILE_UNITS/2; SDWORD zp = ((SWORD)(*zPos)) - VISIBLE_YTILES*TILE_UNITS/2; BOOL ret = CheckInScrollLimits(&xp,&zp); *xPos = (UWORD)(xp + VISIBLE_XTILES*TILE_UNITS/2); *zPos = (UWORD)(zp + VISIBLE_YTILES*TILE_UNITS/2); return ret; } // Check a coordinate is within the scroll limits, SDWORD version. // Returns TRUE if edge hit. // BOOL CheckInScrollLimits(SDWORD *xPos,SDWORD *zPos) { BOOL EdgeHit = FALSE; SDWORD minX,minY,maxX,maxY; //always view that little bit more than the scroll limits... /*minX = scrollMinX * TILE_UNITS; minY = scrollMinY * TILE_UNITS; maxX = (((scrollMaxX-1) - visibleXTiles) * TILE_UNITS); maxY = (((scrollMaxY-1) - visibleYTiles) * TILE_UNITS); if(scrollMinX==0) { minX = ((0 - visibleXTiles/2) * TILE_UNITS); } if((UDWORD)scrollMaxX == mapWidth) { maxX = ((mapWidth-1-(visibleXTiles/2)) * TILE_UNITS); } if(scrollMinY==0) { minY = ((0 - visibleYTiles/2) * TILE_UNITS); } if((UDWORD)scrollMaxY == mapHeight) { maxY = ((mapHeight-1-(visibleYTiles/2)) * TILE_UNITS); }*/ minX = (scrollMinX - (visibleXTiles/2)) * TILE_UNITS; maxX = ((scrollMaxX - 1) - (visibleXTiles/2)) * TILE_UNITS; minY = (scrollMinY - (visibleYTiles/2)) * TILE_UNITS; maxY = ((scrollMaxY - 1) - (visibleYTiles/2)) * TILE_UNITS; //scroll is limited to what can be seen for current campaign if (*xPos < minX) { *xPos = minX; EdgeHit = TRUE; } else if (*xPos >= maxX) { *xPos = maxX; EdgeHit = TRUE; } if (*zPos < minY) { *zPos = minY; EdgeHit = TRUE; } else if (*zPos >= maxY) { *zPos = maxY; EdgeHit = TRUE; } return EdgeHit; } // Check the view is within the scroll limits, // Returns TRUE if edge hit. // BOOL CheckScrollLimits(void) { // need to be carefull here, player position uses SDWORD's on PC and SWORDS on PSX. SDWORD xp = player.p.x; SDWORD zp = player.p.z; BOOL ret = CheckInScrollLimits(&xp,&zp); player.p.x = xp; player.p.z = zp; return ret; } /* Do the 3D display */ void displayWorld(void) { iVector pos; shakeUpdate(); if(mouseDown(MOUSE_RMB) AND rotActive) { if( (abs(mX-rotX)>8) OR xMoved>8) { xMoved += (abs(mX-rotX)); if(mX8) OR yMoved>8) { yMoved += (abs(mY-rotY)); if(bInvertMouse) { if(mYDEG(360 + MAX_PLAYER_X_ANGLE)) { player.r.x = DEG(360 + MAX_PLAYER_X_ANGLE); } if(player.r.x < DEG(360 + MIN_PLAYER_X_ANGLE)) { player.r.x = DEG(360 + MIN_PLAYER_X_ANGLE); } setDesiredPitch(player.r.x/DEG_1); } } if(mouseReleased(MOUSE_RMB) AND rotActive) { rotActive = FALSE; xMoved = yMoved = 0; ignoreRMBC = TRUE; pos.x = player.r.x; pos.y = player.r.y; pos.z = player.r.z; camInformOfRotation(&pos); bRadarDragging = FALSE; } draw3DScene(); } BOOL mouseInBox(SDWORD x0, SDWORD y0, SDWORD x1, SDWORD y1) { if(mX>x0 AND mXy0 AND mY=(SDWORD)StartOfLastFrame) { return TRUE; } return FALSE; } /* Returns what the mouse was clicked on. Only called if there was a mouse pressed message on MOUSE_LMB. We aren't concerned here with setting selection flags - just what it actually was */ BASE_OBJECT *mouseTarget( void ) { UDWORD i; BASE_OBJECT *psReturn; DROID *psDroid; UDWORD dispX,dispY,dispR; if( (mouseTileX < 0) OR (mouseTileY < 0) OR (mouseTileX > (SDWORD)(mapWidth-1)) OR (mouseTileY > (SDWORD)(mapHeight-1)) ) { return(NULL); } /* We haven't found anything yet */ psReturn = NULL; /* First have a look through the droid lists */ for (i=0; ipsNext) { dispX = psDroid->sDisplay.screenX; dispY = psDroid->sDisplay.screenY; dispR = psDroid->sDisplay.screenR; /* Only check droids that're on screen */ // Has the droid been drawn since the start of the last frame if (psDroid->visible[selectedPlayer] AND DrawnInLastFrame(psDroid->sDisplay.frameNumber)==TRUE) // if(psDroid->sDisplay.frameNumber+1 == currentFrame) { if (mouseInBox(dispX-dispR, dispY-dispR, dispX+dispR, dispY+dispR)) { /* We HAVE clicked on droid! */ psReturn = (BASE_OBJECT *) psDroid; /* There's no point in checking other object types */ return(psReturn); } } } } // end of checking for droids /* Not a droid, so maybe a structure or feature? If still NULL after this then nothing */ psReturn = getTileOccupier(mouseTileX, mouseTileY); /* Send the result back - if it's null then we clicked on an area of terrain */ return(psReturn); } UWORD lastangle; // debugging only // Dummy structure stats used for positioning delivery points. static STRUCTURE_STATS ReposStats; static BOOL ReposValid = FALSE; static BOOL BVReposValid = FALSE; static FLAG_POSITION *ReposFlag; void StartTacticalScroll(BOOL driveActive) { } void StartTacticalScrollObj(BOOL driveActive,BASE_OBJECT *psObj) { } void CancelTacticalScroll(void) { } void displayInitVars(void) { ReposValid = FALSE; BVReposValid = FALSE; } // Start repositioning a delivery point. // void StartDeliveryPosition(OBJECT_POSITION *psLocation,BOOL driveActive) { FLAG_POSITION *psFlagPos; /* clear the selection */ // clearSelection(); //clear the Deliv Point if one for (psFlagPos = apsFlagPosLists[selectedPlayer]; psFlagPos; psFlagPos = psFlagPos->psNext) { psFlagPos->selected = FALSE; } //set this object position to be highlighted psLocation->selected = TRUE; if(bInTutorial) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DELIVPOINTMOVED); } // Setup dummy structure stats for positioning a delivery point. ReposValid = FALSE; ReposFlag = NULL; ReposStats.baseWidth = 1; ReposStats.baseBreadth = 1; ReposStats.ref = 0;//REF_STRUCTURE_START; //set up the buildSite variable for drawing buildSite.xTL = (UWORD)psLocation->screenX; buildSite.yTL = (UWORD)psLocation->screenY; buildSite.xBR = (UWORD)(buildSite.xTL-1); buildSite.yBR = (UWORD)(buildSite.yTL-1); init3DBuilding((BASE_STATS *)&ReposStats,FinishDeliveryPosition,psLocation); } // Finished repositioning a delivery point. // void FinishDeliveryPosition(UDWORD xPos,UDWORD yPos,void *UserData) { //This deals with adding waypoints and moving the primary processDeliveryPoint(((FLAG_POSITION*)UserData)->player, xPos<selected = FALSE; CancelDeliveryRepos(); } // Cancel repositioning of the delivery point without moveing it. // /*void CancelDeliveryRepos(void) { if((ReposValid) && (ReposFlag!=NULL)) { if(driveModeActive()) { DROID *Driven = driveGetDriven(); if(Driven != NULL) { Driven->selected = TRUE; camAllignWithTarget(Driven); } driveEnableControl(); } ReposValid = FALSE; ReposFlag = NULL; buildState = BUILD3D_NONE; } }*/ // Get the current screen position of the delivery point. // /*BOOL GetDeliveryRepos(UDWORD *xPos,UDWORD *yPos) { if((ReposValid) && (ReposFlag!=NULL)) { *xPos = scoord_PC2PSXx(ReposFlag->screenX); *yPos = scoord_PC2PSXy(ReposFlag->screenY); return TRUE; } return FALSE; }*/ // Is there a valid delivery point repositioning going on. // BOOL DeliveryReposValid(void) { if(driveModeActive()) { return ReposValid && (ReposFlag !=NULL); } else { return BVReposValid; } } // Cancel repositioning of the delivery point without moving it. // void CancelDeliveryRepos(void) { if((ReposValid) && (ReposFlag!=NULL)) { if(driveModeActive()) { DROID *Driven = driveGetDriven(); if(Driven != NULL) { // Driven->selected = TRUE; SelectDroid(Driven); camAllignWithTarget((BASE_OBJECT *)Driven); } driveEnableControl(); } ReposValid = FALSE; ReposFlag = NULL; } BVReposValid = FALSE; } // check whether a clicked on droid is in a command group or assigned to a sensor BOOL droidHasLeader(DROID *psDroid) { BASE_OBJECT *psLeader; if (psDroid->droidType == DROID_COMMAND || psDroid->droidType == DROID_SENSOR) { return FALSE; } psLeader = NULL; if ((psDroid->psGroup != NULL) && (psDroid->psGroup->type == GT_COMMAND)) { psLeader = (BASE_OBJECT *)psDroid->psGroup->psCommander; } else { //psLeader can be either a droid or a structure orderStateObj(psDroid, DORDER_FIRESUPPORT, &psLeader); } if (psLeader != NULL) { // psLeader->selected = TRUE; if (psLeader->type == OBJ_DROID) { SelectDroid((DROID *)psLeader); } assignSensorTarget(psLeader); return TRUE; } return FALSE; } // deal with selecting a droid void dealWithDroidSelect(DROID *psDroid, BOOL bDragBox) { DROID *psD; BOOL bGotGroup; SDWORD groupNumber = 0; /* Toggle selection on and off - allows you drag around a big area of droids and then exclude certain individuals */ if(!bDragBox && psDroid->selected==TRUE) { // psDroid->selected = FALSE; DeSelectDroid(psDroid); // if(OrderUp) { /* Fix this ALEX M!!! */ } } else if (keyDown(KEY_LCTRL) || keyDown(KEY_RCTRL) || keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT) || !droidHasLeader(psDroid)) { for(psD = apsDroidLists[selectedPlayer],bGotGroup = FALSE; psD AND !bGotGroup; psD = psD->psNext) { if(psD->selected AND (psD->group!=UBYTE_MAX)) { bGotGroup = TRUE; groupNumber = psD->group; } } // psDroid->selected = TRUE; if(keyDown(KEY_LALT) OR keyDown(KEY_RALT) ) { /* We only want to select weapon units if ALT is down on a drag */ if(psDroid->asWeaps[0].nStat > 0) { SelectDroid(psDroid); } } else { SelectDroid(psDroid); } /* if(psDroid->droidType == DROID_COMMAND) { cmdSelectSubDroids(psDroid); }*/ // intObjectSelected((BASE_OBJECT *)psDroid); if (bInTutorial) { psCBSelectedDroid = psDroid; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DROID_SELECTED); psCBSelectedDroid = NULL; } } } void FeedbackOrderGiven(void) { static UDWORD LastFrame = 0; UDWORD ThisFrame = frameGetFrameNumber(); // Ensure only played once per game cycle. if(ThisFrame != LastFrame) { audio_PlayTrack(ID_SOUND_SELECT); LastFrame = ThisFrame; } } void FeedbackClickedOn(void) { FeedbackOrderGiven(); } // check whether the queue order keys are pressed BOOL ctrlShiftDown(void) { return keyDown(KEY_LCTRL) || keyDown(KEY_RCTRL) || keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT); } void BeepMessage(UDWORD StringID) { static UDWORD LastFrame = 0; UDWORD ThisFrame = frameGetFrameNumber(); // Ensure only done once per game cycle. if(ThisFrame != LastFrame) { addConsoleMessage(strresGetString(psStringRes,StringID),DEFAULT_JUSTIFY); audio_PlayTrack( ID_SOUND_BUILD_FAIL ); LastFrame = ThisFrame; } } void AddDerrickBurningMessage(void) { addConsoleMessage(strresGetString(psStringRes,STR_GAM_DERRICK_BURNING),DEFAULT_JUSTIFY); audio_PlayTrack( ID_SOUND_BUILD_FAIL ); } void dealWithLMB( void ) { BASE_OBJECT *psClickedOn; DROID *psDroid,*psCurr,*psNearestUnit; //BOOL bWeapDroidSelected; STRUCTURE *psStructure,*psSLoop; FEATURE *psFeature; OBJECT_POSITION *psLocation; UDWORD i; SELECTION_TYPE selection; /* Don't process if in game options are on screen */ if(InGameOpUp == TRUE OR widgGetFromID(psWScreen,INTINGAMEOP)) { return; } /* What have we clicked on? */ if(driveModeActive() && !driveTacticalActive()) { psClickedOn = targetGetCurrent(); //if(psClickedOn != NULL) { //printf("%p\n",psClickedOn); //} } else { psClickedOn = mouseTarget(); } //DBPRINTF(("dealWithLMB() : %p\n",psClickedOn)); /* If not NULL, then it's a droid or a structure */ if(psClickedOn != NULL) { selection = establishSelection(selectedPlayer); /* We've got a droid or a structure */ if(psClickedOn->type == OBJ_DROID) { /* We clicked on droid */ psDroid = (DROID *) psClickedOn; if(psDroid->player == selectedPlayer) { if (ctrlShiftDown()) { // select/deselect etc. the droid dealWithDroidSelect(psDroid, FALSE); } else if (psDroid->droidType == DROID_TRANSPORTER) { if (selection == SC_INVALID) { //in multiPlayer mode we RMB to get the interface up if (bMultiPlayer) { psDroid->selected = TRUE; } else { intResetScreen(FALSE); if(!getWidgetsStatus()) { setWidgetsStatus(TRUE); } addTransporterInterface(psDroid, FALSE); } } else { orderSelectedObj(selectedPlayer, psClickedOn); FeedbackOrderGiven(); } } /* else if (psDroid->droidType == DROID_SENSOR && selection == SC_DROID_INDIRECT && !(keyDown(KEY_LCTRL) || keyDown(KEY_RCTRL))) // !(keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT))) { orderSelectedObj(selectedPlayer, psClickedOn); } */ // Like to get this working on PSX. else if (keyDown(KEY_LALT) || keyDown(KEY_RALT)) { // try to attack your own unit for(psCurr=apsDroidLists[selectedPlayer]; psCurr; psCurr = psCurr->psNext) { if ((psCurr != psDroid) && // can't attack yourself (psCurr->selected)) { if ((psCurr->droidType == DROID_WEAPON) || (psCurr->droidType == DROID_CYBORG) || (psCurr->droidType == DROID_CYBORG_SUPER) || (psCurr->droidType == DROID_COMMAND)) { orderDroidObj(psCurr, DORDER_ATTACK, psClickedOn); FeedbackOrderGiven(); } else if (psCurr->droidType == DROID_SENSOR) { orderDroidObj(psCurr, DORDER_OBSERVE, psClickedOn); FeedbackOrderGiven(); } else if (psCurr->droidType == DROID_REPAIR OR psCurr->droidType == DROID_CYBORG_REPAIR) { orderDroidObj(psCurr, DORDER_DROIDREPAIR, psClickedOn); FeedbackOrderGiven(); } } } } // Clicked on a commander? Will link to it. else if (psDroid->droidType == DROID_COMMAND && selection != SC_INVALID && selection != SC_DROID_COMMAND && selection != SC_DROID_CONSTRUCT && !( keyDown(KEY_LCTRL) || keyDown(KEY_RCTRL) ) AND !( keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT)) ) { turnOffMultiMsg(TRUE); orderSelectedObj(selectedPlayer, psClickedOn); FeedbackOrderGiven(); clearSelection(); assignSensorTarget((BASE_OBJECT *)psDroid); dealWithDroidSelect(psDroid, FALSE); turnOffMultiMsg(FALSE); } // Clicked on a construction unit? Will guard it. else if ( ((psDroid->droidType == DROID_CONSTRUCT) OR (psDroid->droidType == DROID_SENSOR) ) && selection == SC_DROID_DIRECT) { orderSelectedObj(selectedPlayer, psClickedOn); FeedbackOrderGiven(); } // Clicked on a damaged unit? Will repair it. else if (droidIsDamaged(psDroid) AND repairDroidSelected(selectedPlayer)) { assignDestTarget(); orderSelectedObjAdd(selectedPlayer, psClickedOn, ctrlShiftDown()); FeedbackOrderGiven(); } // Just plain clicked on? else { // Display unit info. /* We've clicked on one of our own droids */ if(godMode) { CONPRINTF(ConsoleString, (ConsoleString, "%s - Damage %d%% - Serial ID %d - Kills %d order %d action %d, %s", droidGetName(psDroid), 100 - PERCENT(psDroid->body, psDroid->originalBody),psDroid->id,psDroid->numKills, psDroid->order, psDroid->action, getDroidLevelName(psDroid))); FeedbackClickedOn(); } else { if(!psDroid->selected) { CONPRINTF(ConsoleString, (ConsoleString, strresGetString(psStringRes,STR_GAM_DROIDSTATE), /* "%s - Damage %d%% - Kills %d, %s",*/ droidGetName(psDroid), 100 - PERCENT(psDroid->body, psDroid->originalBody),psDroid->numKills, getDroidLevelName(psDroid))); FeedbackClickedOn(); } } if(psDroid->droidType == DROID_SENSOR) { //bWeapDroidSelected = FALSE; bSensorAssigned = FALSE; for(psCurr = apsDroidLists[selectedPlayer]; psCurr; psCurr = psCurr->psNext) { //must be indirect weapon droid or VTOL weapon droid if( (psCurr->droidType == DROID_WEAPON) AND (psCurr->selected) //AND (psCurr->numWeaps) AND AND (psCurr->asWeaps[0].nStat > 0) AND ((!proj_Direct(asWeaponStats + psCurr->asWeaps[0].nStat)) OR vtolDroid(psCurr)) AND droidSensorDroidWeapon((BASE_OBJECT *)psDroid, psCurr)) { //bWeapDroidSelected = TRUE; bSensorAssigned = TRUE; orderDroidObj(psCurr, DORDER_FIRESUPPORT, (BASE_OBJECT *)psDroid); FeedbackOrderGiven(); } } //if(bWeapDroidSelected) if (bSensorAssigned) { //assignSensorTarget(psDroid); assignSensorTarget((BASE_OBJECT *)psDroid); } } //cannot have LasSat struct and Droid selected bLasSatStruct = FALSE; // select/deselect etc. the droid if(!ctrlShiftDown()) { clearSelection(); dealWithDroidSelect(psDroid, FALSE); } } } else { /* We've clicked on somebody else's droid */ // addConsoleMessage("Clicked on another player's droid",DEFAULT_JUSTIFY); orderSelectedObjAdd(selectedPlayer,psClickedOn, ctrlShiftDown()); //lasSat structure can select a target - in multiPlayer only if (bMultiPlayer AND bLasSatStruct) { if(aiCheckAlliances(selectedPlayer,psClickedOn->player) == FALSE) { orderStructureObj(selectedPlayer,psClickedOn); } } FeedbackOrderGiven(); driveDisableTactical(); } } // end if its a droid else if (psClickedOn->type == OBJ_STRUCTURE) { // clearSelection(); // Clear droid selection. psStructure = (STRUCTURE *) psClickedOn; if(psStructure->player == selectedPlayer) { /* We've clicked on our own building */ //print some info at the top of the screen for the specific structure printStructureInfo(psStructure); /* Got to be built. Also, you can't 'select' derricks */ if( (psStructure->status==SS_BUILT) AND (psStructure->pStructureType->type != REF_RESOURCE_EXTRACTOR) ) { //if selected object is an upgradeable structure then don't //inform the interface (if not fully upgraded) and a any droid //is selected /* if (!(((psStructure->pStructureType->type == REF_FACTORY AND ((FACTORY *)psStructure->pFunctionality)->capacity < NUM_FACTORY_MODULES) OR (psStructure->pStructureType->type == REF_RESEARCH AND ((RESEARCH_FACILITY *)psStructure->pFunctionality)->capacity < NUM_RESEARCH_MODULES) OR (psStructure->pStructureType->type == REF_VTOL_FACTORY AND ((FACTORY *)psStructure->pFunctionality)->capacity < NUM_FACTORY_MODULES)) AND //constructorDroidSelected(selectedPlayer))) anyDroidSelected(selectedPlayer)))*/ // now only display interface if nothing selected if (!anyDroidSelected(selectedPlayer)) { intObjectSelected((BASE_OBJECT *)psStructure); FeedbackClickedOn(); } // We don't actually wan't to select structures, just inform the interface we've clicked on it, // might wan't to do this on PC as well as it fixes the problem with the interface locking multiple // buttons in the object window. if (selection == SC_INVALID) { /* Clear old building selection(s) - should only be one */ for(psSLoop = apsStructLists[selectedPlayer]; psSLoop; psSLoop = psSLoop->psNext) { psSLoop->selected = FALSE; } /* Establish new one */ psStructure->selected = TRUE; } //determine if LasSat structure has been selected bLasSatStruct = FALSE; if (lasSatStructSelected(psStructure)) { bLasSatStruct = TRUE; } } else if ( (psStructure->status==SS_BUILT) AND (psStructure->pStructureType->type == REF_RESOURCE_EXTRACTOR) ) { if (selection == SC_INVALID) { /* Clear old building selection(s) - should only be one */ for(psSLoop = apsStructLists[selectedPlayer]; psSLoop; psSLoop = psSLoop->psNext) { psSLoop->selected = FALSE; } /* Establish new one */ psStructure->selected = TRUE; } } if (keyDown(KEY_LALT) || keyDown(KEY_RALT)) { // Like to implement this on PSX as well. // try to attack your own structure for(psCurr=apsDroidLists[selectedPlayer]; psCurr; psCurr = psCurr->psNext) { if (psCurr->selected) { //if ((psCurr->droidType == DROID_WEAPON) || (psCurr->droidType == DROID_CYBORG) || if ((psCurr->droidType == DROID_WEAPON) || cyborgDroid(psCurr) || (psCurr->droidType == DROID_COMMAND)) { orderDroidObj(psCurr, DORDER_ATTACK, psClickedOn); FeedbackOrderGiven(); } else if (psCurr->droidType == DROID_SENSOR) { orderDroidObj(psCurr, DORDER_OBSERVE, psClickedOn); FeedbackOrderGiven(); } } } } else { bSensorAssigned = FALSE; orderSelectedObjAdd(selectedPlayer,psClickedOn, ctrlShiftDown()); FeedbackOrderGiven(); if (bSensorAssigned) { clearSelection(); assignSensorTarget((BASE_OBJECT *)psStructure); } } } else { /* We've clicked on somebody else's building */ // addConsoleMessage("Clicked on another player's building",DEFAULT_JUSTIFY); orderSelectedObjAdd(selectedPlayer,psClickedOn, ctrlShiftDown()); //lasSat structure can select a target - in multiPlayer only if (bMultiPlayer AND bLasSatStruct) { orderStructureObj(selectedPlayer,psClickedOn); } FeedbackOrderGiven(); } driveDisableTactical(); } // end if its a structure else if (psClickedOn->type == OBJ_FEATURE) { //some features are targetable psFeature = (FEATURE *) psClickedOn; //check for constructor droid trying to remove wrecked building first if (psFeature->psStats->subType == FEAT_BUILD_WRECK AND (constructorDroidSelected(selectedPlayer) != NULL) ) { orderSelectedObjAdd(selectedPlayer,psClickedOn, ctrlShiftDown()); FeedbackOrderGiven(); } //go on to check for if (psFeature->psStats->damageable) { orderSelectedObjAdd(selectedPlayer,psClickedOn, ctrlShiftDown()); //lasSat structure can select a target - in multiPlayer only if (bMultiPlayer AND bLasSatStruct) { orderStructureObj(selectedPlayer,psClickedOn); } FeedbackOrderGiven(); } //clicking an oil field should start a build.. //if(psFeature->subType == FEAT_OIL_RESOURCE) if(psFeature->psStats->subType == FEAT_OIL_RESOURCE) { // find any construction droids. and order them to build an oil resource. // first find the derrick. for(i=0;(ipsNext) { //if((droidType(psDroid) == DROID_CONSTRUCT) && (psDroid->selected)) if ((droidType(psDroid) == DROID_CONSTRUCT OR droidType(psDroid) == DROID_CYBORG_CONSTRUCT) && (psDroid->selected)) { if(!fireOnLocation(psFeature->x,psFeature->y)) { if (ctrlShiftDown()) { orderDroidStatsLocAdd(psDroid, DORDER_BUILD, (BASE_STATS*) &asStructureStats[i], psFeature->x, psFeature->y); } else { orderDroidStatsLoc(psDroid, DORDER_BUILD, (BASE_STATS*) &asStructureStats[i], psFeature->x, psFeature->y); } addConsoleMessage(strresGetString(psStringRes,STR_GAM_DERRICK),DEFAULT_JUSTIFY); // "Construction vehicle ordered to build a Derrick.",DEFAULT_JUSTIFY); FeedbackOrderGiven(); } else // can't build because it's burning { AddDerrickBurningMessage(); break; } } } } } else { switch(psFeature->psStats->subType) { case FEAT_GEN_ARTE: case FEAT_OIL_DRUM: psNearestUnit = getNearestDroid(mouseTileX*TILE_UNITS+TILE_UNITS/2, mouseTileY*TILE_UNITS+TILE_UNITS/2,TRUE); /* If so then find the nearest unit! */ if(psNearestUnit) // bloody well should be!!! { // orderDroidLoc(psNearestUnit,DORDER_MOVE, mouseTileX*TILE_UNITS+TILE_UNITS/2,mouseTileY*TILE_UNITS+TILE_UNITS/2); orderDroidObj(psNearestUnit, DORDER_RECOVER, psClickedOn); FeedbackOrderGiven(); } else { // orderSelectedLoc(selectedPlayer, psFeature->x,psFeature->y); // recover it. orderSelectedObj(selectedPlayer, psClickedOn); FeedbackOrderGiven(); } break; /* case FEAT_OIL_DRUM: psNearestUnit = getNearestDroid(mouseTileX*TILE_UNITS+TILE_UNITS/2, mouseTileY*TILE_UNITS+TILE_UNITS/2,TRUE); // If so then find the nearest unit! if(psNearestUnit) // bloody well should be!!! { orderDroidLoc(psNearestUnit,DORDER_MOVE, mouseTileX*TILE_UNITS+TILE_UNITS/2,mouseTileY*TILE_UNITS+TILE_UNITS/2); } else { orderSelectedLoc(selectedPlayer, psFeature->x,psFeature->y); // recover it. } break;*/ case FEAT_BOULDER: //addConsoleMessage("Clicked on a Boulder",DEFAULT_JUSTIFY); break; case FEAT_BUILD_WRECK: // addConsoleMessage("Clicked on a Wrecked Building",DEFAULT_JUSTIFY); break; case FEAT_HOVER: // addConsoleMessage("Clicked on a Hover",DEFAULT_JUSTIFY); break; case FEAT_OIL_RESOURCE: case FEAT_VEHICLE: default: // addConsoleMessage("Clicked on an Obstacle",DEFAULT_JUSTIFY); break; } } driveDisableTactical(); } else { ASSERT( FALSE,"Weirdy selection from LMB?!" ); } } else if( !driveModeActive() || driveTacticalActive()) { /*Check for a Delivery Point or a Proximity Message*/ psLocation = NULL; psLocation = checkMouseLoc(); if (psLocation && !driveModeActive() AND !selNumSelected(selectedPlayer)) { switch (psLocation->type) { case POS_DELIVERY: if(psLocation->player == selectedPlayer) { StartDeliveryPosition(psLocation,FALSE); /* We've clicked on one of our own DP */ // addConsoleMessage("Clicked on your delivery point",DEFAULT_JUSTIFY); // /* clear the selection */ // clearSelection(); // // //set this object position to be highlighted // psLocation->selected = TRUE; } else { /* We've clicked on somebody else's DP - remove this sometime?*/ // addConsoleMessage("Clicked on another player's delivery point",DEFAULT_JUSTIFY); } break; /*case POS_PROX: if(psLocation->player == selectedPlayer) { displayProximityMessage((PROXIMITY_DISPLAY *)psLocation); } break;*/ default: ASSERT( FALSE, "Unknown type from checkMouseLoc" ); } } else { #ifdef TEST_EFFECT // Code to test an effect when left mouse button pressed iVector Pos; Pos.x = mouseTileX*TILE_UNITS+TILE_UNITS/2; Pos.z = mouseTileY*TILE_UNITS+TILE_UNITS/2; Pos.y = 100; // addEffect(&Pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_SPECIFIED,TRUE,resGetData("IMD","fxlswave.pie")); // DBPRINTF(("Added test effect %p : %d,%d,%d\n",resGetData("IMD","fxlswave.pie"),Pos.x,Pos.y,Pos.z); // addEffect(&Pos,EFFECT_GRAVITON,GRAVITON_TYPE_EMITTING_DR,TRUE,debrisImds[rand()%MAX_DEBRIS]); addEffect(&Pos,EFFECT_EXPLOSION,EXPLOSION_TYPE_MEDIUM,FALSE,NULL,0); #endif /* We've just clicked on an area of terrain. A 'send to' operation */ /* We need to establish the world coordinates */ /* if(keyDown(KEY_LALT) || keyDown(KEY_RALT)) // shift clicked a destination, add a waypoint. { orderSelectedWaypoint(selectedPlayer,mouseTileX*TILE_UNITS+TILE_UNITS/2,mouseTileY*TILE_UNITS+TILE_UNITS/2); }*/ // now changed to use the multiple order stuff if(ctrlShiftDown()) // shift clicked a destination, add an order { orderSelectedLocAdd(selectedPlayer, mouseTileX*TILE_UNITS+TILE_UNITS/2, mouseTileY*TILE_UNITS+TILE_UNITS/2, TRUE); } else // clicked on a destination. { /* Otherwise send them all */ orderSelectedLoc(selectedPlayer, mouseTileX*TILE_UNITS+TILE_UNITS/2,mouseTileY*TILE_UNITS+TILE_UNITS/2); //DBPRINTF(("orderSelectedLoc(%d,%d,%d)\n",selectedPlayer, mouseTileX*TILE_UNITS+TILE_UNITS/2,mouseTileY*TILE_UNITS+TILE_UNITS/2)); if(getNumDroidsSelected()) { assignDestTarget(); audio_PlayTrack( ID_SOUND_SELECT ); } if(godMode && (mouseTileX >= 0) && (mouseTileX < (SDWORD)mapWidth) && (mouseTileY >= 0) && (mouseTileY < (SDWORD)mapHeight)) { DBCONPRINTF(ConsoleString,(ConsoleString,"Tile Coords : %d,%d (%d,%d) Zone :%d", mouseTileX,mouseTileY, mouseTileX*TILE_UNITS + TILE_UNITS/2, mouseTileY*TILE_UNITS + TILE_UNITS/2, gwGetZone(mouseTileX, mouseTileY))); } //addConsoleMessage("Droid ordered to new location",DEFAULT_JUSTIFY); } driveDisableTactical(); } } } BOOL getRotActive( void ) { return(rotActive); } SDWORD getDesiredPitch( void ) { return(desiredPitch); } void setDesiredPitch(SDWORD pitch) { desiredPitch = pitch; } // process LMB double clicks void dealWithLMBDClick(void) { BASE_OBJECT *psClickedOn; DROID *psDroid; /* What have we clicked on? */ psClickedOn = mouseTarget(); /* If not NULL, then it's a droid or a structure */ if(psClickedOn != NULL) { /* We've got a droid or a structure */ if(psClickedOn->type == OBJ_DROID) { /* We clicked on droid */ psDroid = (DROID *) psClickedOn; if(psDroid->player == selectedPlayer) { /* If we've double clicked on a constructor droid, activate build menu */ //if (psDroid->droidType == DROID_CONSTRUCT) if (psDroid->droidType == DROID_CONSTRUCT OR psDroid->droidType == DROID_CYBORG_CONSTRUCT) { intResetScreen(TRUE); intConstructorSelected(psDroid); } else if (psDroid->droidType == DROID_COMMAND) { intResetScreen(TRUE); intCommanderSelected(psDroid); } else { /* Otherwise, activate the droid's group (if any) */ // activateGroup(selectedPlayer,psDroid->group); // Now selects all of smae type on screen selDroidSelection(selectedPlayer,DS_BY_TYPE,DST_ALL_SAME,TRUE); } } } } } /*This checks to see if the mouse was over a delivery point or a proximity message when the mouse button was pressed */ OBJECT_POSITION * checkMouseLoc(void) { OBJECT_POSITION *psReturn; FLAG_POSITION *psPoint; //PROXIMITY_DISPLAY *psProxDisp; UDWORD i; UDWORD dispX,dispY,dispR; // We haven't found anything yet psReturn = NULL; // First have a look through the DeliveryPoint lists for (i=0; ipsNext) { dispX = psPoint->screenX; dispY = psPoint->screenY; dispR = psPoint->screenR; if (DrawnInLastFrame(psPoint->frameNumber)==TRUE) // Only check DP's that are on screen { if (mouseInBox(dispX-dispR, dispY-dispR, dispX+dispR, dispY+dispR)) { // We HAVE clicked on DP! psReturn = (OBJECT_POSITION *)psPoint; //There's no point in checking other object types return(psReturn); } } } // old way, only one point allowed. // // //look throught the list of structures to see if there is a factory // //and therefore a DP // for (psStructure = apsStructLists[i]; psStructure; psStructure = psStructure->psNext) // { // if (psStructure->pStructureType->type == REF_FACTORY) // { // psPoint = ((FACTORY *)psStructure->pFunctionality)->psAssemblyPoint; // dispX = psPoint->screenX; // dispY = psPoint->screenY; // dispR = psPoint->screenR; // // Only check DP's that are on screen // if (DrawnInLastFrame(psPoint->frameNumber)==TRUE) // { // if (mouseInBox(dispX-dispR, dispY-dispR, dispX+dispR, dispY+dispR)) // { // // We HAVE clicked on DP! // psReturn = psPoint; // //There's no point in checking other object types // return(psReturn); // } // } // } // } // end of checking for droids } //now check for Proximity Message /*for(psProxDisp = apsProxDisp[selectedPlayer]; psProxDisp; psProxDisp = psProxDisp->psNext) { dispX = psProxDisp->screenX; dispY = psProxDisp->screenY; dispR = psProxDisp->screenR; // Only check DP's that are on screen if (DrawnInLastFrame(psProxDisp->frameNumber)==TRUE) { if (mouseInBox(dispX-dispR, dispY-dispR, dispX+dispR, dispY+dispR)) { // We HAVE clicked on Proximity Message! psReturn = (OBJECT_POSITION *)psProxDisp; //There's no point in checking other object types return(psReturn); } } }*/ return NULL; } void dealWithRMB( void ) { BASE_OBJECT *psClickedOn; DROID *psDroid; STRUCTURE *psStructure; STRUCTURE *psSLoop; OBJECT_POSITION *psLocation; //printf("dealWithRMB %d\n",mouseOverRadar); if(driveModeActive()) { return; } if(mouseOverRadar) { return; } //RMB will always cancel the selection of the Las Sat struct bLasSatStruct = FALSE; /* What have we clicked on? */ psClickedOn = mouseTarget(); /* If not NULL, then it's a droid or a structure */ if(psClickedOn != NULL) { /* We've got a droid or a structure */ if(psClickedOn->type == OBJ_DROID ) { // if(radarCheckForHQ(selectedPlayer)) // removed by Jim, well kind of, he asked 19 oct 98 { /* We clicked on droid */ psDroid = (DROID *) psClickedOn; if(psDroid->player == selectedPlayer) { //ignore RMB on a Transporter - for now? if ( (psDroid->droidType != DROID_TRANSPORTER) ) { /* We've clicked on one of our own droids */ // addGameMessage("Right clicked on own droid",1000,TRUE); // addConsoleMessage("Right click detected on own droid",DEFAULT_JUSTIFY); if(psDroid->selected==TRUE) { // psDroid->selected = FALSE; // intObjectSelected(NULL); intObjectSelected((BASE_OBJECT *)psDroid); } else { clearSelection(); // psDroid->selected = TRUE; SelectDroid(psDroid); intObjectSelected((BASE_OBJECT *)psDroid); } } //it was only just 'for now'!!! else { if (bMultiPlayer) { intResetScreen(FALSE); if(!getWidgetsStatus()) { setWidgetsStatus(TRUE); } addTransporterInterface(psDroid, FALSE); } } } else { if(bMultiPlayer) { if(isHumanPlayer(psDroid->player) ) { CONPRINTF(ConsoleString, (ConsoleString,"%s",droidGetName(psDroid))); FeedbackClickedOn(); } } } } } // end if its a droid else if (psClickedOn->type == OBJ_STRUCTURE) { psStructure = (STRUCTURE *) psClickedOn; if(psStructure->player == selectedPlayer) { /* We've clicked on our own building */ // addGameMessage("Right clicked on own building",1000,TRUE); // addConsoleMessage("Right clicked on own building",DEFAULT_JUSTIFY); if(psStructure->selected==TRUE) { psStructure->selected = FALSE; intObjectSelected(NULL); } else { // We don't actually wan't to select structures, just inform the interface weve clicked on it, // might wan't to do this on PC as well as it fixes the problem with the interface locking multiple // buttons in the object window. // clearSelection(); /* Clear old building selection(s) - should only be one */ for(psSLoop = apsStructLists[selectedPlayer]; psSLoop; psSLoop = psSLoop->psNext) { psSLoop->selected = FALSE; } // psStructure->selected = TRUE; //if a factory go to deliv point rather than setting up the interface if (StructIsFactory(psStructure)) { setViewPos(((FACTORY *)psStructure->pFunctionality)-> psAssemblyPoint->coords.x >> TILE_SHIFT, ((FACTORY *)psStructure->pFunctionality)->psAssemblyPoint-> coords.y >> TILE_SHIFT,TRUE); //pop up the order interface for the factory - AB 21/04/99 Patch v1.2-> intAddFactoryOrder(psStructure); } else if (psStructure->pStructureType->type == REF_REPAIR_FACILITY) { setViewPos(((REPAIR_FACILITY *)psStructure->pFunctionality)-> psDeliveryPoint->coords.x >> TILE_SHIFT, ((REPAIR_FACILITY *)psStructure->pFunctionality)->psDeliveryPoint-> coords.y >> TILE_SHIFT,TRUE); } else { intObjectSelected((BASE_OBJECT *)psStructure); } } } } // end if its a structure /* And if it's not a feature, then we're in trouble! */ else if (psClickedOn->type != OBJ_FEATURE) { ASSERT( FALSE,"Weirdy selection from RMB?!" ); } } else { /*Check for a Delivery Point*/ psLocation = NULL; psLocation = checkMouseLoc(); if (psLocation) { switch (psLocation->type) { case POS_DELIVERY: if(psLocation->player == selectedPlayer) { //centre the view on the owning Factory psStructure = findDeliveryFactory((FLAG_POSITION *)psLocation); if (psStructure) { setViewPos(psStructure->x >> TILE_SHIFT, psStructure->y >> TILE_SHIFT,TRUE); } } break; default: ASSERT( FALSE, "Unknown type from checkMouseLoc" ); } } else { /* We've just clicked on an area of terrain. A 'send to' operation for Transporter in multiPlay mode*/ /*if (bMultiPlayer) { //there may be more than one Transporter selected for (psDroid = apsDroidLists[selectedPlayer]; psDroid != NULL; psDroid = psDroid->psNext) { if (psDroid->selected) { if (psDroid->droidType == DROID_TRANSPORTER) { orderDroidLoc(psDroid, DORDER_DISEMBARK, mouseTileX * TILE_UNITS + TILE_UNITS/2, mouseTileY * TILE_UNITS + TILE_UNITS/2); } else { //de-select any other units psDroid->selected = FALSE; } } } } else*/ { clearSelection(); intObjectSelected(NULL); } } } } // wrapper functions ... for psx void ResetMouseBoundryConditions(void) { mouseAtLeft = FALSE; mouseAtRight = FALSE; mouseAtTop = FALSE; mouseAtBottom = FALSE; } BOOL IsMouseAtLeft(void) { return mouseAtLeft; } BOOL IsMouseAtRight(void) { return mouseAtRight; } BOOL IsMouseAtTop(void) { return mouseAtTop; } BOOL IsMouseAtBottom(void) { return mouseAtBottom; } /* if there is a valid object under the mouse this routine returns not only the type of the object in the return code, but also a pointer to the BASE_OBJECT) ... well if your going to be "object orientated" you might as well do it right - it sets it to null if we don't find anything */ static MOUSE_TARGET itemUnderMouse( BASE_OBJECT **ppObjectUnderMouse ) { UDWORD i; MOUSE_TARGET retVal; BASE_OBJECT *psNotDroid; DROID *psDroid; UDWORD dispX,dispY,dispR; STRUCTURE *psStructure; *ppObjectUnderMouse=NULL; if(!driveModeActive() || driveTacticalActive()) { if( (mouseTileX < 0) OR (mouseTileY < 0) OR (mouseTileX > (SDWORD)(mapWidth-1)) OR (mouseTileY > (SDWORD)(mapHeight-1)) ) { retVal = MT_BLOCKING; return(retVal); } } //DBPRINTF(("%d %d\n",mouseTileX,mouseTileY); /* We haven't found anything yet */ retVal = MT_NOTARGET; if(driveModeActive() && !driveTacticalActive()) { BASE_OBJECT *psObj = targetGetCurrent(); if(psObj != NULL) { if(psObj->type == OBJ_DROID) { psDroid = (DROID*)psObj; if(psDroid->player == selectedPlayer) { *ppObjectUnderMouse=psObj; // need to check for command droids here as well if (psDroid->droidType == DROID_SENSOR) { // DBPRINTF(("MT_SENSOR\n"); return MT_SENSOR; } else if (psDroid->droidType == DROID_TRANSPORTER) { // DBPRINTF(("MT_TRANDROID\n"); //check the transporter is not full if (calcRemainingCapacity(psDroid)) { return MT_TRANDROID; } else { return MT_BLOCKING; } } else if (psDroid->droidType == DROID_CONSTRUCT OR psDroid->droidType == DROID_CYBORG_CONSTRUCT) { return MT_CONSTRUCT; } else if (psDroid->droidType == DROID_COMMAND) { // DBPRINTF(("MT_COMMAND\n"); return MT_COMMAND; } else { if (droidIsDamaged(psDroid)) { // DBPRINTF(("MT_OWNDROIDDAM\n"); return MT_OWNDROIDDAM; } else { // return MT_OWNDROID; } } } else { // DBPRINTF(("MT_ENEMYDROID\n"); return MT_ENEMYDROID; } } // if( (psObj->type == OBJ_DROID) && (psObj->player != selectedPlayer) ) { // return MT_ENEMYDROID; // } } } else { /* First have a look through the droid lists */ for (i=0; ipsNext) { dispX = psDroid->sDisplay.screenX; dispY = psDroid->sDisplay.screenY; dispR = psDroid->sDisplay.screenR; /* Only check droids that're on screen */ if(psDroid->sDisplay.frameNumber+1 == currentFrame && psDroid->visible[selectedPlayer] ) { if (mouseInBox(dispX-dispR, dispY-dispR, dispX+dispR, dispY+dispR)) { /* We HAVE clicked on droid! */ if(psDroid->player == selectedPlayer) { *ppObjectUnderMouse=(BASE_OBJECT *)psDroid; // need to check for command droids here as well if (psDroid->droidType == DROID_SENSOR) { retVal = MT_SENSOR; } else if (psDroid->droidType == DROID_TRANSPORTER) { //check the transporter is not full if (calcRemainingCapacity(psDroid)) { retVal = MT_TRANDROID; } else { retVal = MT_BLOCKING; } } else if (psDroid->droidType == DROID_CONSTRUCT OR psDroid->droidType == DROID_CYBORG_CONSTRUCT) { return MT_CONSTRUCT; } else if (psDroid->droidType == DROID_COMMAND) { retVal = MT_COMMAND; } else { if (droidIsDamaged(psDroid)) { retVal = MT_OWNDROIDDAM; } else { retVal = MT_OWNDROID; } } } else { *ppObjectUnderMouse=(BASE_OBJECT *)psDroid; //printf("Enemy Droid %d %d %d\n",dispX,dispY,dispR); retVal = MT_ENEMYDROID; } /* There's no point in checking other object types */ return(retVal); } } } } // end of checking for droids } /* Not a droid, so maybe a structure or feature? If still NULL after this then nothing */ if(driveModeActive() && !driveTacticalActive()) { psNotDroid = targetGetCurrent(); } else { psNotDroid = getTileOccupier(mouseTileX, mouseTileY); } if(psNotDroid!=NULL) { *ppObjectUnderMouse=(BASE_OBJECT *)psNotDroid; if(psNotDroid->type == OBJ_FEATURE) { if( (((FEATURE *)psNotDroid)->psStats->subType == FEAT_GEN_ARTE) || (((FEATURE *)psNotDroid)->psStats->subType == FEAT_OIL_DRUM) ) { retVal = MT_ARTIFACT; } else if(((FEATURE *)psNotDroid)->psStats->damageable) //make damageable features return 'target' mouse pointer { //printf("Damagable Feature %d %d\n",mouseTileX,mouseTileY); retVal = MT_DAMFEATURE; } else if(((FEATURE *)psNotDroid)->psStats->subType == FEAT_OIL_RESOURCE) { retVal = MT_RESOURCE; } else if(((FEATURE *)psNotDroid)->psStats->subType == FEAT_BUILD_WRECK) { retVal = MT_WRECKFEATURE; } else { retVal = MT_BLOCKING; } } else if(psNotDroid->type == OBJ_STRUCTURE) { psStructure = (STRUCTURE *)psNotDroid; if(psNotDroid->player == selectedPlayer) { if(psStructure->status == SS_BEING_BUILT) { retVal = MT_OWNSTRINCOMP; } // repair center. else if(psStructure->pStructureType->type == REF_REPAIR_FACILITY) { if(buildingDamaged(psStructure)) { retVal = MT_REPAIRDAM; } else { retVal = MT_REPAIR; } } //sensor tower else if ((psStructure->pStructureType->pSensor) AND (psStructure->pStructureType->pSensor->location == LOC_TURRET)) { if(buildingDamaged(psStructure)) { retVal = MT_SENSORSTRUCT; } else { retVal = MT_SENSORSTRUCTDAM; } } // standard buildings. - check for buildingDamaged BEFORE upgrades else if(buildingDamaged(psStructure)) { retVal = MT_OWNSTRDAM; } // if factory/powgen/research and not upgraded. make build icon available.. else if( ( psStructure->pStructureType->type == REF_FACTORY AND ((FACTORY *)psStructure->pFunctionality)->capacity < NUM_FACTORY_MODULES ) OR ( psStructure->pStructureType->type == REF_VTOL_FACTORY AND ((FACTORY *)psStructure->pFunctionality)->capacity < NUM_FACTORY_MODULES) OR ( psStructure->pStructureType->type == REF_POWER_GEN AND ((POWER_GEN *)psStructure->pFunctionality)->capacity < NUM_POWER_MODULES) OR ( psStructure->pStructureType->type == REF_RESEARCH AND ((RESEARCH_FACILITY *)psStructure->pFunctionality)->capacity < NUM_RESEARCH_MODULES) ) { retVal = MT_OWNSTRINCOMP; } // standard buildings. //else if(buildingDamaged(psStructure)) //{ // retVal = MT_OWNSTRDAM; //} else { /* All the different stages of construction */ retVal = MT_OWNSTROK; } } else { retVal = MT_ENEMYSTR; // enemy structure } } } /* Send the result back - if it's null then we clicked on an area of terrain */ /* make unseen objects just look like terrain. */ if(retVal == MT_NOTARGET || !(psNotDroid->visible[selectedPlayer]) ) { retVal = MT_TERRAIN; } return(retVal); } // Indicates the priority given to any given droid // type in a multiple droid selection, the larger the // number, the lower the priority. The order of entries // corresponds to the order of droid types in the DROID_TYPE // enum in DroidDef.h // //#define NUM_DROID_WEIGHTS (10) #define NUM_DROID_WEIGHTS (13) UBYTE DroidSelectionWeights[NUM_DROID_WEIGHTS] = { 3, //DROID_WEAPON, 1, //DROID_SENSOR, 2, //DROID_ECM, 4, //DROID_CONSTRUCT, 3, //DROID_PERSON, 3, //DROID_CYBORG, 9, //DROID_TRANSPORTER, 0, //DROID_COMMAND, 4, //DROID_REPAIR, 5, //DROID_DEFAULT, 4, //DROID_CYBORG_CONSTRUCT, 4, //DROID_CYBORG_REPAIR, 3, //DROID_CYBORG_SUPER, }; /* Only deals with one type of droid being selected!!!! */ /* We'll have to make it assesss which selection is to be dominant in the case of multiple selections */ SELECTION_TYPE establishSelection(UDWORD selectedPlayer) { DROID *psDroid,*psDominant=NULL; UBYTE CurrWeight; //BOOL gotWeapon = FALSE; //DROID *psWeapDroid = NULL; BOOL atLeastOne; SELECTION_TYPE selectionClass; atLeastOne = FALSE; selectionClass = SC_INVALID; CurrWeight = UBYTE_MAX; for(psDroid = apsDroidLists[selectedPlayer]; psDroid /*AND !atLeastOne*/; psDroid = psDroid->psNext) { // This code dos'nt work, what about the case of a selection of DROID_WEAPON types with a // DROID_CONSTRUCT type grouped with them,claims to handle this but dos'nt. //PD if(psDroid->selected) //PD { //PD atLeastOne = TRUE; //PD if(psDroid->type == DROID_WEAPON) //PD { //PD gotWeapon = TRUE; //PD psWeapDroid = psDroid; //PD } //PD if (psDroid->droidType == DROID_COMMAND || //PD psDominant == NULL) //PD { //PD psDominant = psDroid; //PD } //PD } // This works, uses the DroidSelectionWeights[] table to priorities the different // droid types and find the dominant selection. if(psDroid->selected) { ASSERT( psDroid->droidType < NUM_DROID_WEIGHTS, "establishSelection : droidType exceeds NUM_DROID_WEIGHTS" ); atLeastOne = TRUE; if(DroidSelectionWeights[psDroid->droidType] < CurrWeight) { CurrWeight = DroidSelectionWeights[psDroid->droidType]; psDominant = psDroid; } } } // /* Weapon droids in a selection will override all others */ // if(psWeapDroid) // { // psDominant = psWeapDroid; // } // if(psDominant) { // DBPRINTF(("Dominant selection type == %d\n",psDominant->droidType)); // } if(atLeastOne) { psDominantSelected = psDominant; switch(psDominant->droidType) { case DROID_WEAPON: if (proj_Direct( asWeaponStats + psDominant->asWeaps[0].nStat )) { selectionClass = SC_DROID_DIRECT; } else { selectionClass = SC_DROID_INDIRECT; } break; case DROID_PERSON: selectionClass = SC_DROID_DIRECT; break; case DROID_CYBORG: case DROID_CYBORG_SUPER: selectionClass = SC_DROID_DIRECT; break; case DROID_TRANSPORTER: //can remove this is NEVER going to select the Transporter to move //Never say Never!! cos here we go in multiPlayer!! selectionClass = SC_DROID_TRANSPORTER; break; case DROID_SENSOR: selectionClass = SC_DROID_SENSOR; break; case DROID_ECM: selectionClass = SC_DROID_ECM; break; case DROID_CONSTRUCT: case DROID_CYBORG_CONSTRUCT: /* Re-written to allow demolish order to be added to the queuing system if ((psDominant->psTarget == NULL AND psDominant->psTarStats == (BASE_STATS *) structGetDemolishStat())*/ if (intDemolishSelectMode()) { selectionClass = SC_DROID_DEMOLISH; // demolish mode. } else { selectionClass = SC_DROID_CONSTRUCT; // ordinary mode. } break; case DROID_COMMAND: selectionClass = SC_DROID_COMMAND; break; case DROID_REPAIR: case DROID_CYBORG_REPAIR: selectionClass = SC_DROID_REPAIR; break; default: ASSERT( FALSE,"Weirdy droid type on what you've clicked on!!!" ); break; } } return(selectionClass); } /* Just returns true if the building's present body points aren't 100 percent */ BOOL buildingDamaged(STRUCTURE *psStructure) { //if( PERCENT(psStructure->body , psStructure->baseBodyPoints ) < 100) if( PERCENT(psStructure->body , structureBody(psStructure)) < 100) { return(TRUE); } else { return(FALSE); } } /*Looks through the list of selected players droids to see if one is a repair droid*/ BOOL repairDroidSelected(UDWORD player) { DROID *psCurr; for (psCurr = apsDroidLists[player]; psCurr != NULL; psCurr = psCurr->psNext) { //if (psCurr->selected AND psCurr->droidType == DROID_REPAIR) if (psCurr->selected AND ( psCurr->droidType == DROID_REPAIR OR psCurr->droidType == DROID_CYBORG_REPAIR)) { return TRUE; } } //didn't find one... return FALSE; } /*Looks through the list of selected players droids to see if one is a constructor droid*/ DROID *constructorDroidSelected(UDWORD player) { DROID *psCurr; for (psCurr = apsDroidLists[player]; psCurr != NULL; psCurr = psCurr->psNext) { //if (psCurr->selected AND psCurr->droidType == DROID_CONSTRUCT) if (psCurr->selected AND ( psCurr->droidType == DROID_CONSTRUCT OR psCurr->droidType == DROID_CYBORG_CONSTRUCT)) { return psCurr; } } //didn't find one... return NULL; } /*Looks through the list of selected players droids to see if one is a VTOL droid*/ BOOL vtolDroidSelected(UDWORD player) { DROID *psCurr; for (psCurr = apsDroidLists[player]; psCurr != NULL; psCurr = psCurr->psNext) { if (psCurr->selected AND vtolDroid(psCurr)) { // horrible hack to note one of the selected vtols psSelectedVtol = psCurr; return TRUE; } } //didn't find one... return FALSE; } /*Looks through the list of selected players droids to see if any is selected*/ BOOL anyDroidSelected(UDWORD player) { DROID *psCurr; for (psCurr = apsDroidLists[player]; psCurr != NULL; psCurr = psCurr->psNext) { if (psCurr->selected) { return TRUE; } } //didn't find one... return FALSE; } /*Looks through the list of selected players droids to see if one is a cyborg droid*/ BOOL cyborgDroidSelected(UDWORD player) { DROID *psCurr; for (psCurr = apsDroidLists[player]; psCurr != NULL; psCurr = psCurr->psNext) { if (psCurr->selected AND cyborgDroid(psCurr)) { return TRUE; } } //didn't find one... return FALSE; } /* Clear the selection flag for a player */ void clearSel(void) { DROID *psCurrDroid; STRUCTURE *psStruct; //FEATURE *psFeat; FLAG_POSITION *psFlagPos; for(psCurrDroid = apsDroidLists[selectedPlayer]; psCurrDroid; psCurrDroid = psCurrDroid->psNext) { psCurrDroid->selected = FALSE; } for(psStruct = apsStructLists[selectedPlayer]; psStruct; psStruct = psStruct->psNext) { psStruct->selected = FALSE; } //can a feature ever be selected? /*for(psFeat = apsFeatureLists[0]; psFeat; psFeat = psFeat->psNext) { psFeat->selected = FALSE; }*/ //clear the Deliv Point if one for (psFlagPos = apsFlagPosLists[selectedPlayer]; psFlagPos; psFlagPos = psFlagPos->psNext) { psFlagPos->selected = FALSE; } setSelectedGroup(UBYTE_MAX); setSelectedCommander(UBYTE_MAX); intRefreshScreen(); } // Clear the selection and stop driver mode. // void clearSelection(void) { StopDriverMode(); // Cancel driver mode ( if active ). clearSel(); } //access function for bSensorAssigned variable void setSensorAssigned(void) { bSensorAssigned = TRUE; }