diff --git a/battle/Battle.gd b/battle/Battle.gd index 3863279..232cb48 100644 --- a/battle/Battle.gd +++ b/battle/Battle.gd @@ -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 diff --git a/battle/BattleScene.gd b/battle/BattleScene.gd index f25de22..31ae508 100644 --- a/battle/BattleScene.gd +++ b/battle/BattleScene.gd @@ -4,7 +4,6 @@ class_name BattleScene extends Node3D func _init() ->void: BATTLE.battleScene = self - BATTLE.battleStarted.connect(onBattleStarted) func onBattleStarted() -> void: diff --git a/battle/action/BattleAction.gd b/battle/action/BattleAction.gd new file mode 100644 index 0000000..bcfe5db --- /dev/null +++ b/battle/action/BattleAction.gd @@ -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 \ No newline at end of file diff --git a/battle/action/BattleAction.gd.uid b/battle/action/BattleAction.gd.uid new file mode 100644 index 0000000..fe96f17 --- /dev/null +++ b/battle/action/BattleAction.gd.uid @@ -0,0 +1 @@ +uid://ref2clyh0nc2 diff --git a/battle/action/BattleDecision.gd b/battle/action/BattleDecision.gd new file mode 100644 index 0000000..885bb60 --- /dev/null +++ b/battle/action/BattleDecision.gd @@ -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 diff --git a/battle/action/BattleDecision.gd.uid b/battle/action/BattleDecision.gd.uid new file mode 100644 index 0000000..930d185 --- /dev/null +++ b/battle/action/BattleDecision.gd.uid @@ -0,0 +1 @@ +uid://bhdv13g6t1h01 diff --git a/battle/action/BattleMove.gd b/battle/action/BattleMove.gd new file mode 100644 index 0000000..c31fc25 --- /dev/null +++ b/battle/action/BattleMove.gd @@ -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 +}) \ No newline at end of file diff --git a/battle/action/BattleMove.gd.uid b/battle/action/BattleMove.gd.uid new file mode 100644 index 0000000..c6ea759 --- /dev/null +++ b/battle/action/BattleMove.gd.uid @@ -0,0 +1 @@ +uid://gb08hhwk0paw diff --git a/battle/fighter/BattleFighter.gd b/battle/fighter/BattleFighter.gd index cedc900..ade093c 100644 --- a/battle/fighter/BattleFighter.gd +++ b/battle/fighter/BattleFighter.gd @@ -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 diff --git a/battle/fighter/BattleMove.gd b/battle/fighter/BattleMove.gd index 519d18a..13f735f 100644 --- a/battle/fighter/BattleMove.gd +++ b/battle/fighter/BattleMove.gd @@ -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", diff --git a/battle/fighter/BattleMove.gd.uid b/battle/fighter/BattleMove.gd.uid index c6ea759..0429769 100644 --- a/battle/fighter/BattleMove.gd.uid +++ b/battle/fighter/BattleMove.gd.uid @@ -1 +1 @@ -uid://gb08hhwk0paw +uid://bgq0u537pt5lm diff --git a/battle/ui/ActionBox.gd b/battle/ui/ActionBox.gd index 24257eb..417dadb 100644 --- a/battle/ui/ActionBox.gd +++ b/battle/ui/ActionBox.gd @@ -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,12 +14,12 @@ 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") decisionMade.emit(null) \ No newline at end of file diff --git a/cutscene/battle/BattleCutsceneAction.gd b/cutscene/battle/BattleCutsceneAction.gd index b3f198d..cd774d4 100644 --- a/cutscene/battle/BattleCutsceneAction.gd +++ b/cutscene/battle/BattleCutsceneAction.gd @@ -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 } diff --git a/scene/RootScene.gd b/scene/RootScene.gd index e78b68d..344f8a2 100644 --- a/scene/RootScene.gd +++ b/scene/RootScene.gd @@ -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.") diff --git a/scene/RootScene.tscn b/scene/RootScene.tscn index 02280a8..2ff2244 100644 --- a/scene/RootScene.tscn +++ b/scene/RootScene.tscn @@ -31,3 +31,4 @@ visible = false [node name="CurrentScene" type="Node" parent="."] [node name="RootUI" parent="." instance=ExtResource("6_ajii0")] +visible = false