RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
battle_manager.gd
Go to the documentation of this file.
1extends RefCounted
2
3
9
10var active := false
11var player_card := {}
12var opponent_card := {}
13var player_hp := 0
14var opponent_hp := 0
15var player_turn := true
16var reward := 0
17var log := []
18
19
20
21func battle(player_card:Dictionary, opponent_card:Dictionary, reward:int = 100) -> Dictionary:
22 if player_card.is_empty() or opponent_card.is_empty():
23 return {"winner": "none", "log": ["No battle could be started."], "reward": 0}
24
25 var player = player_card.duplicate(true)
26 var opponent = opponent_card.duplicate(true)
27 var player_hp = int(player.get("health", 1))
28 var opponent_hp = int(opponent.get("health", 1))
29 var player_turn = randi_range(0, 1) == 0
30 var log = [
31 "%s faces %s." % [player.get("name", "Player"), opponent.get("name", "Opponent")]
32 ]
33
34 while player_hp > 0 and opponent_hp > 0:
35 if player_turn:
36 var damage = _roll_damage(player, opponent)
37 opponent_hp -= damage
38 log.append("%s hits for %d." % [player.get("name", "Player"), damage])
39 else:
40 var damage = _roll_damage(opponent, player)
41 player_hp -= damage
42 log.append("%s hits for %d." % [opponent.get("name", "Opponent"), damage])
43 player_turn = not player_turn
44
45 var player_won = player_hp > 0
46 log.append("%s wins." % [player.get("name", "Player") if player_won else opponent.get("name", "Opponent")])
47 return {
48 "winner": "player" if player_won else "opponent",
49 "reward": reward if player_won else 0,
50 "log": log
51 }
52
53
54func _roll_damage(attacker:Dictionary, defender:Dictionary) -> int:
55 return max(1, int(attacker.get("attack", 1)) + randi_range(1, 6) - int(defender.get("defense", 0)))
56
57
58
60func start_battle(selected_player_card:Dictionary, selected_opponent_card:Dictionary, battle_reward:int = 100, starting_opponent_hp:int = -1) -> Dictionary:
61 player_card = selected_player_card.duplicate(true)
62 opponent_card = selected_opponent_card.duplicate(true)
63 player_hp = int(player_card.get("health", 1))
64 opponent_hp = starting_opponent_hp if starting_opponent_hp > 0 else int(opponent_card.get("health", 1))
65 player_turn = randi_range(0, 1) == 0
66 reward = battle_reward
67 active = not player_card.is_empty() and not opponent_card.is_empty()
68 log = []
69 if active:
70 log.append("%s faces %s." % [player_card.get("name", "Player"), opponent_card.get("name", "Opponent")])
71 log.append("%s has initiative." % [player_card.get("name", "Player") if player_turn else opponent_card.get("name", "Opponent")])
72 else:
73 log.append("No battle could be started.")
74 return get_state()
75
76
77
78func clear_opponent() -> void:
79 active = false
80 player_card = {}
81 opponent_card = {}
82 player_hp = 0
83 opponent_hp = 0
84 log = []
85
86
87
88func take_turn() -> Dictionary:
89 if not active:
90 return get_state()
91
92 if player_turn:
93 var player_roll = randi_range(1, 6)
94 var player_damage = _calculate_damage(player_card, opponent_card, player_roll)
95 opponent_hp -= player_damage
96 log.append("%s rolls %d and deals %d damage." % [player_card.get("name", "Player"), player_roll, player_damage])
97 else:
98 var opponent_roll = randi_range(1, 6)
99 var opponent_damage = _calculate_damage(opponent_card, player_card, opponent_roll)
100 player_hp -= opponent_damage
101 log.append("%s rolls %d and deals %d damage." % [opponent_card.get("name", "Opponent"), opponent_roll, opponent_damage])
102
103 if player_hp <= 0 or opponent_hp <= 0:
104 active = false
105 log.append("%s wins." % [player_card.get("name", "Player") if player_hp > 0 else opponent_card.get("name", "Opponent")])
106 else:
107 player_turn = not player_turn
108
109 return get_state()
110
111
112
113func get_state() -> Dictionary:
114 return {
115 "active": active,
116 "player_card": player_card,
117 "opponent_card": opponent_card,
118 "player_hp": max(0, player_hp),
119 "opponent_hp": max(0, opponent_hp),
120 "player_turn": player_turn,
121 "winner": get_winner(),
122 "reward": reward if get_winner() == "player" else 0,
123 "log": log.duplicate()
124 }
125
126
127
128func get_winner() -> String:
129 if active:
130 return ""
131 if player_card.is_empty() or opponent_card.is_empty():
132 return "none"
133 return "player" if player_hp > 0 else "opponent"
134
135
136func _calculate_damage(attacker:Dictionary, defender:Dictionary, roll:int) -> int:
137 return max(1, int(attacker.get("attack", 1)) + roll - int(defender.get("defense", 0)))
int
Run a complete battle immediately and return winner/reward/log state.