123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- extends "res://entities/GridBasedMovable.gd"
- @export var can_pull = true
- @export var tool_change_time = 0.08
- @onready var ptm = get_node("RotationPoint/PlayerToolManager")
- @onready var audio_player = $AudioStreamPlayer3D
- @onready var bomb_counter = $BombCounter
- #var active_tool: PLAYERTOOLS = get_node("RotationPoint/PlayerToolManager").active_tool
- var requested_mesh_direction
- var distant_object_to_take = null
- var distant_tool_to_place = null
- var distant_bomb_to_place = false
- var enable_input = true
- var last_keys_pressed_amount = 0
- var first_move_started = false
- enum PLAYERTOOLS {NONE, CLEANING_TOOL, PUSH_TOOL, PULL_TOOL, GRINDING_TOOL}
- var tool_changing = false
- func _ready() -> void:
- super._ready()
- ptm.set_active_tool(PLAYERTOOLS.NONE)
- update_rotation_point(DIRECTIONS.UP)
- func _process(delta):
-
- handle_distant_request()
- handle_player_input()
-
- if ray_ground.is_colliding():
- var groundObject = ray_ground.get_collider()
- if groundObject != null:
- if groundObject.is_in_group("enemy"): #spiky things are done in the gridbasedmovable base class
- hit()
-
- func get_keys_pressed_amount():
- var keys = 0
- if Input.is_action_pressed("ui_right"):
- keys += 1
- if Input.is_action_pressed("ui_left"):
- keys += 1
- if Input.is_action_pressed("ui_up"):
- keys += 1
- if Input.is_action_pressed("ui_down"):
- keys += 1
- return keys
- func handle_distant_request():
-
-
- if is_grid_aligned():
-
- if distant_object_to_take != null:
- if distant_object_to_take.is_in_group("tool") and distant_object_to_take.has_method("take_tool"):
- distant_object_to_take = null
- update_tool()
- elif distant_object_to_take.is_in_group("bomb_item"):
- distant_object_to_take = null
- try_take_bomb()
-
- elif distant_bomb_to_place == true:
- distant_bomb_to_place = false
- put_bomb_down()
-
- elif distant_tool_to_place != null:
- update_tool()
- distant_tool_to_place = null
- #ptm.set_active_tool(PLAYERTOOLS.NONE)
-
-
- func hit():
- if health_node.invulnerable == false:
- audio_player.stream = load("res://sfx/ncl_player_hit.ogg")
- #audio_player.volume_db = -1
- audio_player.pitch_scale = randf_range(0.86, 0.93)
- audio_player.play()
- health_node.hurt()
- SceneManager.game_scene.update_labels()
-
- func kill():
- pass
- #health_node.kill()
- func movement_started():
- first_move_started = true
- if animation_player != null:
- animation_player.play("Player_Move", -1, 1.5 * (1/speed_modifier))
-
-
- func put_bomb_down():
- if protection_area.has_overlapping_areas():
- #if a movable has it's PlacementProtectionArea (at front) at Monitorable, then no item can be placed
- #default false for this area, but used for enemies
- return
- if tool_changing == true:
- return
- if !is_grid_aligned():
- distant_bomb_to_place = true
- return
-
-
- if requested_direction != DIRECTIONS.NONE or ray_front.is_colliding():
- return
-
-
-
- if bomb_counter.has_bombs():
- bomb_counter.use_bomb()
- else:
- print ("no bombs left to use!!!")
- return
-
- enable_movement = false
- await get_tree().create_timer(0.1).timeout
-
- var Bomb_Node
- #if put_down != PLAYERTOOLS.NONE:
- # if put_down == PLAYERTOOLS.CLEANING_TOOL:
- Bomb_Node = load("res://entities/objects/bomb/Bomb.tscn")
-
- var bomb_instance = Bomb_Node.instantiate()
- audio_player.stream = load("res://sfx/ncl_bomb_drop.ogg")
- audio_player.volume_db = -3
- audio_player.pitch_scale = randf_range(0.86, 0.93)
- audio_player.play()
-
-
- level.add_child(bomb_instance)
- var movedir = direction_to_vector(mesh_direction)
- bomb_instance.position = position + movedir * step_size
-
- bomb_instance.position.y = position.y
- bomb_instance._ready()
-
- bomb_instance.local_tween_position = bomb_instance.position
-
- enable_movement = true
-
- func put_tool_down(put_down):
- tool_changing = true
- enable_movement = false
- await get_tree().create_timer(tool_change_time).timeout
- tool_changing = false
- var Tool_Node
- if put_down != PLAYERTOOLS.NONE:
- if put_down == PLAYERTOOLS.CLEANING_TOOL:
- Tool_Node = load("res://entities/objects/tools/CleaningToolObject.tscn")
- elif put_down == PLAYERTOOLS.PUSH_TOOL:
- Tool_Node = load("res://entities/objects/tools/PushToolObject.tscn")
- elif put_down == PLAYERTOOLS.PULL_TOOL:
- Tool_Node = load("res://entities/objects/tools/PullToolObject.tscn")
- elif put_down == PLAYERTOOLS.GRINDING_TOOL:
- Tool_Node = load("res://entities/objects/tools/GrindingToolObject.tscn")
- else:
- print ("error: no tool???, put_down == " + str(put_down))
- return
- var tool_instance = Tool_Node.instantiate()
- audio_player.stream = load("res://sfx/ncl_tool.ogg")
- audio_player.volume_db = 6
- audio_player.pitch_scale = randf_range(0.86, 0.93)
- audio_player.play()
- #var game = SceneManager.game_scene
- #var level = game.level_scene_instance
-
- level.add_child(tool_instance)
- var movedir = direction_to_vector(mesh_direction)
- tool_instance.position = position + movedir * step_size
- tool_instance._ready()
- tool_instance.position.y = position.y
-
- tool_instance.local_tween_position = tool_instance.position
-
- enable_movement = true
-
- func try_take_bomb():
- if is_grid_aligned():
- var frontObject = ray_front.get_collider()
- if frontObject != null and frontObject.is_in_group("bomb_item"):
- frontObject.take_bomb()
- bomb_counter.add_bomb()
- func update_tool():
- if protection_area.has_overlapping_areas():
- #if a movable has it's PlacementProtectionArea (at front) at Monitorable, then no item can be placed
- #default false for this area, but used for enemies
- return
- if tool_changing == true:
- return
- var lying_tool = null
- var put_down = ptm.active_tool
- var can_put_down = true
- #do it with the old way when grid aligned
- if is_grid_aligned():
- if ray_front.is_colliding():
-
- var collided_with = ray_front.get_collider()
- if collided_with.is_class("GridMap"):
- return
-
- #step 1: check if there is a tool detected lying on the ground
- if ray_front.is_colliding():
- var frontObject = ray_front.get_collider()
- if frontObject != null: #fixme: maybe check if it is really a tool, has tool_type
- if frontObject.is_in_group("tool") and frontObject.has_method("take_tool"):
- lying_tool = frontObject
-
- elif frontObject.get_parent().is_in_group("tool") and frontObject.get_parent().has_method("take_tool"):
- lying_tool = frontObject.get_parent()
- else:
- can_put_down = false
- elif ray_downramp.is_colliding():
- var frontObject = ray_downramp.get_collider()
- if frontObject != null: #fixme: maybe check if it is really a tool, has tool_type
- if frontObject.is_in_group("tool"):
- lying_tool = frontObject
-
- elif frontObject.get_parent().is_in_group("tool") and frontObject.get_parent().has_method("take_tool"):
- lying_tool = frontObject.get_parent()
-
- if put_down == PLAYERTOOLS.NONE: #player has no tool to put down
- if lying_tool != null:
- lying_tool.take_tool()
- ptm.set_active_tool(lying_tool.tool_type + 1)
- else: #player has a tool:
-
- if can_put_down == false or (requested_direction != DIRECTIONS.NONE and lying_tool == null):
- return
- if lying_tool == null:
- put_tool_down(put_down)
- ptm.set_active_tool(PLAYERTOOLS.NONE)
- else:
- lying_tool.take_tool()
-
- ptm.set_active_tool(lying_tool.tool_type + 1)
- put_tool_down(put_down)
-
- else:
- var distant_object = level.find_object_at_position(self, distant_target_position)
- if distant_object != null:
- if distant_object.is_in_group("tool") and distant_object.has_method("take_tool") and distant_object_to_take == null:
- distant_object_to_take = distant_object
- if put_down != PLAYERTOOLS.NONE:
- distant_tool_to_place = put_down
-
- func _try_push(object, direction):
- if push(object, direction) == true:
- audio_player.stream = load("res://sfx/ncl_object_move.ogg")
- audio_player.volume_db = -9
- audio_player.pitch_scale = randf_range(0.8, 0.8)
- #audio_player.play() #fixme improve movement sfx
-
-
- func _handle_short_direction_change_impulse():
- if tool_changing:
- return
- if is_grid_aligned() and last_keys_pressed_amount == 0:
- if Input.is_action_just_pressed("ui_right"):
- requested_mesh_direction = DIRECTIONS.RIGHT
- elif Input.is_action_just_pressed("ui_left"):
- requested_mesh_direction = DIRECTIONS.LEFT
- elif Input.is_action_just_pressed("ui_up"):
- requested_mesh_direction = DIRECTIONS.UP
- elif Input.is_action_just_pressed("ui_down"):
- requested_mesh_direction = DIRECTIONS.DOWN
- else:
- requested_mesh_direction = DIRECTIONS.NONE
-
- if requested_mesh_direction != DIRECTIONS.NONE:
- if mesh_direction == requested_mesh_direction:
- #the player is facing in the direction it moves, skip short direction change impulse
- return
-
- enable_movement = false
- await get_tree().create_timer(0.06).timeout
- enable_movement = true
-
- update_rotation_point(requested_mesh_direction)
- #requested_direction = requested_mesh_direction
-
-
-
- func _handle_movement_input():
- if !enable_movement or tool_changing:
- return
- if Input.is_action_just_pressed("ui_right"):
- requested_direction = DIRECTIONS.RIGHT
- elif Input.is_action_just_pressed("ui_left"):
- requested_direction = DIRECTIONS.LEFT
- elif Input.is_action_just_pressed("ui_up"):
- requested_direction = DIRECTIONS.UP
- elif Input.is_action_just_pressed("ui_down"):
- requested_direction = DIRECTIONS.DOWN
-
-
- elif Input.is_action_pressed("ui_right") and requested_direction == DIRECTIONS.RIGHT:
- requested_direction = DIRECTIONS.RIGHT
- elif Input.is_action_pressed("ui_left") and requested_direction == DIRECTIONS.LEFT:
- requested_direction = DIRECTIONS.LEFT
- elif Input.is_action_pressed("ui_up") and requested_direction == DIRECTIONS.UP:
- requested_direction = DIRECTIONS.UP
- elif Input.is_action_pressed("ui_down") and requested_direction == DIRECTIONS.DOWN:
- requested_direction = DIRECTIONS.DOWN
-
- elif Input.is_action_pressed("ui_right"):
- requested_direction = DIRECTIONS.RIGHT
- elif Input.is_action_pressed("ui_left"):
- requested_direction = DIRECTIONS.LEFT
- elif Input.is_action_pressed("ui_up"):
- requested_direction = DIRECTIONS.UP
- elif Input.is_action_pressed("ui_down"):
- requested_direction = DIRECTIONS.DOWN
- else:
- requested_direction = DIRECTIONS.NONE
-
-
- func _handle_action_input():
- if !enable_movement:
- return
- if Input.is_action_just_pressed("change_tool"):
- update_tool()
- if Input.is_action_just_pressed("bomb"):
- put_bomb_down()
-
- if OS.is_debug_build():
- if Input.is_action_just_pressed("change_tool_debug"):
- if ptm.active_tool == PLAYERTOOLS.NONE:
- ptm.set_active_tool(PLAYERTOOLS.CLEANING_TOOL)
- elif ptm.active_tool == PLAYERTOOLS.CLEANING_TOOL:
- ptm.set_active_tool(PLAYERTOOLS.PUSH_TOOL)
- elif ptm.active_tool == PLAYERTOOLS.PUSH_TOOL:
- ptm.set_active_tool(PLAYERTOOLS.PULL_TOOL)
- elif ptm.active_tool == PLAYERTOOLS.PULL_TOOL:
- ptm.set_active_tool(PLAYERTOOLS.GRINDING_TOOL)
- elif ptm.active_tool == PLAYERTOOLS.GRINDING_TOOL:
- ptm.set_active_tool(PLAYERTOOLS.NONE)
- else:
- ptm.set_active_tool(PLAYERTOOLS.CLEANING_TOOL)
- if Input.is_action_just_pressed("debug_add_bomb"):
- bomb_counter.add_bombs(5)
-
-
- #pushing and other front collision handling (like running into enemies)
-
- if requested_direction != DIRECTIONS.NONE and ray_front.is_colliding() and is_grid_aligned():
- var frontObject = ray_front.get_collider()
- var local_movedir = direction_to_vector(requested_direction)
- var next_target_pos = position + local_movedir * step_size
- if frontObject != null:
- var _distance = (next_target_pos - frontObject.position).length()
-
- #tool or regular + push tool
- if frontObject.is_in_group("tool") or ((frontObject.is_in_group("pushable") and !frontObject.is_in_group("heavy") and ptm.active_tool == PLAYERTOOLS.PUSH_TOOL)):
- if _distance < 1:
- modify_speed_timed(1.15)
- _try_push(frontObject, requested_direction)
-
- #regular
- elif frontObject.is_in_group("pushable") and !frontObject.is_in_group("heavy"):
- if _distance < 1:
- modify_speed_timed(1.45)
- _try_push(frontObject, requested_direction)
-
- #heavy and push tool
- elif frontObject.is_in_group("pushable") and ptm.active_tool == PLAYERTOOLS.PUSH_TOOL:
- if _distance < 1:
- modify_speed_timed(1.75)
- _try_push(frontObject, requested_direction)
-
- #tool or regular + push tool
- elif frontObject.get_parent().is_in_group("tool") or ((frontObject.get_parent().is_in_group("pushable") and !frontObject.get_parent().is_in_group("heavy") and ptm.active_tool == PLAYERTOOLS.PUSH_TOOL)):
- if _distance < 1:
- modify_speed_timed(1.15)
- _try_push(frontObject.get_parent(), requested_direction)
-
- #regular
- elif frontObject.get_parent().is_in_group("pushable") and !frontObject.is_in_group("heavy"):
- if _distance < 1:
- modify_speed_timed(1.45)
- _try_push(frontObject.get_parent(), requested_direction)
-
- #heavy and push tool
- elif frontObject.get_parent().is_in_group("pushable") and ptm.active_tool == PLAYERTOOLS.PUSH_TOOL:
- if _distance < 1:
- modify_speed_timed(1.75)
- _try_push(frontObject.get_parent(), requested_direction)
-
- elif frontObject.is_in_group("enemy") and _distance < 1:
- hit()
- elif frontObject.get_parent().is_in_group("grindable") and ptm.active_tool == PLAYERTOOLS.GRINDING_TOOL:
- ptm.play_animation()
- frontObject.get_parent().call_deferred("queue_free")
-
-
-
-
- else:
- print ("error: front raycast hit null object")
- elif requested_direction != DIRECTIONS.NONE and is_grid_aligned():
- var push_down = get_push_down_ramp_object()
- if push_down != null:
- var local_movedir = direction_to_vector(requested_direction)
- var next_target_pos = position + local_movedir * step_size
- var _distance = (next_target_pos - push_down.position).length()
- if _distance < 1:
- modify_speed_timed(1.15)
- _try_push(push_down, requested_direction)
-
-
- if requested_direction != DIRECTIONS.NONE and ray_back.is_colliding() and is_grid_aligned():
-
- if Input.is_action_pressed("action") and can_move_to(requested_direction) and can_pull:
- var backObject = ray_back.get_collider()
- if backObject != null:
-
- if backObject.is_in_group("pullable") and ptm.active_tool == PLAYERTOOLS.PULL_TOOL and backObject.can_be_pulled_to(requested_direction):
- #modify_speed_timed(2) #this is buggy right now, so I disabled it
-
- backObject.print_pull_collision()
- backObject.move_to(requested_direction, true)
- ptm.play_start_animation()
- #audio_player.stream = load("res://sfx/ncl_object_move.ogg")
- #audio_player.volume_db = -3
- #audio_player.pitch_scale = randf_range(0.86, 0.93)
- #audio_player.play()
-
- requested_mesh_direction = get_opposite_direction(requested_direction)
-
-
- else:
- print ("error: back raycast hit null object")
-
- if Input.is_action_just_released("action") and ptm.active_tool == PLAYERTOOLS.PULL_TOOL:
- var backObject = ray_back.get_collider()
- if backObject != null and backObject.is_in_group("pullable"):
- ptm.play_end_animation()
- if Input.is_action_just_pressed("action") and ptm.active_tool == PLAYERTOOLS.PULL_TOOL:
- var backObject = ray_back.get_collider()
- if backObject != null and backObject.is_in_group("pullable"):
- ptm.play_start_animation()
- #audio_player.stream = load("res://sfx/ncl_object_move.ogg")
- #audio_player.volume_db = -3
- #audio_player.pitch_scale = randf_range(0.86, 0.93)
- #audio_player.play()
- if ray_front.is_colliding() and (Input.is_action_just_pressed("change_tool") or Input.is_action_just_pressed("action")):
- if is_grid_aligned():
- var frontObject = ray_front.get_collider()
- if frontObject != null and frontObject.is_in_group("bomb_item"):
- frontObject.take_bomb()
- bomb_counter.add_bomb()
- else:
- var distant_object = level.find_object_at_position(self, distant_target_position)
- if distant_object != null:
- if distant_object.is_in_group("bomb_item") and distant_object.has_method("take_bomb") and distant_object_to_take == null:
- distant_object_to_take = distant_object
-
-
- func handle_player_input():
-
- if !enable_input:
- return
- #when a key is only pressed for a short time, no movement is applied by blocking movement with enable_movement = false, only direction changes
- _handle_short_direction_change_impulse()
- _handle_movement_input()
- _handle_action_input()
-
- last_keys_pressed_amount = get_keys_pressed_amount()
- func _on_Health_no_health() -> void:
- if SceneManager.game_scene.is_finished:
- #no gameover when the level is already finished :-)
- return
- print ("you died")
-
- Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
- get_tree().change_scene_to_file("res://UI/GameOverScreen.tscn")
- func wait_after_puddle_cleaned():
- await get_tree().create_timer(0.0666666666667).timeout
- enable_movement = true
|