2372{
2374
2376
2378
2380
2386
2387
2388
2394
2400
2402
2406
2407
2409 {
2411
2412
2413 RegisterNetSyncVariableInt( "m_SyncParts01" );
2414 RegisterNetSyncVariableInt( "m_SyncParts02" );
2415 RegisterNetSyncVariableInt( "m_SyncParts03" );
2416 RegisterNetSyncVariableInt( "m_InteractedPartId" );
2417 RegisterNetSyncVariableInt( "m_PerformedActionId" );
2418 RegisterNetSyncVariableBool( "m_HasBase" );
2419
2420
2422
2423 if (ConfigIsExisting("hybridAttachments"))
2424 {
2427 }
2428 if (ConfigIsExisting("mountables"))
2429 {
2432 }
2433
2435 }
2436
2438 {
2439 super.EEDelete(parent);
2440
2442 {
2443 areaDamage.Destroy();
2444 }
2445
2446 }
2447
2449 {
2450 return "disableBaseDamage";
2451 }
2452
2454 {
2455 return true;
2456 }
2457
2459 {
2460 return EInventoryIconVisibility.HIDE_VICINITY;
2461 }
2462
2464 {
2465 super.InitItemSounds();
2466
2470
2475 }
2476
2478 {
2479 return "putDown_FenceKit_SoundSet";
2480 }
2481
2483 {
2484 return "Shelter_Site_Build_Loop_SoundSet";
2485 }
2486
2487
2489 {
2491 {
2492 SetSynchDirty();
2493 }
2494 }
2495
2497 {
2499 super.OnVariablesSynchronized();
2500
2502 }
2503
2505 {
2506
2508
2509
2511
2512
2514 }
2515
2516
2518 {
2519
2520 int offset;
2521 int mask;
2522
2523 if ( part_id >= 1 && part_id <= 31 )
2524 {
2525 offset = part_id - 1;
2526 mask = 1 << offset;
2527
2529 }
2530 else if ( part_id >= 32 && part_id <= 62 )
2531 {
2532 offset = ( part_id % 32 );
2533 mask = 1 << offset;
2534
2536 }
2537 else if ( part_id >= 63 && part_id <= 93 )
2538 {
2539 offset = ( part_id % 63 );
2540 mask = 1 << offset;
2541
2543 }
2544 }
2545
2547 {
2548
2549 int offset;
2550 int mask;
2551
2552 if ( part_id >= 1 && part_id <= 31 )
2553 {
2554 offset = part_id - 1;
2555 mask = 1 << offset;
2556
2558 }
2559 else if ( part_id >= 32 && part_id <= 62 )
2560 {
2561 offset = ( part_id % 32 );
2562 mask = 1 << offset;
2563
2565 }
2566 else if ( part_id >= 63 && part_id <= 93 )
2567 {
2568 offset = ( part_id % 63 );
2569 mask = 1 << offset;
2570
2572 }
2573 }
2574
2576 {
2577
2578 int offset;
2579 int mask;
2580
2581 if ( part_id >= 1 && part_id <= 31 )
2582 {
2583 offset = part_id - 1;
2584 mask = 1 << offset;
2585
2587 {
2588 return true;
2589 }
2590 }
2591 else if ( part_id >= 32 && part_id <= 62 )
2592 {
2593 offset = ( part_id % 32 );
2594 mask = 1 << offset;
2595
2597 {
2598 return true;
2599 }
2600 }
2601 else if ( part_id >= 63 && part_id <= 93 )
2602 {
2603 offset = ( part_id % 63 );
2604 mask = 1 << offset;
2605
2607 {
2608 return true;
2609 }
2610 }
2611
2612 return false;
2613 }
2614
2616 {
2619 }
2620
2622 {
2623
2626 }
2627
2629 {
2631 {
2634
2635 switch( build_action_id )
2636 {
2640 }
2641 }
2642 }
2643
2644
2646 {
2648 bool is_base = part.
IsBase();
2651 if ( is_part_built_sync )
2652 {
2654 {
2658
2659 if (is_base)
2660 {
2663 }
2664 }
2665 }
2666 else
2667 {
2669 {
2673
2674 if (is_base)
2675 {
2678 }
2679 }
2680 }
2681
2682
2684 }
2685
2686
2688 {
2691
2692 for ( int i = 0; i < construction_parts.Count(); ++i )
2693 {
2694 string key = construction_parts.GetKey( i );
2697 }
2698
2699
2701 }
2702
2704 {
2707
2708 for ( int i = 0; i < construction_parts.Count(); ++i )
2709 {
2710 string key = construction_parts.GetKey( i );
2712
2713 if ( value.
GetId() ==
id )
2714 {
2715 return value;
2716 }
2717 }
2718
2719 return NULL;
2720 }
2721
2722
2723
2725 {
2727 }
2728
2730 {
2732 }
2733
2735 {
2736 return true;
2737 }
2738
2740 {
2741 return false;
2742 }
2743
2744
2746 {
2749 {
2751 }
2752
2753 return construction_kit;
2754 }
2755
2757 {
2760 {
2762 }
2763 }
2764
2766 {
2768 }
2769
2771 {
2772 return "";
2773 }
2774
2776 {
2779 }
2780
2781
2783 {
2786 }
2787
2788
2790 {
2791 super.OnStoreSave( ctx );
2792
2793
2797
2799 }
2800
2802 {
2803 if ( !super.OnStoreLoad( ctx, version ) )
2804 return false;
2805
2806
2807
2809 {
2811 return false;
2812 }
2814 {
2816 return false;
2817 }
2819 {
2821 return false;
2822 }
2823
2824
2826 {
2828 return false;
2829 }
2830
2831
2832 return true;
2833 }
2834
2836 {
2837 super.AfterStoreLoad();
2838
2840 {
2842 }
2843 }
2844
2846 {
2847
2849
2850
2853
2854
2856 }
2857
2859 {
2860 super.OnCreatePhysics();
2863 }
2864
2866 {
2868 return;
2869
2870 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2871
2873 return;
2874
2876 string part_name = zone;
2878
2880 {
2881 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2882
2883 if ( construction_part && construction.IsPartConstructed( part_name ) )
2884 {
2886 construction.DestroyConnectedParts(part_name);
2887 }
2888
2889
2890 if ( part_name.
Contains(
"barbed") )
2891 {
2892 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2893 if (barbed_wire)
2894 barbed_wire.SetMountedState( false );
2895 }
2896 }
2897 }
2898
2900 {
2902 {
2904 }
2905
2906 super.EEOnAfterLoad();
2907 }
2908
2910 {
2911 super.EEInit();
2912
2913
2915
2916
2917 #ifdef DEVELOPER
2919 #endif
2920 }
2921
2923 {
2924 super.EEItemAttached( item, slot_name );
2925
2929 }
2930
2932 {
2933 super.EEItemDetached( item, slot_name );
2934
2937 }
2938
2939 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2940 {
2943
2946 }
2947
2948
2950 {
2951 return true;
2952 }
2953
2954
2955
2957 {
2959
2960
2961 if (construtionPart.
IsBase())
2962 {
2964
2965
2967 }
2968
2969
2971
2972
2974
2975
2977
2979
2981
2982
2984
2985
2987 }
2988
2990 {
2991
2993 }
2994
2995
2997 {
3000
3001
3003
3004
3006
3007
3009
3010
3012
3014
3015
3017
3018
3020
3021
3022 if (construtionPart.
IsBase())
3023 {
3024
3026 }
3027 }
3028
3030 {
3031
3033 }
3034
3035
3036 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
3037 {
3040
3041
3043
3044
3046
3047
3049
3050
3052
3054
3055
3057
3058
3060
3061
3062 if (construtionPart.
IsBase())
3063 {
3064
3066 }
3067 }
3068
3070 {
3071
3073 }
3074
3077 {
3078 bool process = false;
3079
3080
3084
3085 if (process)
3086 {
3087 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
3088 {
3090 return;
3091 }
3092
3094 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
3095 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
3096
3097
3099 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
3100 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
3101 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
3102 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
3103 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
3104 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
3105 mins = minTmp;
3106 maxs = maxTmp;
3107
3108 maxs[1] = maxs[1] + 0.35;
3109
3111 }
3112 }
3113
3116 {
3119
3120
3122 foreach (
EntityAI entity : foundEntities)
3123 {
3126 }
3127 }
3128
3129
3131 {
3133
3137 }
3138
3140 {
3142
3144 {
3146 }
3147 else
3148 {
3150 }
3151
3153 }
3154
3156 {
3158
3160 foreach (
string slotName : attachmentSlots)
3161 {
3163 }
3164
3165
3168 else
3170
3172 }
3173
3175 {
3176 string slotNameMounted = slot_name + "_Mounted";
3177 EntityAI attachment = FindAttachmentBySlotName(slot_name);
3178
3179 if (attachment)
3180 {
3181 BarbedWire barbedWire = BarbedWire.Cast(attachment);
3182 if (barbedWire && barbedWire.IsMounted())
3184 else
3186
3187 if (is_locked)
3188 {
3189 SetAnimationPhase(slotNameMounted, 0);
3190 SetAnimationPhase(slot_name, 1);
3191 }
3192 else
3193 {
3194 SetAnimationPhase(slotNameMounted, 1);
3195 SetAnimationPhase(slot_name, 0);
3196 }
3197 }
3198 else
3199 {
3200 SetAnimationPhase(slotNameMounted, 1);
3201 SetAnimationPhase(slot_name, 1);
3202
3204 }
3205 }
3206
3207
3209 {
3212
3215
3218
3219 foreach (
string slotName : attachmentSlots)
3220 {
3222 }
3223
3224
3226 {
3229
3231 }
3232 else
3233 {
3236
3238 }
3239
3242 }
3243
3245 {
3246
3248 return;
3249
3250 string slot_name_mounted = slot_name + "_Mounted";
3251 EntityAI attachment = FindAttachmentBySlotName( slot_name );
3252
3253
3255 RemoveProxyPhysics( slot_name_mounted );
3256 RemoveProxyPhysics( slot_name );
3257
3258 if ( attachment )
3259 {
3261 if ( is_locked )
3262 {
3264 AddProxyPhysics( slot_name_mounted );
3265 }
3266 else
3267 {
3269 AddProxyPhysics( slot_name );
3270 }
3271 }
3272 }
3273
3275 {
3276 SetAffectPathgraph( true, false );
3278 }
3279
3281 {
3282 return true;
3283 }
3284
3286 {
3287 return true;
3288 }
3289
3291 {
3292 if ( attachment )
3293 {
3295 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
3296
3297 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
3298 }
3299
3300 return false;
3301 }
3302
3304 {
3306 }
3307
3308
3310 {
3311 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
3312 if (
GetGame().ConfigIsExisting( config_path ) )
3313 {
3315 }
3316 }
3317
3319 {
3320 return true;
3321 }
3322
3324 {
3325 return true;
3326 }
3327
3329 {
3330 return true;
3331 }
3332
3333
3335 {
3337 {
3339 }
3340
3342 }
3343
3345 {
3347 }
3348
3349
3350
3352 {
3353 return super.CanReceiveAttachment(attachment, slotId);
3354 }
3355
3357 {
3358 int attachment_count = GetInventory().AttachmentCount();
3359 if ( attachment_count > 0 )
3360 {
3361 if (
HasBase() && attachment_count == 1 )
3362 {
3363 return false;
3364 }
3365
3366 return true;
3367 }
3368
3369 return false;
3370 }
3371
3373 {
3374 return true;
3375 }
3376
3378 {
3379 return false;
3380 }
3381
3382
3384 {
3385 return false;
3386 }
3387
3389 {
3390 return false;
3391 }
3392
3393
3395 {
3396 return false;
3397 }
3398
3399
3400
3402 {
3403 return true;
3404 }
3405
3407 {
3408 return true;
3409 }
3410
3413 {
3414 return false;
3415 }
3416
3417
3419 {
3420 return true;
3421 }
3422
3423
3425 {
3426 return false;
3427 }
3428
3429
3431 {
3432 return true;
3433 }
3434
3435
3437 {
3438 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
3439 {
3440 return false;
3441 }
3442
3443 return true;
3444 }
3445
3447 {
3450
3451 return item;
3452 }
3453
3454
3456 {
3458 {
3459
3461
3462
3465
3467 if ( MemoryPointExists( slot_name + "_min" ) )
3468 {
3469 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
3470 }
3471 if ( MemoryPointExists( slot_name + "_max" ) )
3472 {
3473 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
3474 }
3475
3476
3479
3480
3483 center = ModelToWorld( center );
3484
3485
3488
3489 areaDamage.SetExtents( extents[0], extents[1] );
3490 areaDamage.SetAreaPosition( center );
3491 areaDamage.SetAreaOrientation( orientation );
3494 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
3495 areaDamage.SetAmmoName( "BarbedWireHit" );
3496 areaDamage.Spawn();
3497
3499 }
3500 }
3501
3503 {
3504 if ( angle_deg != 0 )
3505 {
3506
3507 orientation[0] = orientation[0] - angle_deg;
3508
3509
3511 if ( MemoryPointExists( "rotate_axis" ) )
3512 {
3513 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
3514 }
3515 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];
3516 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];
3517 center[0] = r_center_x;
3518 center[2] = r_center_z;
3519 }
3520 }
3521
3523 {
3525 {
3528 {
3529 if (areaDamage)
3530 {
3531 areaDamage.Destroy();
3532 }
3533
3535 }
3536 }
3537 }
3538
3540 {
3541 return true;
3542 }
3543
3544
3545
3546
3548 {
3550 }
3551
3553 {
3555 }
3556
3558 {
3560 }
3561
3563 {
3565
3566 switch ( material_type )
3567 {
3573 }
3574
3575 return "";
3576 }
3577
3579 {
3581
3582 switch ( material_type )
3583 {
3589 }
3590
3591 return "";
3592 }
3593
3594
3596 {
3598 {
3599
3601 {
3602 SetHealth(slot_name,"Health",item.GetHealth());
3603 }
3604 }
3605 }
3606
3608 {
3609 return 111;
3610 }
3611
3613 {
3614 super.SetActions();
3615
3619 }
3620
3621
3622
3623
3625 {
3626 }
3627
3630 {
3631 return null;
3632 }
3633
3635 {
3637 }
3638
3640 {
3643
3644 Man p;
3645
3646 #ifdef SERVER
3649 if (players.Count())
3650 p = players[0];
3651 #else
3653 #endif
3654
3656 {
3657 bool excluded = false;
3659 if (excludes)
3660 {
3661 foreach (string exclude : excludes)
3662 {
3664 {
3665 excluded = true;
3666 break;
3667 }
3668 }
3669 }
3670
3671 if (!excluded)
3672 {
3674 }
3675 }
3676
3678 }
3679}
3680
3682{
3683#ifdef BSB_DEBUG
3685#else
3686
3687#endif
3688}
3690{
3691#ifdef BSB_DEBUG_SPAM
3693#else
3694
3695#endif
3696}
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.