181 lines
5.6 KiB
GDScript
181 lines
5.6 KiB
GDScript
class_name BattleScene extends Node3D
|
|
|
|
@export var actionBox:ActionBox = null
|
|
@export var battleFighterScenes:Node
|
|
@export var cursorScenes:Node
|
|
|
|
signal neverEmitted
|
|
|
|
func _init() ->void:
|
|
BATTLE.battleScene = self
|
|
BATTLE.battleStarted.connect(onBattleStarted)
|
|
|
|
func onBattleStarted() -> void:
|
|
pass
|
|
|
|
func getBattleDecisions(fighters:Array[BattleFighter]) -> Array[BattleDecision]:
|
|
var decisions:Array[BattleDecision] = []
|
|
|
|
while fighters.size() > decisions.size():
|
|
var fighter = fighters[decisions.size()]
|
|
var decision:BattleDecision = null
|
|
|
|
# Simulate walking forward animation like in Final Fantasy
|
|
await get_tree().create_timer(0.5).timeout
|
|
|
|
# Until decision made...
|
|
while decision == null:
|
|
# Get the selected action
|
|
actionBox.visible = true
|
|
var action = await self.actionBox.getAction(fighter)
|
|
|
|
# Go back to previous fighter
|
|
if action == ActionBox.Action.BACK:
|
|
decisions.pop_back()
|
|
actionBox.visible = false
|
|
# Get target for attack
|
|
elif action == ActionBox.Action.ATTACK:
|
|
var targets = await _getTargets(fighter, fighter.movePrimary)
|
|
decision = BattleDecision.new(
|
|
fighter.movePrimary,
|
|
fighter,
|
|
targets
|
|
)
|
|
# Get Magic move and targets
|
|
elif action == ActionBox.Action.MAGIC:
|
|
var magicMove = await _getMagicMove(fighter)
|
|
if magicMove != null:
|
|
var targets = await _getTargets(fighter, magicMove)
|
|
decision = BattleDecision.new(
|
|
magicMove,
|
|
fighter,
|
|
targets
|
|
)
|
|
# Get Item use and targets
|
|
elif action == ActionBox.Action.ITEM:
|
|
var itemMove = await _getItemUse(fighter)
|
|
if itemMove != null:
|
|
var targets = await _getTargets(fighter, itemMove)
|
|
decision = BattleDecision.new(
|
|
itemMove,
|
|
fighter,
|
|
targets
|
|
)
|
|
|
|
if decision != null:
|
|
decisions.append(decision)
|
|
|
|
# Return the made decision
|
|
return decisions
|
|
|
|
func _getInitialTargetPosition(
|
|
fighter:BattleFighter,
|
|
move:BattleAction,
|
|
possiblePositions:Array[BattleSingleton.BattlePosition],
|
|
) -> BattleSingleton.BattlePosition:
|
|
# Find ally in possible positions
|
|
if move.preferAlly:
|
|
for pos in possiblePositions:
|
|
var targetFighter = BATTLE.getFighterAtPosition(pos)
|
|
if targetFighter != null and targetFighter.team == fighter.team:
|
|
return pos
|
|
|
|
# Otherwise, prefer to target enemy
|
|
for pos in possiblePositions:
|
|
var targetFighter = BATTLE.getFighterAtPosition(pos)
|
|
if targetFighter != null and targetFighter.team != fighter.team:
|
|
return pos
|
|
|
|
# If still noting found, just return first possible position
|
|
if possiblePositions.size() > 0:
|
|
return possiblePositions[0]
|
|
|
|
# Fallback (should not happen)
|
|
assert(false)
|
|
return BATTLE.BattlePosition.LEFT_TOP_BACK
|
|
|
|
func _getTargets(fighter:BattleFighter, move:BattleAction) -> Array[BattleFighter]:
|
|
assert(fighter != null)
|
|
assert(move != null)
|
|
|
|
# Determine possible targets and whether to blink or not
|
|
var possiblePositions:Array[BattleSingleton.BattlePosition] = []
|
|
|
|
if move.canTargetEnemy:
|
|
possiblePositions.append_array(BATTLE.getEnemyPositions())
|
|
if move.canTargetAlly:
|
|
possiblePositions.append_array(BATTLE.getAllyPositions())
|
|
|
|
# Should not be possible to have no possible targets here
|
|
assert(possiblePositions.size() > 0)
|
|
|
|
var activePositions:Array[BattleSingleton.BattlePosition] = [
|
|
_getInitialTargetPosition(fighter, move, possiblePositions)
|
|
]
|
|
|
|
# This is where output will be stored.
|
|
var selectedPositions:Array[BattleSingleton.BattlePosition] = []
|
|
|
|
# Here we wait for a selection to be confirmed.
|
|
while selectedPositions.size() == 0:
|
|
var blink = activePositions.size() > 1
|
|
|
|
# Show cursors
|
|
for cursor in cursorScenes.get_children():
|
|
if !(cursor is BattleCursorIcon):
|
|
continue
|
|
if cursor.battlePosition in activePositions:
|
|
if blink:
|
|
cursor.mode = BattleCursorIcon.Mode.BLINKING
|
|
else:
|
|
cursor.mode = BattleCursorIcon.Mode.ACTIVE
|
|
else:
|
|
cursor.mode = BattleCursorIcon.Mode.INACTIVE
|
|
|
|
# Handle movement
|
|
|
|
|
|
# TODO: Allow movement here, wait for selection, etc.
|
|
# Wait 1 second for now and select all possible targets
|
|
await get_tree().create_timer(1.0).timeout
|
|
# selectedPositions = possiblePositions
|
|
|
|
# By this point selection has been made, hide all cursors
|
|
for cursor in cursorScenes.get_children():
|
|
if !(cursor is BattleCursorIcon):
|
|
continue
|
|
cursor.mode = BattleCursorIcon.Mode.INACTIVE
|
|
|
|
# Convert selected positions to fighters
|
|
var targets:Array[BattleFighter] = []
|
|
for pos in selectedPositions:
|
|
var targetFighter = BATTLE.getFighterAtPosition(pos)
|
|
if targetFighter != null:
|
|
targets.append(targetFighter)
|
|
|
|
# Should not be possible to have no targets here
|
|
assert(targets.size() > 0)
|
|
return targets
|
|
|
|
func _getMagicMove(fighter:BattleFighter) -> BattleAction:
|
|
return null
|
|
|
|
func _getItemUse(fighter:BattleFighter) -> BattleAction:
|
|
return null
|
|
|
|
func getFighterSceneAtPosition(pos:BattleSingleton.BattlePosition) -> BattleFighterScene:
|
|
for fighterScene in battleFighterScenes.get_children():
|
|
if !(fighterScene is BattleFighterScene):
|
|
continue
|
|
if fighterScene.battlePosition == pos:
|
|
return fighterScene
|
|
return null
|
|
|
|
func getBattleCursorAtPosition(pos:BattleSingleton.BattlePosition) -> BattleCursorIcon:
|
|
for cursorScene in cursorScenes.get_children():
|
|
if !(cursorScene is BattleCursorIcon):
|
|
continue
|
|
if cursorScene.battlePosition == pos:
|
|
return cursorScene
|
|
return null
|