#ifdef DIAG_DEVELOPER
#ifndef SERVER
//----------------------------------------------------------------------------------------
//!
class WeaponLiftDiagData
{
vector m_Transform[4];
vector m_Start;
vector m_Direction;
float m_WeaponStartDist
float m_WeaponEndDist;
float m_EffectiveAttachmentLength;
float m_ObstructionDistanceCfg;
float m_ObstructionDistance;
float m_RayRadius;
float m_RayRadiusOverride;
ref RaycastRVResult m_RayResult;
float m_HitFraction;
float m_HitDistance;
vector m_LastPosition;
float m_InterpInTime;
float m_InterpInTimeLift;
float m_InterpOutTime;
float m_InterpCurrTime;
float m_InterpCurrValue;
float m_InterpTgtValue;
float m_InterpSmoothValue;
float m_AimUD;
float m_AimLR;
float m_AimUD11;
float m_AimLR11;
//!
void SetTransform(vector transform[4])
{
for (int i = 0; i < 4; ++i) m_Transform[i] = transform[i];
}
//!
void SetAimAngles(float udAngle, float lrAngle, float udAngle11, float lrAngle11)
{
m_AimUD = udAngle;
m_AimLR = lrAngle;
m_AimUD11 = udAngle11;
m_AimLR11 = lrAngle11;
}
//!
void SetWeaponRayParams(vector rayOrigin, vector rayDirection, float weaponStartDist, float weaponEndDist, float effectiveAttachmentLength, float obstructionDistanceCfg, float obstructionDistance, float rayRadius)
{
m_Start = rayOrigin;
m_Direction = rayDirection;
m_WeaponStartDist = weaponStartDist;
m_WeaponEndDist = weaponEndDist;
m_EffectiveAttachmentLength = effectiveAttachmentLength;
m_ObstructionDistanceCfg = obstructionDistanceCfg;
m_ObstructionDistance = obstructionDistance;
m_RayRadius = rayRadius;
}
//!
void SetIntersectionParams(RaycastRVResult rayResult, float hitFraction = 0, float hitDistance = 0)
{
m_RayResult = rayResult;
m_HitFraction = hitFraction;
m_HitDistance = hitDistance;
}
//!
void SetLastPosition(vector lastPosition)
{
m_LastPosition = lastPosition;
}
//!
void SetInterpolation(float inTime, float inTimeLift, float outTime, float currentTime, float smoothValue, float currentValue, float targetValue)
{
m_InterpInTime = inTime;
m_InterpInTimeLift = inTimeLift;
m_InterpOutTime = outTime;
m_InterpCurrTime = currentTime;
m_InterpSmoothValue = smoothValue;
m_InterpCurrValue = currentValue;
m_InterpTgtValue = targetValue;
}
//!
void Clear()
{
Math3D.MatrixIdentity4(m_Transform);
SetIntersectionParams(null, 0, 0);
SetWeaponRayParams(vector.Zero, vector.Zero, 0, 0, 0, 0, 0, 0);
SetLastPosition(vector.Zero);
SetInterpolation(0,0,0,0,0,0,0);
SetAimAngles(0,0,0,0);
}
}
//----------------------------------------------------------------------------------------
//!
class WeaponLiftDiag
{
private ref WeaponLiftDiagData m_Data = new WeaponLiftDiagData();
private const int COLOR_START = 0xFF2ECC71; // Green
private const int COLOR_END = 0xFF4B77BE; // Blue
private const int COLOR_END_NOATTACH = 0xFFF7CA18; // Yellow
private const int COLOR_OBSTRUCTION = 0xFFFF00FF; // Pink
private const int COLOR_HIT = 0xFFFF0000; // Red
private const int COLOR_GUIDE = 0xC03A3A3A; // Semi-transparent gray
private const int COLOR_WEAPON = 0x1FFFFFFF; // Semi-transparent white
private const int COLOR_LAST_POS = 0x3AF7CA18; // Semi-transparent yellow
private bool m_bDrawGizmos = true;
private bool m_bDrawTransform = false;
private bool m_bSmallShapes = false;
private bool m_bZBuffer = false;
private bool m_bWireOnly = true;
private bool m_bForceRaised = false;
private int m_iColorCrosshair= false;
private int m_iCrosshairR = 255;
private int m_iCrosshairG = 0;
private int m_iCrosshairB = 0;
private int m_iCrosshairA = 255;
private float m_fCrosshairBlendPow = 1;
//----------------------------------------------------------------------------------------
WeaponLiftDiagData Data()
{
return m_Data;
}
//----------------------------------------------------------------------------------------
void Reset()
{
m_Data.Clear();
}
//----------------------------------------------------------------------------------------
void DrawDiag(int mode, float deltaTime)
{
const int MODE_BASIC = 1;
const int MODE_EXTENDED = 2;
bool wasColoringCrosshair = m_iColorCrosshair;
WeaponLiftDiagData data = m_Data;
if (data)
{
/// TITLE
DbgUI.Begin("Weapon Lift/Obstruction Diag");
{
/// WEAPON PROPERTIES
int gray = 0x80FFFFFF; // semi transparent white (gray)
int darkObst = gray&COLOR_OBSTRUCTION;
int endNoAttachCol = gray & COLOR_END_NOATTACH;
DbgUI.ColoredText(COLOR_WHITE, "Weapon properties");
DbgUI.ColoredText(COLOR_START, " weaponStartDist: " + data.m_WeaponStartDist);
DbgUI.ColoredText(COLOR_WHITE, " weaponLength: " + (data.m_WeaponEndDist - data.m_WeaponStartDist));
DbgUI.ColoredText(COLOR_END, " weaponEndDist: " + data.m_WeaponEndDist);
if (data.m_EffectiveAttachmentLength > 0)
{
DbgUI.ColoredText(gray, " attachmentLength: " + data.m_EffectiveAttachmentLength);
DbgUI.ColoredText(endNoAttachCol, " distNoAttachment: " + (data.m_WeaponEndDist-data.m_EffectiveAttachmentLength));
}
DbgUI.ColoredText(COLOR_OBSTRUCTION, " obstructionDist(cfg): " + data.m_ObstructionDistanceCfg);
if (DbgUI.FloatOverride("weaponObstruction", data.m_ObstructionDistance, 0.0, data.m_WeaponEndDist - data.m_EffectiveAttachmentLength))
{
data.m_ObstructionDistance += data.m_EffectiveAttachmentLength; // value was overriden directly, take attachment into account
}
DbgUI.ColoredText(darkObst, " obstructionDist(act): " + data.m_ObstructionDistance);
DbgUI.ColoredText(COLOR_HIT, " hitDistance: " + data.m_HitDistance);
DbgUI.PushID_Str("rayRadiusText");
DbgUI.ColoredText(0xFFAAAAAA, " rayRadius: " + data.m_RayRadius );
DbgUI.SameSpot();
DbgUI.Text( " "); // ugly, but prevents some layouting spasms
DbgUI.PopID();
float rayRadius = data.m_RayRadius;
if (DbgUI.FloatOverride("rayRadiusOverride", rayRadius, 0.0, 0.200, 1000))
{
data.m_RayRadiusOverride = rayRadius;
}
else
{
data.m_RayRadiusOverride = rayRadius;
}
/// !WEAPON PROPERTIES
/// UTILITY
DbgUI.Spacer(10);
DbgUI.ColoredText(COLOR_WHITE, "Utility");
DbgUI.Check("Force raised", m_bForceRaised);
TStringArray crossMode = { "Off", "On Obstruction", "On Lift", "On Both (Blend)" };
DbgUI.Combo("Color crosshair", m_iColorCrosshair, crossMode);
/// !UTILITY
/// CROSSHAIR COLOR
if (m_iColorCrosshair)
{
DbgUI.SameLine();
float r = m_iCrosshairR;
float g = m_iCrosshairG;
float b = m_iCrosshairB;
float a = m_iCrosshairA;
DbgUI.ColoredText(ARGB(m_iCrosshairA, m_iCrosshairR, m_iCrosshairG, m_iCrosshairB), " -|-");
//R
DbgUI.SliderFloat("Red: ", r, 0, 255);
DbgUI.SameLine();
DbgUI.PushID_Str("ObstructionDiagColorR");
DbgUI.ColoredText(0xFFFF0000, m_iCrosshairR.ToString());
DbgUI.PopID();
//G
DbgUI.SliderFloat("Green: ", g, 0, 255);
DbgUI.SameLine();
DbgUI.PushID_Str("ObstructionDiagColorG");
DbgUI.ColoredText(0xFF00FF00, m_iCrosshairG.ToString());
DbgUI.PopID();
//B
DbgUI.SliderFloat("Blue: ", b, 0, 255);
DbgUI.SameLine();
DbgUI.PushID_Str("ObstructionDiagColorB");
DbgUI.ColoredText(0xFF0000FF, m_iCrosshairB.ToString());
DbgUI.PopID();
// A
DbgUI.SliderFloat("Alpha: ", a, 0, 255);
DbgUI.SameLine();
DbgUI.PushID_Str("ObstructionDiagColorA");
DbgUI.ColoredText(0xAAFFFFFF, m_iCrosshairA.ToString());
DbgUI.PopID();
m_iCrosshairR = r;
m_iCrosshairG = g;
m_iCrosshairB = b;
m_iCrosshairA = a;
float pow = m_fCrosshairBlendPow * 5000;
DbgUI.SliderFloat("BlendPow: ", pow, 1, 5000);
DbgUI.SameLine();
pow = pow / 1000.0;
DbgUI.Text(pow.ToString());
m_fCrosshairBlendPow = pow;
}
///! CROSSHAIR COLOR
/// INTERSECTIONS
if (mode > MODE_BASIC)
{
DbgUI.Spacer(10);
DbgUI.ColoredText(COLOR_WHITE, "Intersection data");
if (data.m_RayResult && data.m_RayResult.surface)
{
DbgUI.Text(" Name: " + data.m_RayResult.surface.GetName());
DbgUI.Text(" EntryName: " + data.m_RayResult.surface.GetEntryName());
DbgUI.Text(" SurfaceType: " + data.m_RayResult.surface.GetSurfaceType());
DbgUI.Text(" IsPassThrough: " + data.m_RayResult.surface.IsPassthrough());
DbgUI.Text(" IsSolid: " + data.m_RayResult.surface.IsSolid());
DbgUI.Text(" HitFraction: " + data.m_HitFraction);
}
else
{
DbgUI.Text(" Name: - " );
DbgUI.Text(" EntryName: - " );
DbgUI.Text(" SurfaceType: - " );
DbgUI.Text(" IsPassThrough: - " );
DbgUI.Text(" IsSolid: - " );
DbgUI.Text(" HitFraction: - " );
}
}
///! INTERSECTIONS
/// INTERPOLATION
if (mode > MODE_BASIC)
{
DbgUI.Spacer(10);
DbgUI.ColoredText(COLOR_WHITE, "Interpolation");
DbgUI.Text(" In time: " + data.m_InterpInTime);
DbgUI.Text(" In time lift: " + data.m_InterpInTimeLift);
DbgUI.Text(" Out time: " + data.m_InterpOutTime);
DbgUI.Text(" Current time: " + data.m_InterpCurrTime);
DbgUI.Text(" Actual value: " + data.m_InterpCurrValue);
DbgUI.Text(" Target value: " + data.m_InterpTgtValue);
DbgUI.Text(" Smooth value: " + data.m_InterpSmoothValue);
}
///! INTERPOLATION
/// AIMING
if (mode > MODE_BASIC)
{
DbgUI.Spacer(10);
DbgUI.ColoredText(COLOR_WHITE, "Aiming");
DbgUI.ColoredText(0xFF80FF80, " UD Angle: " + data.m_AimUD);
DbgUI.ColoredText(0xFFAAFFAA, " UD[-1,1]: " + data.m_AimUD11);
DbgUI.ColoredText(0xFFFF8080, " LR Angle: " + data.m_AimLR);
DbgUI.ColoredText(0xFFFFAAAA, " LR[-1,1]: " + data.m_AimLR11);
}
///! AIMING
/// SHAPE PREFERENCES
if (mode > MODE_BASIC)
{
DbgUI.Spacer(10);
DbgUI.ColoredText(COLOR_WHITE, "Preferences");
DbgUI.Check(" Draw shapes", m_bDrawGizmos);
DbgUI.Check(" Small shapes", m_bSmallShapes);
DbgUI.Check(" Z-buffer", m_bZBuffer);
DbgUI.Check(" Draw approx transform", m_bDrawTransform);
DbgUI.Check(" Wire only", m_bWireOnly);
}
///! SHAPE PREFERENCES
/// CFGGAMEPLAY
if (mode >= MODE_BASIC)
{
DbgUI.ColoredText(COLOR_WHITE, "CfgGameplay WeaponObstructionData");
DbgUI.Text(" Static: " + EnumTools.EnumToString(EWeaponObstructionMode, CfgGameplayHandler.GetWeaponObstructionModeStatic()));
DbgUI.Text(" Dynamic: " + EnumTools.EnumToString(EWeaponObstructionMode, CfgGameplayHandler.GetWeaponObstructionModeDynamic()));
}
///! SHAPE PREFERENCES
}
DbgUI.End();
// Override input! Extremely helpful!!
if (m_bForceRaised && g_Game.GetPlayer())
{
DayZPlayer ply = g_Game.GetPlayer();
HumanInputController hic = ply.GetInputController();
hic.OverrideRaise( HumanInputControllerOverrideType.ONE_FRAME, true );
}
float radius = rayRadius;
if (m_bSmallShapes) radius = 0.01;
// gizmos
if (m_bDrawTransform) Shape.CreateMatrix(data.m_Transform, 1.0, 0.05);
// "Apply" settings
ShapeFlags flags = ShapeFlags.ONCE | ShapeFlags.TRANSP;
ShapeFlags flags2 = ShapeFlags.ONCE | ShapeFlags.TRANSP | ShapeFlags.NOOUTLINE;
if (!m_bZBuffer)
{
flags |= ShapeFlags.NOZBUFFER;
flags2 |= ShapeFlags.NOZBUFFER;
}
if (m_bWireOnly)
{
flags |= ShapeFlags.WIREFRAME;
}
else
{
flags |= ShapeFlags.NOOUTLINE;
}
vector wepStart = data.m_Start + (data.m_WeaponStartDist * data.m_Direction);
vector wepEnd = data.m_Start + (data.m_WeaponEndDist * data.m_Direction);
vector wepEndNoAttach = data.m_Start + ((data.m_WeaponEndDist - data.m_EffectiveAttachmentLength) * data.m_Direction);
if (m_bDrawGizmos)
{
// Draw "guide" line, start->end
Shape.Create(ShapeType.LINE, COLOR_GUIDE, flags2, data.m_Start, wepEnd);
// Draw weapon points
Shape.CreateSphere(COLOR_START, flags, wepStart, radius);
Shape.CreateSphere(COLOR_END_NOATTACH, flags, wepEndNoAttach, radius);
Shape.CreateSphere(COLOR_END, flags, wepEnd, radius);
// Draw obstruction distance point
if (data.m_ObstructionDistance != 0)
{
vector wepObstr = data.m_Start + (data.m_ObstructionDistance * data.m_Direction);
Shape.CreateSphere(COLOR_OBSTRUCTION, flags, wepObstr, radius);
}
// Draw last hit position (in ext. mode)
if (mode >= MODE_EXTENDED && data.m_LastPosition != vector.Zero)
{
Shape.Create(ShapeType.LINE, COLOR_LAST_POS, flags2, data.m_Start, data.m_LastPosition);
}
// Draw the weapon as it moves (a that slides along the "guide" line)
{
float cylinderLength = (wepEnd - wepStart).Length();
vector cylinderOffset = 0.5 * cylinderLength * data.m_Transform[2];
Shape cylinder = Shape.CreateCylinder(COLOR_WHITE, flags2, vector.Zero, 0.3 * radius, cylinderLength);
vector tm0[4], tm1[3];
Math3D.DirectionAndUpMatrix(data.m_Transform[2], data.m_Transform[1], tm0);
Math3D.YawPitchRollMatrix("90 0 90", tm1);
Math3D.MatrixMultiply3(tm0, tm1, tm0);
float fraction = Math.Clamp(data.m_HitFraction, 0, 1);
if (!data.m_RayResult) fraction = 1.0;
vector center = (data.m_Start + (fraction * (wepEnd - data.m_Start))) - cylinderOffset;
tm0[3] = center;
cylinder.SetMatrix(tm0);
}
// Draw hit
if (data.m_RayResult)
{
Shape.CreateSphere(COLOR_HIT, flags, data.m_RayResult.pos, 0.5 * radius);
}
}
if (m_iColorCrosshair || wasColoringCrosshair)
{
int crossColor = 0xFFFFFFFF;
if (m_iColorCrosshair) // only set if not "restoring"
{
if (m_iColorCrosshair == 1) // obstruction
{
float hitFraction = Data().m_HitFraction;
if (hitFraction != 0 && hitFraction < 1.0)
{
crossColor = ARGB(m_iCrosshairA, m_iCrosshairR, m_iCrosshairG, m_iCrosshairB);
}
}
else if (m_iColorCrosshair == 2) // lift only
{
float hitDist = Data().m_HitDistance;
float obstDist = Data().m_ObstructionDistance;
if (hitDist != 0 && hitDist < obstDist)
{
crossColor = ARGB(m_iCrosshairA, m_iCrosshairR, m_iCrosshairG, m_iCrosshairB);
}
}
else if (m_iColorCrosshair == 3) // magic
{
float t = 0.0;
if (Data().m_HitFraction != 0)
{
float fr = 1.0-Math.InverseLerp( Data().m_ObstructionDistance, Data().m_WeaponEndDist, Data().m_HitDistance );
t = Math.Clamp( fr, 0.0, 1.0 );
t = Math.Pow(t, m_fCrosshairBlendPow);
}
int white=0xFF;
int bA = Math.Lerp(white, m_iCrosshairA, t);
int bR = Math.Lerp(white, m_iCrosshairR, t);
int bG = Math.Lerp(white, m_iCrosshairG, t);
int bB = Math.Lerp(white, m_iCrosshairB, t);
crossColor = ARGB(bA, bR, bG, bB);
}
}
WorkspaceWidget ww = g_Game.GetWorkspace();
if (ww)
{
Widget cw = ww.FindAnyWidget("CrossHairs");
if (cw)
{
Widget child = cw.GetChildren();
while (child)
{
child.SetColor(crossColor);
child = child.GetSibling();
}
}
}
}
}
}
}
#endif
#endif