760 lines
17 KiB
C
760 lines
17 KiB
C
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
Copyright (C) 2005-2009 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
|
|
*/
|
|
/**
|
|
* @file drive.c
|
|
* Routines for player driving units about the map.
|
|
*/
|
|
|
|
#define DEFINE_DRIVE_INLINE
|
|
|
|
#include "lib/framework/frame.h"
|
|
#include "lib/framework/strres.h"
|
|
#include "lib/framework/input.h"
|
|
|
|
#include "lib/ivis_common/rendmode.h"
|
|
|
|
#include "lib/gamelib/gtime.h"
|
|
#include "lib/gamelib/animobj.h"
|
|
#include "lib/sound/audio.h"
|
|
|
|
#include "drive.h"
|
|
#include "objects.h"
|
|
#include "move.h"
|
|
#include "visibility.h"
|
|
#include "map.h"
|
|
#include "loop.h"
|
|
#include "geometry.h"
|
|
#include "anim_id.h"
|
|
#include "formationdef.h"
|
|
#include "formation.h"
|
|
#include "action.h"
|
|
#include "order.h"
|
|
#include "combat.h"
|
|
#include "mapgrid.h"
|
|
#include "display.h"
|
|
#include "effects.h"
|
|
#include "hci.h"
|
|
#include "warcam.h"
|
|
#include "radar.h"
|
|
#include "display3ddef.h"
|
|
#include "display3d.h"
|
|
#include "console.h"
|
|
#include "intdisplay.h"
|
|
#include "multiplay.h"
|
|
#include "target.h"
|
|
|
|
// all the bollox needed for script callbacks
|
|
#include "lib/script/parse.h" // needed to define types in scripttabs.h (Arse!)
|
|
#include "scripttabs.h" // needed to define the callback
|
|
#include "scriptextern.h" // needed to include the GLOBAL for checking bInTutorial
|
|
#include "group.h"
|
|
|
|
#define DRIVENOISE // Enable driving noises.
|
|
#define ENGINEVOL (0xfff)
|
|
#define MINPITCH (768)
|
|
#define PITCHCHANGE (512)
|
|
|
|
static SWORD DrivingAudioTrack=-1; // Which hardware channel are we using for the car driving noise
|
|
|
|
extern UDWORD selectedPlayer;
|
|
extern BOOL DirectControl;
|
|
|
|
// Driving characteristics.
|
|
#define DRIVE_TURNSPEED (4)
|
|
#define DRIVE_ACCELERATE (16)
|
|
#define DRIVE_BRAKE (32)
|
|
#define DRIVE_DECELERATE (16)
|
|
#define FOLLOW_STOP_RANGE (256) // How close followers need to get to the driver before they can stop.
|
|
#define DRIVE_TURNDAMP (32) // Damping value for analogue turning.
|
|
#define MAX_IDLE (GAME_TICKS_PER_SEC*60) // Start to orbit if idle for 60 seconds.
|
|
|
|
DROID *psDrivenDroid = NULL; // The droid that's being driven.
|
|
static BOOL bDriveMode = false;
|
|
static SDWORD driveDir; // Driven droid's direction.
|
|
static SDWORD driveSpeed; // Driven droid's speed.
|
|
static UDWORD driveBumpTime; // Time that followers get a kick up the ass.
|
|
static BOOL DoFollowRangeCheck = true;
|
|
static BOOL AllInRange = true;
|
|
static BOOL ClearFollowRangeCheck = false;
|
|
static BOOL DriveControlEnabled = false;
|
|
static BOOL DriveInterfaceEnabled = false;
|
|
static UDWORD IdleTime;
|
|
static BOOL TacticalActive = false;
|
|
static BOOL WasDriving = false;
|
|
|
|
enum {
|
|
CONTROLMODE_POINTNCLICK,
|
|
CONTROLMODE_DRIVE,
|
|
};
|
|
|
|
static UWORD ControlMode = CONTROLMODE_DRIVE;
|
|
static BOOL TargetFeatures = false;
|
|
|
|
// Intialise drive statics, call with true if coming from frontend, false if
|
|
// coming from a mission.
|
|
//
|
|
void driveInitVars(BOOL Restart)
|
|
{
|
|
if(WasDriving && !Restart)
|
|
{
|
|
debug( LOG_NEVER, "driveInitVars: WasDriving\n" );
|
|
DrivingAudioTrack=-1;
|
|
psDrivenDroid = NULL;
|
|
DoFollowRangeCheck = true;
|
|
ClearFollowRangeCheck = false;
|
|
bDriveMode = false;
|
|
DriveControlEnabled = true; //false;
|
|
DriveInterfaceEnabled = false; //true;
|
|
TacticalActive = false;
|
|
ControlMode = CONTROLMODE_DRIVE;
|
|
TargetFeatures = false;
|
|
|
|
}
|
|
else
|
|
{
|
|
debug( LOG_NEVER, "driveInitVars: Driving\n" );
|
|
DrivingAudioTrack=-1;
|
|
psDrivenDroid = NULL;
|
|
DoFollowRangeCheck = true;
|
|
ClearFollowRangeCheck = false;
|
|
bDriveMode = false;
|
|
DriveControlEnabled = true; //false;
|
|
DriveInterfaceEnabled = false;
|
|
TacticalActive = false;
|
|
ControlMode = CONTROLMODE_DRIVE;
|
|
TargetFeatures = false;
|
|
WasDriving = false;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void setDrivingStatus( BOOL val )
|
|
{
|
|
bDriveMode = val;
|
|
}
|
|
|
|
BOOL getDrivingStatus( void )
|
|
{
|
|
return(bDriveMode);
|
|
}
|
|
|
|
|
|
// Start droid driving mode.
|
|
//
|
|
BOOL StartDriverMode(DROID *psOldDroid)
|
|
{
|
|
DROID *psDroid;
|
|
DROID *psLastDriven;
|
|
|
|
IdleTime = gameTime;
|
|
|
|
psLastDriven = psDrivenDroid;
|
|
psDrivenDroid = NULL;
|
|
|
|
// Find a selected droid and make that the driven one.
|
|
for(psDroid = apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext)
|
|
{
|
|
if(psDroid->selected) {
|
|
if((psDrivenDroid == NULL) && (psDroid != psOldDroid)) {
|
|
// The first droid found becomes the driven droid.
|
|
if(!(DroidIsBuilding(psDroid) || DroidGoingToBuild(psDroid))) {
|
|
// psDroid->sMove.Status = MOVEDRIVE;
|
|
}
|
|
psDrivenDroid = psDroid;
|
|
debug( LOG_NEVER, "New driven droid\n" );
|
|
}
|
|
}
|
|
}
|
|
|
|
// If that failed then find any droid and make it the driven one.
|
|
if(psDrivenDroid == NULL) {
|
|
psLastDriven = NULL;
|
|
psDrivenDroid = intGotoNextDroidType(NULL,DROID_ANY,true);
|
|
|
|
// If it's the same droid then try again
|
|
if(psDrivenDroid == psOldDroid) {
|
|
psDrivenDroid = intGotoNextDroidType(NULL,DROID_ANY,true);
|
|
}
|
|
|
|
if(psDrivenDroid == psOldDroid) {
|
|
psDrivenDroid = NULL;
|
|
}
|
|
|
|
// If it failed then try for a transporter.
|
|
if(psDrivenDroid == NULL) {
|
|
psDrivenDroid = intGotoNextDroidType(NULL,DROID_TRANSPORTER,true);
|
|
}
|
|
|
|
// DBPRINTF(("Selected a new driven droid : %p\n",psDrivenDroid));
|
|
}
|
|
|
|
if(psDrivenDroid) {
|
|
|
|
driveDir = (int)psDrivenDroid->direction % 360;
|
|
driveSpeed = 0;
|
|
driveBumpTime = gameTime;
|
|
|
|
setDrivingStatus(true);
|
|
|
|
if(DriveInterfaceEnabled)
|
|
{
|
|
debug( LOG_NEVER, "Interface enabled1 ! Disabling drive control\n" );
|
|
DriveControlEnabled = false;
|
|
DirectControl = false;
|
|
}
|
|
else
|
|
{
|
|
DriveControlEnabled = true;
|
|
DirectControl = true; // we are taking over the unit.
|
|
}
|
|
|
|
if(psLastDriven != psDrivenDroid) {
|
|
debug( LOG_NEVER, "camAllignWithTarget\n" );
|
|
camAllignWithTarget((BASE_OBJECT*)psDrivenDroid);
|
|
}
|
|
|
|
|
|
return true;
|
|
} else {
|
|
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
static void ChangeDriver(void)
|
|
{
|
|
DROID *psDroid;
|
|
|
|
if(psDrivenDroid != NULL) {
|
|
debug( LOG_NEVER, "Driver Changed\n" );
|
|
|
|
// audio_StopObjTrack(psDrivenDroid,ID_SOUND_SMALL_DROID_RUN);
|
|
|
|
// psDrivenDroid = NULL;
|
|
|
|
for(psDroid = apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext) {
|
|
if( (psDroid->sMove.Status == MOVEDRIVE) ) {
|
|
ASSERT( (psDroid->droidType != DROID_TRANSPORTER),"Tried to control a transporter" );
|
|
secondarySetState(psDroid, DSO_HALTTYPE, DSS_HALT_GUARD);
|
|
psDroid->sMove.Status = MOVEINACTIVE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// setDrivingStatus(false);
|
|
// DriveControlEnabled = false;
|
|
}
|
|
|
|
|
|
// Stop droid driving mode.
|
|
//
|
|
void StopDriverMode(void)
|
|
{
|
|
DROID *psDroid;
|
|
|
|
if(psDrivenDroid != NULL)
|
|
{
|
|
debug( LOG_NEVER, "Drive mode canceled\n" );
|
|
addConsoleMessage("Driver mode canceled.", LEFT_JUSTIFY,SYSTEM_MESSAGE);
|
|
// audio_StopObjTrack(psDrivenDroid,ID_SOUND_SMALL_DROID_RUN);
|
|
|
|
psDrivenDroid = NULL;
|
|
|
|
for(psDroid = apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext) {
|
|
if( (psDroid->sMove.Status == MOVEDRIVE) ) {
|
|
ASSERT( (psDroid->droidType != DROID_TRANSPORTER),"Tried to control a transporter" );
|
|
secondarySetState(psDroid, DSO_HALTTYPE, DSS_HALT_GUARD);
|
|
psDroid->sMove.Status = MOVEINACTIVE;
|
|
}
|
|
}
|
|
}
|
|
|
|
setDrivingStatus(false);
|
|
driveInitVars(false); // reset everything again
|
|
DriveControlEnabled = false;
|
|
DirectControl = false;
|
|
}
|
|
|
|
|
|
// Call this whenever a droid gets killed or removed.
|
|
// returns true if ok, returns false if resulted in driving mode being stopped, ie could'nt find
|
|
// a selected droid to drive.
|
|
//
|
|
BOOL driveDroidKilled(DROID *psDroid)
|
|
{
|
|
if(driveModeActive()) {
|
|
if(psDroid == psDrivenDroid) {
|
|
ChangeDriver();
|
|
// StopDriverMode();
|
|
|
|
psDrivenDroid = NULL;
|
|
DeSelectDroid(psDroid);
|
|
|
|
if(!StartDriverMode(psDroid))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Call whenever the selections change to re initialise drive mode.
|
|
//
|
|
void driveSelectionChanged(void)
|
|
{
|
|
if(driveModeActive()) {
|
|
|
|
if(psDrivenDroid) {
|
|
// StopDriverMode();
|
|
ChangeDriver();
|
|
StartDriverMode(NULL);
|
|
driveTacticalSelectionChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Cycle to next droid in group and make it the driver.
|
|
//
|
|
static void driveNextDriver(void)
|
|
{
|
|
DROID *psDroid;
|
|
|
|
// Start from the current driven droid.
|
|
for(psDroid = psDrivenDroid; psDroid; psDroid = psDroid->psNext) {
|
|
if( (psDroid->selected) && (psDroid != psDrivenDroid) ) {
|
|
// Found one so make it the driven droid.
|
|
// psDrivenDroid->sMove.Status = MOVEINACTIVE;
|
|
// psDroid->sMove.Status = MOVEDRIVE;
|
|
psDrivenDroid = psDroid;
|
|
camAllignWithTarget((BASE_OBJECT*)psDroid);
|
|
driveTacticalSelectionChanged();
|
|
return;
|
|
}
|
|
}
|
|
|
|
for(psDroid = apsDroidLists[selectedPlayer];
|
|
psDroid && (psDroid != psDrivenDroid);
|
|
psDroid = psDroid->psNext) {
|
|
|
|
if(psDroid->selected) {
|
|
// Found one so make it the driven droid.
|
|
// psDrivenDroid->sMove.Status = MOVEINACTIVE;
|
|
// psDroid->sMove.Status = MOVEDRIVE;
|
|
psDrivenDroid = psDroid;
|
|
camAllignWithTarget((BASE_OBJECT*)psDroid);
|
|
driveTacticalSelectionChanged();
|
|
return;
|
|
}
|
|
}
|
|
// No other selected droids found. Oh well...
|
|
}
|
|
|
|
|
|
static BOOL driveControl(DROID *psDroid)
|
|
{
|
|
BOOL Input = false;
|
|
SDWORD MaxSpeed = moveCalcDroidSpeed(psDroid);
|
|
|
|
if(!DriveControlEnabled) {
|
|
return false;
|
|
}
|
|
|
|
if(keyPressed(KEY_N)) {
|
|
driveNextDriver();
|
|
}
|
|
|
|
if(keyDown(KEY_LEFTARROW)) {
|
|
driveDir += DRIVE_TURNSPEED;
|
|
Input = true;
|
|
} else if(keyDown(KEY_RIGHTARROW)) {
|
|
driveDir -= DRIVE_TURNSPEED;
|
|
if(driveDir < 0) {
|
|
driveDir += 360;
|
|
}
|
|
Input = true;
|
|
}
|
|
|
|
driveDir = driveDir % 360;
|
|
|
|
if(keyDown(KEY_UPARROW)) {
|
|
if(driveSpeed >= 0) {
|
|
driveSpeed += DRIVE_ACCELERATE;
|
|
if(driveSpeed > MaxSpeed) {
|
|
driveSpeed = MaxSpeed;
|
|
}
|
|
} else {
|
|
driveSpeed += DRIVE_BRAKE;
|
|
if(driveSpeed > 0) {
|
|
driveSpeed = 0;
|
|
}
|
|
}
|
|
Input = true;
|
|
} else if(keyDown(KEY_DOWNARROW)) {
|
|
if(driveSpeed <= 0) {
|
|
driveSpeed -= DRIVE_ACCELERATE;
|
|
if(driveSpeed < -MaxSpeed) {
|
|
driveSpeed = -MaxSpeed;
|
|
}
|
|
} else {
|
|
driveSpeed -= DRIVE_BRAKE;
|
|
if(driveSpeed < 0) {
|
|
driveSpeed = 0;
|
|
}
|
|
}
|
|
Input = true;
|
|
} else {
|
|
if(driveSpeed > 0) {
|
|
driveSpeed -= DRIVE_DECELERATE;
|
|
if(driveSpeed < 0) {
|
|
driveSpeed = 0;
|
|
}
|
|
} else {
|
|
driveSpeed += DRIVE_DECELERATE;
|
|
if(driveSpeed > 0) {
|
|
driveSpeed = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Input;
|
|
}
|
|
|
|
|
|
static BOOL driveInDriverRange(DROID *psDroid)
|
|
{
|
|
if( (abs(psDroid->pos.x-psDrivenDroid->pos.x) < FOLLOW_STOP_RANGE) &&
|
|
(abs(psDroid->pos.y-psDrivenDroid->pos.y) < FOLLOW_STOP_RANGE) ) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
static void driveMoveFollower(DROID *psDroid)
|
|
{
|
|
if(driveBumpTime < gameTime) {
|
|
// Update the driven droid's followers.
|
|
if(!driveInDriverRange(psDroid)) {
|
|
|
|
//psDroid->secondaryOrder&=~DSS_MOVEHOLD_SET; // Remove secondary order ... this stops the droid from jumping back to GUARD mode ... see order.c #111 - tjc
|
|
secondarySetState(psDroid, DSO_HALTTYPE, DSS_HALT_GUARD);
|
|
// if the droid is currently guarding we need to change the order to a move
|
|
if (psDroid->order==DORDER_GUARD)
|
|
{
|
|
orderDroidLoc(psDroid,DORDER_MOVE, psDrivenDroid->pos.x,psDrivenDroid->pos.y);
|
|
}
|
|
else
|
|
{
|
|
// otherwise we just adjust its move-to location
|
|
moveDroidTo(psDroid,psDrivenDroid->pos.x,psDrivenDroid->pos.y);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Stop it when it gets within range of the driver.
|
|
if(DoFollowRangeCheck) {
|
|
if(driveInDriverRange(psDroid)) {
|
|
psDroid->sMove.Status = MOVEINACTIVE;
|
|
} else {
|
|
AllInRange = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void driveMoveCommandFollowers(DROID *psDroid)
|
|
{
|
|
DROID *psCurr;
|
|
DROID_GROUP *psGroup = psDroid->psGroup;
|
|
|
|
for (psCurr = psGroup->psList; psCurr!=NULL; psCurr=psCurr->psGrpNext)
|
|
{
|
|
driveMoveFollower(psCurr);
|
|
}
|
|
}
|
|
|
|
|
|
// Call once per frame.
|
|
//
|
|
void driveUpdate(void)
|
|
{
|
|
DROID *psDroid;
|
|
PROPULSION_STATS *psPropStats;
|
|
|
|
AllInRange = true;
|
|
|
|
if(DirectControl) {
|
|
if(psDrivenDroid != NULL) {
|
|
if (driveBumpTime < gameTime) // send latest info about driven droid.
|
|
{
|
|
SendDroidInfo(psDrivenDroid,DORDER_MOVE,psDrivenDroid->pos.x,psDrivenDroid->pos.y, NULL);
|
|
}
|
|
|
|
//TO BE DONE:
|
|
//clear the order on taking over the droid, to stop attacks..
|
|
//send some sort of message when droids stopo and get inrange.
|
|
|
|
|
|
// Check the driven droid is still selected
|
|
if(psDrivenDroid->selected == false) {
|
|
// if it's not then reset the driving system.
|
|
driveSelectionChanged();
|
|
return;
|
|
}
|
|
|
|
// Update the driven droid.
|
|
if(driveControl(psDrivenDroid)) {
|
|
// If control did something then force the droid's move status.
|
|
if(psDrivenDroid->sMove.Status != MOVEDRIVE) {
|
|
psDrivenDroid->sMove.Status = MOVEDRIVE;
|
|
ASSERT( (psDrivenDroid->droidType != DROID_TRANSPORTER),"Tried to control a transporter" );
|
|
driveDir = (int)psDrivenDroid->direction % 360;
|
|
}
|
|
|
|
DoFollowRangeCheck = true;
|
|
}
|
|
|
|
// Is the driven droid under user control?
|
|
if(psDrivenDroid->sMove.Status == MOVEDRIVE) {
|
|
// Is it a command droid
|
|
if( (psDrivenDroid->droidType == DROID_COMMAND) &&
|
|
(psDrivenDroid->psGroup != NULL) ) {
|
|
driveMoveCommandFollowers(psDrivenDroid);
|
|
}
|
|
|
|
for(psDroid = apsDroidLists[selectedPlayer]; psDroid; psDroid = psDroid->psNext) {
|
|
|
|
psPropStats = asPropulsionStats + psDroid->asBits[COMP_PROPULSION].nStat;
|
|
|
|
if( (psDroid->selected) &&
|
|
(psDroid != psDrivenDroid) &&
|
|
(psDroid->droidType != DROID_TRANSPORTER) &&
|
|
//((psPropStats->propulsionType != PROPULSION_TYPE_LIFT) || (psDroid->droidType == DROID_CYBORG)) ) {
|
|
((psPropStats->propulsionType != PROPULSION_TYPE_LIFT) || cyborgDroid(psDroid)) )
|
|
{
|
|
// Send new orders to it's followers.
|
|
driveMoveFollower(psDroid);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(AllInRange) {
|
|
DoFollowRangeCheck = false;
|
|
}
|
|
|
|
if(driveBumpTime < gameTime) {
|
|
// Send next order in 1 second.
|
|
driveBumpTime = gameTime+GAME_TICKS_PER_SEC;
|
|
}
|
|
} else {
|
|
if(StartDriverMode(NULL) == false) {
|
|
// nothing
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
SDWORD driveGetMoveSpeed(void)
|
|
{
|
|
return driveSpeed;
|
|
}
|
|
|
|
|
|
SDWORD driveGetMoveDir(void)
|
|
{
|
|
return driveDir;
|
|
}
|
|
|
|
|
|
void driveSetDroidMove(DROID *psDroid)
|
|
{
|
|
// psDroid->sMove.speed = (float)driveSpeed;
|
|
// psDroid->sMove.dir = driveDir;
|
|
psDroid->direction = driveDir;
|
|
}
|
|
|
|
|
|
// Dissable user control of droid, ie when interface is up.
|
|
|
|
void driveDisableControl(void)
|
|
{
|
|
DriveControlEnabled = false;
|
|
DirectControl = false;
|
|
DriveInterfaceEnabled = true;
|
|
}
|
|
|
|
|
|
// Enable user control of droid, ie when interface is down.
|
|
//
|
|
void driveEnableControl(void)
|
|
{
|
|
DriveControlEnabled = true;
|
|
DirectControl = true;
|
|
DriveInterfaceEnabled = false;
|
|
}
|
|
|
|
|
|
|
|
// Return true if drive control is enabled.
|
|
//
|
|
BOOL driveControlEnabled(void)
|
|
{
|
|
return DriveControlEnabled;
|
|
}
|
|
|
|
|
|
// Bring up the reticule.
|
|
//
|
|
void driveEnableInterface(BOOL AddReticule)
|
|
{
|
|
if(AddReticule) {
|
|
intAddReticule();
|
|
}
|
|
|
|
DriveInterfaceEnabled = true;
|
|
}
|
|
|
|
|
|
// Get rid of the reticule.
|
|
//
|
|
void driveDisableInterface(void)
|
|
{
|
|
intResetScreen(false);
|
|
intRemoveReticule();
|
|
|
|
DriveInterfaceEnabled = false;
|
|
}
|
|
|
|
|
|
// Return true if the reticule is up.
|
|
//
|
|
BOOL driveInterfaceEnabled(void)
|
|
{
|
|
return DriveInterfaceEnabled;
|
|
}
|
|
|
|
|
|
// Check for and process a user request for a new target.
|
|
//
|
|
void driveProcessAquireButton(void)
|
|
{
|
|
if(mouseReleased(MOUSE_RMB) || keyPressed(KEY_S))
|
|
{
|
|
BASE_OBJECT *psObj;
|
|
psObj = targetAquireNearestObjView((BASE_OBJECT*)psDrivenDroid);
|
|
// driveMarkTarget();
|
|
// pie_SetMouse(CURSOR_ATTACK, true);
|
|
}
|
|
}
|
|
|
|
|
|
// Start structure placement for drive mode.
|
|
//
|
|
void driveStartBuild(void)
|
|
{
|
|
|
|
intRemoveReticule();
|
|
DriveInterfaceEnabled = false;
|
|
// driveDisableInterface();
|
|
driveEnableControl();
|
|
}
|
|
|
|
|
|
// Return true if all the conditions for allowing user control of the droid are met.
|
|
//
|
|
BOOL driveAllowControl(void)
|
|
{
|
|
if (TacticalActive || DriveInterfaceEnabled || !DriveControlEnabled)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Disable Tactical order mode.
|
|
//
|
|
void driveDisableTactical(void)
|
|
{
|
|
if(driveModeActive() && TacticalActive)
|
|
{
|
|
CancelTacticalScroll();
|
|
TacticalActive = false;
|
|
}
|
|
}
|
|
|
|
|
|
// Return true if Tactical order mode is active.
|
|
//
|
|
BOOL driveTacticalActive(void)
|
|
{
|
|
return TacticalActive;
|
|
}
|
|
|
|
|
|
void driveTacticalSelectionChanged(void)
|
|
{
|
|
if(TacticalActive && psDrivenDroid) {
|
|
StartTacticalScrollObj(true,(BASE_OBJECT *)psDrivenDroid);
|
|
debug( LOG_NEVER, "driveTacticalSelectionChanged\n" );
|
|
}
|
|
}
|
|
|
|
|
|
// Player clicked in the radar window.
|
|
//
|
|
void driveProcessRadarInput(int x,int y)
|
|
{
|
|
int PosX, PosY;
|
|
|
|
// when drive mode is active, clicking on the radar orders all selected droids
|
|
// to move to this position.
|
|
CalcRadarPosition(x, y, &PosX, &PosY);
|
|
orderSelectedLoc(selectedPlayer, PosX*TILE_UNITS,PosY*TILE_UNITS);
|
|
}
|
|
/*
|
|
void driveMarkTarget(void)
|
|
{
|
|
|
|
BASE_OBJECT *psObj = targetGetCurrent();
|
|
if(psObj != NULL)
|
|
{
|
|
if(driveAllowControl())
|
|
{
|
|
// MouseMovement(false);
|
|
targetMarkCurrent();
|
|
SetMousePos(0,psObj->sDisplay.screenX,psObj->sDisplay.screenY);
|
|
// pie_DrawMouse(psObj->sDisplay.screenX,psObj->sDisplay.screenY);
|
|
}
|
|
}
|
|
}
|
|
*/
|