• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
April 18, 2024, 05:56:15 am

Bars

Started by lirmont, October 15, 2011, 02:22:10 pm

lirmont

October 15, 2011, 02:22:10 pm Last Edit: October 16, 2011, 02:51:54 am by lirmont
Bars: Tethical Bars (another issue on the issue list)

Default:


Themed:





Cheetah

Current Projects:

Dome

The second one is the best, IMHO

"Be wise today so you don't cry tomorrow"

Joseph Strife

Quote from: Dome on October 16, 2011, 05:00:32 am
The second one is the best, IMHO

Sure is, altough the third one would very funny, it look a lot like zelda :P
Gaffgarion: It's in the contract!
Ramza: Does your contract says: "When you find a former squire, that now is a Holy knight that has kidnapped a princess, in a bridge by a waterfall fighting a brigade you are supposed to kill everybody that helps him!"
Gaffgarion: ... Sure!
Ramza: ... Let me see your contract...
Gaffgarion: ... No...


Kivutar

Hi lirmont. Thanks again for your code. I just took a look at it. Nothing to say so far, you chose the right way to solve this problem! I will push it tomorrow and close the issue.
Tethical, an online FFT clone

Pickle Girl Fanboy

You might want to try a FFXII system, with Green HP Blobs to designate HP over a certain amount, and a bar after them.  It could be useful for some kind of mist quicking ripoff.

lirmont

