extends RigidBody const TIME_STEP : float = 0.01 const BASE_DPS : float = 300.0 const BASE_ENERGY_USAGE : float = 75.0 const BASE_ENERGY_REGEN : float = 150.0 const BASE_OVERCHARGE_DAMAGE : float = 5.0 const OOB_DAMAGE : float = 100.0 var id: int = 0 var thrust_plan : Plan = Plan.new() var weapons_plan : Plan = Plan.new() var is_ready : bool = false var running_plan : bool = false var was_running_plan : bool = false var using_full_plan : bool = false var plan_time : float = 0.0 var health : float = 100.0 var is_alive : bool = true var time_of_death : float = -1 var has_died : bool = false var is_zombie : bool = false var turn_number : int = 0 var initial_translation : Vector3 = get_translation() var initial_rotation : Vector3 = get_rotation() var initial_velocity : Vector3 = Vector3(0,0,0) var initial_rotational_velocity : Vector3 = Vector3(0,0,0) var last_translation : Vector3 = get_translation() var last_rotation : Vector3 = get_rotation() var enable_physics : bool = false var waiting_for_completion : bool = false var end_translation : Vector3 = Vector3.ZERO var end_rotation : Vector3 = Vector3.ZERO var end_linear_velocity : Vector3 = Vector3.ZERO var end_rotational_velocity : Vector3 = Vector3.ZERO var end_health : float = 100.0 var end_energy : float = 100.0 var energy : float = 100.0 var players_in_firing_arc = [] func init(): last_rotation = get_rotation() last_translation = get_translation() initial_rotation = get_rotation() initial_translation = get_translation() enable_physics = true health = 100 remote func add_thrust_element(time: float, linear_thrust : Vector3, rotational_thrust : Vector3) -> void: var element : ThrustElement = ThrustElement.new() element.time = time element.linear_thrust = linear_thrust element.rotational_thrust = rotational_thrust get_parent().get_parent().console_print("Adding thrust element with the following params: time = " + String(time) + ", lin = " + String(linear_thrust) + ", rot = " + String(rotational_thrust) + ".") thrust_plan.add_element(element) remote func add_weapons_element(time: float, firing: bool) -> void: var element : WeaponsElement = WeaponsElement.new() element.time = time element.firing = firing get_parent().get_parent().console_print("Adding weapons element with the following params: time = " + String(time) + ", firing = "+ String(firing)) weapons_plan.add_element(element) func send_all_plans() -> void: get_parent().get_parent().console_print("Sending plan...") for element in thrust_plan.current_elements: rpc("add_thrust_element", element.time, element.linear_thrust, element.rotational_thrust) for element in weapons_plan.current_elements: rpc("add_weapons_element", element.time, element.firing) get_parent().get_parent().console_print("Time of death is " + String(time_of_death) + " with health " + String(health) + ".") end_translation = self.translation end_rotation = self.rotation end_linear_velocity = self.linear_velocity end_rotational_velocity = self.angular_velocity end_health = self.health end_energy = self.energy get_parent().get_parent().console_print("Starting parameters are: linear velocity = " + String(end_linear_velocity) + ", rotational_velocity = " + String(end_rotational_velocity) + ", position = " + String(end_translation) + ", rotation = " + String(end_rotation)) rpc("r_end_turn", time_of_death, end_translation, end_rotation, end_linear_velocity, end_rotational_velocity, end_health, end_energy) turn_number += 1 thrust_plan.new_turn() weapons_plan.new_turn() remote func end_turn() -> void: get_parent().get_parent().console_print("Setting ready status to true...") is_ready = true func _get_current_plan_element(all_elements) -> PlanElement: var summed_time : float = 0.0 for element in all_elements: summed_time += element.time if summed_time > plan_time: return element return null func _get_all_thrust_elements(): var all_elements = [] for element in thrust_plan.elements: all_elements.append(element) for element in thrust_plan.current_elements: all_elements.append(element) return all_elements func _get_all_weapons_elements(): var all_elements = [] for element in weapons_plan.elements: all_elements.append(element) for element in weapons_plan.current_elements: all_elements.append(element) return all_elements func _physics_process(delta : float) -> void: if !enable_physics: return if !running_plan: if waiting_for_completion: send_all_plans() waiting_for_completion = false translation = last_translation rotation = last_rotation was_running_plan = false return if !was_running_plan: players_in_firing_arc = $GunContainer/Cone.get_overlapping_bodies() if using_full_plan: set_linear_velocity(initial_velocity) set_angular_velocity(initial_rotational_velocity) set_translation(initial_translation) set_rotation(initial_rotation) else: set_linear_velocity(end_linear_velocity) set_angular_velocity(end_rotational_velocity) set_translation(end_translation) set_rotation(end_rotation) was_running_plan = true var all_thrust_elements = _get_all_thrust_elements() var current_thrust_element : ThrustElement = _get_current_plan_element(all_thrust_elements) if current_thrust_element == null: last_translation = translation last_rotation = rotation running_plan = false return add_central_force(self.transform.basis.xform(current_thrust_element.linear_thrust)) add_torque(self.transform.basis.xform(current_thrust_element.rotational_thrust)) var all_weapons_elements = _get_all_weapons_elements() var current_weapons_element : WeaponsElement = _get_current_plan_element(all_weapons_elements) if current_weapons_element == null: running_plan = false return if current_weapons_element.firing and is_alive: fire(delta, plan_time) elif energy < 100: energy += BASE_ENERGY_REGEN * delta calculate_other_damage(delta, plan_time) plan_time += delta func fire(delta : float, time : float) -> void: var closest_enemy = null var distance_of_closest = -1 for player in players_in_firing_arc: if player.id == id or !player.is_alive: continue var player_distance : float = (player.translation - translation).length() if distance_of_closest == -1 or player_distance < distance_of_closest: closest_enemy = player distance_of_closest = player_distance energy -= delta * BASE_ENERGY_USAGE if closest_enemy != null: closest_enemy.take_damage(BASE_DPS * delta, time) func take_damage(damage : float, time : float) -> void: health -= damage if health < 0 and is_alive: self.die(time) func die(time : float) -> void: is_alive = false $GunContainer/Cone.monitoring = false if !has_died: if report_death_to_arena(): finish_game() has_died = true $CollisionShape.disabled = true time_of_death = time func play_all_plans(): get_parent().play_full_plans() func play_full_plan(): using_full_plan = true running_plan = true plan_time = 0.0 is_alive = true $GunContainer/Cone.monitoring = true $CollisionShape.disabled = false func play_last_plan(): using_full_plan = false running_plan = true plan_time = 5 * turn_number if !has_died: is_alive = true $GunContainer/Cone.monitoring = true $CollisionShape.disabled = false func calculate_plans(): if is_zombie: create_zombie_plan() if turn_number == 0: play_full_plan() else: play_last_plan() waiting_for_completion = true func calculate_other_damage(delta : float, time : float): if (translation.length_squared() > 100): take_damage(OOB_DAMAGE * delta, time) if energy < 0: take_damage(-energy * BASE_OVERCHARGE_DAMAGE * delta, time) func report_death_to_arena() -> bool: return get_parent().register_death() func finish_game() -> void: get_parent().finish_game() func _on_player_enter_firing_arc(body): players_in_firing_arc.append(body) func _on_player_exit_firing_arc(body): players_in_firing_arc.erase(body) func create_zombie_plan() -> void: add_thrust_element(5, Vector3.ZERO, Vector3.ZERO) add_weapons_element(5, false)