1570{
1572
1574
1576
1578
1584
1585
1586
1592
1598
1600
1604
1605
1607 {
1609
1610
1611 RegisterNetSyncVariableInt( "m_SyncParts01" );
1612 RegisterNetSyncVariableInt( "m_SyncParts02" );
1613 RegisterNetSyncVariableInt( "m_SyncParts03" );
1614 RegisterNetSyncVariableInt( "m_InteractedPartId" );
1615 RegisterNetSyncVariableInt( "m_PerformedActionId" );
1616 RegisterNetSyncVariableBool( "m_HasBase" );
1617
1618
1620
1621 if (ConfigIsExisting("hybridAttachments"))
1622 {
1625 }
1626 if (ConfigIsExisting("mountables"))
1627 {
1630 }
1631
1633 }
1634
1636 {
1637 super.EEDelete(parent);
1638
1640 {
1641 areaDamage.Destroy();
1642 }
1643
1644 }
1645
1647 {
1648 return "disableBaseDamage";
1649 }
1650
1652 {
1653 return true;
1654 }
1655
1657 {
1658 return EInventoryIconVisibility.HIDE_VICINITY;
1659 }
1660
1662 {
1663 super.InitItemSounds();
1664
1668
1673 }
1674
1676 {
1677 return "putDown_FenceKit_SoundSet";
1678 }
1679
1681 {
1682 return "Shelter_Site_Build_Loop_SoundSet";
1683 }
1684
1685
1687 {
1689 {
1690 SetSynchDirty();
1691 }
1692 }
1693
1695 {
1697 super.OnVariablesSynchronized();
1698
1700 }
1701
1703 {
1704
1706
1707
1709
1710
1712 }
1713
1714
1716 {
1717
1718 int offset;
1719 int mask;
1720
1721 if ( part_id >= 1 && part_id <= 31 )
1722 {
1723 offset = part_id - 1;
1724 mask = 1 << offset;
1725
1727 }
1728 else if ( part_id >= 32 && part_id <= 62 )
1729 {
1730 offset = ( part_id % 32 );
1731 mask = 1 << offset;
1732
1734 }
1735 else if ( part_id >= 63 && part_id <= 93 )
1736 {
1737 offset = ( part_id % 63 );
1738 mask = 1 << offset;
1739
1741 }
1742 }
1743
1745 {
1746
1747 int offset;
1748 int mask;
1749
1750 if ( part_id >= 1 && part_id <= 31 )
1751 {
1752 offset = part_id - 1;
1753 mask = 1 << offset;
1754
1756 }
1757 else if ( part_id >= 32 && part_id <= 62 )
1758 {
1759 offset = ( part_id % 32 );
1760 mask = 1 << offset;
1761
1763 }
1764 else if ( part_id >= 63 && part_id <= 93 )
1765 {
1766 offset = ( part_id % 63 );
1767 mask = 1 << offset;
1768
1770 }
1771 }
1772
1774 {
1775
1776 int offset;
1777 int mask;
1778
1779 if ( part_id >= 1 && part_id <= 31 )
1780 {
1781 offset = part_id - 1;
1782 mask = 1 << offset;
1783
1785 {
1786 return true;
1787 }
1788 }
1789 else if ( part_id >= 32 && part_id <= 62 )
1790 {
1791 offset = ( part_id % 32 );
1792 mask = 1 << offset;
1793
1795 {
1796 return true;
1797 }
1798 }
1799 else if ( part_id >= 63 && part_id <= 93 )
1800 {
1801 offset = ( part_id % 63 );
1802 mask = 1 << offset;
1803
1805 {
1806 return true;
1807 }
1808 }
1809
1810 return false;
1811 }
1812
1814 {
1817 }
1818
1820 {
1821
1824 }
1825
1827 {
1829 {
1832
1833 switch( build_action_id )
1834 {
1838 }
1839 }
1840 }
1841
1842
1844 {
1846 bool is_base = part.
IsBase();
1849 if ( is_part_built_sync )
1850 {
1852 {
1856
1857 if (is_base)
1858 {
1861 }
1862 }
1863 }
1864 else
1865 {
1867 {
1871
1872 if (is_base)
1873 {
1876 }
1877 }
1878 }
1879
1880
1882 }
1883
1884
1886 {
1889
1890 for ( int i = 0; i < construction_parts.Count(); ++i )
1891 {
1892 string key = construction_parts.GetKey( i );
1895 }
1896
1897
1899 }
1900
1902 {
1905
1906 for ( int i = 0; i < construction_parts.Count(); ++i )
1907 {
1908 string key = construction_parts.GetKey( i );
1910
1911 if ( value.
GetId() ==
id )
1912 {
1913 return value;
1914 }
1915 }
1916
1917 return NULL;
1918 }
1919
1920
1921
1923 {
1925 }
1926
1928 {
1930 }
1931
1933 {
1934 return true;
1935 }
1936
1938 {
1939 return false;
1940 }
1941
1942
1944 {
1947 {
1949 }
1950
1951 return construction_kit;
1952 }
1953
1955 {
1958 {
1960 }
1961 }
1962
1964 {
1966 }
1967
1969 {
1970 return "";
1971 }
1972
1974 {
1977 }
1978
1979
1981 {
1984 }
1985
1986
1988 {
1989 super.OnStoreSave( ctx );
1990
1991
1995
1997 }
1998
2000 {
2001 if ( !super.OnStoreLoad( ctx, version ) )
2002 return false;
2003
2004
2005
2007 {
2009 return false;
2010 }
2012 {
2014 return false;
2015 }
2017 {
2019 return false;
2020 }
2021
2022
2024 {
2026 return false;
2027 }
2028
2029
2030 return true;
2031 }
2032
2034 {
2035 super.AfterStoreLoad();
2036
2038 {
2040 }
2041 }
2042
2044 {
2045
2047
2048
2051
2052
2054 }
2055
2057 {
2058 super.OnCreatePhysics();
2061 }
2062
2064 {
2066 return;
2067
2068 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2069
2071 return;
2072
2074 string part_name = zone;
2076
2078 {
2079 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2080
2081 if ( construction_part && construction.IsPartConstructed( part_name ) )
2082 {
2084 construction.DestroyConnectedParts(part_name);
2085 }
2086
2087
2088 if ( part_name.
Contains(
"barbed") )
2089 {
2090 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2091 if (barbed_wire)
2092 barbed_wire.SetMountedState( false );
2093 }
2094 }
2095 }
2096
2098 {
2100 {
2102 }
2103
2104 super.EEOnAfterLoad();
2105 }
2106
2108 {
2109 super.EEInit();
2110
2111
2113
2114
2115 #ifdef DEVELOPER
2117 #endif
2118 }
2119
2121 {
2122 super.EEItemAttached( item, slot_name );
2123
2127 }
2128
2130 {
2131 super.EEItemDetached( item, slot_name );
2132
2135 }
2136
2137 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2138 {
2141
2144 }
2145
2146
2148 {
2149 return true;
2150 }
2151
2152
2153
2155 {
2157
2158
2159 if (construtionPart.
IsBase())
2160 {
2162
2163
2165 }
2166
2167
2169
2170
2172
2173
2175
2177
2179
2180
2182
2183
2185 }
2186
2188 {
2189
2191 }
2192
2193
2195 {
2198
2199
2201
2202
2204
2205
2207
2208
2210
2212
2213
2215
2216
2218
2219
2220 if (construtionPart.
IsBase())
2221 {
2222
2224 }
2225 }
2226
2228 {
2229
2231 }
2232
2233
2234 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2235 {
2238
2239
2241
2242
2244
2245
2247
2248
2250
2252
2253
2255
2256
2258
2259
2260 if (construtionPart.
IsBase())
2261 {
2262
2264 }
2265 }
2266
2268 {
2269
2271 }
2272
2275 {
2276 bool process = false;
2277
2278
2282
2283 if (process)
2284 {
2285 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
2286 {
2288 return;
2289 }
2290
2292 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
2293 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
2294
2295
2297 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
2298 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
2299 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
2300 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
2301 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
2302 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
2303 mins = minTmp;
2304 maxs = maxTmp;
2305
2306 maxs[1] = maxs[1] + 0.35;
2307
2309 }
2310 }
2311
2314 {
2317
2318
2320 foreach (
EntityAI entity : foundEntities)
2321 {
2324 }
2325 }
2326
2327
2329 {
2331
2335 }
2336
2338 {
2340
2342 {
2344 }
2345 else
2346 {
2348 }
2349
2351 }
2352
2354 {
2356
2358 foreach (
string slotName : attachmentSlots)
2359 {
2361 }
2362
2363
2366 else
2368
2370 }
2371
2373 {
2374 string slotNameMounted = slot_name + "_Mounted";
2375 EntityAI attachment = FindAttachmentBySlotName(slot_name);
2376
2377 if (attachment)
2378 {
2379 BarbedWire barbedWire = BarbedWire.Cast(attachment);
2380 if (barbedWire && barbedWire.IsMounted())
2382 else
2384
2385 if (is_locked)
2386 {
2387 SetAnimationPhase(slotNameMounted, 0);
2388 SetAnimationPhase(slot_name, 1);
2389 }
2390 else
2391 {
2392 SetAnimationPhase(slotNameMounted, 1);
2393 SetAnimationPhase(slot_name, 0);
2394 }
2395 }
2396 else
2397 {
2398 SetAnimationPhase(slotNameMounted, 1);
2399 SetAnimationPhase(slot_name, 1);
2400
2402 }
2403 }
2404
2405
2407 {
2410
2413
2416
2417 foreach (
string slotName : attachmentSlots)
2418 {
2420 }
2421
2422
2424 {
2427
2429 }
2430 else
2431 {
2434
2436 }
2437
2440 }
2441
2443 {
2444
2446 return;
2447
2448 string slot_name_mounted = slot_name + "_Mounted";
2449 EntityAI attachment = FindAttachmentBySlotName( slot_name );
2450
2451
2453 RemoveProxyPhysics( slot_name_mounted );
2454 RemoveProxyPhysics( slot_name );
2455
2456 if ( attachment )
2457 {
2459 if ( is_locked )
2460 {
2462 AddProxyPhysics( slot_name_mounted );
2463 }
2464 else
2465 {
2467 AddProxyPhysics( slot_name );
2468 }
2469 }
2470 }
2471
2473 {
2474 SetAffectPathgraph( true, false );
2476 }
2477
2479 {
2480 return true;
2481 }
2482
2484 {
2485 return true;
2486 }
2487
2489 {
2490 if ( attachment )
2491 {
2493 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
2494
2495 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
2496 }
2497
2498 return false;
2499 }
2500
2502 {
2504 }
2505
2506
2508 {
2509 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
2510 if (
GetGame().ConfigIsExisting( config_path ) )
2511 {
2513 }
2514 }
2515
2517 {
2518 return true;
2519 }
2520
2522 {
2523 return true;
2524 }
2525
2527 {
2528 return true;
2529 }
2530
2531
2533 {
2535 {
2537 }
2538
2540 }
2541
2543 {
2545 }
2546
2547
2548
2550 {
2551 return super.CanReceiveAttachment(attachment, slotId);
2552 }
2553
2555 {
2556 int attachment_count = GetInventory().AttachmentCount();
2557 if ( attachment_count > 0 )
2558 {
2559 if (
HasBase() && attachment_count == 1 )
2560 {
2561 return false;
2562 }
2563
2564 return true;
2565 }
2566
2567 return false;
2568 }
2569
2571 {
2572 return true;
2573 }
2574
2576 {
2577 return false;
2578 }
2579
2580
2582 {
2583 return false;
2584 }
2585
2587 {
2588 return false;
2589 }
2590
2591
2593 {
2594 return false;
2595 }
2596
2597
2598
2600 {
2601 return true;
2602 }
2603
2605 {
2606 return true;
2607 }
2608
2611 {
2612 return false;
2613 }
2614
2615
2617 {
2618 return true;
2619 }
2620
2621
2623 {
2624 return false;
2625 }
2626
2627
2629 {
2630 return true;
2631 }
2632
2633
2635 {
2636 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
2637 {
2638 return false;
2639 }
2640
2641 return true;
2642 }
2643
2645 {
2648
2649 return item;
2650 }
2651
2652
2654 {
2656 {
2657
2659
2660
2663
2665 if ( MemoryPointExists( slot_name + "_min" ) )
2666 {
2667 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
2668 }
2669 if ( MemoryPointExists( slot_name + "_max" ) )
2670 {
2671 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
2672 }
2673
2674
2677
2678
2681 center = ModelToWorld( center );
2682
2683
2686
2687 areaDamage.SetExtents( extents[0], extents[1] );
2688 areaDamage.SetAreaPosition( center );
2689 areaDamage.SetAreaOrientation( orientation );
2692 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
2693 areaDamage.SetAmmoName( "BarbedWireHit" );
2694 areaDamage.Spawn();
2695
2697 }
2698 }
2699
2701 {
2702 if ( angle_deg != 0 )
2703 {
2704
2705 orientation[0] = orientation[0] - angle_deg;
2706
2707
2709 if ( MemoryPointExists( "rotate_axis" ) )
2710 {
2711 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
2712 }
2713 float r_center_x = (
Math.
Cos( angle_deg *
Math.
DEG2RAD ) * ( center[0] - rotate_axis[0] ) ) - (
Math.
Sin( angle_deg *
Math.
DEG2RAD ) * ( center[2] - rotate_axis[2] ) ) + rotate_axis[0];
2714 float r_center_z = (
Math.
Sin( angle_deg *
Math.
DEG2RAD ) * ( center[0] - rotate_axis[0] ) ) + (
Math.
Cos( angle_deg *
Math.
DEG2RAD ) * ( center[2] - rotate_axis[2] ) ) + rotate_axis[2];
2715 center[0] = r_center_x;
2716 center[2] = r_center_z;
2717 }
2718 }
2719
2721 {
2723 {
2726 {
2727 if (areaDamage)
2728 {
2729 areaDamage.Destroy();
2730 }
2731
2733 }
2734 }
2735 }
2736
2738 {
2739 return true;
2740 }
2741
2742
2743
2744
2746 {
2748 }
2749
2751 {
2753 }
2754
2756 {
2758 }
2759
2761 {
2763
2764 switch ( material_type )
2765 {
2771 }
2772
2773 return "";
2774 }
2775
2777 {
2779
2780 switch ( material_type )
2781 {
2787 }
2788
2789 return "";
2790 }
2791
2792
2794 {
2796 {
2797
2799 {
2800 SetHealth(slot_name,"Health",item.GetHealth());
2801 }
2802 }
2803 }
2804
2806 {
2807 return 111;
2808 }
2809
2811 {
2812 super.SetActions();
2813
2817 }
2818
2819
2820
2821
2823 {
2824 }
2825
2828 {
2829 return null;
2830 }
2831
2833 {
2835 }
2836
2838 {
2841
2842 Man p;
2843
2844 #ifdef SERVER
2847 if (players.Count())
2848 p = players[0];
2849 #else
2851 #endif
2852
2854 {
2855 bool excluded = false;
2857 if (excludes)
2858 {
2859 foreach (string exclude : excludes)
2860 {
2862 {
2863 excluded = true;
2864 break;
2865 }
2866 }
2867 }
2868
2869 if (!excluded)
2870 {
2872 }
2873 }
2874
2876 }
2877}
2878
2880{
2881#ifdef BSB_DEBUG
2883#else
2884
2885#endif
2886}
2888{
2889#ifdef BSB_DEBUG_SPAM
2891#else
2892
2893#endif
2894}
const int AT_DISMANTLE_PART
const int AT_DESTROY_PART
void AddAction(typename actionName)
void RemoveAction(typename actionName)
void AreaDamageManager(EntityAI parent)
void OnPartDismantledClient(string part_name, int action_id)
const string ANIMATION_DEPLOYED
override int GetHideIconMask()
override void OnStoreSave(ParamsWriteContext ctx)
void SetActionFromSyncData()
bool CheckMemoryPointVerticalDistance(float max_dist, string selection, PlayerBase player)
override void OnDebugSpawn()
array< string > OnDebugSpawnBuildExcludes()
Excludes certain parts from being built by OnDebugSpawn, uses Contains to compare.
void SoundDestroyStart(string part_name)
const string SOUND_BUILD_WOOD_LOG
void SoundBuildStart(string part_name)
void UpdateAttachmentVisuals(string slot_name, bool is_locked)
void CalcDamageAreaRotation(float angle_deg, out vector center, out vector orientation)
override bool CanObstruct()
bool HasAttachmentsBesidesBase()
override void InitItemSounds()
void RegisterPartForSync(int part_id)
const string SOUND_DISMANTLE_METAL
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
void SetPartsAfterStoreLoad()
void DestroyConstruction()
ref array< string > m_HybridAttachments
override string GetFoldSoundset()
string GetDismantleSoundByMaterial(string part_name)
bool IsAttachmentSlotLocked(EntityAI attachment)
override bool IsFacingPlayer(PlayerBase player, string selection)
void OnPartBuiltClient(string part_name, int action_id)
bool HasProperDistance(string selection, PlayerBase player)
override void OnCreatePhysics()
void OnPartBuiltServer(notnull Man player, string part_name, int action_id)
void RegisterActionForSync(int part_id, int action_id)
const string SOUND_BUILD_WOOD_PLANK
void SetPartsFromSyncData()
ref array< string > m_Mountables
const string SOUND_BUILD_WIRE
void ResetActionSyncData()
override string GetInvulnerabilityTypeString()
void OnPartDismantledServer(notnull Man player, string part_name, int action_id)
void CheckForHybridAttachments(EntityAI item, string slot_name)
override void EEOnAfterLoad()
override void EEItemDetached(EntityAI item, string slot_name)
vector GetKitSpawnPosition()
ref Construction m_Construction
bool IsFacingCamera(string selection)
bool CheckSlotVerticalDistance(int slot_id, PlayerBase player)
void GetAttachmentSlots(EntityAI entity, out array< string > attachment_slots)
override bool IsDeployable()
void OnPartDestroyedClient(string part_name, int action_id)
void UnregisterPartForSync(int part_id)
void bsbDebugSpam(string s)
override void OnVariablesSynchronized()
bool PerformRoofCheckForBase(string partName, PlayerBase player, out bool result)
Construction GetConstruction()
void SoundDismantleStart(string part_name)
ConstructionPart GetConstructionPartById(int id)
string GetConstructionKitType()
bool CheckLevelVerticalDistance(float max_dist, string selection, PlayerBase player)
void OnPartDestroyedServer(Man player, string part_name, int action_id, bool destroyed_by_connected_part=false)
bool CanFoldBaseBuildingObject()
override int GetDamageSystemVersionChange()
const string SOUND_DISMANTLE_WOOD_PLANK
override void EEItemAttached(EntityAI item, string slot_name)
const string SOUND_DISMANTLE_WOOD_LOG
class BaseBuildingBase extends ItemBase bsbDebugPrint(string s)
const string SOUND_BUILD_WOOD_STAIRS
ItemBase FoldBaseBuildingObject()
override bool CanPutInCargo(EntityAI parent)
override bool CanUseConstruction()
override void AfterStoreLoad()
void SetPartFromSyncData(ConstructionPart part)
override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
override bool IgnoreOutOfReachCondition()
override bool OnStoreLoad(ParamsReadContext ctx, int version)
override bool ShowZonesHealth()
void UpdateAttachmentPhysics(string slot_name, bool is_locked)
override bool IsPlayerInside(PlayerBase player, string selection)
string GetBuildSoundByMaterial(string part_name)
ItemBase CreateConstructionKit()
const string SOUND_DISMANTLE_WIRE
bool MustBeBuiltFromOutside()
Some buildings can only be built from outside.
override bool IsTakeable()
float m_ConstructionKitHealth
override void EEDelete(EntityAI parent)
override void SetActions()
void HandleItemFalling(ConstructionPart part)
Disconnected temporarily.
void DestroyConstructionKit(ItemBase construction_kit)
void CreateConstructionKitInHands(notnull PlayerBase player)
void ItemFall(vector min, vector max)
Disconnected temporarily.
override bool CanUseConstructionBuild()
void OnSynchronizedClient()
void SynchronizeBaseState()
override bool IsIgnoredByConstruction()
ref map< string, ref AreaDamageManager > m_DamageTriggers
void SetBaseState(bool has_base)
const string SOUND_BUILD_METAL
override string GetLoopFoldSoundset()
void OnSetSlotLock(int slotId, bool locked, bool was_locked)
override bool CanPutIntoHands(EntityAI parent)
bool IsPartBuildInSyncData(int part_id)
override bool CanRemoveFromCargo(EntityAI parent)
const string SOUND_DISMANTLE_WOOD_STAIRS
const int ECE_PLACE_ON_SURFACE
PlayerSpawnPreset slotName
void Construction(BaseBuildingBase parent)
void DayZPlayerUtils()
cannot be instantiated
string GetLoopFoldSoundset()
ItemSoundHandler GetItemSoundHandler()
bool m_FixDamageSystemInit
void ItemSoundHandler(ItemBase parent)
override void SetLoopInterval(float time)
A particular version of the deferred loop used to not damage players inside vehicles.
override void SetDeferDuration(float time)
proto native World GetWorld()
override ScriptCallQueue GetCallQueue(int call_category)
proto native void ConfigGetTextArray(string path, out TStringArray values)
Get array of strings from config on path.
proto native DayZPlayer GetPlayer()
proto native void ObjectDelete(Object obj)
Super root of all classes in Enforce script.
static void Log(string message=LOG_DEFAULT, string plugin=LOG_DEFAULT, string author=LOG_DEFAULT, string label=LOG_DEFAULT, string entity=LOG_DEFAULT)
Prints debug message with normal prio.
Wrapper class for managing sound through SEffectManager.
proto native int GetSlot()
returns slot id if current type is Attachment
static proto native int GetSlotIdFromString(string slot_name)
converts string to slot_id
static proto native owned string GetSlotName(int id)
converts slot_id to string
provides access to slot configuration
override bool CanUseConstruction()
static bool IsBaseBuildingLogEnable()
proto void CallLater(func fn, int delay=0, bool repeat=false, 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)
adds call into the queue with given parameters and arguments (arguments are held in memory until the ...
proto bool Write(void value_out)
proto bool Read(void value_in)
proto native void GetPlayerList(out array< Man > players)
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
override string GetDebugName()
Serializer ParamsReadContext
proto native CGame GetGame()
Serializer ParamsWriteContext
proto void PrintToRPT(void var)
Prints content of variable to RPT file (performance warning - each write means fflush!...
static proto bool CastTo(out Class to, Class from)
Try to safely down-cast base class to child class.
static proto float Max(float x, float y)
Returns bigger of two given values.
static proto float Min(float x, float y)
Returns smaller of two given values.
static proto float Cos(float angle)
Returns cosinus of angle in radians.
static proto float Sin(float angle)
Returns sinus of angle in radians.
static const float DEG2RAD
class JsonUndergroundAreaTriggerData GetPosition
bool Contains(string sample)
Returns true if sample is substring of string.
proto int ToLower()
Changes string to lowercase. Returns length.