1
\$\begingroup\$

I am building a card game. Let's say it's similar to Magic the Gathering, Hearthstone, etc.

The problem I am trying to figure out is how to architect "auras" and how much damage each card takes.

Right now I have a deck and I store card data as follows. I've made up names for the types of cards that will exist.

M.card = {} -- Minion cards have health and damage M.card[1].name = "Minion" M.card[1].hp = 1 M.deck[1].dmg = 1 -- Super Minions have more health and damage M.card[2].name = "Super Minion" M.card[2].hp = 4 M.card[2].dmg = 4 -- Spell cards have no health and damage. Instead they affect the health and damage of other cards. M.card[3].name = "Heal" M.card[3].details = "This card heals any character for +2 health" M.card[3].healthboost = 2 M.card[4].name = "Damage Boost" M.card[4].details = "This card gives + 1 damage to any other card for 1 turn" M.card[4].dmgboost = 1 -- Super damage boost gives more damage boost to other cards M.card[5].name = "Super Damage Boost" M.card[5].details = "This card gives +3 damage to any other card permanently" M.card[5].dmgboost = 3 

So when one card attacks another card, I need to keep track of the damage taken by both cards. I don't want to change the base stats of each card so I need to keep track of adjustments.

I could do something like this

-- Super Minion takes 3 damage M.card[2].newHp = 1 -- or M.card[2].adjHp = -3 -- Not sure which is better. 

During the battle I need to keep track of which auras are played. So for example if the Damage boost card is played. I need to give another card +1 damage for just one turn.

Let's say that I am keep track of each turn number starting from 1.

Should I do something like this M.aura[1] = 4 -- ( aura 1 is card # 4) M.aura[1].target = 2 -- (this aura is applied to card 2) M.aura[1].expires = 5 -- (this aura expires on turn 5)

M.aura[2] = 3 ( second active aura is heal, card #3 ) M.aura[2].target = 2 M.aura[2].expires = 0 -- this is a one time aura. So I need to apply it to card #2 and then immediately expire it so it never activates again. 

Then on every new turn I loop through all the auras and make sure they are still active before a fight begins?

Just wondering architecturally what is the best way to keep track of Damage that characters have taken and spells that are active that are giving characters special abilities.

\$\endgroup\$
0

2 Answers 2

0
\$\begingroup\$

Looks like you want Lua metatables! (http://www.lua.org/manual/5.2/manual.html#2.4)

Metatables are a way of adding extended functionality to Lua tables by changing the effect of different operations on the table. (addition, subtraction, indexing, inserting into a table, etc.) If you set the __index metafunction for a metatable to the original card's table, you can - in a sense - inherit properties/functions of that card.

For example,

-- Hold a list of master cards, that wont change Cards = {} Cards["Minion"] = { name = "Minion", hp= 1, dmg= 1 } -- Insert a card to the player's hand: (In Lua, arrays start at 1) -- Realistically, you'll want a function to do this. M = { cards = { [1] = {} }} setmetatable(M.cards[1], { __index = Cards["Minion"] }); -- Then, when you alter the value of "hp", you aren't changing the original health. M.cards[1].hp = M.cards[1].hp - 1; print(M.cards[1].hp) -- Prints '0' print(Cards["Minion"].hp) -- Prints '1' 

Generally, this is the method you want to follow for giving state to an object in Lua. Create a table, and apply a metatable that represents the functionality of the "class" or "object" it represents.

Keep in mind this is the approach if you want to stay completely in Lua.

EDIT (For misinformation):

I am sorry, when I originally posted my clarification, it was incorrect. You can, in fact, edit the value you inherit off __index. __index will copy the value into the table, so numeric values can change without any issues. (Please see changes above!)

\$\endgroup\$
1
\$\begingroup\$

The easiest approach is to have separate "card instance" objects from "card template" objects. A deck then is a collection of card instances, and each instance references its template. Something like:

 class CardTemplate { uuid id; string name; int base_hp; }; class CardInstance { CardTemplate template; int current_hp; }; 

This has several advantages. The most relevant to your question is that you can have the card's HP change fully independent of the template, both above and below (useful for damage, buffs, debuffs, etc.).

You might find that you need to also have a third struct to make things easier as these types of games often have a large amount of data that can change, e.g.

struct CardInfo { int base_hp; int current_hp; }; 

Because your mechanics might want to differentiate from damage and buffs/debuffs in its UI, e.g. a buff to health might increment both base_hp and current_hp. You can check if a card has its health buffed by comparing its base_hp against that of its template, and can check if it's damaged easily by comparing current_hp against its own base_hp.

It will further come in handy to have stacks of effects with their modifiers (which field they modify and by how much), source cards, durations, all kinds of stuff.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.