update
This commit is contained in:
@@ -20,6 +20,10 @@ var camera: Camera3D = null
|
||||
var scout_player: PlayerState = null
|
||||
var selected_slot := {} ## {"kind": "board"/"bench", ...}
|
||||
var hover_slot := {}
|
||||
## Reichweite der gewählten Einheit: Mitte (Arena-Feld), Radius, Farbe. Radius 0 = aus.
|
||||
var range_center := Vector2i(-1, -1)
|
||||
var range_radius := 0
|
||||
var range_color := Color(1.0, 0.7, 0.3)
|
||||
var drag_active := false
|
||||
var drag_avatar_id := -1
|
||||
var drag_world := Vector3.ZERO
|
||||
@@ -37,6 +41,10 @@ var _dying := {} ## key -> Restzeit der Sterbe-Animation
|
||||
const DEATH_TIME := 0.45
|
||||
var _shots: Array = [] ## fliegende Geschosse {"node", "from", "to", "t", "dur"}
|
||||
var shots_total := 0 ## Zähler aller Geschosse, für Tests
|
||||
var _effects: Array = [] ## Fähigkeitsformen {"node", "t", "dur", "grow"}
|
||||
var effects_total := 0
|
||||
var _ring_fx: TorusMesh
|
||||
var _disc_fx: CylinderMesh
|
||||
var _shot_mesh: SphereMesh
|
||||
var _slash_mesh: BoxMesh
|
||||
var _origin := Vector3.ZERO
|
||||
@@ -63,6 +71,16 @@ func _ready() -> void:
|
||||
_shot_mesh.rings = 4
|
||||
_slash_mesh = BoxMesh.new()
|
||||
_slash_mesh.size = Vector3(0.12, 0.12, 0.7)
|
||||
_ring_fx = TorusMesh.new()
|
||||
_ring_fx.inner_radius = 0.55
|
||||
_ring_fx.outer_radius = 0.7
|
||||
_ring_fx.ring_segments = 8
|
||||
_ring_fx.rings = 28
|
||||
_disc_fx = CylinderMesh.new()
|
||||
_disc_fx.top_radius = 0.9
|
||||
_disc_fx.bottom_radius = 0.9
|
||||
_disc_fx.height = 0.06
|
||||
_disc_fx.radial_segments = 6
|
||||
_build_tiles()
|
||||
_build_bench()
|
||||
set_process(true)
|
||||
@@ -228,6 +246,59 @@ func _process(delta: float) -> void:
|
||||
_update_tiles()
|
||||
_update_units(delta)
|
||||
_update_shots(delta)
|
||||
_update_effects(delta)
|
||||
|
||||
|
||||
## Sichtbare Fähigkeit: Tank = wachsender Schildring, Schütze = Fläche am Ziel,
|
||||
## Heiler = aufsteigender Heilring. Farbe nach Element.
|
||||
func spawn_effect(world: Vector3, target: Vector3, role: int, col: Color) -> void:
|
||||
var mi := MeshInstance3D.new()
|
||||
var m := StandardMaterial3D.new()
|
||||
m.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
|
||||
m.albedo_color = Color(col, 0.75)
|
||||
m.emission_enabled = true
|
||||
m.emission = col
|
||||
m.emission_energy_multiplier = 1.4
|
||||
mi.material_override = m
|
||||
var fx := {"node": mi, "t": 0.0, "dur": 0.45, "rise": 0.0, "grow": 1.0}
|
||||
match role:
|
||||
Data.Role.TANK:
|
||||
mi.mesh = _ring_fx
|
||||
mi.position = world + Vector3(0.0, 0.3, 0.0)
|
||||
fx["grow"] = 1.6
|
||||
Data.Role.DPS:
|
||||
mi.mesh = _disc_fx
|
||||
mi.position = target + Vector3(0.0, 0.12, 0.0)
|
||||
mi.scale = Vector3(0.3, 1.0, 0.3)
|
||||
fx["grow"] = 1.4
|
||||
fx["dur"] = 0.35
|
||||
_:
|
||||
mi.mesh = _ring_fx
|
||||
mi.position = world + Vector3(0.0, 0.1, 0.0)
|
||||
fx["rise"] = 1.2
|
||||
fx["grow"] = 1.2
|
||||
fx["dur"] = 0.6
|
||||
add_child(mi)
|
||||
effects_total += 1
|
||||
_effects.append(fx)
|
||||
|
||||
|
||||
func _update_effects(delta: float) -> void:
|
||||
var keep := []
|
||||
for fx in _effects:
|
||||
fx["t"] += delta
|
||||
var f: float = fx["t"] / fx["dur"]
|
||||
var node: MeshInstance3D = fx["node"]
|
||||
if f >= 1.0:
|
||||
node.queue_free()
|
||||
continue
|
||||
var g: float = lerpf(1.0, fx["grow"], f) if fx["grow"] >= 1.0 else 1.0
|
||||
node.scale = Vector3(g, 1.0, g) if node.mesh == _disc_fx else Vector3(g, g, g)
|
||||
node.position.y += fx["rise"] * delta
|
||||
var m: StandardMaterial3D = node.material_override
|
||||
m.albedo_color.a = 0.75 * (1.0 - f)
|
||||
keep.append(fx)
|
||||
_effects = keep
|
||||
|
||||
|
||||
## Sichtbarer Angriff: Fernkampf schickt eine Kugel, Nahkampf einen kurzen Hieb.
|
||||
@@ -276,6 +347,11 @@ func _update_tiles() -> void:
|
||||
var slot := {"kind": "board", "hex": to_board(h)}
|
||||
var col := Color(0.20, 0.23, 0.31) if own else Color(0.28, 0.18, 0.20)
|
||||
var emit := 0.0
|
||||
var in_range := range_radius > 0 and range_center.x >= 0 \
|
||||
and Hex.distance(h, range_center) <= range_radius and h != range_center
|
||||
if in_range and not drag_active:
|
||||
col = col.lerp(range_color, 0.45)
|
||||
emit = 0.22
|
||||
if own and _is_hover(slot):
|
||||
col = Color(0.42, 0.60, 0.82)
|
||||
emit = 0.40
|
||||
@@ -343,6 +419,7 @@ func _update_units(delta: float) -> void:
|
||||
"slow": u.slow_timer > 0.0 and u.slow > 0.0,
|
||||
"stun": u.stun_timer > 0.0,
|
||||
"shield": clampf(u.shield / maxf(1.0, u.max_hp), 0.0, 1.0),
|
||||
"face": world_pos(_mirror(u.target.pos, my_team)) if (u.target != null and u.target.alive) else null,
|
||||
}
|
||||
else:
|
||||
for bh in game.human.board:
|
||||
@@ -410,7 +487,23 @@ func _update_units(delta: float) -> void:
|
||||
# und sieht nicht angehoben aus.
|
||||
node.position = target
|
||||
else:
|
||||
node.position = node.position.lerp(target, clampf(delta * MOVE_LERP, 0.0, 1.0))
|
||||
var flat_from := Vector3(node.position.x, 0.0, node.position.z)
|
||||
var flat_to := Vector3(target.x, 0.0, target.z)
|
||||
var moving := flat_from.distance_to(flat_to) > 0.05
|
||||
var next := node.position.lerp(target, clampf(delta * MOVE_LERP, 0.0, 1.0))
|
||||
if moving:
|
||||
# Blick in Laufrichtung, kleines Wippen wie ein Schritt.
|
||||
var dirv := flat_to - flat_from
|
||||
node.rotation.y = lerp_angle(node.rotation.y, atan2(dirv.x, dirv.z), clampf(delta * 10.0, 0.0, 1.0))
|
||||
var body: MeshInstance3D = node.get_meta("body")
|
||||
body.position.y = body.get_meta("base_y", body.position.y) + absf(sin(Time.get_ticks_msec() / 90.0)) * 0.12
|
||||
elif d.get("face", null) != null:
|
||||
var fd: Vector3 = d["face"] - flat_to
|
||||
if fd.length() > 0.05:
|
||||
node.rotation.y = lerp_angle(node.rotation.y, atan2(fd.x, fd.z), clampf(delta * 6.0, 0.0, 1.0))
|
||||
var body2: MeshInstance3D = node.get_meta("body")
|
||||
body2.position.y = body2.get_meta("base_y", body2.position.y)
|
||||
node.position = next
|
||||
var body: MeshInstance3D = node.get_meta("body")
|
||||
var mat: StandardMaterial3D = body.material_override
|
||||
var base: Color = d["avatar"].color()
|
||||
@@ -446,8 +539,15 @@ func _update_units(delta: float) -> void:
|
||||
|
||||
|
||||
## Knoten eines Avatars, oder null. Wird von den Tests genutzt.
|
||||
## Findet auch Kampfeinheiten, die unter einem anderen Schlüssel liegen.
|
||||
func unit_node(avatar_id: int) -> Node3D:
|
||||
return _units.get("a%d" % avatar_id)
|
||||
var direct = _units.get("a%d" % avatar_id)
|
||||
if direct != null:
|
||||
return direct
|
||||
for n in _units.values():
|
||||
if n.get_meta("avatar_id", -1) == avatar_id:
|
||||
return n
|
||||
return null
|
||||
|
||||
|
||||
## Für das Overlay: Arena-Feld so spiegeln, wie das Brett gezeichnet wird.
|
||||
@@ -555,8 +655,10 @@ func _make_unit(a: Avatar, side: int) -> Node3D:
|
||||
sph.rings = 10
|
||||
body.mesh = sph
|
||||
body.position.y = 0.55
|
||||
body.set_meta("base_y", body.position.y)
|
||||
root.add_child(body)
|
||||
root.set_meta("body", body)
|
||||
root.set_meta("avatar_id", a.id)
|
||||
|
||||
_add_ornament(root, a, body.position.y)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user