1379{
1381
1383
1385
1387
1393
1394
1395
1401
1407
1409
1413
1414
1416 {
1418
1419
1420 RegisterNetSyncVariableInt( "m_SyncParts01" );
1421 RegisterNetSyncVariableInt( "m_SyncParts02" );
1422 RegisterNetSyncVariableInt( "m_SyncParts03" );
1423 RegisterNetSyncVariableInt( "m_InteractedPartId" );
1424 RegisterNetSyncVariableInt( "m_PerformedActionId" );
1425 RegisterNetSyncVariableBool( "m_HasBase" );
1426
1427
1429
1430 if (ConfigIsExisting("hybridAttachments"))
1431 {
1434 }
1435 if (ConfigIsExisting("mountables"))
1436 {
1439 }
1440
1442 }
1443
1445 {
1446 super.EEDelete(parent);
1447
1449 {
1450 areaDamage.Destroy();
1451 }
1452
1453 }
1454
1456 {
1457 return "disableBaseDamage";
1458 }
1459
1461 {
1462 return true;
1463 }
1464
1466 {
1467 return EInventoryIconVisibility.HIDE_VICINITY;
1468 }
1469
1471 {
1472 super.InitItemSounds();
1473
1477
1482 }
1483
1485 {
1486 return "putDown_FenceKit_SoundSet";
1487 }
1488
1490 {
1491 return "Shelter_Site_Build_Loop_SoundSet";
1492 }
1493
1494
1496 {
1498 {
1499 SetSynchDirty();
1500 }
1501 }
1502
1504 {
1506 super.OnVariablesSynchronized();
1507
1509 }
1510
1512 {
1513
1515
1516
1518
1519
1521 }
1522
1523
1525 {
1526
1527 int offset;
1528 int mask;
1529
1530 if ( part_id >= 1 && part_id <= 31 )
1531 {
1532 offset = part_id - 1;
1533 mask = 1 << offset;
1534
1536 }
1537 else if ( part_id >= 32 && part_id <= 62 )
1538 {
1539 offset = ( part_id % 32 );
1540 mask = 1 << offset;
1541
1543 }
1544 else if ( part_id >= 63 && part_id <= 93 )
1545 {
1546 offset = ( part_id % 63 );
1547 mask = 1 << offset;
1548
1550 }
1551 }
1552
1554 {
1555
1556 int offset;
1557 int mask;
1558
1559 if ( part_id >= 1 && part_id <= 31 )
1560 {
1561 offset = part_id - 1;
1562 mask = 1 << offset;
1563
1565 }
1566 else if ( part_id >= 32 && part_id <= 62 )
1567 {
1568 offset = ( part_id % 32 );
1569 mask = 1 << offset;
1570
1572 }
1573 else if ( part_id >= 63 && part_id <= 93 )
1574 {
1575 offset = ( part_id % 63 );
1576 mask = 1 << offset;
1577
1579 }
1580 }
1581
1583 {
1584
1585 int offset;
1586 int mask;
1587
1588 if ( part_id >= 1 && part_id <= 31 )
1589 {
1590 offset = part_id - 1;
1591 mask = 1 << offset;
1592
1594 {
1595 return true;
1596 }
1597 }
1598 else if ( part_id >= 32 && part_id <= 62 )
1599 {
1600 offset = ( part_id % 32 );
1601 mask = 1 << offset;
1602
1604 {
1605 return true;
1606 }
1607 }
1608 else if ( part_id >= 63 && part_id <= 93 )
1609 {
1610 offset = ( part_id % 63 );
1611 mask = 1 << offset;
1612
1614 {
1615 return true;
1616 }
1617 }
1618
1619 return false;
1620 }
1621
1623 {
1626 }
1627
1629 {
1630
1633 }
1634
1636 {
1638 {
1641
1642 switch( build_action_id )
1643 {
1647 }
1648 }
1649 }
1650
1651
1653 {
1655 bool is_base = part.
IsBase();
1658 if ( is_part_built_sync )
1659 {
1661 {
1665
1666 if (is_base)
1667 {
1670 }
1671 }
1672 }
1673 else
1674 {
1676 {
1680
1681 if (is_base)
1682 {
1685 }
1686 }
1687 }
1688
1689
1691 }
1692
1693
1695 {
1698
1699 for ( int i = 0; i < construction_parts.Count(); ++i )
1700 {
1701 string key = construction_parts.GetKey( i );
1704 }
1705
1706
1708 }
1709
1711 {
1714
1715 for ( int i = 0; i < construction_parts.Count(); ++i )
1716 {
1717 string key = construction_parts.GetKey( i );
1719
1720 if ( value.
GetId() ==
id )
1721 {
1722 return value;
1723 }
1724 }
1725
1726 return NULL;
1727 }
1728
1729
1730
1732 {
1734 }
1735
1737 {
1739 }
1740
1742 {
1743 return true;
1744 }
1745
1747 {
1748 return false;
1749 }
1750
1751
1753 {
1756 {
1758 }
1759
1760 return construction_kit;
1761 }
1762
1764 {
1767 {
1769 }
1770 }
1771
1773 {
1775 }
1776
1778 {
1779 return "";
1780 }
1781
1783 {
1786 }
1787
1788
1790 {
1793 }
1794
1795
1797 {
1798 super.OnStoreSave( ctx );
1799
1800
1804
1806 }
1807
1809 {
1810 if ( !super.OnStoreLoad( ctx, version ) )
1811 return false;
1812
1813
1814
1816 {
1818 return false;
1819 }
1821 {
1823 return false;
1824 }
1826 {
1828 return false;
1829 }
1830
1831
1833 {
1835 return false;
1836 }
1837
1838
1839 return true;
1840 }
1841
1843 {
1844 super.AfterStoreLoad();
1845
1847 {
1849 }
1850 }
1851
1853 {
1854
1856
1857
1860
1861
1863 }
1864
1866 {
1867 super.OnCreatePhysics();
1870 }
1871
1873 {
1875 return;
1876
1877 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
1878
1880 return;
1881
1883 string part_name = zone;
1885
1887 {
1888 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
1889
1890 if ( construction_part && construction.IsPartConstructed( part_name ) )
1891 {
1893 construction.DestroyConnectedParts(part_name);
1894 }
1895
1896
1897 if ( part_name.
Contains(
"barbed") )
1898 {
1899 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
1900 if (barbed_wire)
1901 barbed_wire.SetMountedState( false );
1902 }
1903 }
1904 }
1905
1907 {
1909 {
1911 }
1912
1913 super.EEOnAfterLoad();
1914 }
1915
1917 {
1918 super.EEInit();
1919
1920
1922
1923
1924 #ifdef DEVELOPER
1926 #endif
1927 }
1928
1930 {
1931 super.EEItemAttached( item, slot_name );
1932
1936 }
1937
1939 {
1940 super.EEItemDetached( item, slot_name );
1941
1944 }
1945
1946 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
1947 {
1950
1953 }
1954
1955
1957 {
1958 return true;
1959 }
1960
1961
1962
1964 {
1966
1967
1968 if (construtionPart.
IsBase())
1969 {
1971
1972
1974 }
1975
1976
1978
1979
1981
1982
1984
1986
1988
1989
1991
1992
1994 }
1995
1997 {
1998
2000 }
2001
2002
2004 {
2007
2008
2010
2011
2013
2014
2016
2017
2019
2021
2022
2024
2025
2027
2028
2029 if (construtionPart.
IsBase())
2030 {
2031
2033 }
2034 }
2035
2037 {
2038
2040 }
2041
2042
2043 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2044 {
2047
2048
2050
2051
2053
2054
2056
2057
2059
2061
2062
2064
2065
2067
2068
2069 if (construtionPart.
IsBase())
2070 {
2071
2073 }
2074 }
2075
2077 {
2078
2080 }
2081
2084 {
2085 bool process = false;
2086
2087
2091
2092 if (process)
2093 {
2094 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
2095 {
2097 return;
2098 }
2099
2101 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
2102 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
2103
2104
2106 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
2107 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
2108 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
2109 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
2110 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
2111 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
2112 mins = minTmp;
2113 maxs = maxTmp;
2114
2115 maxs[1] = maxs[1] + 0.35;
2116
2118 }
2119 }
2120
2123 {
2126
2127
2129 foreach (
EntityAI entity : foundEntities)
2130 {
2133 }
2134 }
2135
2136
2138 {
2140
2144 }
2145
2147 {
2149
2151 {
2153 }
2154 else
2155 {
2157 }
2158
2160 }
2161
2163 {
2165
2167 foreach (
string slotName : attachmentSlots)
2168 {
2170 }
2171
2172
2175 else
2177
2179 }
2180
2182 {
2183 string slotNameMounted = slot_name + "_Mounted";
2184 EntityAI attachment = FindAttachmentBySlotName(slot_name);
2185
2186 if (attachment)
2187 {
2188 BarbedWire barbedWire = BarbedWire.Cast(attachment);
2189 if (barbedWire && barbedWire.IsMounted())
2191 else
2193
2194 if (is_locked)
2195 {
2196 SetAnimationPhase(slotNameMounted, 0);
2197 SetAnimationPhase(slot_name, 1);
2198 }
2199 else
2200 {
2201 SetAnimationPhase(slotNameMounted, 1);
2202 SetAnimationPhase(slot_name, 0);
2203 }
2204 }
2205 else
2206 {
2207 SetAnimationPhase(slotNameMounted, 1);
2208 SetAnimationPhase(slot_name, 1);
2209
2211 }
2212 }
2213
2214
2216 {
2219
2222
2225
2226 foreach (
string slotName : attachmentSlots)
2227 {
2229 }
2230
2231
2233 {
2236
2238 }
2239 else
2240 {
2243
2245 }
2246
2249 }
2250
2252 {
2253
2255 return;
2256
2257 string slot_name_mounted = slot_name + "_Mounted";
2258 EntityAI attachment = FindAttachmentBySlotName( slot_name );
2259
2260
2262 RemoveProxyPhysics( slot_name_mounted );
2263 RemoveProxyPhysics( slot_name );
2264
2265 if ( attachment )
2266 {
2268 if ( is_locked )
2269 {
2271 AddProxyPhysics( slot_name_mounted );
2272 }
2273 else
2274 {
2276 AddProxyPhysics( slot_name );
2277 }
2278 }
2279 }
2280
2282 {
2283 SetAffectPathgraph( true, false );
2285 }
2286
2288 {
2289 return true;
2290 }
2291
2293 {
2294 return true;
2295 }
2296
2298 {
2299 if ( attachment )
2300 {
2302 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
2303
2304 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
2305 }
2306
2307 return false;
2308 }
2309
2311 {
2313 }
2314
2315
2317 {
2318 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
2319 if (
GetGame().ConfigIsExisting( config_path ) )
2320 {
2322 }
2323 }
2324
2326 {
2327 return true;
2328 }
2329
2331 {
2332 return true;
2333 }
2334
2336 {
2337 return true;
2338 }
2339
2340
2342 {
2344 {
2346 }
2347
2349 }
2350
2352 {
2354 }
2355
2356
2357
2359 {
2360 return super.CanReceiveAttachment(attachment, slotId);
2361 }
2362
2364 {
2365 int attachment_count = GetInventory().AttachmentCount();
2366 if ( attachment_count > 0 )
2367 {
2368 if (
HasBase() && attachment_count == 1 )
2369 {
2370 return false;
2371 }
2372
2373 return true;
2374 }
2375
2376 return false;
2377 }
2378
2380 {
2381 return true;
2382 }
2383
2385 {
2386 return false;
2387 }
2388
2389
2391 {
2392 return false;
2393 }
2394
2396 {
2397 return false;
2398 }
2399
2400
2402 {
2403 return false;
2404 }
2405
2406
2407
2409 {
2410 return true;
2411 }
2412
2414 {
2415 return true;
2416 }
2417
2420 {
2421 return false;
2422 }
2423
2424
2426 {
2427 return true;
2428 }
2429
2430
2432 {
2433 return false;
2434 }
2435
2436
2438 {
2439 return true;
2440 }
2441
2442
2444 {
2445 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
2446 {
2447 return false;
2448 }
2449
2450 return true;
2451 }
2452
2454 {
2457
2458 return item;
2459 }
2460
2461
2463 {
2465 {
2466
2468
2469
2472
2474 if ( MemoryPointExists( slot_name + "_min" ) )
2475 {
2476 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
2477 }
2478 if ( MemoryPointExists( slot_name + "_max" ) )
2479 {
2480 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
2481 }
2482
2483
2486
2487
2490 center = ModelToWorld( center );
2491
2492
2495
2496 areaDamage.SetExtents( extents[0], extents[1] );
2497 areaDamage.SetAreaPosition( center );
2498 areaDamage.SetAreaOrientation( orientation );
2501 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
2502 areaDamage.SetAmmoName( "BarbedWireHit" );
2503 areaDamage.Spawn();
2504
2506 }
2507 }
2508
2510 {
2511 if ( angle_deg != 0 )
2512 {
2513
2514 orientation[0] = orientation[0] - angle_deg;
2515
2516
2518 if ( MemoryPointExists( "rotate_axis" ) )
2519 {
2520 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
2521 }
2522 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];
2523 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];
2524 center[0] = r_center_x;
2525 center[2] = r_center_z;
2526 }
2527 }
2528
2530 {
2532 {
2535 {
2536 if (areaDamage)
2537 {
2538 areaDamage.Destroy();
2539 }
2540
2542 }
2543 }
2544 }
2545
2547 {
2548 return true;
2549 }
2550
2551
2552
2553
2555 {
2557 }
2558
2560 {
2562 }
2563
2565 {
2567 }
2568
2570 {
2572
2573 switch ( material_type )
2574 {
2580 }
2581
2582 return "";
2583 }
2584
2586 {
2588
2589 switch ( material_type )
2590 {
2596 }
2597
2598 return "";
2599 }
2600
2601
2603 {
2605 {
2606
2608 {
2609 SetHealth(slot_name,"Health",item.GetHealth());
2610 }
2611 }
2612 }
2613
2615 {
2616 return 111;
2617 }
2618
2620 {
2621 super.SetActions();
2622
2626 }
2627
2628
2629
2630
2632 {
2633 }
2634
2637 {
2638 return null;
2639 }
2640
2642 {
2644 }
2645
2647 {
2650
2651 Man p;
2652
2653 #ifdef SERVER
2656 if (players.Count())
2657 p = players[0];
2658 #else
2660 #endif
2661
2663 {
2664 bool excluded = false;
2666 if (excludes)
2667 {
2668 foreach (string exclude : excludes)
2669 {
2671 {
2672 excluded = true;
2673 break;
2674 }
2675 }
2676 }
2677
2678 if (!excluded)
2679 {
2681 }
2682 }
2683
2685 }
2686}
2687
2689{
2690#ifdef BSB_DEBUG
2692#else
2693
2694#endif
2695}
2697{
2698#ifdef BSB_DEBUG_SPAM
2700#else
2701
2702#endif
2703}
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.