game: add player stats and modifiers
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
extends Node2D
|
||||
|
||||
@export var default_attack_time: float = 0.5
|
||||
@export var default_damage: float = 5.0
|
||||
@export var player: Player = null
|
||||
|
||||
@onready var trigger_area: Area2D = $TriggerArea
|
||||
@onready var trigger_collision: CollisionShape2D = $TriggerArea/TriggerCollision
|
||||
@@ -10,7 +10,7 @@ extends Node2D
|
||||
@onready var path_follow_2d: PathFollow2D = $AttackPath/PathFollow2D
|
||||
@onready var attack_area: Area2D = $AttackPath/PathFollow2D/Sprite2D/AttackArea
|
||||
|
||||
var damage: float
|
||||
var base_damage: float = 5.0
|
||||
var current_target: Node2D = null
|
||||
var current_progress: float = 0.0
|
||||
var damaged_this_attack: Array = []
|
||||
@@ -19,7 +19,6 @@ var is_attacking: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
attack_path.visible = false
|
||||
damage = default_damage
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
@@ -93,5 +92,11 @@ func _on_attack_area_body_entered(body: Node2D) -> void:
|
||||
if body in damaged_this_attack:
|
||||
return
|
||||
if body.is_in_group(GlobalConst.GROUP_ENEMY) and body.is_in_group(GlobalConst.GROUP_DAMAGEABLE):
|
||||
body.take_damage(damage)
|
||||
var crit_chance = player.player_stats.get_final("crit_chance", player.modifiers)
|
||||
var damage_dealt = base_damage
|
||||
var is_crit = randf() >= 1 - crit_chance
|
||||
if is_crit:
|
||||
damage_dealt *= player.player_stats.get_final("crit_multiplier", player.modifiers)
|
||||
|
||||
body.take_damage(damage_dealt, is_crit)
|
||||
damaged_this_attack.append(body)
|
||||
|
@@ -2,21 +2,6 @@
|
||||
|
||||
[ext_resource type="Script" uid="uid://dri8n7vfnarub" path="res://scenes/damage_numbers.gd" id="1_bhj6t"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_ngvhj"]
|
||||
resource_name = "normal_damage"
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Control/Label:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(0.148651, 0.148651),
|
||||
"update": 0,
|
||||
"values": [Vector2(-9.5, -11.5), Vector2(-9, -82)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_bhj6t"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
@@ -32,6 +17,21 @@ tracks/0/keys = {
|
||||
"values": [Vector2(0, -248)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_ngvhj"]
|
||||
resource_name = "normal_damage"
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Control/Label:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(0.148651, 0.148651),
|
||||
"update": 0,
|
||||
"values": [Vector2(-9.5, -11.5), Vector2(-9, -82)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_0otjp"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_bhj6t"),
|
||||
|
@@ -34,12 +34,13 @@ func _physics_process(delta: float) -> void:
|
||||
deal_damage()
|
||||
|
||||
|
||||
func take_damage(value: float):
|
||||
func take_damage(value: float, is_crit: bool = false):
|
||||
if god_mode:
|
||||
return
|
||||
health -= value
|
||||
var dm = preload("res://scenes/damage_numbers.tscn").instantiate()
|
||||
dm.damage_taken = value
|
||||
dm.critical_damage = is_crit
|
||||
add_child(dm)
|
||||
if health <= 0:
|
||||
die()
|
||||
|
@@ -45,23 +45,6 @@ tracks/2/keys = {
|
||||
"values": [Color(1, 1, 1, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_8e3ao"]
|
||||
resource_name = "jump"
|
||||
length = 0.7
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Sprite2D:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 0), Vector2(0, -7)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_fcftc"]
|
||||
resource_name = "die"
|
||||
length = 2.0
|
||||
@@ -90,6 +73,23 @@ tracks/1/keys = {
|
||||
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_8e3ao"]
|
||||
resource_name = "jump"
|
||||
length = 0.7
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Sprite2D:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(0, 0), Vector2(0, -7)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_38ino"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_38ino"),
|
||||
|
@@ -1,15 +1,13 @@
|
||||
class_name Player
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var camera: Camera2D
|
||||
@export var main_ui: MainUI
|
||||
@export var default_movement_speed: float = 200.0
|
||||
@export var default_max_health: float = 50.0
|
||||
|
||||
@onready var sprite_2d: Sprite2D = $Sprite2D
|
||||
|
||||
var movement_speed: float
|
||||
var max_health: float
|
||||
var health: float
|
||||
var player_stats: PlayerStats = PlayerStats.new()
|
||||
var modifiers: Array[PlayerStatsModifier] = []
|
||||
var dead: bool = false
|
||||
var death_anim_done: bool = false
|
||||
var god_mode: bool = false
|
||||
@@ -17,9 +15,6 @@ var god_mode: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
camera.position = global_position
|
||||
movement_speed = default_movement_speed
|
||||
max_health = default_max_health
|
||||
health = max_health
|
||||
main_ui.player_ui.set_hp(100)
|
||||
GlobalConst.sig_debug_god_mode.connect(toggle_god_mode)
|
||||
|
||||
@@ -28,7 +23,8 @@ func _physics_process(delta: float) -> void:
|
||||
if dead:
|
||||
return
|
||||
var input_direction = Input.get_vector("left", "right", "up", "down")
|
||||
velocity = input_direction * movement_speed
|
||||
var move_speed = player_stats.get_final("move_speed", modifiers)
|
||||
velocity = input_direction * move_speed
|
||||
move_and_slide()
|
||||
|
||||
|
||||
@@ -42,14 +38,13 @@ func _process(delta: float) -> void:
|
||||
func take_damage(value: float) -> void:
|
||||
if dead or god_mode:
|
||||
return
|
||||
health -= value
|
||||
print_debug("player took damage. now has %s hp" % health)
|
||||
player_stats.current_health -= value
|
||||
var dm = preload("res://scenes/damage_numbers.tscn").instantiate()
|
||||
dm.damage_taken = value
|
||||
dm.player_damage = false
|
||||
add_child(dm)
|
||||
main_ui.player_ui.set_hp(health / max_health * 100)
|
||||
if health <= 0:
|
||||
main_ui.player_ui.set_hp((player_stats.current_health / player_stats.get_final("max_health", modifiers)) * 100)
|
||||
if player_stats.current_health <= 0:
|
||||
die()
|
||||
|
||||
|
||||
|
@@ -19,4 +19,5 @@ region_rect = Rect2(0, 104, 16, 14)
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource("CircleShape2D_3vyb7")
|
||||
|
||||
[node name="AttackSword" parent="." instance=ExtResource("3_qhqgy")]
|
||||
[node name="AttackSword" parent="." node_paths=PackedStringArray("player") instance=ExtResource("3_qhqgy")]
|
||||
player = NodePath("..")
|
||||
|
28
scenes/player_stats.gd
Normal file
28
scenes/player_stats.gd
Normal file
@@ -0,0 +1,28 @@
|
||||
class_name PlayerStats
|
||||
extends Resource
|
||||
|
||||
var max_health: float = 50.0
|
||||
var current_health: float = 50.0
|
||||
var current_xp: float = 0.0
|
||||
var current_level: int = 1
|
||||
var crit_chance: float = 0.05
|
||||
var crit_multiplier: float = 2.0
|
||||
var move_speed: float = 200.0
|
||||
var attack_damage: float = 1.0
|
||||
|
||||
func get_final(stat: String, modifiers: Array[PlayerStatsModifier]) -> Variant:
|
||||
var base_value = get(stat)
|
||||
var add = 0.0
|
||||
var mul = 1.0
|
||||
for mod in modifiers:
|
||||
if mod.stat_name == stat:
|
||||
if mod.type == PlayerStatsModifier.ModifierType.ADDITIVE:
|
||||
add += mod.value
|
||||
if mod.type == PlayerStatsModifier.ModifierType.ADDITIVE:
|
||||
mul *= mod.value
|
||||
if mod.type == PlayerStatsModifier.ModifierType.ABSOLUTE:
|
||||
return mod.value
|
||||
return (base_value + add) * mul
|
||||
|
||||
func xp_required_for_level() -> float:
|
||||
return 100 * (100*(1.5**(current_level-1)))
|
1
scenes/player_stats.gd.uid
Normal file
1
scenes/player_stats.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bcr7dywiutax7
|
8
scenes/player_stats_modifier.gd
Normal file
8
scenes/player_stats_modifier.gd
Normal file
@@ -0,0 +1,8 @@
|
||||
class_name PlayerStatsModifier
|
||||
extends Resource
|
||||
|
||||
enum ModifierType { ADDITIVE, MULTIPLICATIVE, ABSOLUTE }
|
||||
|
||||
var stat_name: String
|
||||
var value: Variant
|
||||
var type: ModifierType = ModifierType.ADDITIVE
|
1
scenes/player_stats_modifier.gd.uid
Normal file
1
scenes/player_stats_modifier.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://d3nkb530haufx
|
Reference in New Issue
Block a user