DayZ Scripts
v1.21.156300 ยท Jun 20, 2023
 
Loading...
Searching...
No Matches
Hologram.c
Go to the documentation of this file.
2{
3 #ifdef SERVER
4 protected const int SPAWN_FLAGS = ECE_CREATEPHYSICS;
5 #else
6 protected const int SPAWN_FLAGS = ECE_LOCAL;
7 #endif
8
9 protected const string SUFFIX_MATERIAL_DEPLOYABLE = "_deployable.rvmat";
10 protected const string SUFFIX_MATERIAL_UNDEPLOYABLE = "_undeployable.rvmat";
11 protected const string SUFFIX_MATERIAL_POWERED = "_powered.rvmat";
12
13 protected ItemBase m_Parent;
16 protected ProjectionTrigger m_ProjectionTrigger;
17 protected string m_ProjectionTypename;
18
19 protected bool m_IsColliding;
20 protected bool m_IsCollidingGPlot;
21 protected bool m_IsSlope;
22 protected bool m_IsCollidingPlayer;
23 protected bool m_IsFloating;
24 protected bool m_UpdatePosition;
25 protected bool m_IsHidden;
26
28 protected vector m_Rotation;
32 protected const string ANIMATION_PLACING = "Placing";
33 protected const string ANIMATION_INVENTORY = "Inventory";
34 protected const string SELECTION_PLACING = "placing";
35 protected const string SELECTION_INVENTORY = "inventory";
36
37 protected const float SMALL_PROJECTION_RADIUS = 1;
38 protected const float SMALL_PROJECTION_GROUND = 2;
39 protected const float DISTANCE_SMALL_PROJECTION = 1;
40 protected const float LARGE_PROJECTION_DISTANCE_LIMIT = 6;
41 protected const float PROJECTION_TRANSITION_MIN = 1;
42 protected const float PROJECTION_TRANSITION_MAX = 0.25;
43 protected const float LOOKING_TO_SKY = 0.75;
44 static const float DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF = 1.5;
45
46 protected float m_SlopeTolerance;
47 protected bool m_AlignToTerrain;
49 protected int m_ContactComponent;
50
51 protected ref set<string> m_SelectionsToRefresh = new set<string>;
52
53 // Watchtower correction variables
54 // These watchtower component names should be corrected when colliding with them as they are supposed to be "trigger boxes", not colliders
56
57 // These watchtower components are supposed to be trigger boxes, but should block placement on them (currently only the boxes above the stairs)
59
60 void Hologram(PlayerBase player, vector pos, ItemBase item)
61 {
62 m_Player = player;
63 m_Parent = item;
64 m_Projection = NULL;
66 m_UpdatePosition = true;
67 m_Rotation = "0 0 0";
69 m_FromAdjusted = "0 0 0";
70
71 // If the static names are empty, generate the needed names
72 // Refer to their definitions to see why these are required
73 if (m_WatchtowerIgnoreComponentNames.Count() == 0)
74 {
75 string baseStringBegin = Watchtower.BASE_VIEW_NAME;
76 string baseIgnoreStringEnd = Watchtower.BASE_WALL_NAME;
77 int floors = Watchtower.MAX_WATCHTOWER_FLOORS;
78 int walls = Watchtower.MAX_WATCHTOWER_WALLS;
79 string compName;
80
81 for (int i = 1; i < floors + 1; ++i)
82 {
83 compName = baseStringBegin + i.ToString();
84 for (int j = 1; j < walls + 1; ++j)
85 m_WatchtowerIgnoreComponentNames.Insert(compName + baseIgnoreStringEnd + j.ToString());
86
87 if (i != 1)
88 m_WatchtowerBlockedComponentNames.Insert(compName);
89 else
90 m_WatchtowerIgnoreComponentNames.Insert(compName);
91
92 }
93 }
94
95 string configPathProjectionTypename = string.Format("CfgVehicles %1 projectionTypename", m_Parent.GetType());
96 if (GetGame().ConfigIsExisting(configPathProjectionTypename))
97 {
98 m_ProjectionTypename = GetGame().ConfigGetTextOut(configPathProjectionTypename);
99 }
100
101 EntityAI projectionEntity;
102 if (GetGame().IsMultiplayer() && GetGame().IsServer())
103 {
104 projectionEntity = EntityAI.Cast(GetGame().CreateObjectEx(ProjectionBasedOnParent(), pos, ECE_PLACE_ON_SURFACE));
105 projectionEntity.SetAllowDamage(false);
106 SetProjectionEntity(projectionEntity);
108 }
109 else
110 {
111 projectionEntity = EntityAI.Cast(GetGame().CreateObjectEx(ProjectionBasedOnParent(), pos, ECE_TRACE|ECE_LOCAL));
112 if (projectionEntity == null)
113 {
114 ErrorEx(string.Format("Cannot create hologram entity from config class %1", ProjectionBasedOnParent()), ErrorExSeverity.WARNING);
115 return;
116 }
117
118 SetProjectionEntity(projectionEntity);
122 }
123
124 if (ItemBase.Cast(projectionEntity))
125 {
126 ItemBase.Cast(GetProjectionEntity()).SetIsHologram(true);
127 }
128
129 string configPathSlope = string.Format("CfgVehicles %1 slopeTolerance", GetProjectionEntity().GetType());
130 if (GetGame().ConfigIsExisting(configPathSlope))
131 {
132 m_SlopeTolerance = GetGame().ConfigGetFloat(configPathSlope);
133 }
134
135 string configPathAlign = string.Format("CfgVehicles %1 alignHologramToTerain", GetProjectionEntity().GetType());
136 if (GetGame().ConfigIsExisting(configPathAlign))
137 {
138 m_AlignToTerrain = GetGame().ConfigGetInt(configPathAlign);
139 }
140
141 string configPathOrientationLimit = string.Format("CfgVehicles %1 yawPitchRollLimit", GetProjectionEntity().GetType());
142 if (GetGame().ConfigIsExisting(configPathOrientationLimit))
143 {
144 m_YawPitchRollLimit = GetGame().ConfigGetVector(configPathOrientationLimit);
145 }
146 }
147
149 {
150 if (GetGame())
151 {
152 if (m_Projection)
153 {
155 }
156
158 {
160 }
161 }
162
163 #ifdef DIAG_DEVELOPER
165 #endif
166 }
167
169 {
170 if ( m_Projection.HasAnimation( ANIMATION_PLACING ) )
171 {
172 m_Projection.SetAnimationPhase( ANIMATION_PLACING, 0 );
174
175 if ( m_Projection.HasAnimation( ANIMATION_INVENTORY ) )
176 {
177 m_Projection.SetAnimationPhase( ANIMATION_INVENTORY, 1 );
178 }
179 }
180 else
181 {
184 }
185 }
186
187 // Updates selections on hologram object so they reflect the state of the parent object's selections.
189 {
190 string cfg_access = "CfgVehicles " + m_Projection.GetType() + " AnimationSources ";
191
192 if ( GetGame().ConfigIsExisting(cfg_access) )
193 {
194 int cfg_access_count = g_Game.ConfigGetChildrenCount(cfg_access);
195
196 for ( int i = 0; i < cfg_access_count; ++i )
197 {
198 string found_anim;
199 GetGame().ConfigGetChildName(cfg_access, i, found_anim);
200
201 float anim_phase = m_Parent.GetAnimationPhase(found_anim);
202 m_Projection.SetAnimationPhase(found_anim, anim_phase);
203 }
204 }
205 }
206
208 {
210 }
211
213 {
215 if (m_ProjectionTypename != "")
216 {
218 }
219
220 if (!item)
221 {
222 return "";
223 }
224
225 if (item.CanMakeGardenplot())
226 {
227 return "GardenPlotPlacing";
228 }
229
230 //Camping & Base building
231 if (item.IsInherited( TentBase ) || item.IsBasebuildingKit())
232 {
233 return item.GetType() + "Placing";
234 }
235
236 return item.GetType();
237 }
238
240 static bool DoesHaveProjection(ItemBase item)
241 {
242 return item && (item.IsDeployable() || item.CanMakeGardenplot() || item.IsInherited(DeployableContainer_Base));
243 }
244
245 // update loop for visuals and collisions of the hologram
246 void UpdateHologram( float timeslice )
247 {
248 if ( !m_Parent )
249 {
250 m_Player.TogglePlacingLocal();
251
252 return;
253 }
254
255 if ( m_Player.IsSwimming() || m_Player.IsClimbingLadder() || m_Player.IsRaised() || m_Player.IsClimbing() || m_Player.IsRestrained() || m_Player.IsUnconscious() )
256 {
257 m_Player.TogglePlacingLocal();
258
259 return;
260 }
261
262 if ( !GetUpdatePosition() )
263 {
264 return;
265 }
266
267
268 #ifdef DIAG_DEVELOPER
269 DebugConfigValues();
271 #endif
272
273 // update hologram position
276
281
282 m_Projection.OnHologramBeingPlaced( m_Player );
283 }
284
286 {
287 vector y_p_r;
288
289 if ( m_AlignToTerrain )
290 {
291 vector projection_orientation_angles = GetDefaultOrientation() + GetProjectionRotation();
292 vector mat0[3];
293 vector mat1[3];
294 vector mat2[3];
295 vector projection_position = m_Projection.GetPosition();
296 vector normal;
297
298 if ( m_ContactDir.Length() > 0 )
299 {
300 normal = m_ContactDir;
301 }
302 else
303 {
304 normal = GetGame().SurfaceGetNormal( projection_position[0], projection_position[2] );
305 }
306
307 vector angles = normal.VectorToAngles();
308 angles[1] = angles[1] + 270;
309
310 angles[0] = Math.Clamp( angles[0], 0, 360 );
311 angles[1] = Math.Clamp( angles[1], 0, 360 );
312 angles[2] = Math.Clamp( angles[2], 0, 360 );
313
314 projection_orientation_angles[0] = projection_orientation_angles[0] + ( 360 - angles[0] );
315
316 Math3D.YawPitchRollMatrix( projection_orientation_angles, mat0 );
317 Math3D.YawPitchRollMatrix( angles, mat1 );
318 Math3D.MatrixMultiply3( mat1, mat0, mat2 );
319
320 y_p_r = Math3D.MatrixToAngles( mat2 );
321 }
322 else
323 {
325
326 if ( y_p_r[0] > 180 )
327 {
328 y_p_r[0] = y_p_r[0] - 360;
329 }
330
331 if ( y_p_r[0] < -180 )
332 {
333 y_p_r[0] = y_p_r[0] + 360;
334 }
335 }
336
337 return SmoothProjectionMovement( y_p_r, timeslice );
338 }
339
340 vector SmoothProjectionMovement( vector y_p_r, float timeslice )
341 {
342 if ( m_y_p_r_previous )
343 {
344 if ( Math.AbsFloat( y_p_r[0] - m_y_p_r_previous[0] ) > 100 )
345 {
346 if ( y_p_r[0] > 0 )
347 {
348 m_y_p_r_previous[0] = m_y_p_r_previous[0] + 360;
349 }
350
351 if ( y_p_r[0] < 0 )
352 {
354 }
355 }
356
357 y_p_r[0] = Math.Lerp( m_y_p_r_previous[0], y_p_r[0], 15 * timeslice );
358 y_p_r[1] = Math.Lerp( m_y_p_r_previous[1], y_p_r[1], 15 * timeslice );
359 y_p_r[2] = Math.Lerp( m_y_p_r_previous[2], y_p_r[2], 15 * timeslice );
360 }
361
362 m_y_p_r_previous = y_p_r;
363
364 return y_p_r;
365 }
366
368 {
369 Class.CastTo(m_ProjectionTrigger, g_Game.CreateObjectEx("ProjectionTrigger", GetProjectionPosition(), SPAWN_FLAGS));
370
372 m_ProjectionTrigger.SetParentObject(this);
373 m_ProjectionTrigger.SetParentOwner(m_Player);
374
376 }
377
379 {
380 vector min_max[2];
381 GetProjectionCollisionBox( min_max );
382
385 m_ProjectionTrigger.SetExtents(min_max[0], min_max[1]);
386 }
387
388 #ifdef DIAG_DEVELOPER
389 void DebugText(string header, bool mustBeTrue = false, bool condition = true, string info = "")
390 {
391 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
392 {
393 int color = 0xFFFFFFFF;
394
395 if (mustBeTrue && !condition || !mustBeTrue && condition)
396 color = COLOR_RED;
397
398 string text = header + condition + info;
399 DbgUI.ColoredText(color, text);
400 }
401 }
402
403 protected float m_PitchOverride;
404 protected float m_RollOverride;
405 void DebugConfigValues()
406 {
407 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
408 {
409 m_PitchOverride = m_YawPitchRollLimit[1];
410 m_RollOverride = m_YawPitchRollLimit[2];
411
412 DbgUI.InputFloat("slopeTolerance override", m_SlopeTolerance);
413 DbgUI.SameLine();
414 DbgUI.InputFloat("pitch limit override", m_PitchOverride);
415 DbgUI.SameLine();
416 DbgUI.InputFloat("roll limit override", m_RollOverride);
417
418 m_YawPitchRollLimit[1] = m_PitchOverride;
419 m_YawPitchRollLimit[2] = m_RollOverride;
420 }
421 }
422 #endif
423
424 void EvaluateCollision(ItemBase action_item = null)
425 {
427 {
428 SetIsColliding( true );
429 }
430 else if ( m_Projection.IsInherited( TrapSpawnBase ))
431 {
432 #ifdef DIAG_DEVELOPER
433 DebugText("Inherits from TrapSpawnBase, checking IsPlaceableAtposition", true);
434 #endif
435 TrapSpawnBase trap_spawn_base;
436 Class.CastTo( trap_spawn_base, m_Projection );
437 SetIsColliding( !trap_spawn_base.IsPlaceableAtPosition( m_Projection.GetPosition() ) );
438 }
439 else if ( m_Projection.IsInherited( TrapBase ))
440 {
441 #ifdef DIAG_DEVELOPER
442 DebugText("Inherits from TrapBase, checking IsPlaceableAtposition", true);
443 #endif
444 TrapBase trap_base;
445 Class.CastTo(trap_base, m_Projection);
446 SetIsColliding( !trap_base.IsPlaceableAtPosition( m_Projection.GetPosition() ) );
447 }
448 else
449 {
450 SetIsColliding( false );
451 }
452 }
453
455 {
457 return false;
458 if (GetGame().IsServer() && GetGame().IsMultiplayer())
459 return false;
460
461 //Some locations allow you to look up and attempt placing the hologram on the bottom side of a floor - most notably the floors of a watchtower
462 //This check also prevents some very unnatural placements
463
464 bool b1 = m_Projection.GetPosition()[1] > GetGame().GetCurrentCameraPosition()[1];
465 bool b2 = false;
466 #ifdef DIAG_DEVELOPER
467 vector from, to;
468 #endif
469 if (m_Projection.DoPlacingHeightCheck())
470 {
471 b2 = MiscGameplayFunctions.IsUnderRoofEx(m_Projection, GameConstants.ROOF_CHECK_RAYCAST_DIST, ObjIntersectFire);
472 #ifdef DIAG_DEVELOPER
473 MiscGameplayFunctions.IsUnderRoofFromToCalculation(m_Projection, from, to);
474 DrawArrow(from, to, !b2);
475 #endif
476 }
477
478 #ifdef DIAG_DEVELOPER
479 DebugText("IsClippingRoof: ", false, b1, " | (projection height) " + m_Projection.GetPosition()[1] + " > (camera height) " + GetGame().GetCurrentCameraPosition()[1]);
480 DebugText("IsClippingRoof: ", false, b2, " | (DoPlacingHeightCheck) " + m_Projection.DoPlacingHeightCheck() + " && (IsUnderRoof) " + MiscGameplayFunctions.IsUnderRoof(m_Projection) + " | from: " + from[1] + " | to: " + to[1]);
481 #endif
482
483 return b1 || b2;
484 }
485
487 {
489 return false;
490 vector projection_orientation = m_Projection.GetOrientation();
491 bool isTrue = Math.AbsFloat( projection_orientation[1] ) > m_YawPitchRollLimit[1] || Math.AbsFloat( projection_orientation[2] ) > m_YawPitchRollLimit[2];
492 #ifdef DIAG_DEVELOPER
493 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]);
494 #endif
495
496 return isTrue;
497 }
498
499 #ifdef DIAG_DEVELOPER
500 protected Shape m_CollisionBox;
501 protected void DrawDebugCollisionBox( vector min_max[2], int color )
502 {
503 vector mat[4];
504 m_Projection.GetTransform( mat );
505 m_CollisionBox = Debug.DrawBox( min_max[0], min_max[1], color );
506 m_CollisionBox.SetMatrix( mat );
507 }
508
509 protected void DestroyDebugCollisionBox()
510 {
511 if ( m_CollisionBox )
512 {
513 m_CollisionBox.Destroy();
514 m_CollisionBox = NULL;
515 }
516 }
517 #endif
518
519 bool IsCollidingBBox(ItemBase action_item = null)
520 {
522 return false;
523
524 vector center;
525 vector relativeOffset; //we need to lift BBox, because it is calculated from the bottom of projection, and not from the middle
526 vector absoluteOffset = "0 0.01 0"; //we need to lift BBox even more, because it colliddes with house floors due to various reasons (probably geometry or float imperfections)
527 vector orientation = GetProjectionOrientation();
528 vector edgeLength;
529 vector minMax[2];
530 array<Object> excludedObjects = new array<Object>();
531 array<Object> collidedObjects = new array<Object>();
532
534 relativeOffset[1] = (minMax[1][1] - minMax[0][1]) * 0.5;
535 center = m_Projection.GetPosition() + relativeOffset + absoluteOffset;
536 edgeLength = GetCollisionBoxSize(minMax);
537 excludedObjects.Insert(m_Projection);
538 excludedObjects.Insert(m_Player);
539
540 if (action_item)
541 excludedObjects.Insert(action_item);
542
543 //add is construction check
544 // Base building objects behave in a way that causes this test to generate false positives
545 bool isTrue = GetGame().IsBoxCollidingGeometry(center, orientation, edgeLength, ObjIntersectFire, ObjIntersectGeom, excludedObjects, collidedObjects);
546 #ifdef DIAG_DEVELOPER
547 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
548 {
549 string text = "";
550 foreach (Object object: collidedObjects)
551 text += " | " + Object.GetDebugName(object);
552
553 DebugText("IsCollidingBBox: ", false, isTrue, text);
554
555 int color = 0x01FFFFFF;
556 if (isTrue)
557 color = 0x33F22613;
558
559 DrawDebugCollisionBox(minMax, color);
560 }
561 #endif
562
563 return isTrue;
564 }
565
567 {
568 //This function is not required to solve server-side fixes for clipping, saves calculations and potential false negatives
569 if (GetGame().IsServer() && GetGame().IsMultiplayer())
570 return true;
571
573 return true;
574
575 vector from_left_close = m_Projection.CoordToParent( GetLeftCloseProjectionVector() );
576 vector to_left_close_down = from_left_close + "0 -1 0";
577
578 vector from_right_close = m_Projection.CoordToParent( GetRightCloseProjectionVector() );
579 vector to_right_close_down = from_right_close + "0 -1 0";
580
581 vector from_left_far = m_Projection.CoordToParent( GetLeftFarProjectionVector() );
582 vector to_left_far_down = from_left_far + "0 -1 0";
583
584 vector from_right_far = m_Projection.CoordToParent( GetRightFarProjectionVector() );
585 vector to_right_far_down = from_right_far + "0 -1 0";
586
587 vector contact_pos_left_close;
588 vector contact_pos_right_close;
589 vector contact_pos_left_far;
590 vector contact_pos_right_far;
591 vector contact_dir_left_close;
592 vector contact_dir_right_close;
593 vector contact_dir_left_far;
594 vector contact_dir_right_far;
595 int contact_component_left_close;
596 int contact_component_right_close;
597 int contact_component_left_far;
598 int contact_component_right_far;
599 set<Object> results_left_close = new set<Object>;
600 set<Object> results_right_close = new set<Object>;
601 set<Object> results_left_far = new set<Object>;
602 set<Object> results_right_far = new set<Object>;
603 Object obj_left_close;
604 Object obj_right_close;
605 Object obj_left_far;
606 Object obj_right_far;
607
608 //Not sure what the intention here was before, but it boiled down to a very bloated version of what you see here right now
609 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 );
610 if (results_left_close.Count() > 0)
611 obj_left_close = results_left_close[results_left_close.Count() - 1];
612
613 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 );
614 if (results_right_close.Count() > 0)
615 obj_right_close = results_right_close[results_right_close.Count() - 1];
616
617 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 );
618 if (results_left_far.Count() > 0)
619 obj_left_far = results_left_far[results_left_far.Count() - 1];
620
621 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 );
622 if (results_right_far.Count() > 0)
623 obj_right_far = results_right_far[results_right_far.Count() - 1];
624
625 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 );
626 }
627
629 {
631 return false;
632
633 #ifdef DIAG_DEVELOPER
634 DebugText("IsCollidingGPlot: ", false, m_IsCollidingGPlot);
635 #endif
636
637 return m_IsCollidingGPlot;
638 }
639
641 {
642 vector origin = Vector(0, 0, 0);
643 bool isTrue = GetProjectionPosition() == origin;
644 #ifdef DIAG_DEVELOPER
645 DebugText("IsCollidingZeroPos: ", false, isTrue);
646 #endif
647
648 return isTrue;
649 }
650
653 {
654 ErrorEx("Deprecated check - do not use", ErrorExSeverity.WARNING);
655 return false;
656 }
657
658 //This function only takes one of the found objects since IsBaseIntact already verifies that all of them are either null or the same object
659 bool IsBaseStatic( Object objectToCheck )
660 {
661 //check if the object below hologram is dynamic object. Dynamic objects like barrels can be taken to hands
662 //and item which had been placed on top of them, would stay floating in the air
663 #ifdef DIAG_DEVELOPER
664 if (objectToCheck == null)
665 DebugText("IsBaseStatic(must be true): ", true, true, " | objectToCheck is null (this is good)");
666 else
667 DebugText("IsBaseStatic(must be true): ", true, IsObjectStatic(objectToCheck));
668 #endif
669 return objectToCheck == null || IsObjectStatic(objectToCheck);
670 }
671
673 {
674 return obj.IsBuilding() || obj.IsPlainObject() || (!m_Parent.IsInherited(KitBase) && obj.IsInherited(BaseBuildingBase) && (m_WatchtowerBlockedComponentNames.Find(obj.GetActionComponentName(m_ContactComponent, LOD.NAME_VIEW)) == -1));
675 }
676
677 bool IsBaseIntact( Object under_left_close, Object under_right_close, Object under_left_far, Object under_right_far )
678 {
679 bool isTrue = (under_left_close == under_right_close && under_right_close == under_left_far && under_left_far == under_right_far);
680 #ifdef DIAG_DEVELOPER
681 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));
682 if (!isTrue)
683 {
684 array<bool> conditions = new array<bool>();
685 conditions.Insert(under_left_close == null);
686 conditions.Insert(under_right_close == null);
687 conditions.Insert(under_left_far == null);
688 conditions.Insert(under_right_far == null);
689
690 int amountOfNull = 0;
691 if (!under_left_close)
692 ++amountOfNull;
693 if (!under_right_close)
694 ++amountOfNull;
695 if (!under_left_far)
696 ++amountOfNull;
697 if (!under_right_far)
698 ++amountOfNull;
699
700 if ( amountOfNull < 3 )
701 for ( int i = 0; i < conditions.Count(); ++i)
702 conditions[i] = !conditions[i];
703
704 DrawBaseSpheres(conditions);
705 }
706 #endif
707
708 return isTrue;
709 }
710
711 #ifdef DIAG_DEVELOPER
712 void DrawArrow(vector from, vector to, bool condition)
713 {
714 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
715 {
716 int color = 0xFFFFFFFF;
717 if (!condition)
718 color = COLOR_RED;
719
720 Debug.DrawArrow(from, to, 1, color, ShapeFlags.ONCE);
721 }
722 }
723
724 void DrawSphere(vector pos, bool condition)
725 {
726 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
727 {
728 int color = 0x01FFFFFF;
729 if (!condition)
730 color = 0x99F22613;
731
732 Debug.DrawSphere(pos, 1, color, ShapeFlags.ONCE|ShapeFlags.TRANSP|ShapeFlags.NOOUTLINE);
733 }
734 }
735
736 void DrawBaseSpheres(array<bool> conditions)
737 {
738 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
739 {
740 array<vector> positions = new array<vector>();
741 positions.Insert(m_Projection.CoordToParent( GetLeftCloseProjectionVector() ));
742 positions.Insert(m_Projection.CoordToParent( GetRightCloseProjectionVector() ));
743 positions.Insert(m_Projection.CoordToParent( GetLeftFarProjectionVector() ));
744 positions.Insert(m_Projection.CoordToParent( GetRightFarProjectionVector() ));
745
746 for (int i = 0; i < positions.Count(); ++i)
747 DrawSphere(positions[i], conditions[i]);
748 }
749 }
750
751 void DrawDebugArrow(float start, float dist, int color = 0xFF1FFFFF)
752 {
753 if ( DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM) )
754 {
755 vector from = m_Player.GetPosition() + start * MiscGameplayFunctions.GetHeadingVector(m_Player);
756 vector to = m_Player.GetPosition() + dist * MiscGameplayFunctions.GetHeadingVector(m_Player);
757
758 Debug.DrawArrow(from, to, 0.5, 0xFF1FFFFF, ShapeFlags.ONCE|ShapeFlags.TRANSP);
759 }
760 }
761 #endif
762
763 bool IsBaseFlat( vector contact_pos_left_close, vector contact_pos_right_close, vector contact_pos_left_far, vector contact_pos_right_far )
764 {
765 vector projection_pos = GetProjectionPosition();
766 float slope_pos_left_close = Math.AbsFloat(projection_pos[1] - contact_pos_left_close[1]);
767 float slope_pos_right_close = Math.AbsFloat(projection_pos[1] - contact_pos_right_close[1]);
768 float slope_pos_left_far = Math.AbsFloat(projection_pos[1] - contact_pos_left_far[1]);
769 float slope_pos_right_far = Math.AbsFloat(projection_pos[1] - contact_pos_right_far[1]);
770
771 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;
772 #ifdef DIAG_DEVELOPER
773 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);
774 DrawArrow(projection_pos, contact_pos_left_close, slope_pos_left_close < m_SlopeTolerance);
775 DrawArrow(projection_pos, contact_pos_right_close, slope_pos_right_close < m_SlopeTolerance);
776 DrawArrow(projection_pos, contact_pos_left_far, slope_pos_left_far < m_SlopeTolerance);
777 DrawArrow(projection_pos, contact_pos_right_far, slope_pos_right_far < m_SlopeTolerance);
778 #endif
779
780 return isTrue;
781 }
782
785 {
787 return true;
788 ItemBase item = m_Player.GetItemInHands();
789 bool isTrue = ( item && item.Type() == GetProjectionEntity().Type() && !item.CanBePlaced(m_Player, GetProjectionPosition()) );
790 isTrue = !isTrue; // ??????
791 #ifdef DIAG_DEVELOPER
792 DebugText("IsPlacementPermitted(must be true): ", true, isTrue, " (Note: CanBePlaced function on item and projection type must be same as item type)");
793 #endif
794 return isTrue;
795 }
796
799 {
801 return true;
802 if ( GetProjectionEntity() ) //simple height check
803 {
804 vector playerpos = m_Player.GetPosition();
805 vector projectionpos = GetProjectionPosition();
806 float delta1 = playerpos[1] - projectionpos[1];
807
809 {
810 #ifdef DIAG_DEVELOPER
811 DebugText("HeightPlacementCheck(must be true): ", true, false, " | Height difference between item and player is larger than " + DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF);
812 #endif
813 return false;
814 }
815 }
816 #ifdef DIAG_DEVELOPER
817 DebugText("HeightPlacementCheck(must be true): ", true, true);
818 #endif
819 return true;
820 }
821
823 {
825 return false;
826 // Fast check middle of object
827 string type;
828 int liquid;
829 g_Game.SurfaceUnderObject(m_Projection, type, liquid);
830
831 if (liquid == LIQUID_WATER)
832 {
833 #ifdef DIAG_DEVELOPER
834 DebugText("IsUnderwater: ", false, true, " | Surface under object is water");
835 #endif
836 return true;
837 }
838
839 // Check every corner of the object
840 vector left_close = m_Projection.CoordToParent( GetLeftCloseProjectionVector() );
841 vector right_close = m_Projection.CoordToParent( GetRightCloseProjectionVector() );
842 vector left_far = m_Projection.CoordToParent( GetLeftFarProjectionVector() );
843 vector right_far = m_Projection.CoordToParent( GetRightFarProjectionVector() );
844 bool surface_sea_water = IsSurfaceSea(left_close) || IsSurfaceSea(right_close) || IsSurfaceSea(left_far) || IsSurfaceSea(right_far);
845
846 #ifdef DIAG_DEVELOPER
847 // I'd rather duplicate this on internal than introduce (even) more raycasts than needed on retail..
848 float lc = g_Game.GetWaterDepth(left_close);
849 float rc = g_Game.GetWaterDepth(right_close);
850 float lf = g_Game.GetWaterDepth(left_far);
851 float rf = g_Game.GetWaterDepth(right_far);
852 bool isTrue = (lc > 0 || rc > 0 || lf > 0 || rf > 0 || surface_sea_water);
853 DebugText("IsUnderwater: ", false, isTrue, " surface_sea_water: " + surface_sea_water + " | (all must be less than zero) | lc: " + lc + " | rc: " + rc + " | lf: " + lf + " | rf: " + rf);
854 //DebugText("Corner Height: ", false, true, " lc: " + left_close[1] + " | rc: " + right_close[1] + " | lf: " + left_far[1] + " | rf: " + right_far[1]);
855 if (isTrue)
856 {
857 array<bool> conditions = {lc <= 0, rc <= 0, lf <= 0, rf <= 0};
858 DrawBaseSpheres(conditions);
859 }
860 #endif
861
862 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);
863 }
864
866 {
868 return false;
869 vector fromHeightOffset = "0 0.3 0";
870 vector toHeightOffset = "0 1 0";
871
872 vector from_left_close = m_Projection.CoordToParent( GetLeftCloseProjectionVector() ) + fromHeightOffset;
873 vector to_left_close_down = from_left_close + toHeightOffset;
874
875 vector from_right_close = m_Projection.CoordToParent( GetRightCloseProjectionVector() ) + fromHeightOffset;
876 vector to_right_close_down = from_right_close + toHeightOffset;
877
878 vector from_left_far = m_Projection.CoordToParent( GetLeftFarProjectionVector() ) + fromHeightOffset;
879 vector to_left_far_down = from_left_far + toHeightOffset;
880
881 vector from_right_far = m_Projection.CoordToParent( GetRightFarProjectionVector() ) + fromHeightOffset;
882 vector to_right_far_down = from_right_far + toHeightOffset;
883
884 vector contact_pos_left_close;
885 vector contact_pos_right_close;
886 vector contact_pos_left_far;
887 vector contact_pos_right_far;
888
889 vector contact_dir_left_close;
890 vector contact_dir_right_close;
891 vector contact_dir_left_far;
892 vector contact_dir_right_far;
893
894 int contact_component_left_close;
895 int contact_component_right_close;
896 int contact_component_left_far;
897 int contact_component_right_far;
898
899 #ifdef DIAG_DEVELOPER
900 // I'd rather duplicate this on internal than introduce (even) more raycasts than needed on retail..
901 set<Object> lcO = new set<Object>();
902 set<Object> rcO = new set<Object>();
903 set<Object> lfO = new set<Object>();
904 set<Object> rfO = new set<Object>();
905 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 );
906 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 );
907 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 );
908 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 );
909 bool isTrue = ( lc || rc || lf || rf );
910 string text = "";
911 if (isTrue)
912 {
913 if (lc)
914 text += " | lc";
915 if (rc)
916 text += " | rc";
917 if (lf)
918 text += " | lf";
919 if (rf)
920 text += " | rf";
921
922 if (lcO.Count() > 0)
923 text += " | lcO: " + lcO[0];
924 if (rcO.Count() > 0)
925 text += " | rcO: " + rcO[0];
926 if (lfO.Count() > 0)
927 text += " | lfO: " + lfO[0];
928 if (rfO.Count() > 0)
929 text += " | rfO: " + rfO[0];
930
931 array<bool> conditions = {!lc, !rc, !lf, !rf};
932 DrawBaseSpheres(conditions);
933 }
934 DebugText("IsInTerrain: ", false, isTrue, text);
935 #endif
936
937 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 ))
938 return true;
939
940 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 ))
941 return true;
942
943 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 ))
944 return true;
945
946 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 ))
947 return true;
948
949 return false;
950 }
951
953 {
954 //in range of its power source.
955 if ( m_Player && m_Parent && m_Parent.HasEnergyManager() && m_Parent.GetCompEM().IsPlugged() )
956 {
957 // Unplug the device when the player is too far from the power source.
958 m_Parent.GetCompEM().UpdatePlugState();
959
960 // Delete local hologram when plug is rippled out and advanced placement is active
961 if( GetGame().IsMultiplayer() && GetGame().IsClient() )
962 {
963 if (!m_Parent.GetCompEM().IsPlugged())
964 m_Player.TogglePlacingLocal();
965 }
966 }
967 }
968
969 EntityAI PlaceEntity( EntityAI entity_for_placing )
970 {
971 //string-based comparison
972 if (entity_for_placing.IsInherited(TentBase) || entity_for_placing.IsBasebuildingKit() )
973 {
974 return entity_for_placing;
975 }
976
977 if (m_Projection.IsInherited(GardenPlotPlacing))
978 {
979 Class.CastTo(entity_for_placing, GetGame().CreateObjectEx( "GardenPlot", m_Projection.GetPosition(), ECE_OBJECT_SWAP ));
980 return entity_for_placing;
981 }
982
983 //inheritance comparison
984 if( !GetProjectionEntity().IsKindOf( m_Parent.GetType() ))
985 {
986 Class.CastTo(entity_for_placing, GetGame().CreateObjectEx( m_Projection.GetType(), m_Projection.GetPosition(), ECE_OBJECT_SWAP ));
987 }
988
989 return entity_for_placing;
990 }
991
992 protected void GetProjectionCollisionBox( out vector min_max[2] )
993 {
994 if (!m_Projection.GetCollisionBox( min_max ) && m_Projection.MemoryPointExists("box_placing_min"))
995 {
996 min_max[0] = m_Projection.GetMemoryPointPos( "box_placing_min" );
997 min_max[1] = m_Projection.GetMemoryPointPos( "box_placing_max" );
998 //Debug.DrawSphere(m_Projection.ModelToWorld(min_max[0]) , 0.8,Colors.RED, ShapeFlags.ONCE);
999 //Debug.DrawSphere(m_Projection.ModelToWorld(min_max[1]), 0.8,Colors.RED, ShapeFlags.ONCE);
1000 }
1001 }
1002
1003 protected vector GetCollisionBoxSize( vector min_max[2] )
1004 {
1005 vector box_size = Vector(1,1,1);
1006
1007 box_size[0] = min_max[1][0] - min_max[0][0];
1008 box_size[2] = min_max[1][2] - min_max[0][2];
1009 box_size[1] = min_max[1][1] - min_max[0][1];
1010
1011 return box_size;
1012 }
1013
1015 {
1016 vector min_max[2];
1017 GetProjectionCollisionBox( min_max );
1018
1019 return min_max[0];
1020 }
1021
1023 {
1024 vector min_max[2];
1025 GetProjectionCollisionBox( min_max );
1026 min_max[1][1] = min_max[0][1];
1027 min_max[1][2] = min_max[0][2];
1028
1029 return min_max[1];
1030 }
1031
1033 {
1034 vector min_max[2];
1035 GetProjectionCollisionBox( min_max );
1036 min_max[0][2] = min_max[1][2];
1037
1038 return min_max[0];
1039 }
1040
1042 {
1043 vector min_max[2];
1044 GetProjectionCollisionBox( min_max );
1045 min_max[1][1] = min_max[0][1];
1046
1047 return min_max[1];
1048 }
1049
1050 // Replaced by IsUnderwater, currently unused
1051 bool IsSurfaceWater( vector position )
1052 {
1053 CGame game = GetGame();
1054 return game.SurfaceIsSea( position[0], position[2] ) || game.SurfaceIsPond( position[0], position[2] );
1055 }
1056
1057 bool IsSurfaceSea( vector position )
1058 {
1059 CGame game = GetGame();
1060 return game.SurfaceIsSea( position[0], position[2] );
1061 }
1062
1064 {
1065 float minProjectionDistance;
1066 float maxProjectionDistance;
1068 vector minMax[2];
1069 float projectionRadius = GetProjectionRadius();
1070 float cameraToPlayerDistance = vector.Distance(GetGame().GetCurrentCameraPosition(), player.GetPosition());
1071
1072 if (projectionRadius < SMALL_PROJECTION_RADIUS) // objects with radius smaller than 1m
1073 {
1074 minProjectionDistance = SMALL_PROJECTION_RADIUS;
1075 maxProjectionDistance = SMALL_PROJECTION_RADIUS * 2;
1076 }
1077 else
1078 {
1079 minProjectionDistance = projectionRadius;
1080 maxProjectionDistance = projectionRadius * 2;
1081 maxProjectionDistance = Math.Clamp(maxProjectionDistance, SMALL_PROJECTION_RADIUS, LARGE_PROJECTION_DISTANCE_LIMIT);
1082 }
1083
1085 //adjusts raycast origin to player head approx. level (limits results behind the character)
1086 if ( DayZPlayerCamera3rdPerson.Cast(player.GetCurrentCamera()) )
1087 {
1088 vector head_pos;
1089 MiscGameplayFunctions.GetHeadBonePos(player,head_pos);
1090 float dist = vector.Distance(head_pos,from);
1091 from = from + GetGame().GetCurrentCameraDirection() * dist;
1092 }
1093
1094 vector to = from + (GetGame().GetCurrentCameraDirection() * (maxProjectionDistance + cameraToPlayerDistance));
1095 vector contactPosition;
1096 set<Object> hitObjects = new set<Object>();
1097
1098 DayZPhysics.RaycastRV(from, to, contactPosition, m_ContactDir, m_ContactComponent, hitObjects, player, m_Projection, false, false, ObjIntersectFire);
1099
1100 bool contactHitProcessed = false;
1103 {
1104 if (hitObjects.Count() > 0)
1105 {
1106 if (hitObjects[0].IsInherited(Watchtower))
1107 {
1108 contactHitProcessed = true;
1109 contactPosition = CorrectForWatchtower(m_ContactComponent, contactPosition, player, hitObjects[0]);
1110 }
1111
1112 if (!contactHitProcessed && hitObjects[0].IsInherited(InventoryItem))
1113 contactPosition = hitObjects[0].GetPosition();
1114 }
1115 }
1116
1117 static const float raycastOriginOffsetOnFail = 0.25;
1118 static const float minDistFromStart = 0.01;
1119 // Camera isn't correctly positioned in some cases, leading to raycasts hitting the object directly behind the camera
1120 if ((hitObjects.Count() > 0) && (vector.DistanceSq(from, contactPosition) < minDistFromStart))
1121 {
1122 from = contactPosition + GetGame().GetCurrentCameraDirection() * raycastOriginOffsetOnFail;
1123 DayZPhysics.RaycastRV(from, to, contactPosition, m_ContactDir, m_ContactComponent, hitObjects, player, m_Projection, false, false, ObjIntersectFire);
1124 }
1125
1126 bool isFloating = SetHologramPosition(player.GetPosition(), minProjectionDistance, maxProjectionDistance, contactPosition);
1127 SetIsFloating(isFloating);
1128
1129 #ifdef DIAG_DEVELOPER
1130 DrawDebugArrow(minProjectionDistance, maxProjectionDistance);
1131 if (DiagMenu.GetBool(DiagMenuIDs.MISC_HOLOGRAM))
1132 {
1133 Debug.DrawSphere(GetProjectionPosition(), 0.1, 0x99FF0000, ShapeFlags.ONCE|ShapeFlags.TRANSP|ShapeFlags.NOOUTLINE);
1134 }
1135 #endif
1136
1137 m_FromAdjusted = from;
1138
1139 return contactPosition;
1140 }
1141
1150 protected bool SetHologramPosition(vector startPosition, float minProjectionDistance, float maxProjectionDistance, inout vector contactPosition)
1151 {
1152 float playerToProjectionDistance = vector.Distance(startPosition, contactPosition);
1153 vector playerToProjection;
1154
1155 #ifdef DIAG_DEVELOPER
1156 DebugText("SetHologramPosition::startPosition: ", false, m_IsHidden, string.Format(" | %1", startPosition));
1157 DebugText("SetHologramPosition::contactPosition [in]: ", false, m_IsHidden, string.Format(" | %1", contactPosition));
1158 DebugText("SetHologramPosition::minProjectionDistance: ", false, m_IsHidden, string.Format(" | %1", minProjectionDistance));
1159 DebugText("SetHologramPosition::maxProjectionDistance: ", false, m_IsHidden, string.Format(" | %1", maxProjectionDistance));
1160 DebugText("SetHologramPosition::playerToProjectionDistance: ", false, m_IsHidden, string.Format(" | %1", playerToProjectionDistance));
1161 #endif
1162
1163 //hologram is at min distance from player
1164 if (playerToProjectionDistance <= minProjectionDistance)
1165 {
1166 playerToProjection = contactPosition - startPosition;
1167 playerToProjection.Normalize();
1168 //prevents the hologram to go underground/floor while hologram exceeds minProjectionDistance
1169 playerToProjection[1] = playerToProjection[1] + PROJECTION_TRANSITION_MIN;
1170
1171 contactPosition = startPosition + (playerToProjection * minProjectionDistance);
1172
1173 #ifdef DIAG_DEVELOPER
1174 DebugText("SetHologramPosition::contactPosition[out] (< minProjectDistance): ", false, m_IsHidden, string.Format(" | %1", contactPosition));
1175 #endif
1176
1177 return true;
1178 }
1179 //hologram is at max distance from player
1180 else if (playerToProjectionDistance >= maxProjectionDistance)
1181 {
1182 playerToProjection = contactPosition - startPosition;
1183 playerToProjection.Normalize();
1184 //prevents the hologram to go underground/floor while hologram exceeds maxProjectionDistance
1185 playerToProjection[1] = playerToProjection[1] + PROJECTION_TRANSITION_MAX;
1186
1187 contactPosition = startPosition + (playerToProjection * maxProjectionDistance);
1188
1189 #ifdef DIAG_DEVELOPER
1190 DebugText("SetHologramPosition::contactPosition[out] (< maxProjectionDistance): ", false, m_IsHidden, string.Format(" | %1", contactPosition));
1191 #endif
1192
1193 return true;
1194 }
1195
1196 return false;
1197 }
1198
1200 {
1201 return m_Parent.IsBasebuildingKit() || m_Parent.IsInherited(TentBase);
1202 }
1203
1204 vector CorrectForWatchtower(int contactComponent, vector contactPos, PlayerBase player, Object hitObject)
1205 {
1206 // Raycast has hit one of the trigger boxes that show construction prompts, so projection would be floating in the air without this correction
1207 if (m_WatchtowerIgnoreComponentNames.Find(hitObject.GetActionComponentName(contactComponent, LOD.NAME_VIEW)) != -1 )
1208 contactPos[1] = hitObject.GetActionComponentPosition(contactComponent, LOD.NAME_VIEW)[1];
1209
1210 return contactPos;
1211 }
1212
1213 //This function is currently unused
1215 {
1216 return m_Projection.IsInherited( TrapBase ) || m_Projection.IsInherited( TrapSpawnBase );
1217 }
1218
1220 {
1221 float diameter;
1222 float radius;
1223 vector diagonal;
1224 vector min_max[2];
1225
1226 GetProjectionCollisionBox( min_max );
1227 diagonal = GetCollisionBoxSize( min_max );
1228 diameter = diagonal.Length();
1229
1230 return diameter;
1231 }
1232
1234 {
1235 float diameter;
1236 float radius;
1237 vector diagonal;
1238 vector min_max[2];
1239
1240 GetProjectionCollisionBox( min_max );
1241 diagonal = GetCollisionBoxSize( min_max );
1242 diameter = diagonal.Length();
1243 radius = diameter / 2;
1244
1245 return radius;
1246 }
1247
1248 void SetUpdatePosition( bool state )
1249 {
1250 m_UpdatePosition = state;
1251 }
1252
1254 {
1255 return m_UpdatePosition;
1256 }
1257
1259 {
1260 return m_Parent;
1261 }
1262
1264 {
1265 m_Projection = projection;
1266 }
1267
1269 {
1270 return m_Projection;
1271 }
1272
1273 void SetIsFloating( bool is_floating )
1274 {
1275 m_IsFloating = is_floating;
1276 }
1277
1278 void SetIsColliding( bool is_colliding )
1279 {
1280 #ifdef DIAG_DEVELOPER
1281 DebugText("Is colliding: ", false, is_colliding);
1282 #endif
1283 m_IsColliding = is_colliding;
1284 }
1285
1286 void SetIsHidden( bool is_hidden )
1287 {
1288 m_IsHidden = is_hidden;
1289 }
1290
1291 void SetIsCollidingPlayer( bool is_colliding )
1292 {
1293 m_IsCollidingPlayer = is_colliding;
1294 }
1295
1296 void SetIsCollidingGPlot( bool is_colliding_gplot )
1297 {
1298 m_IsCollidingGPlot = is_colliding_gplot;
1299 }
1300
1302 {
1303 #ifdef DIAG_DEVELOPER
1304 DebugText("IsFloating: ", false, m_IsFloating);
1305 #endif
1306 return m_IsFloating;
1307 }
1308
1310 {
1311 return m_IsColliding;
1312 }
1313
1315 {
1316 #ifdef DIAG_DEVELOPER
1317 DebugText("IsHidden: ", false, m_IsHidden);
1318 #endif
1319 return m_IsHidden;
1320 }
1321
1323 {
1325 return false;
1326 #ifdef DIAG_DEVELOPER
1327 DebugText("IsCollidingPlayer: ", false, m_IsCollidingPlayer);
1328 #endif
1329 return m_IsCollidingPlayer;
1330 }
1331
1333 {
1334 m_Projection.SetPosition( position );
1335
1336 if (IsFloating())
1337 {
1338 m_Projection.SetPosition(SetOnGround(position));
1339 }
1340 }
1341
1343 {
1344 m_Projection.SetOrientation(orientation);
1345 }
1346
1348 {
1349 return m_Rotation;
1350 }
1351
1352 void AddProjectionRotation( float addition )
1353 {
1354 m_Rotation[0] = m_Rotation[0] + addition;
1355 }
1356
1357 void SubtractProjectionRotation( float subtraction )
1358 {
1359 m_Rotation[0] = m_Rotation[0] - subtraction;
1360 }
1361
1363 {
1364 vector from = position;
1365 vector ground;
1366 vector player_to_projection_vector;
1367 float projection_diameter = GetProjectionDiameter();
1368
1369 ground = Vector(0, -Math.Max(projection_diameter, SMALL_PROJECTION_GROUND), 0);
1370
1371 vector to = from + ground;
1372 vector contact_pos = to;
1373
1374 RaycastRVParams rayInput = new RaycastRVParams(from, to, m_Projection);
1375 rayInput.flags = CollisionFlags.ALLOBJECTS;
1377
1378 if (DayZPhysics.RaycastRVProxy(rayInput, results))
1379 {
1380 RaycastRVResult res;
1381 for (int i = 0; i < results.Count(); i++)
1382 {
1383 res = results.Get(i);
1384 if (res.entry || (!res.obj && !res.parent))
1385 {
1386 contact_pos = res.pos;
1387 break;
1388 }
1389 }
1390 }
1391
1392 //LOS check
1393 if (contact_pos != "0 0 0")
1394 {
1395 vector check_pos;
1396 vector check_dir;
1397 int check_component = -1;
1398 set<Object> hit_object = new set<Object>;
1399 to = contact_pos;
1400 to[1] = to[1] + 0.1;
1401 from = m_FromAdjusted;
1402
1403 if (DayZPhysics.RaycastRV(from, to, check_pos, check_dir, check_component, hit_object, null, m_Player, false, false, ObjIntersectFire))
1404 {
1405 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))))
1406 {
1407 contact_pos = "0 0 0";
1408 }
1409 }
1410 }
1411
1412 HideWhenClose(contact_pos);
1413
1414 return contact_pos;
1415 }
1416
1418 {
1419 //if the hologram is too close to player when he looks to the sky, send the projection to away
1421
1422 if( cam_dir[1] > LOOKING_TO_SKY )
1423 {
1424 pos = "0 0 0";
1425 }
1426
1427 return pos;
1428 }
1429
1431 {
1432 if (m_Projection)
1433 return m_Projection.GetPosition();
1434
1435 return vector.Zero;
1436 }
1437
1439 {
1440 if (m_Projection)
1441 return m_Projection.GetOrientation();
1442
1443 return vector.Zero;
1444 }
1445
1447 {
1449 m_DefaultOrientation[1] = 0;
1450
1451 if (!GetParentEntity().PlacementCanBeRotated())
1452 {
1454 }
1455
1456 return m_DefaultOrientation;
1457 }
1458
1459 int GetHiddenSelection( string selection )
1460 {
1461 int idx = m_Projection.GetHiddenSelectionIndex(selection);
1462
1463 if ( idx != -1 )
1464 return idx;
1465 else
1466 return 0;
1467 }
1468
1469 // the function accepts string
1470 void SetSelectionToRefresh( string selection )
1471 {
1472 m_SelectionsToRefresh.Insert( selection );
1473 }
1474
1475 //overloaded function to accept array of strings
1477 {
1478 for ( int i = 0; i < selection.Count(); i++ )
1479 {
1480 m_SelectionsToRefresh.Insert( selection.Get(i) );
1481 }
1482 }
1483
1485 {
1486 if (m_Projection)
1487 {
1488 static const string textureName = "#(argb,8,8,3)color(0.5,0.5,0.5,0.75,ca)";
1489
1490 int hidden_selection = 0;
1491 string selection_to_refresh;
1492 string config_material = string.Format("CfgVehicles %1 hologramMaterial", m_Projection.GetType());
1493 string hologram_material = GetGame().ConfigGetTextOut(config_material);
1494 string config_model = string.Format("CfgVehicles %1 hologramMaterialPath", m_Projection.GetType());
1495 string hologram_material_path = string.Format("%1\\%2%3", GetGame().ConfigGetTextOut(config_model), hologram_material, CorrectMaterialPathName());
1496
1497 for (int i = 0; i < m_SelectionsToRefresh.Count(); ++i)
1498 {
1499 selection_to_refresh = m_SelectionsToRefresh.Get(i);
1500 hidden_selection = GetHiddenSelection(selection_to_refresh);
1501 m_Projection.SetObjectTexture(hidden_selection, textureName);
1502 m_Projection.SetObjectMaterial(hidden_selection, hologram_material_path);
1503 }
1504 }
1505 }
1506
1507 // Returns correct string to append to material path name
1509 {
1510 if (IsColliding() || IsFloating())
1511 {
1513 }
1514 else if (m_Parent.HasEnergyManager())
1515 {
1516 ComponentEnergyManager comp_em = m_Parent.GetCompEM();
1517 string SEL_CORD_PLUGGED = m_Parent.GetCompEM().SEL_CORD_PLUGGED;
1518 string SEL_CORD_FOLDED = m_Parent.GetCompEM().SEL_CORD_FOLDED;
1519
1520 if (comp_em.IsPlugged() && comp_em.IsEnergySourceAtReach(GetProjectionPosition()))
1521 {
1522 m_Projection.SetAnimationPhase(SEL_CORD_PLUGGED, 0);
1523 m_Projection.SetAnimationPhase(SEL_CORD_FOLDED, 1);
1525 }
1526 else
1527 {
1528 m_Projection.SetAnimationPhase(SEL_CORD_PLUGGED, 1);
1529 m_Projection.SetAnimationPhase(SEL_CORD_FOLDED, 0);
1530 }
1531 }
1532
1534 }
1535};
1536
1537class ProjectionTrigger extends Trigger
1538{
1539 protected int m_TriggerUpdateMs;
1542
1543 override void OnEnter( Object obj )
1544 {
1545 //Print("OnEnter");
1546 if ( m_ParentObj )
1547 {
1548 m_ParentObj.SetIsCollidingPlayer( true );
1549 m_TriggerUpdateMs = 50;
1550 }
1551 }
1552
1553 override void OnLeave( Object obj )
1554 {
1555 //Print("OnLeave");
1556 if ( m_ParentObj )
1557 {
1558 m_ParentObj.SetIsCollidingPlayer( false );
1559 }
1560 }
1561
1562 override protected void UpdateInsiders(int timeout)
1563 {
1564 super.UpdateInsiders(m_TriggerUpdateMs);
1565 }
1566
1567 void SetParentObject( Hologram projection )
1568 {
1569 m_ParentObj = projection;
1570 }
1571
1573 {
1574 m_Player = player;
1575 }
1576}
eBleedingSourceType GetType()
const int ECE_OBJECT_SWAP
const int ECE_LOCAL
const int ECE_PLACE_ON_SURFACE
const int ECE_TRACE
const int ECE_CREATEPHYSICS
protected void DrawDebugCollisionBox(vector min_max[2], int color)
protected void DestroyDebugCollisionBox()
protected Shape m_CollisionBox
void DeployableContainer_Base()
DayZGame g_Game
Definition DayZGame.c:3654
void DayZPlayerCamera3rdPerson(DayZPlayer pPlayer, HumanInputController pInput)
DiagMenuIDs
Definition EDiagMenuIDs.c:2
DayZPlayer m_Player
Definition Hand_Events.c:42
TrapBase m_ParentObj
Definition TrapTrigger.c:58
proto native void ObjectDelete(Object obj)
proto native bool SurfaceIsPond(float x, float z)
proto native vector GetCurrentCameraDirection()
proto native vector ConfigGetVector(string path)
Get vector value from config on path.
proto native vector SurfaceGetNormal(float x, float z)
proto native float ConfigGetFloat(string path)
Get float value from config on path.
proto native bool SurfaceIsSea(float x, float z)
proto native int ConfigGetInt(string path)
Get int value from config on path.
proto bool ConfigGetChildName(string path, int index, out string name)
Get name of subclass in config class on path.
proto native vector GetCurrentCameraPosition()
proto native bool IsBoxCollidingGeometry(vector center, vector orientation, vector edgeLength, int iPrimaryType, int iSecondaryType, array< Object > excludeObjects, array< Object > collidedObjects=NULL)
Finds all objects with geometry iType that are in choosen oriented bounding box (OBB)
string ConfigGetTextOut(string path)
Get string value from config on path.
Definition Game.c:440
static bool GetDisableIsCollidingPlayerCheck()
static bool GetDisableIsClippingRoofCheck()
static bool GetDisableIsCollidingGPlotCheck()
static bool GetDisableIsCollidingBBoxCheck()
static bool GetDisableIsInTerrainCheck()
static bool GetDisableIsCollidingAngleCheck()
static bool GetDisableIsPlacementPermittedCheck()
static bool GetDisableHeightPlacementCheck()
static bool GetDisableIsBaseViableCheck()
static bool GetDisableIsUnderwaterCheck()
Super root of all classes in Enforce script.
Definition EnScript.c:11
bool IsPlugged()
Energy manager: Returns true if this device is plugged into some other device (even if they are OFF o...
bool IsEnergySourceAtReach(vector from_position, float add_tolerance=0, vector override_source_position="-1 -1 -1")
Energy manager: Returns true if this device's virtual power cord can reach its energy source at the g...
static proto bool RaycastRVProxy(notnull RaycastRVParams in, out notnull array< ref RaycastRVResult > results, array< Object > excluded=null)
static proto bool RaycastRV(vector begPos, vector endPos, out vector contactPos, out vector contactDir, out int contactComponent, set< Object > results=NULL, Object with=NULL, Object ignore=NULL, bool sorted=false, bool ground_only=false, int iType=ObjIntersectView, float radius=0.0, CollisionFlags flags=CollisionFlags.NEARESTCONTACT)
Raycasts world by given parameters.
Definition DbgUI.c:60
Definition Debug.c:14
static Shape DrawArrow(vector from, vector to, float size=0.5, int color=0xFFFFFFFF, int flags=0)
Definition Debug.c:383
static Shape DrawBox(vector pos1, vector pos2, int color=0x1fff7f7f)
Definition Debug.c:273
static Shape DrawSphere(vector pos, float size=1, int color=0x1fff7f7f, ShapeFlags flags=ShapeFlags.TRANSP|ShapeFlags.NOOUTLINE)
Definition Debug.c:306
protected const string ANIMATION_INVENTORY
Definition Hologram.c:33
protected const float DISTANCE_SMALL_PROJECTION
Definition Hologram.c:39
protected const string SUFFIX_MATERIAL_UNDEPLOYABLE
Definition Hologram.c:10
protected const string SELECTION_PLACING
Definition Hologram.c:34
bool IsCollidingAngle()
Definition Hologram.c:486
protected const float LARGE_PROJECTION_DISTANCE_LIMIT
Deprecated.
Definition Hologram.c:40
protected const string SELECTION_INVENTORY
Definition Hologram.c:35
vector GetProjectionRotation()
Definition Hologram.c:1347
static const protected ref array< string > m_WatchtowerIgnoreComponentNames
Definition Hologram.c:55
protected bool m_UpdatePosition
Definition Hologram.c:24
void SetIsColliding(bool is_colliding)
Definition Hologram.c:1278
protected vector m_DefaultOrientation
Definition Hologram.c:27
bool IsBehindObstacle()
DEPRECATED.
Definition Hologram.c:652
void SetIsCollidingGPlot(bool is_colliding_gplot)
Definition Hologram.c:1296
protected const int SPAWN_FLAGS
Definition Hologram.c:6
string ProjectionBasedOnParent()
Definition Hologram.c:207
protected vector GetProjectionEntityPosition(PlayerBase player)
Definition Hologram.c:1063
void SetProjectionPosition(vector position)
Definition Hologram.c:1332
protected const float PROJECTION_TRANSITION_MIN
Definition Hologram.c:41
bool IsColliding()
Definition Hologram.c:1309
void SetIsHidden(bool is_hidden)
Definition Hologram.c:1286
bool IsCollidingZeroPos()
Definition Hologram.c:640
protected bool m_AlignToTerrain
Definition Hologram.c:47
protected bool m_IsCollidingGPlot
Definition Hologram.c:20
vector GetProjectionOrientation()
Definition Hologram.c:1438
static const float DEFAULT_MAX_PLACEMENT_HEIGHT_DIFF
Definition Hologram.c:44
void RefreshVisual()
Definition Hologram.c:1484
protected bool m_IsSlope
Definition Hologram.c:21
protected vector m_ContactDir
Definition Hologram.c:30
protected const string ANIMATION_PLACING
Definition Hologram.c:32
EntityAI GetParentEntity()
Definition Hologram.c:1258
protected vector GetCollisionBoxSize(vector min_max[2])
Definition Hologram.c:1003
void EvaluateCollision(ItemBase action_item=null)
Definition Hologram.c:424
protected float m_SlopeTolerance
Definition Hologram.c:46
protected const float PROJECTION_TRANSITION_MAX
Definition Hologram.c:42
bool IsCollidingPlayer()
Definition Hologram.c:1322
protected vector m_FromAdjusted
Definition Hologram.c:31
vector GetRightFarProjectionVector()
Definition Hologram.c:1041
string CorrectMaterialPathName()
Definition Hologram.c:1508
vector GetLeftCloseProjectionVector()
Definition Hologram.c:1014
void CreateTrigger()
Definition Hologram.c:367
vector SmoothProjectionMovement(vector y_p_r, float timeslice)
Definition Hologram.c:340
void SetSelectionToRefresh(string selection)
Definition Hologram.c:1470
EntityAI PlaceEntity(EntityAI entity_for_placing)
Definition Hologram.c:969
void SetUpdatePosition(bool state)
Definition Hologram.c:1248
vector AlignProjectionOnTerrain(float timeslice)
Definition Hologram.c:285
void ~Hologram()
Definition Hologram.c:148
bool IsFloating()
Definition Hologram.c:1301
void Hologram(PlayerBase player, vector pos, ItemBase item)
Definition Hologram.c:60
vector HideWhenClose(vector pos)
Definition Hologram.c:1417
void UpdateSelections()
Definition Hologram.c:188
static bool DoesHaveProjection(ItemBase item)
DEPRECATED.
Definition Hologram.c:240
void SetIsCollidingPlayer(bool is_colliding)
Definition Hologram.c:1291
protected vector m_YawPitchRollLimit
Definition Hologram.c:48
void SetIsFloating(bool is_floating)
Definition Hologram.c:1273
protected int m_ContactComponent
Definition Hologram.c:49
bool IsBaseStatic(Object objectToCheck)
Definition Hologram.c:659
protected const string SUFFIX_MATERIAL_POWERED
Definition Hologram.c:11
int GetHiddenSelection(string selection)
Definition Hologram.c:1459
protected bool m_IsFloating
Definition Hologram.c:23
protected PlayerBase m_Player
Definition Hologram.c:15
static const protected ref array< string > m_WatchtowerBlockedComponentNames
Definition Hologram.c:58
bool IsPlacementPermitted()
Checks if the item can be legally placed (usually checked by action as well)
Definition Hologram.c:784
protected const float SMALL_PROJECTION_RADIUS
Definition Hologram.c:37
protected vector m_y_p_r_previous
Definition Hologram.c:29
protected vector m_Rotation
Definition Hologram.c:28
protected const string SUFFIX_MATERIAL_DEPLOYABLE
Definition Hologram.c:9
bool HeightPlacementCheck()
Checks height relative to player's position.
Definition Hologram.c:798
bool IsClippingRoof()
Definition Hologram.c:454
bool GetUpdatePosition()
Definition Hologram.c:1253
bool IsSurfaceSea(vector position)
Definition Hologram.c:1057
bool IsInTerrain()
Definition Hologram.c:865
bool IsBaseViable()
Definition Hologram.c:566
void SetProjectionEntity(EntityAI projection)
Definition Hologram.c:1263
bool IsBaseFlat(vector contact_pos_left_close, vector contact_pos_right_close, vector contact_pos_left_far, vector contact_pos_right_far)
Definition Hologram.c:763
protected ProjectionTrigger m_ProjectionTrigger
Definition Hologram.c:16
vector CorrectForWatchtower(int contactComponent, vector contactPos, PlayerBase player, Object hitObject)
Definition Hologram.c:1204
protected EntityAI m_Projection
Definition Hologram.c:14
bool IsCollidingBBox(ItemBase action_item=null)
Definition Hologram.c:519
bool IsSurfaceWater(vector position)
Definition Hologram.c:1051
void CheckPowerSource()
Definition Hologram.c:952
protected bool m_IsCollidingPlayer
Definition Hologram.c:22
protected const float SMALL_PROJECTION_GROUND
Definition Hologram.c:38
void SubtractProjectionRotation(float subtraction)
Definition Hologram.c:1357
void SetAnimations()
Definition Hologram.c:168
protected ref set< string > m_SelectionsToRefresh
Definition Hologram.c:51
float GetProjectionDiameter()
Definition Hologram.c:1219
bool IsBaseIntact(Object under_left_close, Object under_right_close, Object under_left_far, Object under_right_far)
Definition Hologram.c:677
EntityAI GetProjectionEntity()
Definition Hologram.c:1268
protected string m_ProjectionTypename
Definition Hologram.c:17
protected bool SetHologramPosition(vector startPosition, float minProjectionDistance, float maxProjectionDistance, inout vector contactPosition)
Sets hologram position based on player and projection distance.
Definition Hologram.c:1150
vector SetOnGround(vector position)
Definition Hologram.c:1362
bool IsFenceOrWatchtowerKit()
Definition Hologram.c:1199
void SetProjectionOrientation(vector orientation)
Definition Hologram.c:1342
protected void GetProjectionCollisionBox(out vector min_max[2])
Definition Hologram.c:992
bool IsHidden()
Definition Hologram.c:1314
void RefreshTrigger()
Definition Hologram.c:378
void UpdateHologram(float timeslice)
Definition Hologram.c:246
bool IsUnderwater()
Definition Hologram.c:822
protected bool m_IsHidden
Definition Hologram.c:25
protected bool m_IsColliding
Definition Hologram.c:19
vector GetDefaultOrientation()
Definition Hologram.c:1446
vector GetProjectionPosition()
Definition Hologram.c:1430
void SetSelectionToRefresh(array< string > selection)
Definition Hologram.c:1476
protected const float LOOKING_TO_SKY
Definition Hologram.c:43
bool IsCollidingGPlot()
Definition Hologram.c:628
float GetProjectionRadius()
Definition Hologram.c:1233
vector GetRightCloseProjectionVector()
Definition Hologram.c:1022
protected ItemBase m_Parent
Definition Hologram.c:13
vector GetLeftFarProjectionVector()
Definition Hologram.c:1032
bool IsObjectStatic(Object obj)
Definition Hologram.c:672
bool IsProjectionTrap()
Definition Hologram.c:1214
string GetProjectionName(ItemBase item)
Definition Hologram.c:212
void AddProjectionRotation(float addition)
Definition Hologram.c:1352
static protected const string SEL_CORD_FOLDED
override bool CanMakeGardenplot()
Definition FieldShovel.c:3
override bool IsBasebuildingKit()
Definition KitBase.c:17
override bool CanBePlaced(Man player, vector position)
Definition TentBase.c:1023
override bool IsDeployable()
static protected const string SEL_CORD_PLUGGED
LOD class.
Definition gameplay.c:203
static const string NAME_VIEW
Definition gameplay.c:206
Definition EnMath.c:7
CollisionFlags flags
Definition DayZPhysics.c:60
vector pos
position of collision (in world coord)
Object obj
object,that we collide with (NULL if none), If hierLevel > 0 object is the proxy object
Definition DayZPhysics.c:97
bool entry
is false if begining point was TriggerInsider
Object parent
if hierLevel > 0 most parent of the proxy object
Definition DayZPhysics.c:98
override bool IsPlaceableAtPosition(vector position)
Scripted Trigger.
Definition Hologram.c:1538
protected int m_TriggerUpdateMs
Definition Hologram.c:1539
void SetParentOwner(PlayerBase player)
Definition Hologram.c:1572
protected Hologram m_ParentObj
Definition Hologram.c:1540
protected PlayerBase m_Player
Definition Hologram.c:1541
override void OnEnter(Object obj)
Definition Hologram.c:1543
override void OnLeave(Object obj)
Definition Hologram.c:1553
override protected void UpdateInsiders(int timeout)
Definition Hologram.c:1562
void SetParentObject(Hologram projection)
Definition Hologram.c:1567
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
static proto native float Distance(vector v1, vector v2)
Returns the distance between tips of two 3D vectors.
proto float Normalize()
Normalizes vector. Returns length.
static const vector Zero
Definition EnConvert.c:110
static proto native float DistanceSq(vector v1, vector v2)
Returns the square distance between tips of two 3D vectors.
proto vector VectorToAngles()
Converts vector to spherical coordinates with radius = 1.
proto native float Length()
Returns length of vector (magnitude)
proto native CGame GetGame()
const int COLOR_RED
Definition constants.c:64
ErrorExSeverity
Definition EnDebug.c:62
enum ShapeType ErrorEx
CollisionFlags
Definition EnDebug.c:141
ShapeFlags
Definition EnDebug.c:126
static proto void InputFloat(string txt, out float value, int pxWidth=150)
static proto native void ColoredText(int color, string label)
static proto native void SameLine()
static proto bool GetBool(int id, bool reverse=false)
Get value as bool from the given script id.
class DiagMenu Shape
don't call destructor directly. Use Destroy() instead
const float ROOF_CHECK_RAYCAST_DIST
Definition constants.c:844
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
const int LIQUID_WATER
Definition constants.c:489
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
static proto vector MatrixToAngles(vector mat[3])
Returns angles of rotation matrix.
static proto void MatrixMultiply3(vector mat0[3], vector mat1[3], out vector res[3])
Transforms rotation matrix.
static proto void YawPitchRollMatrix(vector ang, out vector mat[3])
Creates rotation matrix from angles.
static proto float Max(float x, float y)
Returns bigger of two given values.
static proto float Clamp(float value, float min, float max)
Clamps 'value' to 'min' if it is lower than 'min', or to 'max' if it is higher than 'max'.
static proto float Lerp(float a, float b, float time)
Linearly interpolates between 'a' and 'b' given 'time'.
static proto float AbsFloat(float f)
Returns absolute value.
static proto string Format(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL)
Gets n-th character from string.
static proto string ToString(void var, bool type=false, bool name=false, bool quotes=true)
Return string representation of variable.