diff --git a/engine/MUNGA/GAUGREND.cpp b/engine/MUNGA/GAUGREND.cpp index cdfac22..ed6ea65 100644 --- a/engine/MUNGA/GAUGREND.cpp +++ b/engine/MUNGA/GAUGREND.cpp @@ -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() { diff --git a/engine/MUNGA/GAUGREND.h b/engine/MUNGA/GAUGREND.h index f7ed925..c46933d 100644 --- a/engine/MUNGA/GAUGREND.h +++ b/engine/MUNGA/GAUGREND.h @@ -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, diff --git a/game/reconstructed/btl4rdr.cpp b/game/reconstructed/btl4rdr.cpp index 75dc946..38db1dd 100644 --- a/game/reconstructed/btl4rdr.cpp +++ b/game/reconstructed/btl4rdr.cpp @@ -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); + } } } diff --git a/game/reconstructed/mech.cpp b/game/reconstructed/mech.cpp index a486069..25bff48 100644 --- a/game/reconstructed/mech.cpp +++ b/game/reconstructed/mech.cpp @@ -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