add kick system
This commit is contained in:
+22
-4
@@ -18,6 +18,7 @@ var chain_factor: float = 0.65
|
|||||||
var stun_time: float = 0.5
|
var stun_time: float = 0.5
|
||||||
var base_scale: float = 1.0
|
var base_scale: float = 1.0
|
||||||
var wave_num: int = 1
|
var wave_num: int = 1
|
||||||
|
var damage_modifier: float = 0.75
|
||||||
|
|
||||||
var state: State = State.CHASING
|
var state: State = State.CHASING
|
||||||
var fly_vel: Vector3 = Vector3.ZERO
|
var fly_vel: Vector3 = Vector3.ZERO
|
||||||
@@ -140,14 +141,18 @@ func _fly(delta: float) -> void:
|
|||||||
hit_wall = true
|
hit_wall = true
|
||||||
break
|
break
|
||||||
elif col3d.is_in_group("enemies") and col3d != self:
|
elif col3d.is_in_group("enemies") and col3d != self:
|
||||||
var other: Node = col3d
|
var merged := KickSystem.resolve(self, col3d, fly_vel)
|
||||||
if speed_now >= 3.0 and other.get("enemy_level") == enemy_level and other.get("is_upgrading") == false and is_upgrading == false:
|
if not merged and is_instance_valid(col3d):
|
||||||
_start_merge(other)
|
|
||||||
else:
|
|
||||||
var chain_dir := col3d.global_position - global_position
|
var chain_dir := col3d.global_position - global_position
|
||||||
chain_dir.y = 0.0
|
chain_dir.y = 0.0
|
||||||
if chain_dir.length() > 0.01:
|
if chain_dir.length() > 0.01:
|
||||||
col3d.call("receive_kick", chain_dir.normalized(), speed_now * chain_factor)
|
col3d.call("receive_kick", chain_dir.normalized(), speed_now * chain_factor)
|
||||||
|
elif col3d.is_in_group("rocks"):
|
||||||
|
KickSystem.resolve(self, col3d, fly_vel)
|
||||||
|
var rock_dir := col3d.global_position - global_position
|
||||||
|
rock_dir.y = 0.0
|
||||||
|
if rock_dir.length() > 0.01:
|
||||||
|
col3d.call("receive_kick", rock_dir.normalized(), speed_now * 0.5)
|
||||||
elif col3d.is_in_group("player"):
|
elif col3d.is_in_group("player"):
|
||||||
col3d.call("take_damage", int(speed_now * 0.6))
|
col3d.call("take_damage", int(speed_now * 0.6))
|
||||||
|
|
||||||
@@ -166,6 +171,19 @@ func _stun_tick(delta: float) -> void:
|
|||||||
if stun_timer <= 0.0:
|
if stun_timer <= 0.0:
|
||||||
_enter_chase()
|
_enter_chase()
|
||||||
|
|
||||||
|
func can_merge_with(other: Node3D, collision_speed: float) -> bool:
|
||||||
|
return (collision_speed >= 3.0
|
||||||
|
and other.get("enemy_type") == enemy_type
|
||||||
|
and other.get("enemy_level") == enemy_level
|
||||||
|
and not is_upgrading
|
||||||
|
and not other.get("is_upgrading"))
|
||||||
|
|
||||||
|
func do_merge_with(other: Node3D) -> void:
|
||||||
|
_start_merge(other)
|
||||||
|
|
||||||
|
func apply_collision_damage(dmg: float) -> void:
|
||||||
|
_take_hit(int(dmg))
|
||||||
|
|
||||||
func receive_kick(direction: Vector3, force: float) -> void:
|
func receive_kick(direction: Vector3, force: float) -> void:
|
||||||
if state == State.DEAD:
|
if state == State.DEAD:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
class_name KickSystem
|
||||||
|
|
||||||
|
# Deduplication: each (A,B) pair resolved once per physics frame
|
||||||
|
static var _frame: int = -1
|
||||||
|
static var _pairs: Dictionary = {}
|
||||||
|
|
||||||
|
# Called by a flying kickable when it detects another kickable.
|
||||||
|
# Returns true if a merge happened (both objects will despawn).
|
||||||
|
static func resolve(owner: Node3D, other: Node3D, owner_vel: Vector3) -> bool:
|
||||||
|
var f := Engine.get_physics_frames()
|
||||||
|
if f != _frame:
|
||||||
|
_frame = f
|
||||||
|
_pairs.clear()
|
||||||
|
|
||||||
|
var id_lo := mini(owner.get_instance_id(), other.get_instance_id())
|
||||||
|
var id_hi := maxi(owner.get_instance_id(), other.get_instance_id())
|
||||||
|
var key := str(id_lo) + "_" + str(id_hi)
|
||||||
|
if _pairs.has(key):
|
||||||
|
return false
|
||||||
|
_pairs[key] = true
|
||||||
|
|
||||||
|
var other_vel: Vector3 = other.get("fly_vel") if other.get("fly_vel") != null else Vector3.ZERO
|
||||||
|
var speed_a := Vector2(owner_vel.x, owner_vel.z).length()
|
||||||
|
var speed_b := Vector2(other_vel.x, other_vel.z).length()
|
||||||
|
var collision_speed := speed_a + speed_b
|
||||||
|
|
||||||
|
# ── 1. Merge ──────────────────────────────────────────────────────────────
|
||||||
|
if owner.has_method("can_merge_with") and owner.call("can_merge_with", other, collision_speed):
|
||||||
|
owner.call("do_merge_with", other)
|
||||||
|
return true
|
||||||
|
|
||||||
|
# ── 2. Damage ─────────────────────────────────────────────────────────────
|
||||||
|
var mod_a: float = owner.get("damage_modifier") if owner.get("damage_modifier") != null else 0.0
|
||||||
|
var mod_b: float = other.get("damage_modifier") if other.get("damage_modifier") != null else 0.0
|
||||||
|
|
||||||
|
if is_instance_valid(other) and other.has_method("apply_collision_damage") and mod_a > 0.0:
|
||||||
|
other.call("apply_collision_damage", collision_speed * mod_a)
|
||||||
|
if is_instance_valid(owner) and owner.has_method("apply_collision_damage") and mod_b > 0.0:
|
||||||
|
owner.call("apply_collision_damage", collision_speed * mod_b)
|
||||||
|
|
||||||
|
return false
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://ddke1n1a07f8x
|
||||||
+16
-9
@@ -4,15 +4,14 @@ enum State { IDLE, FLYING }
|
|||||||
|
|
||||||
const AIR_FRICTION := 0.84
|
const AIR_FRICTION := 0.84
|
||||||
const MIN_SPEED := 0.5
|
const MIN_SPEED := 0.5
|
||||||
const DAMAGE_MULT := 0.9
|
|
||||||
const WALL_BOUNCE := 0.5
|
const WALL_BOUNCE := 0.5
|
||||||
const WALL_SELF_DMG := 0.6
|
const WALL_SELF_DMG := 0.6
|
||||||
const HIT_SELF_DMG := 0.4
|
|
||||||
|
|
||||||
var state: State = State.IDLE
|
var state: State = State.IDLE
|
||||||
var fly_vel: Vector3 = Vector3.ZERO
|
var fly_vel: Vector3 = Vector3.ZERO
|
||||||
var health: float = 60.0
|
var health: float = 60.0
|
||||||
var dead: bool = false
|
var dead: bool = false
|
||||||
|
var damage_modifier: float = 1.25
|
||||||
|
|
||||||
@onready var mesh_node: MeshInstance3D = $RockMesh
|
@onready var mesh_node: MeshInstance3D = $RockMesh
|
||||||
var rock_mat: StandardMaterial3D
|
var rock_mat: StandardMaterial3D
|
||||||
@@ -25,6 +24,12 @@ func _ready() -> void:
|
|||||||
rock_mat = mesh_node.material_override.duplicate() as StandardMaterial3D
|
rock_mat = mesh_node.material_override.duplicate() as StandardMaterial3D
|
||||||
mesh_node.material_override = rock_mat
|
mesh_node.material_override = rock_mat
|
||||||
|
|
||||||
|
func can_merge_with(_other: Node3D, _speed: float) -> bool:
|
||||||
|
return false
|
||||||
|
|
||||||
|
func apply_collision_damage(dmg: float) -> void:
|
||||||
|
_take_damage(dmg)
|
||||||
|
|
||||||
func receive_kick(direction: Vector3, force: float) -> void:
|
func receive_kick(direction: Vector3, force: float) -> void:
|
||||||
fly_vel = direction * force
|
fly_vel = direction * force
|
||||||
fly_vel.y = 0.0
|
fly_vel.y = 0.0
|
||||||
@@ -57,14 +62,16 @@ func _fly(delta: float) -> void:
|
|||||||
_take_damage(speed_now * WALL_SELF_DMG)
|
_take_damage(speed_now * WALL_SELF_DMG)
|
||||||
handled = true
|
handled = true
|
||||||
break
|
break
|
||||||
elif col3d.is_in_group("enemies"):
|
elif col3d.is_in_group("enemies") or col3d.is_in_group("rocks"):
|
||||||
var to_enemy := col3d.global_position - global_position
|
if col3d == self:
|
||||||
to_enemy.y = 0.0
|
continue
|
||||||
var dir := to_enemy.normalized() if to_enemy.length() > 0.01 else (fly_vel.normalized() if fly_vel.length() > 0.01 else Vector3.FORWARD)
|
KickSystem.resolve(self, col3d, fly_vel)
|
||||||
col3d.call("_take_hit", int(speed_now * DAMAGE_MULT))
|
if not dead and is_instance_valid(col3d):
|
||||||
col3d.call("receive_kick", dir, speed_now * 0.65)
|
var kick_dir := col3d.global_position - global_position
|
||||||
|
kick_dir.y = 0.0
|
||||||
|
if kick_dir.length() > 0.01:
|
||||||
|
col3d.call("receive_kick", kick_dir.normalized(), speed_now * 0.65)
|
||||||
fly_vel *= 0.45
|
fly_vel *= 0.45
|
||||||
_take_damage(speed_now * HIT_SELF_DMG)
|
|
||||||
handled = true
|
handled = true
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user