2366{
2368
2370
2372
2374
2380
2381
2382
2388
2394
2396
2400
2401
2403 {
2405
2406
2407 RegisterNetSyncVariableInt( "m_SyncParts01" );
2408 RegisterNetSyncVariableInt( "m_SyncParts02" );
2409 RegisterNetSyncVariableInt( "m_SyncParts03" );
2410 RegisterNetSyncVariableInt( "m_InteractedPartId" );
2411 RegisterNetSyncVariableInt( "m_PerformedActionId" );
2412 RegisterNetSyncVariableBool( "m_HasBase" );
2413
2414
2416
2417 if (ConfigIsExisting("hybridAttachments"))
2418 {
2421 }
2422 if (ConfigIsExisting("mountables"))
2423 {
2426 }
2427
2429 }
2430
2432 {
2433 super.EEDelete(parent);
2434
2436 {
2437 areaDamage.Destroy();
2438 }
2439
2440 }
2441
2443 {
2444 return "disableBaseDamage";
2445 }
2446
2448 {
2449 return true;
2450 }
2451
2453 {
2454 return EInventoryIconVisibility.HIDE_VICINITY;
2455 }
2456
2458 {
2459 super.InitItemSounds();
2460
2464
2469 }
2470
2472 {
2473 return "putDown_FenceKit_SoundSet";
2474 }
2475
2477 {
2478 return "Shelter_Site_Build_Loop_SoundSet";
2479 }
2480
2481
2483 {
2485 {
2486 SetSynchDirty();
2487 }
2488 }
2489
2491 {
2493 super.OnVariablesSynchronized();
2494
2496 }
2497
2499 {
2500
2502
2503
2505
2506
2508 }
2509
2510
2512 {
2513
2514 int offset;
2515 int mask;
2516
2517 if ( part_id >= 1 && part_id <= 31 )
2518 {
2519 offset = part_id - 1;
2520 mask = 1 << offset;
2521
2523 }
2524 else if ( part_id >= 32 && part_id <= 62 )
2525 {
2526 offset = ( part_id % 32 );
2527 mask = 1 << offset;
2528
2530 }
2531 else if ( part_id >= 63 && part_id <= 93 )
2532 {
2533 offset = ( part_id % 63 );
2534 mask = 1 << offset;
2535
2537 }
2538 }
2539
2541 {
2542
2543 int offset;
2544 int mask;
2545
2546 if ( part_id >= 1 && part_id <= 31 )
2547 {
2548 offset = part_id - 1;
2549 mask = 1 << offset;
2550
2552 }
2553 else if ( part_id >= 32 && part_id <= 62 )
2554 {
2555 offset = ( part_id % 32 );
2556 mask = 1 << offset;
2557
2559 }
2560 else if ( part_id >= 63 && part_id <= 93 )
2561 {
2562 offset = ( part_id % 63 );
2563 mask = 1 << offset;
2564
2566 }
2567 }
2568
2570 {
2571
2572 int offset;
2573 int mask;
2574
2575 if ( part_id >= 1 && part_id <= 31 )
2576 {
2577 offset = part_id - 1;
2578 mask = 1 << offset;
2579
2581 {
2582 return true;
2583 }
2584 }
2585 else if ( part_id >= 32 && part_id <= 62 )
2586 {
2587 offset = ( part_id % 32 );
2588 mask = 1 << offset;
2589
2591 {
2592 return true;
2593 }
2594 }
2595 else if ( part_id >= 63 && part_id <= 93 )
2596 {
2597 offset = ( part_id % 63 );
2598 mask = 1 << offset;
2599
2601 {
2602 return true;
2603 }
2604 }
2605
2606 return false;
2607 }
2608
2610 {
2613 }
2614
2616 {
2617
2620 }
2621
2623 {
2625 {
2628
2629 switch( build_action_id )
2630 {
2634 }
2635 }
2636 }
2637
2638
2640 {
2642 bool is_base = part.
IsBase();
2645 if ( is_part_built_sync )
2646 {
2648 {
2652
2653 if (is_base)
2654 {
2657 }
2658 }
2659 }
2660 else
2661 {
2663 {
2667
2668 if (is_base)
2669 {
2672 }
2673 }
2674 }
2675
2676
2678 }
2679
2680
2682 {
2685
2686 for ( int i = 0; i < construction_parts.Count(); ++i )
2687 {
2688 string key = construction_parts.GetKey( i );
2691 }
2692
2693
2695 }
2696
2698 {
2701
2702 for ( int i = 0; i < construction_parts.Count(); ++i )
2703 {
2704 string key = construction_parts.GetKey( i );
2706
2707 if ( value.
GetId() ==
id )
2708 {
2709 return value;
2710 }
2711 }
2712
2713 return NULL;
2714 }
2715
2716
2717
2719 {
2721 }
2722
2724 {
2726 }
2727
2729 {
2730 return true;
2731 }
2732
2734 {
2735 return false;
2736 }
2737
2738
2740 {
2743 {
2745 }
2746
2747 return construction_kit;
2748 }
2749
2751 {
2754 {
2756 }
2757 }
2758
2760 {
2762 }
2763
2765 {
2766 return "";
2767 }
2768
2770 {
2773 }
2774
2775
2777 {
2780 }
2781
2782
2784 {
2785 super.OnStoreSave( ctx );
2786
2787
2791
2793 }
2794
2796 {
2797 if ( !super.OnStoreLoad( ctx, version ) )
2798 return false;
2799
2800
2801
2803 {
2805 return false;
2806 }
2808 {
2810 return false;
2811 }
2813 {
2815 return false;
2816 }
2817
2818
2820 {
2822 return false;
2823 }
2824
2825
2826 return true;
2827 }
2828
2830 {
2831 super.AfterStoreLoad();
2832
2834 {
2836 }
2837 }
2838
2840 {
2841
2843
2844
2847
2848
2850 }
2851
2853 {
2854 super.OnCreatePhysics();
2857 }
2858
2860 {
2862 return;
2863
2864 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2865
2867 return;
2868
2870 string part_name = zone;
2872
2874 {
2875 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2876
2877 if ( construction_part && construction.IsPartConstructed( part_name ) )
2878 {
2880 construction.DestroyConnectedParts(part_name);
2881 }
2882
2883
2884 if ( part_name.
Contains(
"barbed") )
2885 {
2886 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2887 if (barbed_wire)
2888 barbed_wire.SetMountedState( false );
2889 }
2890 }
2891 }
2892
2894 {
2896 {
2898 }
2899
2900 super.EEOnAfterLoad();
2901 }
2902
2904 {
2905 super.EEInit();
2906
2907
2909
2910
2911 #ifdef DEVELOPER
2913 #endif
2914 }
2915
2917 {
2918 super.EEItemAttached( item, slot_name );
2919
2923 }
2924
2926 {
2927 super.EEItemDetached( item, slot_name );
2928
2931 }
2932
2933 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2934 {
2937
2940 }
2941
2942
2944 {
2945 return true;
2946 }
2947
2948
2949
2951 {
2953
2954
2955 if (construtionPart.
IsBase())
2956 {
2958
2959
2961 }
2962
2963
2965
2966
2968
2969
2971
2973
2975
2976
2978
2979
2981 }
2982
2984 {
2985
2987 }
2988
2989
2991 {
2994
2995
2997
2998
3000
3001
3003
3004
3006
3008
3009
3011
3012
3014
3015
3016 if (construtionPart.
IsBase())
3017 {
3018
3020 }
3021 }
3022
3024 {
3025
3027 }
3028
3029
3030 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
3031 {
3034
3035
3037
3038
3040
3041
3043
3044
3046
3048
3049
3051
3052
3054
3055
3056 if (construtionPart.
IsBase())
3057 {
3058
3060 }
3061 }
3062
3064 {
3065
3067 }
3068
3071 {
3072 bool process = false;
3073
3074
3078
3079 if (process)
3080 {
3081 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
3082 {
3084 return;
3085 }
3086
3088 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
3089 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
3090
3091
3093 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
3094 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
3095 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
3096 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
3097 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
3098 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
3099 mins = minTmp;
3100 maxs = maxTmp;
3101
3102 maxs[1] = maxs[1] + 0.35;
3103
3105 }
3106 }
3107
3110 {
3113
3114
3116 foreach (
EntityAI entity : foundEntities)
3117 {
3120 }
3121 }
3122
3123
3125 {
3127
3131 }
3132
3134 {
3136
3138 {
3140 }
3141 else
3142 {
3144 }
3145
3147 }
3148
3150 {
3152
3154 foreach (
string slotName : attachmentSlots)
3155 {
3157 }
3158
3159
3162 else
3164
3166 }
3167
3169 {
3170 string slotNameMounted = slot_name + "_Mounted";
3171 EntityAI attachment = FindAttachmentBySlotName(slot_name);
3172
3173 if (attachment)
3174 {
3175 BarbedWire barbedWire = BarbedWire.Cast(attachment);
3176 if (barbedWire && barbedWire.IsMounted())
3178 else
3180
3181 if (is_locked)
3182 {
3183 SetAnimationPhase(slotNameMounted, 0);
3184 SetAnimationPhase(slot_name, 1);
3185 }
3186 else
3187 {
3188 SetAnimationPhase(slotNameMounted, 1);
3189 SetAnimationPhase(slot_name, 0);
3190 }
3191 }
3192 else
3193 {
3194 SetAnimationPhase(slotNameMounted, 1);
3195 SetAnimationPhase(slot_name, 1);
3196
3198 }
3199 }
3200
3201
3203 {
3206
3209
3212
3213 foreach (
string slotName : attachmentSlots)
3214 {
3216 }
3217
3218
3220 {
3223
3225 }
3226 else
3227 {
3230
3232 }
3233
3236 }
3237
3239 {
3240
3242 return;
3243
3244 string slot_name_mounted = slot_name + "_Mounted";
3245 EntityAI attachment = FindAttachmentBySlotName( slot_name );
3246
3247
3249 RemoveProxyPhysics( slot_name_mounted );
3250 RemoveProxyPhysics( slot_name );
3251
3252 if ( attachment )
3253 {
3255 if ( is_locked )
3256 {
3258 AddProxyPhysics( slot_name_mounted );
3259 }
3260 else
3261 {
3263 AddProxyPhysics( slot_name );
3264 }
3265 }
3266 }
3267
3269 {
3270 SetAffectPathgraph( true, false );
3272 }
3273
3275 {
3276 return true;
3277 }
3278
3280 {
3281 return true;
3282 }
3283
3285 {
3286 if ( attachment )
3287 {
3289 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
3290
3291 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
3292 }
3293
3294 return false;
3295 }
3296
3298 {
3300 }
3301
3302
3304 {
3305 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
3306 if (
GetGame().ConfigIsExisting( config_path ) )
3307 {
3309 }
3310 }
3311
3313 {
3314 return true;
3315 }
3316
3318 {
3319 return true;
3320 }
3321
3323 {
3324 return true;
3325 }
3326
3327
3329 {
3331 {
3333 }
3334
3336 }
3337
3339 {
3341 }
3342
3343
3344
3346 {
3347 return super.CanReceiveAttachment(attachment, slotId);
3348 }
3349
3351 {
3352 int attachment_count = GetInventory().AttachmentCount();
3353 if ( attachment_count > 0 )
3354 {
3355 if (
HasBase() && attachment_count == 1 )
3356 {
3357 return false;
3358 }
3359
3360 return true;
3361 }
3362
3363 return false;
3364 }
3365
3367 {
3368 return true;
3369 }
3370
3372 {
3373 return false;
3374 }
3375
3376
3378 {
3379 return false;
3380 }
3381
3383 {
3384 return false;
3385 }
3386
3387
3389 {
3390 return false;
3391 }
3392
3393
3394
3396 {
3397 return true;
3398 }
3399
3401 {
3402 return true;
3403 }
3404
3407 {
3408 return false;
3409 }
3410
3411
3413 {
3414 return true;
3415 }
3416
3417
3419 {
3420 return false;
3421 }
3422
3423
3425 {
3426 return true;
3427 }
3428
3429
3431 {
3432 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
3433 {
3434 return false;
3435 }
3436
3437 return true;
3438 }
3439
3441 {
3444
3445 return item;
3446 }
3447
3448
3450 {
3452 {
3453
3455
3456
3459
3461 if ( MemoryPointExists( slot_name + "_min" ) )
3462 {
3463 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
3464 }
3465 if ( MemoryPointExists( slot_name + "_max" ) )
3466 {
3467 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
3468 }
3469
3470
3473
3474
3477 center = ModelToWorld( center );
3478
3479
3482
3483 areaDamage.SetExtents( extents[0], extents[1] );
3484 areaDamage.SetAreaPosition( center );
3485 areaDamage.SetAreaOrientation( orientation );
3488 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
3489 areaDamage.SetAmmoName( "BarbedWireHit" );
3490 areaDamage.Spawn();
3491
3493 }
3494 }
3495
3497 {
3498 if ( angle_deg != 0 )
3499 {
3500
3501 orientation[0] = orientation[0] - angle_deg;
3502
3503
3505 if ( MemoryPointExists( "rotate_axis" ) )
3506 {
3507 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
3508 }
3509 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];
3510 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];
3511 center[0] = r_center_x;
3512 center[2] = r_center_z;
3513 }
3514 }
3515
3517 {
3519 {
3522 {
3523 if (areaDamage)
3524 {
3525 areaDamage.Destroy();
3526 }
3527
3529 }
3530 }
3531 }
3532
3534 {
3535 return true;
3536 }
3537
3538
3539
3540
3542 {
3544 }
3545
3547 {
3549 }
3550
3552 {
3554 }
3555
3557 {
3559
3560 switch ( material_type )
3561 {
3567 }
3568
3569 return "";
3570 }
3571
3573 {
3575
3576 switch ( material_type )
3577 {
3583 }
3584
3585 return "";
3586 }
3587
3588
3590 {
3592 {
3593
3595 {
3596 SetHealth(slot_name,"Health",item.GetHealth());
3597 }
3598 }
3599 }
3600
3602 {
3603 return 111;
3604 }
3605
3607 {
3608 super.SetActions();
3609
3613 }
3614
3615
3616
3617
3619 {
3620 }
3621
3624 {
3625 return null;
3626 }
3627
3629 {
3631 }
3632
3634 {
3637
3638 Man p;
3639
3640 #ifdef SERVER
3643 if (players.Count())
3644 p = players[0];
3645 #else
3647 #endif
3648
3650 {
3651 bool excluded = false;
3653 if (excludes)
3654 {
3655 foreach (string exclude : excludes)
3656 {
3658 {
3659 excluded = true;
3660 break;
3661 }
3662 }
3663 }
3664
3665 if (!excluded)
3666 {
3668 }
3669 }
3670
3672 }
3673}
3674
3676{
3677#ifdef BSB_DEBUG
3679#else
3680
3681#endif
3682}
3684{
3685#ifdef BSB_DEBUG_SPAM
3687#else
3688
3689#endif
3690}
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.