Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class structure for the cards #27

Merged
merged 19 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e3656d9
Added a base template for effects and relevant functions in CardBase
Turtyo Dec 18, 2023
f02be75
Reformated to use a list of targets and moved some functions to other…
Turtyo Dec 18, 2023
4310bd8
Update Battler to have correct function signature
Turtyo Dec 18, 2023
933ed1d
Simplified _damage_entity since the new logic of effects is applied t…
Turtyo Dec 18, 2023
2669640
Simplified can_play_card
Turtyo Dec 18, 2023
0e311fe
Moved the draw to an effect, changed value from float to int
Turtyo Dec 18, 2023
2f6f856
Moved the discard random to an effect
Turtyo Dec 18, 2023
5b39fce
Made the EffectPoison to have a reference for other Status effects
Turtyo Dec 18, 2023
3512e4d
Moved the deal damage to an effect
Turtyo Dec 18, 2023
1256839
Changed effects from Node to Resource
Turtyo Dec 19, 2023
e1963a9
Modified Battler and Enemy to work with the new effect structure
Turtyo Dec 21, 2023
c028d34
Changed EffectData to prevent an init bug | Added basic targeting fun…
Turtyo Dec 21, 2023
6ac8308
Modified EffectDamage
Turtyo Dec 21, 2023
4e58369
Modified damage and draw resources cards to work with new effect system
Turtyo Dec 21, 2023
584d43e
Modified poison to work with new system
Turtyo Dec 21, 2023
221a971
Added a card with multiple effects to test the current structure
Turtyo Dec 21, 2023
c6a1bba
Tried an effect that was a bit more complex
Turtyo Dec 21, 2023
d00f2ba
Changed parameter name from entity to target for more clarity
Turtyo Dec 21, 2023
7caeeff
Removed unused commented line in tests
Turtyo Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 19 additions & 60 deletions Cards/CardBase.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,78 +18,37 @@ class_name CardBase
@export var damage_to_apply_to_caster: float = 0.0
@export var status_to_apply_to_target: Array[StatusBase]
@export var status_to_apply_to_caster: Array[StatusBase]
@export var affect_all_targets: bool = false
@export var affect_all_casters: bool = false
# @export var affect_all_targets: bool = false
# @export var affect_all_casters: bool = false
# not needed since we use a list of targets, and the party can also be targets
@export var amount_of_cards_to_draw: int = 0
@export var amount_of_cards_to_discard: int = 0
@export var application_type: Enums.ApplicationType = Enums.ApplicationType.ENEMY_ONLY
@export var card_title: String = "NULL"
@export var card_key_art: ImageTexture = null
@export var card_description: String = "NULL"

var card_effects_data: Array[EffectData] = []

func can_play_card(caster: Entity, target: Entity) -> bool:
if caster.get_party_component().can_play_on_entity(application_type, target):
return true
return false


func on_card_play(caster: Entity, target: Entity) -> void:
_deal_damage(caster, target)
_apply_status(caster, target)
_draw_cards()
_discard_random_cards()
# TODO add other functionality that lots of cards may share (eg: restore AP)

func _ready() -> void:
card_effects_data = []

# override in child cards if you want to deal damage in a unique way
func _deal_damage(caster: Entity, target: Entity) -> void:
# damage target
if damage_to_apply_to_target != 0.0:
_damage_entity(caster, target, damage_to_apply_to_target, affect_all_targets)

#damage caster
if damage_to_apply_to_caster != 0.0:
_damage_entity(caster, caster, damage_to_apply_to_caster, affect_all_casters)
# Need a parser of some sort to read a plainform card data and translate it to EffectData
# This will call EffectData.add_effect_data() in a loop for every new effect
Turtyo marked this conversation as resolved.
Show resolved Hide resolved

@warning_ignore("unused_parameter")
func parse_card_data(card_data: Dictionary) -> void:
# TODO
pass

func _damage_entity(caster: Entity, target: Entity, damage_amount: float, damage_all: bool) -> void:
var target_damage_data: DealDamageData = DealDamageData.new()
target_damage_data.damage = damage_amount
target_damage_data.caster = caster

# If damage_all is set, try to damage all the party members set in the party component
if damage_all:
var party: Array[Entity] = target.get_party_component().party
assert(party.size() > 0, "Entity has an empty party. Make sure you added party members.")

for party_member: Entity in party:
party_member.get_health_component().deal_damage(target_damage_data)
else:
target.get_health_component().deal_damage(target_damage_data)
func _apply_all_effects() -> void:
for effect_data: EffectData in card_effects_data:
effect_data.apply_effect_data()


func _apply_status(caster: Entity, target: Entity) -> void:
# apply status to caster
for status: StatusBase in status_to_apply_to_caster:
if affect_all_casters:
for party_member: Entity in caster.get_party_component().party:
party_member.get_status_component().add_status(status, caster)
else:
caster.get_status_component().add_status(status, caster)

# apply status to target
for status: StatusBase in status_to_apply_to_target:
if affect_all_targets:
for party_member: Entity in target.get_party_component().party:
party_member.get_status_component().add_status(status, caster)
else:
target.get_status_component().add_status(status, caster)


func _draw_cards() -> void:
CardManager.card_container.draw_cards(amount_of_cards_to_draw)
func can_play_card(caster: Entity, target: Entity) -> bool:
return caster.get_party_component().can_play_on_entity(application_type, target)


