Rangefinder.c
class Rangefinder extends PoweredOptic_Base
{
static const float RANGEFINDER_MAX_DISTANCE = 913.4856; //TODO adjust maximal distance to match real life rangefinder
protected ref Timer m_Timer;
protected Widget m_Root;
protected TextWidget m_RangeText;
protected string m_LayoutPath;
void Rangefinder()
{
InitRangeFinderData();
}
void ~Rangefinder()
{
m_IsActionActive = false;
}
protected void InitRangeFinderData()
{
string path = "cfgVehicles " + GetType();
if (g_Game.ConfigIsExisting(path))
{
string layout;
if (g_Game.ConfigIsExisting(path + " rangeFinderLayout"))
{
g_Game.ConfigGetText(path + " rangeFinderLayout", layout);
}
if (layout != "" && layout.Length() > 0)
{
m_LayoutPath = layout;
}
else
{
m_LayoutPath = "gui/layouts/gameplay/rangefinder_hud.layout";
}
}
}
// How frequently the measurement should be taken
float GetMeasurementUpdateInterval()
{
return 0.5;
}
override void OnWorkStart()
{
if (g_Game.IsServer() && !m_IsActionActive) // incorrectly synchronized state from EM
StopWorkServer();
if( !g_Game.IsDedicatedServer())
{
PlayerBase player_this = PlayerBase.Cast( g_Game.GetPlayer() );
PlayerBase player_owner = PlayerBase.Cast( GetHierarchyRootPlayer() );
if ( player_this == player_owner )
{
StartPeriodicMeasurement();
}
}
}
override void OnWorkStop()
{
if( !g_Game.IsDedicatedServer())
{
PlayerBase player_this = PlayerBase.Cast( g_Game.GetPlayer() );
PlayerBase player_owner = PlayerBase.Cast( GetHierarchyRootPlayer() );
if ( player_this == player_owner )
{
StopPeriodicMeasurement();
}
}
}
void StartPeriodicMeasurement()
{
if( !m_Timer )
{
m_Timer = new Timer( CALL_CATEGORY_GAMEPLAY );
}
m_Root = g_Game.GetWorkspace().CreateWidgets( m_LayoutPath );
// Either use root as text widget directly or find the text as children, arbitrary layout is supported now.
m_RangeText = TextWidget.Cast(m_Root);
if (!m_RangeText)
m_RangeText = TextWidget.Cast(m_Root.FindAnyWidget("RangeText"));
m_Timer.Run( GetMeasurementUpdateInterval(), this, "DoMeasurement", null, true );
}
void StopPeriodicMeasurement()
{
if( m_Timer )
{
m_Timer.Stop();
}
if (m_Root)
{
delete m_Root;
}
}
protected void SetDistanceText(TextWidget text, float dist)
{
dist = Math.Round(dist);
if (dist < RANGEFINDER_MAX_DISTANCE)
{
if( dist < 10 )
text.SetText( "00" + dist.ToString() );
else if( dist < 100 )
text.SetText( "0" + dist.ToString() );
else
text.SetText( dist.ToString() );
}
else
{
SetInvalidText(text);
}
}
protected void SetInvalidText(TextWidget text)
{
text.SetText( "---" );
}
// Measures the distance and returns result in formated string
void DoMeasurement()
{
PlayerBase player = GetPlayer();
if ( player )
{
vector from = g_Game.GetCurrentCameraPosition();
vector fromDirection = g_Game.GetCurrentCameraDirection();
vector to = from + (fromDirection * RANGEFINDER_MAX_DISTANCE);
vector contact_pos;
vector contact_dir;
int contactComponent;
bool hit = DayZPhysics.RaycastRV( from, to, contact_pos, contact_dir, contactComponent, NULL , NULL, player, false, false, ObjIntersectIFire);
// (a)
// from -> --- <- horizEnd
// (h) \ |
// to -> \|
// Generate result
float h = vector.Distance( from, contact_pos );
if (hit)
SetDistanceText( m_RangeText, h );
else
SetInvalidText( m_RangeText );
// Horizontal distance
TextWidget angleText = TextWidget.Cast(m_Root.FindAnyWidget("AngleText"));
TextWidget horizText = TextWidget.Cast(m_Root.FindAnyWidget("RangeHDText"));
vector horizontalTo = Vector( contact_pos[0], from[1], contact_pos[2] );
float a = vector.Distance( from, horizontalTo );
// Angle between horizontal and actual line
float heightDiff = contact_pos[1] - from[1];
float angle = Math.Atan( heightDiff / a ) * Math.RAD2DEG;
angle = Math.Round(angle);
if (angleText)
{
if (hit)
angleText.SetText(string.Format("%1", angle));
else
SetInvalidText( angleText );
}
if (horizText)
{
if (hit)
SetDistanceText( horizText, a );
else
SetInvalidText( horizText );
}
}
}
override void SetActions()
{
super.SetActions();
RemoveAction(ActionViewOptics);
AddAction(ActionViewBinoculars);
}
override void OnDebugSpawn()
{
GetInventory().CreateInInventory( "Battery9V" );
}
}