From d424c103f18cf621b604665954435372d84d9230 Mon Sep 17 00:00:00 2001 From: ToasterPanic Date: Sun, 17 May 2026 17:41:28 -0400 Subject: [PATCH] Projectile weapon base functionality, damage per second calculation command, rebalancing... --- addons/super_awesome_input_icons/LICENSE.md | 2 +- project.godot | 1 + scenes/dreamer.tscn | 2 +- scenes/projectiles/bullet.tscn | 17 ++++++++-- scripts/enemies/dreamer.gd | 3 +- scripts/global.gd | 28 ++++++++--------- scripts/player.gd | 27 +++++++++++++++- scripts/projectiles/bullet.gd | 35 +++++++++++++++++++++ scripts/projectiles/bullet.gd.uid | 1 + 9 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 scripts/projectiles/bullet.gd create mode 100644 scripts/projectiles/bullet.gd.uid diff --git a/addons/super_awesome_input_icons/LICENSE.md b/addons/super_awesome_input_icons/LICENSE.md index 49ce4b8..bef0351 100644 --- a/addons/super_awesome_input_icons/LICENSE.md +++ b/addons/super_awesome_input_icons/LICENSE.md @@ -4,4 +4,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/project.godot b/project.godot index 3231f64..b655cf6 100644 --- a/project.godot +++ b/project.godot @@ -135,6 +135,7 @@ limbo_console_search_history={ 3d_physics/layer_1="player" 3d_physics/layer_2="enemies" +3d_physics/layer_5="world geometry" 3d_physics/layer_9="camera" [navigation] diff --git a/scenes/dreamer.tscn b/scenes/dreamer.tscn index f01e85f..dbb77bc 100644 --- a/scenes/dreamer.tscn +++ b/scenes/dreamer.tscn @@ -8,7 +8,7 @@ size = Vector3(0.65, 1, 0.65) [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_yqjtg"] -radius = 0.15 +radius = 0.25 height = 1.0 [node name="Dreamer" type="CharacterBody3D" unique_id=272925354] diff --git a/scenes/projectiles/bullet.tscn b/scenes/projectiles/bullet.tscn index 801fd0c..3988ae0 100644 --- a/scenes/projectiles/bullet.tscn +++ b/scenes/projectiles/bullet.tscn @@ -1,15 +1,28 @@ [gd_scene format=3 uid="uid://ufm8kssdh8vx"] -[node name="Bullet" type="Node3D" unique_id=1536641450] +[ext_resource type="Script" uid="uid://bgnro2l31f3y1" path="res://scripts/projectiles/bullet.gd" id="1_yvfy2"] -[node name="MeshInstance3D" type="CSGCylinder3D" parent="." unique_id=1706082204] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yvfy2"] +transparency = 3 +alpha_hash_scale = 1.0 +alpha_antialiasing_mode = 0 +emission_enabled = true +emission = Color(1, 0.9333334, 0, 1) + +[node name="Bullet" type="Node3D" unique_id=1536641450] +script = ExtResource("1_yvfy2") + +[node name="Line" type="CSGCylinder3D" parent="." unique_id=1706082204] transform = Transform3D(4.371139e-08, -1, 8.742278e-08, -1, -4.371139e-08, 0, 3.821371e-15, -8.742278e-08, -1, 0, 0, 0) radius = 0.05 sides = 5 smooth_faces = false +material = SubResource("StandardMaterial3D_yvfy2") [node name="Hit" type="RayCast3D" parent="." unique_id=10285465] transform = Transform3D(-4.371139e-08, 1, -2.9802322e-08, 0, 2.9802322e-08, 1, 1, 4.371139e-08, -1.3027009e-15, 0, 0, 0) +exclude_parent = false target_position = Vector3(0, -500, 0) collision_mask = 19 +hit_from_inside = true debug_shape_custom_color = Color(0, 1, 0, 1) diff --git a/scripts/enemies/dreamer.gd b/scripts/enemies/dreamer.gd index b7ab16c..977b67c 100644 --- a/scripts/enemies/dreamer.gd +++ b/scripts/enemies/dreamer.gd @@ -130,7 +130,7 @@ func _physics_process(delta: float) -> void: if (player.global_position - global_position).length() < 1: state = STATE_CHARGE_ATTACK - state_timer = 1 + state_timer = 0.5 $DreamerBody/Animator.set("parameters/charge_weapon/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE) elif state == STATE_CHARGE_ATTACK: @@ -164,6 +164,7 @@ func _physics_process(delta: float) -> void: if health <= 0: if (state_timer <= 0) or is_on_floor(): state = STATE_DEAD + collision_layer = 0 elif state_timer <= 0: $DreamerBody/Animator.set("parameters/hit/blend_amount", 0.0) diff --git a/scripts/global.gd b/scripts/global.gd index 5e879d6..7886a4d 100644 --- a/scripts/global.gd +++ b/scripts/global.gd @@ -4,7 +4,7 @@ const weapons = { "basic_sword": { "combo_weapon": true, "hits_to_finish": 3, - "swing_time": 0.16, + "swing_time": 0.2, "combo_timeout": 0.35, "swing_time_combo_finish": 0.42, "damage": 15, @@ -20,20 +20,20 @@ const weapons = { "attack_swooshy": "slash", }, "basic_knife": { - "combo_weapon": true, - "hits_to_finish": 10, - "swing_time": 0.06, + "combo_weapon": false, + "hits_to_finish": 15, + "swing_time": 0.13, "combo_timeout": 0.25, "swing_time_combo_finish": 0.66, - "damage": 20, + "damage": 5, "damage_mid_combo": 5, "knockback": 2.5, "knockback_mid_combo": 0.3, "stun_time": 0.4, - "range": 1, - "width": 1, + "range": 0.6, + "width": 0.6, "attack_swooshy": "slash", "attack_swooshy_scale": Vector3(0.8, 0.6, 1), @@ -41,9 +41,9 @@ const weapons = { "basic_hammer": { "combo_weapon": true, "hits_to_finish": 2, - "swing_time": 0.6, + "swing_time": 0.45, "combo_timeout": 1, - "swing_time_combo_finish": 1, + "swing_time_combo_finish": 0.9, "damage": 35, "damage_mid_combo": 25, @@ -59,12 +59,12 @@ const weapons = { "basic_spear": { "combo_weapon": true, - "hits_to_finish": 3, - "swing_time": 0.16, + "hits_to_finish": 4, + "swing_time": 0.2, "combo_timeout": 0.35, "swing_time_combo_finish": 0.55, - "damage": 10, - "damage_mid_combo": 7, + "damage": 15, + "damage_mid_combo": 9, "knockback": 3.5, "knockback_mid_combo": 0.75, @@ -82,7 +82,7 @@ const weapons = { "max_pierces": 3, "knockback": 2.5, "recharge_time": 15, - "bullet": preload("res://scenes/projectiles/bullet.tscn"), + "projectile": preload("res://scenes/projectiles/bullet.tscn"), "attack_swooshy": "pierce", "attack_swooshy_scale": Vector3(1.5, 1, 1), diff --git a/scripts/player.gd b/scripts/player.gd index 499a1ed..e31eaee 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -13,6 +13,13 @@ var iframes = 0 var knockback_time = 0 var health = 100 +var slots = [ + { + "id": "basic_sword", + "cooldown_time": 0, + } +] + var combo_hits = 0 var combo_timer = 0 var swing_timer = 0 @@ -70,10 +77,22 @@ func set_weapon(weapon_name: String = "basic_sword") -> void: $HitCollision/Shape.shape.size = Vector3(range, 1.0, width) $HitCollision/Shape.position.x = range * -0.5 + +func dps(weapon_name: String = "basic_sword") -> void: + var damage = get_weapon_info(weapon_name, "damage") + var time = get_weapon_info(weapon_name, "swing_time") + + if get_weapon_info(weapon_name, "combo_weapon"): + var combo_damage = get_weapon_info(weapon_name, "damage_mid_combo") * get_weapon_info(weapon_name, "hits_to_finish") + time *= float(get_weapon_info(weapon_name, "hits_to_finish")) + time += float(get_weapon_info(weapon_name, "swing_time_combo_finish")) + + LimboConsole.print_line(str(damage / time)) func _ready() -> void: LimboConsole.register_command(hit_me) LimboConsole.register_command(set_weapon) + LimboConsole.register_command(dps) set_weapon(current_weapon) func _process(delta: float) -> void: @@ -246,7 +265,13 @@ func _process(delta: float) -> void: combo_hits = 0 if get_my_weapon_info("ranged_weapon"): - pass + var projectile = get_my_weapon_info("projectile").instantiate() + + game.add_child(projectile) + projectile.global_position = global_position + projectile.rotation = $HitCollision.rotation + + projectile.pow() else: for body in hits: if body == self: continue diff --git a/scripts/projectiles/bullet.gd b/scripts/projectiles/bullet.gd new file mode 100644 index 0000000..5456e4c --- /dev/null +++ b/scripts/projectiles/bullet.gd @@ -0,0 +1,35 @@ +extends Node3D + +# Called when the node enters the scene tree for the first time. +func pow() -> void: + var going = true + + while going: + $Hit.force_raycast_update() + var hit = $Hit.get_collider() + + if not hit: + print("hit nothing") + break + + if "health" in hit: + hit.health -= 100 + if "on_knockback" in hit: hit.on_knockback() + print(hit.name, hit.health) + else: + print("no health in hit: ", hit.name) + break + + $Hit.add_exception(hit) + + $Hit.force_raycast_update() + var final_point = $Hit.get_collision_point() + + $Line.position.x = -(final_point - global_position).length() / 2.0 + $Line.height = (final_point - global_position).length() + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta: float) -> void: + $Line.radius -= delta * 0.2 + + if $Line.radius <= 0.001: queue_free() diff --git a/scripts/projectiles/bullet.gd.uid b/scripts/projectiles/bullet.gd.uid new file mode 100644 index 0000000..bce20df --- /dev/null +++ b/scripts/projectiles/bullet.gd.uid @@ -0,0 +1 @@ +uid://bgnro2l31f3y1