func _discard_random_cards() -> void:
CardManager.card_container.discard_random_card(amount_of_cards_to_discard)
func on_card_play() -> void:
_apply_all_effects()
10 changes: 10 additions & 0 deletions Cards/Effects/EffectBase.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Base class for card effects
class_name EffectBase extends Node
Turtyo marked this conversation as resolved.
Show resolved Hide resolved

@warning_ignore("unused_parameter")
func apply_effect(caster: Entity, target: Entity, value: int) -> void:
pass

# To be called by child classes through apply_effect. But since there might be multiple effects that need it, it's available in the parent class
func _apply_status(status: StatusBase, caster: Entity, target: Entity) -> void:
target.get_status_component().add_status(status, caster)
12 changes: 12 additions & 0 deletions Cards/Effects/EffectDamage.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class_name EffectDamage extends EffectBase

# @Override
func apply_effect(caster: Entity, target: Entity, value: int) -> void:
var target_damage_data: DealDamageData = DealDamageData.new()
target_damage_data.damage = value
target_damage_data.caster = caster
target.get_health_component().deal_damage(target_damage_data)

# TODO : what to do for Status that inflige damage over time ?
# Should they call an EffectDamage when they trigger each turn ?
# or should they directly call deal_damage on the target ?
Turtyo marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 22 additions & 0 deletions Cards/Effects/EffectData.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class_name EffectData extends Node
Turtyo marked this conversation as resolved.
Show resolved Hide resolved

# Effect data is a wrapper for the Effect class. It contains an effect, a caster, a target and a value (which will be applied by the effect)

var effect: EffectBase = null
var caster: Entity = null
var list_targets: Array[Entity] = []
var value: int = 0

func _init(_effect: EffectBase, _caster: Entity, _list_targets: Array[Entity], _value: int) -> void:
self.effect = _effect
self.caster = _caster
self.list_targets = _list_targets
self.value = _value

func add_effect_data(card: CardBase, _effect: EffectBase, _caster: Entity, _list_targets: Array[Entity], _value: int) -> void:
card.card_effects_data.append(EffectData.new(_effect, _caster, _list_targets, _value))

func apply_effect_data() -> void:
# Help function to call more easily from the card point of view
for target: Entity in list_targets:
self.effect.apply_effect(self.caster, target, self.value)
6 changes: 6 additions & 0 deletions Cards/Effects/EffectDiscardRandom.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class_name EffectDiscardRandom extends EffectBase

# @Override
@warning_ignore("unused_parameter")
func apply_effect(caster: Entity, target: Entity, value: int) -> void:
CardManager.card_container.discard_random_card(value)
6 changes: 6 additions & 0 deletions Cards/Effects/EffectDraw.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class_name EffectDraw extends EffectBase

# @Override
@warning_ignore("unused_parameter")
func apply_effect(caster: Entity, target: Entity, value: int) -> void:
CardManager.card_container.draw_cards(value)
8 changes: 8 additions & 0 deletions Cards/Effects/EffectPoison.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class_name EffectPoison extends EffectBase

# @Override
func apply_effect(caster: Entity, target:Entity, value: int) -> void:
var debuff_poison: Debuff_Poison = Debuff_Poison.new()
# if not instanciated, the debuff is not seen as a child of StatusBase
debuff_poison.status_turn_duration = value
_apply_status(debuff_poison, caster, target)
2 changes: 0 additions & 2 deletions Cards/Resource/Card_Poison.tres
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ damage_to_apply_to_target = 0.0
damage_to_apply_to_caster = 0.0
status_to_apply_to_target = Array[Resource("res://Status/StatusBase.gd")]([SubResource("Resource_0h6wx")])
status_to_apply_to_caster = Array[Resource("res://Status/StatusBase.gd")]([])
affect_all_targets = false
affect_all_casters = false
amount_of_cards_to_draw = 0
amount_of_cards_to_discard = 0
application_type = 1
Expand Down
4 changes: 2 additions & 2 deletions Core/Battler.gd
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func _on_enemy_start_turn() -> void:
assert(can_attack == true, "Enemy failed to attack.")

if can_attack:
enemy_attack.on_card_play(enemy, PlayerManager.player)
enemy_attack.on_card_play()

# TODO: temporary delay so we can see the draw pile and discard pile working
await get_tree().create_timer(enemy_attack_time).timeout
Expand All @@ -99,4 +99,4 @@ func _try_player_play_card_on_entity(entity: Entity) -> void:
# remove queued card, then play the card
# This is so the queued card doesn't have any influence over our hand count
CardManager.card_container.remove_queued_card()
queued_card_data.on_card_play(PlayerManager.player, entity)
queued_card_data.on_card_play()
2 changes: 1 addition & 1 deletion Tests/test_cards.gd
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var _battler_scene: PackedScene = load("res://Core/Battler.tscn")
var _card_container_scene: PackedScene = load("res://Cards/CardContainer.tscn")
var _battler: Battler = null
var _card_container: CardContainer = null
var _cards_in_hand: Array[CardWorld] = []
# var _cards_in_hand: Array[CardWorld] = []
Tysterman74 marked this conversation as resolved.
Show resolved Hide resolved


func before_each():
Expand Down
8 changes: 4 additions & 4 deletions addons/gut/gui/GutSceneTheme.tres

Large diffs are not rendered by default.

Loading