Change battle actions to use battle decisions instead.
This commit is contained in:
@@ -46,8 +46,7 @@ func startBattle(params) -> void:
|
||||
|
||||
# Initial cutscene elements. In future I may need to make this editable
|
||||
# somehow?
|
||||
for fighter:BattleFighter in params['fighters'].values():
|
||||
battleCutscene.addCallable(BattleCutsceneAction.getPlayerDecisionCallable(fighter))
|
||||
battleCutscene.addCallable(BattleCutsceneAction.getPlayerDecisionCallable())
|
||||
|
||||
# Emit signals
|
||||
active = true
|
||||
@@ -56,7 +55,15 @@ func startBattle(params) -> void:
|
||||
|
||||
# Start running the battle cutscene.
|
||||
if !battleCutscene.running:
|
||||
battleCutscene.start()
|
||||
battleCutscene.start()# Should this await?
|
||||
|
||||
func getFighterAtPosition(battlePos:BattlePosition) -> BattleFighter:
|
||||
return fighterMap.get(battlePos, null)
|
||||
|
||||
func getPositionOfFighter(fighter:BattleFighter) -> BattlePosition:
|
||||
for pos in fighterMap.keys():
|
||||
if fighterMap[pos] == fighter:
|
||||
return pos
|
||||
|
||||
assert(false)
|
||||
return BattlePosition.LEFT_TOP_BACK
|
||||
|
||||
@@ -4,7 +4,6 @@ class_name BattleScene extends Node3D
|
||||
|
||||
func _init() ->void:
|
||||
BATTLE.battleScene = self
|
||||
|
||||
BATTLE.battleStarted.connect(onBattleStarted)
|
||||
|
||||
func onBattleStarted() -> void:
|
||||
|
||||
11
battle/action/BattleAction.gd
Normal file
11
battle/action/BattleAction.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
class_name BattleAction
|
||||
|
||||
var speedModifier:float
|
||||
|
||||
func _init(params:Dictionary) -> void:
|
||||
self.speedModifier = params.get("speedModifier", 1.0)
|
||||
|
||||
func perform(params:Dictionary) -> void:
|
||||
assert(params.has("user"))
|
||||
assert(params.has("target"))
|
||||
pass
|
||||
1
battle/action/BattleAction.gd.uid
Normal file
1
battle/action/BattleAction.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ref2clyh0nc2
|
||||
13
battle/action/BattleDecision.gd
Normal file
13
battle/action/BattleDecision.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
class_name BattleDecision
|
||||
|
||||
var action:BattleAction
|
||||
var user:BattleFighter
|
||||
var target:BattleFighter
|
||||
|
||||
func _init(_action:BattleAction, _user:BattleFighter, _target:BattleFighter) -> void:
|
||||
action = _action
|
||||
user = _user
|
||||
target = _target
|
||||
|
||||
func getPriority() -> float:
|
||||
return 1.0
|
||||
1
battle/action/BattleDecision.gd.uid
Normal file
1
battle/action/BattleDecision.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bhdv13g6t1h01
|
||||
50
battle/action/BattleMove.gd
Normal file
50
battle/action/BattleMove.gd
Normal file
@@ -0,0 +1,50 @@
|
||||
class_name BattleMove extends BattleAction
|
||||
|
||||
enum MoveType {
|
||||
PHYSICAL,
|
||||
ABILITY,
|
||||
MAGICAL,
|
||||
}
|
||||
|
||||
var name:String
|
||||
var power:int
|
||||
var mpCost:int
|
||||
var accuracy:float
|
||||
var moveType:MoveType
|
||||
var fieldUse:bool
|
||||
|
||||
func _init(params:Dictionary) -> void:
|
||||
self.name = params.get("name", "Unknown Move")
|
||||
self.power = params.get("power", 0)
|
||||
self.mpCost = params.get("mpCost", 0)
|
||||
self.speedModifier = params.get("speedModifier", 1.0)
|
||||
self.accuracy = params.get("accuracy", 1.0)
|
||||
self.moveType = params.get("moveType", MoveType.PHYSICAL)
|
||||
self.fieldUse = params.get("fieldUse", false)
|
||||
|
||||
func getPriority(_fighter:BattleFighter) -> float:
|
||||
return 1.0
|
||||
|
||||
# Moves
|
||||
static var MOVE_PUNCH = BattleMove.new({
|
||||
"name": "Punch",
|
||||
"power": 15,
|
||||
"accuracy": 0.95,
|
||||
"moveType": MoveType.PHYSICAL
|
||||
})
|
||||
|
||||
static var MOVE_FIRE1 = BattleMove.new({
|
||||
"name": "Fire",
|
||||
"power": 25,
|
||||
"mpCost": 5,
|
||||
"accuracy": 0.9,
|
||||
"moveType": MoveType.MAGICAL
|
||||
})
|
||||
|
||||
static var MOVE_HEAL1 = BattleMove.new({
|
||||
"name": "Heal",
|
||||
"power": -20,
|
||||
"mpCost": 8,
|
||||
"accuracy": 1.0,
|
||||
"moveType": MoveType.ABILITY
|
||||
})
|
||||
1
battle/action/BattleMove.gd.uid
Normal file
1
battle/action/BattleMove.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://gb08hhwk0paw
|
||||
@@ -102,8 +102,8 @@ func mpRestore(amount:int) -> void:
|
||||
mp = min(mp + amount, maxMp)
|
||||
mpChanged.emit(amount)
|
||||
|
||||
func isCrit() -> bool:
|
||||
# 10% chance of a crit
|
||||
var chance = 10 + min(luck * 5, 60)
|
||||
var roll = randi() % 100
|
||||
return roll < chance
|
||||
func isPlayerControlled() -> bool:
|
||||
return controller == FighterController.PLAYER
|
||||
|
||||
func getAIDecision() -> BattleDecision:
|
||||
return null
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class_name BattleMove
|
||||
class_name BattleMove extends BattleAction
|
||||
|
||||
enum MoveType {
|
||||
PHYSICAL,
|
||||
@@ -9,24 +9,19 @@ enum MoveType {
|
||||
var name:String
|
||||
var power:int
|
||||
var mpCost:int
|
||||
var speedModifier:float
|
||||
var accuracy:float
|
||||
var moveType:MoveType
|
||||
var fieldUse:bool
|
||||
|
||||
func _init(params:Dictionary) -> void:
|
||||
super(params)
|
||||
self.name = params.get("name", "Unknown Move")
|
||||
self.power = params.get("power", 0)
|
||||
self.mpCost = params.get("mpCost", 0)
|
||||
self.speedModifier = params.get("speedModifier", 1.0)
|
||||
self.accuracy = params.get("accuracy", 1.0)
|
||||
self.moveType = params.get("moveType", MoveType.PHYSICAL)
|
||||
self.fieldUse = params.get("fieldUse", false)
|
||||
|
||||
func start(_params:Dictionary) -> void:
|
||||
# Implement move execution logic here
|
||||
await UI.TEXTBOX.setTextAndWait("Action")
|
||||
|
||||
# Moves
|
||||
static var MOVE_PUNCH = BattleMove.new({
|
||||
"name": "Punch",
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://gb08hhwk0paw
|
||||
uid://bgq0u537pt5lm
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
class_name ActionBox extends GridContainer
|
||||
const BattleMove = preload("res://battle/fighter/BattleMove.gd")
|
||||
|
||||
@export var btnAttack:Button
|
||||
@export var btnMagic:Button
|
||||
@export var btnItem:Button
|
||||
|
||||
signal decisionMade(move:BattleMove)
|
||||
signal decisionMade(move:BattleDecision)
|
||||
|
||||
func _ready() -> void:
|
||||
btnAttack.pressed.connect(onAttackPressed)
|
||||
@@ -15,11 +14,11 @@ func _ready() -> void:
|
||||
|
||||
func onAttackPressed() -> void:
|
||||
print("Attack button pressed")
|
||||
decisionMade.emit(BattleMove.MOVE_PUNCH)
|
||||
decisionMade.emit(BattleDecision.new(BattleMove.MOVE_PUNCH, null, null))
|
||||
|
||||
func onMagicPressed() -> void:
|
||||
print("Magic button pressed")
|
||||
decisionMade.emit(BattleMove.MOVE_FIRE1)
|
||||
decisionMade.emit(BattleDecision.new(BattleMove.MOVE_FIRE1, null, null))
|
||||
|
||||
func onItemPressed() -> void:
|
||||
print("Item button pressed")
|
||||
|
||||
@@ -1,14 +1,62 @@
|
||||
class_name BattleAction
|
||||
const BattleFighter = preload("res://battle/fighter/BattleFighter.gd")
|
||||
class_name BattleCutsceneAction
|
||||
|
||||
static func playerDecisionCallable(_params:Dictionary) -> int:
|
||||
BATTLE.battleScene.actionBox.visible = true
|
||||
var move = await BATTLE.battleScene.actionBox.decisionMade
|
||||
BATTLE.battleScene.actionBox.visible = false
|
||||
static func battleDecisionCallable(_params:Dictionary) -> int:
|
||||
print("Battle action executed.")
|
||||
return Cutscene.CUTSCENE_CONTINUE
|
||||
|
||||
static func getPlayerDecisionCallable(fighter:BattleFighter) -> Dictionary:
|
||||
|
||||
static func getBattleDecisionCallable(decision:BattleDecision) -> Dictionary:
|
||||
return {
|
||||
"function": playerDecisionCallable,
|
||||
"fighter": fighter
|
||||
"function": battleDecisionCallable,
|
||||
"decision": decision
|
||||
}
|
||||
|
||||
static func playerDecisionCallable(_params:Dictionary) -> int:
|
||||
var decisions:Array[BattleDecision] = []
|
||||
|
||||
for fighter:BattleFighter in BATTLE.fighterMap.values():
|
||||
if !fighter || !fighter.isPlayerControlled():
|
||||
continue
|
||||
|
||||
# Handle player decision
|
||||
BATTLE.battleScene.actionBox.visible = true
|
||||
var decision = await BATTLE.battleScene.actionBox.decisionMade
|
||||
BATTLE.battleScene.actionBox.visible = false
|
||||
if decision == null:
|
||||
continue
|
||||
decisions.append(decision)
|
||||
|
||||
# AI decisions
|
||||
for fighter:BattleFighter in BATTLE.fighterMap.values():
|
||||
if !fighter || fighter.isPlayerControlled():
|
||||
continue
|
||||
var decision = fighter.getAIDecision()
|
||||
if decision == null:
|
||||
continue
|
||||
decisions.append(decision)
|
||||
|
||||
# Here I could do something like cutscene specific logic?
|
||||
|
||||
# Prioritize moves
|
||||
decisions.shuffle()# Randomizes for moves that have equal chance of happening
|
||||
decisions.sort_custom(func(a:BattleDecision, b:BattleDecision) -> int:
|
||||
var priorityA = a.getPriority()
|
||||
var priorityB = b.getPriority()
|
||||
if priorityA > priorityB:
|
||||
return -1
|
||||
elif priorityA < priorityB:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
)
|
||||
|
||||
# Turn into cutscene actions.
|
||||
for decision in decisions:
|
||||
_params['cutscene'].addCallable(BattleCutsceneAction.getBattleDecisionCallable(decision))
|
||||
|
||||
return Cutscene.CUTSCENE_CONTINUE
|
||||
|
||||
static func getPlayerDecisionCallable() -> Dictionary:
|
||||
return {
|
||||
"function": playerDecisionCallable
|
||||
}
|
||||
|
||||
@@ -7,17 +7,23 @@ class_name RootScene extends Node3D
|
||||
@export var currentScene:Node = null
|
||||
|
||||
func _enter_tree() -> void:
|
||||
SCENE.sceneChanged.connect(onSceneChange)
|
||||
SCENE.setScene(SceneSingleton.SceneType.INITIAL)
|
||||
# SCENE.sceneChanged.connect(onSceneChange)
|
||||
# SCENE.setScene(SceneSingleton.SceneType.INITIAL)
|
||||
|
||||
# SCENE.setScene(SceneSingleton.SceneType.BATTLE)
|
||||
# # Wait a frame
|
||||
# await get_tree().process_frame
|
||||
# BATTLE.startBattle({
|
||||
# 'fighters': {
|
||||
# BATTLE.BattlePosition.RIGHT_TOP_FRONT: PartySingleton.PARTY_JOHN,
|
||||
# }
|
||||
# })
|
||||
SCENE.setScene(SceneSingleton.SceneType.BATTLE)
|
||||
# Wait a frame
|
||||
await get_tree().process_frame
|
||||
|
||||
var testEnemy = BattleFighter.new({
|
||||
'controller': BattleFighter.FighterController.AI
|
||||
})
|
||||
BATTLE.startBattle({
|
||||
'fighters': {
|
||||
# Test fighters
|
||||
BATTLE.BattlePosition.RIGHT_MIDDLE_FRONT: PartySingleton.PARTY_JOHN,
|
||||
BATTLE.BattlePosition.LEFT_MIDDLE_FRONT: testEnemy
|
||||
}
|
||||
})
|
||||
|
||||
func _exit_tree() -> void:
|
||||
push_error("RootScene should not be removed from the scene tree. This is a bug.")
|
||||
|
||||
@@ -31,3 +31,4 @@ visible = false
|
||||
[node name="CurrentScene" type="Node" parent="."]
|
||||
|
||||
[node name="RootUI" parent="." instance=ExtResource("6_ajii0")]
|
||||
visible = false
|
||||
|
||||
Reference in New Issue
Block a user