2245{
2247
2249
2251
2253
2259
2260
2261
2267
2273
2275
2279
2280
2282 {
2284
2285
2286 RegisterNetSyncVariableInt( "m_SyncParts01" );
2287 RegisterNetSyncVariableInt( "m_SyncParts02" );
2288 RegisterNetSyncVariableInt( "m_SyncParts03" );
2289 RegisterNetSyncVariableInt( "m_InteractedPartId" );
2290 RegisterNetSyncVariableInt( "m_PerformedActionId" );
2291 RegisterNetSyncVariableBool( "m_HasBase" );
2292
2293
2295
2296 if (ConfigIsExisting("hybridAttachments"))
2297 {
2300 }
2301 if (ConfigIsExisting("mountables"))
2302 {
2305 }
2306
2308 }
2309
2311 {
2312 super.EEDelete(parent);
2313
2315 {
2316 areaDamage.Destroy();
2317 }
2318
2319 }
2320
2322 {
2323 return "disableBaseDamage";
2324 }
2325
2327 {
2328 return true;
2329 }
2330
2332 {
2333 return EInventoryIconVisibility.HIDE_VICINITY;
2334 }
2335
2337 {
2338 super.InitItemSounds();
2339
2343
2348 }
2349
2351 {
2352 return "putDown_FenceKit_SoundSet";
2353 }
2354
2356 {
2357 return "Shelter_Site_Build_Loop_SoundSet";
2358 }
2359
2360
2362 {
2364 {
2365 SetSynchDirty();
2366 }
2367 }
2368
2370 {
2372 super.OnVariablesSynchronized();
2373
2375 }
2376
2378 {
2379
2381
2382
2384
2385
2387 }
2388
2389
2391 {
2392
2393 int offset;
2394 int mask;
2395
2396 if ( part_id >= 1 && part_id <= 31 )
2397 {
2398 offset = part_id - 1;
2399 mask = 1 << offset;
2400
2402 }
2403 else if ( part_id >= 32 && part_id <= 62 )
2404 {
2405 offset = ( part_id % 32 );
2406 mask = 1 << offset;
2407
2409 }
2410 else if ( part_id >= 63 && part_id <= 93 )
2411 {
2412 offset = ( part_id % 63 );
2413 mask = 1 << offset;
2414
2416 }
2417 }
2418
2420 {
2421
2422 int offset;
2423 int mask;
2424
2425 if ( part_id >= 1 && part_id <= 31 )
2426 {
2427 offset = part_id - 1;
2428 mask = 1 << offset;
2429
2431 }
2432 else if ( part_id >= 32 && part_id <= 62 )
2433 {
2434 offset = ( part_id % 32 );
2435 mask = 1 << offset;
2436
2438 }
2439 else if ( part_id >= 63 && part_id <= 93 )
2440 {
2441 offset = ( part_id % 63 );
2442 mask = 1 << offset;
2443
2445 }
2446 }
2447
2449 {
2450
2451 int offset;
2452 int mask;
2453
2454 if ( part_id >= 1 && part_id <= 31 )
2455 {
2456 offset = part_id - 1;
2457 mask = 1 << offset;
2458
2460 {
2461 return true;
2462 }
2463 }
2464 else if ( part_id >= 32 && part_id <= 62 )
2465 {
2466 offset = ( part_id % 32 );
2467 mask = 1 << offset;
2468
2470 {
2471 return true;
2472 }
2473 }
2474 else if ( part_id >= 63 && part_id <= 93 )
2475 {
2476 offset = ( part_id % 63 );
2477 mask = 1 << offset;
2478
2480 {
2481 return true;
2482 }
2483 }
2484
2485 return false;
2486 }
2487
2489 {
2492 }
2493
2495 {
2496
2499 }
2500
2502 {
2504 {
2507
2508 switch( build_action_id )
2509 {
2513 }
2514 }
2515 }
2516
2517
2519 {
2521 bool is_base = part.
IsBase();
2524 if ( is_part_built_sync )
2525 {
2527 {
2531
2532 if (is_base)
2533 {
2536 }
2537 }
2538 }
2539 else
2540 {
2542 {
2546
2547 if (is_base)
2548 {
2551 }
2552 }
2553 }
2554
2555
2557 }
2558
2559
2561 {
2564
2565 for ( int i = 0; i < construction_parts.Count(); ++i )
2566 {
2567 string key = construction_parts.GetKey( i );
2570 }
2571
2572
2574 }
2575
2577 {
2580
2581 for ( int i = 0; i < construction_parts.Count(); ++i )
2582 {
2583 string key = construction_parts.GetKey( i );
2585
2586 if ( value.
GetId() ==
id )
2587 {
2588 return value;
2589 }
2590 }
2591
2592 return NULL;
2593 }
2594
2595
2596
2598 {
2600 }
2601
2603 {
2605 }
2606
2608 {
2609 return true;
2610 }
2611
2613 {
2614 return false;
2615 }
2616
2617
2619 {
2622 {
2624 }
2625
2626 return construction_kit;
2627 }
2628
2630 {
2633 {
2635 }
2636 }
2637
2639 {
2641 }
2642
2644 {
2645 return "";
2646 }
2647
2649 {
2652 }
2653
2654
2656 {
2659 }
2660
2661
2663 {
2664 super.OnStoreSave( ctx );
2665
2666
2670
2672 }
2673
2675 {
2676 if ( !super.OnStoreLoad( ctx, version ) )
2677 return false;
2678
2679
2680
2682 {
2684 return false;
2685 }
2687 {
2689 return false;
2690 }
2692 {
2694 return false;
2695 }
2696
2697
2699 {
2701 return false;
2702 }
2703
2704
2705 return true;
2706 }
2707
2709 {
2710 super.AfterStoreLoad();
2711
2713 {
2715 }
2716 }
2717
2719 {
2720
2722
2723
2726
2727
2729 }
2730
2732 {
2733 super.OnCreatePhysics();
2736 }
2737
2739 {
2741 return;
2742
2743 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2744
2746 return;
2747
2749 string part_name = zone;
2751
2753 {
2754 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2755
2756 if ( construction_part && construction.IsPartConstructed( part_name ) )
2757 {
2759 construction.DestroyConnectedParts(part_name);
2760 }
2761
2762
2763 if ( part_name.
Contains(
"barbed") )
2764 {
2765 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2766 if (barbed_wire)
2767 barbed_wire.SetMountedState( false );
2768 }
2769 }
2770 }
2771
2773 {
2775 {
2777 }
2778
2779 super.EEOnAfterLoad();
2780 }
2781
2783 {
2784 super.EEInit();
2785
2786
2788
2789
2790 #ifdef DEVELOPER
2792 #endif
2793 }
2794
2796 {
2797 super.EEItemAttached( item, slot_name );
2798
2802 }
2803
2805 {
2806 super.EEItemDetached( item, slot_name );
2807
2810 }
2811
2812 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2813 {
2816
2819 }
2820
2821
2823 {
2824 return true;
2825 }
2826
2827
2828
2830 {
2832
2833
2834 if (construtionPart.
IsBase())
2835 {
2837
2838
2840 }
2841
2842
2844
2845
2847
2848
2850
2852
2854
2855
2857
2858
2860 }
2861
2863 {
2864
2866 }
2867
2868
2870 {
2873
2874
2876
2877
2879
2880
2882
2883
2885
2887
2888
2890
2891
2893
2894
2895 if (construtionPart.
IsBase())
2896 {
2897
2899 }
2900 }
2901
2903 {
2904
2906 }
2907
2908
2909 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2910 {
2913
2914
2916
2917
2919
2920
2922
2923
2925
2927
2928
2930
2931
2933
2934
2935 if (construtionPart.
IsBase())
2936 {
2937
2939 }
2940 }
2941
2943 {
2944
2946 }
2947
2950 {
2951 bool process = false;
2952
2953
2957
2958 if (process)
2959 {
2960 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
2961 {
2963 return;
2964 }
2965
2967 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
2968 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
2969
2970
2972 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
2973 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
2974 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
2975 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
2976 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
2977 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
2978 mins = minTmp;
2979 maxs = maxTmp;
2980
2981 maxs[1] = maxs[1] + 0.35;
2982
2984 }
2985 }
2986
2989 {
2992
2993
2995 foreach (
EntityAI entity : foundEntities)
2996 {
2999 }
3000 }
3001
3002
3004 {
3006
3010 }
3011
3013 {
3015
3017 {
3019 }
3020 else
3021 {
3023 }
3024
3026 }
3027
3029 {
3031
3033 foreach (
string slotName : attachmentSlots)
3034 {
3036 }
3037
3038
3041 else
3043
3045 }
3046
3048 {
3049 string slotNameMounted = slot_name + "_Mounted";
3050 EntityAI attachment = FindAttachmentBySlotName(slot_name);
3051
3052 if (attachment)
3053 {
3054 BarbedWire barbedWire = BarbedWire.Cast(attachment);
3055 if (barbedWire && barbedWire.IsMounted())
3057 else
3059
3060 if (is_locked)
3061 {
3062 SetAnimationPhase(slotNameMounted, 0);
3063 SetAnimationPhase(slot_name, 1);
3064 }
3065 else
3066 {
3067 SetAnimationPhase(slotNameMounted, 1);
3068 SetAnimationPhase(slot_name, 0);
3069 }
3070 }
3071 else
3072 {
3073 SetAnimationPhase(slotNameMounted, 1);
3074 SetAnimationPhase(slot_name, 1);
3075
3077 }
3078 }
3079
3080
3082 {
3085
3088
3091
3092 foreach (
string slotName : attachmentSlots)
3093 {
3095 }
3096
3097
3099 {
3102
3104 }
3105 else
3106 {
3109
3111 }
3112
3115 }
3116
3118 {
3119
3121 return;
3122
3123 string slot_name_mounted = slot_name + "_Mounted";
3124 EntityAI attachment = FindAttachmentBySlotName( slot_name );
3125
3126
3128 RemoveProxyPhysics( slot_name_mounted );
3129 RemoveProxyPhysics( slot_name );
3130
3131 if ( attachment )
3132 {
3134 if ( is_locked )
3135 {
3137 AddProxyPhysics( slot_name_mounted );
3138 }
3139 else
3140 {
3142 AddProxyPhysics( slot_name );
3143 }
3144 }
3145 }
3146
3148 {
3149 SetAffectPathgraph( true, false );
3151 }
3152
3154 {
3155 return true;
3156 }
3157
3159 {
3160 return true;
3161 }
3162
3164 {
3165 if ( attachment )
3166 {
3168 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
3169
3170 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
3171 }
3172
3173 return false;
3174 }
3175
3177 {
3179 }
3180
3181
3183 {
3184 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
3185 if (
GetGame().ConfigIsExisting( config_path ) )
3186 {
3188 }
3189 }
3190
3192 {
3193 return true;
3194 }
3195
3197 {
3198 return true;
3199 }
3200
3202 {
3203 return true;
3204 }
3205
3206
3208 {
3210 {
3212 }
3213
3215 }
3216
3218 {
3220 }
3221
3222
3223
3225 {
3226 return super.CanReceiveAttachment(attachment, slotId);
3227 }
3228
3230 {
3231 int attachment_count = GetInventory().AttachmentCount();
3232 if ( attachment_count > 0 )
3233 {
3234 if (
HasBase() && attachment_count == 1 )
3235 {
3236 return false;
3237 }
3238
3239 return true;
3240 }
3241
3242 return false;
3243 }
3244
3246 {
3247 return true;
3248 }
3249
3251 {
3252 return false;
3253 }
3254
3255
3257 {
3258 return false;
3259 }
3260
3262 {
3263 return false;
3264 }
3265
3266
3268 {
3269 return false;
3270 }
3271
3272
3273
3275 {
3276 return true;
3277 }
3278
3280 {
3281 return true;
3282 }
3283
3286 {
3287 return false;
3288 }
3289
3290
3292 {
3293 return true;
3294 }
3295
3296
3298 {
3299 return false;
3300 }
3301
3302
3304 {
3305 return true;
3306 }
3307
3308
3310 {
3311 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
3312 {
3313 return false;
3314 }
3315
3316 return true;
3317 }
3318
3320 {
3323
3324 return item;
3325 }
3326
3327
3329 {
3331 {
3332
3334
3335
3338
3340 if ( MemoryPointExists( slot_name + "_min" ) )
3341 {
3342 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
3343 }
3344 if ( MemoryPointExists( slot_name + "_max" ) )
3345 {
3346 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
3347 }
3348
3349
3352
3353
3356 center = ModelToWorld( center );
3357
3358
3361
3362 areaDamage.SetExtents( extents[0], extents[1] );
3363 areaDamage.SetAreaPosition( center );
3364 areaDamage.SetAreaOrientation( orientation );
3367 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
3368 areaDamage.SetAmmoName( "BarbedWireHit" );
3369 areaDamage.Spawn();
3370
3372 }
3373 }
3374
3376 {
3377 if ( angle_deg != 0 )
3378 {
3379
3380 orientation[0] = orientation[0] - angle_deg;
3381
3382
3384 if ( MemoryPointExists( "rotate_axis" ) )
3385 {
3386 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
3387 }
3388 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];
3389 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];
3390 center[0] = r_center_x;
3391 center[2] = r_center_z;
3392 }
3393 }
3394
3396 {
3398 {
3401 {
3402 if (areaDamage)
3403 {
3404 areaDamage.Destroy();
3405 }
3406
3408 }
3409 }
3410 }
3411
3413 {
3414 return true;
3415 }
3416
3417
3418
3419
3421 {
3423 }
3424
3426 {
3428 }
3429
3431 {
3433 }
3434
3436 {
3438
3439 switch ( material_type )
3440 {
3446 }
3447
3448 return "";
3449 }
3450
3452 {
3454
3455 switch ( material_type )
3456 {
3462 }
3463
3464 return "";
3465 }
3466
3467
3469 {
3471 {
3472
3474 {
3475 SetHealth(slot_name,"Health",item.GetHealth());
3476 }
3477 }
3478 }
3479
3481 {
3482 return 111;
3483 }
3484
3486 {
3487 super.SetActions();
3488
3492 }
3493
3494
3495
3496
3498 {
3499 }
3500
3503 {
3504 return null;
3505 }
3506
3508 {
3510 }
3511
3513 {
3516
3517 Man p;
3518
3519 #ifdef SERVER
3522 if (players.Count())
3523 p = players[0];
3524 #else
3526 #endif
3527
3529 {
3530 bool excluded = false;
3532 if (excludes)
3533 {
3534 foreach (string exclude : excludes)
3535 {
3537 {
3538 excluded = true;
3539 break;
3540 }
3541 }
3542 }
3543
3544 if (!excluded)
3545 {
3547 }
3548 }
3549
3551 }
3552}
3553
3555{
3556#ifdef BSB_DEBUG
3558#else
3559
3560#endif
3561}
3563{
3564#ifdef BSB_DEBUG_SPAM
3566#else
3567
3568#endif
3569}
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.