[agent:claude-cli] feat(mobs): shark pursuit 15u + dégâts -20HP + knockback, fish school fuite boost, drops requin(dent)/méduse(gelée), recettes Amulette T2 + Lampe Portable
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
extends CharacterBody3D
|
||||
|
||||
signal attacked_player(damage: float)
|
||||
signal attacked_player(damage: float, knockback_dir: Vector3)
|
||||
|
||||
@export var max_health: float = 50.0
|
||||
@export var damage: float = 15.0
|
||||
@export var detection_radius: float = 12.0
|
||||
@export var damage: float = 20.0
|
||||
@export var detection_radius: float = 15.0 # chase trigger distance (15 units)
|
||||
@export var move_speed: float = 4.0
|
||||
@export var chase_speed: float = 7.0
|
||||
@export var knockback_force: float = 14.0
|
||||
|
||||
enum State { PATROL, CHASE, ATTACK }
|
||||
|
||||
@@ -153,7 +154,13 @@ func _physics_process(delta: float) -> void:
|
||||
|
||||
State.ATTACK:
|
||||
if is_instance_valid(_player) and _attack_cooldown <= 0.0:
|
||||
attacked_player.emit(damage)
|
||||
var kb_dir: Vector3 = (_player.global_position - global_position).normalized()
|
||||
attacked_player.emit(damage, kb_dir)
|
||||
# Apply knockback directly on player
|
||||
if _player.has_method("apply_knockback"):
|
||||
_player.call("apply_knockback", kb_dir * knockback_force)
|
||||
elif "velocity" in _player:
|
||||
_player.velocity += kb_dir * knockback_force
|
||||
_attack_cooldown = 2.0
|
||||
if player_dist > 3.0:
|
||||
_state = State.CHASE
|
||||
@@ -186,4 +193,26 @@ func _do_patrol(delta: float) -> void:
|
||||
func take_damage(dmg: float) -> void:
|
||||
health -= dmg
|
||||
if health <= 0.0:
|
||||
_drop_loot()
|
||||
queue_free()
|
||||
|
||||
|
||||
func _drop_loot() -> void:
|
||||
# Give shark tooth to nearby player inventory
|
||||
if not is_instance_valid(_player):
|
||||
return
|
||||
var dist: float = global_position.distance_to(_player.global_position)
|
||||
if dist > 12.0:
|
||||
return
|
||||
var main: Node = get_tree().get_first_node_in_group("main")
|
||||
if main == null or main.get("inventory") == null:
|
||||
return
|
||||
# Drop 1-2 shark teeth
|
||||
var count: int = randi_range(1, 2)
|
||||
main.inventory.add_item(107, count)
|
||||
# Visual popup
|
||||
if main.has_method("_spawn_xp_popup"):
|
||||
main.call("_spawn_xp_popup", 0, global_position)
|
||||
var pp: Node = get_node_or_null("/root/PlayerProgress")
|
||||
if pp != null:
|
||||
pp.award(15, "requin", global_position)
|
||||
|
||||
Reference in New Issue
Block a user