Yeah, that's a cool idea I can see doing in the existing setup. The other thing I want to do (but don't want to write until after Tethical is closer to play-ability/test-ability) is animation of each state. A state is something like 100% health, 50% health, 48.2% health, 0% health, etc. In the first themed example (which is really just to show it's possible to do something other than the default), maybe the gradient point (where the color changes) could wave back and forth. In the Zelda-esque proof-of-concept, the hearts/potions/lightning bolts could have a shine effect that rolls over each individual item. That would all done just with composited images outside of the game. Like I said though, I'm saving adding the animation idea for later once everything that needs to get done on the main branch of the software tree gets done.

On that note, I'm going to get back to writing a database model for Tethical as a point of discussion. Of all the things presented thus far, that will be the most important thing to make sure is 100% correct (because logic problems within a database will make working on the project unpleasant, to say the least).

Pickle Girl Fanboy

You should have options to turn off such animations for users with weak computers.

MasterGrand

that is wonderful lirmont
Let's be together !!

Kivutar

I'm still working on integrating your code to the trunk. It is almost done. I found a couple bug but they were easy to fix.
Tethical, an online FFT clone

MasterGrand

I can said good luck also keep up Kivutar
Let's be together !!

Pickle Girl Fanboy

October 19, 2011, 03:39:46 pm #12 Last Edit: October 19, 2011, 03:49:53 pm by Pickle Girl Fanboy
Quote from: lirmont on October 17, 2011, 04:02:17 pm
Yeah, that's a cool idea I can see doing in the existing setup. The other thing I want to do (but don't want to write until after Tethical is closer to play-ability/test-ability) is animation of each state. A state is something like 100% health, 50% health, 48.2% health, 0% health, etc. In the first themed example (which is really just to show it's possible to do something other than the default), maybe the gradient point (where the color changes) could wave back and forth. In the Zelda-esque proof-of-concept, the hearts/potions/lightning bolts could have a shine effect that rolls over each individual item. That would all done just with composited images outside of the game. Like I said though, I'm saving adding the animation idea for later once everything that needs to get done on the main branch of the software tree gets done.

On that note, I'm going to get back to writing a database model for Tethical as a point of discussion. Of all the things presented thus far, that will be the most important thing to make sure is 100% correct (because logic problems within a database will make working on the project unpleasant, to say the least).


http://ffhacktics.com/smf/index.php?topic=7778.0

As you can see, I've been wracking my mind, trying and failing to find a way to avoid hardcoding sub-abilities, meta-abilites, and their unique action dialogs.  My efforts in the link above achieved something though; we now have the vocabulary we need to at least talk about what your doing.

Some other things:

*The Charge skillet could be hardcoded, and then linked to a flag on each ability.  Let's call it the "Power Varies" flag.  When Power Varies is true, it adds an additional battle dialog when that ability is selected in battle, which allows the player to increase a x value (which is presumably linked to the power of the ability), while adding a charge time if one is not present and increasing the charge time by a Y value (which is presumably linked to the charge time of an ability.  It might be best if these x and y values for each charge time are hard-coded somewhere else, since not all formulas use x and y for power and charge time.
**Perhaps like this:
***Power+1 : AbiltySpeed(-1/20)
***Power+2 : AbiltySpeed(-1/10)
***Power+4 : AbiltySpeed(-1/8)
***Power+8 : AbiltySpeed(-1/5)
**This way, the Charge or Aim skillset the Archer employs could become a passive skillset triggered by a passive support ability - much like Defend and Equip Change - which modifies the Attack ability.  Specifically, it would modify the Power Varies flag in the Attack ability, and set it to true when the Charge/Aim Passive Support is equipped.
***Speaking of Support abilities, there should be a distinction between Reactions, Active Supports, and Passive Supports.  Reactions are abilities like Critical: HP Restore or Speed Save - they trigger under a specific circumstance, but with conditions.  Active supports are like Weapon Guard or Abandon, they must be triggered by certain abilities or circumstances, but they are otherwise always active.  Passive Supports are like Halve MP or Move+3, they are simply static bonuses.  I'm not sure these distinctions stand up well, but they are a little better than Reaction/Support/Movement.

*How should I define a meta-ability?
**A meta-ability is a set of related abilities which could plausibly form a skillset in their own right, but which are useless by themselves(? need to work on that).

*Meta-ability flag?  Sub-ability flag?
**Both still require hard-coding, in the mother ability, which will indicate what the x, y, and z values (or other things, since the sub-abilities or meta-abilities are useless on their own, you can use anything in those sub- or meta-abilities for whatever you want) in the abilities flagged as sub-abilities will be used for.

lirmont

October 19, 2011, 06:53:20 pm #13 Last Edit: October 19, 2011, 06:56:09 pm by lirmont
Yeah, it is decidely complicated to keep everything together. However, I can explain my current approach to that section. Admittedly, it SEEMS a little more complicated when considered in it's component parts like it needs to be in a database since the commonplace reponse is, "But why wouldn't you just do this [insert example that works for one skill, statistic, etc]". The reason is: because it wouldn't work for every case.

Before anyone reads any further, this is not ready for use; there is lots of work I have to do to ensure that this setup both works and is easy to use on a database level. There will be pretty pictures like usual when I reach that point.

--

Current Thought Process

The idea is storing formulas that relate to a generic entity called a "Game Mechanic". What needs are we addressing here? We're addressing storage space and addressibility (within formulas) for the following:


  • Permanent Statistic (examples: Max HP, Max MP, Max CT, Base STR, Base MV, etc.)

  • Exhaustible Statistic (calculated/in-use statistics/register values; examples: Current HP, Current MP, Current CT, Current STR, Current MV, etc.)

  • Temporary Penalty (examples: Poison, Physical Damage, Fire Magic Damage, Ice Magic Damage, etc.)

  • Temporary Bonus (examples: Float, STR Boost, MV Boost, etc.)

  • Permanent Penalty (equipment/race penalty; examples: Weak to Fire, MV Down, etc.)

  • Permanent Bonus (equipment/race bonus; examples: Walk on Water, Flying, STR Boost, etc.)

  • Scalar (ex: 1, 2, .5, 5, etc.)



Immediately, someone might point out something like, "Why would I want to address ALL of those game mechanics in a formula? Can't the program just take care of doing that?" The point quickly becomes that, if you take the approach that the programming should do it, you're not going to have a flexible system at all. In other words, you'll be stuck with whatever gets programmed. For instance, you might have access to "poison" but not something that's similar but different to a "poison" effect (because it would need to be programmed).

So, what does this part of the database deliver? Here is an example:


id, gameid,                   name,   abbr,   uniqueName,            description,                    type, exhaustibleMechanicAnalogId
1,         1,             "Poison",  "POS",     "POISON",      "Poisons target.",     "Temporary Penalty",                        NULL
2,         1,         "Hit Points",   "HP",    "BASE_HP",          "Hit points.",   "Permanent Statistic",                           3
3,         1, "Current Hit Points",   "HP",         "HP",  "Current Hit points.", "Exhaustible Statistic",                        NULL
4,         1,           "Strength",  "STR",   "BASE_STR",            "Strength.",   "Permanent Statistic",                           5
5,         1,   "Current Strength",  "STR",        "STR",    "Current Strength.", "Exhaustible Statistic",                        NULL
6,         1,              "Haste","HASTE","MAGIC_HASTE",       "Hastes target.",       "Temporary Bonus",                        NULL
7,         1,              "Haste","HASTE",  "EQP_HASTE",       "Hastes target.",       "Permanent Bonus",                        NULL
8,         1,               "Slow", "SLOW",   "EQP_SLOW",        "Slows target.",     "Permanent Penalty",                        NULL
9,         1,       "Two (Scalar)",  "TWO",        "TWO",      "Static value 2.",                "Scalar",                        NULL
10,        1,  "FFXI-Style Attack",  "ATT","BASE_ATTACK",        "Attack value.",   "Permanent Statistic",                        NULL
11,        1,     "Current Attack",  "ATT",     "ATTACK",        "Attack value.", "Exhaustible Statistic",                        NULL


Now, someone familiar with databases would be quick to point out the fact that there are two unique identifiers here. One is the value-meaningless version (which is the `id` field). The second is the value-meaningful version (which is the `uniqueName` field). The ultimate goal is to spit out a formula that can be parsed and re-written by programming. That is, we want to spit something out like the "Attack" formula from a game like FFXI: STR * 2. Who does this formula apply to? That is, it could be ANYONE or ANYTHING with a STR value. Where does the STR value come from? The programming could calculate it from all references to the 'id', 4 (which would be relative changes to BASE_STR). So long as it gets set up correctly, this becomes a simple SUM operation (you're adding up calculated values), which is an aggregate function a lot of databases optimize for.

Anyway, moving on. We need a place to store a formula such as "STR * 2". There is an immediately obvious problem that basically goes, "What about duration? What about Evasion? What about [insert term here]?" To solve THAT problem, we have to treat the "Game Mechanic" as a function, being able to take several values and being able to handle those values. I propose a storage facility like what I'm calling "[Game] Mechanic Functions". However, before we do that, when do we evaluate this function? I propose several options: "Proc on Add", "Proc on Turn", "Proc on Add and Turn", and "Proc on Load". Here is an example for the HP function (that is, logically the concept of "damage" or "healing") and "Attack":


id, mechanicId, evaluationType
1,          3,  "Proc on Add"
2,         10,  "Proc on Load"


So, when we go to evaluate our HP formula, we'll be doing it only when the mechanic's formula is requested and added into the mix. However, we have nothing yet to evaluate for three reasons: (1) we need input, (2) we need a place to store that input, and (3) we need operations to perform on the stored input. Perhaps we'll cover storage in a place called "Function Arguments" as follows (with the HP and Attack functions as examples):


id, mechanicFunctionId,       argumentName, defaultValue
1,                  1,         "Severity",            0
2,                  1,  "Chance to Dodge",           .5
3,                  1,  "Chance to React",           .5
4,                  1,"Chance to Counter",           .5
5,                  2,    "Bonus-Penalty",            0


Now, this is as far as I've gotten in the design write-up for myself on this part. However, the next step is two-fold. The first step is to break out argument types between "Severity" and "Chance to [insert skill type here]". That way, you have essentially a function level (defined by "severity") and the goal level comparison as to whether or not you will be affected by the function. Regardless of that, we need to create and store operations, something like an "Argument Formula" table (this is the head of the formula; programmatically, load the input value at this step):


id, argumentId
1,          1
2,          2
3,          3
4,          4
5,          5


"Argument Formula Operations" (the body of the formula; post-fix/reverse polish notation):


id, argumentFormulaId, leftSign, loadMechanicId,       rightSign
1,                 1,     NONE,              3,        ADDITION
2,                 5, ADDITION,              5,            NONE
3,                 5,     NONE,              9,  MULTIPLICATION


Okay, so, for the HP function. I've only written out the severity part. What would happen is it would take the input value (severity), load the current HP, and add them together. For the STR*2 "Attack" formula, we end up loading the input value (bonus-penality), then the addition sign (to the end), then the current STR value, then the scalar value "2", and then the multiplication sign: INPUT_VALUE STR 2 * +. In normal notation, that looks like: INPUT_VALUE + (STR * 2).

Now, we're still missing WHERE the input value comes from. That's skill functions, but we have to define skills first:


id, skillsetId, name, description, costToLearn, effectFile, areaFunctionId, areaFunctionLevel, selectionFunctionId, selectionFunctionLevel
1, ..., "Damage Something", "Damages something for 50 points.", 0, NULL, ..., ..., ..., ...


And we'll call this "Skill Actions" (actions to be taken when a skill is picked), what we've been leading up to this whole time:


id, skillId, mechanicId, value
1,       1,          3, -50


The "action" is really captured implicitly by the affinity of the input value (negative in this case). The value -50 goes into our HP formula. When the function we made earlier is evaluated, the programming applies the result to the mechanic. Evaluation would happen upon using the "Damage Something" skill (assuming it had no wait time).


--

How it Relates

Anyway, if skills implements a parenting scheme, that could handle the look-and-feel. This, I believe, already handles the levels you're talking about. Aim is a function with several unique levels. Those are input values for game mechanic functions. Those input values get passed into the HP function (damage/healing) and CT(?) function (wait time?) formulas. And that solves the problem, I think.



Pickle Girl Fanboy

Keep in mind that I only understood 1 word in 20, but I notice you didn't mention x, y, and z values anywhere.

lirmont

October 19, 2011, 07:21:50 pm #15 Last Edit: October 19, 2011, 07:22:19 pm by lirmont
I just gave them real names. See the "Severity", "Chance to Dodge", etc. Consider f(x, y, z, a) = HP(severity, chance to dodge, chance to react, chance to counter), where the function "HP" determines your current HP, whether it changes, whether you react, and whether you counter.

Pickle Girl Fanboy

October 19, 2011, 07:26:52 pm #16 Last Edit: October 19, 2011, 07:31:11 pm by Pickle Girl Fanboy
As much as I'd love to dive head first into a really tedious discussion (I'm not kidding), I am forced to admit that I know nothing about programming.

*hangs head in shame*

But I'm glad that you are in charge of this.

EDIT

I just had a flash where I kinda got it.

lirmont

I promise, when the pretty pictures of a more complete and tested design show up in a week or two, it'll be easier to make sense out of it and to comment on what needs to change/be added.

Pickle Girl Fanboy

October 19, 2011, 07:33:58 pm #18 Last Edit: October 19, 2011, 07:43:20 pm by Pickle Girl Fanboy
So, you're saying that you'll just make a sort of database of all the potential values for each piece of a formula, and then you'll just reference the parts that you need and run/calculate them as you need them?  (See, it took me a while, but it sunk in eventually >.<)

lirmont

October 19, 2011, 08:20:01 pm #19 Last Edit: October 19, 2011, 08:35:42 pm by lirmont
Yes, that's right. This part of the database is constructing tables to generate formulas which the programming can blindly fill out and calculate (using character data). As someone who just intends on writing a formula (you can do this in FFT, right?), you wouldn't see anything but the actual formula.

For instance, you might have a damage formula of some kind in FFT that looks like: PA * Br.  

What is "PA"? It's a game mechanic. What is "Br"? It's also a game mechanic. When the programming asks for the function, it gets something that looks like that formula (now, understand, it won't look like that in the database). So long as "PA" and "Br" are unique names and the character has "PA" and "Br" defined, the programming can say, "What's the character's PA? And, what's the character's Br?" and plug the response from the database into the formula.

Now, in the case of my setup, we also must consider the input value defined at the skill action level. In this particular case, you might want to add 50 damage to the base damage for every level up you go (the level of the function is defined by the input value). That would look like: INPUT_VALUE * 50 + PA * Br.

So, f(1) sends back to the program "50 + PA * Br". f(2) sends back "100 + PA * Br". f(3) sends back "150 + PA * Br". Then, the program runs through the formula and replaces PA and Br (and any other game mechanic) with an actual numeric value. The only difference is that's just not the format it does it in. The format would look like 50 PA Br * +, 100 PA Br * +, 150 PA Br * +, etc. (because that's a format easy for programming to use).

Another example might be Poison. I don't have any knowledge of FFT, but, in FFXI, you had levels of the effect. So, let's say you were fighting something that cast poison on you. Based on their stats, maybe it did 5 damage per proc to you. Then again, you could be fighting something that had an ability that poisoned which did 200 damage per proc to you.

For argument's sake, let's say MND of the casting character is equal to 50. Let's say the damage per turn for Poison is: INPUT_VALUE * MND / 10

The INPUT_VALUE again is the level of the formula here. Let's say you use a skill called "Poison" that has an "INPUT_VALUE" of +1. That turns out to be f(1) = 1 * MND / 10 = 1 * 50 / 10 = 5. Let's say instead you use something called "Poison II" that has an "INPUT_VALUE" of +2. We get f(2) = 2 * MND / 10 = 2 * 50 / 10 = 10.

The part where I replaced MND and did the calculation is what the programming would do. Again, it's the next part I haven't done yet, which is to have the pieces separated out so that the formulas can check against a value (for dodging; which would nullify the action).

Anyway, if it helps you think about it, all the game mechanics (except scalar values) would end up being "keys" to your character's data (which is why they need unique names):

Character X

  • "POISON" => "false" (or "true" if the person is poisoned)

  • "BASE_HP" => 200

  • "HP" => 150

  • ...

  • "BASE_ATTACK" => 50

  • "ATTACK" => 52



But that's a simplification of what would actually be happening. I mentioned severity, duration, and the formula that uses them. THAT information would also be held by anything that used it. For instance "POISON" data on your character would really look like:

"Character X" -> "POISON"

  • "Severity" => 1

  • "Duration" => 3 (turns)

  • "Formula" => (value pointing to something in the database)

  • "IconFile" => (value pointing to something in the filesystem)