extends BaseProjectileWeapon class_name Mortar func _init() -> void: weapon_name = "Mortar" fire_rate = 1.5 # Slow max_ammo = 1 reload_time = 3.0 # Extremely long base_damage = 230.0 # Huge damage min_damage = 50.0 falloff_start = 0.0 max_range = 500.0 automatic = false spread_angle = 0.0 projectile_speed = 25.0 # Very slow projectile_gravity = 15.0 # Heavy drop func _build_model() -> void: position = Vector3(0.5, -0.4, -0.8) var model_scene = load("res://assets/weapons/mortar/source/scene.gltf") if model_scene: var model = model_scene.instantiate() model_root.add_child(model) model.scale = Vector3(0.0025, 0.0025, 0.0025) model.rotation_degrees.y = -90 model.position.y -= 0.2 # Aggressively strip any rogue nodes from the GLTF that could ruin the scene for node in model.find_children("*", "", true, false): if node is Light3D or node is Camera3D or node is WorldEnvironment or node is ReflectionProbe: if node is Node3D: node.visible = false node.queue_free() # Audio fire_sound = AudioStreamPlayer3D.new() fire_sound.bus = "SFX" fire_sound.stream = AudioManager.stream_for("mortar_fire", "res://assets/sounds/mortar_fire.wav") model_root.add_child(fire_sound) reload_sound = AudioStreamPlayer3D.new() reload_sound.bus = "SFX" reload_sound.stream = AudioManager.stream_for("shotgun_reload", "res://assets/sounds/shotgun_reload.wav") model_root.add_child(reload_sound) func _spawn_custom_projectile(origin: Vector3, fire_dir: Vector3) -> void: var proj = load("res://weapons/bouncing_projectile.gd").new() # Mesh var mesh_instance = MeshInstance3D.new() var p_mesh = SphereMesh.new() p_mesh.radius = 0.1 p_mesh.height = 0.2 var mat = StandardMaterial3D.new() mat.albedo_color = Color(0.1, 0.1, 0.1) # Black bomb p_mesh.material = mat mesh_instance.mesh = p_mesh proj.add_child(mesh_instance) # Logic proj.position = origin + fire_dir * 0.2 proj.logical_source = origin proj.velocity = fire_dir * projectile_speed if player: proj.velocity += fire_dir * max(0.0, player.velocity.dot(fire_dir)) proj.damage = base_damage proj.min_damage = min_damage proj.falloff_start = falloff_start proj.max_range = max_range proj.drop_gravity = projectile_gravity proj.owner_player = player # Mortar Bouncing logic proj.fuse_time = -1.0 # Don't start ticking until it bounces proj.bounce_fuse_delay = 3.0 # Explodes 3 seconds after first bounce proj.impact_detonate_time = 1.0 # If flying > 1s, explode on impact instead proj.bounciness = 0.4 # Heavy, loses momentum on bounce # Explosive stats proj.explosion_radius = 10.0 # Very large AoE proj.explosion_knockback = 60.0 # Massive knockback proj.falloff_curve = 2.0 # Steep dropoff: "Should be an instant kill in closest 50%" # (0-50% = dist<6. 6/12 = 0.5. 1.0 - 0.5^2 = 0.75 multiplier. 200 * 0.75 = 150 damage -> 1 shot kill) proj.can_self_damage = true # Can self damage proj.explosion_pitch = 0.4 # Deepest explosion get_tree().current_scene.add_child(proj)