{"TotalCount":212,"Files":[{"Ident":"facepunch.memory","Path":"FloaterLock.cs","FileName":"FloaterLock.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Drawing;\r\n\r\npublic class FloaterLock : Component\r\n{\r\n\tpublic int NumTurns { get; set; }\r\n\r\n\tprivate TimeSince _timeSinceSpawn;\r\n\r\n\tpublic float Lifetime { get; set; }\r\n\tpublic bool ShowLocked { get; set ; }\r\n\r\n\tprivate float _startScale;\r\n\tprivate float _endScale;\r\n\tprivate Vector2 _velocity;\r\n\tprivate float _deceleration;\r\n\r\n\tpublic float Scale { get; set; }\r\n\tpublic float Opacity { get; set; }\r\n\r\n\tpublic void Init( int numTurns )\r\n\t{\r\n\t\tNumTurns = numTurns;\r\n\r\n\t\tLifetime = 1.25f;\r\n\t\t_velocity = new Vector2( 0f, 12f );\r\n\t\t_deceleration = 4f;\r\n\t\tScale = _startScale = 1f;\r\n\t\t_endScale = 1f;\r\n\t}\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tbase.OnStart();\r\n\r\n\t\t_timeSinceSpawn = 0f;\r\n\r\n\t\tManager.Instance.PlaySfx( \u0022lock_start\u0022, new Vector3( WorldPosition.x, WorldPosition.y, Manager.Instance.Camera.WorldPosition.z - 100f ), volume: 0.9f, pitch: Game.Random.Float( 1.05f, 1.13f ) );\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tOpacity = Utils.Map( _timeSinceSpawn, 0f, 0.3f, 0f, 1f, EasingType.QuadOut ) * Utils.Map( _timeSinceSpawn, 0f, Lifetime - 0.1f, 1f, 0.1f, EasingType.ExpoIn ) * Utils.Map( _timeSinceSpawn, Lifetime - 0.3f, Lifetime - 0.05f, 1f, 0f, EasingType.Linear );\r\n\t\tScale = Utils.Map( _timeSinceSpawn, 0f, Lifetime, _startScale, _endScale, EasingType.SineOut );\r\n\r\n\t\tWorldPosition \u002B= new Vector3( _velocity.x, _velocity.y, 0f ) * Time.Delta;\r\n\t\t_velocity *= (1f - _deceleration * Time.Delta);\r\n\r\n\t\tif( !ShowLocked \u0026\u0026 _timeSinceSpawn \u003E 0.5f )\r\n\t\t{\r\n\t\t\tShowLocked = true;\r\n\t\t\t_velocity = new Vector2( 0f, -20f );\r\n\t\t\t_deceleration = 7f;\r\n\r\n\t\t\tManager.Instance.PlaySfx( \u0022lock\u0022, new Vector3( WorldPosition.x, WorldPosition.y, Manager.Instance.Camera.WorldPosition.z - 100f ), volume: 2f, pitch: Game.Random.Float( 0.97f, 1.03f ) );\r\n\t\t}\r\n\r\n\t\tif ( _timeSinceSpawn \u003E Lifetime )\r\n\t\t{\r\n\t\t\tManager.Instance.NumFloaters--;\r\n\t\t\tGameObject.Destroy();\r\n\t\t}\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/Card.cs","FileName":"Card.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Microsoft.VisualBasic;\r\nusing Sandbox;\r\nusing Sandbox.UI;\r\nusing Sandbox.ui;\r\nusing System.Runtime;\r\nusing System.Threading.Tasks;\r\n\r\npublic enum CardType { None, Apple, Bomb, Rocket, Telephone, Trumpet, Pawn, Balloon, Spider, Umbrella, UmbrellaClosed, Juggler, Coin, Vampire, Maracas, Microwave, Raccoon, Rock, Bear, Candle, \r\n\tCrystalBall, Snake, Rose, RoseWilted, Bell, Ant, Twins, Compass, Antenna, Wizard, AncientScroll, JumpingSpider, Bento, Ninja, Flashlight, Bodybuilder, Helicopter, FlyingMoney,\r\n\tSyringe, Cellphone, Crab, Magnet, Stethoscope, UFO, Teacher, Tractor, FortuneCookie, Dolphin, Detective, Genie, Potion, Mirror, FaxMachine, Dice, Coffee, Tree, Chipmunk,\r\n\tDancer, Wine, King, Police, Ogre, Clown, MoneyBag, Bank, Steak, MagicWand, Carrot, Caterpillar, Butterfly, Tornado, Map, Cockroach, Broccoli, Donut, Cheese, CheeseMoldy, GuideDog, Taco, Burrito,\r\n\tSkunk, CarePackage, Cash, BirthdayCake, Gem, Pickaxe, Mountain, DiamondRing, Rabbit, RedEnvelope,\r\n}\r\n\r\n// StockMarket, StockMarketDown, Key, AlarmClock, ATM\r\n\r\npublic class Card : Component, IEventHandler\r\n{\r\n\tpublic GameObject Model { get; set; }\r\n\tpublic ModelRenderer ModelRenderer { get; set; }\r\n\tpublic GameObject IconObj { get; set; }\r\n\tpublic GameObject IconBackObj { get; set; }\r\n\tpublic bool IsFlagShown { get; set; }\r\n\r\n\tpublic float CardIconScale { get; set; } = 1f;\r\n\r\n\tpublic bool IsHovered { get; set; }\r\n\tpublic bool IsRevealed { get; set; }\r\n\tpublic bool IsSpawning { get; set; }\r\n\r\n\tpublic int NumTimesRevealed { get; set; }\r\n\tpublic int NumTimesChosen { get; set; }\r\n\r\n\tpublic CardType CardType { get; private set; }\r\n\tpublic CardType OriginalCardType { get; private set; }\r\n\r\n\tpublic virtual bool IsFoodOrBeverage =\u003E false;\r\n\tpublic virtual bool IsAlive =\u003E false;\r\n\tpublic virtual bool CantBeMoved =\u003E false;\r\n\r\n\tpublic IntVector2 GridPos { get; set; }\r\n\r\n\tpublic bool IsShaking { get; private set; }\r\n\tprivate TimeSince _timeSinceShakeStart; // todo: replace with timer? this can become negative somehow\r\n\tprivate float _shakeTime;\r\n\tprivate EasingType _shakeEasingType;\r\n\tpublic Vector2 ShakeOffset { get; set; }\r\n\tprivate float _shakeStrength;\r\n\r\n\tpublic bool IsMovementControlled { get; set; }\r\n\tprivate Vector3 _moveStartPos;\r\n\tprivate Vector3 _moveTargetPos;\r\n\tprivate float _moveTime;\r\n\tprivate TimeSince _timeSinceMoveStart;\r\n\tprivate EasingType _moveEasingType;\r\n\tprivate bool _moveRemoveControlAfter;\r\n\r\n\tpublic int HP { get; set; }\r\n\r\n\tpublic bool IsLocked { get; set; }\r\n\tpublic int LockTurnsRemaining { get; set; }\r\n\tpublic bool WasJustLocked { get; set; }\r\n\r\n\tpublic int CardTypeID { get; set; }\r\n\r\n\tpublic float IconOpacity { get; set; }\r\n\tpublic bool IsExploding;\r\n\tprivate TimeSince _timeSinceStartExploding;\r\n\tprivate float _explodeTime;\r\n\tprivate EasingType _explodeEasingType;\r\n\tprivate Vector3 _explodeStartPos;\r\n\tprivate EasingType _explodeShakeEasingType;\r\n\r\n\tpublic bool IsScaling;\r\n\tprivate TimeSince _timeSinceScale;\r\n\tprivate float _scaleTime;\r\n\tprivate float _scaleAmount;\r\n\tprivate EasingType _scaleEasingType;\r\n\r\n\tpublic bool AreRevealMarksShown { get; set; }\r\n\r\n\tprotected override void OnAwake()\r\n\t{\r\n\t\tbase.OnAwake();\r\n\r\n\t}\r\n\r\n\tpublic virtual void Init(CardType cardType)\r\n\t{\r\n\t\tCardType = OriginalCardType = cardType;\r\n\r\n\t\tModel = GameObject.Children.Find( x =\u003E x.Name == \u0022model\u0022 );\r\n\t\tModelRenderer = Model.Components.Get\u003CModelRenderer\u003E();\r\n\r\n\t\tIconOpacity = 1f;\r\n\r\n\t\tIconObj = GameObject.Children.Find( x =\u003E x.Name == \u0022icon\u0022 );\r\n\t\tvar cardIcon = IconObj.Components.Get\u003CCardIcon\u003E( includeDisabled: true );\r\n\t\tcardIcon.Card = this;\r\n\r\n\t\tIconBackObj = GameObject.Children.Find( x =\u003E x.Name == \u0022icon_back\u0022 );\r\n\t\tvar cardIconBack = IconBackObj.Components.Get\u003CCardIconBack\u003E( includeDisabled: true );\r\n\t\tcardIconBack.Card = this;\r\n\r\n\t\tSetMaterial( cardType );\r\n\t}\r\n\r\n\tpublic void SetMaterial(CardType cardType)\r\n\t{\r\n\t\tvar matFilename = GetMaterialFilename( cardType );\r\n\t\tif ( !string.IsNullOrEmpty( matFilename ) )\r\n\t\t\tModelRenderer.MaterialOverride = Material.Load( matFilename );\r\n\t}\r\n\r\n\tpublic void SetCardType(CardType newType)\r\n\t{\r\n\t\tCardType = newType;\r\n\t\tSetMaterial( newType );\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\t//if ( Input.Down( \u0022Duck\u0022 ) )\r\n\t\t//{\r\n\t\t//\tvar emoji = Card.GetIconEmoji( CardType );\r\n\t\t//\tif ( string.IsNullOrEmpty( emoji ) )\r\n\t\t//\t{\r\n\t\t//\t\tGizmo.Draw.Color = Color.Black.WithAlpha( 1f );\r\n\t\t//\t\tGizmo.Draw.Text( $\u0022{CardType}\u0022, new global::Transform( WorldPosition \u002B new Vector3( -0.5f, -0.5f, -1f ) ), size: 24f );\r\n\r\n\t\t//\t\tGizmo.Draw.Color = Color.White.WithAlpha( 1f );\r\n\t\t//\t\tGizmo.Draw.Text( $\u0022{CardType}\u0022, new global::Transform( WorldPosition ), size: 24f );\r\n\t\t//\t}\r\n\t\t//\telse\r\n\t\t//\t{\r\n\t\t//\t\tGizmo.Draw.Color = Color.White.WithAlpha( 1f );\r\n\t\t//\t\tGizmo.Draw.Text( emoji, new global::Transform( WorldPosition ), size: 60f );\r\n\t\t//\t}\r\n\r\n\t\t//\tif ( IsMovementControlled )\r\n\t\t//\t{\r\n\t\t//\t\tGizmo.Draw.Color = Color.White.WithAlpha( 1f );\r\n\t\t//\t\tGizmo.Draw.Text( \u0022\u27A1\uFE0F\u0022, new global::Transform( WorldPosition \u002B new Vector3( -15.5f, -19f, -1f ) ), size: 30f );\r\n\t\t//\t}\r\n\r\n\t\t//\tif ( IsLocked )\r\n\t\t//\t{\r\n\t\t//\t\tGizmo.Draw.Color = Color.White.WithAlpha( 1f );\r\n\t\t//\t\tGizmo.Draw.Text( \u0022\uD83D\uDD12\u0022, new global::Transform( WorldPosition \u002B new Vector3( 15.5f, -19f, -1f ) ), size: 30f );\r\n\r\n\t\t//\t\tGizmo.Draw.Color = Color.Red.WithAlpha( 1f );\r\n\t\t//\t\tGizmo.Draw.Text( $\u0022{LockTurnsRemaining}\u0022, new global::Transform( WorldPosition \u002B new Vector3( 15.5f, -21f, 1f ) ), size: 20f );\r\n\t\t//\t}\r\n\r\n\t\t//\tGizmo.Draw.Color = Color.Black.WithAlpha( 1f );\r\n\t\t//\tGizmo.Draw.Text( $\u0022ID: {CardTypeID}\u0022, new global::Transform( WorldPosition \u002B new Vector3( -13.5f, 19f, -1f ) \u002B new Vector3( -0.5f, -0.5f, -1f ) ), size: 16 );\r\n\r\n\t\t//\tGizmo.Draw.Color = Color.White.WithAlpha( 1f );\r\n\t\t//\tGizmo.Draw.Text( $\u0022ID: {CardTypeID}\u0022, new global::Transform( WorldPosition \u002B new Vector3( -13.5f, 19f, -1f ) ), size: 16 );\r\n\t\t//}\r\n\r\n\t\tHandleMoving();\r\n\t\tHandleShaking();\r\n\r\n\t\tif(IsExploding)\r\n\t\t{\r\n\t\t\tHandleExploding();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ( IsScaling )\r\n\t\t{\r\n\t\t\tHandleScaling();\r\n\t\t}\r\n\t\t\r\n\t\t//if(!IsScaling \u0026\u0026 !IsExploding)\r\n\t\t//{\r\n\t\t//\tTransform.LocalScale = new Vector3( Utils.DynamicEaseTo( Transform.LocalScale.x, IsHovered ? 1.05f : 1f, 0.3f, Time.Delta ) );\r\n\t\t//}\r\n\r\n\t\tif( IsSpawning )\r\n\t\t{\r\n\t\t\t// do nothing\r\n\t\t}\r\n\t\telse if( IsMovementControlled )\r\n\t\t{\r\n\t\t\tLocalPosition \u002B= new Vector3( ShakeOffset.x, ShakeOffset.y, 0f ) * Time.Delta * 10f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvar targetPos = Manager.GetCardPos( GridPos );\r\n\r\n\t\t\tif ( IsShaking )\r\n\t\t\t\ttargetPos \u002B= new Vector3( ShakeOffset.x, ShakeOffset.y, 0f );\r\n\r\n\t\t\tvar height = 10f \u002B ((IsRevealed || IsHovered) ? Globals.CARD_ADD_HEIGHT_REVEALED_OR_HOVERED : 0f) \u002B ((IsRevealed \u0026\u0026 IsHovered) ? Globals.CARD_ADD_HEIGHT_REVEALED_AND_HOVERED : 0f);\r\n\t\t\tvar zPos = MathX.Lerp( LocalPosition.z, height, Time.Delta * 20f );\r\n\r\n\t\t\tLocalPosition = Vector3.Lerp( LocalPosition, targetPos, Time.Delta * 10f ).WithZ( zPos );\r\n\t\t}\r\n\r\n\t\tvar targetRot = Rotation.FromPitch( IsRevealed ? 0f : 180f );\r\n\t\tWorldRotation = Rotation.Lerp( WorldRotation, targetRot, Time.Delta * 15f );\r\n\t}\r\n\r\n\tpublic void MoveToPos( Vector3 pos, float time, EasingType easingType = EasingType.Linear, bool removeControlAfter = false)\r\n\t{\r\n\t\t//Log.Info( $\u0022Card - MoveToPos: {pos}\u0022 );\r\n\r\n\t\tIsMovementControlled = true;\r\n\t\t_moveStartPos = LocalPosition;\r\n\t\t_moveTargetPos = pos;\r\n\t\t_moveTime = time;\r\n\t\t_timeSinceMoveStart = 0f;\r\n\t\t_moveEasingType = easingType;\r\n\t\t_moveRemoveControlAfter = removeControlAfter;\r\n\t}\r\n\r\n\tvoid HandleMoving()\r\n\t{\r\n\t\tif ( !IsMovementControlled )\r\n\t\t\treturn;\r\n\r\n\t\tif(_timeSinceMoveStart \u003E _moveTime)\r\n\t\t{\r\n\t\t\tLocalPosition = _moveTargetPos;\r\n\r\n\t\t\tif( _moveRemoveControlAfter )\r\n\t\t\t\tIsMovementControlled = false;\r\n\t\t}\r\n\t\telse \r\n\t\t{\r\n\t\t\tLocalPosition = Vector3.Lerp( _moveStartPos, _moveTargetPos, Utils.Map( _timeSinceMoveStart, 0f, _moveTime, 0f, 1f, _moveEasingType ) );\r\n\t\t}\r\n\t}\r\n\r\n\tprotected void HandleShaking()\r\n\t{\r\n\t\tif ( IsShaking )\r\n\t\t{\r\n\t\t\tif ( _timeSinceShakeStart \u003E _shakeTime )\r\n\t\t\t\tIsShaking = false;\r\n\t\t\telse\r\n\t\t\t\tShakeOffset = Utils.GetRandomVector() * _shakeStrength * Utils.Map( _timeSinceShakeStart, 0f, _shakeTime, 1f, 0f, _shakeEasingType );\r\n\t\t}\r\n\t}\r\n\r\n\tvoid HandleExploding()\r\n\t{\r\n\t\tLocalScale = new Vector3( Utils.Map(_timeSinceStartExploding, 0f, _explodeTime, 1f, Globals.CARD_EXPLODE_SCALE, _explodeEasingType) );\r\n\t\tIconOpacity = Utils.Map( _timeSinceStartExploding, 0f, _explodeTime, 1f, 0f, EasingType.SineIn );\r\n\r\n\t\tLocalPosition = _explodeStartPos \u002B Vector3.Random * Utils.Map( _timeSinceStartExploding, 0f, _explodeTime, 0f, 2f, _explodeShakeEasingType) * Utils.Map( _timeSinceStartExploding, _explodeTime * 0.9f, _explodeTime, 1f, 0f );\r\n\t}\r\n\r\n\tvoid HandleScaling()\r\n\t{\r\n\t\tif(_timeSinceScale \u003E 0.25f)\r\n\t\t{\r\n\t\t\tIsScaling = false;\r\n\t\t\tLocalScale = new Vector3( 1f );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tLocalScale = Utils.MapReturn( _timeSinceScale, 0f, _scaleTime, 1f, _scaleAmount, _scaleEasingType);\r\n\t\t}\r\n\t}\r\n\r\n\tpublic static string GetName( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.CrystalBall: return \u0022Crystal Ball\u0022;\r\n\t\t\tcase CardType.AncientScroll: return \u0022Ancient Scroll\u0022;\r\n\t\t\tcase CardType.JumpingSpider: return \u0022Jumping Spider\u0022;\r\n\t\t\tcase CardType.Rock: return \u0022Boulder\u0022;\r\n\t\t\tcase CardType.Syringe: return \u0022Morphine\u0022;\r\n\t\t\tcase CardType.FlyingMoney: return \u0022Flying Money\u0022;\r\n\t\t\tcase CardType.FortuneCookie: return \u0022Fortune Cookie\u0022;\r\n\t\t\t//case CardType.AlarmClock: return \u0022Alarm Clock\u0022;\r\n\t\t\tcase CardType.FaxMachine: return \u0022Fax Machine\u0022;\r\n\t\t\tcase CardType.MoneyBag: return \u0022Money Bag\u0022;\r\n\t\t\tcase CardType.MagicWand: return \u0022Magic Wand\u0022;\r\n\t\t\t//case CardType.StockMarket: return \u0022Stock Market\u0022;\r\n\t\t\tcase CardType.GuideDog: return \u0022Guide Dog\u0022;\r\n\t\t\tcase CardType.CarePackage: return \u0022Care Package\u0022;\r\n\t\t\tcase CardType.BirthdayCake: return \u0022Birthday Cake\u0022;\r\n\t\t\tcase CardType.DiamondRing: return \u0022Diamond Ring\u0022;\r\n\t\t\tcase CardType.RedEnvelope: return \u0022Red Envelope\u0022;\r\n\t\t}\r\n\r\n\t\treturn cardType.ToString();\r\n\t}\r\n\r\n\tpublic static string GetFilename( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.Apple: return \u0022apple\u0022;\r\n\t\t\tcase CardType.Bomb: return \u0022bomb\u0022;\r\n\t\t\tcase CardType.Rocket: return \u0022rocket\u0022;\r\n\t\t\tcase CardType.Telephone: return \u0022telephone\u0022;\r\n\t\t\tcase CardType.Trumpet: return \u0022trumpet\u0022;\r\n\t\t\tcase CardType.Pawn: return \u0022pawn\u0022;\r\n\t\t\tcase CardType.Balloon: return \u0022balloon\u0022;\r\n\t\t\tcase CardType.Spider: return \u0022spider\u0022;\r\n\t\t\tcase CardType.Umbrella: return \u0022umbrella\u0022;\r\n\t\t\tcase CardType.UmbrellaClosed: return \u0022umbrella_closed\u0022;\r\n\t\t\tcase CardType.Juggler: return \u0022juggler\u0022;\r\n\t\t\tcase CardType.Coin: return \u0022coin\u0022;\r\n\t\t\tcase CardType.Vampire: return \u0022vampire\u0022;\r\n\t\t\tcase CardType.Maracas: return \u0022maracas\u0022;\r\n\t\t\tcase CardType.Microwave: return \u0022microwave\u0022;\r\n\t\t\tcase CardType.Raccoon: return \u0022raccoon\u0022;\r\n\t\t\tcase CardType.Rock: return \u0022rock\u0022;\r\n\t\t\tcase CardType.Bear: return \u0022bear\u0022;\r\n\t\t\tcase CardType.Candle: return \u0022candle\u0022;\r\n\t\t\tcase CardType.CrystalBall: return \u0022crystal_ball\u0022;\r\n\t\t\tcase CardType.Snake: return \u0022snake\u0022;\r\n\t\t\tcase CardType.Rose: return \u0022rose\u0022;\r\n\t\t\tcase CardType.RoseWilted: return \u0022rose_wilted\u0022;\r\n\t\t\tcase CardType.Bell: return \u0022bell\u0022;\r\n\t\t\tcase CardType.Ant: return \u0022ant\u0022;\r\n\t\t\tcase CardType.Twins: return \u0022twins\u0022;\r\n\t\t\tcase CardType.Compass: return \u0022compass\u0022;\r\n\t\t\tcase CardType.Antenna: return \u0022antenna\u0022;\r\n\t\t\tcase CardType.Wizard: return \u0022wizard\u0022;\r\n\t\t\tcase CardType.AncientScroll: return \u0022scroll\u0022;\r\n\t\t\tcase CardType.JumpingSpider: return \u0022spider_jumping\u0022;\r\n\t\t\tcase CardType.Bento: return \u0022bento\u0022;\r\n\t\t\t//case CardType.StockMarket: return \u0022investment\u0022;\r\n\t\t\t//case CardType.StockMarketDown: return \u0022investment_down\u0022;\r\n\t\t\tcase CardType.Ninja: return \u0022ninja\u0022;\r\n\t\t\tcase CardType.Flashlight: return \u0022flashlight\u0022;\r\n\t\t\tcase CardType.Bodybuilder: return \u0022bodybuilder\u0022;\r\n\t\t\tcase CardType.Helicopter: return \u0022helicopter\u0022;\r\n\t\t\tcase CardType.FlyingMoney: return \u0022flying_money\u0022;\r\n\t\t\tcase CardType.Syringe: return \u0022syringe\u0022;\r\n\t\t\tcase CardType.Cellphone: return \u0022cellphone\u0022;\r\n\t\t\tcase CardType.Crab: return \u0022crab\u0022;\r\n\t\t\tcase CardType.Magnet: return \u0022magnet\u0022;\r\n\t\t\tcase CardType.Stethoscope: return \u0022stethoscope\u0022;\r\n\t\t\tcase CardType.UFO: return \u0022ufo\u0022;\r\n\t\t\tcase CardType.Teacher: return \u0022teacher\u0022;\r\n\t\t\tcase CardType.Tractor: return \u0022tractor\u0022;\r\n\t\t\tcase CardType.FortuneCookie: return \u0022fortune_cookie\u0022;\r\n\t\t\tcase CardType.Dolphin: return \u0022dolphin\u0022;\r\n\t\t\tcase CardType.Detective: return \u0022detective\u0022;\r\n\t\t\tcase CardType.Genie: return \u0022genie\u0022;\r\n\t\t\tcase CardType.Potion: return \u0022potion\u0022;\r\n\t\t\tcase CardType.Mirror: return \u0022mirror\u0022;\r\n\t\t\t//case CardType.AlarmClock: return \u0022alarm_clock\u0022;\r\n\t\t\tcase CardType.FaxMachine: return \u0022fax_machine\u0022;\r\n\t\t\tcase CardType.Dice: return \u0022dice\u0022;\r\n\t\t\tcase CardType.Coffee: return \u0022coffee\u0022;\r\n\t\t\tcase CardType.Tree: return \u0022tree\u0022;\r\n\t\t\tcase CardType.Chipmunk: return \u0022chipmunk\u0022;\r\n\t\t\tcase CardType.Dancer: return \u0022dancer\u0022;\r\n\t\t\tcase CardType.Wine: return \u0022wine\u0022;\r\n\t\t\tcase CardType.King: return \u0022king\u0022;\r\n\t\t\tcase CardType.Police: return \u0022police\u0022;\r\n\t\t\tcase CardType.Ogre: return \u0022ogre\u0022;\r\n\t\t\tcase CardType.Clown: return \u0022clown\u0022;\r\n\t\t\tcase CardType.MoneyBag: return \u0022money_bag\u0022;\r\n\t\t\tcase CardType.Bank: return \u0022bank\u0022;\r\n\t\t\tcase CardType.Steak: return \u0022steak\u0022;\r\n\t\t\tcase CardType.MagicWand: return \u0022magic_wand\u0022;\r\n\t\t\tcase CardType.Carrot: return \u0022carrot\u0022;\r\n\t\t\tcase CardType.Caterpillar: return \u0022caterpillar\u0022;\r\n\t\t\tcase CardType.Butterfly: return \u0022butterfly\u0022;\r\n\t\t\tcase CardType.Tornado: return \u0022tornado\u0022;\r\n\t\t\tcase CardType.Map: return \u0022map\u0022;\r\n\t\t\tcase CardType.Cockroach: return \u0022cockroach\u0022;\r\n\t\t\t//case CardType.Key: return \u0022key\u0022;\r\n\t\t\tcase CardType.Broccoli: return \u0022broccoli\u0022;\r\n\t\t\t//case CardType.ATM: return \u0022atm\u0022;\r\n\t\t\tcase CardType.Donut: return \u0022donut\u0022;\r\n\t\t\tcase CardType.Cheese: return \u0022cheese\u0022;\r\n\t\t\tcase CardType.CheeseMoldy: return \u0022cheese_moldy\u0022;\r\n\t\t\tcase CardType.GuideDog: return \u0022guide_dog\u0022;\r\n\t\t\tcase CardType.Taco: return \u0022taco\u0022;\r\n\t\t\tcase CardType.Burrito: return \u0022burrito\u0022;\r\n\t\t\tcase CardType.Skunk: return \u0022skunk\u0022;\r\n\t\t\tcase CardType.CarePackage: return \u0022care_package\u0022;\r\n\t\t\tcase CardType.Cash: return \u0022cash\u0022;\r\n\t\t\tcase CardType.BirthdayCake: return \u0022birthday_cake\u0022;\r\n\t\t\tcase CardType.Gem: return \u0022gem\u0022;\r\n\t\t\tcase CardType.Pickaxe: return \u0022pickaxe\u0022;\r\n\t\t\tcase CardType.Mountain: return \u0022mountain\u0022;\r\n\t\t\tcase CardType.DiamondRing: return \u0022diamond_ring\u0022;\r\n\t\t\tcase CardType.Rabbit: return \u0022rabbit\u0022;\r\n\t\t\tcase CardType.RedEnvelope: return \u0022red_envelope\u0022;\r\n\t\t}\r\n\r\n\t\treturn \u0022\u0022;\r\n\t}\r\n\r\n\tpublic static string GetIconFilename( CardType cardType )\r\n\t{\r\n\t\treturn $\u0022textures/{GetFilename( cardType )}.png\u0022;\r\n\t}\r\n\r\n\tpublic static string GetMaterialFilename( CardType cardType )\r\n\t{\r\n\t\treturn $\u0022materials/cards/{GetFilename( cardType )}.vmat\u0022;\r\n\t}\r\n\r\n\tpublic static string GetIconEmoji( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.Apple: return \u0022\uD83C\uDF4E\u0022;\r\n\t\t\tcase CardType.Bomb: return \u0022\uD83D\uDCA3\u0022;\r\n\t\t\tcase CardType.Rocket: return \u0022\uD83D\uDE80\u0022;\r\n\t\t\tcase CardType.Telephone: return \u0022\u260E\uFE0F\u0022;\r\n\t\t\tcase CardType.Trumpet: return \u0022\uD83C\uDFBA\u0022;\r\n\t\t\tcase CardType.Pawn: return \u0022\u265F\uFE0F\u0022;\r\n\t\t\tcase CardType.Balloon: return \u0022\uD83C\uDF88\u0022;\r\n\t\t\tcase CardType.Spider: return \u0022\uD83D\uDD77\uFE0F\u0022;\r\n\t\t\tcase CardType.Umbrella: return \u0022\u2602\uFE0F\u0022;\r\n\t\t\tcase CardType.UmbrellaClosed: return \u0022\uD83C\uDF02\u0022;\r\n\t\t\tcase CardType.Juggler: return \u0022\uD83E\uDD39\u0022;\r\n\t\t\tcase CardType.Coin: return \u0022\uD83D\uDFE1\u0022;\r\n\t\t\tcase CardType.Vampire: return \u0022\uD83E\uDDDB\u0022;\r\n\t\t\tcase CardType.Raccoon: return \u0022\uD83E\uDD9D\u0022;\r\n\t\t\tcase CardType.Rock: return \u0022\uD83D\uDDFF\u0022;\r\n\t\t\tcase CardType.Bear: return \u0022\uD83D\uDC3B\u0022;\r\n\t\t\tcase CardType.Candle: return \u0022\uD83D\uDD6F\uFE0F\u0022;\r\n\t\t\tcase CardType.CrystalBall: return \u0022\uD83D\uDD2E\u0022;\r\n\t\t\tcase CardType.Snake: return \u0022\uD83D\uDC0D\u0022;\r\n\t\t\tcase CardType.Rose: return \u0022\uD83C\uDF39\u0022;\r\n\t\t\tcase CardType.RoseWilted: return \u0022\uD83E\uDD40\u0022;\r\n\t\t\tcase CardType.Bell: return \u0022\uD83D\uDD14\u0022;\r\n\t\t\tcase CardType.Ant: return \u0022\uD83D\uDC1C\u0022;\r\n\t\t\tcase CardType.Twins: return \u0022\uD83D\uDC6F\u0022;\r\n\t\t\tcase CardType.Compass: return \u0022\uD83E\uDDED\u0022;\r\n\t\t\tcase CardType.Antenna: return \u0022\uD83D\uDCE1\u0022;\r\n\t\t\tcase CardType.Wizard: return \u0022\uD83E\uDDD9\u0022;\r\n\t\t\tcase CardType.AncientScroll: return \u0022\uD83D\uDCDC\u0022;\r\n\t\t\tcase CardType.JumpingSpider: return \u0022\uD83D\uDD77\uFE0F\u0022;\r\n\t\t\tcase CardType.Bento: return \u0022\uD83C\uDF71\u0022;\r\n\t\t\t//case CardType.StockMarket: return \u0022\uD83D\uDCC8\u0022;\r\n\t\t\t//case CardType.StockMarketDown: return \u0022\uD83D\uDCC9\u0022;\r\n\t\t\tcase CardType.Ninja: return \u0022\uD83D\uDC31\u200D\uD83D\uDC64\u0022;\r\n\t\t\tcase CardType.Flashlight: return \u0022\uD83D\uDD26\u0022;\r\n\t\t\tcase CardType.Bodybuilder: return \u0022\uD83C\uDFCB\uFE0F\u0022;\r\n\t\t\tcase CardType.Helicopter: return \u0022\uD83D\uDE81\u0022;\r\n\t\t\tcase CardType.FlyingMoney: return \u0022\uD83D\uDCB8\u0022;\r\n\t\t\tcase CardType.Syringe: return \u0022\uD83D\uDC89\u0022;\r\n\t\t\tcase CardType.Cellphone: return \u0022\uD83D\uDCF1\u0022;\r\n\t\t\tcase CardType.Crab: return \u0022\uD83E\uDD80\u0022;\r\n\t\t\tcase CardType.Magnet: return \u0022\uD83E\uDDF2\u0022;\r\n\t\t\tcase CardType.Stethoscope: return \u0022\uD83E\uDE7A\u0022;\r\n\t\t\tcase CardType.UFO: return \u0022\uD83D\uDEF8\u0022;\r\n\t\t\tcase CardType.Teacher: return \u0022\uD83D\uDC69\u200D\uD83C\uDFEB\u0022;\r\n\t\t\tcase CardType.Tractor: return \u0022\uD83D\uDE9C\u0022;\r\n\t\t\tcase CardType.FortuneCookie: return \u0022\uD83E\uDD60\u0022;\r\n\t\t\tcase CardType.Dolphin: return \u0022\uD83D\uDC2C\u0022;\r\n\t\t\tcase CardType.Detective: return \u0022\uD83D\uDD75\uFE0F\u0022;\r\n\t\t\tcase CardType.Genie: return \u0022\uD83E\uDDDE\u0022;\r\n\t\t\tcase CardType.Potion: return \u0022\uD83E\uDDEA\u0022;\r\n\t\t\tcase CardType.Mirror: return \u0022\uD83D\uDD18\u0022;\r\n\t\t\t//case CardType.AlarmClock: return \u0022\u23F0\u0022;\r\n\t\t\tcase CardType.FaxMachine: return \u0022\uD83D\uDCE0\u0022;\r\n\t\t\tcase CardType.Dice: return \u0022\uD83C\uDFB2\u0022;\r\n\t\t\tcase CardType.Coffee: return \u0022\u2615\u0022;\r\n\t\t\tcase CardType.Tree: return \u0022\uD83C\uDF33\u0022;\r\n\t\t\tcase CardType.Chipmunk: return \u0022\uD83D\uDC3F\uFE0F\u0022;\r\n\t\t\tcase CardType.Dancer: return \u0022\uD83D\uDC83\u0022;\r\n\t\t\tcase CardType.Wine: return \u0022\uD83C\uDF77\u0022;\r\n\t\t\tcase CardType.King: return \u0022\uD83E\uDD34\u0022;\r\n\t\t\tcase CardType.Police: return \u0022\uD83D\uDC6E\u0022;\r\n\t\t\tcase CardType.Ogre: return \u0022\uD83D\uDC79\u0022;\r\n\t\t\tcase CardType.Clown: return \u0022\uD83E\uDD21\u0022;\r\n\t\t\tcase CardType.MoneyBag: return \u0022\uD83D\uDCB0\u0022;\r\n\t\t\tcase CardType.Bank: return \u0022\uD83C\uDFE6\u0022;\r\n\t\t\tcase CardType.Steak: return \u0022\uD83E\uDD69\u0022;\r\n\t\t\tcase CardType.MagicWand: return \u0022\u2728\u0022;\r\n\t\t\tcase CardType.Carrot: return \u0022\uD83E\uDD55\u0022;\r\n\t\t\tcase CardType.Caterpillar: return \u0022\uD83D\uDC1B\u0022;\r\n\t\t\tcase CardType.Butterfly: return \u0022\uD83E\uDD8B\u0022;\r\n\t\t\tcase CardType.Tornado: return \u0022\uD83C\uDF2A\uFE0F\u0022;\r\n\t\t\tcase CardType.Map: return \u0022\uD83D\uDDFA\uFE0F\u0022;\r\n\t\t\tcase CardType.Cockroach: return \u0022\uD80C\uDDA3\u0022;\r\n\t\t\t//case CardType.Key: return \u0022\uD83D\uDD11\u0022;\r\n\t\t\tcase CardType.Broccoli: return \u0022\uD83E\uDD66\u0022;\r\n\t\t\t//case CardType.ATM: return \u0022\uD83C\uDFE7\u0022;\r\n\t\t\tcase CardType.Donut: return \u0022\uD83C\uDF69\u0022;\r\n\t\t\tcase CardType.Cheese: return \u0022\uD83E\uDDC0\u0022;\r\n\t\t\tcase CardType.CheeseMoldy: return \u0022\uD83E\uDD2E\u0022;\r\n\t\t\tcase CardType.GuideDog: return \u0022\uD83E\uDDAE\u0022;\r\n\t\t\tcase CardType.Taco: return \u0022\uD83C\uDF2E\u0022;\r\n\t\t\tcase CardType.Burrito: return \u0022\uD83C\uDF2F\u0022;\r\n\t\t\tcase CardType.Skunk: return \u0022\uD83E\uDDA8\u0022;\r\n\t\t\tcase CardType.CarePackage: return \u0022\uD83D\uDCE6\u0022;\r\n\t\t\tcase CardType.Cash: return \u0022\uD83D\uDCB5\u0022;\r\n\t\t\tcase CardType.BirthdayCake: return \u0022\uD83C\uDF82\u0022;\r\n\t\t\tcase CardType.Gem: return \u0022\uD83D\uDC8E\u0022;\r\n\t\t\tcase CardType.Pickaxe: return \u0022\u26CF\uFE0F\u0022;\r\n\t\t\tcase CardType.Mountain: return \u0022\u26F0\uFE0F\u0022;\r\n\t\t\tcase CardType.DiamondRing: return \u0022\uD83D\uDC8D\u0022;\r\n\t\t\tcase CardType.Rabbit: return \u0022\uD83D\uDC07\u0022;\r\n\t\t\tcase CardType.RedEnvelope: return \u0022\uD83E\uDDE7\u0022;\r\n\t\t}\r\n\r\n\t\treturn \u0022\u0022;\r\n\t}\r\n\r\n\tpublic static string GetCardDescription( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.Apple: return \u0022\u2705Match: \u002B1 HP\u0022;\r\n\t\t\tcase CardType.Bomb: return \u0022\u2705Match: reveal nearby cards then shuffle them\u0022;\r\n\t\t\tcase CardType.Rocket: return \u0022\u274CMismatch: swap position\u0022;\r\n\t\t\tcase CardType.Telephone: return \u0022\u2705Match: shake nearby pairs\u0022;\r\n\t\t\tcase CardType.Trumpet: return \u0022Match other cards: 30% chance to reveal\u0022;\r\n\t\t\tcase CardType.Pawn: return \u0022\u27A1\uFE0FTurn start: 50% to try to move upward\u0022;\r\n\t\t\tcase CardType.Balloon: return \u0022Floats upward\u0022;\r\n\t\t\tcase CardType.Spider: return \u0022Starts in a corner\u0022;\r\n\t\t\tcase CardType.Umbrella: return \u0022\uD83D\uDC41\uFE0FRevealed: toggle open/closed\u0022;\r\n\t\t\tcase CardType.Juggler: return \u0022\u274CMismatch: rearrange nearby cards\u0022;\r\n\t\t\tcase CardType.Coin: return \u0022\u2705Match: \u002B$2\u0022;\r\n\t\t\tcase CardType.Vampire: return \u0022While hovered: shake if you lose HP\u0022;\r\n\t\t\tcase CardType.Maracas: return \u0022Makes a distinctive sound when shook\u0022;\r\n\t\t\tcase CardType.Microwave: return \u0022\u27A1\uFE0FTurn start: shake a nearby food/drink\u0022;\r\n\t\t\tcase CardType.Raccoon: return \u0022\u27A1\uFE0FTurn start: shake an adjacent card\u0022;\r\n\t\t\tcase CardType.Rock: return \u0022Falls downward, pushing other cards\u0022;\r\n\t\t\tcase CardType.Bear: return \u0022Food/drink revealed: 20% chance to shake\u0022;\r\n\t\t\tcase CardType.Candle: return \u0022\u2705Match: each reveal a nearby card\u0022;\r\n\t\t\tcase CardType.CrystalBall: return \u0022\u274CMismatch: shake cards, including other card\u0027s match\u0022;\r\n\t\t\tcase CardType.Snake: return \u0022Shake when an adjacent card is matched\u0022;\r\n\t\t\tcase CardType.Rose: return \u0022When moved: shake and wilt\u0022;\r\n\t\t\tcase CardType.Bell: return \u0022Rings when moved or shook\u0022;\r\n\t\t\tcase CardType.Ant: return \u0022\u27A1\uFE0FTurn start: move to nearby empty space\u0022;\r\n\t\t\tcase CardType.Twins: return \u0022\uD83D\uDC41\uFE0FRevealed: nudge toward match\u0022;\r\n\t\t\tcase CardType.Compass: return \u0022\u274CMismatch: nudge toward other card\u0027s match\u0022;\r\n\t\t\tcase CardType.Antenna: return \u0022\uD83D\uDC41\uFE0FRevealed: sound indicates distance to match\u0022;\r\n\t\t\tcase CardType.Wizard: return \u0022\u23E9Every 3 turns: shuffle some cards\\n\uD83D\uDC94Damage Wizard: respawn some cards and shuffle them\u0022;\r\n\t\t\tcase CardType.AncientScroll: return \u0022\u2705Match: reveal all cards (after next turn, shuffle all cards)\u0022;\r\n\t\t\tcase CardType.JumpingSpider: return \u0022Starts in a corner\\n\u274CMismatch: swaps with an unknown card\u0022;\r\n\t\t\tcase CardType.Bento: return \u0022\u2705Match: \u002B1 HP for each consecutive match\u0022;\r\n\t\t\t//case CardType.StockMarket: return \u0022\u2705Match: gain half your money if the market is up, lose half if the market is down\u0022;\r\n\t\t\tcase CardType.Ninja: return \u0022\u27A1\uFE0FTurn start: 25% chance to swap position\u0022;\r\n\t\t\tcase CardType.Flashlight: return \u0022\uD83D\uDC46Chosen: reveal a nearby card\u0022;\r\n\t\t\tcase CardType.Bodybuilder: return \u0022\u27A1\uFE0FTurn start: move adjacent card upwards, pushing other cards\u0022;\r\n\t\t\tcase CardType.Helicopter: return \u0022\u274CMismatch: relocate along with an adjacent card\u0022;\r\n\t\t\tcase CardType.FlyingMoney: return \u0022\u2705Match: \u002B$3\\n\u274CMismatch: shuffle with some nearby cards\u0022;\r\n\t\t\tcase CardType.Syringe: return \u0022\u2705Match: heal all HP, but time is halved until end of level\u0022;\r\n\t\t\tcase CardType.Cellphone: return \u0022\u274CMismatch: vibrate nearest cellphone\u0022;\r\n\t\t\tcase CardType.Crab: return \u0022Moves sideways to empty spaces\u0022;\r\n\t\t\tcase CardType.Magnet: return \u0022\u27A1\uFE0FTurn start: pull card toward it\u0022;\r\n\t\t\tcase CardType.Stethoscope: return \u0022\u2705Match/\u274CMismatch: shake nearby cards with a heartbeat\u0022;\r\n\t\t\tcase CardType.UFO: return \u0022\u2705Match: abduct and shuffle nearby cards\u0022;\r\n\t\t\tcase CardType.Teacher: return \u0022\u2705Match: arrange row alphabetically\u0022;\r\n\t\t\tcase CardType.Tractor: return \u0022\u2705Match/\u274CMismatch: shift row one space\u0022;\r\n\t\t\tcase CardType.FortuneCookie: return \u0022\u2705Match: \u002B1 HP, and reveal 5 cards that you haven\u0027t seen before\u0022;\r\n\t\t\tcase CardType.Dolphin: return \u0022Revealed on 4 consecutive mismatches\u0022;\r\n\t\t\tcase CardType.Detective: return \u0022\u27A1\uFE0FTurn start: 50% chance to reveal a nearby card\u0022;\r\n\t\t\tcase CardType.Genie: return \u0022\u2705Match: next card chosen shakes its match\u0022;\r\n\t\t\tcase CardType.Potion: return \u0022\u2705Match: your HP is set to half\u0022;\r\n\t\t\tcase CardType.Mirror: return \u0022\u2705Match: flip the level horizontally\u0022;\r\n\t\t\t//case CardType.AlarmClock: return \u002270% chance to shake when timer goes below 1s\u0022;\r\n\t\t\tcase CardType.FaxMachine: return \u0022\uD83D\uDC46Chosen: shake 3 cards, including another fax machine\u0022;\r\n\t\t\tcase CardType.Dice: return \u0022\u274CMismatch: roll a 6 to get \u002B$2 (rolling 1 loses $1)\\n\u2705Match: Roll a 12 to get \u002B$5 (rolling 2 loses $2)\u0022;\r\n\t\t\tcase CardType.Coffee: return \u0022\u2705Match: \u002B2 HP, and your next turn lasts 3 seconds\u0022;\r\n\t\t\tcase CardType.Tree: return \u0022\u2705Match: reveal an apple\u0022;\r\n\t\t\tcase CardType.Chipmunk: return \u0022\u27A1\uFE0FTurn start: move toward a tree\u0022;\r\n\t\t\tcase CardType.Dancer: return \u0022\u274CMismatch: dance with multiple partners\u0022;\r\n\t\t\tcase CardType.Wine: return \u0022\u2705Match: \u002B2 HP\\nShake if an adjacent card shakes\u0022;\r\n\t\t\tcase CardType.King: return \u0022\uD83D\uDC94Damage King: he decides your next choice\u0022;\r\n\t\t\tcase CardType.Police: return \u0022\u274CMismatch: Reveal and lock a nearby card for 2 turns\\n\uD83D\uDC94Damage Police: Lock some nearby cards for 1 turn, then shuffle\u0022;\r\n\t\t\tcase CardType.Ogre: return \u0022\uD83D\uDC94Damage Ogre: shuffle with nearby cards\u0022;\r\n\t\t\tcase CardType.Clown: return \u0022\uD83D\uDC94Damage Clown: swap multiple times\u0022;\r\n\t\t\tcase CardType.MoneyBag: return \u0022\u2705Match: \u002B$5\u0022;\r\n\t\t\tcase CardType.Bank: return \u0022\u2705Match: transform all coins into money bags\u0022;\r\n\t\t\tcase CardType.Steak: return \u0022\u2705Match: -$1 and \u002B4 HP\u0022;\r\n\t\t\tcase CardType.MagicWand: return \u0022\u274CMismatch: send other card adjacent to its match\u0022;\r\n\t\t\tcase CardType.Carrot: return \u0022\u2705Match: \u002B3 HP, and timer is doubled next turn\u0022;\r\n\t\t\tcase CardType.Caterpillar: return \u0022\u27A1\uFE0FTurn start: 20% chance to shake and transform into a butterfly\u0022;\r\n\t\t\tcase CardType.Tornado: return \u0022\u27A1\uFE0FTurn start: swap 2 adjacent cards\u0022;\r\n\t\t\tcase CardType.Map: return \u0022\u2705Match: reveal all cards between\u0022;\r\n\t\t\tcase CardType.Cockroach: return \u0022Can\u0027t be matched until no other cards remain\u0022;\r\n\t\t\t//case CardType.Key: return \u0022\u274CMismatch: unlock other card\\n\u2705Match: unlock all cards\u0022;\r\n\t\t\tcase CardType.Broccoli: return \u0022\u2705Match: \u002B3 HP\u0022;\r\n\t\t\t//case CardType.ATM: return \u0022\u2705Match: \u002B$1 for every 2 matches you\u0027ve made this level (max: $7)\u0022;\r\n\t\t\tcase CardType.Donut: return \u0022\u2705Match: \u002B1 HP for each adjacent empty space\u0022;\r\n\t\t\tcase CardType.Cheese: return \u0022\u2705Match: \u002B3 HP if not moldy\\nGoes moldy after 7 turns\u0022;\r\n\t\t\tcase CardType.GuideDog: return \u0022When you mismatch other cards, 50% chance to point toward one of their matches\u0022;\r\n\t\t\tcase CardType.Taco: return \u0022\u2705Match: \u002B1 Max HP\u0022;\r\n\t\t\tcase CardType.Burrito: return \u0022\u2705Match: \u002B2 Max HP\u0022;\r\n\t\t\tcase CardType.Skunk: return \u0022Can\u0027t be matched while adjacent to any non-skunks\u0022;\r\n\t\t\tcase CardType.CarePackage: return \u0022\u2705Match: \u002B$1 for every 2 HP missing\u0022;\r\n\t\t\tcase CardType.Cash: return \u0022\u2705Match: \u002B$3 if both cash are nearby eachother, otherwise \u002B$1\u0022;\r\n\t\t\tcase CardType.BirthdayCake: return \u0022\u2705Match: \u002B1 HP and \u002B$2\u0022;\r\n\t\t\tcase CardType.Gem: return \u0022\u2705Match: \u002B$4\u0022;\r\n\t\t\tcase CardType.Pickaxe: return \u0022\u2705Match: transform all boulders into gems\u0022;\r\n\t\t\tcase CardType.Mountain: return \u0022Can\u0027t be moved\u0022;\r\n\t\t\tcase CardType.DiamondRing: return \u0022\u2705Match: \u002B$3 if no other cards remain, otherwise \u002B$1\u0022;\r\n\t\t\tcase CardType.Rabbit: return \u0022\u27A1\uFE0FTurn start: 50% chance to move towards its match\u0022;\r\n\t\t\tcase CardType.RedEnvelope: return \u0022\u2705Match: if you have less than $5, set your money to $5\u0022;\r\n\t\t}\r\n\r\n\t\treturn \u0022\u0022;\r\n\t}\r\n\r\n\tpublic static string GetCardExplanation( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.Ant: return \u0022\\\u0022nearby\\\u0022 means 1 space away\\n(including diagonal)\u0022;\r\n\t\t\tcase CardType.Snake: return \u0022\\\u0022adjacent\\\u0022 means 1 space away\\n(NOT including diagonal)\u0022;\r\n\t\t}\r\n\r\n\t\treturn \u0022\u0022;\r\n\t}\r\n\r\n\tpublic static bool HasHP( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.Ogre: return true;\r\n\t\t\tcase CardType.Clown: return true;\r\n\t\t\tcase CardType.Police: return true;\r\n\t\t\tcase CardType.Wizard: return true;\r\n\t\t\tcase CardType.King: return true;\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tpublic static int GetMaxHP( CardType cardType )\r\n\t{\r\n\t\tswitch ( cardType )\r\n\t\t{\r\n\t\t\tcase CardType.Ogre: return 2;\r\n\t\t\tcase CardType.Clown: return 2;\r\n\t\t\tcase CardType.Police: return 2;\r\n\t\t\tcase CardType.Wizard: return 3;\r\n\t\t\tcase CardType.King: return 3;\r\n\t\t}\r\n\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tpublic void SetRevealedFromAsync(bool revealed)\r\n\t{\r\n\t\tIsRevealed = revealed;\r\n\r\n\t\tif( Card.HasHP(CardType) || IsLocked )\r\n\t\t\tIconObj.Enabled = revealed;\r\n\r\n\t\tif ( revealed )\r\n\t\t{\r\n\t\t\tNumTimesRevealed\u002B\u002B;\r\n\r\n\t\t\tif(Manager.Instance.Stats[StatType.MaxCrayonMarks] \u003E 0f \u0026\u0026 !AreRevealMarksShown)\r\n\t\t\t\tShowRevealMarks();\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void SetRevealedInstant()\r\n\t{\r\n\t\tIsRevealed = true;\r\n\r\n\t\tif ( Card.HasHP( CardType ) || IsLocked )\r\n\t\t\tIconObj.Enabled = true;\r\n\r\n\t\tWorldRotation = Rotation.FromPitch( 0f );\r\n\r\n\t\tNumTimesRevealed\u002B\u002B;\r\n\r\n\t\tif ( Manager.Instance.Stats[StatType.MaxCrayonMarks] \u003E 0f \u0026\u0026 !AreRevealMarksShown )\r\n\t\t\tShowRevealMarks();\r\n\t}\r\n\r\n\tpublic void SetHiddenInstant()\r\n\t{\r\n\t\tIsRevealed = false;\r\n\r\n\t\tif ( Card.HasHP( CardType ) )\r\n\t\t\tIconObj.Enabled = false;\r\n\r\n\t\tWorldRotation = Rotation.FromPitch( 180f );\r\n\t}\r\n\r\n\tpublic void Shake( float strength, float time = 0.6f, EasingType easingType = EasingType.QuadOut, bool playSfx = true )\r\n\t{\r\n\t\tIsShaking = true;\r\n\t\t_timeSinceShakeStart = 0f;\r\n\t\t_shakeTime = time;\r\n\t\t_shakeEasingType = easingType;\r\n\t\t_shakeStrength = strength;\r\n\r\n\t\tif ( playSfx || ( OverrideShakeSfx \u0026\u0026 ( IsRevealed || !OnlyOverrideShakeSfxWhenRevealed ) )  )\r\n\t\t\tPlayShakeSfx();\r\n\t}\r\n\r\n\tpublic virtual void PlayShakeSfx()\r\n\t{\r\n\t\t//Manager.Instance.PlayCardSfx( \u0022shake_1\u0022, this, volume: 1.1f, pitch: Game.Random.Float( 1.4f, 1.6f ) );\r\n\t\tManager.Instance.PlayCardSfx( \u0022shake_3\u0022, this, volume: 1.35f, pitch: Game.Random.Float( 0.94f, 1.06f ) );\r\n\t}\r\n\r\n\tpublic virtual bool OverrideShakeSfx =\u003E false;\r\n\tpublic virtual bool OnlyOverrideShakeSfxWhenRevealed =\u003E false;\r\n\r\n\tpublic virtual void PlayHurtSfx(Card card0, Card card1)\r\n\t{\r\n\t\tManager.Instance.PlayCardSfxBetween( \u0022shake_1\u0022, card0, card1, volume: 1.3f, pitch: Game.Random.Float( 1.4f, 1.6f ) );\r\n\t}\r\n\r\n\t// return false if needed to change start pos\r\n\tpublic virtual bool ValidateStartingGridPos()\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpublic virtual bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tpublic virtual async Task HandleEventAsync(EventType eventType)\r\n\t{\r\n\t\tawait Task.Frame();\r\n\t}\r\n\r\n\tpublic virtual string GetEventText( EventType eventType )\r\n\t{\r\n\t\treturn GetCardDescription( CardType );\r\n\t}\r\n\r\n\tpublic async Task Hurt()\r\n\t{\r\n\t\tif(!Card.HasHP(CardType))\r\n\t\t{\r\n\t\t\tLog.Error( $\u0022Trying to hurt card {CardType} with no HP!\u0022 );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tHP--;\r\n\t\tawait Manager.Instance.ShakeCard(this, playSfx: false);\r\n\t}\r\n\r\n\tpublic void Lock(int numTurns)\r\n\t{\r\n\t\tIsLocked = true;\r\n\t\tLockTurnsRemaining = numTurns;\r\n\t\tWasJustLocked = true;\r\n\t}\r\n\r\n\tpublic void Unlock()\r\n\t{\r\n\t\tIsLocked = false;\r\n\t}\r\n\r\n\tpublic virtual bool CanBeMatched()\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpublic void StartExploding(float explodeTime)\r\n\t{\r\n\t\tIsExploding = true;\r\n\t\t_timeSinceStartExploding = 0f;\r\n\t\t_explodeTime = explodeTime;\r\n\t\t_explodeStartPos = LocalPosition;\r\n\r\n\t\tint rand = Game.Random.Int( 0, 5 );\r\n\t\tswitch(rand)\r\n\t\t{\r\n\t\t\tcase 0: _explodeEasingType = EasingType.SineIn; break;\r\n\t\t\tcase 1: _explodeEasingType = EasingType.SineIn; break;\r\n\t\t\tcase 2: _explodeEasingType = EasingType.QuadIn; break;\r\n\t\t\tcase 3: _explodeEasingType = EasingType.QuadIn; break;\r\n\t\t\tcase 4: _explodeEasingType = EasingType.QuartIn; break;\r\n\t\t\tcase 5: _explodeEasingType = EasingType.Linear; break;\r\n\t\t}\r\n\r\n\t\trand = Game.Random.Int( 0, 7 );\r\n\t\tswitch ( rand )\r\n\t\t{\r\n\t\t\tcase 0: _explodeShakeEasingType = EasingType.SineIn; break;\r\n\t\t\tcase 1: _explodeShakeEasingType = EasingType.QuadIn; break;\r\n\t\t\tcase 2: _explodeShakeEasingType = EasingType.QuartIn; break;\r\n\t\t\tcase 3: _explodeShakeEasingType = EasingType.ExpoIn; break;\r\n\t\t\tcase 4: _explodeShakeEasingType = EasingType.ExpoIn; break;\r\n\t\t\tcase 5: _explodeShakeEasingType = EasingType.ExpoIn; break;\r\n\t\t\tcase 6: _explodeShakeEasingType = EasingType.ExpoIn; break;\r\n\t\t\tcase 7: _explodeShakeEasingType = EasingType.Linear; break;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic void Explode( int breakNum )\r\n\t{\r\n\t\tvar scale = LocalScale.x * Model.LocalScale.x;\r\n\t\tManager.Instance.SpawnCardBreak( WorldPosition, LocalRotation, scale, ModelRenderer.MaterialOverride, breakNum );\r\n\t\tManager.Instance.PlayCardSfx( \u0022explosion\u0022, this, volume: Game.Random.Float( 0.4f, 0.55f ), pitch: Game.Random.Float( 0.4f, 2f ) );\r\n\r\n\t\tManager.Instance.CardBreakParticlesPrefab.Clone( WorldPosition.WithZ( 25f ) );\r\n\t\tManager.Instance.CardBreakShockwavePrefab.Clone( WorldPosition.WithZ( 55f ) );\r\n\r\n\t\tGameObject.Destroy();\r\n\t}\r\n\r\n\tpublic void StartScaling(float time, float amount, EasingType easingType)\r\n\t{\r\n\t\tIsScaling = true;\r\n\t\t_timeSinceScale = 0f;\r\n\t\t_scaleTime = time;\r\n\t\t_scaleAmount = amount;\r\n\t\t_scaleEasingType = easingType;\r\n\t}\r\n\r\n\tpublic void ShowFlag()\r\n\t{\r\n\t\tIsFlagShown = true;\r\n\t\tIconBackObj.Enabled = true;\r\n\t}\r\n\r\n\tpublic void HideFlag()\r\n\t{\r\n\t\tIsFlagShown = false;\r\n\r\n\t\tif ( !AreRevealMarksShown )\r\n\t\t\tIconBackObj.Enabled = false;\r\n\t}\r\n\r\n\tpublic void ShowRevealMarks()\r\n\t{\r\n\t\tAreRevealMarksShown = true;\r\n\t\tIconBackObj.Enabled = true;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardBank.cs","FileName":"CardBank.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Net;\r\nusing System.Threading.Tasks;\r\n\r\npublic class CardBank : Card\r\n{\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\tswitch ( eventType )\r\n\t\t{\r\n\t\t\tcase EventType.Match:\r\n\t\t\t\treturn Manager.Instance.ChosenCards[1] == this;\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tawait Task.DelayRealtime( 150 );\r\n\r\n\t\tvar coins = Manager.Instance.Cards.Where( x =\u003E x.CardType == CardType.Coin ).ToList();\r\n\t\tif(coins.Count \u003E 0)\r\n\t\t{\r\n\t\t\tManager.Instance.PlayCardSfxBetween( \u0022bank\u0022, Manager.Instance.ChosenCards[0], Manager.Instance.ChosenCards[1], volume: 1f, pitch: Game.Random.Float( 0.9f, 1.1f ) );\r\n\r\n\t\t\tawait Task.DelayRealtime( 50 );\r\n\r\n\t\t\tforeach ( var coin in coins )\r\n\t\t\t\tcoin.SetCardType( CardType.MoneyBag );\r\n\r\n\t\t\tawait Task.DelayRealtime( 300 );\r\n\t\t}\r\n\r\n\t\tawait Task.DelayRealtime( 800 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardCockroach.cs","FileName":"CardCockroach.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Threading.Tasks;\r\n\r\npublic class CardCockroach : Card\r\n{\r\n\tpublic override bool IsAlive =\u003E true;\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.Mismatch \u0026\u0026 Manager.Instance.ChosenCards[0].CardType == CardType.Cockroach \u0026\u0026 Manager.Instance.ChosenCards[1].CardType == CardType.Cockroach \u0026\u0026 !IsLocked;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tawait Task.DelayRealtime( 850 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n\r\n\tpublic override bool CanBeMatched()\r\n\t{\r\n\t\tforeach(var card in Manager.Instance.Cards)\r\n\t\t{\r\n\t\t\tif ( card.CardType != CardType.Cockroach )\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardDancer.cs","FileName":"CardDancer.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Threading.Tasks;\r\n\r\npublic class CardDancer : Card\r\n{\r\n\tpublic override bool IsAlive =\u003E true;\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.Mismatch \u0026\u0026 Manager.Instance.ChosenCards.Contains( this ) \u0026\u0026 !Manager.Instance.IsMismatchALockedMatch;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tList\u003CCard\u003E neighbourCards = new();\r\n\t\tList\u003CIntVector2\u003E neighboursEmpty = new();\r\n\t\tCard lastPartnerCard = null;\r\n\r\n\t\tawait Task.DelayRealtime( 300 );\r\n\r\n\t\tManager.Instance.PlayCardSfx( \u0022dancer\u0022, this, volume: 1.1f, pitch: Game.Random.Float( 0.98f, 1.02f ) );\r\n\r\n\t\tfor (int i = 0; i \u003C 4; i\u002B\u002B)\r\n\t\t{\r\n\t\t\tneighbourCards.Clear();\r\n\t\t\tneighboursEmpty.Clear();\r\n\r\n\t\t\tEvaluateNeighbour( GridPos \u002B new IntVector2( -1, 0 ), neighbourCards, neighboursEmpty );\r\n\t\t\tEvaluateNeighbour( GridPos \u002B new IntVector2( 1, 0 ), neighbourCards, neighboursEmpty );\r\n\t\t\tEvaluateNeighbour( GridPos \u002B new IntVector2( 0, -1 ), neighbourCards, neighboursEmpty );\r\n\t\t\tEvaluateNeighbour( GridPos \u002B new IntVector2( 0, 1 ), neighbourCards, neighboursEmpty );\r\n\r\n\t\t\tIntVector2 targetGridPos;\r\n\t\t\tCard targetCard = null;\r\n\r\n\t\t\tvar validNeighbourCards = neighbourCards.Where( x =\u003E x != lastPartnerCard ).ToList();\r\n\r\n\t\t\tif ( validNeighbourCards.Count \u003E 0 )\r\n\t\t\t{\r\n\t\t\t\tvalidNeighbourCards.Shuffle();\r\n\t\t\t\ttargetCard = validNeighbourCards.First();\r\n\t\t\t\ttargetGridPos = targetCard.GridPos;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tneighboursEmpty.Shuffle();\r\n\t\t\t\ttargetGridPos = neighboursEmpty.First();\r\n\t\t\t}\r\n\r\n\t\t\tif ( targetCard != null )\r\n\t\t\t{\r\n\t\t\t\tawait Manager.Instance.ShakeCard( this );\r\n\t\t\t\tawait Manager.Instance.ShakeCard( targetCard );\r\n\r\n\t\t\t\tlastPartnerCard = targetCard;\r\n\r\n\t\t\t\tawait Task.DelayRealtime( 650 );\r\n\r\n\t\t\t\tif(i \u003C 3)\r\n\t\t\t\t{\r\n\t\t\t\t\tawait Manager.Instance.SwapCardPositions( this, targetCard );\r\n\t\t\t\t\tawait Task.DelayRealtime( 250 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tlastPartnerCard = null;\r\n\r\n\t\t\t\tif ( i \u003C 3 )\r\n\t\t\t\t{\r\n\t\t\t\t\tManager.Instance.RemoveCardGridPos( this );\r\n\t\t\t\t\tawait Manager.Instance.SetCardGridPos( this, targetGridPos );\r\n\r\n\t\t\t\t\tawait Task.DelayRealtime( 400 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tawait Task.DelayRealtime( 100 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\r\n\t\tawait Manager.Instance.EventHappened( EventType.AfterCardsMoved );\r\n\t}\r\n\r\n\tvoid EvaluateNeighbour(IntVector2 gridPos, List\u003CCard\u003E neighbourCards, List\u003CIntVector2\u003E empty)\r\n\t{\r\n\t\tif ( !Manager.Instance.IsGridPosInBounds( gridPos ) )\r\n\t\t\treturn;\r\n\r\n\t\tvar card = Manager.Instance.GetCardAtGridPos( gridPos );\r\n\t\tif ( card != null )\r\n\t\t\tneighbourCards.Add( card );\r\n\t\telse\r\n\t\t\tempty.Add( gridPos );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardDolphin.cs","FileName":"CardDolphin.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Threading.Tasks;\r\nusing System.Xml.Linq;\r\n\r\npublic class CardDolphin : Card\r\n{\r\n\tpublic override bool IsAlive =\u003E true;\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.Mismatch \u0026\u0026 !Manager.Instance.ChosenCards.Contains(this) \u0026\u0026 Manager.Instance.Stats[StatType.ConsecutiveMismatches] == 3;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tawait Task.DelayRealtime( 250 );\r\n\r\n\t\tManager.Instance.PlayCardSfx( \u0022card_flip\u0022, this, volume: 0.8f, pitch: Game.Random.Float( 1.15f, 1.2f ) );\r\n\t\tawait Task.DelayRealtime( 100 );\r\n\t\tManager.Instance.PlayCardSfx( \u0022dolphin\u0022, this, volume: 0.8f, pitch: Game.Random.Float( 1f, 1.15f ) );\r\n\t\tawait Manager.Instance.RevealCard( this );\r\n\r\n\t\tawait Task.DelayRealtime( Game.Random.Int(400, 700) );\r\n\r\n\t\tManager.Instance.HideCard( this );\r\n\t\tManager.Instance.PlayCardSfx( \u0022card_flip\u0022, this, volume: 0.7f, pitch: Game.Random.Float( 0.65f, 0.75f ) );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardGenie.cs","FileName":"CardGenie.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Threading.Tasks;\r\n\r\npublic class CardGenie : Card\r\n{\r\n\tpublic override bool IsAlive =\u003E true;\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.Match \u0026\u0026 Manager.Instance.ChosenCards[0] == this;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tawait Task.DelayRealtime( 250 );\r\n\r\n\t\tManager.Instance.PlayCardSfxBetween( \u0022genie\u0022, Manager.Instance.ChosenCards[0], Manager.Instance.ChosenCards[1], volume: 0.6f, pitch: Game.Random.Float( 1.25f, 1.26f ) );\r\n\r\n\t\tManager.Instance.AddStatus( \u0022StatusGenie\u0022 );\r\n\r\n\t\tawait Task.DelayRealtime( 1750 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n\r\npublic class StatusGenie : StatusEffect\r\n{\r\n\tpublic float TimerReductionAmount { get; set; }\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.Choose;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tvar validCards = Manager.Instance.Cards.Where(x =\u003E x.CardType == Manager.Instance.ChosenCard.CardType \u0026\u0026 x != Manager.Instance.ChosenCard).ToList();\r\n\t\tif ( validCards.Count == 0 )\r\n\t\t\treturn;\r\n\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tawait Task.DelayRealtime( 250 );\r\n\r\n\t\tManager.Instance.PlayCardSfx( \u0022genie_choose\u0022, Manager.Instance.ChosenCard, volume: 0.9f, pitch: Game.Random.Float( 0.95f, 1.05f ) );\r\n\r\n\t\tawait Task.DelayRealtime( 750 );\r\n\r\n\t\tvalidCards.Shuffle();\r\n\r\n\t\tawait Manager.Instance.ShakeCard( validCards.FirstOrDefault() );\r\n\t\t\r\n\t\tawait Task.DelayRealtime( 750 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\r\n\t\tManager.Instance.RemoveStatus( this );\r\n\t}\r\n\r\n\tpublic override string GetEventIcon( EventType eventType )\r\n\t{\r\n\t\treturn \u0022textures/genie.png\u0022;\r\n\t}\r\n\r\n\tpublic override string GetEventText( EventType eventType )\r\n\t{\r\n\t\treturn \u0022Shake matching card\u0022;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardKey.cs","FileName":"CardKey.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Threading.Tasks;\r\n\r\npublic class CardKey : Card\r\n{\r\n\t//public override bool ShouldHandleEvent( EventType eventType )\r\n\t//{\r\n\t//\treturn eventType == EventType.Mismatch \u0026\u0026 Manager.Instance.ChosenCards.Contains(this) || eventType == EventType.Match \u0026\u0026 Manager.Instance.ChosenCards[1] == this;\r\n\t//}\r\n\r\n\t//public override async Task HandleEventAsync( EventType eventType )\r\n\t//{\r\n\t//\tif ( eventType == EventType.Mismatch )\r\n\t//\t{\r\n\t//\t\tvar key = Manager.Instance.ChosenCards[0].CardType == CardType.Key ? Manager.Instance.ChosenCards[0] : Manager.Instance.ChosenCards[1];\r\n\t//\t\tvar otherCard = Manager.Instance.ChosenCards[0].CardType == CardType.Key ? Manager.Instance.ChosenCards[1] : Manager.Instance.ChosenCards[0];\r\n\r\n\t//\t\tif ( key.IsLocked || !otherCard.IsLocked )\r\n\t//\t\t\treturn;\r\n\r\n\t//\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t//\t\tawait Task.DelayRealtime( 50 );\r\n\r\n\t//\t\tManager.Instance.PlayCardSfxBetween( \u0022key\u0022, Manager.Instance.ChosenCards[0], Manager.Instance.ChosenCards[1], volume: 1.5f, pitch: Game.Random.Float( 0.9f, 1.1f ) );\r\n\r\n\t//\t\tawait Task.DelayRealtime( 50 );\r\n\r\n\t//\t\tawait Manager.Instance.UnlockCard( otherCard );\r\n\r\n\t//\t\tawait Task.DelayRealtime( 900 );\r\n\r\n\t//\t\tManager.Instance.PopEventMessage();\r\n\t//\t}\r\n //       else if (eventType == EventType.Match)\r\n\t//\t{\r\n\t//\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t//\t\tawait Task.DelayRealtime( 50 );\r\n\r\n\t//\t\tvar lockedCards = Manager.Instance.Cards.Where( x =\u003E x.IsLocked ).ToList();\r\n\r\n\t//\t\tif ( lockedCards.Count == 0 )\r\n\t//\t\t{\r\n\t//\t\t\tawait Task.DelayRealtime( 800 );\r\n\r\n\t//\t\t\tManager.Instance.PopEventMessage();\r\n\r\n\t//\t\t\treturn;\r\n\t//\t\t}\r\n\r\n\t//\t\tManager.Instance.PlayCardSfxBetween( \u0022key\u0022, Manager.Instance.ChosenCards[0], Manager.Instance.ChosenCards[1], volume: 1.5f, pitch: Game.Random.Float( 0.9f, 1.1f ) );\r\n\r\n\t//\t\tawait Task.DelayRealtime( 50 );\r\n\r\n\t//\t\tforeach ( var card in lockedCards )\r\n\t//\t\t{\r\n\t//\t\t\tawait Manager.Instance.UnlockCard( card );\r\n\t//\t\t}\r\n\r\n\t//\t\tawait Task.DelayRealtime( 1000 );\r\n\r\n\t//\t\tManager.Instance.PopEventMessage();\r\n\t//\t}\r\n\t//}\r\n\r\n\t//public override string GetEventText( EventType eventType )\r\n\t//{\r\n\t//\tif ( eventType == EventType.Mismatch )\r\n\t//\t{\r\n\t//\t\treturn \u0022\u274CMismatch: unlock other card\u0022;\r\n\t//\t}\r\n\t//\telse\r\n\t//\t{\r\n\t//\t\treturn \u0022\u2705Match: unlock all cards\u0022;\r\n\t//\t}\r\n\t//}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicGuideDog.cs","FileName":"RelicGuideDog.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicGuideDog : Relic\r\n{\r\n\tpublic override void Init()\r\n\t{\r\n\t\tbase.Init();\r\n\r\n\t\tMaxLevel = 1;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicMammothMeat.cs","FileName":"RelicMammothMeat.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicMammothMeat : Relic\r\n{\r\n\tpublic override void LevelUp()\r\n\t{\r\n\t\tbase.LevelUp();\r\n\r\n\t\tvar mouse = Mouse.Position;\r\n\t\tvar camera = Scene.Camera;\r\n\t\tvar ray = camera.ScreenPixelToRay( mouse );\r\n\r\n\t\tvar tr = Scene.Trace.Ray( ray, 10000f ).Run();\r\n\r\n\t\tManager.Instance.PlaySfxCenter( \u0022mammoth_meat\u0022, volume: 0.75f, pitch: Game.Random.Float( 0.85f, 0.9f ) );\r\n\r\n\t\tint maxHpAmount = 8;\r\n\t\tManager.Instance.SpawnMaxHPFloater( maxHpAmount, tr.EndPosition );// \u002B new Vector3(0f, -30f, 0f) );\r\n\t\tManager.Instance.MaxHP \u002B= maxHpAmount;\r\n\r\n\t\t//int hpAmount = 5;\r\n\t\t//Manager.Instance.HP = Math.Min( Manager.Instance.HP \u002B hpAmount, Manager.Instance.MaxHP );\r\n\t\tManager.Instance.TimeSinceHPChanged = 0f;\r\n\r\n\t\t//Manager.Instance.SpawnHealHPFloater( hpAmount, tr.EndPosition );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicMantlepieceClock.cs","FileName":"RelicMantlepieceClock.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicMantlepieceClock : Relic\r\n{\r\n\tpublic override void LevelUp()\r\n\t{\r\n\t\tbase.LevelUp();\r\n\r\n\t\tManager.Instance.Stats[StatType.NumExtraBountyTurns] \u002B= (Level == 1 ? 2f : 1f);\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicMedicalLicense.cs","FileName":"RelicMedicalLicense.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicMedicalLicense : Relic\r\n{\r\n\tpublic override void Init()\r\n\t{\r\n\t\tbase.Init();\r\n\r\n\t\tMaxLevel = 1;\r\n\t}\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.OverhealHP;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tawait Task.DelayRealtime( 1000 );\r\n\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tvar camera = Scene.Camera;\r\n\t\tvar ray = camera.ScreenPixelToRay( new Vector3( Screen.Width / 2, Screen.Height / 2, 0f ) );\r\n\r\n\t\tvar tr = Scene.Trace.Ray( ray, 10000f ).Run();\r\n\r\n\t\tManager.Instance.PlaySfx( \u0022medical_license\u0022, tr.EndPosition.WithZ( Scene.Camera.WorldPosition.z - Globals.CARD_SFX_DEPTH_DIFF ), volume: 1.2f, pitch: Game.Random.Float( 0.95f, 1.05f ) );\r\n\r\n\t\tawait Task.DelayRealtime( 350 );\r\n\r\n\t\tint moneyAmount = (int)Manager.Instance.Stats[StatType.LatestOverhealAmount] \u002B (int)Manager.Instance.Stats[StatType.EarnExtraMoney];\r\n\r\n\t\tManager.Instance.SpawnGainMoneyFloater( moneyAmount, tr.EndPosition );\r\n\r\n\t\tawait Manager.Instance.GainMoney( moneyAmount );\r\n\r\n\t\tawait Task.DelayRealtime( 650 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicMouseTrap.cs","FileName":"RelicMouseTrap.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicMouseTrap : Relic\r\n{\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.ClaimBounty;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync(EventType eventType)\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tawait Task.DelayRealtime( 100 );\r\n\r\n\t\tManager.Instance.PlaySfxCenter( \u0022mouse_trap\u0022, volume: 0.8f, pitch: Game.Random.Float( 0.95f, 1.05f ) );\r\n\r\n\t\tawait Task.DelayRealtime( 400 );\r\n\r\n\t\tvar camera = Scene.Camera;\r\n\t\tvar ray = camera.ScreenPixelToRay( new Vector3( Screen.Width / 2, Screen.Height / 2, 0f ) );\r\n\t\tvar tr = Scene.Trace.Ray( ray, 10000f ).Run();\r\n\r\n\t\tint maxHP = Level;\r\n\t\tManager.Instance.SpawnMaxHPFloater( maxHP, tr.EndPosition );\r\n\t\tManager.Instance.MaxHP \u002B= maxHP;\r\n\r\n\t\tManager.Instance.TimeSinceHPChanged = 0f;\r\n\r\n\t\tawait Task.DelayRealtime( 500 );\r\n\t\t\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicSacrificialBlade.cs","FileName":"RelicSacrificialBlade.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicSacrificialBlade : Relic\r\n{\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.HurtCards;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync(EventType eventType)\r\n\t{\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\tvar camera = Scene.Camera;\r\n\t\tvar ray = camera.ScreenPixelToRay( new Vector3( Screen.Width / 2, Screen.Height / 2, 0f ) );\r\n\t\tvar tr = Scene.Trace.Ray( ray, 10000f ).Run();\r\n\r\n\t\tManager.Instance.PlaySfx( \u0022sacrificial_blade\u0022, tr.EndPosition.WithZ( Scene.Camera.WorldPosition.z - Globals.CARD_SFX_DEPTH_DIFF ), volume: 0.75f, pitch: Game.Random.Float( 1.6f, 1.65f ) );\r\n\r\n\t\tawait Task.DelayRealtime( 450 );\r\n\r\n\t\tint healAmount = Level;\r\n\r\n\t\tManager.Instance.SpawnHealHPFloater( healAmount, tr.EndPosition );\r\n\r\n\t\tawait Task.DelayRealtime( 350 );\r\n\r\n\t\tawait Manager.Instance.GainHP( healAmount );\r\n\r\n\t\tawait Task.DelayRealtime( 250 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"relics/RelicSign.cs","FileName":"RelicSign.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Reflection.PortableExecutable;\r\nusing System.Runtime.Versioning;\r\nusing System.Text.RegularExpressions;\r\nusing System.Threading.Tasks;\r\n\r\npublic class RelicSign : Relic\r\n{\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.Mismatch \u0026\u0026 Game.Random.Float(0f, 1f) \u003C Level * 0.25f;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tList\u003CCard\u003E validCards = new();\r\n\t\tforeach ( var card in Manager.Instance.Cards )\r\n\t\t{\r\n\t\t\tif ( card.NumTimesRevealed \u003E 0 \u0026\u0026 !Manager.Instance.ChosenCards.Contains(card) \u0026\u0026 !card.IsRevealed )\r\n\t\t\t\tvalidCards.Add( card );\r\n\t\t}\r\n\r\n\t\tif ( validCards.Count == 0 )\r\n\t\t\treturn;\r\n\r\n\t\tManager.Instance.PushEventMessage( this, eventType );\r\n\r\n\t\t// todo: sfx\r\n\r\n\t\tawait Task.DelayRealtime( 250 );\r\n\r\n\t\tvalidCards.Shuffle();\r\n\r\n\t\tvar cardToReveal = validCards.First();\r\n\r\n\t\tManager.Instance.PlayCardSfx( \u0022card_flip\u0022, cardToReveal, volume: 0.8f, pitch: Game.Random.Float( 1.15f, 1.2f ) );\r\n\t\tawait Manager.Instance.RevealCard( cardToReveal );\r\n\r\n\t\tawait Task.DelayRealtime( 750 );\r\n\r\n\t\tManager.Instance.HideCard( cardToReveal );\r\n\t\tManager.Instance.PlayCardSfx( \u0022card_flip\u0022, cardToReveal, volume: 0.7f, pitch: Game.Random.Float( 0.65f, 0.75f ) );\r\n\r\n\t\tawait Task.DelayRealtime( 300 );\r\n\r\n\t\tManager.Instance.PopEventMessage();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"ui/messagepanel.razor.scss","FileName":"messagepanel.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"MessagePanel {\r\n    position: absolute;\r\n    //min-width: 60%;\r\n    height: 60px;\r\n    bottom: 10px;\r\n    display: flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    border-radius: 15px;\r\n    //background-color: #00000088;\r\n    flex-direction: row;\r\n    padding: 8px;\r\n    backdrop-filter: blur(5px);\r\n    //transition: bottom 0.25s ease-out, transform 0.25s ease-out, opacity 0.25s ease-out;\r\n    transition: all 0.25s ease-out;\r\n\r\n    .message {\r\n        font-size: 24px;\r\n        color: #ffffffee;\r\n    }\r\n\r\n    .icon {\r\n        width: 55px;\r\n        height: 55px;\r\n        background-repeat: no-repeat;\r\n        background-size: contain;\r\n        background-position: center center;\r\n    }\r\n\r\n    \u0026.depth-0 {\r\n        transform: scale(1);\r\n        bottom: 10px;\r\n        z-index: 0;\r\n    }\r\n\r\n    \u0026.depth-1 {\r\n        transform: scale(0.8);\r\n        bottom: 50px;\r\n        z-index: -3;\r\n    }\r\n\r\n    \u0026.depth-2 {\r\n        transform: scale(0.6);\r\n        bottom: 90px;\r\n        z-index: -6;\r\n    }\r\n\r\n    \u0026.depth-3 {\r\n        transform: scale(0.5);\r\n        bottom: 110px;\r\n        z-index: -9;\r\n    }\r\n\r\n    \u0026.depth-4 {\r\n        transform: scale(0.4);\r\n        bottom: 140px;\r\n        z-index: -12;\r\n    }\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"ui/cardtypepanelelement.razor.scss","FileName":"cardtypepanelelement.razor.scss","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"CardTypePanelElement {\r\n\t//border-radius: 10px;\r\n\theight: 80px;\r\n\twidth: 80px;\r\n\tjustify-content: center;\r\n\t//flex-shrink: 1;\r\n\t//margin: 2px;\r\n\t//background-color: blue;\r\n\t//border: 2px solid #111111;\r\n\t//overflow: visible;\r\n\tposition: relative;\r\n\r\n\t.icon_container {\r\n\t\twidth: 100%;\r\n\t\theight: 100%;\r\n\t\ttransform: scale(1);\r\n\t\ttransition: transform 0.075s ease-out;\r\n\t\tpointer-events: all;\r\n\r\n\t\t\u0026:hover {\r\n\t\t\t//background-color: #301B3F99;\r\n\t\t\t//border: 2px solid #111111;\r\n\t\t\t//opacity: 1;\r\n\t\t\ttransform: scale(1.2);\r\n\t\t}\r\n\t}\r\n\r\n\t.icon {\r\n\t\tposition: absolute;\r\n\t\twidth: 100%;\r\n\t\theight: 100%;\r\n\t\tbackground-repeat: no-repeat;\r\n\t\tbackground-size: contain;\r\n\t\tbackground-position: center center;\r\n\t\tpointer-events: none;\r\n\t}\r\n\r\n\t.normal {\r\n\t\tfilter: brightness(1);\r\n\t\topacity: 1;\r\n\t}\r\n\r\n\t.matched {\r\n\t\tfilter: brightness(0);\r\n\t\topacity: 0.4;\r\n\t}\r\n\r\n\t.bounty {\r\n\t\tposition: absolute;\r\n\t\twidth: 60px;\r\n\t\theight: 60px;\r\n\t\tbackground-color: #0000ff99;\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"CardBreaker.cs","FileName":"CardBreaker.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\n\r\npublic sealed class CardBreaker : Component\r\n{\r\n\tprotected override void OnStart()\r\n\t{\r\n\r\n\t}\r\n\r\n\tpublic void Init(Material material, Rotation rot, float scale)\r\n\t{\r\n\t\tLocalRotation = rot;\r\n\t\tLocalScale = new Vector3( scale );\r\n\r\n\t\tfor ( int i = GameObject.Children.Count - 1; i \u003E= 0; i-- )\r\n\t\t{\r\n\t\t\tvar child = GameObject.Children[i];\r\n\t\t\tchild.SetParent( null );\r\n\r\n\t\t\tvar modelRenderer = child.Components.Get\u003CModelRenderer\u003E();\r\n\t\t\tmodelRenderer.Tint = Color.White;\r\n\t\t\tmodelRenderer.MaterialOverride = material;\r\n\r\n\t\t\tvar rigidBody = child.Components.Get\u003CRigidbody\u003E();\r\n\t\t\trigidBody.ApplyImpulse( (child.WorldPosition - WorldPosition).Normal * Game.Random.Float( 10f, 100f ) * rigidBody.PhysicsBody.Mass );\r\n\t\t\trigidBody.ApplyImpulse( new Vector3( 0f, 0f, 1f ) * Game.Random.Float( 400f, 800f ) * rigidBody.PhysicsBody.Mass );\r\n\t\t\trigidBody.AngularVelocity = Vector3.Random * Game.Random.Float( -10f, 10f );\r\n\t\t}\r\n\r\n\t\tGameObject.Destroy();\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"Utils.cs","FileName":"Utils.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing Sandbox;\r\nusing System.Text.Json;\r\n\r\npublic enum EasingType\r\n{\r\n\tNone = -1,\r\n\tLinear = 0,\r\n\tSineIn, SineOut, SineInOut,\r\n\tQuadIn, QuadOut, QuadInOut,\r\n\tCubicIn, CubicOut, CubicInOut,\r\n\tQuartIn, QuartOut, QuartInOut,\r\n\tQuintIn, QuintOut, QuintInOut,\r\n\tExpoIn, ExpoOut, ExpoInOut,\r\n\tExtremeIn, ExtremeOut, ExtremeInOut,\r\n\tElasticIn, ElasticOut, ElasticInOut,\r\n\tElasticSoftIn, ElasticSoftOut, ElasticSoftInOut,\r\n\tBackIn, BackOut, BackInOut,\r\n\tBounceIn, BounceOut, BounceInOut\r\n};\r\n\r\npublic struct IntVector2 : IEquatable\u003CIntVector2\u003E\r\n{\r\n\tpublic static implicit operator Vector2( IntVector2 vec )\r\n\t{\r\n\t\treturn new Vector2( vec.x, vec.y );\r\n\t}\r\n\r\n\tpublic static explicit operator IntVector2( Vector2 vec )\r\n\t{\r\n\t\treturn new IntVector2( (int)vec.x, (int)vec.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// A vector with zero for all components.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static readonly IntVector2 Zero = new IntVector2( 0, 0 );\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// A normalized vector along the positive X axis.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static readonly IntVector2 UnitX = new IntVector2( 1, 0 );\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// A normalized vector along the positive Y axis.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static readonly IntVector2 UnitY = new IntVector2( 0, 1 );\r\n\r\n\t#region Operators\r\n\t/// \u003Csummary\u003E\r\n\t/// The identity operator.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator \u002B( IntVector2 vec )\r\n\t{\r\n\t\treturn vec;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Component-wise addition of a vector to another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator \u002B( IntVector2 a, IntVector2 b )\r\n\t{\r\n\t\treturn new IntVector2( a.x \u002B b.x, a.y \u002B b.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Finds the negation of a vector.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator -( IntVector2 vec )\r\n\t{\r\n\t\treturn new IntVector2( -vec.x, -vec.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Component-wise subtraction of a vector from another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator -( IntVector2 a, IntVector2 b )\r\n\t{\r\n\t\treturn new IntVector2( a.x - b.x, a.y - b.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Component-wise multiplication of a vector by another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator *( IntVector2 a, IntVector2 b )\r\n\t{\r\n\t\treturn new IntVector2( a.x * b.x, a.y * b.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Multiplies a vector by a scalar.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator *( IntVector2 vec, int val )\r\n\t{\r\n\t\treturn new IntVector2( vec.x * val, vec.y * val );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Multiplies a vector by a scalar.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static Vector2 operator *( IntVector2 vec, float val )\r\n\t{\r\n\t\treturn new Vector2( vec.x * val, vec.y * val );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Multiplies a vector by a scalar.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator *( int val, IntVector2 vec )\r\n\t{\r\n\t\treturn new IntVector2( vec.x * val, vec.y * val );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Multiplies a vector by a scalar.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static Vector2 operator *( float val, IntVector2 vec )\r\n\t{\r\n\t\treturn new Vector2( vec.x * val, vec.y * val );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Component-wise division of a vector by another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator /( IntVector2 a, IntVector2 b )\r\n\t{\r\n\t\treturn new IntVector2( a.x / b.x, a.y / b.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Component-wise division of a vector by another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static Vector2 operator /( Vector2 a, IntVector2 b )\r\n\t{\r\n\t\treturn new Vector2( a.x / b.x, a.y / b.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Component-wise division of a vector by another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static Vector2 operator /( IntVector2 a, Vector2 b )\r\n\t{\r\n\t\treturn new Vector2( a.x / b.x, a.y / b.y );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Division of this vector by a scalar.\r\n\t/// \u003C/summary\u003E\r\n\tpublic static IntVector2 operator /( IntVector2 vec, int val )\r\n\t{\r\n\t\treturn new IntVector2( vec.x / val, vec.y / val );\r\n\t}\r\n\r\n\tpublic static Vector2 operator /( IntVector2 vec, float val )\r\n\t{\r\n\t\treturn new Vector2( vec.x / val, vec.y / val );\r\n\t}\r\n\r\n\tpublic static IntVector2 operator /( int val, IntVector2 vec )\r\n\t{\r\n\t\treturn new IntVector2( val / vec.x, val / vec.y );\r\n\t}\r\n\r\n\tpublic static Vector2 operator /( float val, IntVector2 vec )\r\n\t{\r\n\t\treturn new Vector2( val / vec.x, val / vec.y );\r\n\t}\r\n\t#endregion\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Horizontal component.\r\n\t/// \u003C/summary\u003E\r\n\tpublic int x;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Vertical component.\r\n\t/// \u003C/summary\u003E\r\n\tpublic int y;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Floating point magnitude of the vector.\r\n\t/// \u003C/summary\u003E\r\n\tpublic float Length { get { return (float)MathF.Sqrt( x * x \u002B y * y ); } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Magnitude of the vector in Taxicab geometry.\r\n\t/// \u003C/summary\u003E\r\n\tpublic int ManhattanLength { get { return Math.Abs( x ) \u002B Math.Abs( y ); } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Sum of each component squared.\r\n\t/// \u003C/summary\u003E\r\n\tpublic int LengthSquared { get { return x * x \u002B y * y; } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Gets a normalized vector in the same direction as this one.\r\n\t/// \u003C/summary\u003E\r\n\tpublic Vector2 Normalized { get { return LengthSquared \u003E= float.Epsilon ? this / Length : Zero; } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Gets a vector equal to this one rotated counter-clockwise by 90 degrees.\r\n\t/// \u003C/summary\u003E\r\n\tpublic IntVector2 Left { get { return new IntVector2( -y, x ); } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Gets a vector equal to this one rotated clockwise 90 degrees.\r\n\t/// \u003C/summary\u003E\r\n\tpublic IntVector2 Right { get { return new IntVector2( y, -x ); } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Gets a vector equal to this one rotated 180 degrees.\r\n\t/// \u003C/summary\u003E\r\n\tpublic IntVector2 Back { get { return -this; } }\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Constructs a vector from the given X and Y components.\r\n\t/// \u003C/summary\u003E\r\n\tpublic IntVector2( int x, int y )\r\n\t{\r\n\t\tthis.x = x; this.y = y;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Finds the scalar product of this vector and another.\r\n\t/// \u003C/summary\u003E\r\n\tpublic int Dot( IntVector2 vec )\r\n\t{\r\n\t\treturn x * vec.x \u002B y * vec.y;\r\n\t}\r\n\r\n\tpublic override bool Equals( object obj )\r\n\t{\r\n\t\treturn obj is IntVector2 \u0026\u0026 Equals( (IntVector2)obj );\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Tests for equality with another vector.\r\n\t/// \u003C/summary\u003E\r\n\tpublic bool Equals( IntVector2 vec )\r\n\t{\r\n\t\treturn x == vec.x \u0026\u0026 y == vec.y;\r\n\t}\r\n\r\n\tpublic override int GetHashCode()\r\n\t{\r\n\t\treturn x ^ y;\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Gets a string representing this vector in (X, Y) format.\r\n\t/// \u003C/summary\u003E\r\n\tpublic override string ToString()\r\n\t{\r\n\t\treturn string.Format( \u0022({0}, {1})\u0022, x, y );\r\n\t}\r\n}\r\n\r\npublic struct AStarEdge\u003CT\u003E\r\n{\r\n\t/// \u003Csummary\u003E\r\n\t/// The node this connection leads to.\r\n\t/// \u003C/summary\u003E\r\n\tpublic readonly T Dest;\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// The cost of using this connection.\r\n\t/// \u003C/summary\u003E\r\n\tpublic readonly float Cost;\r\n\r\n\tinternal AStarEdge( T dest, float cost )\r\n\t{\r\n\t\tDest = dest;\r\n\t\tCost = cost;\r\n\t}\r\n}\r\n\r\npublic static class Utils\r\n{\r\n\t// projects vector A onto B\r\n\tpublic static Vector3 ProjectVector( Vector3 a, Vector3 b )\r\n\t{\r\n\t\tfloat dotProduct = Vector3.Dot( a, b );\r\n\t\tfloat lengthSquared = Vector3.Dot( b, b );\r\n\t\treturn (dotProduct / lengthSquared) * b;\r\n\t}\r\n\r\n\t// returns vector B or C, whichever is in the closest direction compared to A\r\n\tpublic static Vector3 FindCloserVector( Vector3 a, Vector3 b, Vector3 c )\r\n\t{\r\n\t\t// Normalize B and C\r\n\t\tb = b.Normal;\r\n\t\tc = c.Normal;\r\n\r\n\t\t// Compute dot products\r\n\t\tfloat dotProductB = Vector3.Dot( a, b );\r\n\t\tfloat dotProductC = Vector3.Dot( a, c );\r\n\r\n\t\t// Determine which dot product is larger\r\n\t\treturn dotProductB \u003E dotProductC ? b : c;\r\n\t}\r\n\r\n\tpublic static GameObject FindChild( this Component component, string name )\r\n\t{\r\n\t\treturn component.GameObject.Children.Where( x =\u003E x.Name == name ).FirstOrDefault();\r\n\t}\r\n\r\n\tpublic static Color GetRandomColor( float total = 1.5f )\r\n\t{\r\n\t\tfloat r = Game.Random.Float( 0f, 1f );\r\n\t\ttotal = Math.Max( total - r, 0f );\r\n\t\tfloat g = MathF.Min( Game.Random.Float( 0f, 1f ), total );\r\n\t\ttotal = Math.Max( total - g, 0f );\r\n\t\tfloat b = MathF.Min( Game.Random.Float( 0f, 1f ), total );\r\n\r\n\t\treturn new Color( r, g, b );\r\n\t}\r\n\r\n\tpublic static T ReadJsonCustom\u003CT\u003E( this BaseFileSystem fs, string filename, T defaultValue = default( T ) )\r\n\t{\r\n\t\tstring text = fs.ReadAllText( filename );\r\n\t\tif ( string.IsNullOrWhiteSpace( text ) )\r\n\t\t{\r\n\t\t\treturn defaultValue;\r\n\t\t}\r\n\r\n\t\tJsonSerializerOptions options = new JsonSerializerOptions\r\n\t\t{\r\n\t\t\tReadCommentHandling = JsonCommentHandling.Skip,\r\n\t\t\tPropertyNameCaseInsensitive = true,\r\n\t\t\tAllowTrailingCommas = true,\r\n\t\t\tConverters = { new System.Text.Json.Serialization.JsonStringEnumConverter() },\r\n\t\t};\r\n\t\treturn JsonSerializer.Deserialize\u003CT\u003E( text, options );\r\n\t}\r\n\r\n\tpublic const float Deg2Rad = MathF.PI / 180f;\r\n\tpublic const float Rad2Deg = 360f / (MathF.PI * 2f);\r\n\r\n\tpublic static Vector2 RotateVector( Vector2 v, float degrees )\r\n\t{\r\n\t\tvar rads = Deg2Rad * degrees;\r\n\t\tvar ca = MathF.Cos( rads );\r\n\t\tvar sa = MathF.Sin( rads );\r\n\r\n\t\treturn new Vector2( ca * v.x - sa * v.y, sa * v.x \u002B ca * v.y );\r\n\t}\r\n\r\n\tpublic static Vector2 RotatePointAround( Vector2 p, Vector2 anchor, float degrees )\r\n\t{\r\n\t\tvar offset = p - anchor;\r\n\t\tvar newVec = RotateVector( offset, degrees );\r\n\t\treturn anchor \u002B newVec;\r\n\t}\r\n\r\n\tpublic static Vector2 DegreesToVector( float degrees )\r\n\t{\r\n\t\tvar rads = Deg2Rad * degrees;\r\n\t\treturn new Vector2( MathF.Cos( rads ), MathF.Sin( rads ) );\r\n\t}\r\n\r\n\tpublic static float VectorToDegrees( Vector2 vec )\r\n\t{\r\n\t\tfloat radians = (float)Math.Atan2( vec.y, vec.x );\r\n\t\tfloat degrees = radians * (180f / (float)Math.PI);\r\n\t\treturn degrees;\r\n\t}\r\n\r\n\tpublic static Vector2 GetPerpendicularVector( Vector2 vec )\r\n\t{\r\n\t\treturn new Vector2( -vec.y, vec.x );\r\n\t}\r\n\r\n\tpublic static int GetDistance( int x, int y )\r\n\t{\r\n\t\treturn (int)Math.Round( Math.Sqrt( x * x \u002B y * y ) );\r\n\t}\r\n\r\n\tpublic static Vector2 GetRandomVector()\r\n\t{\r\n\t\treturn DegreesToVector( Game.Random.Float( 0f, 360f ) );\r\n\t}\r\n\r\n\tpublic static float FastSin( float input )\r\n\t{\r\n\t\t// wrap input angle to -PI..PI\r\n\t\twhile ( input \u003C -3.14159265f )\r\n\t\t\tinput \u002B= 6.28318531f;\r\n\t\twhile ( input \u003E 3.14159265f )\r\n\t\t\tinput -= 6.28318531f;\r\n\r\n\t\treturn 1.27323954f * input \u002B 0.405284735f * (input \u003C 0f ? 1f : -1f) * input * input;\r\n\t}\r\n\r\n\tpublic static float DynamicEaseTo( float current, float goal, float factorPercent, float dt, float referenceFrameRate = 60f )\r\n\t{\r\n\t\tif ( float.IsPositiveInfinity( dt ) )\r\n\t\t\treturn goal;\r\n\r\n\t\treturn current \u002B (goal - current) * (1f - MathF.Pow( 1f - MathX.Clamp( factorPercent, 0f, 1f ), dt * referenceFrameRate ));\r\n\t}\r\n\r\n\tpublic static Vector2 DynamicEaseTo( Vector2 current, Vector2 goal, float factorPercent, float dt, float referenceFrameRate = 60f )\r\n\t{\r\n\t\tif ( float.IsPositiveInfinity( dt ) )\r\n\t\t\treturn goal;\r\n\t\tvar diff = goal - current;\r\n\r\n\t\treturn current \u002B diff * (1f - MathF.Pow( 1f - MathX.Clamp( factorPercent, 0f, 1f ), dt * referenceFrameRate ));\r\n\t}\r\n\r\n\tpublic static Vector3 DynamicEaseTo( Vector3 current, Vector3 goal, float factorPercent, float dt, float referenceFrameRate = 60f )\r\n\t{\r\n\t\tif ( float.IsPositiveInfinity( dt ) )\r\n\t\t\treturn goal;\r\n\t\tvar diff = goal - current;\r\n\r\n\t\treturn current \u002B diff * (1f - MathF.Pow( 1f - MathX.Clamp( factorPercent, 0f, 1f ), dt * referenceFrameRate ));\r\n\t}\r\n\r\n\tpublic static Rotation DynamicEaseTo( Rotation currentRot, Rotation goalRot, float factorPercent, float dt, float referenceFrameRate = 60f )\r\n\t{\r\n\t\tif ( float.IsPositiveInfinity( dt ) )\r\n\t\t\treturn goalRot;\r\n\r\n\t\tVector3 current = currentRot.Angles().AsVector3();\r\n\t\tVector3 goal = goalRot.Angles().AsVector3();\r\n\r\n\t\tvar diff = goal - current;\r\n\r\n\t\tvar output = current \u002B diff * (1f - MathF.Pow( 1f - MathX.Clamp( factorPercent, 0f, 1f ), dt * referenceFrameRate ));\r\n\t\treturn Rotation.From( new Angles( output ) );\r\n\t}\r\n\r\n\tpublic static float EaseUnclamped( float value, EasingType easingType )\r\n\t{\r\n\t\tswitch ( easingType )\r\n\t\t{\r\n\t\t\tcase EasingType.SineIn: return SineIn( value );\r\n\t\t\tcase EasingType.SineOut: return SineOut( value );\r\n\t\t\tcase EasingType.SineInOut: return SineInOut( value );\r\n\r\n\t\t\tcase EasingType.QuadIn: return QuadIn( value );\r\n\t\t\tcase EasingType.QuadOut: return QuadOut( value );\r\n\t\t\tcase EasingType.QuadInOut: return QuadInOut( value );\r\n\r\n\t\t\tcase EasingType.CubicIn: return CubicIn( value );\r\n\t\t\tcase EasingType.CubicOut: return CubicOut( value );\r\n\t\t\tcase EasingType.CubicInOut: return CubicInOut( value );\r\n\r\n\t\t\tcase EasingType.QuartIn: return QuartIn( value );\r\n\t\t\tcase EasingType.QuartOut: return QuartOut( value );\r\n\t\t\tcase EasingType.QuartInOut: return QuartInOut( value );\r\n\r\n\t\t\tcase EasingType.QuintIn: return QuintIn( value );\r\n\t\t\tcase EasingType.QuintOut: return QuintOut( value );\r\n\t\t\tcase EasingType.QuintInOut: return QuintInOut( value );\r\n\r\n\t\t\tcase EasingType.ExpoIn: return ExpoIn( value );\r\n\t\t\tcase EasingType.ExpoOut: return ExpoOut( value );\r\n\t\t\tcase EasingType.ExpoInOut: return ExpoInOut( value );\r\n\r\n\t\t\tcase EasingType.ExtremeIn: return ExtremeIn( value );\r\n\t\t\tcase EasingType.ExtremeOut: return ExtremeOut( value );\r\n\t\t\tcase EasingType.ExtremeInOut: return ExtremeInOut( value );\r\n\r\n\t\t\tcase EasingType.ElasticIn: return ElasticIn( value );\r\n\t\t\tcase EasingType.ElasticOut: return ElasticOut( value );\r\n\t\t\tcase EasingType.ElasticInOut: return ElasticInOut( value );\r\n\r\n\t\t\tcase EasingType.ElasticSoftIn: return ElasticSoftIn( value );\r\n\t\t\tcase EasingType.ElasticSoftOut: return ElasticSoftOut( value );\r\n\t\t\tcase EasingType.ElasticSoftInOut: return ElasticSoftInOut( value );\r\n\r\n\t\t\tcase EasingType.BackIn: return BackIn( value );\r\n\t\t\tcase EasingType.BackOut: return BackOut( value );\r\n\t\t\tcase EasingType.BackInOut: return BackInOut( value );\r\n\r\n\t\t\tcase EasingType.BounceIn: return BounceIn( value );\r\n\t\t\tcase EasingType.BounceOut: return BounceOut( value );\r\n\t\t\tcase EasingType.BounceInOut: return BounceInOut( value );\r\n\t\t\tdefault: return value;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic static float Map( float value, float inputMin, float inputMax, float outputMin, float outputMax, EasingType easingType = EasingType.Linear, bool clamp = true )\r\n\t{\r\n\t\tif ( inputMin.Equals( inputMax ) || outputMin.Equals( outputMax ) )\r\n\t\t\treturn outputMin;\r\n\r\n\t\t//            if(inputMin.Equals(inputMax) || outputMin.Equals(outputMax))\r\n\t\t//                return outputMax;\r\n\r\n\t\tif ( clamp )\r\n\t\t{\r\n\t\t\t// clamp input\r\n\t\t\tif ( inputMax \u003E inputMin )\r\n\t\t\t{\r\n\t\t\t\tif ( value \u003C inputMin ) value = inputMin;\r\n\t\t\t\telse if ( value \u003E inputMax ) value = inputMax;\r\n\t\t\t}\r\n\t\t\telse if ( inputMax \u003C inputMin )\r\n\t\t\t{\r\n\t\t\t\tif ( value \u003E inputMin ) value = inputMin;\r\n\t\t\t\telse if ( value \u003C inputMax ) value = inputMax;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar ratio = EaseUnclamped( (value - inputMin) / (inputMax - inputMin), easingType );\r\n\r\n\t\tvar outVal = outputMin \u002B ratio * (outputMax - outputMin);\r\n\r\n\t\t//            // clamp output\r\n\t\t//            if(outputMax \u003C outputMin) {\r\n\t\t//                if(outVal \u003C outputMax) outVal = outputMax;\r\n\t\t//                else if(outVal \u003E outputMin) outVal = outputMin;\r\n\t\t//            } else {\r\n\t\t//                if(outVal \u003E outputMax) outVal = outputMax;\r\n\t\t//                else if(outVal \u003C outputMin) outVal = outputMin;\r\n\t\t//            }\r\n\r\n\t\treturn outVal;\r\n\t}\r\n\r\n\tpublic static float MapReturn( float value, float inputMin, float inputMax, float outputMin, float outputMax, EasingType easingType = EasingType.Linear )\r\n\t{\r\n\t\tvar halfway = inputMin \u002B (inputMax - inputMin) * 0.5f;\r\n\t\tif ( value \u003C halfway ) return Map( value, inputMin, halfway, outputMin, outputMax, easingType );\r\n\t\telse return Map( value, halfway, inputMax, outputMax, outputMin, GetOppositeEasingType( easingType ) );\r\n\t}\r\n\r\n\tpublic static float EasePercent( float percent, EasingType easingType )\r\n\t{\r\n\t\treturn Map( percent, 0f, 1f, 0f, 1f, easingType );\r\n\t}\r\n\r\n\tpublic static EasingType GetOppositeEasingType( EasingType easingType )\r\n\t{\r\n\t\tvar opposite = EasingType.Linear;\r\n\t\tswitch ( easingType )\r\n\t\t{\r\n\t\t\tcase EasingType.SineIn: opposite = EasingType.SineOut; break;\r\n\t\t\tcase EasingType.SineOut: opposite = EasingType.SineIn; break;\r\n\t\t\tcase EasingType.SineInOut: opposite = EasingType.SineInOut; break;\r\n\r\n\t\t\tcase EasingType.QuadIn: opposite = EasingType.QuadOut; break;\r\n\t\t\tcase EasingType.QuadOut: opposite = EasingType.QuadIn; break;\r\n\t\t\tcase EasingType.QuadInOut: opposite = EasingType.QuadInOut; break;\r\n\r\n\t\t\tcase EasingType.CubicIn: opposite = EasingType.CubicOut; break;\r\n\t\t\tcase EasingType.CubicOut: opposite = EasingType.CubicIn; break;\r\n\t\t\tcase EasingType.CubicInOut: opposite = EasingType.CubicInOut; break;\r\n\r\n\t\t\tcase EasingType.QuartIn: opposite = EasingType.QuartOut; break;\r\n\t\t\tcase EasingType.QuartOut: opposite = EasingType.QuartIn; break;\r\n\t\t\tcase EasingType.QuartInOut: opposite = EasingType.QuartInOut; break;\r\n\r\n\t\t\tcase EasingType.QuintIn: opposite = EasingType.QuintOut; break;\r\n\t\t\tcase EasingType.QuintOut: opposite = EasingType.QuintIn; break;\r\n\t\t\tcase EasingType.QuintInOut: opposite = EasingType.QuintInOut; break;\r\n\r\n\t\t\tcase EasingType.ExpoIn: opposite = EasingType.ExpoOut; break;\r\n\t\t\tcase EasingType.ExpoOut: opposite = EasingType.ExpoIn; break;\r\n\t\t\tcase EasingType.ExpoInOut: opposite = EasingType.ExpoInOut; break;\r\n\r\n\t\t\tcase EasingType.ExtremeIn: opposite = EasingType.ExtremeOut; break;\r\n\t\t\tcase EasingType.ExtremeOut: opposite = EasingType.ExtremeIn; break;\r\n\t\t\tcase EasingType.ExtremeInOut: opposite = EasingType.ExtremeInOut; break;\r\n\r\n\t\t\tcase EasingType.ElasticIn: opposite = EasingType.ElasticOut; break;\r\n\t\t\tcase EasingType.ElasticOut: opposite = EasingType.ElasticIn; break;\r\n\t\t\tcase EasingType.ElasticInOut: opposite = EasingType.ElasticInOut; break;\r\n\r\n\t\t\tcase EasingType.ElasticSoftIn: opposite = EasingType.ElasticSoftOut; break;\r\n\t\t\tcase EasingType.ElasticSoftOut: opposite = EasingType.ElasticSoftIn; break;\r\n\t\t\tcase EasingType.ElasticSoftInOut: opposite = EasingType.ElasticSoftInOut; break;\r\n\r\n\t\t\tcase EasingType.BackIn: opposite = EasingType.BackOut; break;\r\n\t\t\tcase EasingType.BackOut: opposite = EasingType.BackIn; break;\r\n\t\t\tcase EasingType.BackInOut: opposite = EasingType.BackInOut; break;\r\n\r\n\t\t\tcase EasingType.BounceIn: opposite = EasingType.BounceOut; break;\r\n\t\t\tcase EasingType.BounceOut: opposite = EasingType.BounceIn; break;\r\n\t\t\tcase EasingType.BounceInOut: opposite = EasingType.BounceInOut; break;\r\n\t\t}\r\n\r\n\t\treturn opposite;\r\n\t}\r\n\r\n\tpublic static float SineIn( float t ) { return 1f - MathF.Cos( t * MathF.PI * 0.5f ); }\r\n\tpublic static float SineOut( float t ) { return MathF.Sin( t * (MathF.PI * 0.5f) ); }\r\n\tpublic static float SineInOut( float t ) { return -0.5f * (MathF.Cos( MathF.PI * t ) - 1f); }\r\n\r\n\tpublic static float QuadIn( float t ) { return t * t; }\r\n\tpublic static float QuadOut( float t ) { return t * (2f - t); }\r\n\tpublic static float QuadInOut( float t ) { return t \u003C 0.5f ? 2f * t * t : -1f \u002B (4f - 2f * t) * t; }\r\n\r\n\tpublic static float CubicIn( float t ) { return t * t * t; }\r\n\tpublic static float CubicOut( float t ) { var t1 = t - 1f; return t1 * t1 * t1 \u002B 1f; }\r\n\tpublic static float CubicInOut( float t ) { return t \u003C 0.5f ? 4f * t * t * t : (t - 1f) * (2f * t - 2f) * (2f * t - 2f) \u002B 1f; }\r\n\r\n\tpublic static float QuartIn( float t ) { return t * t * t * t; }\r\n\tpublic static float QuartOut( float t ) { var t1 = t - 1f; return 1f - t1 * t1 * t1 * t1; }\r\n\tpublic static float QuartInOut( float t ) { return t \u003C 0.5f ? 4f * t * t * t : (t - 1f) * (2f * t - 2f) * (2f * t - 2f) \u002B 1f; }\r\n\r\n\tpublic static float QuintIn( float t ) { return t * t * t * t * t; }\r\n\tpublic static float QuintOut( float t ) { var t1 = t - 1f; return 1f \u002B t1 * t1 * t1 * t1 * t1; }\r\n\tpublic static float QuintInOut( float t ) { var t1 = t - 1f; return t \u003C 0.5f ? 16f * t * t * t * t * t : 1f \u002B 16f * t1 * t1 * t1 * t1 * t1; }\r\n\r\n\tpublic static float ExpoIn( float t ) { return MathF.Pow( 2f, 10f * (t - 1f) ); }\r\n\tpublic static float ExpoOut( float t ) { return 1f - MathF.Pow( 2f, -10f * t ); }\r\n\tpublic static float ExpoInOut( float t ) { return t \u003C 0.5f ? ExpoIn( t * 2f ) * 0.5f : 1f - ExpoIn( 2f - t * 2f ) * 0.5f; }\r\n\r\n\tpublic static float ExtremeIn( float t ) { return MathF.Pow( 10f, 10f * (t - 1f) ); }\r\n\tpublic static float ExtremeOut( float t ) { return 1f - MathF.Pow( 10f, -10f * t ); }\r\n\tpublic static float ExtremeInOut( float t ) { return t \u003C 0.5f ? ExtremeIn( t * 2f ) * 0.5f : 1f - ExtremeIn( 2f - t * 2f ) * 0.5f; }\r\n\r\n\tpublic static float ElasticIn( float t ) { return 1f - ElasticOut( 1f - t ); }\r\n\tpublic static float ElasticOut( float t ) { var p = 0.3f; return MathF.Pow( 2f, -10f * t ) * MathF.Sin( (t - p / 4f) * (2f * (float)Math.PI) / p ) \u002B 1f; }\r\n\tpublic static float ElasticInOut( float t ) { return t \u003C 0.5f ? ElasticIn( t * 2f ) * 0.5f : 1f - ElasticIn( 2f - t * 2f ) * 0.5f; }\r\n\r\n\tpublic static float ElasticSoftIn( float t ) { return 1f - ElasticSoftOut( 1f - t ); }\r\n\tpublic static float ElasticSoftOut( float t ) { var p = 0.5f; return MathF.Pow( 2f, -10f * t ) * MathF.Sin( (t - p / 4f) * (2f * (float)Math.PI) / p ) \u002B 1f; }\r\n\tpublic static float ElasticSoftInOut( float t ) { return t \u003C 0.5f ? ElasticSoftIn( t * 2f ) * 0.5f : 1f - ElasticSoftIn( 2f - t * 2f ) * 0.5f; }\r\n\r\n\tpublic static float BackIn( float t ) { var p = 1f; return t * t * ((p \u002B 1f) * t - p); }\r\n\tpublic static float BackOut( float t ) { var p = 1f; var scaledTime = t / 1f - 1f; return scaledTime * scaledTime * ((p \u002B 1f) * scaledTime \u002B p) \u002B 1f; }\r\n\tpublic static float BackInOut( float t )\r\n\t{\r\n\t\tvar p = 1f;\r\n\t\tvar scaledTime = t * 2f;\r\n\t\tvar scaledTime2 = scaledTime - 2f;\r\n\t\tvar s = p * 1.525f;\r\n\r\n\t\tif ( scaledTime \u003C 1f ) return 0.5f * scaledTime * scaledTime * ((s \u002B 1f) * scaledTime - s);\r\n\t\telse return 0.5f * (scaledTime2 * scaledTime2 * ((s \u002B 1f) * scaledTime2 \u002B s) \u002B 2f);\r\n\t}\r\n\r\n\tpublic static float BounceIn( float t ) { return 1f - BounceOut( 1f - t ); }\r\n\tpublic static float BounceOut( float t )\r\n\t{\r\n\t\tvar scaledTime = t / 1f;\r\n\r\n\t\tif ( scaledTime \u003C 1 / 2.75f )\r\n\t\t{\r\n\t\t\treturn 7.5625f * scaledTime * scaledTime;\r\n\t\t}\r\n\t\telse if ( scaledTime \u003C 2 / 2.75 )\r\n\t\t{\r\n\t\t\tvar scaledTime2 = scaledTime - 1.5f / 2.75f;\r\n\t\t\treturn 7.5625f * scaledTime2 * scaledTime2 \u002B 0.75f;\r\n\t\t}\r\n\t\telse if ( scaledTime \u003C 2.5 / 2.75 )\r\n\t\t{\r\n\t\t\tvar scaledTime2 = scaledTime - 2.25f / 2.75f;\r\n\t\t\treturn 7.5625f * scaledTime2 * scaledTime2 \u002B 0.9375f;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvar scaledTime2 = scaledTime - 2.625f / 2.75f;\r\n\t\t\treturn 7.5625f * scaledTime2 * scaledTime2 \u002B 0.984375f;\r\n\t\t}\r\n\t}\r\n\tpublic static float BounceInOut( float t )\r\n\t{\r\n\t\tif ( t \u003C 0.5 ) return BounceIn( t * 2f ) * 0.5f;\r\n\t\telse return BounceOut( t * 2f - 1f ) * 0.5f \u002B 0.5f;\r\n\t}\r\n\r\n\tpublic static void Shuffle\u003CT\u003E( this IList\u003CT\u003E list )\r\n\t{\r\n\t\tSystem.Random rng = new System.Random();\r\n\t\tint n = list.Count;\r\n\t\twhile ( n \u003E 1 )\r\n\t\t{\r\n\t\t\tn--;\r\n\t\t\tint k = rng.Next( n \u002B 1 );\r\n\t\t\tT value = list[k];\r\n\t\t\tlist[k] = list[n];\r\n\t\t\tlist[n] = value;\r\n\t\t}\r\n\t}\r\n\r\n\tpublic static string FirstCharToUpper( this string input ) =\u003E\r\n\t\tinput switch\r\n\t\t{\r\n\t\t\tnull =\u003E throw new ArgumentNullException( nameof( input ) ),\r\n\t\t\t\u0022\u0022 =\u003E throw new ArgumentException( $\u0022{nameof( input )} cannot be empty\u0022, nameof( input ) ),\r\n\t\t\t_ =\u003E string.Concat( input[0].ToString().ToUpper(), input.AsSpan( 1 ) )\r\n\t\t};\r\n\r\n\tpublic static string GetRandomIcon( string i0, string i1 ) { int rand = Game.Random.Int( 0, 1 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; } }\r\n\tpublic static string GetRandomIcon( string i0, string i1, string i2 ) { int rand = Game.Random.Int( 0, 2 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; case 2: return i2; } }\r\n\tpublic static string GetRandomIcon( string i0, string i1, string i2, string i3 ) { int rand = Game.Random.Int( 0, 3 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; case 2: return i2; case 3: return i3; } }\r\n\tpublic static string GetRandomIcon( string i0, string i1, string i2, string i3, string i4 ) { int rand = Game.Random.Int( 0, 4 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; case 2: return i2; case 3: return i3; case 4: return i4; } }\r\n\tpublic static string GetRandomIcon( string i0, string i1, string i2, string i3, string i4, string i5 ) { int rand = Game.Random.Int( 0, 5 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; case 2: return i2; case 3: return i3; case 4: return i4; case 5: return i5; } }\r\n\tpublic static string GetRandomIcon( string i0, string i1, string i2, string i3, string i4, string i5, string i6 ) { int rand = Game.Random.Int( 0, 6 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; case 2: return i2; case 3: return i3; case 4: return i4; case 5: return i5; case 6: return i6; } }\r\n\tpublic static string GetRandomIcon( string i0, string i1, string i2, string i3, string i4, string i5, string i6, string i7 ) { int rand = Game.Random.Int( 0, 7 ); switch ( rand ) { case 0: default: return i0; case 1: return i1; case 2: return i2; case 3: return i3; case 4: return i4; case 5: return i5; case 6: return i6; case 7: return i7; } }\r\n\r\n\r\n\tprivate class NodeInfo\u003CT\u003E\r\n\t{\r\n\t\tprivate const int MaxPoolSize = 8192;\r\n\r\n\t\tprivate static List\u003CNodeInfo\u003CT\u003E\u003E _sPool;\r\n\r\n\t\tinternal static NodeInfo\u003CT\u003E Create( T node, NodeInfo\u003CT\u003E prev = null, float costAdd = 0f )\r\n\t\t{\r\n\t\t\tNodeInfo\u003CT\u003E nodeInfo;\r\n\r\n\t\t\tif ( _sPool == null || _sPool.Count == 0 )\r\n\t\t\t{\r\n\t\t\t\tnodeInfo = new NodeInfo\u003CT\u003E();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnodeInfo = _sPool[_sPool.Count - 1];\r\n\t\t\t\t_sPool.RemoveAt( _sPool.Count - 1 );\r\n\t\t\t}\r\n\r\n\t\t\tnodeInfo.Node = node;\r\n\t\t\tnodeInfo.Prev = prev;\r\n\r\n\t\t\tif ( prev == null )\r\n\t\t\t{\r\n\t\t\t\tnodeInfo.Depth = 0;\r\n\t\t\t\tnodeInfo.Cost = 0f;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnodeInfo.Depth = prev.Depth \u002B 1;\r\n\t\t\t\tnodeInfo.Cost = prev.Cost \u002B costAdd;\r\n\t\t\t}\r\n\r\n\t\t\treturn nodeInfo;\r\n\t\t}\r\n\r\n\t\tinternal static void Pool( NodeInfo\u003CT\u003E nodeInfo )\r\n\t\t{\r\n\t\t\tif ( _sPool == null ) _sPool = new List\u003CNodeInfo\u003CT\u003E\u003E( MaxPoolSize );\r\n\t\t\tif ( _sPool.Count \u003E= MaxPoolSize ) return;\r\n\r\n\t\t\t_sPool.Add( nodeInfo );\r\n\t\t}\r\n\r\n\t\tprivate float _heuristic;\r\n\r\n\t\tpublic T Node { get; private set; }\r\n\t\tpublic NodeInfo\u003CT\u003E Prev { get; private set; }\r\n\t\tpublic int Depth { get; private set; }\r\n\t\tpublic float Cost { get; private set; }\r\n\t\tpublic float Total { get; private set; }\r\n\r\n\t\tpublic float Heuristic\r\n\t\t{\r\n\t\t\tget { return _heuristic; }\r\n\t\t\tset\r\n\t\t\t{\r\n\t\t\t\t_heuristic = value;\r\n\t\t\t\tTotal = Cost \u002B value;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// Convenience method to produce a graph connection for use when calling AStar().\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Ctypeparam name=\u0022T\u0022\u003EGraph node type.\u003C/typeparam\u003E\r\n\t/// \u003Cparam name=\u0022dest\u0022\u003EDestination node of the connection.\u003C/param\u003E\r\n\t/// \u003Cparam name=\u0022cost\u0022\u003ECost of taking the connection.\u003C/param\u003E\r\n\tpublic static AStarEdge\u003CT\u003E Edge\u003CT\u003E( T dest, float cost )\r\n\t{\r\n\t\treturn new AStarEdge\u003CT\u003E( dest, cost );\r\n\t}\r\n\r\n\tprivate static class AStarWrapper\u003CT\u003E\r\n\t\twhere T : IEquatable\u003CT\u003E\r\n\t{\r\n\t\tpublic static NodeInfo\u003CT\u003E FirstMatchOrDefault( List\u003CNodeInfo\u003CT\u003E\u003E list, T toCompare )\r\n\t\t{\r\n\t\t\tvar count = list.Count;\r\n\r\n\t\t\tfor ( var i = count - 1; i \u003E= 0; --i )\r\n\t\t\t{\r\n\t\t\t\tvar item = list[i];\r\n\t\t\t\tif ( item.Node.Equals( toCompare ) )\r\n\t\t\t\t\treturn item;\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tprivate static List\u003CNodeInfo\u003CT\u003E\u003E _sOpen;\r\n\t\tprivate static List\u003CNodeInfo\u003CT\u003E\u003E _sClosed;\r\n\r\n\t\tpublic static bool AStar( T origin, T target, List\u003CT\u003E destList,\r\n\t\t\tFunc\u003CT, IEnumerable\u003CAStarEdge\u003CT\u003E\u003E\u003E adjFunc, Func\u003CT, T, float\u003E heuristicFunc )\r\n\t\t{\r\n\t\t\tvar open = _sOpen ?? (_sOpen = new List\u003CNodeInfo\u003CT\u003E\u003E());\r\n\t\t\tvar clsd = _sClosed ?? (_sClosed = new List\u003CNodeInfo\u003CT\u003E\u003E());\r\n\r\n\t\t\topen.Clear();\r\n\t\t\tclsd.Clear();\r\n\r\n\t\t\tvar first = NodeInfo\u003CT\u003E.Create( origin );\r\n\t\t\tfirst.Heuristic = heuristicFunc( origin, target );\r\n\r\n\t\t\topen.Add( first );\r\n\r\n\t\t\ttry\r\n\t\t\t{\r\n\t\t\t\twhile ( open.Count \u003E 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tNodeInfo\u003CT\u003E cur = null;\r\n\t\t\t\t\tforeach ( var node in open )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( cur == null || node.Total \u003C cur.Total ) cur = node;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( cur.Node.Equals( target ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor ( var i = cur.Depth; i \u003E= 0; --i )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdestList.Add( cur.Node );\r\n\t\t\t\t\t\t\tcur = cur.Prev;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdestList.Reverse();\r\n\t\t\t\t\t\treturn true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\topen.Remove( cur );\r\n\t\t\t\t\tclsd.Add( cur );\r\n\r\n\t\t\t\t\tforeach ( var adj in adjFunc( cur.Node ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvar node = NodeInfo\u003CT\u003E.Create( adj.Dest, cur, adj.Cost );\r\n\t\t\t\t\t\tvar existing = FirstMatchOrDefault( clsd, adj.Dest );\r\n\r\n\t\t\t\t\t\tif ( existing != null )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( existing.Cost \u003C= node.Cost ) continue;\r\n\r\n\t\t\t\t\t\t\tclsd.Remove( existing );\r\n\t\t\t\t\t\t\tnode.Heuristic = existing.Heuristic;\r\n\r\n\t\t\t\t\t\t\tNodeInfo\u003CT\u003E.Pool( existing );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\texisting = FirstMatchOrDefault( open, adj.Dest );\r\n\r\n\t\t\t\t\t\tif ( existing != null )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( existing.Cost \u003C= node.Cost ) continue;\r\n\r\n\t\t\t\t\t\t\topen.Remove( existing );\r\n\t\t\t\t\t\t\tnode.Heuristic = existing.Heuristic;\r\n\r\n\t\t\t\t\t\t\tNodeInfo\u003CT\u003E.Pool( existing );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnode.Heuristic = heuristicFunc( node.Node, target );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\topen.Add( node );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\t\t\tfinally\r\n\t\t\t{\r\n\t\t\t\tforeach ( var nodeInfo in open )\r\n\t\t\t\t{\r\n\t\t\t\t\tNodeInfo\u003CT\u003E.Pool( nodeInfo );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tforeach ( var nodeInfo in clsd )\r\n\t\t\t\t{\r\n\t\t\t\t\tNodeInfo\u003CT\u003E.Pool( nodeInfo );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/// \u003Csummary\u003E\r\n\t/// An implementation of the AStar path finding algorithm.\r\n\t/// \u003C/summary\u003E\r\n\t/// \u003Ctypeparam name=\u0022T\u0022\u003EGraph node type.\u003C/typeparam\u003E\r\n\t/// \u003Cparam name=\u0022origin\u0022\u003ENode to start path finding from.\u003C/param\u003E\r\n\t/// \u003Cparam name=\u0022target\u0022\u003EThe goal node to reach.\u003C/param\u003E\r\n\t/// \u003Cparam name=\u0022adjFunc\u0022\u003EFunction returning the neighbouring connections for a node.\u003C/param\u003E\r\n\t/// \u003Cparam name=\u0022heuristicFunc\u0022\u003EFunction returning the estimated cost of travelling between two nodes.\u003C/param\u003E\r\n\t/// \u003Creturns\u003EA sequence of nodes representing a path if one is found, otherwise an empty array.\u003C/returns\u003E\r\n\tpublic static bool AStar\u003CT\u003E( T origin, T target, List\u003CT\u003E destPath,\r\n\t\tFunc\u003CT, IEnumerable\u003CAStarEdge\u003CT\u003E\u003E\u003E adjFunc, Func\u003CT, T, float\u003E heuristicFunc )\r\n\t\twhere T : IEquatable\u003CT\u003E\r\n\t{\r\n\t\treturn AStarWrapper\u003CT\u003E.AStar( origin, target, destPath, adjFunc, heuristicFunc );\r\n\t}\r\n}\r\n"},{"Ident":"facepunch.memory","Path":"cards/CardAnt.cs","FileName":"CardAnt.cs","PackageType":"game","CodeKind":"Game","AssetVersionId":398889,"IsPrivate":false,"Code":"using Sandbox;\r\nusing System.Threading.Tasks;\r\n\r\npublic class CardAnt : Card\r\n{\r\n\tpublic override bool IsAlive =\u003E true;\r\n\r\n\tpublic override bool ShouldHandleEvent( EventType eventType )\r\n\t{\r\n\t\treturn eventType == EventType.TurnStart \u0026\u0026 Manager.Instance.GetNumNearbyEmptyGridPositions( GridPos, adjacentOnly: false ) \u003E 0;\r\n\t}\r\n\r\n\tpublic override async Task HandleEventAsync( EventType eventType )\r\n\t{\r\n\t\tvar emptyGridPos = Manager.Instance.GetRandomNearbyGridPos( GridPos, empty: true, adjacentOnly: false );\r\n\r\n\t\tawait Task.DelayRealtime( 200 );\r\n\r\n\t\tManager.Instance.PlayCardSfx( \u0022card_move\u0022, this, volume: 1.1f, pitch: Game.Random.Float( 0.85f, 1.15f ) );\r\n\r\n\t\tawait Task.DelayRealtime( 100 );\r\n\r\n\t\tManager.Instance.RemoveCardGridPos( this );\r\n\t\tawait Manager.Instance.SetCardGridPos( this, emptyGridPos );\r\n\r\n\t\tawait Task.DelayRealtime( 300 );\r\n\r\n\t\tawait Manager.Instance.EventHappened( EventType.AfterCardsMoved );\r\n\t}\r\n}\r\n"}]}