extends KinematicBody signal equip( p_slot, p_item ) signal unequip( p_slot ) var character = null var rotation_speed_factor = 0.01 var move_speed = 2.5 var run_speed = 5.0 var max_speed = 12.0 export var gravity = -9.0 var velocity: = Vector3.ZERO var is_running = false var can_turn = false var ground_contacts = 0 var is_jump_started = false var is_jumping = false var jump_strength = 250.0 var is_falling = false var is_on_ground = true var is_readying_weapon = false var is_weapon_ready = false var can_attack = true var is_dying = false var is_dead = false var direction = Vector3.ZERO var orientation = 0.0 enum PLAYER_RELATION { neutre, friend, ennemy } export( PLAYER_RELATION ) var player_relation = PLAYER_RELATION.neutre export( String ) var creature_filename = null setget set_creature_filename func set_creature_filename( p_filename ): creature_filename = p_filename self.load_from_name( p_filename ) func _process( delta ): # Calculate a move direction vector relative to the camera # The basis stores the (right, up, -forwards) vectors of our camera. var forwards: Vector3 = $look_at.global_transform.basis.z * direction.z var right: Vector3 = $look_at.global_transform.basis.x * direction.x if forwards: right = Vector3.ZERO var move_direction: = forwards + right if move_direction.length() > 1.0: move_direction = move_direction.normalized() move_direction.y = 0 # Rotation. if (self.has_node( "creature" ) and $creature.can_turn()) or self.is_readying_weapon or self.is_weapon_ready: self.rotate_y( rotation_speed_factor * orientation ) # Movement. velocity = self.calculate_velocity(velocity, move_direction, delta) if not self.is_readying_weapon and not self.is_weapon_ready: if not self.is_jumping and not self.is_jump_started and not self.is_falling: velocity = self.move_and_slide_with_snap(velocity, Vector3.DOWN, Vector3.UP, true) else: velocity = self.move_and_slide(velocity, Vector3.UP, true) # Animation. if self.has_node( "creature" ): if self.is_dead: $creature.play( "dead_loop" ) elif self.is_dying: $creature.play( "dying", 2.0 ) elif self.is_readying_weapon: $creature.play( "1h_pistol_ready_start" ) elif self.is_weapon_ready: $creature.play( "1h_pistol_ready_loop" ) elif direction and not self.is_jump_started and not self.is_jumping and not self.is_falling: if direction.z < 0.0: if self.is_running: $creature.play( "run" , 2.0 ) else: $creature.play( "walk" ) elif direction.z > 0.0: if self.is_running: $creature.play_backwards( "run", 2.0 ) else: $creature.play_backwards( "walk" ) elif direction.x > 0.0: $creature.play( "strafe_right" ) elif direction.x < 0.0: $creature.play( "strafe_left" ) elif self.is_jump_started and not self.is_jumping: $creature.play( "jump_start" ) elif self.is_jumping or self.is_falling: if not self.is_on_ground: $creature.play( "jump_loop" ) else: $creature.play( "jump_end", 2 ) elif not self.orientation == 0.0: if self.orientation < 0.0: $creature.play( "turn_right", 2.0 ) elif self.orientation > 0.0: $creature.play( "turn_left", 2.0 ) else: $creature.play( "idle" ) func calculate_velocity( velocity_current: Vector3, move_direction: Vector3, delta: float ) -> Vector3: # var velocity_new := move_direction var velocity_new = Vector3.ZERO if not self.is_jump_started: velocity_new = move_direction if self.is_running: velocity_new *= run_speed else: velocity_new *= move_speed if velocity_new.length() > max_speed: velocity_new = velocity_new.normalized() * max_speed velocity_new.y = velocity_current.y + gravity * delta if self.is_jumping: velocity_new.y += self.jump_strength * delta self.is_jumping = false self.is_falling = true if self.is_falling: velocity_new.x *= 2.0 velocity_new.z *= 2.0 return velocity_new func load_from_name( p_name, p_emplacement = null ): var creature = Datas.Creature.new() creature.set_data( "name", p_name ) creature.load( null, p_emplacement ) if creature.get_data( "race" ) == Globals.RACE.human: if creature.get_data( "sex" ) == Globals.SEX.female: self.change_creature( "res://scenes/creatures/human/human_female.tscn" ) elif creature.get_data( "sex" ) == Globals.SEX.male: self.change_creature( "res://scenes/creatures/human/human_male.tscn" ) if $creature: $creature.load_from_name( p_name, p_emplacement ) func change_creature( new_model_path ): if $creature: var old_model = $creature self.remove_child( old_model ) old_model.queue_free() var new_model = load( new_model_path ) if new_model: new_model = new_model.instance() new_model.name = "creature" self.add_child( new_model ) new_model.connect( "animation_finished", self, "_on_creature_animation_finished" ) new_model.duplicate_meshes() func set_blend_shape( p_blend_shape_name, p_value ): $creature.set_blend_shape( p_blend_shape_name, p_value ) func _on_ground_area_body_entered(body): if not body == self: self.ground_contacts += 1 if self.ground_contacts > 0: # self.is_falling = false self.is_on_ground = true func _on_ground_area_body_exited(body): if not body == self: self.ground_contacts -= 1 if self.ground_contacts <= 0: self.is_falling = true self.is_on_ground = false func _on_creature_animation_finished(anim_name): if anim_name == "jump_start": self.is_jump_started = false self.is_jumping = true elif anim_name == "jump_end": self.is_falling = false elif anim_name == "turn_right": self.can_turn = false elif anim_name == "turn_left": self.can_turn = false elif anim_name == "1h_pistol_ready_start": self.is_readying_weapon = false self.is_weapon_ready = true elif anim_name == "dying": self.is_dying = false self.is_dead = true func set_focus( p_focus = true ): if p_focus: $focus.show() if self.player_relation == PLAYER_RELATION.neutre: $focus.get_surface_material( 0 ).albedo_color = Color.white elif self.player_relation == PLAYER_RELATION.friend: $focus.get_surface_material( 0 ).albedo_color = Color.green elif self.player_relation == PLAYER_RELATION.ennemy: $focus.get_surface_material( 0 ).albedo_color = Color.red else: $focus.hide() func get_weapons(): var weapons = [] if Datas.Equipment.SLOT.weapon_hands in $creature.slots: if $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item: weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item ) if not weapons.size() > 0: if Datas.Equipment.SLOT.weapon_hand_right in $creature.slots: if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item: weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item ) if Datas.Equipment.SLOT.weapon_hand_left in $creature.slots: if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item: weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item ) return weapons func get_main_weapon_node(): var weapon = null if Datas.Equipment.SLOT.weapon_hands in $creature.slots: if $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item: if $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children().size() > 0: weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] if not weapon and Datas.Equipment.SLOT.weapon_hand_right in $creature.slots: if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item: if $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children().size() > 0: weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] if not weapon and Datas.Equipment.SLOT.weapon_hand_left in $creature.slots: if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item: if $creature/body_parts/body/skeleton/attachment_hand_L/handle.get_children().size() > 0: weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] return weapon func attack(): if self.can_attack: var weapon = null var attachment = null weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].attachment if not weapon: weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].attachment if not weapon: weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].attachment if weapon: print( "pan " + str(weapon.get_data( "damage" )) ) var weapon_node = $creature/body_parts/body/skeleton.get_node( attachment ) if weapon_node: weapon_node = weapon_node.get_node( "handle" ).get_children()[0] # if weapon_node is preload( "res://scenes/items/equipments/weapons/firearm.gd" ): # weapon_node.fire( self, [self] ) # self.can_attack = false $attack_delay.start() func hit( p_damage, p_from = null ): $creature.creature.set_data( "current_life", $creature.creature.get_data( "current_life" )-p_damage ) $head_infos_viewport/head_infos/bars/life.max_value = $creature.creature.get_max_life() $head_infos_viewport/head_infos/bars/life.value = $creature.creature.get_data( "current_life", 0 ) func die(): self.is_dying = true func _on_creature_equip(p_slot, p_item): var weapons = self.get_weapons() if weapons.size() > 0: var max_delay = null for weapon in weapons: if not max_delay: max_delay = weapon.get_data( "attack_delay" ) else: max_delay = max( max_delay, weapon.get_data( "attack_delay" ) ) $attack_delay.wait_time = max_delay emit_signal( "equip", p_slot, p_item ) func _on_creature_unequip(p_slot): emit_signal( "unequip", p_slot ) func _on_attack_delay_timeout(): self.can_attack = true func _on_creature_is_dead(): self.die()