2011{
2013
2015
2017
2019
2025
2026
2027
2033
2039
2041
2045
2046
2048 {
2050
2051
2052 RegisterNetSyncVariableInt( "m_SyncParts01" );
2053 RegisterNetSyncVariableInt( "m_SyncParts02" );
2054 RegisterNetSyncVariableInt( "m_SyncParts03" );
2055 RegisterNetSyncVariableInt( "m_InteractedPartId" );
2056 RegisterNetSyncVariableInt( "m_PerformedActionId" );
2057 RegisterNetSyncVariableBool( "m_HasBase" );
2058
2059
2061
2062 if (ConfigIsExisting("hybridAttachments"))
2063 {
2066 }
2067 if (ConfigIsExisting("mountables"))
2068 {
2071 }
2072
2074 }
2075
2077 {
2078 super.EEDelete(parent);
2079
2081 {
2082 areaDamage.Destroy();
2083 }
2084
2085 }
2086
2088 {
2089 return "disableBaseDamage";
2090 }
2091
2093 {
2094 return true;
2095 }
2096
2098 {
2099 return EInventoryIconVisibility.HIDE_VICINITY;
2100 }
2101
2103 {
2104 super.InitItemSounds();
2105
2109
2114 }
2115
2117 {
2118 return "putDown_FenceKit_SoundSet";
2119 }
2120
2122 {
2123 return "Shelter_Site_Build_Loop_SoundSet";
2124 }
2125
2126
2128 {
2130 {
2131 SetSynchDirty();
2132 }
2133 }
2134
2136 {
2138 super.OnVariablesSynchronized();
2139
2141 }
2142
2144 {
2145
2147
2148
2150
2151
2153 }
2154
2155
2157 {
2158
2159 int offset;
2160 int mask;
2161
2162 if ( part_id >= 1 && part_id <= 31 )
2163 {
2164 offset = part_id - 1;
2165 mask = 1 << offset;
2166
2168 }
2169 else if ( part_id >= 32 && part_id <= 62 )
2170 {
2171 offset = ( part_id % 32 );
2172 mask = 1 << offset;
2173
2175 }
2176 else if ( part_id >= 63 && part_id <= 93 )
2177 {
2178 offset = ( part_id % 63 );
2179 mask = 1 << offset;
2180
2182 }
2183 }
2184
2186 {
2187
2188 int offset;
2189 int mask;
2190
2191 if ( part_id >= 1 && part_id <= 31 )
2192 {
2193 offset = part_id - 1;
2194 mask = 1 << offset;
2195
2197 }
2198 else if ( part_id >= 32 && part_id <= 62 )
2199 {
2200 offset = ( part_id % 32 );
2201 mask = 1 << offset;
2202
2204 }
2205 else if ( part_id >= 63 && part_id <= 93 )
2206 {
2207 offset = ( part_id % 63 );
2208 mask = 1 << offset;
2209
2211 }
2212 }
2213
2215 {
2216
2217 int offset;
2218 int mask;
2219
2220 if ( part_id >= 1 && part_id <= 31 )
2221 {
2222 offset = part_id - 1;
2223 mask = 1 << offset;
2224
2226 {
2227 return true;
2228 }
2229 }
2230 else if ( part_id >= 32 && part_id <= 62 )
2231 {
2232 offset = ( part_id % 32 );
2233 mask = 1 << offset;
2234
2236 {
2237 return true;
2238 }
2239 }
2240 else if ( part_id >= 63 && part_id <= 93 )
2241 {
2242 offset = ( part_id % 63 );
2243 mask = 1 << offset;
2244
2246 {
2247 return true;
2248 }
2249 }
2250
2251 return false;
2252 }
2253
2255 {
2258 }
2259
2261 {
2262
2265 }
2266
2268 {
2270 {
2273
2274 switch( build_action_id )
2275 {
2279 }
2280 }
2281 }
2282
2283
2285 {
2287 bool is_base = part.
IsBase();
2290 if ( is_part_built_sync )
2291 {
2293 {
2297
2298 if (is_base)
2299 {
2302 }
2303 }
2304 }
2305 else
2306 {
2308 {
2312
2313 if (is_base)
2314 {
2317 }
2318 }
2319 }
2320
2321
2323 }
2324
2325
2327 {
2330
2331 for ( int i = 0; i < construction_parts.Count(); ++i )
2332 {
2333 string key = construction_parts.GetKey( i );
2336 }
2337
2338
2340 }
2341
2343 {
2346
2347 for ( int i = 0; i < construction_parts.Count(); ++i )
2348 {
2349 string key = construction_parts.GetKey( i );
2351
2352 if ( value.
GetId() ==
id )
2353 {
2354 return value;
2355 }
2356 }
2357
2358 return NULL;
2359 }
2360
2361
2362
2364 {
2366 }
2367
2369 {
2371 }
2372
2374 {
2375 return true;
2376 }
2377
2379 {
2380 return false;
2381 }
2382
2383
2385 {
2388 {
2390 }
2391
2392 return construction_kit;
2393 }
2394
2396 {
2399 {
2401 }
2402 }
2403
2405 {
2407 }
2408
2410 {
2411 return "";
2412 }
2413
2415 {
2418 }
2419
2420
2422 {
2425 }
2426
2427
2429 {
2430 super.OnStoreSave( ctx );
2431
2432
2436
2438 }
2439
2441 {
2442 if ( !super.OnStoreLoad( ctx, version ) )
2443 return false;
2444
2445
2446
2448 {
2450 return false;
2451 }
2453 {
2455 return false;
2456 }
2458 {
2460 return false;
2461 }
2462
2463
2465 {
2467 return false;
2468 }
2469
2470
2471 return true;
2472 }
2473
2475 {
2476 super.AfterStoreLoad();
2477
2479 {
2481 }
2482 }
2483
2485 {
2486
2488
2489
2492
2493
2495 }
2496
2498 {
2499 super.OnCreatePhysics();
2502 }
2503
2505 {
2507 return;
2508
2509 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2510
2512 return;
2513
2515 string part_name = zone;
2517
2519 {
2520 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2521
2522 if ( construction_part && construction.IsPartConstructed( part_name ) )
2523 {
2525 construction.DestroyConnectedParts(part_name);
2526 }
2527
2528
2529 if ( part_name.
Contains(
"barbed") )
2530 {
2531 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2532 if (barbed_wire)
2533 barbed_wire.SetMountedState( false );
2534 }
2535 }
2536 }
2537
2539 {
2541 {
2543 }
2544
2545 super.EEOnAfterLoad();
2546 }
2547
2549 {
2550 super.EEInit();
2551
2552
2554
2555
2556 #ifdef DEVELOPER
2558 #endif
2559 }
2560
2562 {
2563 super.EEItemAttached( item, slot_name );
2564
2568 }
2569
2571 {
2572 super.EEItemDetached( item, slot_name );
2573
2576 }
2577
2578 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2579 {
2582
2585 }
2586
2587
2589 {
2590 return true;
2591 }
2592
2593
2594
2596 {
2598
2599
2600 if (construtionPart.
IsBase())
2601 {
2603
2604
2606 }
2607
2608
2610
2611
2613
2614
2616
2618
2620
2621
2623
2624
2626 }
2627
2629 {
2630
2632 }
2633
2634
2636 {
2639
2640
2642
2643
2645
2646
2648
2649
2651
2653
2654
2656
2657
2659
2660
2661 if (construtionPart.
IsBase())
2662 {
2663
2665 }
2666 }
2667
2669 {
2670
2672 }
2673
2674
2675 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2676 {
2679
2680
2682
2683
2685
2686
2688
2689
2691
2693
2694
2696
2697
2699
2700
2701 if (construtionPart.
IsBase())
2702 {
2703
2705 }
2706 }
2707
2709 {
2710
2712 }
2713
2716 {
2717 bool process = false;
2718
2719
2723
2724 if (process)
2725 {
2726 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
2727 {
2729 return;
2730 }
2731
2733 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
2734 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
2735
2736
2738 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
2739 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
2740 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
2741 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
2742 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
2743 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
2744 mins = minTmp;
2745 maxs = maxTmp;
2746
2747 maxs[1] = maxs[1] + 0.35;
2748
2750 }
2751 }
2752
2755 {
2758
2759
2761 foreach (
EntityAI entity : foundEntities)
2762 {
2765 }
2766 }
2767
2768
2770 {
2772
2776 }
2777
2779 {
2781
2783 {
2785 }
2786 else
2787 {
2789 }
2790
2792 }
2793
2795 {
2797
2799 foreach (
string slotName : attachmentSlots)
2800 {
2802 }
2803
2804
2807 else
2809
2811 }
2812
2814 {
2815 string slotNameMounted = slot_name + "_Mounted";
2816 EntityAI attachment = FindAttachmentBySlotName(slot_name);
2817
2818 if (attachment)
2819 {
2820 BarbedWire barbedWire = BarbedWire.Cast(attachment);
2821 if (barbedWire && barbedWire.IsMounted())
2823 else
2825
2826 if (is_locked)
2827 {
2828 SetAnimationPhase(slotNameMounted, 0);
2829 SetAnimationPhase(slot_name, 1);
2830 }
2831 else
2832 {
2833 SetAnimationPhase(slotNameMounted, 1);
2834 SetAnimationPhase(slot_name, 0);
2835 }
2836 }
2837 else
2838 {
2839 SetAnimationPhase(slotNameMounted, 1);
2840 SetAnimationPhase(slot_name, 1);
2841
2843 }
2844 }
2845
2846
2848 {
2851
2854
2857
2858 foreach (
string slotName : attachmentSlots)
2859 {
2861 }
2862
2863
2865 {
2868
2870 }
2871 else
2872 {
2875
2877 }
2878
2881 }
2882
2884 {
2885
2887 return;
2888
2889 string slot_name_mounted = slot_name + "_Mounted";
2890 EntityAI attachment = FindAttachmentBySlotName( slot_name );
2891
2892
2894 RemoveProxyPhysics( slot_name_mounted );
2895 RemoveProxyPhysics( slot_name );
2896
2897 if ( attachment )
2898 {
2900 if ( is_locked )
2901 {
2903 AddProxyPhysics( slot_name_mounted );
2904 }
2905 else
2906 {
2908 AddProxyPhysics( slot_name );
2909 }
2910 }
2911 }
2912
2914 {
2915 SetAffectPathgraph( true, false );
2917 }
2918
2920 {
2921 return true;
2922 }
2923
2925 {
2926 return true;
2927 }
2928
2930 {
2931 if ( attachment )
2932 {
2934 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
2935
2936 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
2937 }
2938
2939 return false;
2940 }
2941
2943 {
2945 }
2946
2947
2949 {
2950 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
2951 if (
GetGame().ConfigIsExisting( config_path ) )
2952 {
2954 }
2955 }
2956
2958 {
2959 return true;
2960 }
2961
2963 {
2964 return true;
2965 }
2966
2968 {
2969 return true;
2970 }
2971
2972
2974 {
2976 {
2978 }
2979
2981 }
2982
2984 {
2986 }
2987
2988
2989
2991 {
2992 return super.CanReceiveAttachment(attachment, slotId);
2993 }
2994
2996 {
2997 int attachment_count = GetInventory().AttachmentCount();
2998 if ( attachment_count > 0 )
2999 {
3000 if (
HasBase() && attachment_count == 1 )
3001 {
3002 return false;
3003 }
3004
3005 return true;
3006 }
3007
3008 return false;
3009 }
3010
3012 {
3013 return true;
3014 }
3015
3017 {
3018 return false;
3019 }
3020
3021
3023 {
3024 return false;
3025 }
3026
3028 {
3029 return false;
3030 }
3031
3032
3034 {
3035 return false;
3036 }
3037
3038
3039
3041 {
3042 return true;
3043 }
3044
3046 {
3047 return true;
3048 }
3049
3052 {
3053 return false;
3054 }
3055
3056
3058 {
3059 return true;
3060 }
3061
3062
3064 {
3065 return false;
3066 }
3067
3068
3070 {
3071 return true;
3072 }
3073
3074
3076 {
3077 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
3078 {
3079 return false;
3080 }
3081
3082 return true;
3083 }
3084
3086 {
3089
3090 return item;
3091 }
3092
3093
3095 {
3097 {
3098
3100
3101
3104
3106 if ( MemoryPointExists( slot_name + "_min" ) )
3107 {
3108 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
3109 }
3110 if ( MemoryPointExists( slot_name + "_max" ) )
3111 {
3112 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
3113 }
3114
3115
3118
3119
3122 center = ModelToWorld( center );
3123
3124
3127
3128 areaDamage.SetExtents( extents[0], extents[1] );
3129 areaDamage.SetAreaPosition( center );
3130 areaDamage.SetAreaOrientation( orientation );
3133 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
3134 areaDamage.SetAmmoName( "BarbedWireHit" );
3135 areaDamage.Spawn();
3136
3138 }
3139 }
3140
3142 {
3143 if ( angle_deg != 0 )
3144 {
3145
3146 orientation[0] = orientation[0] - angle_deg;
3147
3148
3150 if ( MemoryPointExists( "rotate_axis" ) )
3151 {
3152 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
3153 }
3154 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];
3155 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];
3156 center[0] = r_center_x;
3157 center[2] = r_center_z;
3158 }
3159 }
3160
3162 {
3164 {
3167 {
3168 if (areaDamage)
3169 {
3170 areaDamage.Destroy();
3171 }
3172
3174 }
3175 }
3176 }
3177
3179 {
3180 return true;
3181 }
3182
3183
3184
3185
3187 {
3189 }
3190
3192 {
3194 }
3195
3197 {
3199 }
3200
3202 {
3204
3205 switch ( material_type )
3206 {
3212 }
3213
3214 return "";
3215 }
3216
3218 {
3220
3221 switch ( material_type )
3222 {
3228 }
3229
3230 return "";
3231 }
3232
3233
3235 {
3237 {
3238
3240 {
3241 SetHealth(slot_name,"Health",item.GetHealth());
3242 }
3243 }
3244 }
3245
3247 {
3248 return 111;
3249 }
3250
3252 {
3253 super.SetActions();
3254
3258 }
3259
3260
3261
3262
3264 {
3265 }
3266
3269 {
3270 return null;
3271 }
3272
3274 {
3276 }
3277
3279 {
3282
3283 Man p;
3284
3285 #ifdef SERVER
3288 if (players.Count())
3289 p = players[0];
3290 #else
3292 #endif
3293
3295 {
3296 bool excluded = false;
3298 if (excludes)
3299 {
3300 foreach (string exclude : excludes)
3301 {
3303 {
3304 excluded = true;
3305 break;
3306 }
3307 }
3308 }
3309
3310 if (!excluded)
3311 {
3313 }
3314 }
3315
3317 }
3318}
3319
3321{
3322#ifdef BSB_DEBUG
3324#else
3325
3326#endif
3327}
3329{
3330#ifdef BSB_DEBUG_SPAM
3332#else
3333
3334#endif
3335}
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.