2325{
2327
2329
2331
2333
2339
2340
2341
2347
2353
2355
2359
2360
2362 {
2364
2365
2366 RegisterNetSyncVariableInt( "m_SyncParts01" );
2367 RegisterNetSyncVariableInt( "m_SyncParts02" );
2368 RegisterNetSyncVariableInt( "m_SyncParts03" );
2369 RegisterNetSyncVariableInt( "m_InteractedPartId" );
2370 RegisterNetSyncVariableInt( "m_PerformedActionId" );
2371 RegisterNetSyncVariableBool( "m_HasBase" );
2372
2373
2375
2376 if (ConfigIsExisting("hybridAttachments"))
2377 {
2380 }
2381 if (ConfigIsExisting("mountables"))
2382 {
2385 }
2386
2388 }
2389
2391 {
2392 super.EEDelete(parent);
2393
2395 {
2396 areaDamage.Destroy();
2397 }
2398
2399 }
2400
2402 {
2403 return "disableBaseDamage";
2404 }
2405
2407 {
2408 return true;
2409 }
2410
2412 {
2413 return EInventoryIconVisibility.HIDE_VICINITY;
2414 }
2415
2417 {
2418 super.InitItemSounds();
2419
2423
2428 }
2429
2431 {
2432 return "putDown_FenceKit_SoundSet";
2433 }
2434
2436 {
2437 return "Shelter_Site_Build_Loop_SoundSet";
2438 }
2439
2440
2442 {
2444 {
2445 SetSynchDirty();
2446 }
2447 }
2448
2450 {
2452 super.OnVariablesSynchronized();
2453
2455 }
2456
2458 {
2459
2461
2462
2464
2465
2467 }
2468
2469
2471 {
2472
2473 int offset;
2474 int mask;
2475
2476 if ( part_id >= 1 && part_id <= 31 )
2477 {
2478 offset = part_id - 1;
2479 mask = 1 << offset;
2480
2482 }
2483 else if ( part_id >= 32 && part_id <= 62 )
2484 {
2485 offset = ( part_id % 32 );
2486 mask = 1 << offset;
2487
2489 }
2490 else if ( part_id >= 63 && part_id <= 93 )
2491 {
2492 offset = ( part_id % 63 );
2493 mask = 1 << offset;
2494
2496 }
2497 }
2498
2500 {
2501
2502 int offset;
2503 int mask;
2504
2505 if ( part_id >= 1 && part_id <= 31 )
2506 {
2507 offset = part_id - 1;
2508 mask = 1 << offset;
2509
2511 }
2512 else if ( part_id >= 32 && part_id <= 62 )
2513 {
2514 offset = ( part_id % 32 );
2515 mask = 1 << offset;
2516
2518 }
2519 else if ( part_id >= 63 && part_id <= 93 )
2520 {
2521 offset = ( part_id % 63 );
2522 mask = 1 << offset;
2523
2525 }
2526 }
2527
2529 {
2530
2531 int offset;
2532 int mask;
2533
2534 if ( part_id >= 1 && part_id <= 31 )
2535 {
2536 offset = part_id - 1;
2537 mask = 1 << offset;
2538
2540 {
2541 return true;
2542 }
2543 }
2544 else if ( part_id >= 32 && part_id <= 62 )
2545 {
2546 offset = ( part_id % 32 );
2547 mask = 1 << offset;
2548
2550 {
2551 return true;
2552 }
2553 }
2554 else if ( part_id >= 63 && part_id <= 93 )
2555 {
2556 offset = ( part_id % 63 );
2557 mask = 1 << offset;
2558
2560 {
2561 return true;
2562 }
2563 }
2564
2565 return false;
2566 }
2567
2569 {
2572 }
2573
2575 {
2576
2579 }
2580
2582 {
2584 {
2587
2588 switch( build_action_id )
2589 {
2593 }
2594 }
2595 }
2596
2597
2599 {
2601 bool is_base = part.
IsBase();
2604 if ( is_part_built_sync )
2605 {
2607 {
2611
2612 if (is_base)
2613 {
2616 }
2617 }
2618 }
2619 else
2620 {
2622 {
2626
2627 if (is_base)
2628 {
2631 }
2632 }
2633 }
2634
2635
2637 }
2638
2639
2641 {
2644
2645 for ( int i = 0; i < construction_parts.Count(); ++i )
2646 {
2647 string key = construction_parts.GetKey( i );
2650 }
2651
2652
2654 }
2655
2657 {
2660
2661 for ( int i = 0; i < construction_parts.Count(); ++i )
2662 {
2663 string key = construction_parts.GetKey( i );
2665
2666 if ( value.
GetId() ==
id )
2667 {
2668 return value;
2669 }
2670 }
2671
2672 return NULL;
2673 }
2674
2675
2676
2678 {
2680 }
2681
2683 {
2685 }
2686
2688 {
2689 return true;
2690 }
2691
2693 {
2694 return false;
2695 }
2696
2697
2699 {
2702 {
2704 }
2705
2706 return construction_kit;
2707 }
2708
2710 {
2713 {
2715 }
2716 }
2717
2719 {
2721 }
2722
2724 {
2725 return "";
2726 }
2727
2729 {
2732 }
2733
2734
2736 {
2739 }
2740
2741
2743 {
2744 super.OnStoreSave( ctx );
2745
2746
2750
2752 }
2753
2755 {
2756 if ( !super.OnStoreLoad( ctx, version ) )
2757 return false;
2758
2759
2760
2762 {
2764 return false;
2765 }
2767 {
2769 return false;
2770 }
2772 {
2774 return false;
2775 }
2776
2777
2779 {
2781 return false;
2782 }
2783
2784
2785 return true;
2786 }
2787
2789 {
2790 super.AfterStoreLoad();
2791
2793 {
2795 }
2796 }
2797
2799 {
2800
2802
2803
2806
2807
2809 }
2810
2812 {
2813 super.OnCreatePhysics();
2816 }
2817
2819 {
2821 return;
2822
2823 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2824
2826 return;
2827
2829 string part_name = zone;
2831
2833 {
2834 ConstructionPart construction_part = construction.GetConstructionPart( part_name );
2835
2836 if ( construction_part && construction.IsPartConstructed( part_name ) )
2837 {
2839 construction.DestroyConnectedParts(part_name);
2840 }
2841
2842
2843 if ( part_name.
Contains(
"barbed") )
2844 {
2845 BarbedWire barbed_wire = BarbedWire.Cast( FindAttachmentBySlotName( zone ) );
2846 if (barbed_wire)
2847 barbed_wire.SetMountedState( false );
2848 }
2849 }
2850 }
2851
2853 {
2855 {
2857 }
2858
2859 super.EEOnAfterLoad();
2860 }
2861
2863 {
2864 super.EEInit();
2865
2866
2868
2869
2870 #ifdef DEVELOPER
2872 #endif
2873 }
2874
2876 {
2877 super.EEItemAttached( item, slot_name );
2878
2882 }
2883
2885 {
2886 super.EEItemDetached( item, slot_name );
2887
2890 }
2891
2892 protected void OnSetSlotLock(
int slotId,
bool locked,
bool was_locked )
2893 {
2896
2899 }
2900
2901
2903 {
2904 return true;
2905 }
2906
2907
2908
2910 {
2912
2913
2914 if (construtionPart.
IsBase())
2915 {
2917
2918
2920 }
2921
2922
2924
2925
2927
2928
2930
2932
2934
2935
2937
2938
2940 }
2941
2943 {
2944
2946 }
2947
2948
2950 {
2953
2954
2956
2957
2959
2960
2962
2963
2965
2967
2968
2970
2971
2973
2974
2975 if (construtionPart.
IsBase())
2976 {
2977
2979 }
2980 }
2981
2983 {
2984
2986 }
2987
2988
2989 void OnPartDestroyedServer(Man player,
string part_name,
int action_id,
bool destroyed_by_connected_part =
false)
2990 {
2993
2994
2996
2997
2999
3000
3002
3003
3005
3007
3008
3010
3011
3013
3014
3015 if (construtionPart.
IsBase())
3016 {
3017
3019 }
3020 }
3021
3023 {
3024
3026 }
3027
3030 {
3031 bool process = false;
3032
3033
3037
3038 if (process)
3039 {
3040 if (!MemoryPointExists(part.
m_PartName +
"_min") || !MemoryPointExists(part.
m_PartName +
"_max"))
3041 {
3043 return;
3044 }
3045
3047 mins = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_min"));
3048 maxs = ModelToWorld(GetMemoryPointPos(part.
m_PartName +
"_max"));
3049
3050
3052 minTmp[0] =
Math.
Min(mins[0],maxs[0]);
3053 maxTmp[0] =
Math.
Max(mins[0],maxs[0]);
3054 minTmp[1] =
Math.
Min(mins[1],maxs[1]);
3055 maxTmp[1] =
Math.
Max(mins[1],maxs[1]);
3056 minTmp[2] =
Math.
Min(mins[2],maxs[2]);
3057 maxTmp[2] =
Math.
Max(mins[2],maxs[2]);
3058 mins = minTmp;
3059 maxs = maxTmp;
3060
3061 maxs[1] = maxs[1] + 0.35;
3062
3064 }
3065 }
3066
3069 {
3072
3073
3075 foreach (
EntityAI entity : foundEntities)
3076 {
3079 }
3080 }
3081
3082
3084 {
3086
3090 }
3091
3093 {
3095
3097 {
3099 }
3100 else
3101 {
3103 }
3104
3106 }
3107
3109 {
3111
3113 foreach (
string slotName : attachmentSlots)
3114 {
3116 }
3117
3118
3121 else
3123
3125 }
3126
3128 {
3129 string slotNameMounted = slot_name + "_Mounted";
3130 EntityAI attachment = FindAttachmentBySlotName(slot_name);
3131
3132 if (attachment)
3133 {
3134 BarbedWire barbedWire = BarbedWire.Cast(attachment);
3135 if (barbedWire && barbedWire.IsMounted())
3137 else
3139
3140 if (is_locked)
3141 {
3142 SetAnimationPhase(slotNameMounted, 0);
3143 SetAnimationPhase(slot_name, 1);
3144 }
3145 else
3146 {
3147 SetAnimationPhase(slotNameMounted, 1);
3148 SetAnimationPhase(slot_name, 0);
3149 }
3150 }
3151 else
3152 {
3153 SetAnimationPhase(slotNameMounted, 1);
3154 SetAnimationPhase(slot_name, 1);
3155
3157 }
3158 }
3159
3160
3162 {
3165
3168
3171
3172 foreach (
string slotName : attachmentSlots)
3173 {
3175 }
3176
3177
3179 {
3182
3184 }
3185 else
3186 {
3189
3191 }
3192
3195 }
3196
3198 {
3199
3201 return;
3202
3203 string slot_name_mounted = slot_name + "_Mounted";
3204 EntityAI attachment = FindAttachmentBySlotName( slot_name );
3205
3206
3208 RemoveProxyPhysics( slot_name_mounted );
3209 RemoveProxyPhysics( slot_name );
3210
3211 if ( attachment )
3212 {
3214 if ( is_locked )
3215 {
3217 AddProxyPhysics( slot_name_mounted );
3218 }
3219 else
3220 {
3222 AddProxyPhysics( slot_name );
3223 }
3224 }
3225 }
3226
3228 {
3229 SetAffectPathgraph( true, false );
3231 }
3232
3234 {
3235 return true;
3236 }
3237
3239 {
3240 return true;
3241 }
3242
3244 {
3245 if ( attachment )
3246 {
3248 attachment.GetInventory().GetCurrentInventoryLocation( inventory_location );
3249
3250 return GetInventory().GetSlotLock( inventory_location.
GetSlot() );
3251 }
3252
3253 return false;
3254 }
3255
3257 {
3259 }
3260
3261
3263 {
3264 string config_path = "CfgVehicles" + " " + entity.GetType() + " " + "attachments";
3265 if (
GetGame().ConfigIsExisting( config_path ) )
3266 {
3268 }
3269 }
3270
3272 {
3273 return true;
3274 }
3275
3277 {
3278 return true;
3279 }
3280
3282 {
3283 return true;
3284 }
3285
3286
3288 {
3290 {
3292 }
3293
3295 }
3296
3298 {
3300 }
3301
3302
3303
3305 {
3306 return super.CanReceiveAttachment(attachment, slotId);
3307 }
3308
3310 {
3311 int attachment_count = GetInventory().AttachmentCount();
3312 if ( attachment_count > 0 )
3313 {
3314 if (
HasBase() && attachment_count == 1 )
3315 {
3316 return false;
3317 }
3318
3319 return true;
3320 }
3321
3322 return false;
3323 }
3324
3326 {
3327 return true;
3328 }
3329
3331 {
3332 return false;
3333 }
3334
3335
3337 {
3338 return false;
3339 }
3340
3342 {
3343 return false;
3344 }
3345
3346
3348 {
3349 return false;
3350 }
3351
3352
3353
3355 {
3356 return true;
3357 }
3358
3360 {
3361 return true;
3362 }
3363
3366 {
3367 return false;
3368 }
3369
3370
3372 {
3373 return true;
3374 }
3375
3376
3378 {
3379 return false;
3380 }
3381
3382
3384 {
3385 return true;
3386 }
3387
3388
3390 {
3391 if (
HasBase() || GetInventory().AttachmentCount() > 0 )
3392 {
3393 return false;
3394 }
3395
3396 return true;
3397 }
3398
3400 {
3403
3404 return item;
3405 }
3406
3407
3409 {
3411 {
3412
3414
3415
3418
3420 if ( MemoryPointExists( slot_name + "_min" ) )
3421 {
3422 min_max[0] = GetMemoryPointPos( slot_name + "_min" );
3423 }
3424 if ( MemoryPointExists( slot_name + "_max" ) )
3425 {
3426 min_max[1] = GetMemoryPointPos( slot_name + "_max" );
3427 }
3428
3429
3432
3433
3436 center = ModelToWorld( center );
3437
3438
3441
3442 areaDamage.SetExtents( extents[0], extents[1] );
3443 areaDamage.SetAreaPosition( center );
3444 areaDamage.SetAreaOrientation( orientation );
3447 areaDamage.SetHitZones( { "Torso","LeftHand","LeftLeg","LeftFoot","RightHand","RightLeg","RightFoot" } );
3448 areaDamage.SetAmmoName( "BarbedWireHit" );
3449 areaDamage.Spawn();
3450
3452 }
3453 }
3454
3456 {
3457 if ( angle_deg != 0 )
3458 {
3459
3460 orientation[0] = orientation[0] - angle_deg;
3461
3462
3464 if ( MemoryPointExists( "rotate_axis" ) )
3465 {
3466 rotate_axis = ModelToWorld( GetMemoryPointPos( "rotate_axis" ) );
3467 }
3468 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];
3469 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];
3470 center[0] = r_center_x;
3471 center[2] = r_center_z;
3472 }
3473 }
3474
3476 {
3478 {
3481 {
3482 if (areaDamage)
3483 {
3484 areaDamage.Destroy();
3485 }
3486
3488 }
3489 }
3490 }
3491
3493 {
3494 return true;
3495 }
3496
3497
3498
3499
3501 {
3503 }
3504
3506 {
3508 }
3509
3511 {
3513 }
3514
3516 {
3518
3519 switch ( material_type )
3520 {
3526 }
3527
3528 return "";
3529 }
3530
3532 {
3534
3535 switch ( material_type )
3536 {
3542 }
3543
3544 return "";
3545 }
3546
3547
3549 {
3551 {
3552
3554 {
3555 SetHealth(slot_name,"Health",item.GetHealth());
3556 }
3557 }
3558 }
3559
3561 {
3562 return 111;
3563 }
3564
3566 {
3567 super.SetActions();
3568
3572 }
3573
3574
3575
3576
3578 {
3579 }
3580
3583 {
3584 return null;
3585 }
3586
3588 {
3590 }
3591
3593 {
3596
3597 Man p;
3598
3599 #ifdef SERVER
3602 if (players.Count())
3603 p = players[0];
3604 #else
3606 #endif
3607
3609 {
3610 bool excluded = false;
3612 if (excludes)
3613 {
3614 foreach (string exclude : excludes)
3615 {
3617 {
3618 excluded = true;
3619 break;
3620 }
3621 }
3622 }
3623
3624 if (!excluded)
3625 {
3627 }
3628 }
3629
3631 }
3632}
3633
3635{
3636#ifdef BSB_DEBUG
3638#else
3639
3640#endif
3641}
3643{
3644#ifdef BSB_DEBUG_SPAM
3646#else
3647
3648#endif
3649}
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.