diff --git a/Assets/Sounds/electricity.wav b/Assets/Sounds/electricity.wav new file mode 100644 index 0000000..a92ecf0 Binary files /dev/null and b/Assets/Sounds/electricity.wav differ diff --git a/Assets/Sounds/electricity.wav.import b/Assets/Sounds/electricity.wav.import new file mode 100644 index 0000000..1fccbd2 --- /dev/null +++ b/Assets/Sounds/electricity.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://st8qgqiygy5a" +path="res://.godot/imported/electricity.wav-4f5dd5035ad6bc81baa17eb1f0e1cf12.sample" + +[deps] + +source_file="res://Assets/Sounds/electricity.wav" +dest_files=["res://.godot/imported/electricity.wav-4f5dd5035ad6bc81baa17eb1f0e1cf12.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/Assets/Sounds/lightning.wav b/Assets/Sounds/lightning.wav new file mode 100644 index 0000000..8f7f49f Binary files /dev/null and b/Assets/Sounds/lightning.wav differ diff --git a/Assets/Sounds/lightning.wav.import b/Assets/Sounds/lightning.wav.import new file mode 100644 index 0000000..b5d713e --- /dev/null +++ b/Assets/Sounds/lightning.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://b1jmusgltouak" +path="res://.godot/imported/lightning.wav-0c79746e61bfbd3e703c768ad9b1f4a8.sample" + +[deps] + +source_file="res://Assets/Sounds/lightning.wav" +dest_files=["res://.godot/imported/lightning.wav-0c79746e61bfbd3e703c768ad9b1f4a8.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/Assets/Sprites/Characters/forsen2.ase b/Assets/Sprites/Characters/forsen2.ase index 93a1475..53e5807 100644 Binary files a/Assets/Sprites/Characters/forsen2.ase and b/Assets/Sprites/Characters/forsen2.ase differ diff --git a/Assets/Sprites/Characters/forsen2.png b/Assets/Sprites/Characters/forsen2.png index 00ed56b..0f3a27b 100644 Binary files a/Assets/Sprites/Characters/forsen2.png and b/Assets/Sprites/Characters/forsen2.png differ diff --git a/Assets/Sprites/Particles/cast-effect.ase b/Assets/Sprites/Particles/cast-effect.ase new file mode 100644 index 0000000..a6da10a Binary files /dev/null and b/Assets/Sprites/Particles/cast-effect.ase differ diff --git a/Assets/Sprites/Particles/cast-effect.png b/Assets/Sprites/Particles/cast-effect.png new file mode 100644 index 0000000..072c532 Binary files /dev/null and b/Assets/Sprites/Particles/cast-effect.png differ diff --git a/Assets/Sprites/Particles/cast-effect.png.import b/Assets/Sprites/Particles/cast-effect.png.import new file mode 100644 index 0000000..ed66e96 --- /dev/null +++ b/Assets/Sprites/Particles/cast-effect.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bcgm3r168qjn3" +path="res://.godot/imported/cast-effect.png-a55c94ba5f88606435ca8cf19d5d4d2c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Sprites/Particles/cast-effect.png" +dest_files=["res://.godot/imported/cast-effect.png-a55c94ba5f88606435ca8cf19d5d4d2c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Assets/Sprites/Particles/lightning.ase b/Assets/Sprites/Particles/lightning.ase new file mode 100644 index 0000000..5fbb58f Binary files /dev/null and b/Assets/Sprites/Particles/lightning.ase differ diff --git a/Assets/Sprites/Particles/lightning.png b/Assets/Sprites/Particles/lightning.png new file mode 100644 index 0000000..b999458 Binary files /dev/null and b/Assets/Sprites/Particles/lightning.png differ diff --git a/Assets/Sprites/Particles/lightning.png.import b/Assets/Sprites/Particles/lightning.png.import new file mode 100644 index 0000000..96ee26b --- /dev/null +++ b/Assets/Sprites/Particles/lightning.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cf1a0uk34o343" +path="res://.godot/imported/lightning.png-63b6bcc35fd63e8582f4de50211aa0f6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Sprites/Particles/lightning.png" +dest_files=["res://.godot/imported/lightning.png-63b6bcc35fd63e8582f4de50211aa0f6.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Characters/Player.cs b/Characters/Player.cs index 5204686..0c1a7c9 100644 --- a/Characters/Player.cs +++ b/Characters/Player.cs @@ -15,6 +15,8 @@ public sealed partial class Player : Character private Node2D _effects; + private Node2D _characterEffects; + [Node] private TargetTracer _targetTracer; @@ -51,6 +53,8 @@ public sealed partial class Player : Character _effects = GetNode("%Effects"); + _characterEffects = GetNode("%CharacterEffects"); + _targetTracer = GetNode("%TargetTracer"); Stats = GetNode("Stats"); @@ -174,6 +178,14 @@ public sealed partial class Player : Character { base.DrawTarget(); DirectionMarker.GlobalRotation = DesiredTarget.Angle(); + if (Target.X < 0) + { + _characterEffects.Scale = new Vector2(-1, 1); + } + else if (Target.X > 0) + { + _characterEffects.Scale = new Vector2(1, 1); + } } public override void Footstep() diff --git a/Characters/Player.tscn b/Characters/Player.tscn index fddcdec..d696967 100644 --- a/Characters/Player.tscn +++ b/Characters/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=70 format=3 uid="uid://b2254pup8k161"] +[gd_scene load_steps=77 format=3 uid="uid://b2254pup8k161"] [ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"] [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"] @@ -28,15 +28,16 @@ [ext_resource type="AudioStream" uid="uid://cruylv4pu2fo1" path="res://Assets/Sounds/footstep-tile.wav" id="13_bxguv"] [ext_resource type="Script" path="res://BoundingBoxes/InteractionRay.cs" id="13_hs3u1"] [ext_resource type="Script" path="res://State/Character/PlayerHealState.cs" id="13_t103m"] +[ext_resource type="Script" path="res://State/Character/PlayerMaxLevelState.cs" id="14_1sn10"] [ext_resource type="PackedScene" uid="uid://p7oijq6dbvvk" path="res://Items/Weapons/DocLance.tscn" id="14_bj0lo"] [ext_resource type="Texture2D" uid="uid://d1ukste16yq6v" path="res://Assets/Sprites/Particles/player-light.png" id="15_3hahh"] [ext_resource type="Script" path="res://Utils/DamageTime.cs" id="15_4xl06"] [ext_resource type="AudioStream" uid="uid://st8qgqiygy5a" path="res://Assets/Sounds/electricity.wav" id="15_61bua"] -[ext_resource type="AudioStream" uid="uid://b1jmusgltouak" path="res://Assets/Sounds/lightning.wav" id="16_fo4my"] [ext_resource type="PackedScene" uid="uid://g7wfcubs6bdd" path="res://Items/Weapons/Railgun.tscn" id="21_n8w32"] [ext_resource type="PackedScene" uid="uid://ce0ph4wk0ylra" path="res://UI/TargetTracer.tscn" id="22_hxi53"] [ext_resource type="PackedScene" uid="uid://5y1acxl4j4n7" path="res://Items/Weapons/Pugio.tscn" id="22_mqpn7"] [ext_resource type="PackedScene" uid="uid://d1d4vg7we5rjr" path="res://Items/Weapons/Shotgun.tscn" id="22_rmciq"] +[ext_resource type="Texture2D" uid="uid://bd8l8kafb42dt" path="res://Assets/Sprites/Particles/circle.png" id="22_uefct"] [ext_resource type="Texture2D" uid="uid://bcgm3r168qjn3" path="res://Assets/Sprites/Particles/cast-effect.png" id="24_njn4h"] [ext_resource type="PackedScene" uid="uid://cgg0sfm2qeiwn" path="res://Items/Weapons/Bow.tscn" id="29_7j1fs"] @@ -251,7 +252,7 @@ tracks/2/keys = { tracks/3/type = "value" tracks/3/imported = false tracks/3/enabled = true -tracks/3/path = NodePath("%Effects/Cast:visible") +tracks/3/path = NodePath("../Sprites/CharacterEffects/Cast:visible") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/keys = { @@ -263,7 +264,7 @@ tracks/3/keys = { tracks/4/type = "value" tracks/4/imported = false tracks/4/enabled = true -tracks/4/path = NodePath("%Effects/Cast:frame") +tracks/4/path = NodePath("../Sprites/CharacterEffects/Cast:frame") tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { @@ -308,7 +309,7 @@ tracks/1/keys = { tracks/2/type = "value" tracks/2/imported = false tracks/2/enabled = true -tracks/2/path = NodePath("%Effects/Cast:visible") +tracks/2/path = NodePath("../Sprites/CharacterEffects/Cast:visible") tracks/2/interp = 1 tracks/2/loop_wrap = true tracks/2/keys = { @@ -320,7 +321,7 @@ tracks/2/keys = { tracks/3/type = "value" tracks/3/imported = false tracks/3/enabled = true -tracks/3/path = NodePath("%Effects/Cast:frame") +tracks/3/path = NodePath("../Sprites/CharacterEffects/Cast:frame") tracks/3/interp = 1 tracks/3/loop_wrap = true tracks/3/keys = { @@ -337,17 +338,33 @@ tracks/4/interp = 1 tracks/4/loop_wrap = true tracks/4/keys = { "clips": [{ -"end_offset": 2.31782, +"end_offset": 1.59007, "start_offset": 0.141459, "stream": ExtResource("15_61bua") -}, { -"end_offset": 0.0, -"start_offset": 0.0, -"stream": ExtResource("16_fo4my") }], -"times": PackedFloat32Array(0.075, 0.3) +"times": PackedFloat32Array(0.075) } tracks/4/use_blend = true +tracks/5/type = "method" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("%Animations/../StateMachine/MaxLevel") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(0.5, 0.7, 0.9), +"transitions": PackedFloat32Array(1, 1, 1), +"values": [{ +"args": [], +"method": &"Cast" +}, { +"args": [], +"method": &"Cast" +}, { +"args": [], +"method": &"Cast" +}] +} [sub_resource type="Animation" id="Animation_audkv"] resource_name = "heal" @@ -526,6 +543,32 @@ scale_max = 0.25 color = Color(0, 0, 0, 1) color_ramp = SubResource("GradientTexture1D_jb8kb") +[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_y1v5m"] +light_mode = 1 + +[sub_resource type="Gradient" id="Gradient_80g57"] +offsets = PackedFloat32Array(0.2, 1) +colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_3jlnh"] +gradient = SubResource("Gradient_80g57") + +[sub_resource type="Curve" id="Curve_xcuxr"] +_data = [Vector2(0, 0.2), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_80m7d"] +curve = SubResource("Curve_xcuxr") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_4jub4"] +particle_flag_disable_z = true +gravity = Vector3(0, 0, 0) +orbit_velocity_min = 0.0 +orbit_velocity_max = 0.0 +scale_curve = SubResource("CurveTexture_80m7d") +color = Color(1, 1, 1, 0.25098) +color_ramp = SubResource("GradientTexture1D_3jlnh") + [sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_ejdrf"] light_mode = 1 @@ -574,18 +617,20 @@ script = ExtResource("5_rgckv") InitialState = NodePath("Idle") Character = NodePath("..") -[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("MoveState", "EmoteState", "HealState", "IdleState", "Character")] +[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("MoveState", "EmoteState", "HealState", "IdleState", "MaxLevelState", "Character")] script = ExtResource("6_wkfdm") MoveState = NodePath("../Move") EmoteState = NodePath("../Emote") HealState = NodePath("../Heal") IdleState = NodePath(".") +MaxLevelState = NodePath("../MaxLevel") Character = NodePath("../..") -[node name="Move" type="Node" parent="StateMachine" node_paths=PackedStringArray("AbilityState", "IdleState", "Character")] +[node name="Move" type="Node" parent="StateMachine" node_paths=PackedStringArray("AbilityState", "IdleState", "MaxLevelState", "Character")] script = ExtResource("7_dfqd8") AbilityState = NodePath("../Roll") IdleState = NodePath("../Idle") +MaxLevelState = NodePath("../MaxLevel") Character = NodePath("../..") [node name="Dash" type="Node" parent="StateMachine" node_paths=PackedStringArray("IdleState", "Character")] @@ -612,6 +657,14 @@ HealAmount = 20.0 IdleState = NodePath("../Idle") Character = NodePath("../..") +[node name="MaxLevel" type="Node" parent="StateMachine" node_paths=PackedStringArray("IdleState", "Character")] +script = ExtResource("14_1sn10") +CastDistance = 128.0 +CastTime = 1.0 +LevelCost = 4 +IdleState = NodePath("../Idle") +Character = NodePath("../..") + [node name="Animations" type="Node" parent="."] unique_name_in_owner = true script = ExtResource("7_sdgvb") @@ -685,6 +738,16 @@ lifetime = 0.8 one_shot = true explosiveness = 1.0 +[node name="CastParticles" type="GPUParticles2D" parent="Effects"] +material = SubResource("CanvasItemMaterial_y1v5m") +position = Vector2(0, -4) +emitting = false +amount = 2 +process_material = SubResource("ParticleProcessMaterial_4jub4") +texture = ExtResource("22_uefct") +lifetime = 0.5 +one_shot = true + [node name="DeathCry" type="AudioStreamPlayer2D" parent="Effects"] stream = ExtResource("12_vd7j4") volume_db = 2.0 @@ -703,16 +766,6 @@ stream = ExtResource("12_vvem5") unique_name_in_owner = true position = Vector2(0, -4) -[node name="Cast" type="Sprite2D" parent="Effects"] -visible = false -y_sort_enabled = true -material = SubResource("CanvasItemMaterial_ejdrf") -position = Vector2(2, 1) -texture = ExtResource("24_njn4h") -centered = false -offset = Vector2(-9.5, -14) -hframes = 6 - [node name="Camera2D" parent="." instance=ExtResource("4_ym125")] zoom = Vector2(4, 4) position_smoothing_speed = 8.0 @@ -734,6 +787,19 @@ texture = ExtResource("4_5vird") offset = Vector2(0, -4) hframes = 46 +[node name="CharacterEffects" type="Node2D" parent="Sprites"] +unique_name_in_owner = true + +[node name="Cast" type="Sprite2D" parent="Sprites/CharacterEffects"] +visible = false +y_sort_enabled = true +material = SubResource("CanvasItemMaterial_ejdrf") +position = Vector2(2.5, 0.999989) +texture = ExtResource("24_njn4h") +centered = false +offset = Vector2(-9.5, -14) +hframes = 6 + [node name="CollisionShape2D" type="CollisionShape2D" parent="."] position = Vector2(0, -4) shape = SubResource("RectangleShape2D_bfqew") @@ -763,7 +829,7 @@ InventoryMap = { "equip_3": 2 } -[node name="Sword" parent="Inventory" instance=ExtResource("22_mqpn7")] +[node name="DocLance" parent="Inventory" instance=ExtResource("14_bj0lo")] visible = false [node name="Node2D" parent="Inventory" instance=ExtResource("7_4rxuv")] @@ -772,6 +838,9 @@ visible = false [node name="Bow" parent="Inventory" instance=ExtResource("29_7j1fs")] visible = false +[node name="Sword" parent="Inventory" instance=ExtResource("22_mqpn7")] +visible = false + [node name="Shotgun" parent="Inventory" instance=ExtResource("22_rmciq")] visible = false @@ -779,9 +848,6 @@ visible = false visible = false UseTime = 0.2 -[node name="DocLance" parent="Inventory" instance=ExtResource("14_bj0lo")] -visible = false - [node name="RemoteTransform2D2" type="RemoteTransform2D" parent="Inventory"] position = Vector2(0, 4) diff --git a/Entities/Lightning.cs b/Entities/Lightning.cs new file mode 100644 index 0000000..44edc53 --- /dev/null +++ b/Entities/Lightning.cs @@ -0,0 +1,36 @@ +using Godot; +using SupaLidlGame.Extensions; + +namespace SupaLidlGame.Entities; + +public partial class Lightning : Projectile +{ + private AnimationPlayer _animPlayer; + + public override void _Ready() + { + base._Ready(); + _animPlayer = GetNode("AnimationPlayer"); + _animPlayer.Play("start"); + _animPlayer.AnimationFinished += (anim) => Die(); + + var stream = GetNode("AudioStreamPlayer2D"); + stream.CloneOnWorld() + .WithPitchDeviation(0.125f) + .Play(); + + // hitbox should only be active for one frame only + //Hitbox.SetDeferred("monitoring", false); + + Hitbox.Hit += (box) => + { + if (box is BoundingBoxes.Hurtbox) + { + if (box.GetParent() is Characters.Character ch) + { + ch.Stun(3); + } + } + }; + } +} diff --git a/Entities/Lightning.tscn b/Entities/Lightning.tscn new file mode 100644 index 0000000..2970374 --- /dev/null +++ b/Entities/Lightning.tscn @@ -0,0 +1,139 @@ +[gd_scene load_steps=11 format=3 uid="uid://dwbyhbaoutu7q"] + +[ext_resource type="Texture2D" uid="uid://cf1a0uk34o343" path="res://Assets/Sprites/Particles/lightning.png" id="1_bf8ae"] +[ext_resource type="Script" path="res://Entities/Lightning.cs" id="1_worfg"] +[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="3_vlt1v"] +[ext_resource type="AudioStream" uid="uid://b1jmusgltouak" path="res://Assets/Sounds/lightning.wav" id="4_qxpk6"] +[ext_resource type="Texture2D" uid="uid://bd8l8kafb42dt" path="res://Assets/Sprites/Particles/circle.png" id="5_vkpuj"] + +[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_3bsa7"] +light_mode = 1 + +[sub_resource type="Animation" id="Animation_1c3yr"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [0] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:visible") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("PointLight2D:energy") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.5] +} + +[sub_resource type="Animation" id="Animation_jexpw"] +resource_name = "start" +length = 0.7 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3, 4, 5] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:visible") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.6), +"transitions": PackedFloat32Array(1, 1), +"update": 1, +"values": [true, false] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath("PointLight2D:energy") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 0.7), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.5, 0.0] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_g3m4l"] +_data = { +"RESET": SubResource("Animation_1c3yr"), +"start": SubResource("Animation_jexpw") +} + +[sub_resource type="CircleShape2D" id="CircleShape2D_f1v7c"] +radius = 8.0 + +[node name="Lightning" type="RigidBody2D" node_paths=PackedStringArray("Hitbox")] +collision_layer = 0 +collision_mask = 0 +script = ExtResource("1_worfg") +ProjectileName = "Lightning" +Hitbox = NodePath("Hitbox") + +[node name="Sprite2D" type="Sprite2D" parent="."] +material = SubResource("CanvasItemMaterial_3bsa7") +position = Vector2(0, 8) +texture = ExtResource("1_bf8ae") +centered = false +offset = Vector2(-16, -64) +hframes = 6 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_g3m4l") +} + +[node name="Hitbox" parent="." instance=ExtResource("3_vlt1v")] +collision_layer = 0 +Damage = 20.0 + +[node name="CollisionShape2D" parent="Hitbox" index="0"] +shape = SubResource("CircleShape2D_f1v7c") + +[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."] +stream = ExtResource("4_qxpk6") +pitch_scale = 0.8 +max_distance = 1024.0 +attenuation = 0.25 +bus = &"Effects" + +[node name="PointLight2D" type="PointLight2D" parent="."] +energy = 0.5 +texture = ExtResource("5_vkpuj") +texture_scale = 0.25 + +[editable path="Hitbox"] diff --git a/State/Character/PlayerHealState.cs b/State/Character/PlayerHealState.cs index 52fcbe2..08010c5 100644 --- a/State/Character/PlayerHealState.cs +++ b/State/Character/PlayerHealState.cs @@ -39,6 +39,7 @@ public partial class PlayerHealState : PlayerState { _player.AttackAnimation.Play("heal_cancel"); } + base.Exit(nextState); } public override CharacterState Process(double delta) diff --git a/State/Character/PlayerMaxLevelState.cs b/State/Character/PlayerMaxLevelState.cs new file mode 100644 index 0000000..32cd139 --- /dev/null +++ b/State/Character/PlayerMaxLevelState.cs @@ -0,0 +1,125 @@ +using Godot; + +namespace SupaLidlGame.State.Character; + +public partial class PlayerMaxLevelState : PlayerState +{ + [Export] + public float CastDistance { get; set; } + + [Export] + public double CastTime { get; set; } + + [Export] + public int LevelCost { get; set; } + + private double _castTimeLeft = 0; + + private static PackedScene _lightningScene; + + private GpuParticles2D _particles; + + static PlayerMaxLevelState() + { + _lightningScene = GD.Load("res://Entities/Lightning.tscn"); + } + + public override void _Ready() + { + base._Ready(); + _particles = GetNode("%Effects/CastParticles"); + } + + public override IState Enter(IState prevState) + { + _player.AttackAnimation.Play("cast"); + _player.Inventory.Visible = false; + _player.Stats.Level.Value -= LevelCost; + _castTimeLeft = CastTime; + return base.Enter(prevState); + } + + public override void Exit(IState nextState) + { + _player.Inventory.Visible = true; + base.Exit(nextState); + } + + public override CharacterState Process(double delta) + { + // return to idle when finished + if ((_castTimeLeft -= delta) <= 0) + { + return IdleState; + } + + return base.Process(delta); + } + + public override CharacterState Input(InputEvent @event) + { + return null; + } + + public void Cast() + { + Scenes.Map map = Utils.World.Instance.CurrentMap; + bool hasSpawned = false; + foreach (var node in map.Entities.GetChildren()) + { + if (node is Characters.Character ch) + { + if (ch.Faction == Character.Faction) + { + continue; + } + + if (!ch.IsAlive) + { + continue; + } + + // check if distance good and spawn lightning + var dist = Character.GlobalPosition + .DistanceTo(ch.GlobalPosition); + if (dist <= CastDistance) + { + // delay up to 150 milliseconds + double delay = GD.Randf() * 0.150; + GetTree().CreateTimer(delay).Timeout += () => + { + SpawnLightning(ch); + }; + hasSpawned = true; + } + } + } + + if (hasSpawned) + { + _player.Camera.Shake(2.0f, 0.5f); + // delay to time out + // this is a workaround where particles of amount 1 won't render + GetTree().CreateTimer(0.1f).Timeout += () => + { + _particles.Emitting = false; + }; + _particles.Emitting = true; + //_particles.SetDeferred("emitting", false); + } + } + + private void SpawnLightning(Characters.Character target) + { + if (target is null || !IsInstanceValid(target) || !target.IsAlive) + { + return; + } + var map = Utils.World.Instance.CurrentMap; + var instance = map.SpawnEntity(_lightningScene); + instance.Hitbox.Faction = Character.Faction; + instance.Hitbox.Inflictor = Character; + instance.Weapon = null; + instance.GlobalPosition = target.GlobalPosition; + } +} diff --git a/State/Character/PlayerState.cs b/State/Character/PlayerState.cs index 0ed756d..db3f57f 100644 --- a/State/Character/PlayerState.cs +++ b/State/Character/PlayerState.cs @@ -10,6 +10,9 @@ public abstract partial class PlayerState : CharacterState [Export] public PlayerIdleState IdleState { get; set; } + [Export] + public PlayerMaxLevelState MaxLevelState { get; set; } + public override CharacterState Input(InputEvent @event) { var inventory = Character.Inventory; @@ -44,6 +47,14 @@ public abstract partial class PlayerState : CharacterState // if looking at a trigger then interact with it player.InteractionRay.Trigger?.InvokeInteraction(); } + + if (@event.IsActionPressed("cast")) + { + if (_player.Stats.Level.Value >= MaxLevelState.LevelCost) + { + return MaxLevelState; + } + } } return base.Input(@event); diff --git a/project.godot b/project.godot index 994f587..c4a8c1b 100644 --- a/project.godot +++ b/project.godot @@ -187,6 +187,11 @@ ability={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"echo":false,"script":null) ] } +cast={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"echo":false,"script":null) +] +} [internationalization]