added battle state as globals, adds half working battle flow

This commit is contained in:
Luca 2024-09-29 16:18:32 +02:00
parent b09eee0805
commit 4963131d3e
12 changed files with 250 additions and 95 deletions

View file

@ -45,3 +45,13 @@ func _physics_process(delta: float) -> void:
velocity = Vector3.ZERO
in_battle = true
collider.start_battle(self)
func faint() -> void:
self.queue_free()
func attack_enemy(enemy: Monster) -> int:
var damage = data.attack_enemy(enemy.data)
return damage
func take_damage(amount: int) -> void:
data.take_damage(amount)

View file

@ -9,6 +9,12 @@ extends Node3D
## List that holds all spawnable monsters
@export var spawnable_monsters: Array[MonsterSpawnpointProbability]
## Minimum Level the spawnable monsters have
@export var min_level = 1
## Maximum level the spawnable monsters can have
@export var max_level = 1
## Ignore spawning only if visible
@export var ignore_visibility: bool = false
@ -66,10 +72,19 @@ func spawn() -> void:
# instantiate a monster .tscn scene
var monster_to_spawn = monster_tscn.instantiate()
# get a random monster data
# Create a new MonsterData for the monster to spawn
var monster_data: MonsterData = MonsterData.new()
# Get a random monster data as a template
var random := randi() % spawnable_monsters.size()
var data : MonsterData = spawnable_monsters[random].monster_data
monster_to_spawn.data = data
var template_data : MonsterData = spawnable_monsters[random].monster_data
monster_data.set_values(template_data.unique_id, {}, randi_range(min_level, max_level))
## Heal the wild monster fully
monster_data.heal(9999)
## Set the data of the Node3D monster to spawn
monster_to_spawn.data = monster_data
# keep track of the current monster
active_monsters.append(monster_to_spawn)

View file

