118 lines
3.8 KiB
GDScript
118 lines
3.8 KiB
GDScript
class_name BattleCutsceneAction
|
|
const DialogueAction = preload("res://cutscene/dialogue/DialogueAction.gd")
|
|
|
|
static var NARRATION:DialogueResource = preload("res://dialogue/battle/narration.dialogue")
|
|
|
|
# State object passed as extra_game_states so {{variable}} tokens resolve in the dialogue file.
|
|
class BattleNarrationState:
|
|
var fighter_name:String
|
|
var user_name:String
|
|
var target_name:String
|
|
var move_name:String
|
|
var damage:int
|
|
|
|
func _init(params:Dictionary) -> void:
|
|
fighter_name = params.get('fighter_name', '')
|
|
user_name = params.get('user_name', '')
|
|
target_name = params.get('target_name', '')
|
|
move_name = params.get('move_name', '')
|
|
damage = params.get('damage', 0)
|
|
|
|
# Narrates and executes a single fighter's decision.
|
|
static func battleDecisionCallable(params:Dictionary) -> int:
|
|
var decision:BattleDecision = params['decision']
|
|
var state = BattleNarrationState.new({
|
|
'user_name': decision.user.name if decision.user is PartyMember else 'Enemy',
|
|
'move_name': decision.action.handle,
|
|
'target_name': decision.targets[0].name if decision.targets[0] is PartyMember else 'Enemy',
|
|
})
|
|
|
|
var cutscene:Cutscene = params['cutscene']
|
|
cutscene.addCallable(
|
|
DialogueAction.getDialogueCallable(NARRATION, 'move_perform', [state]).merged(
|
|
{'position': Cutscene.CUTSCENE_ADD_NEXT}, false
|
|
)
|
|
)
|
|
decision.action.perform({'user': decision.user, 'targets': decision.targets})
|
|
return Cutscene.CUTSCENE_CONTINUE
|
|
|
|
static func getBattleDecisionCallable(decision:BattleDecision) -> Dictionary:
|
|
return {
|
|
'function': battleDecisionCallable,
|
|
'decision': decision,
|
|
}
|
|
|
|
static func playerDecisionCallable(params:Dictionary) -> int:
|
|
# Check end conditions
|
|
var allPlayersDead:bool = true
|
|
var allEnemiesDead:bool = true
|
|
for fighter:BattleFighter in BATTLE.fighterMap.values():
|
|
if fighter == null:
|
|
continue
|
|
if fighter.status == BattleFighter.Status.DEAD:
|
|
continue
|
|
if fighter.isPlayerControlled():
|
|
allPlayersDead = false
|
|
else:
|
|
allEnemiesDead = false
|
|
|
|
if allPlayersDead:
|
|
params['cutscene'].addCallable(
|
|
DialogueAction.getDialogueCallable(NARRATION, 'battle_defeat').merged(
|
|
{'position': Cutscene.CUTSCENE_ADD_NEXT}, false
|
|
)
|
|
)
|
|
return Cutscene.CUTSCENE_END
|
|
|
|
if allEnemiesDead:
|
|
params['cutscene'].addCallable(
|
|
DialogueAction.getDialogueCallable(NARRATION, 'battle_victory').merged(
|
|
{'position': Cutscene.CUTSCENE_ADD_NEXT}, false
|
|
)
|
|
)
|
|
return Cutscene.CUTSCENE_END
|
|
|
|
# Collect fighters
|
|
var playerFighters:Array[BattleFighter] = []
|
|
var aiFighters:Array[BattleFighter] = []
|
|
for fighter:BattleFighter in BATTLE.fighterMap.values():
|
|
if !fighter || !fighter.canPlayerMakeDecision():
|
|
continue
|
|
playerFighters.append(fighter)
|
|
for fighter:BattleFighter in BATTLE.fighterMap.values():
|
|
if !fighter || !fighter.canMakeDecision():
|
|
continue
|
|
if fighter in playerFighters:
|
|
continue
|
|
aiFighters.append(fighter)
|
|
|
|
# Gather decisions
|
|
var decisions:Array[BattleDecision] = []
|
|
var playerDecisions = await BATTLE.battleScene.getBattleDecisions(playerFighters)
|
|
decisions.append_array(playerDecisions)
|
|
for fighter in aiFighters:
|
|
var decision = fighter.getAIDecision()
|
|
if decision != null:
|
|
decisions.append(decision)
|
|
|
|
# Sort by priority
|
|
decisions.shuffle()
|
|
decisions.sort_custom(func(a:BattleDecision, b:BattleDecision) -> int:
|
|
var pa = a.getPriority()
|
|
var pb = b.getPriority()
|
|
if pa > pb: return -1
|
|
elif pa < pb: return 1
|
|
else: return 0
|
|
)
|
|
|
|
for decision in decisions:
|
|
params['cutscene'].addCallable(getBattleDecisionCallable(decision))
|
|
|
|
params['cutscene'].addCallable(getPlayerDecisionCallable())
|
|
return Cutscene.CUTSCENE_CONTINUE
|
|
|
|
static func getPlayerDecisionCallable() -> Dictionary:
|
|
return {
|
|
'function': playerDecisionCallable,
|
|
}
|