143 lines
3.9 KiB
GDScript
143 lines
3.9 KiB
GDScript
@tool
|
|
extends CharacterBody3D
|
|
class_name Mecha
|
|
|
|
const STEP_MOVE_DISPLACEMENT = 3
|
|
const RECOIL_STRENGHT = 0.5
|
|
const MOUSE_SENSIVITY = 0.01
|
|
const ZOOM_SENSIVITY = 1.
|
|
|
|
const MAX_ZOOM = 60.
|
|
const MIN_ZOOM = 15.
|
|
|
|
const MAX_HP : float = 50.
|
|
|
|
signal died
|
|
|
|
@export var hp : float = MAX_HP
|
|
|
|
@export var max_speed : float = 15.
|
|
@export var turn_speed : float = 5.
|
|
|
|
var destination := Vector2()
|
|
|
|
@onready var legs : Array[MechaLeg] = [
|
|
%Leg1,
|
|
%Leg2,
|
|
%Leg3,
|
|
%Leg4,
|
|
]
|
|
|
|
var turn_normal : Vector2 = Vector2.UP
|
|
|
|
var selected_item = 0
|
|
|
|
var current_recoil = 0.
|
|
|
|
func _ready():
|
|
for l in legs:
|
|
l.step.connect(next_leg_can_step)
|
|
|
|
|
|
func next_leg_can_step():
|
|
for l in legs:
|
|
l.can_step = false
|
|
await get_tree().create_timer(MechaLeg.STEP_DURATION / len(legs)).timeout
|
|
for l in legs:
|
|
l.can_step = true
|
|
|
|
|
|
func _process(delta):
|
|
if not Engine.is_editor_hint():
|
|
var target = calculate_target_position()
|
|
%Target.global_position = target
|
|
|
|
var target_turn = (Vector2(position.x,position.z) - Vector2(target.x,target.z)).normalized()
|
|
|
|
turn_normal = lerp(
|
|
turn_normal,
|
|
target_turn,
|
|
min(turn_speed * delta, 1.)
|
|
)
|
|
|
|
var speed = 0.
|
|
var item_used = false
|
|
|
|
for i in range(len(%Inventory.get_children())):
|
|
var item = %Inventory.get_children()[i]
|
|
if item is Weapon:
|
|
var used = item.process_fire(
|
|
delta,
|
|
self,
|
|
selected_item == i and Input.is_action_pressed("fire")
|
|
)
|
|
if used:
|
|
item_used = true
|
|
|
|
if not item_used and Input.is_action_pressed("move_to"):
|
|
speed = max_speed
|
|
|
|
var front_factor = 1 - (turn_normal - target_turn).length() / 2.
|
|
|
|
velocity = position.direction_to(target) * speed * front_factor
|
|
|
|
%Model.rotation.y = - turn_normal.angle()
|
|
|
|
# Recoil
|
|
%Model.position = Vector3(turn_normal.x, 0, turn_normal.y) * current_recoil * RECOIL_STRENGHT
|
|
current_recoil = lerp(current_recoil, 0., 0.5)
|
|
|
|
%StepTargets.position.x = lerp(
|
|
0,
|
|
-STEP_MOVE_DISPLACEMENT,
|
|
speed/max_speed
|
|
)
|
|
|
|
%Camera3D.look_at(self.position)
|
|
|
|
move_and_slide()
|
|
|
|
func calculate_target_position() -> Vector3:
|
|
var camera : Camera3D = get_viewport().get_camera_3d()
|
|
|
|
if camera:
|
|
var ray_normal := camera.project_ray_normal(get_viewport().get_mouse_position())
|
|
var ray_origin := camera.project_ray_origin(get_viewport().get_mouse_position())
|
|
|
|
var plane = Plane(Vector3.UP, 0)
|
|
var intersection = plane.intersects_ray(ray_origin, ray_normal)
|
|
if intersection:
|
|
return intersection
|
|
return global_position
|
|
|
|
func get_target_angle() -> float:
|
|
return - turn_normal.angle() + PI / 2
|
|
|
|
func get_projectile_spwan_point() -> Vector3:
|
|
return global_position + Vector3.UP * 2.
|
|
|
|
func add_recoil(recoil : = 1.):
|
|
current_recoil += recoil
|
|
|
|
func hit(damage = 1.):
|
|
hp = max(0, hp - damage)
|
|
if hp == 0:
|
|
die()
|
|
|
|
func die():
|
|
died.emit()
|
|
|
|
func _unhandled_input(event):
|
|
if Input.is_action_just_pressed("zoom_in"):
|
|
%Camera3D.position.z = max(MIN_ZOOM, %Camera3D.position.z - ZOOM_SENSIVITY)
|
|
if Input.is_action_just_pressed("zoom_out"):
|
|
%Camera3D.position.z = min(MAX_ZOOM, %Camera3D.position.z + ZOOM_SENSIVITY)
|
|
if event is InputEventMouseMotion and Input.is_action_pressed("turn_camera") and Input.mouse_mode == Input.MOUSE_MODE_VISIBLE:
|
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
|
%CameraPivot.rotation.y -= event.relative.x * MOUSE_SENSIVITY
|
|
%CameraPivot.rotation.x -= event.relative.y * MOUSE_SENSIVITY
|
|
if %CameraPivot.rotation.x > deg_to_rad(-20):
|
|
%CameraPivot.rotation.x = deg_to_rad(-20)
|
|
if %CameraPivot.rotation.x < deg_to_rad(-80):
|
|
%CameraPivot.rotation.x = deg_to_rad(-80)
|