370 lines
7.4 KiB
C
370 lines
7.4 KiB
C
|
|
// Screen coordinate based targeting system. Maintains a list of on screen objects
|
|
// and provides various functions for aquiring targets from this list.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include "frame.h"
|
|
#include "gtime.h"
|
|
#include "animobj.h"
|
|
|
|
#include "statsdef.h"
|
|
#include "base.h"
|
|
#include "featuredef.h"
|
|
#include "weapons.h"
|
|
#include "structuredef.h"
|
|
#include "display.h"
|
|
#include "visibility.h"
|
|
#include "objectdef.h"
|
|
#include "droid.h"
|
|
|
|
#include "geo.h"
|
|
#include "imd.h"
|
|
#include "vid.h"
|
|
|
|
|
|
|
|
#include "target.h"
|
|
|
|
extern UDWORD selectedPlayer;
|
|
|
|
#define TARGET_RESOURCES // Allow targeting of resources.
|
|
#define TARGET_WALLS // Allow targeting of walls.
|
|
|
|
#define MAX_TARGETS 32
|
|
|
|
typedef struct {
|
|
UWORD Type;
|
|
BASE_OBJECT *psObj;
|
|
} TARGET;
|
|
|
|
static BOOL FoundCurrent;
|
|
static UWORD NumTargets;
|
|
static UWORD TargetCurrent;
|
|
static UDWORD TargetCurrentID;
|
|
static TARGET TargetList[MAX_TARGETS];
|
|
static UDWORD TargetEndTime;
|
|
static BASE_OBJECT *TargetingObject;
|
|
static UWORD TargetingType;
|
|
|
|
extern UDWORD currentGameFrame;
|
|
|
|
// Initialise the targeting system.
|
|
//
|
|
void targetInitialise(void)
|
|
{
|
|
TargetCurrent = 0;
|
|
TargetCurrentID = UDWORD_MAX;
|
|
}
|
|
|
|
|
|
// Reset the target list, call once per frame.
|
|
//
|
|
void targetOpenList(BASE_OBJECT *psTargeting)
|
|
{
|
|
NumTargets = 0;
|
|
FoundCurrent = FALSE;
|
|
TargetingObject = psTargeting;
|
|
}
|
|
|
|
|
|
void targetCloseList(void)
|
|
{
|
|
if(!FoundCurrent) {
|
|
// targetAquireNew();
|
|
}
|
|
//DBPRINTF(("%d %d %d\n",NumTargets,TargetCurrent,TargetCurrentID);
|
|
}
|
|
|
|
|
|
//// Aquire a new target.
|
|
////
|
|
//BASE_OBJECT *targetAquireNew(void)
|
|
//{
|
|
// BASE_OBJECT *psObj;
|
|
//
|
|
// // First try and target the nearest threat.
|
|
// if( (psObj=targetAquireNearestObj(TargetingObject,TARGET_TYPE_THREAT)) != NULL) {
|
|
// DBPRINTF(("Targeting threat\n"));
|
|
// return psObj;
|
|
// }
|
|
//
|
|
// // if that failed then attempt to target the nearest object.
|
|
// if( (psObj=targetAquireNearestObj(TargetingObject,TARGET_TYPE_ANY)) != NULL) {
|
|
// DBPRINTF(("Targeting any\n"));
|
|
// return psObj;
|
|
// }
|
|
//
|
|
// TargetCurrent = 0;
|
|
// TargetCurrentID = UDWORD_MAX;
|
|
//
|
|
// return NULL;
|
|
//}
|
|
|
|
/*
|
|
DROID_WEAPON, // Weapon droid
|
|
DROID_SENSOR, // Sensor droid
|
|
DROID_ECM, // ECM droid
|
|
DROID_CONSTRUCT, // Constructor droid
|
|
DROID_PERSON, // person
|
|
DROID_CYBORG, // cyborg-type thang
|
|
DROID_TRANSPORTER, // guess what this is!
|
|
DROID_COMMAND, // Command droid
|
|
DROID_REPAIR, // Repair droid
|
|
DROID_DEFAULT, // Default droid
|
|
DROID_ANY, // Any droid, Only used as a parameter for intGotoNextDroidType(droidtype).
|
|
*/
|
|
|
|
// Tell the targeting system what type of droid is doing the targeting.
|
|
//
|
|
void targetSetTargetable(UWORD DroidType)
|
|
{
|
|
TargetingType = DroidType;
|
|
}
|
|
|
|
|
|
|
|
void targetAdd(BASE_OBJECT *psObj)
|
|
{
|
|
}
|
|
|
|
|
|
// Call whenever an object is removed. probably don't need this as
|
|
// the list is rebuilt every frame any way.
|
|
//
|
|
void targetKilledObject(BASE_OBJECT *psObj)
|
|
{
|
|
}
|
|
|
|
|
|
//// Aquire the target nearest to the specified screen coords.
|
|
////
|
|
//BASE_OBJECT *targetAquireNearestScreen(SWORD x,SWORD y,UWORD TargetType)
|
|
//{
|
|
// UWORD i;
|
|
// UWORD Nearesti = 0;
|
|
// UDWORD NearestDsq = UDWORD_MAX;
|
|
// UDWORD dx,dy;
|
|
// UDWORD Dsq;
|
|
// BASE_OBJECT *NearestObj = NULL;
|
|
// BASE_OBJECT *psObj;
|
|
//
|
|
// for(i=0; i<NumTargets; i++) {
|
|
// psObj = TargetList[i].psObj;
|
|
// dx = abs(psObj->sDisplay.screenX - x);
|
|
// dy = abs(psObj->sDisplay.screenY - y);
|
|
// Dsq = dx*dx+dy*dy;
|
|
// if(Dsq < NearestDsq) {
|
|
// if(TargetList[i].Type & TargetType) {
|
|
// NearestDsq = Dsq;
|
|
// Nearesti = i;
|
|
// NearestObj = psObj;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// if(NearestObj != NULL) {
|
|
// TargetCurrent = Nearesti;
|
|
// if(TargetCurrentID != NearestObj->id) {
|
|
// TargetCurrentID = NearestObj->id;
|
|
// targetStartAnim();
|
|
// }
|
|
// }
|
|
//
|
|
// return NearestObj;
|
|
//}
|
|
|
|
|
|
// Aquire the target nearest the vector from x,y to the top of the screen.
|
|
//
|
|
BASE_OBJECT *targetAquireNearestView(SWORD x,SWORD y,UWORD TargetType)
|
|
{
|
|
UWORD i;
|
|
UWORD Nearesti = 0;
|
|
// UDWORD NearestDsq = UDWORD_MAX;
|
|
UDWORD NearestDx = UDWORD_MAX;
|
|
UDWORD dx,dy;
|
|
// UDWORD Dsq;
|
|
BASE_OBJECT *NearestObj = NULL;
|
|
BASE_OBJECT *psObj;
|
|
|
|
for(i=0; i<NumTargets; i++) {
|
|
psObj = TargetList[i].psObj;
|
|
dx = abs(psObj->sDisplay.screenX - x);
|
|
dy = abs(psObj->sDisplay.screenY - y);
|
|
// Dsq = dx*dx+dy*dy*4;
|
|
dx += dy/2;
|
|
if(dx < NearestDx) {
|
|
if(TargetList[i].Type & TargetType) {
|
|
NearestDx = dx;
|
|
Nearesti = i;
|
|
NearestObj = psObj;
|
|
}
|
|
}
|
|
|
|
// if(Dsq < NearestDsq) {
|
|
// if(TargetList[i].Type & TargetType) {
|
|
// NearestDsq = Dsq;
|
|
// Nearesti = i;
|
|
// NearestObj = psObj;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
if(NearestObj != NULL) {
|
|
TargetCurrent = Nearesti;
|
|
if(TargetCurrentID != NearestObj->id) {
|
|
//printf("set1 %d\n",TargetCurrentID);
|
|
TargetCurrentID = NearestObj->id;
|
|
targetStartAnim();
|
|
}
|
|
} else {
|
|
TargetCurrentID = UDWORD_MAX;
|
|
}
|
|
|
|
return NearestObj;
|
|
}
|
|
|
|
|
|
//// Aquire the target nearest to the specified object.
|
|
////
|
|
//BASE_OBJECT *targetAquireNearestObj(BASE_OBJECT *psObj,UWORD TargetType)
|
|
//{
|
|
// if(psObj != NULL) {
|
|
// return targetAquireNearestScreen(psObj->sDisplay.screenX,psObj->sDisplay.screenY,TargetType);
|
|
// } else {
|
|
// return NULL;
|
|
// }
|
|
//}
|
|
|
|
|
|
// Aquire the target nearest to the specified object.
|
|
//
|
|
BASE_OBJECT *targetAquireNearestObjView(BASE_OBJECT *psObj,UWORD TargetType)
|
|
{
|
|
if(psObj != NULL) {
|
|
return targetAquireNearestView((SWORD)(psObj->sDisplay.screenX),
|
|
(SWORD)(psObj->sDisplay.screenY)
|
|
,TargetType);
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//// Aquire the next target in the target list.
|
|
////
|
|
//BASE_OBJECT *targetAquireNext(UWORD TargetType)
|
|
//{
|
|
// BASE_OBJECT *Target = NULL;
|
|
//
|
|
// if(NumTargets) {
|
|
// UWORD OldCurrent = TargetCurrent;
|
|
//
|
|
// TargetCurrent++;
|
|
//
|
|
// while( (Target == NULL) && (TargetCurrent < NumTargets) ) {
|
|
// // Target is of required type?
|
|
// if(TargetList[TargetCurrent].Type & TargetType) {
|
|
// Target = TargetList[TargetCurrent].psObj;
|
|
// }
|
|
//
|
|
// TargetCurrent++;
|
|
// }
|
|
//
|
|
//
|
|
// if(Target == NULL) {
|
|
// TargetCurrent = 0;
|
|
//
|
|
// while( (Target == NULL) && (TargetCurrent < OldCurrent) ) {
|
|
// // Target is of required type?
|
|
// if(TargetList[TargetCurrent].Type & TargetType) {
|
|
// Target = TargetList[TargetCurrent].psObj;
|
|
// }
|
|
//
|
|
// TargetCurrent++;
|
|
// }
|
|
// }
|
|
//
|
|
// if(TargetCurrent >= NumTargets) {
|
|
// TargetCurrent = 0;
|
|
// }
|
|
// }
|
|
//
|
|
// if(Target != NULL) {
|
|
// if(TargetCurrentID != Target->id) {
|
|
// TargetCurrentID = Target->id;
|
|
// targetStartAnim();
|
|
// }
|
|
// }
|
|
//
|
|
// return Target;
|
|
//}
|
|
|
|
|
|
// Get the currently targeted object.
|
|
//
|
|
BASE_OBJECT *targetGetCurrent(void)
|
|
{
|
|
if(TargetCurrentID != UDWORD_MAX) {
|
|
return TargetList[TargetCurrent].psObj;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// Start the box zoom animation.
|
|
//
|
|
void targetStartAnim(void)
|
|
{
|
|
TargetEndTime = gameTime+GAME_TICKS_PER_SEC/2;
|
|
}
|
|
|
|
|
|
// Display a marker over the current target.
|
|
//
|
|
void targetMarkCurrent(void)
|
|
{
|
|
SWORD x,y;
|
|
SWORD Offset;
|
|
SWORD x0,y0,x1,y1;
|
|
|
|
//printf("%d\n",TargetCurrentID);
|
|
if(TargetCurrentID == UDWORD_MAX) {
|
|
return;
|
|
}
|
|
|
|
x = (SWORD)(TargetList[TargetCurrent].psObj->sDisplay.screenX);
|
|
y = (SWORD)(TargetList[TargetCurrent].psObj->sDisplay.screenY);
|
|
|
|
// Make it zoom in.
|
|
if(TargetEndTime > gameTime) {
|
|
Offset =(SWORD)(16+(TargetEndTime-gameTime)/2);
|
|
} else {
|
|
Offset = 16;
|
|
}
|
|
|
|
|
|
|
|
x0 = (SWORD)(x-Offset);
|
|
y0 = (SWORD)(y-Offset);
|
|
x1 = (SWORD)(x+Offset);
|
|
y1 = (SWORD)(y+Offset);
|
|
|
|
iV_Line(x0,y0,x0+8,y0,COL_YELLOW);
|
|
iV_Line(x0,y0,x0,y0+8,COL_YELLOW);
|
|
|
|
iV_Line(x1,y0,x1-8,y0,COL_YELLOW);
|
|
iV_Line(x1,y0,x1,y0+8,COL_YELLOW);
|
|
|
|
iV_Line(x1,y1,x1-8,y1,COL_YELLOW);
|
|
iV_Line(x1,y1,x1,y1-8,COL_YELLOW);
|
|
|
|
iV_Line(x0,y1,x0+8,y1,COL_YELLOW);
|
|
iV_Line(x0,y1,x0,y1-8,COL_YELLOW);
|
|
}
|
|
|
|
|