jwm
New Member
Posts: 3
|
Post by jwm on Mar 10, 2019 10:44:00 GMT
Hey there,
I posted on the stats page of your blog the following, and was asked to bring it here for more of a discussion:
Hello, love these posts. I am making a little tactics game in my free time and the focus on architecture and design has been very helpful, especially this post about exceptions, which was a real stumbling block for me. I have a question about modelling derived stats. Say you have an armor class, that is based off your Agility, but can be adjusted separately from Agility. Derived stats wouldn’t need to be stored in job or class data or save data, but calculated at run time based on base stats and exceptions. Curious how would you expand the design from the post to model something like this? I’ve been trying to come up with an elegant solution and coming up.. inelegant…
You brought up using something like an ability or item to augment the stat, but I think that would be a different use case. I hope that I am not over thinking this! The following is an example of what I am thinking of:
Intimidation, defined as your Charisma plus ranks in a skill or however it is raised, plus intimidation specific bonuses from equipment/spells/whatever. If your charisma goes up, so does the intimidate. But if something only improves your intimidation skill, that doesn't improve your charisma.
Creating a wrapper class for each derived stat, or even a generic wrapper for derived stats in general which listens for changes of its base stat (the solution I am currently using), seems like its maybe taking the long way around. It seems like it treats these stats as somehow separate, when they are not so different really. I have a few thoughts on ways to model this, but since I found your blog, I figured I'd pick your brain and see if I am missing something obvious that you already set up. Or anyone reading, I'd love to hear your thoughts.
|
|
|
Post by Admin on Mar 12, 2019 13:39:33 GMT
I think I understand a bit better now what you are asking about. If I fully understood how you intended to use this derived skill it would help as well. For example, is Intimidation an ability all by itself, or is it just a stat that you want to factor into your other abilities?
I don't know if you'd think I created this setup "exactly" but take a look at the "DamageAbilityEffect" script and its "Predict" method. In a way, I consider there to be several derived stats all determined in this one place. For example, there is an "attack" and "power" stat for the attacker, as well as a "defense" stat for the target. These stats can all be based partly on actual stats as well as bonuses from items, applied effects, or anything else for that matter thanks to the notification patterns.
The stats are only determined when I need them, because if I had to keep a running tally of the stat, I might need to add maintenance code in many places. For example, it might be modified inside and outside of battle, on a large variety of screens such as when changing armor, when casting or removing spells, etc.
|
|
jwm
New Member
Posts: 3
|
Post by jwm on Mar 13, 2019 1:56:59 GMT
Example: Joe the Magicman:Charisma (a base stat): 10 Intimidate Ranks (a base stat): 3 Intimidate (when queried for): 13 Sweet Talk Ranks (a base stat): 6 Sweet Talk (when queried for): 16 He puts on an intimidating hat (+Intimidate): Charisma (a base stat): 10 Intimidate Ranks (a base stat): 6Intimidate (when queried for): 16Sweet Talk Ranks (a base stat): 6 Sweet Talk (when queried for): 16 He instead puts on a loud and distasteful hat (-Charisma):Charisma (a base stat): 7Intimidate Ranks (a base stat): 3 Intimidate (when queried for): 10Sweet Talk Ranks (a base stat): 6 Sweet Talk (when queried for): 13
The design I'm modelling is that intimidation (or any derived stat) is its own stat, with its own base value. When queried for, it should return just an int, like if I was querying for Attack in your game. But that int would be the ranks in Intimidate + Charisma + bonuses. Right now I'm not planning on having more that one stat be the base of a derived stat, but it's possible (maybe you add half of your Strength), so the solution I'm working towards leaves room for that.
Intimidation (or armor class or w/e) could be used in an attack, or a spell, or in a dialog option, as a requirement for a new ability, and always needs to be able to be seen from the stat menu. Each time I needed to use it, I could just calculate it in the ability (or menu display, or stat threshold, or..), but that would get messy quick, to the point of being unfeasible. I'm working on a layer between the stats class and the rest of the game which calculates a final value for me, but it is a lot of very specific code, which I'm not a fan of, since I want to move to a place where all stat values are passed in through a sqlite (which I am at right now without the derived stats). Just wanted to discuss potential design for this if it's within the scope of the forum.
|
|
|
Post by Admin on Mar 13, 2019 11:48:25 GMT
So if I understand, you will store each of the base stats in sqlite, but are you hoping that the derived stats are also an SQL query of some sort, or are you happy to do the notification pattern like I did to determine attack strength? Since you want to use this stat so frequently, another layer will be a great idea. I definitely don't suggest you get it from a component on the ability.
You might consider some sort of system (could be a component on a root level game object, a singleton, or even just a class method) that triggers the notification to query the intimidate stat as needed.
Alternatively, you could do something like a bounds check on the Stats component, and any request for an out of bounds stat would be determined to be a derived stat, and so could post a notification at that time.
|
|
jwm
New Member
Posts: 3
|
Post by jwm on Mar 13, 2019 22:21:09 GMT
The 'ranks' in a skill belong to the character as part of his stat growth. Maybe you get 3 skill ranks per level and 2 base stat ranks. I'm only using sql for loading character/game data during init/character switches etc, not for queries in game. I am using the notification pattern that you have for 'run time' stat queries (thank you!). Maybe querying a db during the game is not a bad idea though. Any thoughts on performance benefits/cost between the two?
Since in my game skills and a couple of other attributes are the derived skills, I've created AbilityScore (eg Charisma) and Skill (eg Intimidation) that inherit from a BaseStat class. Skills store a list of AbilityScores that we loop through and add in the 'value' property. All of them are subject to notifications and value exceptions in the same way, and are stored in a single list in the actor. I think I mightttt be in the clear with a solution. Still developing it, I'll post a quick run down when I'm done in case anyone reading has a similar setup. A lot of games have something like this, like the fallout games, dnd etc, so I could see it coming up again. I'm not entirely happy with two different classes for something so similar, but in the end, there is a difference, and I guess that is exactly what inheritance is for, right?
Thanks for helping me rubber ducky, by really defining the problem it helped a lot with the solution. If you have any more thoughts I'd love to hear them. I'm a front end web developer by day, so a lot of the inheritance and component architecture is swimming in new territory (the synchronous notifications you used are so handy oh man), so I am always interested in more info that can help!
|
|
|
Post by Admin on Mar 14, 2019 16:15:40 GMT
Assuming your game is still a turn based RPG, I don't think performance will be a problem regardless of if you use run time or sql queries, but I do think it is probably easier to create complex setups using run time stuff.
Well cool, it sounds like you've got something good cooking, so I'll wait and see how you like it. Good luck!
|
|