the-scavanger/the-scavanger/scripts/player.gd
2025-04-17 20:04:51 +02:00

485 lines
13 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends CharacterBody2D
const speed = 100
const dodge_speed = 200 # Speed during dodge
const dodge_duration = 0.5 # How long the dodge lasts (in seconds)
const dodge_cooldown_time = 3.0 # Dodge cooldown (in seconds)
var current_direction = "none"
var is_dodging = false
var dodge_cooldown_active = false
var enemy_in_attack_range = false
var enemy_attack_cooldown = true
var healt = 100 # return to 100 before turnin
var player_alive = true
var attack_ip = false
var attack_in_progress = false # New state for attack-in-progress
# variables for game progress
var has_blue_potion = false
var has_red_potion = false
var has_green_potion = false
var coin_count = 0
var word_chunks = [] # Stores the words to show in chunks
var current_chunk_index = 0 # Tracks which chunk we're on
# Call this to start displaying the text in chunks
func show_text_in_chunks(full_text: String) -> void:
# Add wizard/knight-style ending at the end
full_text += " Ave Domine Limosus, gloria regni slime aeterni!"
# Tokenize the full text into words and punctuation
word_chunks = tokenize_text(full_text)
current_chunk_index = 0
$"TextEdit".visible = true
$"TextEdit".text = "" # Start clean
set_process(true) # Allow input checking in _process
# Tokenize text into words and punctuation marks separately
func tokenize_text(text: String) -> Array:
var regex = RegEx.new()
regex.compile(r"[\w']+|[.,!?;]") # Match words and punctuation
var matches = regex.search_all(text)
var tokens = []
for match in matches:
tokens.append(match.strings[0])
return tokens
# Called every frame, listens for just-pressed input to show next chunk
func _process(_delta):
if Input.is_action_just_pressed("ui_accept"):
if current_chunk_index * 7 < word_chunks.size():
_display_next_chunk()
elif $"TextEdit".visible:
_display_empty_chunk()
# Show the current chunk of exactly 7 words
func _display_next_chunk() -> void:
var start = current_chunk_index * 7
var end = min(start + 7, word_chunks.size())
var chunk_text = " ".join(word_chunks.slice(start, end))
$"TextEdit".text = chunk_text
current_chunk_index += 1
# Show empty chunk and hide the box
func _display_empty_chunk() -> void:
$"TextEdit".text = ""
$"TextEdit".visible = false
set_process(false)
func resetGame():
has_blue_potion = false
has_red_potion = false
has_green_potion = false
current_direction = "none"
is_dodging = false
dodge_cooldown_active = false
enemy_in_attack_range = false
enemy_attack_cooldown = true
healt = 100
player_alive = true
attack_ip = false
position.x = 0
position.y = 0
func _ready():
var animation = $AnimatedSprite2D
animation.play("front_idle")
# Initialize dodge cooldown bar at full value
$DodgeCoolDownBar.max_value = dodge_cooldown_time
$DodgeCoolDownBar.value = dodge_cooldown_time # Start at full
# Make sure healthbar is always visible
$healthbar.visible = true # Set to true to always display health bar
func _physics_process(delta):
player_movement()
enemy_attack()
play_attack_animation()
update_healt()
update_dodge_cooldown(delta)
if healt <= 0:
player_alive = false
healt = 0
print("Player has been killed")
resetGame()
func player_movement():
velocity = Vector2.ZERO
if Input.is_action_pressed("ui_right"):
velocity.x = speed
current_direction = "right"
if Input.is_action_pressed("ui_left"):
velocity.x = -speed
current_direction = "left"
if Input.is_action_pressed("ui_down"):
velocity.y = speed
current_direction = "down"
if Input.is_action_pressed("ui_up"):
velocity.y = -speed
current_direction = "up"
# Normalize velocity for diagonal movement
if velocity.length() > speed:
velocity = velocity.normalized() * speed
if is_dodging:
velocity = velocity.normalized() * dodge_speed # Apply dodge boost
# Use move_and_slide() with only the velocity
move_and_slide()
# Play walking or idle animation
if velocity != Vector2.ZERO and !attack_in_progress:
play_animation(1) # Walking animation
elif !attack_in_progress:
play_animation(0) # Idle animation
func play_animation(movement):
var dir = current_direction
var animation = $AnimatedSprite2D
if dir == "right":
animation.flip_h = false
if movement == 1:
animation.play("side_walk")
elif movement == 0:
if !attack_ip:
animation.play("side_idle")
if dir == "left":
animation.flip_h = true
if movement == 1:
animation.play("side_walk")
elif movement == 0:
if !attack_ip:
animation.play("side_idle")
if dir == "down":
animation.flip_h = false
if movement == 1:
animation.play("front_walk")
elif movement == 0:
if !attack_ip:
animation.play("front_idle")
if dir == "up":
animation.flip_h = false
if movement == 1:
animation.play("back_walk")
elif movement == 0:
if !attack_ip:
animation.play("back_idle")
func play_attack_animation():
var dir = current_direction
var animation = $AnimatedSprite2D
var timer = $deal_attack_timer
if Input.is_action_just_pressed("attack") and !attack_in_progress:
attack_in_progress = true
global.player_current_attack = true
attack_ip = true
if dir == "right":
animation.flip_h = false
animation.play("side_attack")
timer.start()
elif dir == "left":
animation.flip_h = true
animation.play("side_attack")
timer.start()
elif dir == "down":
animation.flip_h = false
animation.play("front_attack")
timer.start()
elif dir == "up":
animation.flip_h = false
animation.play("back_attack")
timer.start()
func _on_deal_attack_timer_timeout():
var timer = $deal_attack_timer
timer.stop()
global.player_current_attack = false
attack_ip = false
attack_in_progress = false # Reset attack progress
func _on_player_hitbox_body_entered(body):
if body.has_method("enemy"):
enemy_in_attack_range = true
func _on_player_hitbox_body_exited(body):
if body.has_method("enemy"):
enemy_in_attack_range = false
func player():
pass
func enemy_attack():
if enemy_in_attack_range && enemy_attack_cooldown:
healt -= 10
enemy_attack_cooldown = false
$attack_cooldown.start()
print("Current healt: ", healt)
func _on_attack_cooldown_timeout():
enemy_attack_cooldown = true
func update_healt():
var healtbar = $healthbar
healtbar.value = healt
# Healthbar is now always visible
if healt >= 100:
healtbar.visible = true # Ensure it's visible at all times
else:
healtbar.visible = true # Ensure it's visible even when health drops below 100
func _on_regen_timer_timeout():
if healt < 100:
healt = healt + 20
if healt > 100:
healt = 100
if healt <= 0:
healt = 0
# Handle Dodge
func _input(event):
if event.is_action_pressed("dodge") and !dodge_cooldown_active:
is_dodging = true
# When dodge is triggered, set the cooldown to 0 (start cooldown)
$DodgeCoolDownBar.value = 0
# Dodge lasts for a short time
await get_tree().create_timer(dodge_duration).timeout
is_dodging = false
dodge_cooldown_active = true
# Update Dodge cooldown
func update_dodge_cooldown(delta):
if dodge_cooldown_active:
$DodgeCoolDownBar.value += delta # Slowly fill up the dodge bar over time
if $DodgeCoolDownBar.value >= dodge_cooldown_time:
dodge_cooldown_active = false
$DodgeCoolDownBar.value = dodge_cooldown_time # Reset to full after cooldown ends
func gameEnd() -> void:
while $"TextEdit".visible:
await get_tree().create_timer(1.0).timeout
print("The game has been beaten!")
queue_free()
get_tree().quit()
func enterHouseNico(body: Node2D) -> void:
if body == self:
self.position = Vector2(1290, 1130)
func leaveHouseNico(body: Node2D) -> void:
if body == self:
self.position = Vector2(1300, 580)
func goIntoBasementNico(body: Node2D) -> void:
if body == self:
self.position = Vector2(1100, 1130)
func leaveBasementNico(body: Node2D) -> void:
if body == self:
self.position = Vector2(1250, 1200)
func enterHouse(body: Node2D) -> void:
if body == self:
self.position = Vector2(400, -800)
func leaveHouse(body: Node2D) -> void:
if body == self:
self.position = Vector2(80, -30)
func enterCastle(body: Node2D) -> void:
if body == self:
self.position = Vector2(3820, -1025)
func leaveCastle(body: Node2D) -> void:
if body == self:
self.position = Vector2(2420, -1225)
func layer0(body: Node2D) -> void:
if body == self:
self.position = Vector2(3620, -1425)
func layer1(body: Node2D) -> void:
if body == self:
self.position = Vector2(4220, -1025)
func layer2(body: Node2D) -> void:
if body == self:
self.position = Vector2(4820, -1025)
func layer3(body: Node2D) -> void:
if body == self:
self.position = Vector2(4220, -1325)
func layer4(body: Node2D) -> void:
if body == self:
self.position = Vector2(4820, -1325)
func layer5(body: Node2D) -> void:
if body == self:
self.position = Vector2(5420, -1325)
func layer6(body: Node2D) -> void:
if body == self:
self.position = Vector2(5420, -1025)
func leaveDungeon(body: Node2D) -> void:
if body == self:
enterCastle(self)
func keyPickUp(body: Node2D) -> void:
if body == self:
$"../collectables/Area2D".queue_free()
$"../center-left/StaticBody2D".queue_free()
func pickUpRedPotion(body: Node2D) -> void:
if body == self:
$"../collectables/Area2D2".queue_free()
has_red_potion = true
func pickUpBluePotion(body: Node2D) -> void:
if body == self:
$"../collectables/Area2D3".queue_free()
has_blue_potion = true
func pickUpGreenPotion(body: Node2D) -> void:
if body == self:
$"../collectables/Area2D4".queue_free()
has_green_potion = true
func pickUpCoin1(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin1".queue_free()
coin_count +=1
print(coin_count)
func pickUpCoin2(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin2".queue_free()
coin_count +=1
print(coin_count)
func pickUpCoin3(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin3".queue_free()
coin_count +=1
print(coin_count)
func pickUpCoin4(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin4".queue_free()
coin_count +=1
print(coin_count)
func pickUpCoin5(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin5".queue_free()
coin_count +=1
print(coin_count)
func pickUpCoin6(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin6".queue_free()
coin_count +=1
print(coin_count)
func pickUpCoin7(body: Node2D) -> void:
if body == self:
$"../collectables/coins/coin7".queue_free()
coin_count += 1
print(coin_count)
func wizardTalking(body: Node2D) -> void:
if body == self:
if has_blue_potion and has_green_potion and has_red_potion:
show_text_in_chunks(
"By the stars, you actually did it! You brought all three potions—red, green, and blue!
...Oh. Uh, yeah—about that. So here's the thing...
You only need to drink the red one to return to your world. The other two?
Yeah those were... kinda for me. I just really like how the green one tastes with toast. And the blue one? Makes bath time way more interesting. Heh.
Anyway! Bottoms up with that red one, and—poof!—youre home.
No refunds!"
)
gameEnd()
else:
show_text_in_chunks("Ah... you're not from this world, are you? Curious. Your aura—it's foreign, like a breeze from a land long forgotten. Fear not! I can send you back... but the spell requires three ancient potions: red, green, and blue. They're scattered deep within this slime-infested forest. Charming place, really. Oh, before you go stumbling into a slime's belly, a few pointers: WASD or arrow keys to move, Spacebar for a quick dodge—handy for avoiding gooey hugs, and to deal with trouble, just left-click or press E to strike. Now go! The forest wont wait... and neither will the slimes.")
func knightTalking(body: Node2D) -> void:
if body == self and coin_count >= 6:
show_text_in_chunks(
"...Well now. You actually returned... and with all seven coins of Lazaret, no less.
Many have entered that cursed dungeon—most were not so fortunate.
Youve proven your strength... and your spirit. As promised, I shall open the gate.
The blue potion is yours. Use it wisely—it holds power not meant for the faint of heart.
May your path forward be clear... and your enemies less so."
)
$"../north/StaticBody2D2".queue_free()
coin_count = 0
elif body == self:
show_text_in_chunks(
"Ah, I see your eyes are fixed on that glowing prize beyond the gate—the blue potion. So close you could almost taste it… yet still out of reach.
Know this: that potion is not yours for the taking—not yet. Only those who prove their worth may claim it.
Venture into the dungeon below and retrieve the Sixa Gold Coins of Lazaret. Only then will I raise this gate.
Do not return empty-handed... or not at all."
)