diff --git a/Assets/Sounds/bow-draw.wav b/Assets/Sounds/bow-draw.wav new file mode 100644 index 0000000..f63d324 Binary files /dev/null and b/Assets/Sounds/bow-draw.wav differ diff --git a/Assets/Sounds/bow-draw.wav.import b/Assets/Sounds/bow-draw.wav.import new file mode 100644 index 0000000..ebfc307 --- /dev/null +++ b/Assets/Sounds/bow-draw.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://bkekgj4gu7fw4" +path="res://.godot/imported/bow-draw.wav-ee71f46d06974ee4e5189d4b26502070.sample" + +[deps] + +source_file="res://Assets/Sounds/bow-draw.wav" +dest_files=["res://.godot/imported/bow-draw.wav-ee71f46d06974ee4e5189d4b26502070.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/bow-release.wav b/Assets/Sounds/bow-release.wav new file mode 100644 index 0000000..2d89e29 Binary files /dev/null and b/Assets/Sounds/bow-release.wav differ diff --git a/Assets/Sounds/bow-release.wav.import b/Assets/Sounds/bow-release.wav.import new file mode 100644 index 0000000..50aeda6 --- /dev/null +++ b/Assets/Sounds/bow-release.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cwy4giq8eod5g" +path="res://.godot/imported/bow-release.wav-d35b52831a4c6f71b205857c7b22db33.sample" + +[deps] + +source_file="res://Assets/Sounds/bow-release.wav" +dest_files=["res://.godot/imported/bow-release.wav-d35b52831a4c6f71b205857c7b22db33.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/Items/bow-and-arrow.ase b/Assets/Sprites/Items/bow-and-arrow.ase new file mode 100644 index 0000000..c32c470 Binary files /dev/null and b/Assets/Sprites/Items/bow-and-arrow.ase differ diff --git a/Assets/Sprites/Items/bow-and-arrow.png b/Assets/Sprites/Items/bow-and-arrow.png new file mode 100644 index 0000000..0d5df4a Binary files /dev/null and b/Assets/Sprites/Items/bow-and-arrow.png differ diff --git a/Assets/Sprites/Items/bow-and-arrow.png.import b/Assets/Sprites/Items/bow-and-arrow.png.import new file mode 100644 index 0000000..0c2dce9 --- /dev/null +++ b/Assets/Sprites/Items/bow-and-arrow.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dam6aigkw8xs" +path="res://.godot/imported/bow-and-arrow.png-60392c320abf41d03c424138c789f873.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Sprites/Items/bow-and-arrow.png" +dest_files=["res://.godot/imported/bow-and-arrow.png-60392c320abf41d03c424138c789f873.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/Misc/arrow.ase b/Assets/Sprites/Misc/arrow.ase new file mode 100644 index 0000000..d5f3272 Binary files /dev/null and b/Assets/Sprites/Misc/arrow.ase differ diff --git a/Assets/Sprites/Misc/arrow.png b/Assets/Sprites/Misc/arrow.png new file mode 100644 index 0000000..7aca505 Binary files /dev/null and b/Assets/Sprites/Misc/arrow.png differ diff --git a/Assets/Sprites/Misc/arrow.png.import b/Assets/Sprites/Misc/arrow.png.import new file mode 100644 index 0000000..81f230d --- /dev/null +++ b/Assets/Sprites/Misc/arrow.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://blr4xbgysdyto" +path="res://.godot/imported/arrow.png-6bb20391966d951f9ad648e44b1019b9.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Sprites/Misc/arrow.png" +dest_files=["res://.godot/imported/arrow.png-6bb20391966d951f9ad648e44b1019b9.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.tscn b/Characters/Player.tscn index 6d1c27c..947fcde 100644 --- a/Characters/Player.tscn +++ b/Characters/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=64 format=3 uid="uid://b2254pup8k161"] +[gd_scene load_steps=65 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"] @@ -35,6 +35,7 @@ [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="PackedScene" uid="uid://cgg0sfm2qeiwn" path="res://Items/Weapons/Bow.tscn" id="29_7j1fs"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_h78y7"] shader = ExtResource("2_ngsgt") @@ -645,16 +646,22 @@ InventoryMap = { } [node name="Sword" parent="Inventory" instance=ExtResource("22_mqpn7")] +visible = false [node name="Node2D" parent="Inventory" instance=ExtResource("7_4rxuv")] visible = false +[node name="Bow" parent="Inventory" instance=ExtResource("29_7j1fs")] + [node name="Shotgun" parent="Inventory" instance=ExtResource("22_rmciq")] +visible = false [node name="Railgun" parent="Inventory" instance=ExtResource("21_n8w32")] +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/Arrow.tscn b/Entities/Arrow.tscn new file mode 100644 index 0000000..92572ff --- /dev/null +++ b/Entities/Arrow.tscn @@ -0,0 +1,57 @@ +[gd_scene load_steps=9 format=3 uid="uid://cjiftn2suskla"] + +[ext_resource type="Texture2D" uid="uid://blr4xbgysdyto" path="res://Assets/Sprites/Misc/arrow.png" id="1_0im1r"] +[ext_resource type="Script" path="res://Entities/Projectile.cs" id="1_8ijcc"] +[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="3_f4lib"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_m22ef"] +radius = 3.0 + +[sub_resource type="Gradient" id="Gradient_uqfn8"] +offsets = PackedFloat32Array(0, 0.1, 0.9) +colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_te0n4"] +gradient = SubResource("Gradient_uqfn8") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_yg5po"] +particle_flag_disable_z = true +direction = Vector3(-1, 0, 0) +gravity = Vector3(0, 0, 0) +initial_velocity_min = 4.0 +initial_velocity_max = 8.0 +orbit_velocity_min = 0.0 +orbit_velocity_max = 0.0 +scale_min = 2.0 +scale_max = 2.0 +color_ramp = SubResource("GradientTexture1D_te0n4") + +[sub_resource type="CanvasTexture" id="CanvasTexture_ggksk"] + +[node name="Arrow" type="RigidBody2D" node_paths=PackedStringArray("Hitbox")] +script = ExtResource("1_8ijcc") +ProjectileName = "Arrow" +Speed = 256.0 +Hitbox = NodePath("Hitbox") +Lifetime = 3.0 + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(-11, -2) +texture = ExtResource("1_0im1r") +centered = false + +[node name="Hitbox" parent="." instance=ExtResource("3_f4lib")] + +[node name="CollisionShape2D" parent="Hitbox" index="0"] +position = Vector2(0, -0.5) +shape = SubResource("CircleShape2D_m22ef") + +[node name="GPUParticles2D" type="GPUParticles2D" parent="."] +position = Vector2(-9, 0) +amount = 16 +process_material = SubResource("ParticleProcessMaterial_yg5po") +texture = SubResource("CanvasTexture_ggksk") +lifetime = 0.8 +fixed_fps = 12 + +[editable path="Hitbox"] diff --git a/Items/Weapons/Bow.tscn b/Items/Weapons/Bow.tscn new file mode 100644 index 0000000..2d96336 --- /dev/null +++ b/Items/Weapons/Bow.tscn @@ -0,0 +1,170 @@ +[gd_scene load_steps=15 format=3 uid="uid://cgg0sfm2qeiwn"] + +[ext_resource type="Texture2D" uid="uid://dam6aigkw8xs" path="res://Assets/Sprites/Items/bow-and-arrow.png" id="1_1ghvv"] +[ext_resource type="Script" path="res://Items/Weapons/ProjectileSpawner.cs" id="1_76bur"] +[ext_resource type="PackedScene" uid="uid://cjiftn2suskla" path="res://Entities/Arrow.tscn" id="2_mvw0j"] +[ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="3_pg4gy"] +[ext_resource type="Script" path="res://State/Weapon/RangedIdleState.cs" id="3_uxif8"] +[ext_resource type="Script" path="res://State/Weapon/RangedFireState.cs" id="4_moo4d"] +[ext_resource type="Script" path="res://State/Weapon/RangedChargeState.cs" id="5_k8y6f"] +[ext_resource type="AudioStream" uid="uid://bkekgj4gu7fw4" path="res://Assets/Sounds/bow-draw.wav" id="7_t07v0"] +[ext_resource type="AudioStream" uid="uid://cwy4giq8eod5g" path="res://Assets/Sounds/bow-release.wav" id="9_v051g"] + +[sub_resource type="Animation" id="Animation_h0fti"] +resource_name = "RESET" +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Anchor/Sprite2D:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [0] +} + +[sub_resource type="Animation" id="Animation_8qr8x"] +resource_name = "charge" +length = 0.5 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Anchor/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, 0.9), +"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1), +"update": 1, +"values": [0, 1, 2, 3, 4, 6, 5] +} +tracks/1/type = "audio" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("AudioStreamPlayer2D") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"clips": [{ +"end_offset": 0.0, +"start_offset": 0.0, +"stream": ExtResource("7_t07v0") +}], +"times": PackedFloat32Array(0) +} +tracks/1/use_blend = true + +[sub_resource type="Animation" id="Animation_bejvb"] +resource_name = "fire" +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Anchor/Sprite2D:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [7] +} +tracks/1/type = "audio" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("AudioStreamPlayer2D") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"clips": [{ +"end_offset": 0.0, +"start_offset": 0.03, +"stream": ExtResource("9_v051g") +}], +"times": PackedFloat32Array(0) +} +tracks/1/use_blend = true + +[sub_resource type="Animation" id="Animation_riv7t"] +resource_name = "idle" +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Anchor/Sprite2D:frame") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [0] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_5vx8d"] +_data = { +"RESET": SubResource("Animation_h0fti"), +"charge": SubResource("Animation_8qr8x"), +"fire": SubResource("Animation_bejvb"), +"idle": SubResource("Animation_riv7t") +} + +[node name="Bow" type="Node2D" node_paths=PackedStringArray("StateMachine")] +y_sort_enabled = true +script = ExtResource("1_76bur") +Projectile = ExtResource("2_mvw0j") +ChargeTime = 0.5 +StateMachine = NodePath("StateMachine") +Damage = 20.0 +UseTime = 0.5 +Knockback = 64.0 +InitialVelocity = 200.0 +ShouldFreezeAngleOnUse = false +PlayerLevelGain = 1.0 + +[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState")] +script = ExtResource("3_pg4gy") +InitialState = NodePath("Idle") +UsedItemStates = Array[NodePath]([NodePath("Charge"), NodePath("Fire")]) +DeusedItemStates = Array[NodePath]([NodePath("Idle")]) + +[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("FireState", "Weapon", "AnimationPlayer")] +script = ExtResource("3_uxif8") +FireState = NodePath("../Charge") +Weapon = NodePath("../..") +AnimationPlayer = NodePath("../../AnimationPlayer") +AnimationKey = "idle" + +[node name="Charge" type="Node" parent="StateMachine" node_paths=PackedStringArray("Weapon", "FireState", "IdleState", "AnimationPlayer")] +script = ExtResource("5_k8y6f") +Weapon = NodePath("../..") +FireState = NodePath("../Fire") +IdleState = NodePath("../Idle") +AnimationPlayer = NodePath("../../AnimationPlayer") +AnimationKey = "charge" + +[node name="Fire" type="Node" parent="StateMachine" node_paths=PackedStringArray("Weapon", "IdleState", "AnimationPlayer")] +script = ExtResource("4_moo4d") +Weapon = NodePath("../..") +IdleState = NodePath("../Idle") +AnimationPlayer = NodePath("../../AnimationPlayer") +AnimationKey = "fire" + +[node name="Anchor" type="Node2D" parent="."] +y_sort_enabled = true +position = Vector2(0, 4) + +[node name="Sprite2D" type="Sprite2D" parent="Anchor"] +y_sort_enabled = true +position = Vector2(4, 2) +texture = ExtResource("1_1ghvv") +centered = false +offset = Vector2(-8, -16) +hframes = 8 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +libraries = { +"": SubResource("AnimationLibrary_5vx8d") +} + +[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."] diff --git a/Items/Weapons/ProjectileSpawner.cs b/Items/Weapons/ProjectileSpawner.cs index 61e3b9d..591d97a 100644 --- a/Items/Weapons/ProjectileSpawner.cs +++ b/Items/Weapons/ProjectileSpawner.cs @@ -24,7 +24,7 @@ public partial class ProjectileSpawner : Ranged [Export] public float ProjectileAngleDeviation { get; set; } - private void SpawnProjectile(Scenes.Map map, Vector2 direction) + private void SpawnProjectile(Scenes.Map map, Vector2 direction, float v = 1) { var projectile = map.SpawnEntity(Projectile); projectile.Hitbox.Faction = Character.Faction; @@ -33,7 +33,7 @@ public partial class ProjectileSpawner : Ranged if (ShouldOverrideVelocity) { - projectile.Speed = InitialVelocity; + projectile.Speed = InitialVelocity * v; } if (ShouldRotate) @@ -63,6 +63,11 @@ public partial class ProjectileSpawner : Ranged } public override void Attack() + { + Attack(1); + } + + public override void Attack(float velocityModifier) { Character.Inventory.EmitSignal("UsedItem", this); @@ -78,7 +83,7 @@ public partial class ProjectileSpawner : Ranged // avoid unnecessary math if only spawning 1 projectile if (ProjectileCount == 1) { - SpawnProjectile(map, target); + SpawnProjectile(map, target, velocityModifier); return; } @@ -95,7 +100,9 @@ public partial class ProjectileSpawner : Ranged for (int i = 0; i < ProjectileCount; i++) { float curDeviation = -i + maxAngleDeviations; - SpawnProjectile(map, target.Rotated(curDeviation * theta)); + SpawnProjectile(map, + target.Rotated(curDeviation * theta), + velocityModifier); } } } diff --git a/Items/Weapons/Ranged.cs b/Items/Weapons/Ranged.cs index a282e0d..659b61b 100644 --- a/Items/Weapons/Ranged.cs +++ b/Items/Weapons/Ranged.cs @@ -17,7 +17,7 @@ public abstract partial class Ranged : Weapon public State.Weapon.WeaponStateMachine StateMachine { get; set; } public override bool IsUsingPrimary => StateMachine.CurrentState - is State.Weapon.RangedFireState; + is State.Weapon.RangedFireState or State.Weapon.RangedChargeState; public bool IsChargeable => ChargeTime > 0; @@ -42,4 +42,6 @@ public abstract partial class Ranged : Weapon } public abstract void Attack(); + + public virtual void Attack(float velocityModifier) => Attack(); } diff --git a/Shaders/GodraysCompatible.gdshader b/Shaders/GodraysCompatible.gdshader new file mode 100644 index 0000000..d400b79 --- /dev/null +++ b/Shaders/GodraysCompatible.gdshader @@ -0,0 +1,57 @@ +/* + * This shader is based on the Godrays shader by pend00 + * (https://godotshaders.com/shader/god-rays/), but heavily modified to be + * compatible with both the Forward+ (Vulkan) and Compatibility (OpenGL) + * renderers. + */ + +shader_type canvas_item; + +uniform vec4 tint_color : source_color; +uniform float alpha : hint_range(0.0, 1.0) = 0.75; +uniform sampler2D noise_texture : repeat_enable; +uniform float speed : hint_range(0.0, 1.0) = 0.25; +uniform float spread = 1; +uniform float opposite_ray_mult = 1.0; +uniform float negative_intensity = 1.0; +uniform float negative_ray_speed : hint_range(0.0, 1.0) = 0; +uniform float cutoff : hint_range(0.0, 1.0) = 0; +uniform float smooth_cutoff : hint_range(0.0, 1.0) = 0; +uniform float y_cutoff : hint_range(0.0, 1.0) = 0; +uniform float y_smooth_cutoff : hint_range(0.0, 1.0) = 0; +uniform float angle : hint_range(-3.14, 3.14); + +float noise(vec2 uv) { + return texture(noise_texture, uv).r; +} + +mat2 rotate(float _angle){ + return mat2(vec2(cos(_angle), -sin(_angle)), + vec2(sin(_angle), cos(_angle))); +} + +void fragment() { + vec2 t_uv = UV * rotate(angle) / ((UV.y + spread) - (UV.y * spread)); + + vec2 ray1 = vec2(t_uv.x + sin(TIME * speed / 10.0)); + vec2 ray2 = vec2(-t_uv.x + sin(TIME * speed / 15.0)); + vec2 ray3 = vec2(t_uv.x + cos(TIME * negative_ray_speed / 10.0)); + float a; + + // if t_uv.x exceeds cut value then do not show ray (multiply by 0) + float cut = step(cutoff, t_uv.x) * step(cutoff, 1.0 - UV.x); + cut *= smoothstep(cutoff, cutoff + smooth_cutoff, t_uv.x) * + smoothstep(cutoff, cutoff + smooth_cutoff, 1.0 - t_uv.x); + float y_cut = step(y_cutoff, 1.0 - t_uv.y) * smoothstep(y_cutoff, y_cutoff + y_smooth_cutoff, 1.0 - UV.y); + ray1 *= cut; + ray2 *= cut; + ray3 *= cut; + a = cut * y_cut; + + float rays; + rays = clamp(noise(ray1) + opposite_ray_mult * noise(ray2) - negative_intensity * noise(ray3), 0.0, 1.0); + + + //shine = screen(texture(SCREEN_TEXTURE, SCREEN_UV), vec4(color)).rgb; + COLOR = vec4(vec3(1.0), rays * a) * tint_color; +} diff --git a/State/Character/CharacterState.cs b/State/Character/CharacterState.cs index 901715c..1cd0609 100644 --- a/State/Character/CharacterState.cs +++ b/State/Character/CharacterState.cs @@ -23,15 +23,16 @@ public abstract partial class CharacterState : Node, IState var item = Character.Inventory.SelectedItem; - // angle towards item use angle or offhand use angle if not used - bool targetTowards(Items.Item item) { if (item is Items.Weapon weapon) { if (weapon.IsUsing) { - Character.Target = weapon.UseDirection; + if (weapon.ShouldFreezeAngleOnUse) + { + Character.Target = weapon.UseDirection; + } return true; } } diff --git a/State/Character/PlayerHealState.cs b/State/Character/PlayerHealState.cs index f0c193c..52fcbe2 100644 --- a/State/Character/PlayerHealState.cs +++ b/State/Character/PlayerHealState.cs @@ -22,6 +22,7 @@ public partial class PlayerHealState : PlayerState } _timeLeftToHeal = TimeToHeal; GD.Print("Heal anim"); + _player.MovementAnimation.Stop(); _player.AttackAnimation.Play("heal_start"); _player.AttackAnimation.Queue("heal"); _hasHealed = false; diff --git a/State/Character/PlayerIdleState.cs b/State/Character/PlayerIdleState.cs index 2769cf2..6f79b8f 100644 --- a/State/Character/PlayerIdleState.cs +++ b/State/Character/PlayerIdleState.cs @@ -36,6 +36,14 @@ public partial class PlayerIdleState : PlayerState // NOTE: more conditions may be added soon } + if (Godot.Input.IsActionPressed("ability")) + { + if (CanHeal()) + { + return HealState; + } + } + if (shouldPlayStopAnim) { _player.MovementAnimation.Play("stop"); @@ -69,7 +77,7 @@ public partial class PlayerIdleState : PlayerState if (Godot.Input.IsActionPressed("ability")) { - if (!_player.Inventory.IsUsingItem) + if (CanHeal()) { return HealState; } @@ -77,4 +85,9 @@ public partial class PlayerIdleState : PlayerState return null; } + + private bool CanHeal() + { + return !_player.Inventory.IsUsingItem && _player.Stats.Level.Value > 0; + } } diff --git a/State/Character/PlayerState.cs b/State/Character/PlayerState.cs index aea87c6..0ed756d 100644 --- a/State/Character/PlayerState.cs +++ b/State/Character/PlayerState.cs @@ -68,7 +68,7 @@ public abstract partial class PlayerState : CharacterState var isAttack1On = Godot.Input.IsActionPressed("attack1"); var isAttack2On = Godot.Input.IsActionPressed("attack2"); - if (!weapon.ShouldHideIdle || isAttack1On) + if (!weapon.ShouldHideIdle || !weapon.ShouldFreezeAngleOnUse || isAttack1On) { player.Target = player.DesiredTarget; } @@ -81,6 +81,11 @@ public abstract partial class PlayerState : CharacterState { Character.UseCurrentItemAlt(); } + + if (Godot.Input.IsActionJustReleased("attack1")) + { + Character.DeuseCurrentItem(); + } } return base.Process(delta); diff --git a/State/Weapon/RangedChargeState.cs b/State/Weapon/RangedChargeState.cs new file mode 100644 index 0000000..947aa67 --- /dev/null +++ b/State/Weapon/RangedChargeState.cs @@ -0,0 +1,65 @@ +using Godot; +using SupaLidlGame.Extensions; + +namespace SupaLidlGame.State.Weapon; + +public partial class RangedChargeState : WeaponState +{ + [Export] + public Items.Weapons.Ranged Weapon { get; set; } + + [Export] + public RangedFireState FireState { get; set; } + + [Export] + public RangedIdleState IdleState { get; set; } + + [Export] + public AnimationPlayer AnimationPlayer { get; set; } + + [Export] + public string AnimationKey { get; set; } + + private double _timeLeftToCharge = 0; + + //private double _timeLeftToOvercharge = 0; + + public override IState Enter(IState prev) + { + _timeLeftToCharge = Weapon.ChargeTime; + AnimationPlayer?.TryPlay(AnimationKey); + return null; + } + + public override WeaponState Process(double delta) + { + if (_timeLeftToCharge > 0) + { + if ((_timeLeftToCharge -= delta) < 0) + { + _timeLeftToCharge = 0; + } + } + + Weapon.UseDirection = Weapon.Character.Target; + GD.Print(Weapon.UseDirection); + + return null; + } + + public override WeaponState Deuse() + { + // fire + double progress = _timeLeftToCharge / Weapon.ChargeTime; + + if (progress > 0.5) + { + GD.Print("not enough"); + return IdleState; + } + + GD.Print("firing"); + FireState.VelocityModifier = (float)(1 - progress); + return FireState; + } +} diff --git a/State/Weapon/RangedFireState.cs b/State/Weapon/RangedFireState.cs index 6da6614..188132b 100644 --- a/State/Weapon/RangedFireState.cs +++ b/State/Weapon/RangedFireState.cs @@ -17,13 +17,15 @@ public partial class RangedFireState : WeaponState [Export] public string AnimationKey { get; set; } + public float VelocityModifier { get; set; } + private double _timeLeft = 0; public override IState Enter(IState prev) { //_timeLeft _timeLeft = Weapon.UseTime; - Weapon.Attack(); + Weapon.Attack(VelocityModifier); Weapon.UseDirection = Weapon.Character.Target; AnimationPlayer?.TryPlay(AnimationKey); return null; diff --git a/State/Weapon/RangedIdleState.cs b/State/Weapon/RangedIdleState.cs index 2b8a6da..2113aca 100644 --- a/State/Weapon/RangedIdleState.cs +++ b/State/Weapon/RangedIdleState.cs @@ -6,7 +6,7 @@ namespace SupaLidlGame.State.Weapon; public partial class RangedIdleState : WeaponState { [Export] - public RangedFireState FireState { get; set; } + public WeaponState FireState { get; set; } [Export] public Items.Weapons.Ranged Weapon { get; set; }