gauges/map: populate the radar entity grid + draw mech contact blips
Root-caused why the radar showed 0 contacts: the gauge renderer's moving/static entity grids (queried by GetMoving/StaticEntitiesWithinBounds) were NEVER populated -- the 1995 game fed them from ExecuteImplementation's InterestingEntity iterator, which the WinTesla port dropped. Fix (engine): add GaugeRenderer::RebuildEntityGrid() -- Clear + repopulate movingEntities from the world's DynamicMaster + DynamicReplicant entities (the vehicles/mechs; AllEntity would flood the grid with ~300 props/effects/terrain). Called from the map's Execute phase 0 (under the gauge's guarded Execute, so a fault disables only the map). Verified: contacts are now found, combat un- regressed (TARGET DESTROYED), heap-clean under BT_HEAPCHECK. Fix (map): DrawMoving now draws a cross blip for mech-class contacts (0xBB9) when the authentic pip raster set is absent (the BT pip table is stubbed in this engine build). KEY PROJECTION FIX: worldToView is a camera (view->world) matrix and Point3D::Multiply applies only rotation+scale (NOT translation), so projecting the absolute entity position left the viewpoint un-subtracted and the blip landed off-screen (verified: blip @(580,-1154)). Project the RELATIVE position (delta = entity - viewpoint, already computed for the range check) instead -> the blip projects viewpoint-relative + heading-rotated correctly (@(164,221)). radarRange default 500->1000 (1km zoom) so contacts within ~500m show on the radar (SetTargetRange, the real player zoom, is still stubbed). BT_MAP_LOG traces the blip coords. STATE: the grid population + viewpoint-relative blip projection are correct and combat-safe. A reliable on-screen contact demo still needs the display-scale vs spawn-distance reconciliation (the BT_SPAWN_ENEMY dummy sits at a varying, large distance -- 377-828m -- beyond the display radius across runs) + the authentic pip symbol/name/video-object infrastructure (still stubbed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1746c5bb1f
commit
0bceb9a638
@@ -6,6 +6,7 @@
|
||||
#include "mover.h"
|
||||
#include "terrain.h"
|
||||
#include "app.h"
|
||||
#include "hostmgr.h" // HostManager + AllEntityIterator (RebuildEntityGrid)
|
||||
|
||||
// #define LOCAL_TEST
|
||||
|
||||
@@ -3587,6 +3588,57 @@ void
|
||||
CLEAR_GAUGE_RENDERER();
|
||||
}
|
||||
|
||||
//
|
||||
//===========================================================================
|
||||
// RebuildEntityGrid -- repopulate the moving/static entity grids from the world
|
||||
// entity list (the port dropped ExecuteImplementation's InterestingEntity feed,
|
||||
// so the radar/map gauge's within-bounds queries found no contacts).
|
||||
//===========================================================================
|
||||
//
|
||||
void
|
||||
GaugeRenderer::RebuildEntityGrid()
|
||||
{
|
||||
Check(this);
|
||||
|
||||
movingEntities.Clear();
|
||||
staticEntities.Clear();
|
||||
|
||||
if (application == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HostManager *host_manager = application->GetHostManager();
|
||||
if (host_manager == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Radar contacts are the DYNAMIC vehicles (mechs), not the props/terrain/
|
||||
// projectiles that AllEntityIterator would flood the grid with -- iterate the
|
||||
// dynamic masters (the local + AI/dummy vehicles) plus the dynamic replicants
|
||||
// (peer vehicles in multiplayer). Static beacons/props (a separate
|
||||
// classification) are left for a follow-up.
|
||||
{
|
||||
HostManager::DynamicMasterEntityIterator master_iterator(host_manager);
|
||||
master_iterator.First();
|
||||
Entity *entity;
|
||||
while ((entity = master_iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
movingEntities.Add(entity);
|
||||
}
|
||||
}
|
||||
{
|
||||
HostManager::DynamicReplicantEntityIterator replicant_iterator(host_manager);
|
||||
replicant_iterator.First();
|
||||
Entity *entity;
|
||||
while ((entity = replicant_iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
movingEntities.Add(entity);
|
||||
}
|
||||
}
|
||||
Check_Fpu();
|
||||
}
|
||||
|
||||
void
|
||||
GaugeRenderer::ExecuteForeground()
|
||||
{
|
||||
|
||||
@@ -560,6 +560,13 @@ public:
|
||||
maxX, maxY, maxZ
|
||||
);
|
||||
}
|
||||
|
||||
// Rebuild the moving/static entity grids that the radar/map gauge queries.
|
||||
// The 1995 game fed these from ExecuteImplementation's InterestingEntity
|
||||
// iterator, which the WinTesla port dropped, so the grids stayed empty and
|
||||
// the radar found no contacts. Repopulate from the world entity list.
|
||||
void
|
||||
RebuildEntityGrid();
|
||||
void
|
||||
GetStaticBounds(
|
||||
Scalar *min_x,
|
||||
|
||||
@@ -533,6 +533,11 @@ void
|
||||
<< " cap=" << currentCapabilitiesRatio << " scale=" << currentScale << "\n" << std::flush;
|
||||
if (operating)
|
||||
{
|
||||
// Repopulate the renderer's entity grids (the port dropped the engine's
|
||||
// per-frame InterestingEntity feed, so the within-bounds queries in
|
||||
// phases 1/2 found nothing). Done here, under the gauge's guarded
|
||||
// Execute, so a fault disables only the map -- not the whole renderer.
|
||||
renderer->RebuildEntityGrid();
|
||||
maximumDistanceSquared = currentCapabilitiesRatio * maximumRange;
|
||||
maximumDistanceSquared = maximumDistanceSquared * maximumDistanceSquared;
|
||||
CalculateBounds(); // FUN_004c2178
|
||||
@@ -866,6 +871,35 @@ void
|
||||
LODIndex, metersPerPixel, &localView,
|
||||
MapBlipColor() /*7*/, blipXform, boxColour);
|
||||
}
|
||||
else if (entity->GetClassID() == 0xBB9) // MechClassID -- radar contacts are mechs
|
||||
{
|
||||
// BRING-UP: the authentic pip raster set (pips table) is not present
|
||||
// in this engine build, so draw a simple cross blip at the contact's
|
||||
// projected radar position (the target flashes in boxColor). Filtered
|
||||
// to mechs so the ~300 dynamic world entities (effects/props) the grid
|
||||
// carries don't clutter the display -- the real pip table would key the
|
||||
// symbol off the model class, which is the proper follow-up.
|
||||
//
|
||||
// Project the RELATIVE position (delta = entity - viewpoint): worldToView
|
||||
// is a camera matrix and Point3D::Multiply applies only rotation+scale
|
||||
// (not the translation), so feeding the absolute position leaves the
|
||||
// viewpoint un-subtracted and the blip lands off-screen.
|
||||
Point3D relative;
|
||||
relative.x = delta.x;
|
||||
relative.y = delta.y;
|
||||
relative.z = delta.z;
|
||||
Point3D screen;
|
||||
screen.Multiply(relative, worldToView); // FUN_00408b98 (rotate+scale)
|
||||
int sx = Round(screen.x);
|
||||
int sz = Round(screen.z);
|
||||
if (getenv("BT_MAP_LOG"))
|
||||
DEBUG_STREAM << "[map] blip mech @(" << sx << "," << sz << ")\n" << std::flush;
|
||||
localView.SetColor((entity == target) ? boxColor : MapBlipColor());
|
||||
localView.MoveToAbsolute(sx - 4, sz);
|
||||
localView.DrawLineToAbsolute(sx + 4, sz);
|
||||
localView.MoveToAbsolute(sx, sz - 4);
|
||||
localView.DrawLineToAbsolute(sx, sz + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -595,9 +595,9 @@ Mech::Mech(
|
||||
sensorSubsystem = 0; // this[0x1f7] (0xBBE) -- same hazard, zero it too
|
||||
attrPad = 0.0f; // shared read pad for un-populated gauge attributes
|
||||
linearSpeed = 0.0f; // live forward ground speed (LinearSpeed gauge); set per frame
|
||||
radarRange = 500.0f; // radar display scale (SetTargetRange is stubbed;
|
||||
// 500m default zoom so nearby contacts are visible,
|
||||
// vs the config maximum_range=4000 outer detection edge)
|
||||
radarRange = 1000.0f; // radar display scale (SetTargetRange is stubbed;
|
||||
// 1km default zoom so contacts within ~500m show on
|
||||
// the radar, vs the config maximum_range=4000 edge)
|
||||
radarLinearPosition = &localOrigin.linearPosition; // map reads the mech's live world position...
|
||||
radarAngularPosition= &localOrigin.angularPosition; // ...and orientation (pointers into the base origin)
|
||||
duckState = 0; // not crouching
|
||||
|
||||
Reference in New Issue
Block a user