@ -1,32 +1,25 @@
extends CharacterBody3D
@onready var animated_mesh = $GobotSkin
@onready var animated_mesh: Node3D = %GobotSkin
@onready var camera: Camera3D = %Camera3D
## State
@export var battle_state := Global.BattleState.NOT_IN_BATTLE
var in_battle: bool = false
var enemy: MonsterData = null
var player_monster: Monster = null
var enemy: Monster = null
## Movement
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
func _ready() -> void:
Utils.set_player(self)
func on_save_game(saved_data : Array[SavedData]):
var data = SavedData.new()
data.position = global_position
data.scene_path = scene_file_path
saved_data.append(data)
func on_before_load_game():
get_parent().remove_child(self)
queue_free()
func on_load_game(saved_data: SavedData):
global_position = saved_data.position
# Update the global reference to the player
Utils.set_player(self)
func _physics_process(delta: float) -> void:
if in_battle == true:
# If the player is in a battle, handle it via start_battle and then handle_battle
if battle_state != Global.BattleState.NOT_IN_BATTLE:
return
animated_mesh.idle()
@ -79,41 +72,121 @@ func _physics_process(delta: float) -> void:
if velocity.length() < 0.05:
animated_mesh.idle()
# what happens when a battle starts?
# the player is positioned (mostly somewhere else than the current position)
# ui changes
# music changes
func start_battle(p_enemy: Node3D) -> void:
enemy = p_enemy.data
var camera: Camera3D = $CameraRoot/SpringArm3D/Camera3D
# local z axis of the camera
var local_z = camera.global_transform.basis.z
var new_player_position = camera.global_transform.origin + local_z * 3
var monster_position = camera.global_transform.origin + local_z * 2
position = Vector3(new_player_position.x, position.y, new_player_position.z)
func on_save_game(saved_data : Array[SavedData]):
var data = SavedData.new()
data.position = global_position
data.scene_path = scene_file_path
saved_data.append(data)
in_battle = true
func on_before_load_game():
get_parent().remove_child(self)
queue_free()
func on_load_game(saved_data: SavedData):
global_position = saved_data.position
# Update the global reference to the player
Utils.set_player(self)
func handle_battle() -> void:
match battle_state:
Global.BattleState.STARTED:
# disable battle_UI
# UI.battle_ui.disable()
UI.battle_ui.set_message("A wild %s appeared!" % enemy.data.name)
await get_tree().create_timer(3.0).timeout
battle_state = Global.BattleState.PLAYER_TURN
handle_battle()
Global.BattleState.PLAYER_TURN:
UI.battle_ui.set_message("What will you do?")
# todo: enable battle_ui again
# UI.battle_ui.enable()
UI.battle_ui.update()
Global.BattleState.ENEMY_TURN:
# If the enemy has no health left, we win
if enemy.data.current_health <= 0:
print("win")
battle_state = Global.BattleState.WIN
handle_battle()
return
UI.battle_ui.set_message("What will the enemy do?")
await get_tree().create_timer(3.0).timeout
var damage_amount: int = enemy.attack_enemy(player_monster)
UI.battle_ui.set_message("The enemy attacked you for %s damage!" % str(damage_amount))
await get_tree().create_timer(1.0).timeout
UI.battle_ui.update()
battle_state = Global.BattleState.PLAYER_TURN
handle_battle()
Global.BattleState.CATCH:
print("Catch")
await get_tree().create_timer(3.0).timeout
Global.BattleState.WIN:
UI.battle_ui.set_message("You won!")
await get_tree().create_timer(3.0).timeout
battle_state = Global.BattleState.NOT_IN_BATTLE
UI.ingame_menu.update()
UI.show_battle_ui(false)
UI.show_ingame_controls(true)
Global.BattleState.LOSE:
print("LOSE")
await get_tree().create_timer(3.0).timeout
## This method sets up a battle between the player and an enemy monster
func start_battle(p_enemy: Monster) -> void:
# Don't start a battle if we are already in one
# TODO: Maybe add a cooldown of 1.5s after the battle ended
if battle_state != Global.BattleState.NOT_IN_BATTLE:
return
# Stop the player
velocity = Vector3.ZERO
animated_mesh.idle()
# Set the current enemy
enemy = p_enemy
# Get the loccal z axis of the camera to position the player
var local_z = camera.global_transform.basis.z
# Get the new player and monster positions
var new_player_position = camera.global_transform.origin + local_z * 3
var monster_position = camera.global_transform.origin + local_z * 3
# Set the players new position
position = Vector3(new_player_position.x, position.y, new_player_position.z)
# Change the UI
UI.show_battle_ui(true)
UI.show_ingame_controls(false)
# Spawn player monster
# Create the player's monster
player_monster = Monster.new()
# Get the data from the party
var monster_data : MonsterData = SaveManager.current_save.party[0]
var monster = Monster.new()
monster.data = monster_data
monster.idle = true
print("%s (%s), Lv. %s, %s XP" % [monster.data.name, monster.data.nickname, monster.data.level, monster.data.xp])
monster.position = Vector3(monster_position.x, position.y + 1, monster_position.z)
add_child(monster)
camera.look_at(monster.position, Vector3.UP, false)
# How to attack and finish the battle?
# And add it to the monster
player_monster.data = monster_data
player_monster.idle = true
player_monster.position = Vector3(monster_position.x, position.y + 1, monster_position.z)
add_child(player_monster)
# Get into the battle and switch between the states
battle_state = Global.BattleState.STARTED
handle_battle()
func attack_enemy():
UI.battle_ui.set_message("You attacked the enemy!")
await get_tree().create_timer(1.0).timeout
await get_tree().create_timer(5.0).timeout
print("Battle over")
remove_child(monster)
monster.queue_free()
in_battle = false
# this should rather be player_monster.attack_enemy(enemy) for correct values
enemy.take_damage(7)
UI.battle_ui.update()
await get_tree().create_timer(1.0).timeout
battle_state = Global.BattleState.ENEMY_TURN
handle_battle()

View file

@ -14,6 +14,7 @@ axis_lock_angular_z = true
script = ExtResource("1_mv2yl")
[node name="GobotSkin" parent="." instance=ExtResource("2_a4t6w")]
unique_name_in_owner = true
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
@ -26,4 +27,5 @@ shape = SubResource("CapsuleShape3D_xuba7")
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.64528, 2.83335)
[node name="Camera3D" type="Camera3D" parent="CameraRoot/SpringArm3D"]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 0.965926, 0.258819, 0, -0.258819, 0.965926, 0, 0.0210915, 0.372644)