Godot Version
4.7.1 stable
Question
This is sort of a programming question, but also sort of a general design question.
Lots of ARPGs have weapons which have a damage stat. When a character equips such a weapon, the damage is used as a modifier for their total attack stat. When they actually attack, the damage dealt is equal to the character’s attack stat. That’s the sort of system I was envisioning that I wanted.
If you’re willing to check out this really old browser game for a couple minutes, I was basically hoping to just replicate its weapon and attack system. How it works should be pretty apparent if you fiddle with the inventory a bit and look at the character stats.
Weapons extend Resource in my game, so I just put the damage stats right on Weapon as a variable.
Then I started learning about composition. After lots of forethought, I decided I wanted the actual behavior of the weapon (like if it fires a projectile, spawns a melee attack, summons something, does a hitscan, etc.) to be a component. I call it AttackBehavior. With that, I could make lots of different weapons with data.
Here’s what that portion of the Weapon script looks like for me with that. This felt like it would be simple and easy to work with.
But then something felt a little wrong. The range and the cooldown of the weapon definitely feel like they belong on the weapon, since they determine when you can use it. But what about the damage? That feels more like an effect on the actual behavior itself…
One of the many reasons I wanted this AttackBehavior component was so that I could give weapons secondary effects, like the game I linked above. For example, a projectile that explodes on impact, and the explosion does a different amount of damage than the projectile itself.
So to me, it feels like in actuality, something like damage (and other stats associated with a particular behavior, like “speed” for projectiles or “duration” for summons, to name a few) should actually be on the AttackBehavior.
Then, when making that “exploding projectile” weapon, you would have two different AttackBehaviors stored somewhere: one with the projectile’s damage, and one with the explosion’s damage.
Problem #1 for me here is… where should those behaviors actually go? Should AttackBehavior itself have a variable for another AttackBehavior it can spawn on hit? Or, should there just be a second behavior variable right on Weapon itself?
And problem #2… in this game, I don’t want the character’s attack stat to be used for such secondary effects, like the explosion. Imagine a melee sword attack, and it’s a magic sword that does some extra splash damage. I think I would want to use the character’s attack stat for the sword swing, but the splash damage should be determined by the weapon alone, not the player’s stats. But that would mean damage is handled in two different ways… so I’m confused even further about where to actually put the damage stats or how to apply damage in the first place. For this reason, I’m open to reconsider how calculating damage in my game should even work in the first place, because maybe some other calculation method would make more sense if I want more modularity. But I was just kind of hoping I could make something like that game I linked, or like I described at the start.
For some final context, the actual AttackBehavior class is just an abstract class that looks like this for now. I’m planning on extending it into four types at the moment: projectiles, melee attacks, summons, and hitscans. I pass in an “AttackPackage” as a parameter, which holds the context for that moment of the game. It’s a snapshot of the attacker, the target, and all stats of the attacker and the weapon at the time of use.
I would appreciate any help figuring this out! I really like having this AttackBehavior component, but figuring out how to put it all together is making me scratch my head. Especially in a way that makes sense for the player. Also, the reason I have a lot of these other components figured out already is because I already made a prototype a long time ago when I first learned to code… by using terrible amounts of inheritance and duplicated code. So this is actually my attempt to clean things up, rather than starting from nothing.

