11 string m_CollisionDetails;
14 protected const string SUFFIX_MATERIAL_DEPLOYABLE =
"_deployable.rvmat";
15 protected const string SUFFIX_MATERIAL_UNDEPLOYABLE =
"_undeployable.rvmat";
16 protected const string SUFFIX_MATERIAL_POWERED =
"_powered.rvmat";
21 protected ProjectionTrigger m_ProjectionTrigger;
22 protected string m_ProjectionTypename;
24 protected bool m_IsColliding;
25 protected bool m_IsCollidingGPlot;
26 protected bool m_IsSlope;
27 protected bool m_IsCollidingPlayer;
28 protected bool m_IsFloating;
29 protected bool m_UpdatePosition;
30 protected bool m_IsHidden;
32 protected vector m_DefaultOrientation;
33 protected vector m_Rotation;
34 protected vector m_y_p_r_previous;
35 protected vector m_ContactDir;
36 protected vector m_FromAdjusted;
37 protected const string ANIMATION_PLACING =
"Placing";
38 protected const string ANIMATION_INVENTORY =
"Inventory";
39 protected const string SELECTION_PLACING =
"placing";
40 protected const string SELECTION_INVENTORY =
"inventory";
42 protected const float SMALL_PROJECTION_RADIUS = 1;
43 protected const float SMALL_PROJECTION_GROUND = 2;
44 protected const float DISTANCE_SMALL_PROJECTION = 1;
45 protected const float LARGE_PROJECTION_DISTANCE_LIMIT = 6;
46 protected const float PROJECTION_TRANSITION_MIN = 1;
47 protected const float PROJECTION_TRANSITION_MAX = 0.25;
48 protected const float LOOKING_TO_SKY = 0.75;
49 static const float DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF = 1.5;
51 protected float m_SlopeTolerance;
52 protected bool m_AlignToTerrain;
53 protected vector m_YawPitchRollLimit;
54 protected int m_ContactComponent;
56 protected ref set<string> m_SelectionsToRefresh =
new set<string>;
71 m_ProjectionTrigger =
null;
72 m_UpdatePosition =
true;
73 m_ContactComponent = -1;
76 m_FromAdjusted =
"0 0 0";
80 if (m_WatchtowerIgnoreComponentNames.Count() == 0)
82 string baseStringBegin = Watchtower.BASE_VIEW_NAME;
83 string baseIgnoreStringEnd = Watchtower.BASE_WALL_NAME;
85 int floors = Watchtower.MAX_WATCHTOWER_FLOORS;
86 int walls = Watchtower.MAX_WATCHTOWER_WALLS;
89 for (
int i = 1; i < floors + 1; ++i)
91 compName = baseStringBegin + i.ToString();
92 for (
int j = 1; j < walls + 1; ++j)
93 m_WatchtowerIgnoreComponentNames.Insert(compName + baseIgnoreStringEnd + j.ToString());
96 m_WatchtowerBlockedComponentNames.Insert(compName);
98 m_WatchtowerIgnoreComponentNames.Insert(compName);
102 string configPathProjectionTypename =
string.Format(
"CfgVehicles %1 projectionTypename",
m_Parent.GetType());
103 if (
GetGame().ConfigIsExisting(configPathProjectionTypename))
105 m_ProjectionTypename =
GetGame().ConfigGetTextOut(configPathProjectionTypename);
112 projectionEntity.SetAllowDamage(
false);
113 SetProjectionEntity(projectionEntity);
119 if (projectionEntity ==
null)
121 ErrorEx(
string.Format(
"Cannot create hologram entity from config class %1", ProjectionBasedOnParent()),
ErrorExSeverity.WARNING);
125 SetProjectionEntity(projectionEntity);
131 if (
ItemBase.Cast(projectionEntity))
133 ItemBase.Cast(GetProjectionEntity()).SetIsHologram(
true);
136 string configPathSlope =
string.Format(
"CfgVehicles %1 slopeTolerance", GetProjectionEntity().
GetType());
137 if (
GetGame().ConfigIsExisting(configPathSlope))
139 m_SlopeTolerance =
GetGame().ConfigGetFloat(configPathSlope);
142 string configPathAlign =
string.Format(
"CfgVehicles %1 alignHologramToTerain", GetProjectionEntity().
GetType());
143 if (
GetGame().ConfigIsExisting(configPathAlign))
145 m_AlignToTerrain =
GetGame().ConfigGetInt(configPathAlign);
148 string configPathOrientationLimit =
string.Format(
"CfgVehicles %1 yawPitchRollLimit", GetProjectionEntity().
GetType());
149 if (
GetGame().ConfigIsExisting(configPathOrientationLimit))
151 m_YawPitchRollLimit =
GetGame().ConfigGetVector(configPathOrientationLimit);
161 GetGame().ObjectDelete(m_Projection);
164 if (m_ProjectionTrigger)
166 GetGame().ObjectDelete(m_ProjectionTrigger);
170 #ifdef DIAG_DEVELOPER
177 if ( m_Projection.HasAnimation( ANIMATION_PLACING ) )
179 m_Projection.SetAnimationPhase( ANIMATION_PLACING, 0 );
180 SetSelectionToRefresh( SELECTION_PLACING );
190 SetSelectionToRefresh( SELECTION_INVENTORY );
195 void UpdateSelections()
197 string cfg_access =
"CfgVehicles " + m_Projection.GetType() +
" AnimationSources ";
199 if (
GetGame().ConfigIsExisting(cfg_access) )
201 int cfg_access_count =
g_Game.ConfigGetChildrenCount(cfg_access);
203 for (
int i = 0; i < cfg_access_count; ++i )
206 GetGame().ConfigGetChildName(cfg_access, i, found_anim);
208 float anim_phase =
m_Parent.GetAnimationPhase(found_anim);
209 m_Projection.SetAnimationPhase(found_anim, anim_phase);
214 string ProjectionBasedOnParent()
219 string GetProjectionName(
ItemBase item)
222 if (m_ProjectionTypename !=
"")
224 return m_ProjectionTypename;
232 if (item.CanMakeGardenplot())
234 return "GardenPlotPlacing";
238 if (item.IsInherited(
TentBase ) || item.IsBasebuildingKit())
240 return item.GetType() +
"Placing";
243 return item.GetType();
247 static bool DoesHaveProjection(
ItemBase item)
253 void UpdateHologram(
float timeslice)
262 if (IsRestrictedFromAdvancedPlacing())
269 if (!GetUpdatePosition())
273 #ifdef DIAG_DEVELOPER
279 SetProjectionPosition(GetProjectionEntityPosition(
m_Player));
280 SetProjectionOrientation(AlignProjectionOnTerrain(timeslice));
287 m_Projection.OnHologramBeingPlaced(
m_Player);
290 vector AlignProjectionOnTerrain(
float timeslice )
294 if ( m_AlignToTerrain )
296 vector projection_orientation_angles = GetDefaultOrientation() + GetProjectionRotation();
300 vector projection_position = m_Projection.GetPosition();
303 if ( m_ContactDir.Length() > 0 )
305 normal = m_ContactDir;
309 normal =
GetGame().SurfaceGetNormal( projection_position[0], projection_position[2] );
312 vector angles = normal.VectorToAngles();
313 angles[1] = angles[1] + 270;
315 angles[0] =
Math.Clamp( angles[0], 0, 360 );
316 angles[1] =
Math.Clamp( angles[1], 0, 360 );
317 angles[2] =
Math.Clamp( angles[2], 0, 360 );
319 projection_orientation_angles[0] = projection_orientation_angles[0] + ( 360 - angles[0] );
321 Math3D.YawPitchRollMatrix( projection_orientation_angles, mat0 );
322 Math3D.YawPitchRollMatrix( angles, mat1 );
323 Math3D.MatrixMultiply3( mat1, mat0, mat2 );
325 y_p_r =
Math3D.MatrixToAngles( mat2 );
329 y_p_r = GetDefaultOrientation() + GetProjectionRotation();
331 if ( y_p_r[0] > 180 )
333 y_p_r[0] = y_p_r[0] - 360;
336 if ( y_p_r[0] < -180 )
338 y_p_r[0] = y_p_r[0] + 360;
342 return SmoothProjectionMovement( y_p_r, timeslice );
345 vector SmoothProjectionMovement(
vector y_p_r,
float timeslice )
347 if ( m_y_p_r_previous )
349 if (
Math.AbsFloat( y_p_r[0] - m_y_p_r_previous[0] ) > 100 )
353 m_y_p_r_previous[0] = m_y_p_r_previous[0] + 360;
358 m_y_p_r_previous[0] = m_y_p_r_previous[0] - 360;
362 y_p_r[0] =
Math.Lerp( m_y_p_r_previous[0], y_p_r[0], 15 * timeslice );
363 y_p_r[1] =
Math.Lerp( m_y_p_r_previous[1], y_p_r[1], 15 * timeslice );
364 y_p_r[2] =
Math.Lerp( m_y_p_r_previous[2], y_p_r[2], 15 * timeslice );
367 m_y_p_r_previous = y_p_r;
374 Class.CastTo(m_ProjectionTrigger,
g_Game.CreateObjectEx(
"ProjectionTrigger", GetProjectionPosition(),
SPAWN_FLAGS));
376 m_ProjectionTrigger.SetOrientation(GetProjectionOrientation());
377 m_ProjectionTrigger.SetParentObject(
this);
378 m_ProjectionTrigger.SetParentOwner(
m_Player);
383 void RefreshTrigger()
386 GetProjectionCollisionBox( min_max );
388 m_ProjectionTrigger.SetPosition(GetProjectionPosition());
389 m_ProjectionTrigger.SetOrientation(GetProjectionOrientation());
390 m_ProjectionTrigger.SetExtents(min_max[0], min_max[1]);
393 #ifdef DIAG_DEVELOPER
394 void DebugText(
string header,
bool mustBeTrue =
false,
bool condition =
true,
string info =
"")
398 int color = 0xFFFFFFFF;
400 if (mustBeTrue && !condition || !mustBeTrue && condition)
403 string text = header + condition + info;
404 DbgUI.ColoredText(color, text);
408 protected float m_PitchOverride;
409 protected float m_RollOverride;
410 void DebugConfigValues()
414 m_PitchOverride = m_YawPitchRollLimit[1];
415 m_RollOverride = m_YawPitchRollLimit[2];
417 DbgUI.InputFloat(
"slopeTolerance override", m_SlopeTolerance);
419 DbgUI.InputFloat(
"pitch limit override", m_PitchOverride);
421 DbgUI.InputFloat(
"roll limit override", m_RollOverride);
423 m_YawPitchRollLimit[1] = m_PitchOverride;
424 m_YawPitchRollLimit[2] = m_RollOverride;
429 void EvaluateCollision(
ItemBase action_item =
null)
431 #ifdef DIAG_DEVELOPER
432 m_CollisionDetails =
"";
435 if (!
m_Player.CanPlaceItem(m_Projection))
437 #ifdef DIAG_DEVELOPER
438 m_CollisionDetails +=
"[Player]";
440 SetIsColliding(
true);
443 else if (IsFloating() || IsHidden() || IsCollidingBBox(action_item) || IsCollidingPlayer() || IsClippingRoof() || !IsBaseViable() || IsCollidingGPlot() || IsCollidingZeroPos() || IsCollidingAngle() || !IsPlacementPermitted() || !HeightPlacementCheck() || IsUnderwater() || IsInTerrain())
445 SetIsColliding(
true);
449 #ifdef DIAG_DEVELOPER
450 DebugText(
"Inherits from TrapSpawnBase, checking IsPlaceableAtposition",
true);
454 Class.CastTo(trapSpawnBase, m_Projection);
455 SetIsColliding(!trapSpawnBase.IsPlaceableAtPosition(m_Projection.GetPosition()));
457 else if (m_Projection.IsInherited(
TrapBase))
459 #ifdef DIAG_DEVELOPER
460 DebugText(
"Inherits from TrapBase, checking IsPlaceableAtposition",
true);
463 Class.CastTo(trapBase, m_Projection);
464 SetIsColliding(!trapBase.IsPlaceableAtPosition(m_Projection.GetPosition()));
468 SetIsColliding(
false);
472 bool IsClippingRoof()
482 bool b1 = m_Projection.GetPosition()[1] >
GetGame().GetCurrentCameraPosition()[1];
484 #ifdef DIAG_DEVELOPER
487 if (m_Projection.DoPlacingHeightCheck())
489 b2 = MiscGameplayFunctions.IsUnderRoofEx(m_Projection,
GameConstants.ROOF_CHECK_RAYCAST_DIST, ObjIntersectFire);
490 #ifdef DIAG_DEVELOPER
491 MiscGameplayFunctions.IsUnderRoofFromToCalculation(m_Projection, from, to);
492 DrawArrow(from, to, !b2);
496 #ifdef DIAG_DEVELOPER
497 DebugText(
"IsClippingRoof: ",
false, b1,
" | (projection height) " + m_Projection.GetPosition()[1] +
" > (camera height) " +
GetGame().GetCurrentCameraPosition()[1]);
498 DebugText(
"IsClippingRoof: ",
false, b2,
" | (DoPlacingHeightCheck) " + m_Projection.DoPlacingHeightCheck() +
" && (IsUnderRoof) " + MiscGameplayFunctions.IsUnderRoof(m_Projection) +
" | from: " + from[1] +
" | to: " + to[1]);
504 bool IsCollidingAngle()
508 vector projection_orientation = m_Projection.GetOrientation();
509 bool isTrue =
Math.AbsFloat( projection_orientation[1] ) > m_YawPitchRollLimit[1] ||
Math.AbsFloat( projection_orientation[2] ) > m_YawPitchRollLimit[2];
510 #ifdef DIAG_DEVELOPER
511 DebugText(
"IsCollidingAngle: ",
false, isTrue,
" | (proj pitch) " +
Math.AbsFloat( projection_orientation[1] ) +
" > (pitch limit) " + m_YawPitchRollLimit[1] +
" | (proj roll) " +
Math.AbsFloat( projection_orientation[2] ) +
" > (roll limit) " + m_YawPitchRollLimit[2]);
517 #ifdef DIAG_DEVELOPER
522 m_Projection.GetTransform( mat );
537 bool IsCollidingBBox(
ItemBase action_item =
null)
544 vector absoluteOffset =
"0 0.05 0";
545 vector orientation = GetProjectionOrientation();
551 GetProjectionCollisionBox(minMax);
552 relativeOffset[1] = (minMax[1][1] - minMax[0][1]) * 0.5;
553 center = m_Projection.GetPosition() + relativeOffset + absoluteOffset;
554 edgeLength = GetCollisionBoxSize(minMax);
555 excludedObjects.Insert(m_Projection);
559 excludedObjects.Insert(action_item);
563 bool isTrue =
GetGame().IsBoxCollidingGeometry(center, orientation, edgeLength, ObjIntersectFire, ObjIntersectGeom, excludedObjects, collidedObjects);
564 #ifdef DIAG_DEVELOPER
568 foreach (
Object object: collidedObjects)
569 text +=
" | " +
Object.GetDebugName(
object);
571 DebugText(
"IsCollidingBBox: ",
false, isTrue, text);
573 int color = 0x01FFFFFF;
593 vector from_left_close = m_Projection.CoordToParent(GetLeftCloseProjectionVector());
594 vector to_left_close_down = from_left_close +
"0 -1 0";
596 vector from_right_close = m_Projection.CoordToParent(GetRightCloseProjectionVector());
597 vector to_right_close_down = from_right_close +
"0 -1 0";
599 vector from_left_far = m_Projection.CoordToParent(GetLeftFarProjectionVector());
600 vector to_left_far_down = from_left_far +
"0 -1 0";
602 vector from_right_far = m_Projection.CoordToParent(GetRightFarProjectionVector());
603 vector to_right_far_down = from_right_far +
"0 -1 0";
605 vector contact_pos_left_close;
606 vector contact_pos_right_close;
607 vector contact_pos_left_far;
608 vector contact_pos_right_far;
609 vector contact_dir_left_close;
610 vector contact_dir_right_close;
611 vector contact_dir_left_far;
612 vector contact_dir_right_far;
613 int contact_component_left_close;
614 int contact_component_right_close;
615 int contact_component_left_far;
616 int contact_component_right_far;
617 set<Object> results_left_close =
new set<Object>;
618 set<Object> results_right_close =
new set<Object>;
619 set<Object> results_left_far =
new set<Object>;
620 set<Object> results_right_far =
new set<Object>;
627 DayZPhysics.RaycastRV(from_left_close, to_left_close_down, contact_pos_left_close, contact_dir_left_close, contact_component_left_close, results_left_close,
null, m_Projection,
false,
false, ObjIntersectFire);
628 if (results_left_close.Count() > 0)
629 obj_left_close = results_left_close[results_left_close.Count() - 1];
631 DayZPhysics.RaycastRV(from_right_close, to_right_close_down, contact_pos_right_close, contact_dir_right_close, contact_component_right_close, results_right_close,
null, m_Projection,
false,
false, ObjIntersectFire);
632 if (results_right_close.Count() > 0)
633 obj_right_close = results_right_close[results_right_close.Count() - 1];
635 DayZPhysics.RaycastRV(from_left_far, to_left_far_down, contact_pos_left_far, contact_dir_left_far, contact_component_left_far, results_left_far,
null, m_Projection,
false,
false, ObjIntersectFire);
636 if (results_left_far.Count() > 0)
637 obj_left_far = results_left_far[results_left_far.Count() - 1];
639 DayZPhysics.RaycastRV(from_right_far, to_right_far_down, contact_pos_right_far, contact_dir_right_far, contact_component_right_far, results_right_far,
null, m_Projection,
false,
false, ObjIntersectFire);
640 if (results_right_far.Count() > 0)
641 obj_right_far = results_right_far[results_right_far.Count() - 1];
643 return IsBaseIntact(obj_left_close, obj_right_close, obj_left_far, obj_right_far ) && IsBaseStatic( obj_left_close ) && IsBaseFlat( contact_pos_left_close, contact_pos_right_close, contact_pos_left_far, contact_pos_right_far);
646 bool IsCollidingGPlot()
651 #ifdef DIAG_DEVELOPER
652 DebugText(
"IsCollidingGPlot: ",
false, m_IsCollidingGPlot);
655 return m_IsCollidingGPlot;
658 bool IsCollidingZeroPos()
661 bool isTrue = GetProjectionPosition() == origin;
662 #ifdef DIAG_DEVELOPER
663 DebugText(
"IsCollidingZeroPos: ",
false, isTrue);
670 bool IsBehindObstacle()
677 bool IsBaseStatic(
Object objectToCheck )
681 #ifdef DIAG_DEVELOPER
682 if (objectToCheck ==
null)
683 DebugText(
"IsBaseStatic(must be true): ",
true,
true,
" | objectToCheck is null (this is good)");
685 DebugText(
"IsBaseStatic(must be true): ",
true, IsObjectStatic(objectToCheck));
687 return objectToCheck ==
null || IsObjectStatic(objectToCheck);
690 bool IsObjectStatic(
Object obj )
692 return obj.IsBuilding() || obj.IsPlainObject() || (!
m_Parent.IsInherited(
KitBase) && obj.IsInherited(
BaseBuildingBase) && (m_WatchtowerBlockedComponentNames.Find(obj.GetActionComponentName(m_ContactComponent,
LOD.NAME_VIEW)) == -1));
695 bool IsBaseIntact(
Object under_left_close,
Object under_right_close,
Object under_left_far,
Object under_right_far )
697 bool isTrue = (under_left_close == under_right_close && under_right_close == under_left_far && under_left_far == under_right_far);
698 #ifdef DIAG_DEVELOPER
699 DebugText(
"IsBaseIntact(must be true and all equal): ",
true, isTrue,
" | ulc: " +
Object.GetDebugName(under_left_close) +
" | urc: " +
Object.GetDebugName(under_right_close) +
" | ulf: " +
Object.GetDebugName(under_left_far) +
" | urf: " +
Object.GetDebugName(under_right_far));
703 conditions.Insert(under_left_close ==
null);
704 conditions.Insert(under_right_close ==
null);
705 conditions.Insert(under_left_far ==
null);
706 conditions.Insert(under_right_far ==
null);
708 int amountOfNull = 0;
709 if (!under_left_close)
711 if (!under_right_close)
715 if (!under_right_far)
718 if ( amountOfNull < 3 )
719 for (
int i = 0; i < conditions.Count(); ++i)
720 conditions[i] = !conditions[i];
722 DrawBaseSpheres(conditions);
729 #ifdef DIAG_DEVELOPER
734 int color = 0xFFFFFFFF;
742 void DrawSphere(
vector pos,
bool condition)
746 int color = 0x01FFFFFF;
759 positions.Insert(m_Projection.CoordToParent( GetLeftCloseProjectionVector() ));
760 positions.Insert(m_Projection.CoordToParent( GetRightCloseProjectionVector() ));
761 positions.Insert(m_Projection.CoordToParent( GetLeftFarProjectionVector() ));
762 positions.Insert(m_Projection.CoordToParent( GetRightFarProjectionVector() ));
764 for (
int i = 0; i < positions.Count(); ++i)
765 DrawSphere(positions[i], conditions[i]);
769 void DrawDebugArrow(
float start,
float dist,
int color = 0xFF1FFFFF)
781 bool IsBaseFlat(
vector contact_pos_left_close,
vector contact_pos_right_close,
vector contact_pos_left_far,
vector contact_pos_right_far )
783 vector projection_pos = GetProjectionPosition();
784 float slope_pos_left_close =
Math.AbsFloat(projection_pos[1] - contact_pos_left_close[1]);
785 float slope_pos_right_close =
Math.AbsFloat(projection_pos[1] - contact_pos_right_close[1]);
786 float slope_pos_left_far =
Math.AbsFloat(projection_pos[1] - contact_pos_left_far[1]);
787 float slope_pos_right_far =
Math.AbsFloat(projection_pos[1] - contact_pos_right_far[1]);
789 bool isTrue = slope_pos_left_close < m_SlopeTolerance && slope_pos_right_close < m_SlopeTolerance && slope_pos_left_far < m_SlopeTolerance && slope_pos_right_far < m_SlopeTolerance;
790 #ifdef DIAG_DEVELOPER
791 DebugText(
"IsBaseFlat(must be true): ",
true, isTrue,
" (slope < slopeTolerance) | slopeTolerance: " + m_SlopeTolerance +
" | lc: " + slope_pos_left_close +
" | rc: " + slope_pos_right_close +
" | lf: " + slope_pos_left_far +
" | rf: " + slope_pos_right_far);
792 DrawArrow(projection_pos, contact_pos_left_close, slope_pos_left_close < m_SlopeTolerance);
793 DrawArrow(projection_pos, contact_pos_right_close, slope_pos_right_close < m_SlopeTolerance);
794 DrawArrow(projection_pos, contact_pos_left_far, slope_pos_left_far < m_SlopeTolerance);
795 DrawArrow(projection_pos, contact_pos_right_far, slope_pos_right_far < m_SlopeTolerance);
802 bool IsPlacementPermitted()
809 #ifdef DIAG_DEVELOPER
810 DebugText(
"IsPlacementPermitted(must be true): ",
true, isTrue,
" (Note: ItemBase::CanBePlaced() return value)");
816 bool HeightPlacementCheck()
820 if ( GetProjectionEntity() )
823 vector projectionpos = GetProjectionPosition();
824 float delta1 = playerpos[1] - projectionpos[1];
826 if ( delta1 > DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF || delta1 < -DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF )
828 #ifdef DIAG_DEVELOPER
829 DebugText(
"HeightPlacementCheck(must be true): ",
true,
false,
" | Height difference between item and player is larger than " + DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF);
834 #ifdef DIAG_DEVELOPER
835 DebugText(
"HeightPlacementCheck(must be true): ",
true,
true);
847 g_Game.SurfaceUnderObject(m_Projection, type, liquid);
851 #ifdef DIAG_DEVELOPER
852 DebugText(
"IsUnderwater: ",
false,
true,
" | Surface under object is water");
858 vector left_close = m_Projection.CoordToParent( GetLeftCloseProjectionVector() );
859 vector right_close = m_Projection.CoordToParent( GetRightCloseProjectionVector() );
860 vector left_far = m_Projection.CoordToParent( GetLeftFarProjectionVector() );
861 vector right_far = m_Projection.CoordToParent( GetRightFarProjectionVector() );
862 bool surface_sea_water = IsSurfaceSea(left_close) || IsSurfaceSea(right_close) || IsSurfaceSea(left_far) || IsSurfaceSea(right_far);
864 #ifdef DIAG_DEVELOPER
866 float lc =
g_Game.GetWaterDepth(left_close);
867 float rc =
g_Game.GetWaterDepth(right_close);
868 float lf =
g_Game.GetWaterDepth(left_far);
869 float rf =
g_Game.GetWaterDepth(right_far);
870 bool isTrue = (lc > 0 || rc > 0 || lf > 0 || rf > 0 || surface_sea_water);
871 DebugText(
"IsUnderwater: ",
false, isTrue,
" surface_sea_water: " + surface_sea_water +
" | (all must be less than zero) | lc: " + lc +
" | rc: " + rc +
" | lf: " + lf +
" | rf: " + rf);
875 array<bool> conditions = {lc <= 0, rc <= 0, lf <= 0, rf <= 0};
876 DrawBaseSpheres(conditions);
880 return (surface_sea_water ||
g_Game.GetWaterDepth(left_close) > 0 ||
g_Game.GetWaterDepth(right_close) > 0 ||
g_Game.GetWaterDepth(left_far) > 0 ||
g_Game.GetWaterDepth(right_far) > 0);
887 vector fromHeightOffset =
"0 0.3 0";
888 vector toHeightOffset =
"0 1 0";
890 vector from_left_close = m_Projection.CoordToParent( GetLeftCloseProjectionVector() ) + fromHeightOffset;
891 vector to_left_close_down = from_left_close + toHeightOffset;
893 vector from_right_close = m_Projection.CoordToParent( GetRightCloseProjectionVector() ) + fromHeightOffset;
894 vector to_right_close_down = from_right_close + toHeightOffset;
896 vector from_left_far = m_Projection.CoordToParent( GetLeftFarProjectionVector() ) + fromHeightOffset;
897 vector to_left_far_down = from_left_far + toHeightOffset;
899 vector from_right_far = m_Projection.CoordToParent( GetRightFarProjectionVector() ) + fromHeightOffset;
900 vector to_right_far_down = from_right_far + toHeightOffset;
902 vector contact_pos_left_close;
903 vector contact_pos_right_close;
904 vector contact_pos_left_far;
905 vector contact_pos_right_far;
907 vector contact_dir_left_close;
908 vector contact_dir_right_close;
909 vector contact_dir_left_far;
910 vector contact_dir_right_far;
912 int contact_component_left_close;
913 int contact_component_right_close;
914 int contact_component_left_far;
915 int contact_component_right_far;
917 #ifdef DIAG_DEVELOPER
919 set<Object> lcO =
new set<Object>();
920 set<Object> rcO =
new set<Object>();
921 set<Object> lfO =
new set<Object>();
922 set<Object> rfO =
new set<Object>();
923 bool lc =
DayZPhysics.RaycastRV( from_left_close, to_left_close_down, contact_pos_left_close, contact_dir_left_close, contact_component_left_close, lcO, m_Projection, m_Projection,
false,
true, ObjIntersectFire );
924 bool rc =
DayZPhysics.RaycastRV( from_right_close, to_right_close_down, contact_pos_right_close, contact_dir_right_close, contact_component_right_close, rcO, m_Projection, m_Projection,
false,
true, ObjIntersectFire );
925 bool lf =
DayZPhysics.RaycastRV( from_left_far, to_left_far_down, contact_pos_left_far, contact_dir_left_far, contact_component_left_far, lfO, m_Projection, m_Projection,
false,
true, ObjIntersectFire );
926 bool rf =
DayZPhysics.RaycastRV( from_right_far, to_right_far_down, contact_pos_right_far, contact_dir_right_far, contact_component_right_far, rfO, m_Projection, m_Projection,
false,
true, ObjIntersectFire );
927 bool isTrue = ( lc || rc || lf || rf );
941 text +=
" | lcO: " + lcO[0];
943 text +=
" | rcO: " + rcO[0];
945 text +=
" | lfO: " + lfO[0];
947 text +=
" | rfO: " + rfO[0];
950 DrawBaseSpheres(conditions);
952 DebugText(
"IsInTerrain: ",
false, isTrue, text);
955 if (
DayZPhysics.RaycastRV( from_left_close, to_left_close_down, contact_pos_left_close, contact_dir_left_close, contact_component_left_close, NULL, m_Projection, m_Projection,
false,
true, ObjIntersectFire ))
958 if (
DayZPhysics.RaycastRV( from_right_close, to_right_close_down, contact_pos_right_close, contact_dir_right_close, contact_component_right_close, NULL,m_Projection, m_Projection,
false,
true, ObjIntersectFire ))
961 if (
DayZPhysics.RaycastRV( from_left_far, to_left_far_down, contact_pos_left_far, contact_dir_left_far, contact_component_left_far, NULL, m_Projection, m_Projection,
false,
true, ObjIntersectFire ))
964 if (
DayZPhysics.RaycastRV( from_right_far, to_right_far_down, contact_pos_right_far, contact_dir_right_far, contact_component_right_far, NULL, m_Projection, m_Projection,
false,
true, ObjIntersectFire ))
970 void CheckPowerSource()
976 m_Parent.GetCompEM().UpdatePlugState();
981 if (!
m_Parent.GetCompEM().IsPlugged())
990 if (entity_for_placing.IsInherited(
TentBase) || entity_for_placing.IsBasebuildingKit() )
992 return entity_for_placing;
995 if (m_Projection.IsInherited(GardenPlotPlacing))
998 return entity_for_placing;
1002 if( !GetProjectionEntity().IsKindOf(
m_Parent.GetType() ))
1004 Class.CastTo(entity_for_placing,
GetGame().CreateObjectEx( m_Projection.GetType(), m_Projection.GetPosition(),
ECE_OBJECT_SWAP ));
1007 return entity_for_placing;
1010 protected void GetProjectionCollisionBox( out
vector min_max[2] )
1012 if (!m_Projection.GetCollisionBox( min_max ) && m_Projection.MemoryPointExists(
"box_placing_min"))
1014 min_max[0] = m_Projection.GetMemoryPointPos(
"box_placing_min" );
1015 min_max[1] = m_Projection.GetMemoryPointPos(
"box_placing_max" );
1021 protected vector GetCollisionBoxSize(
vector min_max[2] )
1025 box_size[0] = min_max[1][0] - min_max[0][0];
1026 box_size[2] = min_max[1][2] - min_max[0][2];
1027 box_size[1] = min_max[1][1] - min_max[0][1];
1032 vector GetLeftCloseProjectionVector()
1035 GetProjectionCollisionBox( min_max );
1040 vector GetRightCloseProjectionVector()
1043 GetProjectionCollisionBox( min_max );
1044 min_max[1][1] = min_max[0][1];
1045 min_max[1][2] = min_max[0][2];
1050 vector GetLeftFarProjectionVector()
1053 GetProjectionCollisionBox( min_max );
1054 min_max[0][2] = min_max[1][2];
1059 vector GetRightFarProjectionVector()
1062 GetProjectionCollisionBox( min_max );
1063 min_max[1][1] = min_max[0][1];
1069 bool IsSurfaceWater(
vector position )
1072 return game.SurfaceIsSea( position[0], position[2] ) || game.SurfaceIsPond( position[0], position[2] );
1075 bool IsSurfaceSea(
vector position )
1078 return game.SurfaceIsSea( position[0], position[2] );
1083 float minProjectionDistance;
1084 float maxProjectionDistance;
1085 m_ContactDir =
vector.Zero;
1087 float projectionRadius = GetProjectionRadius();
1088 float cameraToPlayerDistance =
vector.Distance(
GetGame().GetCurrentCameraPosition(), player.GetPosition());
1090 if (projectionRadius < SMALL_PROJECTION_RADIUS)
1092 minProjectionDistance = SMALL_PROJECTION_RADIUS;
1093 maxProjectionDistance = SMALL_PROJECTION_RADIUS * 2;
1097 minProjectionDistance = projectionRadius;
1098 maxProjectionDistance = projectionRadius * 2;
1099 maxProjectionDistance =
Math.Clamp(maxProjectionDistance, SMALL_PROJECTION_RADIUS, LARGE_PROJECTION_DISTANCE_LIMIT);
1107 MiscGameplayFunctions.GetHeadBonePos(player,head_pos);
1108 float dist =
vector.Distance(head_pos,from);
1109 from = from +
GetGame().GetCurrentCameraDirection() * dist;
1112 vector to = from + (
GetGame().GetCurrentCameraDirection() * (maxProjectionDistance + cameraToPlayerDistance));
1114 set<Object> hitObjects =
new set<Object>();
1116 DayZPhysics.RaycastRV(from, to, contactPosition, m_ContactDir, m_ContactComponent, hitObjects, player, m_Projection,
false,
false, ObjIntersectFire);
1118 bool contactHitProcessed =
false;
1122 if (hitObjects.Count() > 0)
1124 if (hitObjects[0].IsInherited(Watchtower))
1126 contactHitProcessed =
true;
1127 contactPosition = CorrectForWatchtower(m_ContactComponent, contactPosition, player, hitObjects[0]);
1130 if (!contactHitProcessed && hitObjects[0].IsInherited(
InventoryItem))
1131 contactPosition = hitObjects[0].GetPosition();
1135 static const float raycastOriginOffsetOnFail = 0.25;
1136 static const float minDistFromStart = 0.01;
1138 if ((hitObjects.Count() > 0) && (
vector.DistanceSq(from, contactPosition) < minDistFromStart))
1140 from = contactPosition +
GetGame().GetCurrentCameraDirection() * raycastOriginOffsetOnFail;
1141 DayZPhysics.RaycastRV(from, to, contactPosition, m_ContactDir, m_ContactComponent, hitObjects, player, m_Projection,
false,
false, ObjIntersectFire);
1144 bool isFloating = SetHologramPosition(player.GetPosition(), minProjectionDistance, maxProjectionDistance, contactPosition);
1145 SetIsFloating(isFloating);
1147 #ifdef DIAG_DEVELOPER
1148 DrawDebugArrow(minProjectionDistance, maxProjectionDistance);
1155 m_FromAdjusted = from;
1157 return contactPosition;
1168 protected bool SetHologramPosition(
vector startPosition,
float minProjectionDistance,
float maxProjectionDistance, inout
vector contactPosition)
1170 float playerToProjectionDistance =
vector.Distance(startPosition, contactPosition);
1171 vector playerToProjection;
1173 #ifdef DIAG_DEVELOPER
1174 DebugText(
"SetHologramPosition::startPosition: ",
false, m_IsHidden,
string.Format(
" | %1", startPosition));
1175 DebugText(
"SetHologramPosition::contactPosition [in]: ",
false, m_IsHidden,
string.Format(
" | %1", contactPosition));
1176 DebugText(
"SetHologramPosition::minProjectionDistance: ",
false, m_IsHidden,
string.Format(
" | %1", minProjectionDistance));
1177 DebugText(
"SetHologramPosition::maxProjectionDistance: ",
false, m_IsHidden,
string.Format(
" | %1", maxProjectionDistance));
1178 DebugText(
"SetHologramPosition::playerToProjectionDistance: ",
false, m_IsHidden,
string.Format(
" | %1", playerToProjectionDistance));
1182 if (playerToProjectionDistance <= minProjectionDistance)
1184 playerToProjection = contactPosition - startPosition;
1185 playerToProjection.Normalize();
1187 playerToProjection[1] = playerToProjection[1] + PROJECTION_TRANSITION_MIN;
1189 contactPosition = startPosition + (playerToProjection * minProjectionDistance);
1191 #ifdef DIAG_DEVELOPER
1192 DebugText(
"SetHologramPosition::contactPosition[out] (< minProjectDistance): ",
false, m_IsHidden,
string.Format(
" | %1", contactPosition));
1198 else if (playerToProjectionDistance >= maxProjectionDistance)
1200 playerToProjection = contactPosition - startPosition;
1201 playerToProjection.Normalize();
1203 playerToProjection[1] = playerToProjection[1] + PROJECTION_TRANSITION_MAX;
1205 contactPosition = startPosition + (playerToProjection * maxProjectionDistance);
1207 #ifdef DIAG_DEVELOPER
1208 DebugText(
"SetHologramPosition::contactPosition[out] (< maxProjectionDistance): ",
false, m_IsHidden,
string.Format(
" | %1", contactPosition));
1217 bool IsFenceOrWatchtowerKit()
1225 if (m_WatchtowerIgnoreComponentNames.Find(hitObject.GetActionComponentName(contactComponent,
LOD.NAME_VIEW)) != -1 )
1226 contactPos[1] = hitObject.GetActionComponentPosition(contactComponent,
LOD.NAME_VIEW)[1];
1232 bool IsProjectionTrap()
1237 float GetProjectionDiameter()
1244 GetProjectionCollisionBox( min_max );
1245 diagonal = GetCollisionBoxSize( min_max );
1246 diameter = diagonal.Length();
1251 float GetProjectionRadius()
1258 GetProjectionCollisionBox( min_max );
1259 diagonal = GetCollisionBoxSize( min_max );
1260 diameter = diagonal.Length();
1261 radius = diameter / 2;
1266 void SetUpdatePosition(
bool state )
1268 m_UpdatePosition = state;
1271 bool GetUpdatePosition()
1273 return m_UpdatePosition;
1281 void SetProjectionEntity(
EntityAI projection )
1283 m_Projection = projection;
1288 return m_Projection;
1291 void SetIsFloating(
bool is_floating )
1293 m_IsFloating = is_floating;
1296 void SetIsColliding(
bool is_colliding )
1298 #ifdef DIAG_DEVELOPER
1299 DebugText(
"Is colliding: ",
false, is_colliding, m_CollisionDetails);
1301 m_IsColliding = is_colliding;
1304 void SetIsHidden(
bool is_hidden )
1306 m_IsHidden = is_hidden;
1309 void SetIsCollidingPlayer(
bool is_colliding )
1311 m_IsCollidingPlayer = is_colliding;
1314 void SetIsCollidingGPlot(
bool is_colliding_gplot )
1316 m_IsCollidingGPlot = is_colliding_gplot;
1321 #ifdef DIAG_DEVELOPER
1322 DebugText(
"IsFloating: ",
false, m_IsFloating);
1324 return m_IsFloating;
1329 return m_IsColliding;
1334 #ifdef DIAG_DEVELOPER
1335 DebugText(
"IsHidden: ",
false, m_IsHidden);
1340 bool IsCollidingPlayer()
1344 #ifdef DIAG_DEVELOPER
1345 DebugText(
"IsCollidingPlayer: ",
false, m_IsCollidingPlayer);
1347 return m_IsCollidingPlayer;
1350 void SetProjectionPosition(
vector position)
1352 m_Projection.SetPosition( position );
1356 m_Projection.SetPosition(SetOnGround(position));
1360 void SetProjectionOrientation(
vector orientation)
1362 m_Projection.SetOrientation(orientation);
1365 vector GetProjectionRotation()
1370 void AddProjectionRotation(
float addition )
1372 m_Rotation[0] = m_Rotation[0] + addition;
1375 void SubtractProjectionRotation(
float subtraction )
1377 m_Rotation[0] = m_Rotation[0] - subtraction;
1384 vector player_to_projection_vector;
1385 float projection_diameter = GetProjectionDiameter();
1387 ground =
Vector(0, -
Math.Max(projection_diameter, SMALL_PROJECTION_GROUND), 0);
1389 vector to = from + ground;
1396 if (
DayZPhysics.RaycastRVProxy(rayInput, results))
1399 for (
int i = 0; i < results.Count(); i++)
1401 res = results.Get(i);
1402 if (res.entry || (!res.obj && !res.parent))
1404 contact_pos = res.pos;
1411 if (contact_pos !=
"0 0 0")
1415 int check_component = -1;
1416 set<Object> hit_object =
new set<Object>;
1418 to[1] = to[1] + 0.1;
1419 from = m_FromAdjusted;
1421 if (
DayZPhysics.RaycastRV(from, to, check_pos, check_dir, check_component, hit_object,
null,
m_Player,
false,
false, ObjIntersectFire))
1423 if ((hit_object.Count() > 0)&& (!hit_object[0].IsInherited(Watchtower) || (hit_object[0].IsInherited(Watchtower) && (m_WatchtowerIgnoreComponentNames.Find(hit_object[0].GetActionComponentName(check_component,
LOD.NAME_VIEW)) == -1))))
1425 contact_pos =
"0 0 0";
1430 HideWhenClose(contact_pos);
1440 if( cam_dir[1] > LOOKING_TO_SKY )
1448 vector GetProjectionPosition()
1451 return m_Projection.GetPosition();
1456 vector GetProjectionOrientation()
1459 return m_Projection.GetOrientation();
1464 vector GetDefaultOrientation()
1466 m_DefaultOrientation =
GetGame().GetCurrentCameraDirection().VectorToAngles();
1467 m_DefaultOrientation[1] = 0;
1469 if (!GetParentEntity().PlacementCanBeRotated())
1471 m_DefaultOrientation =
vector.Zero;
1474 return m_DefaultOrientation;
1477 int GetHiddenSelection(
string selection )
1479 int idx = m_Projection.GetHiddenSelectionIndex(selection);
1488 void SetSelectionToRefresh(
string selection )
1490 m_SelectionsToRefresh.Insert( selection );
1496 foreach (
string s : selection)
1497 m_SelectionsToRefresh.Insert(s);
1500 void RefreshVisual()
1504 static const string textureName =
"#(argb,8,8,3)color(0.5,0.5,0.5,0.75,ca)";
1506 int hidden_selection = 0;
1507 string selection_to_refresh;
1508 string config_material =
string.Format(
"CfgVehicles %1 hologramMaterial", m_Projection.GetType());
1509 string hologram_material =
GetGame().ConfigGetTextOut(config_material);
1510 string config_model =
string.Format(
"CfgVehicles %1 hologramMaterialPath", m_Projection.GetType());
1511 string hologram_material_path =
string.Format(
"%1\\%2%3",
GetGame().ConfigGetTextOut(config_model), hologram_material, CorrectMaterialPathName());
1513 for (
int i = 0; i < m_SelectionsToRefresh.Count(); ++i)
1515 selection_to_refresh = m_SelectionsToRefresh.Get(i);
1516 hidden_selection = GetHiddenSelection(selection_to_refresh);
1517 m_Projection.SetObjectTexture(hidden_selection, textureName);
1518 m_Projection.SetObjectMaterial(hidden_selection, hologram_material_path);
1524 string CorrectMaterialPathName()
1526 if (IsColliding() || IsFloating())
1528 return SUFFIX_MATERIAL_UNDEPLOYABLE;
1530 else if (
m_Parent.HasEnergyManager())
1533 string SEL_CORD_PLUGGED =
m_Parent.GetCompEM().SEL_CORD_PLUGGED;
1534 string SEL_CORD_FOLDED =
m_Parent.GetCompEM().SEL_CORD_FOLDED;
1536 if (comp_em.IsPlugged() && comp_em.IsEnergySourceAtReach(GetProjectionPosition()))
1538 m_Projection.SetAnimationPhase(SEL_CORD_PLUGGED, 0);
1539 m_Projection.SetAnimationPhase(SEL_CORD_FOLDED, 1);
1540 return SUFFIX_MATERIAL_POWERED;
1544 m_Projection.SetAnimationPhase(SEL_CORD_PLUGGED, 1);
1545 m_Projection.SetAnimationPhase(SEL_CORD_FOLDED, 0);
1549 return SUFFIX_MATERIAL_DEPLOYABLE;
1552 private bool IsRestrictedFromAdvancedPlacing()
1575 protected int m_TriggerUpdateMs;
1579 override void OnEnter(
Object obj )
1585 m_TriggerUpdateMs = 50;
1589 override void OnLeave(
Object obj )
1600 super.UpdateInsiders(m_TriggerUpdateMs);