Files
zombie-fps/scripts/grenade_explosion.gd
T

62 lines
2.1 KiB
GDScript

extends Node3D
## Original Half-Life fireball, 15 frames at 15 FPS, additive camera-facing quad.
## A PNG atlas avoids the native GoldSrc importer in Web exports.
const ATLAS = preload("res://assets/effects/explosion/zerogxplode_atlas.png")
const FRAME_COUNT := 15
const FPS := 15.0
const DURATION := FRAME_COUNT / FPS
const SIZE := 3.2
var elapsed := 0.0
var frame_index := 0
var fireball: MeshInstance3D
var material: StandardMaterial3D
func _ready() -> void:
name = "GrenadeExplosion"
material = StandardMaterial3D.new()
material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
material.blend_mode = BaseMaterial3D.BLEND_MODE_ADD
material.billboard_mode = BaseMaterial3D.BILLBOARD_ENABLED
material.cull_mode = BaseMaterial3D.CULL_DISABLED
material.albedo_texture = ATLAS
material.texture_filter = BaseMaterial3D.TEXTURE_FILTER_LINEAR
material.texture_repeat = false
# Two-pixel black gutters prevent adjacent frames bleeding under filtering.
material.uv1_scale = Vector3(64.0 / 340.0, 64.0 / 204.0, 1)
fireball = MeshInstance3D.new()
fireball.name = "Fireball"
fireball.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
var quad := QuadMesh.new()
quad.size = Vector2(SIZE, SIZE)
quad.material = material
fireball.mesh = quad
# Raise the fireball, but leave the damage origin at the physical impact.
fireball.position.y = 0.8
add_child(fireball)
_set_frame(0)
var light := OmniLight3D.new()
light.name = "Flash"
light.light_color = Color(1, 0.45, 0.08)
light.light_energy = 8
light.omni_range = 10
light.shadow_enabled = false
add_child(light)
create_tween().tween_property(light, "light_energy", 0.0, 0.3)
# Keep the node alive for the original explosion sound to finish.
get_tree().create_timer(4).timeout.connect(queue_free)
func _process(delta: float) -> void:
elapsed += delta
if elapsed >= DURATION:
fireball.hide()
set_process(false)
return
_set_frame(mini(int(elapsed * FPS), FRAME_COUNT - 1))
func _set_frame(index: int) -> void:
frame_index = index
material.uv1_offset = Vector3(
(float(index % 5) * 68 + 2) / 340.0,
(float(index / 5) * 68 + 2) / 204.0, 0)