1712{
1714
1716
1718
1720
1726
1727
1728
1734
1740
1742
1746
1747
1749 {
1751
1752
1753 RegisterNetSyncVariableInt( "m_SyncParts01" );
1754 RegisterNetSyncVariableInt( "m_SyncParts02" );
1755 RegisterNetSyncVariableInt( "m_SyncParts03" );
1756 RegisterNetSyncVariableInt( "m_InteractedPartId" );
1757 RegisterNetSyncVariableInt( "m_PerformedActionId" );
1758 RegisterNetSyncVariableBool( "m_HasBase" );
1759
1760
1762
1763 if (ConfigIsExisting("hybridAttachments"))
1764 {
1767 }
1768 if (ConfigIsExisting("mountables"))
1769 {
1772 }
1773
1775 }
1776
1778 {
1779 super.EEDelete(parent);
1780
1782 {
1783 areaDamage.Destroy();
1784 }
1785
1786 }
1787
1789 {
1790 return "disableBaseDamage";
1791 }
1792
1794 {
1795 return true;
1796 }
1797
1799 {
1800 return EInventoryIconVisibility.HIDE_VICINITY;
1801 }
1802
1804 {
1805 super.InitItemSounds();
1806
1810
1815 }
1816
1818 {
1819 return "putDown_FenceKit_SoundSet";
1820 }
1821
1823 {
1824 return "Shelter_Site_Build_Loop_SoundSet";
1825 }
1826
1827
1829 {
1831 {
1832 SetSynchDirty();
1833 }
1834 }
1835
1837 {
1839 super.OnVariablesSynchronized();
1840
1842 }
1843
1845 {
1846
1848
1849
1851
1852
1854 }
1855
1856
1858 {
1859
1860 int offset;
1861 int mask;
1862
1863 if ( part_id >= 1 && part_id <= 31 )
1864 {
1865 offset = part_id - 1;
1866 mask = 1 << offset;
1867
1869 }
1870 else if ( part_id >= 32 && part_id <= 62 )
1871 {
1872 offset = ( part_id % 32 );
1873 mask = 1 << offset;
1874
1876 }
1877 else if ( part_id >= 63 && part_id <= 93 )
1878 {
1879 offset = ( part_id % 63 );
1880 mask = 1 << offset;
1881
1883 }
1884 }
1885
1887 {
1888
1889 int offset;
1890 int mask;
1891
1892 if ( part_id >= 1 && part_id <= 31 )
1893 {
1894 offset = part_id - 1;
1895 mask = 1 << offset;
1896
1898 }
1899 else if ( part_id >= 32 && part_id <= 62 )
1900 {
1901 offset = ( part_id % 32 );
1902 mask = 1 << offset;
1903
1905 }
1906 else if ( part_id >= 63 && part_id <= 93 )
1907 {
1908 offset = ( part_id % 63 );
1909 mask = 1 << offset;
1910
1912 }
1913 }
1914
1916 {
1917
1918 int offset;
1919 int mask;
1920
1921 if ( part_id >= 1 && part_id <= 31 )
1922 {
1923 offset = part_id - 1;
1924 mask = 1 << offset;
1925
1927 {
1928 return true;
1929 }
1930 }
1931 else if ( part_id >= 32 && part_id <= 62 )
1932 {
1933 offset = ( part_id % 32 );
1934 mask = 1 << offset;
1935
1937 {
1938 return true;
1939 }
1940 }
1941 else if ( part_id >= 63 && part_id <= 93 )
1942 {
1943 offset = ( part_id % 63 );
1944 mask = 1 << offset;
1945
1947 {
1948 return true;
1949 }
1950 }
1951
1952 return false;
1953 }
1954
1956 {
1959 }
1960
1962 {
1963
1966 }
1967
1969 {
1971 {
1974
1975 switch( build_action_id )
1976 {
1980 }
1981 }
1982 }
1983
1984
1986 {
1988 bool is_base = part.
IsBase();
1991 if ( is_part_built_sync )
1992 {
1994 {
1998
1999 if (is_base)
2000 {
2003 }
2004 }
2005 }
2006 else
2007 {
2009 {
2013
2014 if (is_base)
2015 {
2018 }
2019 }
2020 }
2021
2022
2024 }
2025
2026
2028 {
2031
2032 for ( int i = 0; i < construction_parts.Count(); ++i )
2033 {
2034 string key = construction_parts.GetKey( i );
2037 }
2038
2039
2041 }
2042
2044 {
2047
2048 for ( int i = 0; i < construction_parts.Count(); ++i )
2049 {
2050 string key = construction_parts.GetKey( i );
2052
2053 if ( value.
GetId() ==
id )
2054 {
2055 return value;
2056 }
2057 }
2058
2059 return NULL;
2060 }
2061
2062
2063
2065 {
2067 }
2068
2070 {
2072 }
2073
2075 {
2076 return true;
2077 }
2078
2080 {
2081 return false;
2082 }
2083
2084
2086 {
2089 {
2091 }
2092
2093 return construction_kit;
2094 }
2095
2097 {
2100 {
2102 }
2103 }
2104
2106 {
2108 }
2109
2111 {
2112 return "";
2113 }
2114
2116 {
2119 }
2120
2121
2123 {
2126 }
2127
2128
2130 {
2131 super.OnStoreSave( ctx );
2132
2133
2137
2139 }
2140
2142 {
2143 if ( !super.OnStoreLoad( ctx, version ) )
2144 return false;
2145
2146
2147
2149 {
2151 return false;
2152 }
2154 {
2156 return false;
2157 }
2159 {
2161 return false;
2162 }
2163
2164
2166 {
2168 return false;
2169 }
2170
2171
2172 return true;
2173 }
2174
2176 {
2177 super.AfterStoreLoad();
2178
2180 {
2182 }
2183 }
2184
2186 {
2187
2189
2190
2193
2194
2196 }
2197
2199 {
2200 super.OnCreatePhysics();
2203 }
2204
2206 {
2208 return;
2209
2210 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2211
2213 return;
2214
2216 string part_name = zone;
2218
2220 {
2221 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2222
2223 if ( construction_part && construction.IsPartConstructed( part_name ) )
2224 {
2226 construction.DestroyConnectedParts(part_name);
2227 }
2228
2229
2230 if ( part_name.
Contains(
"barbed") )
2231 {
2232 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2233 if (barbed_wire)
2234 barbed_wire.SetMountedState( false );
2235 }
2236 }
2237 }
2238
2240 {
2242 {
2244 }
2245
2246 super.EEOnAfterLoad();
2247 }
2248
2250 {
2251 super.EEInit();
2252
2253
2255
2256
2257 #ifdef DEVELOPER
2259 #endif
2260 }
2261
2263 {
2264 super.EEItemAttached( item, slot_name );
2265
2269 }
2270
2272 {
2273 super.EEItemDetached( item, slot_name );
2274
2277 }
2278
2279 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2280 {
2283
2286 }
2287
2288
2290 {
2291 return true;
2292 }
2293
2294
2295
2297 {
2299
2300
2301 if (construtionPart.
IsBase())
2302 {
2304
2305
2307 }
2308
2309
2311
2312
2314
2315
2317
2319
2321
2322
2324
2325
2327 }
2328
2330 {
2331
2333 }
2334
2335
2337 {
2340
2341
2343
2344
2346
2347
2349
2350
2352
2354
2355
2357
2358
2360
2361
2362 if (construtionPart.
IsBase())
2363 {
2364
2366 }
2367 }
2368
2370 {
2371
2373 }
2374
2375
2376 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2377 {
2380
2381
2383
2384
2386
2387
2389
2390
2392
2394
2395
2397
2398
2400
2401
2402 if (construtionPart.
IsBase())
2403 {
2404
2406 }
2407 }
2408
2410 {
2411
2413 }
2414
2417 {
2418 bool process = false;
2419
2420
2424
2425 if (process)
2426 {
2427 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
2428 {
2430 return;
2431 }
2432
2434 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
2435 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
2436
2437
2439 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
2440 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
2441 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
2442 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
2443 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
2444 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
2445 mins = minTmp;
2446 maxs = maxTmp;
2447
2448 maxs[1] = maxs[1] + 0.35;
2449
2451 }
2452 }
2453
2456 {
2459
2460
2462 foreach (
EntityAI entity : foundEntities)
2463 {
2466 }
2467 }
2468
2469
2471 {
2473
2477 }
2478
2480 {
2482
2484 {
2486 }
2487 else
2488 {
2490 }
2491
2493 }
2494
2496 {
2498
2500 foreach (
string slotName : attachmentSlots)
2501 {
2503 }
2504
2505
2508 else
2510
2512 }
2513
2515 {
2516 string slotNameMounted = slot_name + "_Mounted";
2517 EntityAI attachment = FindAttachmentBySlotName(slot_name);
2518
2519 if (attachment)
2520 {
2521 BarbedWire barbedWire = BarbedWire.Cast(attachment);
2522 if (barbedWire && barbedWire.IsMounted())
2524 else
2526
2527 if (is_locked)
2528 {
2529 SetAnimationPhase(slotNameMounted, 0);
2530 SetAnimationPhase(slot_name, 1);
2531 }
2532 else
2533 {
2534 SetAnimationPhase(slotNameMounted, 1);
2535 SetAnimationPhase(slot_name, 0);
2536 }
2537 }
2538 else
2539 {
2540 SetAnimationPhase(slotNameMounted, 1);
2541 SetAnimationPhase(slot_name, 1);
2542
2544 }
2545 }
2546
2547
2549 {
2552
2555
2558
2559 foreach (
string slotName : attachmentSlots)
2560 {
2562 }
2563
2564
2566 {
2569
2571 }
2572 else
2573 {
2576
2578 }
2579
2582 }
2583
2585 {
2586
2588 return;
2589
2590 string slot_name_mounted = slot_name + "_Mounted";
2591 EntityAI attachment = FindAttachmentBySlotName( slot_name );
2592
2593
2595 RemoveProxyPhysics( slot_name_mounted );
2596 RemoveProxyPhysics( slot_name );
2597
2598 if ( attachment )
2599 {
2601 if ( is_locked )
2602 {
2604 AddProxyPhysics( slot_name_mounted );
2605 }
2606 else
2607 {
2609 AddProxyPhysics( slot_name );
2610 }
2611 }
2612 }
2613
2615 {
2616 SetAffectPathgraph( true, false );
2618 }
2619
2621 {
2622 return true;
2623 }
2624
2626 {
2627 return true;
2628 }
2629
2631 {
2632 if ( attachment )
2633 {
2635 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
2636
2637 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
2638 }
2639
2640 return false;
2641 }
2642
2644 {
2646 }
2647
2648
2650 {
2651 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
2652 if (
GetGame().ConfigIsExisting( config_path ) )
2653 {
2655 }
2656 }
2657
2659 {
2660 return true;
2661 }
2662
2664 {
2665 return true;
2666 }
2667
2669 {
2670 return true;
2671 }
2672
2673
2675 {
2677 {
2679 }
2680
2682 }
2683
2685 {
2687 }
2688
2689
2690
2692 {
2693 return super.CanReceiveAttachment(attachment, slotId);
2694 }
2695
2697 {
2698 int attachment_count = GetInventory().AttachmentCount();
2699 if ( attachment_count > 0 )
2700 {
2701 if (
HasBase() && attachment_count == 1 )
2702 {
2703 return false;
2704 }
2705
2706 return true;
2707 }
2708
2709 return false;
2710 }
2711
2713 {
2714 return true;
2715 }
2716
2718 {
2719 return false;
2720 }
2721
2722
2724 {
2725 return false;
2726 }
2727
2729 {
2730 return false;
2731 }
2732
2733
2735 {
2736 return false;
2737 }
2738
2739
2740
2742 {
2743 return true;
2744 }
2745
2747 {
2748 return true;
2749 }
2750
2753 {
2754 return false;
2755 }
2756
2757
2759 {
2760 return true;
2761 }
2762
2763
2765 {
2766 return false;
2767 }
2768
2769
2771 {
2772 return true;
2773 }
2774
2775
2777 {
2778 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
2779 {
2780 return false;
2781 }
2782
2783 return true;
2784 }
2785
2787 {
2790
2791 return item;
2792 }
2793
2794
2796 {
2798 {
2799
2801
2802
2805
2807 if ( MemoryPointExists( slot_name + "_min" ) )
2808 {
2809 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
2810 }
2811 if ( MemoryPointExists( slot_name + "_max" ) )
2812 {
2813 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
2814 }
2815
2816
2819
2820
2823 center = ModelToWorld( center );
2824
2825
2828
2829 areaDamage.SetExtents( extents[0], extents[1] );
2830 areaDamage.SetAreaPosition( center );
2831 areaDamage.SetAreaOrientation( orientation );
2834 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
2835 areaDamage.SetAmmoName( "BarbedWireHit" );
2836 areaDamage.Spawn();
2837
2839 }
2840 }
2841
2843 {
2844 if ( angle_deg != 0 )
2845 {
2846
2847 orientation[0] = orientation[0] - angle_deg;
2848
2849
2851 if ( MemoryPointExists( "rotate_axis" ) )
2852 {
2853 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
2854 }
2855 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];
2856 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];
2857 center[0] = r_center_x;
2858 center[2] = r_center_z;
2859 }
2860 }
2861
2863 {
2865 {
2868 {
2869 if (areaDamage)
2870 {
2871 areaDamage.Destroy();
2872 }
2873
2875 }
2876 }
2877 }
2878
2880 {
2881 return true;
2882 }
2883
2884
2885
2886
2888 {
2890 }
2891
2893 {
2895 }
2896
2898 {
2900 }
2901
2903 {
2905
2906 switch ( material_type )
2907 {
2913 }
2914
2915 return "";
2916 }
2917
2919 {
2921
2922 switch ( material_type )
2923 {
2929 }
2930
2931 return "";
2932 }
2933
2934
2936 {
2938 {
2939
2941 {
2942 SetHealth(slot_name,"Health",item.GetHealth());
2943 }
2944 }
2945 }
2946
2948 {
2949 return 111;
2950 }
2951
2953 {
2954 super.SetActions();
2955
2959 }
2960
2961
2962
2963
2965 {
2966 }
2967
2970 {
2971 return null;
2972 }
2973
2975 {
2977 }
2978
2980 {
2983
2984 Man p;
2985
2986 #ifdef SERVER
2989 if (players.Count())
2990 p = players[0];
2991 #else
2993 #endif
2994
2996 {
2997 bool excluded = false;
2999 if (excludes)
3000 {
3001 foreach (string exclude : excludes)
3002 {
3004 {
3005 excluded = true;
3006 break;
3007 }
3008 }
3009 }
3010
3011 if (!excluded)
3012 {
3014 }
3015 }
3016
3018 }
3019}
3020
3022{
3023#ifdef BSB_DEBUG
3025#else
3026
3027#endif
3028}
3030{
3031#ifdef BSB_DEBUG_SPAM
3033#else
3034
3035#endif
3036}
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.