1424{
1426
1428
1430
1432
1438
1439
1440
1446
1452
1454
1458
1459
1461 {
1463
1464
1465 RegisterNetSyncVariableInt( "m_SyncParts01" );
1466 RegisterNetSyncVariableInt( "m_SyncParts02" );
1467 RegisterNetSyncVariableInt( "m_SyncParts03" );
1468 RegisterNetSyncVariableInt( "m_InteractedPartId" );
1469 RegisterNetSyncVariableInt( "m_PerformedActionId" );
1470 RegisterNetSyncVariableBool( "m_HasBase" );
1471
1472
1474
1475 if (ConfigIsExisting("hybridAttachments"))
1476 {
1479 }
1480 if (ConfigIsExisting("mountables"))
1481 {
1484 }
1485
1487 }
1488
1490 {
1491 super.EEDelete(parent);
1492
1494 {
1495 areaDamage.Destroy();
1496 }
1497
1498 }
1499
1501 {
1502 return "disableBaseDamage";
1503 }
1504
1506 {
1507 return true;
1508 }
1509
1511 {
1512 return EInventoryIconVisibility.HIDE_VICINITY;
1513 }
1514
1516 {
1517 super.InitItemSounds();
1518
1522
1527 }
1528
1530 {
1531 return "putDown_FenceKit_SoundSet";
1532 }
1533
1535 {
1536 return "Shelter_Site_Build_Loop_SoundSet";
1537 }
1538
1539
1541 {
1543 {
1544 SetSynchDirty();
1545 }
1546 }
1547
1549 {
1551 super.OnVariablesSynchronized();
1552
1554 }
1555
1557 {
1558
1560
1561
1563
1564
1566 }
1567
1568
1570 {
1571
1572 int offset;
1573 int mask;
1574
1575 if ( part_id >= 1 && part_id <= 31 )
1576 {
1577 offset = part_id - 1;
1578 mask = 1 << offset;
1579
1581 }
1582 else if ( part_id >= 32 && part_id <= 62 )
1583 {
1584 offset = ( part_id % 32 );
1585 mask = 1 << offset;
1586
1588 }
1589 else if ( part_id >= 63 && part_id <= 93 )
1590 {
1591 offset = ( part_id % 63 );
1592 mask = 1 << offset;
1593
1595 }
1596 }
1597
1599 {
1600
1601 int offset;
1602 int mask;
1603
1604 if ( part_id >= 1 && part_id <= 31 )
1605 {
1606 offset = part_id - 1;
1607 mask = 1 << offset;
1608
1610 }
1611 else if ( part_id >= 32 && part_id <= 62 )
1612 {
1613 offset = ( part_id % 32 );
1614 mask = 1 << offset;
1615
1617 }
1618 else if ( part_id >= 63 && part_id <= 93 )
1619 {
1620 offset = ( part_id % 63 );
1621 mask = 1 << offset;
1622
1624 }
1625 }
1626
1628 {
1629
1630 int offset;
1631 int mask;
1632
1633 if ( part_id >= 1 && part_id <= 31 )
1634 {
1635 offset = part_id - 1;
1636 mask = 1 << offset;
1637
1639 {
1640 return true;
1641 }
1642 }
1643 else if ( part_id >= 32 && part_id <= 62 )
1644 {
1645 offset = ( part_id % 32 );
1646 mask = 1 << offset;
1647
1649 {
1650 return true;
1651 }
1652 }
1653 else if ( part_id >= 63 && part_id <= 93 )
1654 {
1655 offset = ( part_id % 63 );
1656 mask = 1 << offset;
1657
1659 {
1660 return true;
1661 }
1662 }
1663
1664 return false;
1665 }
1666
1668 {
1671 }
1672
1674 {
1675
1678 }
1679
1681 {
1683 {
1686
1687 switch( build_action_id )
1688 {
1692 }
1693 }
1694 }
1695
1696
1698 {
1700 bool is_base = part.
IsBase();
1703 if ( is_part_built_sync )
1704 {
1706 {
1710
1711 if (is_base)
1712 {
1715 }
1716 }
1717 }
1718 else
1719 {
1721 {
1725
1726 if (is_base)
1727 {
1730 }
1731 }
1732 }
1733
1734
1736 }
1737
1738
1740 {
1743
1744 for ( int i = 0; i < construction_parts.Count(); ++i )
1745 {
1746 string key = construction_parts.GetKey( i );
1749 }
1750
1751
1753 }
1754
1756 {
1759
1760 for ( int i = 0; i < construction_parts.Count(); ++i )
1761 {
1762 string key = construction_parts.GetKey( i );
1764
1765 if ( value.
GetId() ==
id )
1766 {
1767 return value;
1768 }
1769 }
1770
1771 return NULL;
1772 }
1773
1774
1775
1777 {
1779 }
1780
1782 {
1784 }
1785
1787 {
1788 return true;
1789 }
1790
1792 {
1793 return false;
1794 }
1795
1796
1798 {
1801 {
1803 }
1804
1805 return construction_kit;
1806 }
1807
1809 {
1812 {
1814 }
1815 }
1816
1818 {
1820 }
1821
1823 {
1824 return "";
1825 }
1826
1828 {
1831 }
1832
1833
1835 {
1838 }
1839
1840
1842 {
1843 super.OnStoreSave( ctx );
1844
1845
1849
1851 }
1852
1854 {
1855 if ( !super.OnStoreLoad( ctx, version ) )
1856 return false;
1857
1858
1859
1861 {
1863 return false;
1864 }
1866 {
1868 return false;
1869 }
1871 {
1873 return false;
1874 }
1875
1876
1878 {
1880 return false;
1881 }
1882
1883
1884 return true;
1885 }
1886
1888 {
1889 super.AfterStoreLoad();
1890
1892 {
1894 }
1895 }
1896
1898 {
1899
1901
1902
1905
1906
1908 }
1909
1911 {
1912 super.OnCreatePhysics();
1915 }
1916
1918 {
1920 return;
1921
1922 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
1923
1925 return;
1926
1928 string part_name = zone;
1930
1932 {
1933 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
1934
1935 if ( construction_part && construction.IsPartConstructed( part_name ) )
1936 {
1938 construction.DestroyConnectedParts(part_name);
1939 }
1940
1941
1942 if ( part_name.
Contains(
"barbed") )
1943 {
1944 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
1945 if (barbed_wire)
1946 barbed_wire.SetMountedState( false );
1947 }
1948 }
1949 }
1950
1952 {
1954 {
1956 }
1957
1958 super.EEOnAfterLoad();
1959 }
1960
1962 {
1963 super.EEInit();
1964
1965
1967
1968
1969 #ifdef DEVELOPER
1971 #endif
1972 }
1973
1975 {
1976 super.EEItemAttached( item, slot_name );
1977
1981 }
1982
1984 {
1985 super.EEItemDetached( item, slot_name );
1986
1989 }
1990
1991 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
1992 {
1995
1998 }
1999
2000
2002 {
2003 return true;
2004 }
2005
2006
2007
2009 {
2011
2012
2013 if (construtionPart.
IsBase())
2014 {
2016
2017
2019 }
2020
2021
2023
2024
2026
2027
2029
2031
2033
2034
2036
2037
2039 }
2040
2042 {
2043
2045 }
2046
2047
2049 {
2052
2053
2055
2056
2058
2059
2061
2062
2064
2066
2067
2069
2070
2072
2073
2074 if (construtionPart.
IsBase())
2075 {
2076
2078 }
2079 }
2080
2082 {
2083
2085 }
2086
2087
2088 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2089 {
2092
2093
2095
2096
2098
2099
2101
2102
2104
2106
2107
2109
2110
2112
2113
2114 if (construtionPart.
IsBase())
2115 {
2116
2118 }
2119 }
2120
2122 {
2123
2125 }
2126
2129 {
2130 bool process = false;
2131
2132
2136
2137 if (process)
2138 {
2139 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
2140 {
2142 return;
2143 }
2144
2146 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
2147 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
2148
2149
2151 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
2152 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
2153 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
2154 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
2155 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
2156 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
2157 mins = minTmp;
2158 maxs = maxTmp;
2159
2160 maxs[1] = maxs[1] + 0.35;
2161
2163 }
2164 }
2165
2168 {
2171
2172
2174 foreach (
EntityAI entity : foundEntities)
2175 {
2178 }
2179 }
2180
2181
2183 {
2185
2189 }
2190
2192 {
2194
2196 {
2198 }
2199 else
2200 {
2202 }
2203
2205 }
2206
2208 {
2210
2212 foreach (
string slotName : attachmentSlots)
2213 {
2215 }
2216
2217
2220 else
2222
2224 }
2225
2227 {
2228 string slotNameMounted = slot_name + "_Mounted";
2229 EntityAI attachment = FindAttachmentBySlotName(slot_name);
2230
2231 if (attachment)
2232 {
2233 BarbedWire barbedWire = BarbedWire.Cast(attachment);
2234 if (barbedWire && barbedWire.IsMounted())
2236 else
2238
2239 if (is_locked)
2240 {
2241 SetAnimationPhase(slotNameMounted, 0);
2242 SetAnimationPhase(slot_name, 1);
2243 }
2244 else
2245 {
2246 SetAnimationPhase(slotNameMounted, 1);
2247 SetAnimationPhase(slot_name, 0);
2248 }
2249 }
2250 else
2251 {
2252 SetAnimationPhase(slotNameMounted, 1);
2253 SetAnimationPhase(slot_name, 1);
2254
2256 }
2257 }
2258
2259
2261 {
2264
2267
2270
2271 foreach (
string slotName : attachmentSlots)
2272 {
2274 }
2275
2276
2278 {
2281
2283 }
2284 else
2285 {
2288
2290 }
2291
2294 }
2295
2297 {
2298
2300 return;
2301
2302 string slot_name_mounted = slot_name + "_Mounted";
2303 EntityAI attachment = FindAttachmentBySlotName( slot_name );
2304
2305
2307 RemoveProxyPhysics( slot_name_mounted );
2308 RemoveProxyPhysics( slot_name );
2309
2310 if ( attachment )
2311 {
2313 if ( is_locked )
2314 {
2316 AddProxyPhysics( slot_name_mounted );
2317 }
2318 else
2319 {
2321 AddProxyPhysics( slot_name );
2322 }
2323 }
2324 }
2325
2327 {
2328 SetAffectPathgraph( true, false );
2330 }
2331
2333 {
2334 return true;
2335 }
2336
2338 {
2339 return true;
2340 }
2341
2343 {
2344 if ( attachment )
2345 {
2347 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
2348
2349 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
2350 }
2351
2352 return false;
2353 }
2354
2356 {
2358 }
2359
2360
2362 {
2363 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
2364 if (
GetGame().ConfigIsExisting( config_path ) )
2365 {
2367 }
2368 }
2369
2371 {
2372 return true;
2373 }
2374
2376 {
2377 return true;
2378 }
2379
2381 {
2382 return true;
2383 }
2384
2385
2387 {
2389 {
2391 }
2392
2394 }
2395
2397 {
2399 }
2400
2401
2402
2404 {
2405 return super.CanReceiveAttachment(attachment, slotId);
2406 }
2407
2409 {
2410 int attachment_count = GetInventory().AttachmentCount();
2411 if ( attachment_count > 0 )
2412 {
2413 if (
HasBase() && attachment_count == 1 )
2414 {
2415 return false;
2416 }
2417
2418 return true;
2419 }
2420
2421 return false;
2422 }
2423
2425 {
2426 return true;
2427 }
2428
2430 {
2431 return false;
2432 }
2433
2434
2436 {
2437 return false;
2438 }
2439
2441 {
2442 return false;
2443 }
2444
2445
2447 {
2448 return false;
2449 }
2450
2451
2452
2454 {
2455 return true;
2456 }
2457
2459 {
2460 return true;
2461 }
2462
2465 {
2466 return false;
2467 }
2468
2469
2471 {
2472 return true;
2473 }
2474
2475
2477 {
2478 return false;
2479 }
2480
2481
2483 {
2484 return true;
2485 }
2486
2487
2489 {
2490 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
2491 {
2492 return false;
2493 }
2494
2495 return true;
2496 }
2497
2499 {
2502
2503 return item;
2504 }
2505
2506
2508 {
2510 {
2511
2513
2514
2517
2519 if ( MemoryPointExists( slot_name + "_min" ) )
2520 {
2521 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
2522 }
2523 if ( MemoryPointExists( slot_name + "_max" ) )
2524 {
2525 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
2526 }
2527
2528
2531
2532
2535 center = ModelToWorld( center );
2536
2537
2540
2541 areaDamage.SetExtents( extents[0], extents[1] );
2542 areaDamage.SetAreaPosition( center );
2543 areaDamage.SetAreaOrientation( orientation );
2546 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
2547 areaDamage.SetAmmoName( "BarbedWireHit" );
2548 areaDamage.Spawn();
2549
2551 }
2552 }
2553
2555 {
2556 if ( angle_deg != 0 )
2557 {
2558
2559 orientation[0] = orientation[0] - angle_deg;
2560
2561
2563 if ( MemoryPointExists( "rotate_axis" ) )
2564 {
2565 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
2566 }
2567 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];
2568 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];
2569 center[0] = r_center_x;
2570 center[2] = r_center_z;
2571 }
2572 }
2573
2575 {
2577 {
2580 {
2581 if (areaDamage)
2582 {
2583 areaDamage.Destroy();
2584 }
2585
2587 }
2588 }
2589 }
2590
2592 {
2593 return true;
2594 }
2595
2596
2597
2598
2600 {
2602 }
2603
2605 {
2607 }
2608
2610 {
2612 }
2613
2615 {
2617
2618 switch ( material_type )
2619 {
2625 }
2626
2627 return "";
2628 }
2629
2631 {
2633
2634 switch ( material_type )
2635 {
2641 }
2642
2643 return "";
2644 }
2645
2646
2648 {
2650 {
2651
2653 {
2654 SetHealth(slot_name,"Health",item.GetHealth());
2655 }
2656 }
2657 }
2658
2660 {
2661 return 111;
2662 }
2663
2665 {
2666 super.SetActions();
2667
2671 }
2672
2673
2674
2675
2677 {
2678 }
2679
2682 {
2683 return null;
2684 }
2685
2687 {
2689 }
2690
2692 {
2695
2696 Man p;
2697
2698 #ifdef SERVER
2701 if (players.Count())
2702 p = players[0];
2703 #else
2705 #endif
2706
2708 {
2709 bool excluded = false;
2711 if (excludes)
2712 {
2713 foreach (string exclude : excludes)
2714 {
2716 {
2717 excluded = true;
2718 break;
2719 }
2720 }
2721 }
2722
2723 if (!excluded)
2724 {
2726 }
2727 }
2728
2730 }
2731}
2732
2734{
2735#ifdef BSB_DEBUG
2737#else
2738
2739#endif
2740}
2742{
2743#ifdef BSB_DEBUG_SPAM
2745#else
2746
2747#endif
2748}
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.