{"TotalCount":154,"Files":[{"Ident":"facepunch.sbdm","Path":"Items/Pickups/ArmourPickup.cs","FileName":"ArmourPickup.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\r\n/// A pickup that gives the player some armour.\r\n/// \u003C/summary\u003E\r\npublic sealed class ArmourPickup : BasePickup\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// How much armour to give to the player\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Group( \u0022Armour\u0022 )] float ArmourGive { get; set; } = 0;\r\n\r\n\tpublic override bool CanPickup( Player player, PlayerInventory inventory )\r\n\t{\r\n\t\tif ( player.Armour \u003E= player.MaxArmour \u0026\u0026 ArmourGive \u003E 0 )\r\n\t\t\treturn false;\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\tprotected override bool OnPickup( Player player, PlayerInventory inventory )\r\n\t{\r\n\t\tplayer.Armour = (player.Armour \u002B ArmourGive).Clamp( 0, player.MaxArmour );\r\n\t\tplayer.PlayerData.AddStat( $\u0022pickup.armor\u0022 );\r\n\r\n\t\treturn true;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Map/BaseToggle.cs","FileName":"BaseToggle.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"public abstract class BaseToggle : Component\r\n{\r\n\tpublic delegate Task StateChangedDelegate( bool state );\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The toggle state has changed\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public StateChangedDelegate OnStateChanged { get; set; }\r\n\r\n\tbool _state;\r\n\r\n\t[Property, Sync]\r\n\tpublic bool State\r\n\t{\r\n\t\tget =\u003E _state;\r\n\t\tset\r\n\t\t{\r\n\t\t\tif ( _state == value ) return;\r\n\r\n\t\t\t_state = value;\r\n\t\t\tStateHasChanged( _state );\r\n\r\n\t\t}\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The toggle state has changed\r\n\t/// \u003C/summary\u003E\r\n\tprotected virtual void StateHasChanged( bool newState )\r\n\t{\r\n\t\tOnStateChanged?.Invoke( _state );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Player/GrabAction.cs","FileName":"GrabAction.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\r\n/// Put this component on something that is pressable, and the player will grab it with a certain style animation.\r\n/// \u003C/summary\u003E\r\npublic partial class GrabAction : Component\r\n{\r\n\tpublic enum GrabStyle\r\n\t{\r\n\t\tNone,\r\n\t\tSweepDown,\r\n\t\tSweepRight,\r\n\t\tSweepLeft,\r\n\t\tPressButton\r\n\t}\r\n\r\n\t[Property]\r\n\tpublic GrabStyle Style { get; set; } = GrabStyle.SweepDown;\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"UI/Inventory.razor","FileName":"Inventory.razor","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"@using Sandbox;\r\n@using Sandbox.UI;\r\n@inherits PanelComponent\r\n@implements ILocalPlayerEvent\r\n\r\n\u003Croot\u003E\r\n\t@for (int i = 0; i \u003C 5; i\u002B\u002B)\r\n\t{\r\n        @if ( ItemsInSlot(i).Count() \u003C 1 )\r\n        {\r\n            continue;\r\n        }\r\n\r\n        \u003CInventorySlot Index=@i Inventory=@inventory Hovered=@hovered Active=@active\u003E\u003C/InventorySlot\u003E\r\n\t}\r\n\u003C/root\u003E\r\n\r\n@code\r\n{\r\n    [Property] public SoundEvent SwitchSound { get; set; }\r\n    [Property] public SoundEvent SelectSound { get; set; }\r\n    [Property] public SoundEvent CancelSound { get; set; }\r\n\r\n    PlayerInventory inventory =\u003E Player.Local.IsValid() ? Player.Local.Inventory : null;\r\n    Carryable hovered;\r\n    Carryable active;\r\n    Carryable prev;\r\n\r\n    protected override int BuildHash() =\u003E HashCode.Combine(inventory, hovered, active);\r\n\r\n    IEnumerable\u003CCarryable\u003E ItemsInSlot( int slot )\r\n    {\r\n        return inventory.IsValid() ? inventory.Carryables.Where(x =\u003E x.PreferredSlot == slot) : [];\r\n    }\r\n\r\n    void ILocalPlayerEvent.OnPickup( BaseInventoryItem weapon )\r\n    {\r\n        StateHasChanged();\r\n    }\r\n\r\n    protected override void OnUpdate()\r\n    {\r\n        DoInventoryInput();\r\n\t}\r\n\r\n\tRealTimeSince timeSinceInteraction;\r\n\r\n\tvoid DoInventoryInput()\r\n\t{\r\n\t\tif (inventory is null)\r\n\t\t\treturn;\r\n\r\n\t\tif (GameManager.Current.CurrentGameStage != GameManager.GameStage.Game)\r\n\t\t{\r\n\t\t\tif (hovered is not null)\r\n\t\t\t{\r\n\t\t\t\thovered = null;\r\n\t\t\t\tactive = null;\r\n\t\t\t\tprev = null;\r\n\t\t\t}\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tMoveSlot(-(int)Input.MouseWheel.y);\r\n\r\n\t\tif ( Input.Pressed( \u0022Menu\u0022 ) \u0026\u0026 prev.IsValid() )\r\n\t\t{\r\n\t\t\tvar weapon = prev;\r\n            prev = inventory.Current;\r\n\t\t\tinventory.SwitchWeapon( weapon );\r\n\t\t}\r\n\r\n\t\tif (Input.Pressed(\u0022SlotNext\u0022)) MoveSlot(1);\r\n\t\tif (Input.Pressed(\u0022SlotPrev\u0022)) MoveSlot(-1);\r\n\r\n\t\tif (Input.Pressed(\u0022Slot1\u0022)) IterateSlot(0);\r\n\t\tif (Input.Pressed(\u0022Slot2\u0022)) IterateSlot(1);\r\n\t\tif (Input.Pressed(\u0022Slot3\u0022)) IterateSlot(2);\r\n\t\tif (Input.Pressed(\u0022Slot4\u0022)) IterateSlot(3);\r\n\t\tif (Input.Pressed(\u0022Slot5\u0022)) IterateSlot(4);\r\n\r\n\t\tif (hovered is null)\r\n\t\t\treturn;\r\n\r\n\t\tif (Input.Pressed(\u0022Attack1\u0022))\r\n\t\t{\r\n\t\t\tInput.ReleaseAction(\u0022Attack1\u0022);\r\n\t\t\tInput.SetAction(\u0022Attack1\u0022, false);\r\n\r\n\t\t\tprev = inventory.Current;\r\n\t\t\tinventory.SwitchWeapon(hovered);\r\n\t\t\tactive = hovered;\r\n\t\t\thovered = null;\r\n\t\t\tSound.Play(SelectSound);\r\n\t\t}\r\n\r\n\t\tif (Input.Pressed(\u0022Attack2\u0022) || timeSinceInteraction \u003E 2f)\r\n\t\t{\r\n\t\t\tInput.ReleaseAction(\u0022Attack2\u0022);\r\n\t\t\tInput.SetAction(\u0022Attack2\u0022, false);\r\n\t\t\tactive = null;\r\n\t\t\thovered = null;\r\n\t\t\tSound.Play(CancelSound);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void MoveSlot( int delta )\r\n\t{\r\n\t\tif ( delta == 0 )\r\n\t\t\treturn;\r\n\r\n\t\tvar weapons = inventory.Carryables.Where( x =\u003E x.CanSwitch() ).ToList();\r\n\r\n\t\tif ( weapons.Count == 0 )\r\n\t\t\treturn;\r\n\r\n        var currentHover = hovered ?? active ?? inventory.Current ?? weapons.FirstOrDefault();\r\n\r\n\t\tint currentIndex = weapons.IndexOf( currentHover );\r\n\r\n\t\tcurrentIndex \u002B= delta;\r\n\t\tcurrentIndex %= weapons.Count;\r\n\t\tif ( currentIndex \u003C 0 )\r\n\t\t\tcurrentIndex = weapons.Count \u002B currentIndex;\r\n\r\n\t\tactive = null;\r\n\t\tif ( GamePreferences.FastSwitch )\r\n\t\t{\r\n\t\t\tinventory.SwitchWeapon( weapons[currentIndex] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thovered = weapons[currentIndex];\r\n\t\t\ttimeSinceInteraction = 0;\r\n\t\t}\r\n\r\n\t\tSound.Play( SwitchSound );\r\n\t}\r\n\r\n\tpublic void IterateSlot( int slot )\r\n\t{\r\n\t\tvar slotWeapons = inventory.Carryables.Where( x =\u003E x.PreferredSlot == slot ).Where( x =\u003E x.CanSwitch() ).OrderBy( x =\u003E x.SlotOrder ).ToList();\r\n\t\tif ( slotWeapons.Count == 0 )\r\n\t\t\treturn;\r\n\r\n\t\t// if inventory wasn\u0027t open, and current weapon is in a different slot, currentIndex will be -1 (incremented to 0), and first weapon in target slot will be selected\r\n        var currentHover = hovered ?? active ?? inventory.Current ?? slotWeapons.FirstOrDefault();\r\n\r\n\t\tint currentIndex = slotWeapons.IndexOf( currentHover );\r\n\r\n\t\tcurrentIndex \u002B= 1;\r\n\t\tcurrentIndex %= slotWeapons.Count;\r\n\r\n\t\tif ( currentIndex \u003C 0 )\r\n\t\t\tcurrentIndex = slotWeapons.Count \u002B currentIndex;\r\n\r\n\t\tactive = null;\r\n\t\tif ( GamePreferences.FastSwitch )\r\n\t\t{\r\n\t\t\tinventory.SwitchWeapon( slotWeapons[currentIndex] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thovered = slotWeapons[currentIndex];\r\n\t\t\ttimeSinceInteraction = 0;\r\n\t\t}\r\n\r\n\t\tSound.Play( SwitchSound );\r\n    }\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Utility/CameraNoise/CameraNoiseSystem.cs","FileName":"CameraNoiseSystem.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"namespace Sandbox.CameraNoise;\r\n\r\npublic class CameraNoiseSystem : GameObjectSystem\u003CCameraNoiseSystem\u003E, ICameraSetup\r\n{\r\n\tList\u003CBaseCameraNoise\u003E _all = new();\r\n\r\n\tpublic CameraNoiseSystem( Scene scene ) : base( scene )\r\n\t{\r\n\t}\r\n\r\n\tvoid ICameraSetup.PreSetup( Sandbox.CameraComponent cc )\r\n\t{\r\n\t\tforeach ( var effect in _all )\r\n\t\t{\r\n\t\t\teffect.Update();\r\n\t\t}\r\n\r\n\t\t_all.RemoveAll( x =\u003E x.IsDone );\r\n\t}\r\n\r\n\tvoid ICameraSetup.PostSetup( CameraComponent cc )\r\n\t{\r\n\t\tforeach ( var effect in _all )\r\n\t\t{\r\n\t\t\teffect.ModifyCamera( cc );\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void Add( BaseCameraNoise noise )\r\n\t{\r\n\t\t_all.Add( noise );\r\n\t}\r\n}\r\n\r\npublic abstract class BaseCameraNoise\r\n{\r\n\tpublic float LifeTime { get; protected set; }\r\n\tpublic float CurrentTime { get; protected set; }\r\n\tpublic float Delta =\u003E CurrentTime.LerpInverse( 0, LifeTime, true );\r\n\tpublic float DeltaInverse =\u003E 1 - Delta;\r\n\r\n\tpublic BaseCameraNoise()\r\n\t{\r\n\t\tCameraNoiseSystem.Current.Add( this );\r\n\t}\r\n\r\n\tpublic virtual bool IsDone =\u003E CurrentTime \u003E LifeTime;\r\n\r\n\tpublic virtual void Update()\r\n\t{\r\n\t\tCurrentTime \u002B= Time.Delta;\r\n\t}\r\n\r\n\tpublic virtual void ModifyCamera( CameraComponent cc ) { }\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Weapons/CrossbowProjectile.cs","FileName":"CrossbowProjectile.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"namespace Sandbox;\r\n\r\ninternal class CrossbowProjectile : Projectile, IKillIcon\r\n{\r\n\t[Property]\r\n\tpublic Curve Curve { get; set; }\r\n\r\n\t[Property]\r\n\tpublic float ExplosiveDamage { get; set; } = 70f;\r\n\r\n\t[Property]\r\n\tpublic float Radius { get; set; } = 128.0f;\r\n\r\n\t[Property]\r\n\tTexture IKillIcon.DisplayIcon { get; set; }\r\n\r\n\tprotected override void OnHit( Collision collision = default )\r\n\t{\r\n\t\tCreateEffects( collision.Contact.Point \u002B (collision.Contact.Speed.Normal * 32) );\r\n\r\n\t\t// Direct hit, just kill the player\r\n\t\tif ( collision.Other.GameObject.GetComponentInParent\u003CPlayer\u003E() is Player player \u0026\u0026 player.IsValid() )\r\n\t\t{\r\n\t\t\tplayer.OnDamage( new DamageInfo( 200, Instigator?.Player?.GameObject, GameObject ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Explode in radius\r\n\t\t\tDamage.Radius( collision.Contact.Point, Radius, ExplosiveDamage, [DamageTags.Explosion], GameObject, GameObject, Curve, Instigator );\r\n\t\t}\r\n\r\n\t\tGameObject.Destroy();\r\n\t}\r\n\r\n\t[Rpc.Broadcast( NetFlags.HostOnly )]\r\n\tprivate void CreateEffects( Vector3 position )\r\n\t{\r\n\t\tif ( Application.IsDedicatedServer ) return;\r\n\r\n\t\tEffects.SpawnExplosionSmall( position );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Weapons/Item.cs","FileName":"Item.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\n/// Base class for a passive thing a player carries in their inventory and stores in a coffin - it is\n/// never equipped. Anything that can be selected and held derives from \u003Csee cref=\u0022Carryable\u0022/\u003E instead.\n/// \u003C/summary\u003E\npublic abstract partial class Item : BaseInventoryItem\n{\n\t/// \u003Csummary\u003E\n\t/// The player that owns this item\n\t/// \u003C/summary\u003E\n\tpublic Player Owner =\u003E GetComponentInParent\u003CPlayer\u003E( true );\n\n\t/// \u003Csummary\u003E\n\t/// Passive items are never deployed, so the inventory must never select one.\n\t/// \u003C/summary\u003E\n\tprotected override bool OnCanSwitchTo() =\u003E false;\n\n\t/// \u003Csummary\u003E\n\t/// Called when the owner dies\n\t/// \u003C/summary\u003E\n\tpublic virtual void OnPlayerDeath( IPlayerEvent.DiedParams args )\n\t{\n\t}\n}\n"},{"Ident":"facepunch.sbdm","Path":"ui/controls/color/coloralphacontrol.cs.scss","FileName":"coloralphacontrol.cs.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"ColorAlphaControl\r\n{\r\n\tgap: 0.5rem;\r\n\tflex-grow: 1;\r\n\tpointer-events: all;\r\n\tbackground: linear-gradient( to right, black, white );\r\n\tborder-radius: 4px;\r\n\tpadding: 2px;\r\n\theight: 12px;\r\n\tposition: relative;\r\n\tcursor: pointer;\r\n\tborder: 1px solid #333;\r\n\r\n\t\u0026:hover\r\n\t{\r\n\t\tborder: 1px solid #08f;\r\n\t}\r\n\r\n\t\u0026:active\r\n\t{\r\n\t\tborder: 1px solid #fff;\r\n\t}\r\n\r\n\t.handle\r\n\t{\r\n\t\ttop: -5px;\r\n\t\tbottom: -5px;\r\n\t\taspect-ratio: 1;\r\n\t\tborder-radius: 100px;\r\n\t\tborder: 2px solid #444;\r\n\t\tposition: absolute;\r\n\t\tbackground-color: white;\r\n\t\tbox-shadow: 2px 2px 16px #000a;\r\n\t\ttransform: translateX( -50% );\r\n\t\tpointer-events: none;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":".obj/__compiler_extra.cs","FileName":"__compiler_extra.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"global using static Sandbox.Internal.GlobalGameNamespace;\r\nglobal using Microsoft.AspNetCore.Components;\r\nglobal using Microsoft.AspNetCore.Components.Rendering;\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022AddonTitle\u0022, \u0022Deathmatch\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022AddonIdent\u0022, \u0022sbdm\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022OrgIdent\u0022, \u0022facepunch\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022Ident\u0022, \u0022facepunch.sbdm\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022EngineVersion\u0022, \u002228\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022EngineMinorVersion\u0022, \u00221\u0022 )]\r\n\r\n[assembly: System.Runtime.Versioning.TargetFramework( \u0022.NETCoreApp,Version=v9.0\u0022, FrameworkDisplayName = \u0022.NET 9.0\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyMetadata( \u0022CompileTime\u0022, \u00222026-07-29T09:34:51.9024540Z\u0022 )]\r\n[assembly: global::System.Reflection.AssemblyVersion(\u00220.0.111.0\u0022)]\r\n[assembly: global::System.Reflection.AssemblyFileVersion(\u00220.0.111.0\u0022)]"},{"Ident":"facepunch.sbdm","Path":"AI/Rat.cs","FileName":"Rat.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\r\n/// A rat NPC\r\n/// \u003C/summary\u003E\r\npublic sealed class Rat : Component, Component.IDamageable, IKillIcon, Component.ICollisionListener, IInstigator\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// The \u003Csee cref=\u0022NavMeshAgent\u0022/\u003E which lets the rat traverse the navmesh\r\n\t/// \u003C/summary\u003E\r\n\t[RequireComponent] public NavMeshAgent Agent { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The \u003Csee cref=\u0022Rigidbody\u0022/\u003E which we switch out to when jumping off of the navmesh\r\n\t/// \u003C/summary\u003E\r\n\t[RequireComponent] public Rigidbody Rigidbody { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// What should we spawn when the Rat dies?\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public GameObject DeathEffects { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// What sound should we play when the Rat dies?\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public SoundEvent AttackSound { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The mouth of the rat, used for attack range\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public GameObject Mouth { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// An icon to show on the kill feed when the rat kills someone\r\n\t/// \u003C/summary\u003E\r\n\t[Property] Texture IKillIcon.DisplayIcon { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How far (sq units) away should the rat be before it starts attacking people?\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float AttackDistance { get; set; } = 50000f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How long until the rat implodes\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float Lifetime { get; set; } = 30f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How frequently should the rat choose a new roam location\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float RoamFrequency { get; set; } = 5f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How far away can the rat roam\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float RoamRadius { get; set; } = 1024f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Damage dealt when the rat bites a target\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float BiteDamage { get; set; } = 10f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Time (in seconds) between bite attacks\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float BiteCooldown { get; set; } = 1f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Time (in seconds) between lunge attacks\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float LungeCooldown { get; set; } = 3f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How often the rat thinks/updates its behavior (in seconds)\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float ThinkInterval { get; set; } = 0.1f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Distance squared for bite attack range\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float BiteRangeSquared { get; set; } = 5000f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Distance squared for target detection range\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float TargetDetectionRangeSquared { get; set; } = 262144f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Distance threshold for reaching roam target\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float RoamTargetThreshold { get; set; } = 32f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Velocity when lunging at target (X = horizontal, Y = vertical)\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public Vector2 LungeVelocity { get; set; } = new Vector2( 512f, 256f );\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Velocity when thrown (X = horizontal, Y = vertical)\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public Vector2 ThrowVelocity { get; set; } = new Vector2( 1024f, 50f );\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Initial think timer delay on start\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float InitialThinkDelay { get; set; } = 5f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Lunge timer when a new target is acquired\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float NewTargetLungeDelay { get; set; } = 1.5f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Height for roam area bounding box\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float RoamAreaHeight { get; set; } = 128f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Ground check distance (up and down)\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Balance\u0022 )] public float GroundCheckDistance { get; set; } = 8f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Who\u0027s the rat\u0027s friend (the person who threw them.. not much of a friend are they)\r\n\t/// \u003C/summary\u003E\r\n\t[Sync]\r\n\tpublic PlayerData Instigator { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Are we on the ground?\r\n\t/// \u003C/summary\u003E\r\n\tbool IsOnGround = true;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The current target of the rat\r\n\t/// \u003C/summary\u003E\r\n\tPlayer target;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How many seconds has it been since the rat bit someone?\r\n\t/// \u003C/summary\u003E\r\n\tTimeSince TimeSinceBitten = 0;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How many seconds has it been since we last LUNGED\r\n\t/// \u003C/summary\u003E\r\n\tTimeSince LungeTimer = 0;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How long has the rat been alive?\r\n\t/// \u003C/summary\u003E\r\n\tTimeSince TimeSinceCreated = 0;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Time since we picked a new target\r\n\t/// \u003C/summary\u003E\r\n\tTimeSince ThinkTimer = 0;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The roam target\r\n\t/// \u003C/summary\u003E\r\n\tVector3 RoamTarget;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tTimeSinceCreated = 0;\r\n\t\tThinkTimer = InitialThinkDelay;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Trace down, see if we\u0027re hitting the ground\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Creturns\u003E\u003C/returns\u003E\r\n\tprivate void UpdateGrounded()\r\n\t{\r\n\t\tvar tr = Scene.Trace.Ray( WorldPosition \u002B Vector3.Up * GroundCheckDistance, WorldPosition \u002B Vector3.Down * GroundCheckDistance )\r\n\t\t\t.IgnoreGameObjectHierarchy( GameObject.Root )\r\n\t\t\t.Run();\r\n\r\n\t\tIsOnGround = tr.Hit;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Throws a rat in a set direction\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Cparam name=\u0022rotation\u0022\u003E\u003C/param\u003E\r\n\tpublic void Throw( Rotation rotation )\r\n\t{\r\n\t\tvar direction = rotation.Forward;\r\n\t\tAgent.UpdatePosition = false;\r\n\t\tWorldRotation = Rotation.LookAt( direction, Vector3.Up );\r\n\t\tRigidbody.Velocity = WorldRotation.Forward * ThrowVelocity.x \u002B Vector3.Up * ThrowVelocity.y;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Called when the rat either lifts off the ground, or lands\r\n\t/// \u003C/summary\u003E\r\n\tvoid OnGroundedChanged( bool before, bool after )\r\n\t{\r\n\t\tAgent.SetAgentPosition( WorldPosition );\r\n\t}\r\n\r\n\r\n\tprivate bool hasLanded = false;\r\n\tvoid ICollisionListener.OnCollisionStart( Collision collision )\r\n\t{\r\n\t\t// if we\u0027re thrown somewhere, hit the ground running\r\n\t\tif ( !hasLanded )\r\n\t\t{\r\n\t\t\tRigidbody.Velocity = Vector3.Zero;\r\n\t\t\tAgent.SetAgentPosition( WorldPosition );\r\n\t\t\thasLanded = true;\r\n\t\t}\r\n\t}\r\n\r\n\tvoid Bite( Player target )\r\n\t{\r\n\t\tTimeSinceBitten = 0;\r\n\r\n\t\tDoAttackEffects();\r\n\r\n\t\tvar dmg = new DamageInfo( BiteDamage, Instigator?.Player?.GameObject, GameObject );\r\n\r\n\t\ttarget.OnDamage( dmg );\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( IsProxy )\r\n\t\t\treturn;\r\n\r\n\t\tif ( TimeSinceCreated \u003E Lifetime )\r\n\t\t{\r\n\t\t\tDie();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// We\u0027re lunging, and we have a target\r\n\t\tif ( !IsOnGround \u0026\u0026 target.IsValid() \u0026\u0026 TimeSinceBitten \u003E BiteCooldown )\r\n\t\t{\r\n\t\t\t// Bite the target if they\u0027re close enough\r\n\t\t\tif ( target.WorldPosition.DistanceSquared( Mouth.WorldPosition ) \u003C BiteRangeSquared )\r\n\t\t\t\tBite( target );\r\n\t\t}\r\n\r\n\t\tvar prevOnGround = IsOnGround;\r\n\t\tUpdateGrounded();\r\n\r\n\t\tif ( prevOnGround != IsOnGround )\r\n\t\t\tOnGroundedChanged( prevOnGround, IsOnGround );\r\n\r\n\t\tif ( !IsOnGround )\r\n\t\t\treturn;\r\n\r\n\t\tif ( !Agent.Enabled )\r\n\t\t\treturn;\r\n\r\n\t\tif ( target.IsValid() )\r\n\t\t{\r\n\t\t\t// If we haven\u0027t attacked in a while, move towards the enemy and try to jump them\r\n\t\t\tif ( ThinkTimer \u003E ThinkInterval )\r\n\t\t\t{\r\n\t\t\t\tThinkTimer = 0;\r\n\t\t\t\tif ( WorldPosition.DistanceSquared( target.WorldPosition ) \u003C AttackDistance \u0026\u0026 LungeTimer \u003E LungeCooldown )\r\n\t\t\t\t{\r\n\t\t\t\t\tAttack();\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tAgent.UpdatePosition = true;\r\n\t\t\t\tAgent.UpdateRotation = true;\r\n\t\t\t\tAgent.MoveTo( target.WorldPosition );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse // roaming\r\n\t\t{\r\n\t\t\tif ( ThinkTimer \u003E RoamFrequency || Vector3.DistanceBetween( WorldPosition, RoamTarget ) \u003C= RoamTargetThreshold )\r\n\t\t\t{\r\n\t\t\t\tThinkTimer = 0;\r\n\r\n\t\t\t\tvar target = GetRoamPoint();\r\n\t\t\t\tif ( target.HasValue )\r\n\t\t\t\t{\r\n\t\t\t\t\tRoamTarget = target.Value;\r\n\r\n\t\t\t\t\tAgent.UpdatePosition = true;\r\n\t\t\t\t\tAgent.UpdateRotation = true;\r\n\t\t\t\t\tAgent.MoveTo( RoamTarget );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tLookForTarget();\r\n\r\n\t\t\tif ( target.IsValid() )\r\n\t\t\t{\r\n\t\t\t\t// attack soon if we\u0027ve just got a target\r\n\t\t\t\tLungeTimer = NewTargetLungeDelay;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate Vector3? GetRoamPoint()\r\n\t{\r\n\t\tvar roamSize = new Vector3( RoamRadius, RoamRadius, RoamAreaHeight );\r\n\t\tvar bbox = BBox.FromPositionAndSize( WorldPosition, new Vector3( RoamRadius, RoamRadius, RoamAreaHeight ) );\r\n\r\n\t\t// vaguely prefer moving in the direction we\u0027re looking\r\n\t\tbbox \u002B= ((roamSize.WithZ( 0 ) * WorldRotation.Forward) * 0.4f);\r\n\r\n\t\tfor ( int i = 0; i \u003C 10; i\u002B\u002B )\r\n\t\t{\r\n\t\t\tvar p = Scene.NavMesh.GetClosestPoint( bbox.RandomPointInside );\r\n\t\t\tif ( !p.HasValue || p.Value.Distance( WorldPosition ) \u003E RoamRadius )\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\t// check if navable\r\n\t\t\tvar path = Scene.NavMesh.CalculatePath( new Sandbox.Navigation.CalculatePathRequest()\r\n\t\t\t{\r\n\t\t\t\tStart = WorldPosition,\r\n\t\t\t\tTarget = p.Value\r\n\t\t\t} );\r\n\r\n\t\t\tif ( path.Status != Sandbox.Navigation.NavMeshPathStatus.Partial \u0026\u0026 path.Status != Sandbox.Navigation.NavMeshPathStatus.Complete )\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\treturn p.Value;\r\n\t\t}\r\n\r\n\t\treturn default;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Looks for a target, closest non-friend player is the target\r\n\t/// \u003C/summary\u003E\r\n\tprivate void LookForTarget( bool withRange = true )\r\n\t{\r\n\t\tvar allPlayers = Scene.GetAllComponents\u003CPlayer\u003E()\r\n\t\t\t.Where( x =\u003E Instigator.IsValid() ? x.PlayerData != Instigator : true );\r\n\r\n\t\tif ( withRange )\r\n\t\t\tallPlayers = allPlayers.Where( x =\u003E x.WorldPosition.DistanceSquared( WorldPosition ) \u003C TargetDetectionRangeSquared );\r\n\r\n\t\tallPlayers = allPlayers.OrderBy( x =\u003E x.WorldPosition.DistanceSquared( WorldPosition ) );\r\n\r\n\t\tif ( allPlayers.Any() ) target = allPlayers.First();\r\n\t}\r\n\r\n\tvoid Attack()\r\n\t{\r\n\t\t// wait the full attack length\r\n\t\tLungeTimer = 0;\r\n\r\n\t\tDoAttackEffects();\r\n\r\n\t\t// We want to take over the rat movement by enabling a rigidbody and just flinging them at a player\r\n\t\tAgent.UpdatePosition = false;\r\n\t\tAgent.UpdateRotation = false;\r\n\r\n\t\tvar dir = (target.WorldPosition - WorldPosition).WithZ( 0 ).Normal;\r\n\r\n\t\tIsOnGround = false;\r\n\t\tRigidbody.Velocity = (dir * LungeVelocity.x) \u002B (Vector3.Up * LungeVelocity.y);\r\n\t\tWorldRotation = Rotation.LookAt( dir );\r\n\r\n\t\ttarget = null;\r\n\t}\r\n\r\n\t[Rpc.Broadcast]\r\n\tvoid DoDeathEffects()\r\n\t{\r\n\t\tif ( Application.IsDedicatedServer ) return;\r\n\r\n\t\tDeathEffects?.Clone( WorldPosition );\r\n\t}\r\n\r\n\t[Rpc.Broadcast]\r\n\tvoid DoAttackEffects()\r\n\t{\r\n\t\tif ( Application.IsDedicatedServer ) return;\r\n\r\n\t\tSound.Play( AttackSound, WorldPosition );\r\n\t}\r\n\r\n\tvoid IDamageable.OnDamage( in DamageInfo damage )\r\n\t{\r\n\t\tDie();\r\n\t}\r\n\r\n\tvoid Die()\r\n\t{\r\n\t\tDoDeathEffects();\r\n\t\tGameObject.Destroy();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Items/Pickups/InventoryPickup.cs","FileName":"InventoryPickup.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\r\n/// A pickup that gives an inventory item, like a weapon\r\n/// \u003C/summary\u003E\r\npublic sealed class InventoryPickup : BasePickup\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// A list of prefabs (that have to be inventory items) that are given to the player\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Group( \u0022Inventory\u0022 )] public List\u003CGameObject\u003E Items { get; set; }\r\n\r\n\tprotected override bool OnPickup( Player player, PlayerInventory inventory )\r\n\t{\r\n\t\tif ( Items == null ) return false;\r\n\r\n\t\tbool consumed = false;\r\n\t\tforeach ( var prefab in Items )\r\n\t\t{\r\n\t\t\tif ( inventory.Pickup( prefab ).IsValid() )\r\n\t\t\t{\r\n\t\t\t\tconsumed = true;\r\n\t\t\t\tplayer.PlayerData.AddStat( $\u0022pickup.inventory.{prefab.Name}\u0022 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn consumed;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Map/TriggerTeleport.cs","FileName":"TriggerTeleport.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"public sealed class TriggerTeleport : Component, Component.ITriggerListener\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// If not empty, the target must have one of these tags\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Group( \u0022Target\u0022 )] public TagSet Include { get; set; } = new();\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// If not empty, the target must not have one of these tags\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Group( \u0022Target\u0022 )] public TagSet Exclude { get; set; } = new();\r\n\r\n\t[Property] public GameObject Target { get; set; }\r\n\t[Property] public Action\u003CGameObject\u003E OnTeleported { get; set; }\r\n\r\n\tprotected override void DrawGizmos()\r\n\t{\r\n\t\tif ( !Target.IsValid() )\r\n\t\t\treturn;\r\n\r\n\t\tGizmo.Draw.Arrow( 0, WorldTransform.PointToLocal( Target.WorldPosition ) );\r\n\t}\r\n\r\n\tvoid ITriggerListener.OnTriggerEnter( Collider other )\r\n\t{\r\n\t\tvar go = other.GameObject;\r\n\r\n\t\tif ( !IsValidTarget( ref go ) ) return;\r\n\r\n\t\tgo.WorldPosition = Target.WorldPosition;\r\n\t\tgo.Transform.ClearInterpolation();\r\n\r\n\t\tDoTeleportedEvent( go );\r\n\t}\r\n\r\n\tbool IsValidTarget( ref GameObject go )\r\n\t{\r\n\t\tgo = go.Root;\r\n\t\tif ( go.IsProxy ) return false;\r\n\r\n\t\tif ( !Exclude.IsEmpty \u0026\u0026 go.Tags.HasAny( Exclude ) )\r\n\t\t\treturn false;\r\n\r\n\t\tif ( !Include.IsEmpty \u0026\u0026 !go.Tags.HasAny( Include ) )\r\n\t\t\treturn false;\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\t[Rpc.Broadcast]\r\n\tvoid DoTeleportedEvent( GameObject obj )\r\n\t{\r\n\t\tOnTeleported?.Invoke( obj );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Player/PlayerObserver.cs","FileName":"PlayerObserver.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\r\n/// Dead players become these. They try to observe their last corpse. \r\n/// \u003C/summary\u003E\r\npublic sealed class PlayerObserver : Component\r\n{\r\n\tAngles EyeAngles;\r\n\tTimeSince timeSinceStarted;\r\n\r\n\tprotected override void OnEnabled()\r\n\t{\r\n\t\tbase.OnEnabled();\r\n\r\n\t\tEyeAngles = Scene.Camera.WorldRotation;\r\n\t\ttimeSinceStarted = 0;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tif ( IsProxy ) return;\r\n\r\n\t\tvar corpse = Scene.GetAllComponents\u003CDeathCameraTarget\u003E()\r\n\t\t\t\t\t.Where( x =\u003E x.Connection == Network.Owner )\r\n\t\t\t\t\t.OrderByDescending( x =\u003E x.Created )\r\n\t\t\t\t\t.FirstOrDefault();\r\n\r\n\t\tif ( corpse.IsValid() )\r\n\t\t{\r\n\t\t\tRotateAround( corpse );\r\n\t\t}\r\n\r\n\t\t// Don\u0027t allow immediate respawn\r\n\t\tif ( timeSinceStarted \u003C 1 )\r\n\t\t\treturn;\r\n\r\n\t\t// If pressed a button, or has been too long\r\n\t\tif ( Input.Pressed( \u0022attack1\u0022 ) || Input.Pressed( \u0022jump\u0022 ) || timeSinceStarted \u003E 4f )\r\n\t\t{\r\n\t\t\tRespawn();\r\n\t\t\tGameObject.Destroy();\r\n\t\t}\r\n\t}\r\n\r\n\t[Rpc.Host( NetFlags.OwnerOnly | NetFlags.Reliable )]\r\n\tpublic void Respawn()\r\n\t{\r\n\t\tGameManager.Current.SpawnPlayer( Network.Owner );\r\n\t\tGameObject.Destroy();\r\n\t}\r\n\r\n\tprivate void RotateAround( Component target )\r\n\t{\r\n\t\t// Find the corpse eyes\r\n\t\tif ( !target.Components.Get\u003CSkinnedModelRenderer\u003E().TryGetBoneTransform( \u0022head\u0022, out var tx ) )\r\n\t\t{\r\n\t\t\ttx.Position = target.GameObject.GetBounds().Center \u002B Vector3.Up * 25f;\r\n\t\t}\r\n\r\n\t\tvar e = EyeAngles;\r\n\t\te \u002B= Input.AnalogLook;\r\n\t\te.pitch = e.pitch.Clamp( -90, 90 );\r\n\t\te.roll = 0.0f;\r\n\t\tEyeAngles = e;\r\n\r\n\t\tvar center = tx.Position;\r\n\t\tvar targetPos = center - EyeAngles.Forward * 150f;\r\n\r\n\t\tvar tr = Scene.Trace.FromTo( center, targetPos ).Radius( 1.0f ).WithoutTags( \u0022ragdoll\u0022, \u0022effect\u0022 ).Run();\r\n\r\n\t\tScene.Camera.WorldPosition = Vector3.Lerp( Scene.Camera.WorldPosition, tr.EndPosition, timeSinceStarted, true );\r\n\t\tScene.Camera.WorldRotation = EyeAngles;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"UI/InventorySlot.razor","FileName":"InventorySlot.razor","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"@using Sandbox;\r\n@using Sandbox.UI;\r\n@inherits Panel\r\n\r\n@if ( GetWeapons().Count() \u003C 1 )\r\n{\r\n    return;\r\n}\r\n\r\n\u003Croot\u003E\r\n    \u003Cdiv class=\u0022index\u0022\u003E\r\n        \u003Clabel\u003E@(Index\u002B1)\u003C/label\u003E\r\n    \u003C/div\u003E\r\n\r\n    \u003Cdiv class=\u0022list\u0022\u003E\r\n    @foreach ( var weapon in GetWeapons() )\r\n    {\r\n        \u003CInventoryWeapon Carryable=\u0022@weapon\u0022 CanSwitch=@weapon.CanSwitch() IsHovered=\u0022@(weapon == Hovered)\u0022 /\u003E\r\n    }\r\n    \u003C/div\u003E\r\n\r\n\u003C/root\u003E\r\n\r\n@code\r\n{\r\n    public PlayerInventory Inventory { get; set; }\r\n    public Carryable Active { get; set; }\r\n    public Carryable Hovered { get; set; }\r\n\r\n    public int Index { get; set; }\r\n\r\n    IEnumerable\u003CCarryable\u003E GetWeapons()\r\n    {\r\n        if (!Inventory.IsValid()) return Enumerable.Empty\u003CCarryable\u003E();\r\n\r\n        return Inventory.Carryables.Where(x =\u003E x.PreferredSlot == Index).OrderBy(x =\u003E x.SlotOrder);\r\n    }\r\n\r\n    public override void Tick()\r\n    {\r\n        base.Tick();\r\n\r\n        SetClass(\u0022active\u0022, Hovered?.PreferredSlot == Index || Active?.PreferredSlot == Index);\r\n    }\r\n\r\n\tprotected override int BuildHash() =\u003E HashCode.Combine( GetWeapons().Count() );\r\n\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Weapons/BaseWeapon/BaseWeapon.cs","FileName":"BaseWeapon.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"using Sandbox.Rendering;\n\n/// \u003Csummary\u003E\n/// A \u003Csee cref=\u0022Carryable\u0022/\u003E that shoots. Magazines, reserve ammo, reloading and fire timing all live\n/// on \u003Csee cref=\u0022BaseCombatWeapon\u0022/\u003E now - this keeps the deathmatch-facing names and the dry-fire /\n/// auto-reload behaviour our weapons are written against.\n/// \u003C/summary\u003E\npublic partial class BaseWeapon : Carryable\n{\n\t/// \u003Csummary\u003E\n\t/// Rounds in the magazine. Read-only alias for the engine\u0027s \u003Csee cref=\u0022BaseCombatWeapon.Clip1\u0022/\u003E,\n\t/// which is host owned - spend it through \u003Csee cref=\u0022TakeAmmo(int)\u0022/\u003E so the host sees the spend,\n\t/// rather than assigning, which a client couldn\u0027t make stick.\n\t/// \u003C/summary\u003E\n\tpublic int ClipContents =\u003E Clip1;\n\n\t/// \u003Csummary\u003E\n\t/// Adds a delay, making it so we can\u0027t shoot for the specified time\n\t/// \u003C/summary\u003E\n\t/// \u003Cparam name=\u0022seconds\u0022\u003E\u003C/param\u003E\n\tpublic void AddShootDelay( float seconds )\n\t{\n\t\tSetNextFire( seconds );\n\t}\n\n\t/// \u003Csummary\u003E\n\t/// The dry fire sound if we have no ammo\n\t/// \u003C/summary\u003E\n\tprivate static SoundEvent DefaultDryFireSound = new SoundEvent( \u0022audio/sounds/dry_fire.sound\u0022 );\n\n\t/// \u003Csummary\u003E\n\t/// Play a dry fire sound. You should only call this on weapons that can\u0027t auto reload - if they can, use \u003Csee cref=\u0022TryAutoReload\u0022/\u003E instead.\n\t/// \u003C/summary\u003E\n\tpublic override void DryFire()\n\t{\n\t\tif ( HasAmmo() )\n\t\t\treturn;\n\n\t\tif ( IsReloading )\n\t\t\treturn;\n\n\t\tif ( NextPrimaryFire \u003E 0 )\n\t\t\treturn;\n\n\t\tGameObject.PlaySound( DryFireSound ?? DefaultDryFireSound );\n\t}\n\n\t/// \u003Csummary\u003E\n\t/// Player has fired an empty gun - play dry fire sound and start reloading. You should only call this on weapons that can reload - if they can\u0027t, use \u003Csee cref=\u0022DryFire\u0022/\u003E instead.\n\t/// \u003C/summary\u003E\n\tpublic virtual void TryAutoReload()\n\t{\n\t\tif ( HasAmmo() )\n\t\t\treturn;\n\n\t\tif ( IsReloading )\n\t\t\treturn;\n\n\t\tif ( NextPrimaryFire \u003E 0 )\n\t\t\treturn;\n\n\t\tDryFire();\n\n\t\tAddShootDelay( 0.1f );\n\n\t\tif ( CanReload() )\n\t\t\tReload();\n\t\telse\n\t\t\tSwitchAway();\n\t}\n\n\t/// \u003Csummary\u003E\n\t/// Are we allowed to shoot this weapon? Can be overriden per-weapon\n\t/// \u003C/summary\u003E\n\t/// \u003Creturns\u003E\u003C/returns\u003E\n\tpublic virtual bool CanShoot()\n\t{\n\t\tif ( !HasAmmo() ) return false;\n\t\tif ( IsReloading ) return false;\n\t\tif ( NextPrimaryFire \u003E 0 ) return false;\n\n\t\treturn true;\n\t}\n\n\tpublic override void DrawHud( HudPainter painter, Vector2 crosshair )\n\t{\n\t\tDrawCrosshair( painter, crosshair );\n\t}\n\n\tpublic override void DrawCrosshair( HudPainter hud, Vector2 center )\n\t{\n\t\tColor color = Color.Red;\n\n\t\thud.DrawLine( center \u002B Vector2.Left * 32, center \u002B Vector2.Left * 15, 3, color );\n\t\thud.DrawLine( center - Vector2.Left * 32, center - Vector2.Left * 15, 3, color );\n\t\thud.DrawLine( center \u002B Vector2.Up * 32, center \u002B Vector2.Up * 15, 3, color );\n\t\thud.DrawLine( center - Vector2.Up * 32, center - Vector2.Up * 15, 3, color );\n\t}\n\n\tpublic override void OnControl( Player player )\n\t{\n\t\tbase.OnControl( player );\n\n\t\tbool wantsToCancelReload = Input.Pressed( \u0022Attack1\u0022 ) || Input.Pressed( \u0022Attack2\u0022 );\n\t\tif ( CanCancelReload \u0026\u0026 IsReloading \u0026\u0026 wantsToCancelReload \u0026\u0026 HasAmmo() )\n\t\t{\n\t\t\tCancelReload();\n\t\t}\n\n\t\tif ( CanReload() \u0026\u0026 Input.Pressed( \u0022reload\u0022 ) )\n\t\t{\n\t\t\tReload();\n\t\t}\n\t}\n}\n"},{"Ident":"facepunch.sbdm","Path":"Weapons/GaussGun/GaussWeapon.cs","FileName":"GaussWeapon.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"using Sandbox.Rendering;\r\nusing Sandbox.Utility;\r\n\r\npublic class GaussWeapon : BaseBulletWeapon\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// Having this as its own event separate from weapon events until we have a reason to use it for another weapon\r\n\t/// \u003C/summary\u003E\r\n\tpublic interface IGaussWeaponEvents : ISceneEvent\u003CIGaussWeaponEvents\u003E\r\n\t{\r\n\t\t/// \u003Csummary\u003E\r\n\t\t/// Called when we consume a bit of ammo\r\n\t\t/// \u003C/summary\u003E\r\n\t\tvoid OnConsumedAmmo();\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Shot frequency delay\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public float TimeBetweenShots { get; set; } = 0.1f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How much damage\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public float Damage { get; set; } = 12.0f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How many units deep can geometry be for us to penetrate directly through it.\r\n\t/// \u003C/summary\u003E\r\n\t[Property] public float PenetrationThickness { get; set; } = 32f;\r\n\r\n\t[Property] public GameObject ImpactEffectPrefab { get; set; }\r\n\r\n\t[Property] public GameObject LargeImpactEffect { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// What looping sound should we play while charging the gun\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Charge\u0022 )]\r\n\tpublic SoundEvent ChargeSoundEvent { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// A curve to get a damage value directly from ChargePower \r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Charge\u0022 )]\r\n\tpublic Curve ChargeDamage { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How much force is applied when we shoot a charged shot\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Charge\u0022 )]\r\n\tpublic Curve ChargeForce { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How frequently does the ammo drain whilst charging the gauss gun\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Charge\u0022 )]\r\n\tpublic float ChargeAmmoDrainFrequency { get; set; } = 0.2f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How long do we charge for until the gun overloads\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Overload\u0022 )]\r\n\tpublic float OverloadTime { get; set; } = 5f;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How much damage to inflict on the player if the gun overloads\r\n\t/// \u003C/summary\u003E\r\n\t[Property, Feature( \u0022Overload\u0022 )]\r\n\tpublic float OverloadDamage { get; set; } = 20f;\r\n\r\n\t[Property, Feature( \u0022Overload\u0022 )]\r\n\tpublic SoundEvent OverloadSound { get; set; }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The charge loop sound handle, we handle its lifetime.\r\n\t/// \u003C/summary\u003E\r\n\tSoundHandle chargeHandle;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Normalized charge power between 0 and 1\r\n\t/// \u003C/summary\u003E\r\n\tfloat chargePower = 0;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Is this gun charging up to shoot?\r\n\t/// \u003C/summary\u003E\r\n\tbool isCharging = false;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How long has it been since we started charging?\r\n\t/// \u003C/summary\u003E\r\n\tTimeSince timeSinceChargeStart = 0;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// How long since we drained ammo while charged?\r\n\t/// \u003C/summary\u003E\r\n\tTimeSince timeSinceAmmoTick;\r\n\r\n\tprotected override void OnDisabled()\r\n\t{\r\n\t\tStopCharge();\r\n\t\tbase.OnDisabled();\r\n\t}\r\n\r\n\t[Rpc.Host]\r\n\tprivate void HurtSelf()\r\n\t{\r\n\t\tif ( !Owner.IsValid() ) return;\r\n\r\n\t\tOwner.OnDamage( new DamageInfo( OverloadDamage, Owner.GameObject, GameObject ) );\r\n\t\tSound.Play( OverloadSound, WorldPosition );\r\n\t}\r\n\r\n\tpublic override void OnControl( Player player )\r\n\t{\r\n\t\tbase.OnControl( player );\r\n\r\n\t\tif ( isCharging )\r\n\t\t{\r\n\t\t\tif ( chargeHandle is not null )\r\n\t\t\t\tchargeHandle.Position = WorldPosition;\r\n\r\n\t\t\tif ( timeSinceChargeStart \u003E OverloadTime )\r\n\t\t\t{\r\n\t\t\t\tStopCharge();\r\n\t\t\t\tHurtSelf();\r\n\r\n\t\t\t\tif ( !player.Controller.ThirdPerson \u0026\u0026 player.IsLocalPlayer )\r\n\t\t\t\t{\r\n\t\t\t\t\tvar target = new Vector3( Random.Shared.Float( -10, -15 ), Random.Shared.Float( -25, 0 ), 0 );\r\n\r\n\t\t\t\t\tnew Sandbox.CameraNoise.Punch( target, 1.0f, 3, 0.5f );\r\n\t\t\t\t\tnew Sandbox.CameraNoise.Shake( 0.3f, 1.2f );\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif ( chargePower \u003C 1f \u0026\u0026 timeSinceAmmoTick \u003E ChargeAmmoDrainFrequency )\r\n\t\t\t{\r\n\t\t\t\ttimeSinceAmmoTick = 0;\r\n\r\n\t\t\t\tif ( !TakeAmmo( 1 ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tShootCharged( player );\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tIGaussWeaponEvents.PostToGameObject( GameObject.Root, x =\u003E x.OnConsumedAmmo() );\r\n\t\t\t}\r\n\r\n\t\t\tchargePower \u002B= 0.5f * Time.Delta;\r\n\t\t\tchargePower = chargePower.Clamp( 0, 1 );\r\n\t\t\tchargeHandle.Pitch = chargePower.Remap( 0, 1, 0.5f, 1.2f );\r\n\r\n\t\t\tif ( !player.Controller.ThirdPerson \u0026\u0026 player.IsLocalPlayer )\r\n\t\t\t{\r\n\t\t\t\tnew Sandbox.CameraNoise.Shake( 0.3f * chargePower.Remap( 0, 1, 0.5f, 3f ), Time.Delta );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !isCharging \u0026\u0026 Input.Down( \u0022attack1\u0022 ) )\r\n\t\t{\r\n\t\t\tShoot( player );\r\n\t\t}\r\n\r\n\t\tif ( Input.Pressed( \u0022Attack2\u0022 ) )\r\n\t\t{\r\n\t\t\tif ( !TakeAmmo( 1 ) )\r\n\t\t\t{\r\n\t\t\t\tTryAutoReload();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse if ( CanShoot() )\r\n\t\t\t{\r\n\t\t\t\ttimeSinceChargeStart = 0;\r\n\t\t\t\tisCharging = true;\r\n\t\t\t\tchargeHandle?.Stop();\r\n\t\t\t\tchargeHandle = Sound.Play( ChargeSoundEvent );\r\n\r\n\t\t\t\tStartAttack();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( Input.Released( \u0022Attack2\u0022 ) \u0026\u0026 isCharging )\r\n\t\t{\r\n\t\t\tStopAttack();\r\n\t\t\tShootCharged( player );\r\n\t\t}\r\n\t}\r\n\r\n\tpublic override bool IsInUse() =\u003E isCharging;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Shoot a charged shot\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Cparam name=\u0022player\u0022\u003E\u003C/param\u003E\r\n\tvoid ShootCharged( Player player )\r\n\t{\r\n\t\tShootBullet( player, ChargeDamage.Evaluate( chargePower ), true, true );\r\n\r\n\t\t// Fling the player \r\n\t\tvar controller = player.GetComponent\u003CPlayerController\u003E();\r\n\r\n\t\t// Should expose all these to properties\r\n\t\tcontroller.Jump( -player.EyeTransform.ForwardRay.Forward * ChargeForce.Evaluate( chargePower ) );\r\n\r\n\t\tStopCharge();\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Stop charging the gun\r\n\t/// \u003C/summary\u003E\r\n\tvoid StopCharge()\r\n\t{\r\n\t\tisCharging = false;\r\n\t\tchargeHandle?.Stop();\r\n\t\tchargePower = 0;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Constructs a trace and returns it, doesn\u0027t run it yet!\r\n\t/// \u003C/summary\u003E\r\n\tSceneTrace GetBulletTrace( Player player, Vector3 start, Vector3 end, float radius )\r\n\t{\r\n\t\treturn Scene.Trace.Ray( start, end )\r\n\t\t\t.IgnoreGameObjectHierarchy( player.GameObject )\r\n\t\t\t.WithCollisionRules( \u0022bullet\u0022 )\r\n\t\t\t.UseHitboxes()\r\n\t\t\t.Size( radius );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Runs a trace with all the data we have supplied it, and returns the result\r\n\t/// \u003C/summary\u003E\r\n\tIEnumerable\u003CSceneTraceResult\u003E GetShootTraceResults( Player player )\r\n\t{\r\n\t\tvar hits = new List\u003CSceneTraceResult\u003E();\r\n\r\n\t\tvar start = player.EyeTransform.Position;\r\n\t\tvar rot = Rotation.LookAt( player.EyeTransform.Forward );\r\n\r\n\t\tvar forward = rot.Forward.WithAimCone( 2 );\r\n\r\n\t\tvar original = GetBulletTrace( player, start, player.EyeTransform.Position \u002B forward * 4096f, 2f )\r\n\t\t\t\t\t\t.RunAll();\r\n\r\n\r\n\t\tif ( original.Count() \u003C 1 )\r\n\t\t{\r\n\t\t\thits.Add( GetBulletTrace( player, start, player.EyeTransform.Position \u002B forward * 4096f, 2f ).Run() );\r\n\t\t\treturn hits;\r\n\t\t}\r\n\r\n\t\t// Run through and fix the start positions for the traces\r\n\t\t// By using the last end position as the start\r\n\t\tvar startPos = original.ElementAt( 0 ).StartPosition;\r\n\t\tList\u003CSceneTraceResult\u003E fixedPath = new();\r\n\t\tfor ( int i = 0; i \u003C original.Count(); i\u002B\u002B )\r\n\t\t{\r\n\t\t\tvar el = original.ElementAt( i );\r\n\r\n\t\t\tfixedPath.Add( el with { StartPosition = startPos } );\r\n\t\t\tstartPos = el.EndPosition;\r\n\t\t}\r\n\r\n\t\tvar entries = new List\u003C(SceneTraceResult Trace, float Thickness)\u003E();\r\n\r\n\t\t// Then, trace backwards from the end so we can get exit points and thickness\r\n\t\tfor ( int i = fixedPath.Count - 1; i \u003E= 0; i-- )\r\n\t\t{\r\n\t\t\tvar el = fixedPath.ElementAt( i );\r\n\r\n\t\t\t// Do a trace back, from the end position to the start, this\u0027ll give us the LAST entry\u0027s exit point.\r\n\t\t\tvar backTrace = GetBulletTrace( player, el.EndPosition, el.StartPosition, 2f )\r\n\t\t\t\t\t\t\t.Run();\r\n\r\n\t\t\tvar impact = backTrace.EndPosition;\r\n\r\n\t\t\t// From that, we can calculate the surface thickness\r\n\t\t\tfloat thickness = (el.StartPosition - impact).Length;\r\n\r\n\t\t\t// Return the element starting at the exit point, it\u0027s more useful that way.\r\n\t\t\tel = el with { StartPosition = impact };\r\n\t\t\tentries.Insert( 0, (el, thickness) );\r\n\t\t}\r\n\r\n\t\t// Thickness detection\r\n\t\t{\r\n\t\t\tvar thickness = 0f;\r\n\t\t\tforeach ( var el in entries )\r\n\t\t\t{\r\n\t\t\t\tthickness \u002B= el.Thickness;\r\n\t\t\t\tif ( thickness \u003E= PenetrationThickness )\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\thits.Add( el.Trace );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn hits\r\n\t\t\t.Where( x =\u003E x.Hit \u0026\u0026 x.Distance \u003E 0f );\r\n\t}\r\n\r\n\tvoid Shoot( Player player )\r\n\t{\r\n\t\tif ( !CanShoot() || !TakeAmmo( 1 ) )\r\n\t\t{\r\n\t\t\tTryAutoReload();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tShootBullet( player, Damage );\r\n\t}\r\n\r\n\tpublic void ShootBullet( Player player, float damage, bool isCharged = false, bool shouldRicochet = true )\r\n\t{\r\n\t\tAddShootDelay( TimeBetweenShots );\r\n\r\n\t\tbool shouldPenetrate = isCharged;\r\n\r\n\t\tIGaussWeaponEvents.PostToGameObject( GameObject.Root, x =\u003E x.OnConsumedAmmo() );\r\n\r\n\t\tint count = 0;\r\n\t\tvar traces = GetShootTraceResults( player );\r\n\r\n\t\tforeach ( var tr in traces )\r\n\t\t{\r\n\t\t\tShootEffects( tr.EndPosition, false, tr.Normal, tr.GameObject, tr.Surface, count \u003E 0 ? tr.StartPosition : null );\r\n\t\t\tTraceAttack( TraceAttackInfo.From( tr, damage, damage \u003E 70 ? [DamageTags.GibAlways] : null ) );\r\n\t\t\tcount\u002B\u002B;\r\n\r\n\t\t\tif ( player.IsLocalPlayer )\r\n\t\t\t{\r\n\t\t\t\tHitMarker.CreateFromTrace( tr );\r\n\t\t\t}\r\n\r\n\t\t\tif ( tr.Hit )\r\n\t\t\t{\r\n\t\t\t\tSpecialImpactEffects( tr.EndPosition, tr.Normal, tr.GameObject, tr.Surface );\r\n\t\t\t}\r\n\r\n\t\t\tif ( !shouldPenetrate ) break;\r\n\t\t}\r\n\r\n\t\tTimeSinceShoot = 0;\r\n\r\n\t\tif ( shouldRicochet \u0026\u0026 traces.Any() )\r\n\t\t{\r\n\t\t\t// Grab the last sufficient trace, we only want to ricochet at the end\r\n\t\t\tvar tr = traces.Last();\r\n\r\n\t\t\tvar reflectDir = Vector3.Reflect( tr.Direction, tr.Normal ).Normal;\r\n\t\t\tvar angle = reflectDir.Angle( tr.Direction );\r\n\r\n\t\t\t// Some acute angle\r\n\t\t\tif ( angle \u003C 45f )\r\n\t\t\t{\r\n\t\t\t\ttr = GetBulletTrace( player, tr.EndPosition, tr.EndPosition \u002B (reflectDir * 4096), 2f ).Run();\r\n\r\n\t\t\t\tShootEffects( tr.EndPosition, false, tr.Normal, tr.GameObject, tr.Surface, count \u003E 0 ? tr.StartPosition : null );\r\n\t\t\t\tTraceAttack( TraceAttackInfo.From( tr, damage ) );\r\n\r\n\t\t\t\tif ( player.IsLocalPlayer )\r\n\t\t\t\t{\r\n\t\t\t\t\tHitMarker.CreateFromTrace( tr );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( tr.Hit )\r\n\t\t\t\t{\r\n\t\t\t\t\tSpecialImpactEffects( tr.EndPosition, tr.Normal, tr.GameObject, tr.Surface );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tplayer.Controller.EyeAngles \u002B= new Angles( Random.Shared.Float( -0.2f, -0.3f ), Random.Shared.Float( -0.1f, 0.1f ), 0 );\r\n\r\n\t\tif ( !player.Controller.ThirdPerson \u0026\u0026 player.IsLocalPlayer )\r\n\t\t{\r\n\t\t\tvar target = new Vector3( Random.Shared.Float( -10, -15 ), Random.Shared.Float( -10, 0 ), 0 );\r\n\t\t\ttarget *= chargePower.Remap( 0, 1, 1, 10 );\r\n\r\n\t\t\tnew Sandbox.CameraNoise.Punch( target, 1.0f, 3, 0.5f );\r\n\t\t\tnew Sandbox.CameraNoise.Shake( 0.3f, 1.2f );\r\n\t\t}\r\n\t}\r\n\r\n\tpublic override void DrawCrosshair( HudPainter hud, Vector2 center )\r\n\t{\r\n\t\tvar tss = TimeSinceShoot.Relative.Remap( 0, 0.2f, 1, 0 );\r\n\r\n\t\tvar gap = 6 \u002B Easing.EaseOut( tss ) * 32;\r\n\t\tvar len = 6;\r\n\t\tvar w = 2;\r\n\r\n\t\tColor color = !CanShoot() ? UI.CrosshairInactive : UI.CrosshairActive;\r\n\r\n\t\thud.DrawLine( center \u002B Vector2.Left * (len \u002B gap) * 2, center \u002B Vector2.Left * gap * 2, w, color );\r\n\t\thud.DrawLine( center - Vector2.Left * (len \u002B gap) * 2, center - Vector2.Left * gap * 2, w, color );\r\n\t\thud.DrawLine( center \u002B Vector2.Up * (len \u002B gap), center \u002B Vector2.Up * gap, w, color );\r\n\t\thud.DrawLine( center - Vector2.Up * (len \u002B gap), center - Vector2.Up * gap, w, color );\r\n\t}\r\n\r\n\t[Rpc.Broadcast]\r\n\tpublic void SpecialImpactEffects( Vector3 hitpoint, Vector3 normal, GameObject hitObject, Surface hitSurface )\r\n\t{\r\n\t\tif ( Application.IsDedicatedServer ) return;\r\n\r\n\t\tif ( ImpactEffectPrefab is null )\r\n\t\t\treturn;\r\n\r\n\t\tvar impact = ImpactEffectPrefab.Clone();\r\n\t\timpact.WorldPosition = hitpoint \u002B normal;\r\n\t\timpact.WorldRotation = Rotation.LookAt( normal ) * new Angles( 90, 0, 0 );\r\n\t\timpact.SetParent( hitObject, true );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"Weapons/WeaponModel/WeaponModel.cs","FileName":"WeaponModel.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"/// \u003Csummary\u003E\n/// Base for our view and world model components. \u003Csee cref=\u0022BaseWeaponModel\u0022/\u003E supplies the muzzle\n/// and shell-eject attachments, the effect prefabs and the deploy/attack/reload presentation hooks -\n/// this exists so the deathmatch view and world models share a type of their own.\n/// \u003C/summary\u003E\npublic abstract class WeaponModel : BaseWeaponModel\n{\n}\n"},{"Ident":"facepunch.sbdm","Path":"Weapons/WeaponModel/WorldModel.cs","FileName":"WorldModel.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"using static BaseWeapon;\r\n\r\npublic sealed class WorldModel : WeaponModel, IWeaponEvent\r\n{\r\n\tvoid IWeaponEvent.OnAttack( IWeaponEvent.AttackEvent e )\r\n\t{\r\n\t\tRenderer?.Set( \u0022b_attack\u0022, true );\r\n\r\n\t\tif ( e.isFirstPerson )\r\n\t\t\treturn;\r\n\r\n\t\tDoMuzzleEffect();\r\n\t\tDoEjectBrass();\r\n\t}\r\n\r\n\tvoid IWeaponEvent.CreateRangedEffects( BaseWeapon weapon, Vector3 hitPoint, Vector3? origin )\r\n\t{\r\n\t\tif ( weapon.ViewModel.IsValid() )\r\n\t\t\treturn;\r\n\r\n\t\tDoTracerEffect( hitPoint, origin );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.sbdm","Path":"styles/base.scss","FileName":"base.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":"@import \u0022base/_splitcontainer.scss\u0022;\r\n@import \u0022base/_navigator.scss\u0022;\r\n\r\nbutton\r\n{\r\n\tcursor: pointer;\r\n}\r\n\r\nIconPanel\r\n{\r\n\tfont-family: Material Icons;\r\n}\r\n\r\n.is-half\r\n{\r\n\twidth: 50%;\r\n}\r\n\r\n.is-third\r\n{\r\n\twidth: 33%;\r\n}\r\n\r\n.is-quarter\r\n{\r\n\twidth: 25%;\r\n}\r\n\r\nbutton.has-subtitle\r\n{\r\n\tposition: relative;\r\n\tflex-direction: column;\r\n\tjustify-content: flex-start;\r\n\talign-items: flex-start;\r\n\tpadding-left: 40px; // icon space\r\n\r\n\t.iconpanel\r\n\t{\r\n\t\tposition: absolute;\r\n\t\tleft: 5px;\r\n\t\ttop: 0;\r\n\t\tbottom: 0;\r\n\t\talign-items: center;\r\n\t}\r\n\r\n\t.button-label\r\n\t{\r\n\t\tfont-weight: bold;\r\n\t}\r\n\r\n\t.button-subtitle\r\n\t{\r\n\t\tfont-size: 12px;\r\n\t\topacity: 0.5;\r\n\t\tmix-blend-mode: lighten;\r\n\t}\r\n}"},{"Ident":"facepunch.sbdm","Path":"ui/dropdown.cs.scss","FileName":"dropdown.cs.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":336963,"Code":".dropdown\r\n{\r\n\tgap: 2px;\r\n\tflex-grow: 1;\r\n\tcursor: pointer;\r\n\tjustify-content: flex-end;\r\n\talign-items: center;\r\n\tpadding: 0px 12px;\r\n\r\n\t.button-right-column\r\n\t{\r\n\t\tflex-grow: 1;\r\n\t}\r\n}\r\n"}]}