Fixed unit selection and cursor actions not being pixel accurate. Visible Cells/Visible Cell Render world positions are now cached.

This commit is contained in:
Justin Marshall
2020-07-28 16:40:48 -07:00
parent a97502f650
commit ebbce748ee
6 changed files with 147 additions and 121 deletions
+52 -62
View File
@@ -1389,82 +1389,72 @@ if (BlubCell->Overlapper[1]) {
* HISTORY: *
* 08/20/1995 JLB : Created. *
*=============================================================================================*/
ObjectClass * MapClass::Close_Object(COORDINATE coord) const
{
ObjectClass * object = 0;
int distance = 0;
CELL cell = Coord_Cell(coord);
ObjectClass * MapClass::Close_Object(int screenx, int screeny) const {
int x1 = screenx - 10;
int y1 = screeny - 10;
int x2 = screenx + 10;
int y2 = screeny + 10;
/*
** Scan through current and adjacent cells, looking for the
** closest object (within reason) to the specified coordinate.
** Ensure that coordinate number one represents the upper left corner
** and coordinate number two represents the lower right corner.
*/
static int _offsets[] = {0, -1, 1, -MAP_CELL_W, MAP_CELL_W, MAP_CELL_W-1, MAP_CELL_W+1, -(MAP_CELL_W-1), -(MAP_CELL_W+1)};
for (int index = 0; index < (sizeof(_offsets) / sizeof(_offsets[0])); index++) {
if (x1 > x2) {
int temp = x1;
x1 = x2;
x2 = temp;
}
if (y1 > y2) {
int temp = y1;
y1 = y2;
y2 = temp;
}
AllowVoice = true;
for (int index = 0; index < DisplayClass::Layer[LAYER_GROUND].Count(); index++) {
ObjectClass* obj = DisplayClass::Layer[LAYER_GROUND][index];
//COORDINATE ocoord = obj->Center_Coord();
int x = obj->GetRenderX();
int y = obj->GetRenderY();
// Not on screen.
if (x == -1 && y == -1) {
continue;
}
/*
** Examine the cell for close object. Make sure that the cell actually is a
** legal one.
** Only try to select objects that are allowed to be selected, and are within the bounding box.
*/
CELL newcell = cell + _offsets[index];
if (In_Radar(newcell)) {
/*
** Search through all objects that occupy this cell and then
** find the closest object. Check against any previously found object
** to ensure that it is actually closer.
*/
ObjectClass * o = Array[newcell].Cell_Occupier();
while (o != NULL) {
/*
** Special case check to ignore cloaked object if not owned by the player.
*/
// Change for client/server multiplayer. ST - 8/7/2019 10:35AM
//if (!o->Is_Techno() || ((TechnoClass *)o)->IsOwnedByPlayer || ((TechnoClass *)o)->Cloak != CLOAKED) {
if (!o->Is_Techno() || ((TechnoClass *)o)->Is_Owned_By_Player() || ((TechnoClass *)o)->Cloak != CLOAKED) {
int d=-1;
if (o->What_Am_I() == RTTI_BUILDING) {
d = Distance(coord, Cell_Coord(newcell));
if (d > 0x00C0) d = -1;
} else {
d = Distance(coord, o->Center_Coord());
}
if (d >= 0 && (!object || d < distance)) {
distance = d;
object = o;
}
}
o = o->Next;
}
HouseClass* hptr = HouseClass::As_Pointer(obj->Owner());
if (obj->Class_Of().IsSelectable &&
x >= x1 && x <= x2 && y >= y1 && y <= y2) {
return obj;
}
}
/*
** Handle aircraft selection separately, since they aren't tracked in cells while flying
** Select any aircraft with the bounding box.
*/
for (int index = 0; index < Aircraft.Count(); index++) {
AircraftClass * aircraft = Aircraft.Ptr(index);
for (int air_index = 0; air_index < Aircraft.Count(); air_index++) {
AircraftClass* aircraft = Aircraft.Ptr(air_index);
//COORDINATE ocoord = aircraft->Center_Coord();
int x = aircraft->GetRenderX();
int y = aircraft->GetRenderY();
// Not on screen.
if (x == -1 && y == -1) {
continue;
}
if (aircraft->In_Which_Layer() != LAYER_GROUND) {
if (aircraft->Is_Owned_By_Player() || (aircraft->Cloak != CLOAKED)) {
int d = Distance(coord, Coord_Add(aircraft->Center_Coord(), XY_Coord(0, -aircraft->Height)));
if (d >= 0 && (!object || d < distance)) {
distance = d;
object = aircraft;
}
}
/*
** Only try to select objects that are allowed to be selected, and are within the bounding box.
*/
if (aircraft->Class->IsSelectable &&
!aircraft->Is_Selected_By_Player() &&
x >= x1 && x <= x2 && y >= y1 && y <= y2) {
return aircraft;
}
}
/*
** Only return the object if it is within 1/4 cell distance from the specified
** coordinate.
*/
if (object && distance > 0xC0) {
object = 0;
}
return(object);
return NULL;
}