update
This commit is contained in:
+96
-51
@@ -11,48 +11,60 @@ signal movement_finished
|
||||
|
||||
var enhanced_gridmap: Node
|
||||
var is_moving: bool = false
|
||||
var is_carried: bool = false
|
||||
var carrier: Node3D = null
|
||||
var tween: Tween
|
||||
|
||||
const SIDE_OFFSET = 0.35 # Distance from center
|
||||
|
||||
func initialize(start_pos: Vector2i, p_gridmap: Node):
|
||||
current_position = start_pos
|
||||
enhanced_gridmap = p_gridmap
|
||||
|
||||
# Snap to grid visual (Center on tile)
|
||||
# User wanted Z=1.0. X should ideally be 0.5 (center).
|
||||
# Ensuring consistent offset across Init, Sync, and Move.
|
||||
position = Vector3(current_position.x + 0.5, 1.0, current_position.y + 1.0)
|
||||
|
||||
# NO RPC HERE - Spawn RPC handles initial position sync
|
||||
# Grounded and Side-positioned
|
||||
# We use a consistent side offset (e.g. North-West corner of the tile)
|
||||
update_visual_position()
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func sync_position(pos: Vector2i):
|
||||
current_position = pos
|
||||
position = Vector3(current_position.x + 0.5, 1.0, current_position.y + 1.0)
|
||||
update_visual_position()
|
||||
|
||||
func update_visual_position():
|
||||
if is_carried: return
|
||||
|
||||
# Align with floor height (matching player's typical grounded height)
|
||||
var floor_y = 0.05
|
||||
if enhanced_gridmap and "cell_size" in enhanced_gridmap:
|
||||
floor_y = enhanced_gridmap.cell_size.y
|
||||
|
||||
# Side offset: place it near the edge
|
||||
# Using NW corner (+0.2, +0.2) instead of center (+0.5, +0.5)
|
||||
position = Vector3(current_position.x + 0.2, floor_y, current_position.y + 0.2)
|
||||
|
||||
func move_to(target_pos: Vector2i):
|
||||
if is_moving: return
|
||||
if is_moving or is_carried: return
|
||||
|
||||
# Validate
|
||||
if not enhanced_gridmap.is_position_valid(target_pos):
|
||||
return
|
||||
|
||||
# Check simple collision (optional, can be expanded)
|
||||
# For now, Tekton walks through things or we check elsewhere?
|
||||
# Controller should check validity.
|
||||
|
||||
is_moving = true
|
||||
var world_pos = Vector3(target_pos.x + 0.5, 1.0, target_pos.y + 1.0)
|
||||
|
||||
var floor_y = 0.05
|
||||
if enhanced_gridmap and "cell_size" in enhanced_gridmap:
|
||||
floor_y = enhanced_gridmap.cell_size.y
|
||||
|
||||
var target_world_pos = Vector3(target_pos.x + 0.2, floor_y, target_pos.y + 0.2)
|
||||
|
||||
# Rotation
|
||||
var dir = world_pos - position
|
||||
if dir.length_squared() > 0.1:
|
||||
var dir = target_world_pos - position
|
||||
if dir.length_squared() > 0.01:
|
||||
var target_rot = atan2(dir.x, dir.z)
|
||||
rotation.y = target_rot
|
||||
|
||||
# Tween Movement (Match Z+0.5 offset for symmetry during movement as requested)
|
||||
var final_world_pos = Vector3(target_pos.x + 0.5, 1.0, target_pos.y + 0.5)
|
||||
tween = create_tween()
|
||||
tween.tween_property(self, "position", final_world_pos, movement_speed).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
tween.tween_property(self , "position", target_world_pos, movement_speed).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
tween.tween_callback(func():
|
||||
current_position = target_pos
|
||||
is_moving = false
|
||||
@@ -69,16 +81,43 @@ func sync_movement(target_pos: Vector2i):
|
||||
|
||||
# --- COMBAT / INTERACTION ---
|
||||
|
||||
func on_hit(attacker: Node = null):
|
||||
"""Called when hit by a player attack."""
|
||||
print("[Tekton] Hit by %s!" % (attacker.name if attacker else "Unknown"))
|
||||
func on_hit(attacker: Node = null, intensity: float = 1.0):
|
||||
"""Called when hit by a player attack or knock.
|
||||
Intensity: 0.5 for throw, 1.0+ for knock."""
|
||||
print("[Tekton] Hit by %s! Intensity: %.1f" % [attacker.name if attacker else "Unknown", intensity])
|
||||
|
||||
# Visual Reaction (Flash red)
|
||||
_flash_damage()
|
||||
|
||||
# Spawn Tiles
|
||||
if is_multiplayer_authority():
|
||||
spawn_tiles_around()
|
||||
var tile_count = int(8 * intensity) # Base 8 tiles for 1.0 intensity
|
||||
spawn_tiles_around(tile_count)
|
||||
|
||||
@rpc("any_peer", "call_local")
|
||||
func set_carried(state: bool, p_carrier: Node3D = null):
|
||||
is_carried = state
|
||||
carrier = p_carrier
|
||||
is_moving = false
|
||||
if tween: tween.kill()
|
||||
|
||||
# Disable/Enable controller
|
||||
var controller = get_node_or_null("TektonController")
|
||||
if controller:
|
||||
controller.set_physics_process(not state)
|
||||
if state:
|
||||
controller.get_node("Timer").stop()
|
||||
else:
|
||||
controller.call("_start_timer")
|
||||
|
||||
if not state:
|
||||
update_visual_position()
|
||||
|
||||
func _process(delta):
|
||||
if is_carried and is_instance_valid(carrier):
|
||||
# Carry on head: offset Y by approx carrier height (e.g. 1.25)
|
||||
global_position = carrier.global_position + Vector3(0, 1.5, 0)
|
||||
rotation = carrier.rotation
|
||||
|
||||
func _flash_damage():
|
||||
var meshes = find_children("*", "MeshInstance3D", true)
|
||||
@@ -90,7 +129,7 @@ func _flash_damage():
|
||||
t.tween_property(mesh, "scale", Vector3(1.2, 1.2, 1.2), 0.1)
|
||||
t.tween_property(mesh, "scale", Vector3(1.0, 1.0, 1.0), 0.1)
|
||||
|
||||
func spawn_tiles_around():
|
||||
func spawn_tiles_around(count: int = 4):
|
||||
"""Spawns a mix of normal and special tiles in a radius."""
|
||||
if not enhanced_gridmap: return
|
||||
|
||||
@@ -98,35 +137,41 @@ func spawn_tiles_around():
|
||||
var rng = RandomNumberGenerator.new()
|
||||
rng.randomize()
|
||||
|
||||
print("[Tekton] Spawning tiles around %s" % current_position)
|
||||
print("[Tekton] Spawning %d tiles around %s" % [count, current_position])
|
||||
|
||||
for x in range(-radius, radius + 1):
|
||||
for y in range(-radius, radius + 1):
|
||||
var pos = current_position + Vector2i(x, y)
|
||||
var spawned = 0
|
||||
var attempts = 0
|
||||
while spawned < count and attempts < 25:
|
||||
attempts += 1
|
||||
var x = rng.randi_range(-radius, radius)
|
||||
var y = rng.randi_range(-radius, radius)
|
||||
|
||||
var pos = current_position + Vector2i(x, y)
|
||||
|
||||
# Don't overwrite the Tekton's own cell? Or do?
|
||||
# Maybe avoid center.
|
||||
if x == 0 and y == 0: continue
|
||||
|
||||
if enhanced_gridmap.is_position_valid(pos):
|
||||
# 50% chance to spawn something
|
||||
if rng.randf() > 0.5: continue
|
||||
|
||||
# Don't overwrite the Tekton's own cell? Or do?
|
||||
# Maybe avoid center.
|
||||
if x == 0 and y == 0: continue
|
||||
# Determine Type
|
||||
var item_id: int
|
||||
var roll = rng.randf()
|
||||
|
||||
if enhanced_gridmap.is_position_valid(pos):
|
||||
# 50% chance to spawn something
|
||||
if rng.randf() > 0.5: continue
|
||||
if roll < 0.6:
|
||||
# 60% Normal Tile (7-10)
|
||||
item_id = rng.randi_range(7, 10)
|
||||
elif roll < 0.9:
|
||||
# 30% PowerUp (11-14)
|
||||
item_id = rng.randi_range(11, 14)
|
||||
else:
|
||||
# 10% Obstacle/Trap (optional)
|
||||
item_id = -1 # Clear?
|
||||
|
||||
# Determine Type
|
||||
var item_id: int
|
||||
var roll = rng.randf()
|
||||
|
||||
if roll < 0.6:
|
||||
# 60% Normal Tile (7-10)
|
||||
item_id = rng.randi_range(7, 10)
|
||||
elif roll < 0.9:
|
||||
# 30% PowerUp (11-14)
|
||||
item_id = rng.randi_range(11, 14)
|
||||
else:
|
||||
# 10% Obstacle/Trap (optional)
|
||||
item_id = -1 # Clear?
|
||||
|
||||
if item_id != -1:
|
||||
var main = get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
main.rpc("sync_grid_item", pos.x, 1, pos.y, item_id)
|
||||
if item_id != -1:
|
||||
var main = get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
main.rpc("sync_grid_item", pos.x, 1, pos.y, item_id)
|
||||
spawned += 1
|
||||
|
||||
Reference in New Issue
Block a user