Final Fantasy Hacktics

General => Archives => Tethical => Topic started by: lirmont on October 15, 2011, 02:22:10 pm

Title: Bars
Post by: lirmont on October 15, 2011, 02:22:10 pm
Bars: Tethical Bars (http://darkabstraction.com/showOff/ffhacktics/tethical-bars.zip) (another issue on the issue list)

Default:
(http://darkabstraction.com/showOff/ffhacktics/tethical-bars-001.png)

Themed:
(http://darkabstraction.com/showOff/ffhacktics/tethical-bars-002.png)


(http://darkabstraction.com/showOff/ffhacktics/tethical-bars-003.png)
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 15, 2011, 03:06:28 pm
Looks great.  Good job.

Got nothing else to say.
Title: Re: Bars
Post by: Cheetah on October 16, 2011, 04:59:53 am
Quite snazzy.
Title: Re: Bars
Post by: Dome on October 16, 2011, 05:00:32 am
The second one is the best, IMHO
Title: Re: Bars
Post by: Joseph Strife on October 16, 2011, 10:36:54 am
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
Title: Re: Bars
Post by: Kivutar on October 16, 2011, 02:42:13 pm
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.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 17, 2011, 02:46:13 pm
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.
Title: Re: Bars
Post by: 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).
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 17, 2011, 04:06:14 pm
You should have options to turn off such animations for users with weak computers.
Title: Re: Bars
Post by: MasterGrand on October 17, 2011, 08:48:44 pm
that is wonderful lirmont
Title: Re: Bars
Post by: Kivutar on October 18, 2011, 06:17:53 am
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.
Title: Re: Bars
Post by: MasterGrand on October 18, 2011, 06:12:31 pm
I can said good luck also keep up Kivutar
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 19, 2011, 03:39:46 pm
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.
Title: Re: Bars
Post by: lirmont on October 19, 2011, 06:53:20 pm
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:



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.


Title: Re: Bars
Post by: Pickle Girl Fanboy on October 19, 2011, 07:11:59 pm
Keep in mind that I only understood 1 word in 20, but I notice you didn't mention x, y, and z values anywhere.
Title: Re: Bars
Post by: lirmont on October 19, 2011, 07:21:50 pm
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.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 19, 2011, 07:26:52 pm
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.
Title: Re: Bars
Post by: lirmont on October 19, 2011, 07:29:07 pm
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.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 19, 2011, 07:33:58 pm
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 >.<)
Title: Re: Bars
Post by: lirmont on October 19, 2011, 08:20:01 pm
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


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"


Title: Re: Bars
Post by: Pickle Girl Fanboy on October 19, 2011, 08:45:41 pm
Poison in FFT is:
Damage Per Turn = (CharacterMaxHP * 1/8)
though it arguably should be either:
Damage Per Turn = (CharacterCurrentHP * 1/8)
OR
Damage Per Turn = ((CharacterMaxHP OR 999, whichever is smaller) * 1/8)
The actor who inflicts poison - and that actor's stats - don't factor in, except for the infliction rate.

Some words you might find useful:
Actor = person using the ability.
Target = person the ability is being used on.
Effects Processes = It's a better phrase than formulas.  It's more descriptive, at least.

You might also want to follow some kind of naming convention, so you can blindly Ctrl+H (Replace) through a text file and make changes without worrying that you're affecting something important.  Something like naming certain types of things in only all lowercase, other types of things in all caps, other things with the first letter of each word capitalized.

And yes, most modders who want to write their own formulas will just want the stuff you're providing, without actually dealing with programming.  It helps if you think of it as legos - that's what flashed through my mind while reading your explanation a few posts ago.  You, Lirmont, are using really small bits of code to create building blocks which non-programmers can use, so that non-programmers can manipulate it without having the skillset you have.  This is exactly the best way to generate interest in this project, since it will make it accessible to as many people as possible.  Which is the whole point of collaborative media and open-source programming.

http://db.gamefaqs.com/console/psx/file/final_fantasy_tactics_battle_mechanics.txt
^This is the Battle Mechanics Guide for Final Fantasy Tactics.  It should have everything you need for this part of tethical, though the people here at ffhacktics can tell you what is messed up about vanilla FFT, and how they would improve it.

http://db.gamefaqs.com/console/psx/file/saga_frontier_data.txt
^This is the SaGa Frontier Data and Mechanics Guide.  The parts about Effect Processes may be useful, since Zaraktheus walks you through how they are calculated.  You can talk to him in his "How various things work, according to debugger" topic over at the SaGa Frontier Board at GameFAQs, for advice on anything, since he's a phenomenal ASM programmer, and I suspect he knows some other languages as well.
Title: Re: Bars
Post by: lirmont on October 19, 2011, 10:11:59 pm
Oh, man. Looking at that first link, I will probably read through it as I can to work it into use-cases for this formulas/skills piece. Man, PSX didn't have floating point numbers; that's wild. Anyway, I'm confident the model is heading in the right direction after browsing through part of that document, at least. I might tie up some loose ends on the rest of the model (i.e. the part that doesn't have anything to do with formulas) and release it for discussion/changes while I spend a while reading that first document.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 20, 2011, 08:52:11 am
I'm surprised nobody told you about it.  Yay, I did something useful!  Anyways, you might want to lump Reaction/Support/Movement effects in with formulas, since any future modders will want them moddable as well as forumulas.

http://ffhacktics.com/smf/index.php?topic=6885.0
^Here's a link to a topic I made where I threw together a half-assed text file containing some info on R/S/M effects.  For reference, R/S/M effects should be treated just like any other effect, and the R/S/M abilities should have a way to reference those effects.

And you might want to add something like ALMA, which can add bonuses to specific classes once certain abilities are learned... or you might not, I don't know.  Pokeytax can explain it better than I can.

I think ALMA works like this:
You have an ability, any ability.  It can be an action ability, a reaction, a support, or a movement.  You can attach a passive effect - like +1 PA for the Squire Job Class - to, say, Accumulate, which will become permanantly attached once Accumulate is learned.  Or is only triggered when the ability Accummulate is used in battle.  Or any given set of conditions.

Don't know how I forgot this, but you should look into the Ability Requirement Hack.  Basically, Xifanie removed the hardcoding behind the Require Sword and Require Materia Blade flags in Abilities, so that you can make an ability require any piece of equipment, and a bunch of other things I don't remember.  I'll go sniffing after the topics for the ARH and ALMA and get back to you.

How are you designing it, in terms of modularity?  Will it be possible to swtich out, say, character stat modules and formula/effects modules with those using different stat systems, like maybe one similiar to FFTA?
Title: Re: Bars
Post by: lirmont on October 20, 2011, 12:51:48 pm
The feeling I get from past work is that Kivutar will want something that is "pixel-perfect" in terms of the original game. As with the rest of my code, I will try to do something that is big enough to encompass and include what FFT did completely while not being bound to it. That is, FFT's system (it's really a mathematical model, from looking at that document) should be able to exist within this model. There are things you will not be able to get away from. These are things I've dubbed "univeral mechanic types". That is, HP/HPMAX, MP/MPMAX, CT/CTMAX/CTR, Levels, JP, etc. There is also another category besides permanent statistics that will need to be added to match up to FFT, which is the programming-supplied set of information like ActorDistanceFromTarget, ActorDirection, TargetLevel, TargetDirection, WearingSlotXYZ, etc, but that's no big deal because that fits with the "supply formula for re-write by program" approach.

At the database level, the game mechanics (which includes statistics) exist as value-meaningless numbers. What does that mean? That means you will be able to rename them because the system (probably at game-load time as opposed to server-start) will be designed to go looking for these universal game mechanic labels to fill out its internal data model. That is, the system has to do this step anyway. If there's a layer in-between (like a lookup-table that correlates game battle mechanics to universal mechanic types), then you get control over what and how these behave (because the mechanics are user-defined functions and have settable names and descriptions).

If you compare the pictures in the first post that use bars versus the Zelda-esque one that doesn't, you should see that already there would be a huge amount of flexibility between themes defined in the filesystem by your game and what you choose to call and describe your game's universal mechanics.

But the "universal mechanic types" are solely for use within the programming's mathematical model (because things like CT and CTR are necessary to move the battle forward within the FFT game rules). But you aren't bound, for instance, to use "Speed" as the plus factor to CT. As long as you match your function to the universal "Speed" type (really "Add this number to user's CT every game tic" type), you can have it reference a relatively infinite number of other game mechanics while STILL existing within FFT's core rules.

For look-and-feel things, the plan is to define a look-up table that relates game mechanics to a "Character Stat Sheet". This is the database interpretation of what you probably know as a flag. That is, if they're in the table, they're GAME_MECHANIC_BELONGS_ON_STAT_SHEET. If they're not, they don't have that or the value is false. With the scrollable list already mostly done, you could have a remarkably long list of these for display within the original pixel-perfect design of the character viewing menus. The point would just be to make the list traversable like FFT's were.

Now, as far as bonuses for having skills go, I haven't written the storage for it yet, but it's certainly possible. It will follow the same model I have planned for class level bonuses and equipment bonuses. Basically, it's another set of look-up tables. You reference a battle mechanic, you reference a skill, and you supply an input value yourself. Conditions for application if it initially applies (i.e. you have the skill in this case) would exist on the mechanic you reference as part of the formula. In this particular case, you'd want to create a new game mechanic (formula) for the particular skill instead of using an existing one. Yes, it is overkill if you're thinking to yourself, "I just want to add +1 to MV!" However, again, what you'd see in an interface is a list of effect processes and you'd never have to see how it's stored. Point being, this format hopefully supports the least common denominator among game mechanics, but I need to read through that battle mechanic document.

The best thing about a database that's designed well is that you can absolutely ignore certain parts of it. That is, from a programming perspective, when a model begins to be used, you're not referecing every last piece of the database; you're referencing what you want. So, as long as the FFT game mechnics are covered, there can be other stuff that gets built at the database level that doesn't interact or impede those things until they are wanted. However, I hope to write part of the formula resolution at the database level too (this is programming in a scripting language called PL/SQL). I've already done it for options where it provides you back with a list of variables that have values filled out based on the user you asked for (because this is a client-server scheme where you have to log in and probably pick a game). It's these type of utilities that I want to provide so that the database holds and controls the rules, and the programming simply does them. If they're all FFT's rules or if they're some other game's rules above and beyond the core rules (which I have no intention of allowing you to change), the programming shouldn't know or care.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 20, 2011, 04:12:25 pm
I feel like it's Christmas.
Title: Re: Bars
Post by: Kivutar on October 21, 2011, 09:06:39 am
That was a long thread to read (and hard to understand with my poor english) but here are my comments:

QuoteThe feeling I get from past work is that Kivutar will want something that is "pixel-perfect" in terms of the original game. As with the rest of my code, I will try to do something that is big enough to encompass and include what FFT did completely while not being bound to it. That is, FFT's system (it's really a mathematical model, from looking at that document) should be able to exist within this model. There are things you will not be able to get away from. These are things I've dubbed "univeral mechanic types".

I totaly agree!

I had the feeling that it would be too difficult to code something truely modular for formulas so I was planning to write them using code. Mostly because I've never heard of PL/SQL before!
Now that I understand your plan, I think that your idea is genius and I want to go this way. I'm very curious to see how far we can go with this database model.

The FFT battle mechanics is my bible, since Eternal send me the link when I was coding the character's formulas. I'm going to read it again, and talk about the points which I think may be difficult to implement.

Yesterday, I pushed some patches to integrate your recent work on the bars. I fixed a last bug about classes vars and ported all the GUI.py, so there is no more char_bars.png :)
Tomorrow, I will replace some labels with your new font, and some frame backgrounds with your nodedrawer. So the texture folder will finaly be clean.

Thank you all for your help! Team work is so better than working alone!
Title: Re: Bars
Post by: lirmont on October 21, 2011, 02:14:11 pm
Nice! I'm just long-winded. :P I'm sure some people have already gotten tired of seeing my posts.

Anyway, what's more important to discuss with you is my idea for how it will probably be programmed. To begin with, let me give you an example of what options for a game looks like as a routine (a PL/SQL function). First, someone wanting to play has to sign up, right? They're assigned a network login. Once they've logged in, you'll have to handle picking a game somehow; this could be either from a list or from what URL you logged in from. Either way, once the game has been picked, if they have an account with that game, you store that identification number. You would then load their options for the game. So, I've already written a routine for that. The routine for that is called in SQL like the following: "call getUserSettings(1);"

That sends back the following: call getUserSettings(1); (http://darkabstraction.com/showOff/ffhacktics/tethical-db-001.png)

Now, about the formulas, when they should be evaluated is the most important part for the programming. The way I see it happening is that, yes, you will have to hard-code the core rules (the "universal mechanic types"). Now, what is the programming need here? The need is to store something that eventually updates the CharBars value to the right values. CharBars include HP, MP, CT, Level, and Exp. When I get closer to a more accurate design, making something that is able to update those from the database is probably a good start.

There are several needs the core rules have. The first one is to calculate statistics like strength "on-load". That is, when you need to display the statistic, it should already be made ready from the loading time of the game state. What is a "game state"? A game state is the fighting area of the game, the "pick a map" screen, the "unit formation" screen, etc. The point is, when these types of statistics are needed for display by the state, they need to be ready. A database is not slow in and of itself, but if you're dealing with a lot of players at one time, we need to try to minimize large database query consumption.

Anyway, something like this "on-load" for the permanent statistics game mechanics might look like this as an algorithm:





Title: Re: Bars
Post by: Pickle Girl Fanboy on October 21, 2011, 02:27:52 pm
Quote from: Kivutar on October 21, 2011, 09:06:39 amThe FFT battle mechanics is my bible, since Eternal send me the link when I was coding the character's formulas. I'm going to read it again, and talk about the points which I think may be difficult to implement.


Don't forget, we also need to talk about what is wrong with FFT, if it should be fixed, and what the fix should be.  The worst offender on this front is MP Switch.

MP Switch works like this: if you have any MP left, and you are about to take HP damage, and MP Switch triggers, then it will convert the HP Damage you recieve to MP Damage.  But there's a problem with this.  Let's say you have 10 HP and 10 MP.  A guy walks up to you, get's ready to attack you and deal 15 HP damage, and MP Switch triggers.  It will reduce your MP to 0, and throw away the remaining HP damage.  So you can survive the most powerful attacks in the game, with only 1 MP.

MP Switch should not throw away the remaining damage when your MP is reduced to zero.  Instead, it should allow the remaining HP damage to land on you.

There are other things concerning Reaction, Support, and Movement abilities I could talk about right now, but I have to organize my thoughts first.

*FFT lacks a Blood Mana ability.  That is, an ability which will proportionally regenerate MP when HP damage is taken or dealt.  Similiar abilities include those that regenerate MP when an actor restores HP, inflicts a negative status effect, inflicts a positive status effect, or KOs a target.  I think one of these types of abilities is called Mana Rage in another Final Fantasy game.
Title: Re: Bars
Post by: lirmont on October 21, 2011, 02:46:34 pm
Yes, this is one of the exact reasons why you will have access to formulas. For MP Switch, it sounds like FFT addresses one formula, when it really requires addressing two.

The "MP Switch" skill would have two effect processes. INPUT_VALUE in this case is the total damage.

HP_DAMAGE_FROM_MP_SWITCH("150", ...)

The first argument's operations result in something like: TargetHPBeforeChange - CLAMP(INPUT_VALUE - TargetMPBeforeChange, 0, infinity)

MP_DAMAGE_FROM_MP_SWITCH("150", ...)

The first argument's operations result in something like: CLAMP(INPUT_VALUE - TargetMPBeforeChange, 0, infinity)

It's just getting all the math operators in there. "CLAMP" is obviously not an operator you ever learned in school, but, for this, it does need to operate on values. However, I don't have a good idea for storing those yet. It may get separated into CLAMP_POSITIVE and CLAMP_NEGATIVE, where the first value supplied is the number you want to clamp. The second value is the number to positive or negative infinity. I don't know yet. There may also be a more mathematically correct way to do a clamp function without needing to take 3 arguments (that is, you split it up into two other functions that each take two values, one being the other).

Actually, here:

HP_DAMAGE_FROM_MP_SWITCH("150", ...) = TargetHPBeforeChange - MAX(ZERO_SCALAR, MIN(POSITIVE_INFINITY_SCALAR, INPUT_VALUE - TargetMPBeforeChange))

MP_DAMAGE_FROM_MP_SWITCH("150", ...) = MAX(ZERO_SCALAR, MIN(POSITIVE_INFINITY_SCALAR, INPUT_VALUE - TargetMPBeforeChange))

Title: Re: Bars
Post by: Kivutar on October 21, 2011, 03:01:02 pm
Ok.

I see exactly where we have to hook into the server (do you agree that for now we don't have support for offline mode, so this mechanics system have to be coded server side, right?).

There is already a login function in the server. For now, this login function checks that the credentials, login and password, are the same. This is a temporary behaviour that I choose waiting for the database backend. Since we are going to have an account table to store account, this function is going to check if the credentials exists, then instanciate the session.

The session: for now, all the sessions are in RAM, I store them in a Python structure, a nested dictionnary, using the unique name, or login, as key. I don't know if it is a good idea to keep all the sessions in the RAM. But I don't know either if we can do it another way!

Anyway, this is where the getUserSettings must be called and we have to store its output in the session if I understood what you say. This makes sense because we'll have to loop over all the account characters (so we'll have a table to store the characters) to compute their stats.

But a big part of these mechanics are not specific to characters, isn't it? We could load some of them right from the launch of the server, before the first account get logged in. Tell me more please.
Title: Re: Bars
Post by: lirmont on October 21, 2011, 03:23:18 pm
Offline mode

As far as a specifically offline mode goes, I think you're looking at something like we do with maps and other game engines do where you bake everything. Baking, in this case, may just mean having an installer that installs things needed to run the Panda3D game client, installs and sets up a database engine with the data (there are standalone ones that you could bake into other than MySQL), sets up the "OFFLINE_MODE" flag, and then sets up the client to ONLY point to that data. However, in the meantime, if someone wants to play their own creation offline, they just need the server running on their own machine with the appropriate data in the database and files in the filesystem.

Game mechanics

Yes, characters will be stored in the database. I'm just not that far yet, since I didn't follow the game mechanic guide as the starting point.

I can't think of any mechanic that wouldn't relate to a character in some way. It's just a matter of when the mechanic relates to the character. That is, did we call it because of a skill? Did we call it because we need to show it in the formation screen? As far as conserving space, all of the formula strings NEVER change between characters; they do change between different games, though. That is, you don't need to store the formulas on a character object, but you should point from the character object to the formula. The programming just runs through the string that is the formula and fills its information in. For example, this is something you could cache against the data stored by the program so that you don't even need to call the database after you have everything set up. It would just be a difference of asking the database for the stat "Br" versus looking the stat "Br" up in your character object. While the programming fills out ALL look-ups, there are some that will not be in the database at all. Those are the calculated ones (like ActorDistanceFromTarget).

Sessions

The other ways to store them are in a database or in files. Think about what information you're storing already. Imagine the client asks for something. The server might check to see if it has the data cached already, but ultimately it may end up asking the database, "What's this session id's data?" And then the database provides you back with a list of whatever it is you asked for.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 21, 2011, 03:51:42 pm
Terrain effects, weather effects, traps - these are things that will reference formulas, and perhaps abilities, but not characters.  Especially random lightning strikes!  So the next time you post a Black Mage on top of a water tower, God himself might lean down and say, "I don't think so."

Also, you could have stationary cannons (like the PS1 game Kartia) which a character can man and fire at things.  Maybe even destroyable terrain.
Title: Re: Bars
Post by: lirmont on October 21, 2011, 04:07:49 pm
Even those effects relate to a character. Think about what they do. That lightning strike, which would be hilarious, would still only be something like a skill that the game randomly uses. The mechanics it calls relate to the target character still.

And Kartia was too fucking hard.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 21, 2011, 04:16:02 pm
Quote from: lirmont on October 21, 2011, 04:07:49 pm
That lightning strike, which would be hilarious

Thank you.  I put some thought into that one.

Quote from: lirmont on October 21, 2011, 04:07:49 pm
And Kartia was too fucking hard.

Bullshit.  Just don't use any phantoms, and your characters will easily make level 20.
Title: Re: Bars
Post by: lirmont on October 21, 2011, 04:26:21 pm
I'm not saying I didn't play all the way through. I'm just saying, if I had been playing it on a console, I would have broken the controller with no savestates.
Title: Re: Bars
Post by: Kivutar on October 21, 2011, 04:49:45 pm
Thanks for the explanations about these 3 points.

Does mySQL supports PL/SQL? I read on the net that it was not yet the case. Or maybe the documentation is obsolete.
Title: Re: Bars
Post by: lirmont on October 21, 2011, 05:06:10 pm
It's true that you wouldn't call it PL/SQL if you were talking to someone in exact terms. However, even though the implementations are very different and have different constraints placed upon what they can do, they use similar key words and do similar things. The only PL/SQL, if you view it like that, belongs to the Oracle database. However, MySQL has routines that do the same type of thing and will certainly be capable of handling what I intend to use it for. The features are available in MySQL 5+ (MySQL 5.0 Stored Procedure Syntax (http://dev.mysql.com/doc/refman/5.0/en/stored-routines-syntax.html)).

This is what the routine for getUserSettings looks like: getUserSettings (http://darkabstraction.com/showOff/ffhacktics/tethical-db-002.png).

Title: Re: Bars
Post by: Kivutar on October 22, 2011, 05:32:45 am
What do you mean by "game"? Is it the "game" setting variable that we use to switch between fft and lijj folders? Or is it the party (wich exists since the user hit the triangle button on the party list screen). Or is it the battle (wich exists once a all teams are ready) ?

If it is the first, I think we should not use a table to store games, and use a different database for each game. Because the server never runs two games at the same time.

If it is the second or the third, I see a problem because we may need some formulas before any party is created: when we want to add the party management screen. Or the soldier office. Or the armor shop.
Take a look at the Random function in the Character.py module of the server, you will see some formulas taken from the battle mechanics guide, wich computes stats like HP, MP, depending on the job.
We need these to display the bars, and the bars can be seen outside a party or a battle.
Title: Re: Bars
Post by: lirmont on October 22, 2011, 01:02:47 pm
"game" refers to "fft", "lijj", etc. It's possible to use this design as-is in more than one database if you really want. However, even if the server never runs more games than one at a time, would you rather ask for a different number or game name ("game id" or "name" which you can ask for all numbers and enumerate from the database) or change a database name? The other issue this raises is that everytime you push a change to the database structure, you need to update all game data. That is, if it's all in one database, this is done one time. If it's all in separate databases, this is done for each database (but not at once). I know it would be easy to use the name of the game folder as the database name, but not all web hosts allow you to choose your database names, since you may exist within a pool of other hosting client's data. If on the other hand, you have one database, which can be flexibily named in the configuration file, then you can call the game(s) whatever you want.

Like I said earlier in the post, I'm reading through the battle mechanics guide for the first time. My plan is to get you something you can look at programming-wise (it will be another test___.py) that handles CT as an example using the database as a model. Once you've seen it, you can adjust it. Like I said though, this isn't for actual use. This is just for testing at the moment. As you mentioned, there are the "Raw" statistics that Characters.py builds from. Since "Speed" is one of those and because "Speed" is added to CT, my example is taking longer to do because I have to model more of the database correctly (which includes game-genders, game-races, and game-classes).
Title: Re: Bars
Post by: Kivutar on October 22, 2011, 05:48:39 pm
The server depends on python and panda, so you need a webhost with ssh access to host a tethical server, so you can create as many databases as you want. I think we can start with one db per game.This will make our dbs schemas more simple.

Providing updates for the database structure is another separate issue. We don't need to do it for no, as there is no production servers to maintain.

This guide is long to read, gambatte ne!

I can't wait to see a proof of concept of your mechanics system!

(Also, remember that python is dynamic, we can evaluate some code at runtime, so if you prefer python to PL, you can store some python code in the db, and tethical can eval it)
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 22, 2011, 10:16:10 pm
Random comment: It's raining and thundering outside right now, and I couldn't help but think about the semi-random lightning strikes I suggested while watching the lighting flash across the sky.
Title: Re: Bars
Post by: lirmont on October 23, 2011, 02:25:36 am
Here's where I'm at so far in pulling out information from the database: "game" structure (http://darkabstraction.com/showOff/ffhacktics/tethical-db-003.png) (current db structure (http://darkabstraction.com/showOff/ffhacktics/tethical-db-004.png)).

Before you read any further, this accomplishes getting some of the most important pieces of information out of the database. That is, we have formulas and the constants that begin to make them up. Now, sadly it looks mostly unreadable. However, let me direct your attention to the part that says, "formulas". A lot of them say "None", which is accurate if I haven't set them up or if they're a scalar. Two of them are filled out, though. First, we have the statistic "CurrentSpeend" (Sp). It's formula for the argument "MultiplyBaseBy" is listed as: 1638400 Actor.Class.SpM RawSpeed INPUT_VALUE * * /

We reorganize this into infix notation and end up with: INPUT_VALUE * RawSpeed * Actor.Class.SpM / 1638400

And what does the guide say Sp is: [(RawSp * ClassSpMultiplier) / 1638400]

So, as long as you specify "1" you match up with FFT. Where is our "ClassSpMultiplier"? It's "Actor.Class.SpM", which is to be supplied by the programming. Specifically, when the programming goes to evaluate the formula at loading time, it will look for the game mechanic "Actor.Class.SpM". It will find that that mechanic is a "Programming-Supplied Value". Following that, it will look for Actor["Class"]["SpM"].

Moving on to the other formula, it's for the argument "MultiplyBaseBy" for "RawSpeed" (RSp): Actor.Race-and-Gender.SpM INPUT_VALUE *

And we reorganize that into infix notation: INPUT_VALUE * Actor.Race-and-Gender.SpM

RSp doesn't have an explicit formula listed in the mechanics guide. However, "human male" has a constant value for it, "human female" has a constant value for it, and "monster unspecified" has a constant value for it. Our formula simply replaces the operand "Actor.Race-and-Gender.SpM" with Actor["Race-and-Gender"]["SpM"]. For example, what is the "human male" RSp constant from the guide? It's 98304. And in our design? It's the scalar game mechanic "HumanSpeedConstant" with a value of 98304.
Title: Re: Bars
Post by: Kivutar on October 23, 2011, 05:21:37 am
Great! :shock:
Title: Re: Bars
Post by: lirmont on October 29, 2011, 03:06:10 am
I wish I could say I have a working demo of CT done, but I'm still working on the intermediary steps.

CT depends on Speed. Speed depends on RSp and Class multipliers. RSp depends on race and gender. I have race and gender done.

Example of getting the formulas for all raw statistics based on race and gender. In this case, it's "Human" (id: 1) and "Male" (id: 1), and "R" is the operator for random in my proposed setup: mysql console view (http://darkabstraction.com/showOff/ffhacktics/tethical-db-005.png) (current db structure (http://darkabstraction.com/showOff/ffhacktics/tethical-db-004.png)).

I'm posting the MySQL workbench file because it will be too difficult to show what I mean in pictures, considering all the data involved. The only real table that's readable that you might care to look at is the "gameMechanics" table. Everything else is important, but it's segmented and difficult to read in MySQL Workbench. If you "Forward Engineer" it to an actual database, you can use phpMyAdmin to follow the id numbers to where they link to (it makes them into hyperlinks you can click through). You will need to disable the proxy user from being imported (since the "Forward Engineer" function will not drop a user for you once it exists).

MySQL Workbench File: current MySQL workbench file (http://darkabstraction.com/showOff/ffhacktics/tethical.mwb).
MySQL Workbench: http://www.mysql.com/downloads/workbench/ (http://www.mysql.com/downloads/workbench/).

Title: Re: Bars
Post by: RandMuadDib on October 29, 2011, 03:31:44 am
lol i didnt even think about races, that adds so many possibilities
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 29, 2011, 11:01:02 am
He's just going from the Battle Mechanics Guide.  There are four sets of raw stats - Male, Female, Monster, and Ramza.  Honestly, it should be called Species, not Race.  And there's really no need to link raw stats to Species and Gender, since Gender and Species specific raw stat bonuses can be job-specific (as in you just give all, say, Chocobo-Species jobs extra speed).  You could just draw up a number of raw stat sets, and choose one of them (or have one randomly chosen for you) when creating a character.

Do you want to see my notes on things I was thinking about, when I was daydreaming about making a FFT clone?
Title: Re: Bars
Post by: lirmont on October 29, 2011, 01:02:33 pm
If you post it here, I'll read over it and tell you how likely it is to be able to do it with the base of the model. Point being, once this database design is finished and there is an engine that uses it, you'd be able to make specific changes. One of the areas for development will certainly be the "Programming-Supplied" game mechanic type. The base engine will handle all of FFT's mass amount of needs, which hopefully means that everyone benefits from their utility, but, if you want to do something like provide a special bonus in the Physical damage formula chain based on the stats of a specific player (like a group effect), you'd need to code something that provides values for "Programming-Supplied" game mechanics. If you were doing a notorious monster system like FFXI has, maybe you'd use isNotoriousMonsterInEnemyParty, isNotoriousMonsterInThisParty, NotoriousMonsterSpBonus, NotoriousMonsterPABonus, and NotoriousMonsterMABonus. However, there's nothing stopping anyone from writing the formulas in the database, they just won't resolve to anything but a default value without altering the base engine's pool of "Programming Supplied" values.

Thinking forward, you could also do the same stort of thing to provide a difficulty setting, where the setting ranges from 0 < x < (infinity). The closer you approach to 0, the smaller your raw stats on character creation get. At one, you are on normal difficulty. At values past 1, your raw stats on character create become higher and higher. Of course, you could just apply this to RHP as a sense of balance, or go 180 and apply the difficulty instead to enemy raw stats.

I'm not saying I want to implement any of those (or that anyone should), I'm just showing that you could do it quickly. You write your formulas ahead of time with whatever it is you have in mind. You make sure they're in the database correctly, and then you go and edit your instance of the game engine's server to provide real values for those game mechanics. Then you're done!

Anyway, I make no claim to understand what FFT does behind the scenes, but the race[sic] and gender looks like such a thing does exist. Maybe it exists at a programming level in an two-dimensional array of values (such as it was presented in the guide), but I still have to account for the information somewhere in the database. Turning it into a cartesian product (where some combinations will not make sense) seemed like an acceptable idea, even if you have to have "Human (Ramza) - Male" as one of the results (causing you to have the ability to do logically meaningless things like "Human (Ramza) - Female"; or, "Monster - Male" and "Monster - Female" when FFT only ever uses "Monster - Unspecified").

I blame MUDs for my obviously erroneous connotation of what the word "race" means.
Title: Re: Bars
Post by: RandMuadDib on October 29, 2011, 01:32:15 pm
i think race is supposed to be used when differing types of peoples can breed (i.e. elves/humans/dwarves etc.) and species is for when they cant, so race/species could differ from server to server, so what its called behind the scenes is fairly irrelevant and up to the whims of the programmer.
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 29, 2011, 02:17:25 pm
**Subclasses**

The goal is to fit all possible unique NPC classes into the vanilla generic class structure.  More classes must be created to accommodate monsters, Zodiac beasts, and other unique creatures.

Everyone can gain access to all the basic classes by gaining JP in the requisite classes.

Subclasses should be unlockable by completing certain tasks (not in this version of Tethical though, since it's VS mode only so far), or by getting stat (x) above (y).

The catch is that everyone has their own unique Job Tree.  So, if you have opened up all the Sub-Classes for Knight for a particular Character, and you decide to change that Character's Knight class to it's Holy Knight variation, then that Character will lose access to all other Knight Sub-Classes and the Holy Knight will replace the Knight in for that Character.  In this way, even your generics will be unique, and as customizable as any NPC.  the only difference being that some NPCs are flagged so they will never change their sprite and portrait.

Squire->--------------------->---------------->-\
|                              |                |
V                              V                |
Knight->-\                     Archer->-\       |
|        |                     |        |       V
V        |                     V        |       |
Monk->---|                     Thief->--|       |
|        \-------->--\         |        |       |
V                    |         V        |       |
Geomancer            |--<----<-Lancer   |       |
|                    |         |        |       |
V                    |         V        V       |
|                    V         |        |       |
|--->--\             Samurai   |        |       |
|      |                       |->-\    |       |
|      |-----------------<-----/   |    |       |
|      |                           |    |       V
V      V                           |    |       |
|      Dancer                      V    V       |
|->--------------------------------+-->-|       |
|                                  V    |       |
|                                  |    V       |
\-->----------------------------->-|    Ninja   |
                                   V            |
                                   |            V
Chemist->---------------->-------->-->-------->-|
|                          |                    |
V                          V                    V
Wizard->---\ /-----------<-Priest               |
|           |              |                    |
V           V              V                    |
Time Mage->-|------------<-Oracle               |
|           V              |                    |
V           Calculator     V                    |
Summoner                   Mediator             |
|                          |                    |
|->---\ /----------------<-|                    |
|      |                   V                    |
|      V                   |                    |
V      Bard                V                    |
|                          |                    |
\->---------------------->--->---------------->-|
                                                V
                                                Mime

/----------KEY------------\
| Class                   |
|  >Subclass              |
|   >Subclass Description |
\-------------------------/

The Subclasses
Squire
>Lord
  >Son of a Noble.  Gains additional skills.
>Lady
  >Daughter of a Noble.  Gains additional skills.
>Prince
  >Son of a Royal.  Gains additional skills.
>Princess
  >Daughter of a Royal.  Gains additional skills.
>Duke
  >A ranking Nobleman
>Duchess
  >A ranking Noblewoman

Knight
>Paladin - related to Priest
  >Slightly lower SP, Move, and Jump than a Knight.  Much higher HP and MA.  Has some additional healing and defensive skills
>Gladiator
  >Slightly higher SP, Move, and Jump than a knight.  Much lower HP and MA.   Inherent Monkey Grip.  Can't equip Body Armor.  Has some additional offensive skills - 2 ranged attacks, 1 hit all around.
>Holy Knight
  >Has some additional offensive skills, Holy Elemental sword strikes.  Weak against Dark.  Resists Holy.
>Dark Knight
  >Has some additional offensive skills, Dark Elemental sword strikes.  Weak against Holy.  Resists Dark.

Archer
>Poacher
  >Deals greater damage to Beasts.  Can equip Knives and Swords.
>Ranger
  >Master hunters and trackers.  Higher HP, Move, and Evasion than Archer.  Always Invisible at start of turn.
>Expert
  >Marksmen trained on the principle of One Shot, One Kill.  Gains 2 additional attack range with Bows and Crossbows.  Hit rate is 150%, evasion rate is 50%.  Takes 50% more damage from non-ranged attacks.
>Amazon - Related to Monk, Witch, Dancer.
  >Female only.  Deals greater damage to males.  Has new attacks - Female Specific Healing and Buffing, and Male Specific Offensive and DeBuffing.  Immune to Charm from males, but can be charmed by females.

Monk
>Brawler
  >Higher HP, PA, SP, Move, and Jump.  Inherent Dual Wield.  Has additional offensive skills - all self-damaging attacks - and no healing skills.  Some limits on equipment.  Can't be healed in battle.
>Dervish
  >Has some additional healing skills.  Offensive skills not as damaging.

Thief
>Bandit
  >Changes Steal Skillset to Pillage, which relies on PA instead of SP.  Lower SP, higher PA.  Can equip Swords, Axes, and Clubs.
>Minx - related to Witch and Dancer
  >Changes Steal Skillset to Wile, which relies on MA instead of SP.  Higher MA.  Inherent Dual Wield.
>Phantom Thief - related to Knight - Also, NPC specific.
  >A chivalrous gentleman thief.  Robs only the nobility.

Geomancer
>Terranite
  >Channels Geomancy through one's weapon.
  >Changes Geomancy Skillset so that Weapon Power becomes a factor in Damage Formula.

Lancer
>Dragon Knight
  >Lancer sworn to protect Dragons.  Deals greater Damage when an Allied Dragon is present.  Recieves 1/5 damage when attacking Dragons.
  >Bahamut Dragoon
   >Dragon Knight dedicated to the Dragon Lord, Bahamut.  Changes Jump and Attack(Spear) to use Brave along with PA and WP.  Higher HP and PA, lower MA and Evasion.
  >Leviathan Dragoon
   >Dragon Knight dedicated to Leviathan.  Resistant to Water.  Changes Jump and Attack(Spear) to use SP instead of PA.  Higher SP and Evasion. Lower PA and HP.  Can Act and Move in all depths of water.  Weak to Lightning.
  >Dragon Slayer, Dark Dragoon, Wyrm Hunter, Wyrm Betrayer
   >Fallen Dragoon who wishes nothing more than to see Dragons and their Kin exterminated.  Deals greater damage to Dragons and Dragon Knights.  Loses Jump Skillset and gains Dragon/Dragon Knight Specific attacks.
>Dragon-Kin
  >One related to Dragons.  NPC specific.  Gains additional attacks - Dragon Breaths, and Dragon Specific Healing and Buffing skills.
>Valkyrie - Female Only - related to Geomancer and Knight
  >Better SP, Move, and Jump than Lancer.  Lower HP and PA.  Deals mid to long range thunder and holy elemental damage.
>Athena Adept - Female Only
  >Warrior devoted to the goddess Athena.  Changes Jump and Attack(Spear) formula to use MA and SP instead of PA.  Jump and Attack(Spear) also gain a chance to cause any of a number of negative status effects.

Dancer - Female Only
>Gymnast - related to Monk
  >Warrior who uses balance, leverage, and momentum to attack unexpectedly.
  >Higher HP, SP, PA, Move, and Jump.  Has additional offensive skills.  Can dodge and counter enemy counter-attacks.

Samurai
>Ronin
  >Male Only
  >Can't wear Heavy Armor.  Changes all Draw Out skills from MA to PA powered.  Gains additional SP and PA.  Loses MA and MP.

Ninja
>Assassin
  >Female Only
  >Lower Stat Multipliers.  Gains additional offensive skills - one-hit kills up close and from a distance.  Takes additonal damage from all attacks.  Can't Equip Any Armor?

Chemist
>Herbalist - related to Witch
  >Female Only.
  >Uses herbs found in the wild to heal allies and harm enemies.  Gains an entire sub-skillset.
>Tinkerer
  >Male Only.
  >Dabbles with mechanical weapons and dangerous chemicals.  Gains an entire sub-skillset.

Wizard
>Witch
  >Female Only
  >Confers blessing upon her allies and hurls curses at her enemies.
  >Curses: 8 spells, one for each major element, which cause minor damage and have a very good chance of adding one or more negative status effects.
  >Blessings: 8 spells, one for each major element, which heal a little bit of health and have a very good chance of adding a positive status effect.
>Sage
  >Male Only
  >Just like a Wizard, but
  >Uses elements of Air, Earth, and Water.

Priest
>Shaman
  >Male Only, heals with all of nature's elements.
>Exorcist
  >White Mage granted holy magics by the gods.
  >Loses all but the most basic healing spells and buffs, gains a number of holy elemental attacks and undead specific de-buffs.

Time Mage
>Space Lord
  >Masterful manipulater of matter and gravity.  Gains additional offensive spells, loses all buffs and debuffs.  Has Master Teleport.
>Time Lord
  >Mage who excels at bending time.  Loses all offensive spells, but gains additional buffs and debuffs.  Has Non-Charge.

Oracle
>Adept - related to Witch
  >Mage who loses him/herself in the Universal Mind.
  >MP regenerates every turn.
  >Skillset is named Archetype
  >Adept has a special method for attacking.  It can learn various Archetypes, which are collections of spells, AI set-ups, and inherent bonuses.
   >Archetypes:
    >Hero
    >Mentor
    >Threshold Guardian
    >Herald
    >Shapeshifter
    >Ally
    >Trickster
  >The Adept, when it choses an Archtype in battle, will no longer be under the player's control for a semi-random number of clockticks.
  >The Adept will gain the archetypes resistances, weaknesses, stat bonuses, and so on.
  >The Adept will use the archetypes attacks according to the archetypes AI set-up.
  >Furthermore, each Archetype can be blended, refined, and altered in a number of ways, once the player completes certain tasks.

Summoner
>Necromancer
  >Summons the dead.
   >Sorcerer - subclass of Necromancer
    >Summons demons and the dead.
     >Lich - subclass of Sorcerer
      >Undead Mage able to summon Death itself.

Mediator
>Story Teller - related to Bard
  >Tells stories which effect everyone on the battlefield.  Gains an entire sub-skillset.
  >One skill in the skillset makes all allies blend in with the enemy, effectively ending the battle at a draw.
  >If a female gains access to Story Teller, she also gains access to Bard and it's subclasses.
>Actor - related to Dancer and Mime
  >Warriors who use their uncanny acting skills to blend in with the enemy.  Gains an entire sub-skillset.
  >One skill in the skillset makes the Actor fake over to the enemies side, where he or she is treated like on of them until the Actor breaks character (attacks an enemy, aids an ally).
  >If a male gains access to Actor, he also gains access to Dancer and it's skillsets.

Bard - Male only
>Musician - related to Thief and Mediator
  >Appeal to the enemies emotions.  Unfortunately, everyone has different tastes in music.

Calculator
>Physicist
  >Uses understanding of natural phenomenon to attack and defend.  Gains additonal evasion.  Boosts attack, defense, and evasion of all allies on the battlefield.
>Wheel Walker - related to Time Mage, Story Teller, Actor, and Musician
  >Mage who walks the wheel of human experience.  Uses Empathy to destroy enemies and heal allies from the inside out.

Mime
>Jester



Proposed Data Layout
Each unit has, as part of their unit data, an ID byte.  Or maybe several bytes, but for ID.  And what these do is tell you what jobs are available to them on their job wheel/tree, whether or not they have a unique sprite, what - if anything - that unique sprite is, and if that unique sprite overrides the usual job sprite when they change from one job to another.

Each genus and species is flagged to specific jobs, which make up their job wheel/tree.  To access some classes, one must be (or become) a sub-species.  For instance, you can make the Knight job accessible to all humanoids, but not accessible to one specific sub-species of humanoid (say, Uncorperal Undead - Ghosts).  IF - and this is a big if - you're going with the layout I'm dropping here, you basically need either raw stats for each Genus, Species, Sub-Species, Gender, and Alliegence; or (pay attention) a database of formulas, which the user can modify, which will modify the base stats for each character, depending on what they are flagged as.  Also, some Genus, Species, Sub-Species, Genders, and Alliegences will have extra skillsets automatically, no matter what their job is.  Like, a Species Vampire will always have a skillset which includes the ability to suck blood, though they may choose to develop their vampiric skills in different ways.

Genus, Species, Sub-Species, Gender, Alliegence, Job, Sub-Job

Genus Humanoid
Species Human
Species Giant
Species Ogre (Similiar to Bangaa?)
Species Orc (Porky in Vanilla)  (I imagine they're like moogles)
Species Goblin
Species Mystic (SaGa Frontier) (Could also double as Elves) (are spiritually "different" humanoids, related to Fey)
Species Transmigrated
Sub-species Angel
Sub-species Demon
Sub-species Corperal Undead (Zombie)
Sub-species Uncorperal Undead (Ghost)

Genus Fey
Species Gorgon
Species Fairy
Species Gremlin
Species Hawkman
Species Mermaid
Species Vampire?  Succubus? (depends on gender?)
Species Lycanthrope

Genus Ephemeral
Species Elemental
Species Esper

Genus Aquatic
Species Octopus
Species Mindflayer
Species Slime

Genus Avian
Species Chocobo, Ostrich (Flightless Grazing Birds)
Species Raptor/Cassorwary (Flightless Predators)
Species Jura Aevis (Flying Predators)

Genus Dragon
Species Dragon
Species Tiamat (Three-headed Dragons, non-flying)
Species Wyvern/Wyrm (Flying Dragons)
Hybrid Tiamat/Wyvern(Three-headed flying dragons)
Species Naga (Aquatic Dragon)

Genus Beast
Species Wolf
Sub-species Cerberus (multi-headed dog)
Species Panther
Species Horse
Sub-species Unicorn (Fey Horse)
Species Tortoise
Species Tyrant (Tyrannosaurus Rex)
Species Bomb (classes: mombomb)
Species Behemoth

Genus Hybrid
Species Chimera
Species Griffin
Species Manticore

Genus Construct
Species Golem
Species Frankenstein (biological construct.  differs from Hybrids in that it is constructed, not the product of magic or unusual couplings)
Species Pumpkinhead
Species Machine
Species Dullahan?

Genus Plant
Species Marlboro
Species Cactuar
Species Woodman/Treant/Ent


Genders
Male
Female
Hermaprhodite
Neuter
Other (for slimes, and creatures which reproduce asexually)


Non-Humans in FFT (I need to fit these into the categories above)
chocobo
goblin
bomb
panther
mindflayer
skeleton
ghoul
ahriman
jura aevis
porky
woodman
minotaur
marlboro
dragon
tiamat
apanda
demon


Humanoids in FFT (I made this list so I could check off where each unique NPC class in vanilla would go)
Noble Knights - derived from Knight.  (holy knight, white knight, dark knight, rune knight, temple knight, swordmaster, divine knight, arch knight)
Noble Samurai - derived from Samurai?  (whatever elmdor is)
Noble or Royal Priest - derived from Priest.  (cleric, princess, cardinal, holy priest)
Lycanthrope - derived from Squire?  (dragoner/dragonkin)
Philosopher - derived from Calculator?  (truth mage, untruth mage, astrologer)
Noble Houses - derived fom Squire?  (Vicount)
Royal Houses - derived from Squire? (duke, duchess, king, queen)
Witch (already a subclass, derived from Wizard)
Arch Witch (same as witch, but character specific)
where does Engineer go?  Ditto knight blade, sorcerer, assassin, soldier,


*OTHER THINGS*
**Status Effects**
*Negative Status Effects*
Blind - Reduce Hit Rate and Evasion by 50%.
Mute - Lose ability to speak.  (abilities flagged as with the Mutable flag are unusable)
Confusion - Move and act randomly.
Berserk - Attack enemies non-stop.  Attack Power and Hit Rate increase by 50%.
Addled - Can't use skills.  (every ability not Mutable, besides the basic Attack)
Poison - Lose a % of your HP every turn.
KO - Unable to move or attack.  Do not gain CT.  Does not disappear over time.
Undead - Healing damages, Dark heals.  Weak against Fire and Holy.  Revive after a while when KO.
Vampire - Sleep during the day.  Suck blood from whoever's closest at night.
Lycanthrope - Transform into a monster at night.  The transformation itself depends on the creature that infected you.
Charm - Treat allies like enemies and enemies like allies for a period of time.
Critial - Status when HP is at or below 20%.  Triggers various effects.
Oil - Covered in Oil.  Weak against Fire, halve Water.
Curse - Will KO after a period of time.
Slow - Increase time between Act/Move cycles.  (Reduce CT gained every clocktick by (x/y)
Stop - Cannot more or act for a period of time.  Evasion drops to nothing.
Immobilize - Unable to Move.
Disable - Unable to Act.
Traiter - Defect to enemy side.

*Positive Status Effects*
Protect - Reduce damage recieved from physical attacks by 1/3.  Reduce hit rate for physical attacks by 1/3.  Reduce hit rate of negative status effects caused by physical attacks by 1/3.
Shell - Reduce damage recieved from magical attacks by 1/3.  Reduce hit rate for magical attacks by 1/3.  Reduce hit rate of negative status effects caused by magical attacks by 1/3.
Haste - Reduce time between Act/Move cylces.
Invisible - Enemies can not target you.  Increase hit rate to 100%.  Increase Damage dealt by physical attacks by 50%.
Regen - Gain a % of your HP every turn.
Disguise - Enemies will treat you as one of their own, until you damage on of them or inflict a negative status effect on one of them.

*Neutral Status Effects*
Defending - reduces physical damage recieved by 1/5, increases physical evasion by 1/5.
Charging - increases physical damage recieved by 1/5, decreases physical evasion by 1/5.
Performing - increases physical damage recieved by 1/5.
Jumping - take no damage from anything, untargetable, all status effects on hold until jump is completed.


**Questions**
1.  What will you set the minimum and maximum levels as?
2.  Will you go with a Final Fantasy 12 system for projectile weapons?  That is, you must equip a specific bow and a specific type of arrow, to use the bow?  Guns, Slings/Slingshots, Bows, Crossbows - these are all weapons that would be affected, though Sling and Slingshot could have an default to use stones from the battlefield.
Title: Re: Bars
Post by: lirmont on October 29, 2011, 04:16:36 pm
I haven't set up classes or class requirements to be stored in the database yet (because I was working on raw stats). However, if the ability to select the job is a formula based on game mechanics (and everything is a game mechanic at this point), then I can certainly see ways to implement that idea.

Now, about sub-species, you're really looking at a hierarchy in real-life (thank you, science), but it could be implemented as their own individual "races". Nothing will stop you from using the same argument id (how you address a particular part of a game mechanic's formula) from the race-and-gender raw stats sub-formula lookup table. What does that mean? That means that you can use the same sub-formula for every race-and-gender combination that belongs to a real-life family (to give them the same stats), but there is no family hierarchy within the system. For instance, "Human" would have its own race. "Angel" (a sub-species) would have its own race. Whatever genders you choose, you could share the same sub-formula for individual raw statistics between them. If I wasn't clear, raw statistics are attached to "race and gender" and not "race" and/or "gender". You couldn't ask for, say, the stats of a "human". You'd have to ask for a "human male", "human female", or "angel female". Anyway, sub-species could exist in the dubiously named "gameRaces" table already to accomplish what you want.

As to the questions about max level and projectiles, I'm almost postive Kivutar wants to use whatever FFT has for the base engine. However, "max level" sounds like a configuration variable you could set (possibly at the database level, but that's a ways off). I haven't started on storage for items, armor, or weapons yet, so I can't give you a definitive answer on what criteria you'll be bound by; I hope I can have slots be user-controlled so that it can encompass FFT's existing setup but allow people to get rid of or add other things. The scrollable list might make a list of equipped items look weird to someone who's played FFT before, but I bet it would fit right in. In which case, you could add a conditional slot "arrows" based on the existence of "bow", or "bolts" and "crossbow", or "bullets" and "gun". The more amorphous it is, the easier it will be to program is my opinion since you're addressing the broadest question first and just deciding the details later.

--

And now for how you may likely expect to see class requirements, but first let me mention that this requires math operators I haven't added yet (namely, boolean logic functions for greater than, less than, greater than or equal to, less than or equal to, equal to, not equal to):

Squire Requirement: TARGET_VALUE = 1 (as in zero to one, one is 100%; conveniently, 1 is also a synonym for "true").
Squire Requirement Formula: TARGET_VALUE == 1
RPN: TARGET_VALUE 1 ==

Squire's Lord Requirement: TARGET_VALUE = 1
Squire's Lord Requirement Formula: (TARGET_VALUE == Actor.isCharacterNoble) * (Actor.Level >= 10)
RPN: TARGET_VALUE Actor.isCharacterNoble == Actor.Level 10 >= *

Knight's Requirement: TARGET_VALUE = 1
Knight's Requirement Formula: TARGET_VALUE == (Actor.Classes.Squire.Level >= 2) * (Actor.MaxHP >= 200)
RPN: TARGET_VALUE 200 Actor.MaxHP >= 2 Actor.Classes.Squire.Level >= * ==

Knight's Requirement: TARGET_VALUE = 1 (if Holy Knight is level 1, value resolves to 0; comparison resolves to false, which is zero)
Knight's Requirement Formula: TARGET_VALUE == ((Actor.Classes.Squire.Level >= 2) * (Actor.Classes.HolyKnight.Level < 1))
RPN: TARGET_VALUE 1 Actor.Classes.HolyKnight.Level <= 2 Actor.Classes.Squire.Level >= * ==

Holy Knight's Requirement: TARGET_VALUE = 1 (flags add up to 3 and are bounded by 0 and 3 as to whether or not Knight is level 10 or more; 3 gets compared to 3 if all are true which equals 1)
Holy Knight's Requirement Formula: TARGET_VALUE == (3 == ((Actor.holyKnightSponsorCompleted + Actor.holyKnightPilgrimageCompleted + Actor.holyKnightCeremonyCompleted) * Actor.Classes.Knight.Level >= 10))
RPN: TARGET_VALUE 3 10 Actor.Classes.Knight.Level >= Actor.holyKnightSponsorCompleted Actor.holyKnightPilgrimageCompleted Actor.holyKnightCeremonyCompleted + + * == ==
Title: Re: Bars
Post by: Pickle Girl Fanboy on October 29, 2011, 10:19:23 pm
Whatever is simplest and easiest for you to implement is fine with me.  I still can't believe that we're gonna have our own FFT clone.

I was thinking about Reaction, Support, and Movement abilities earlier.  Specifically, I was thinking - based on my own limited programming knowledge - how they would look.  Here's HP Restore:
If Actor
    Takes HP Damage
         And Actor Status
              Is Critical: True After taking HP damage
    Then Actor HP
              Is Restored by the following formula: HP restored = (Max HP - Current HP)

Here's Counter:
If Actor
    Takes HP Damage
         And Dealer of HP Damage is within Actors Weapon Range
    Then Target Dealer of HP Damage with the ability Attack

It's lame, I know, but it's the best I can do.
Title: Re: Bars
Post by: lirmont on October 29, 2011, 11:33:50 pm
Yeah, I don't have a solid plan for reactions yet, since I haven't read that section in the guide. I do have a solid plan (and storage already) for capturing the damage types (and the chain of formulas that accompany them). I don't know enough to say, "It would fit fine with FFT if..." to clarify my idea about reactions, though. Basically, damage types (physical, magical, neutral, worker 8, etc.) have a chain of formulas that determine damage and a chain of formulas that determine evasion (yes, the guide should have set it up like that damage chain is in the guide because it determines hit, miss, and guarded from some intermediate step and not the final value). Anyway, so the idea is basically say, "Check this during X, Y, and Z damage types." This is a logical setup for something that is "a reaction to..." and in this case it's the damage type (literally, "this skill reacts to..."). Since the evasion chain is attached to a damage type, I think this is fitting, since I don't think it's appropriate to require all such abilities to check whether or not the skill evaded in their own formulas.

Like I said though, haven't read that section yet. This is just how I would have done it prior to actually reading the section.
Title: Re: Bars
Post by: RandMuadDib on October 30, 2011, 01:11:09 am
might i suggest two things? obviously they can't be implemented yet but perhaps you could keep them in the back of your mind, and perhaps they're not generalized enough to make it into the engine directly.

-A 'prone' status, so that you can trip/knock down people, and their evasion would drop or be negated completely
-the ability to knock back an enemy x number of squares, which would be set by the individual skill, instead of having the limit of 1 that's normal in FFT, and setting x to less than zero would actually pull them toward you (of course this wouldnt work in melee range, it would need to be with some kind of force spell or a whip or something)
-the ability to have skills move the caster (for example, to have the attacker and target switch places)

maybe i'm taking too many cues from D&D and Disgaea, but it would make a martial (non-supernatual) monk viable (or less boring) as well as add a lot of variety to other classes. Whips, anyone?
Title: Re: Bars
Post by: lirmont on October 30, 2011, 01:34:20 am
Well, something has to be written for "Dash" as a formula anyway, so I'll speak to those game mechanics:

Location X - "Programming-Supplied" - "Universal Type" (remember, other universal types are CT, HP, MP, Exp, JP, etc.)
Location Y - "Programming-Supplied" - "Universal Type"
Location Z - "Programming-Supplied" - "Universal Type"

Then, it's just a matter of attaching a "Skill Action" to the skill for each mechanic that you want affected. You would need to know the direction the attacker is facing to tell which direction to alter x, y, and/or z, but that's likely one of the more important ones to have early on anyway (think of X, Y, and Z as individual aspects of a location, you're essentially setting their values separately).
Title: Re: Bars
Post by: Kivutar on October 30, 2011, 05:58:35 am
I can't wait to see the result :) Keep up the good work!
Title: Re: Bars
Post by: lirmont on November 01, 2011, 08:06:49 am
Wheee: CT Test (video; Zelda theme) (http://darkabstraction.com/showOff/ffhacktics/tethical-ct-test.mp4), CT Test (video; neon theme) (http://darkabstraction.com/showOff/ffhacktics/tethical-ct-test-neon.mp4), test_db.zip (http://darkabstraction.com/showOff/ffhacktics/test_db.zip), tethical.sql (http://darkabstraction.com/showOff/ffhacktics/tethical.sql).


--

Still no proof of concept for CT yet, but here is the result of a working proof of concept for character stats with reference to the class the character is (important part is right at the top):


{'characters': [{'baseStatistics': {'ClockticksToResolution': 0.0,
                                   'CurrentCT': 0.0,
                                   'CurrentSpeed': 6.0,
                                   'HP': 5.0,
                                   'MA': 11.0,
                                   'MP': 3.0,
                                   'MaxCT': 100.0,
                                   'PA': 28.0},
                'classId': 1L,
                'effectiveStatistics': {'ClockticksToResolution': 0.0,
                                        'CurrentCT': 0.0,
                                        'CurrentSpeed': 6.0,
                                        'HP': 5.0,
                                        'MA': 11.0,
                                        'MP': 3.0,
                                        'MaxCT': 100.0,
                                        'PA': 28.0},
                'genderId': 1L,
                'id': 1L,
                'level': 1L,
                'name': 'Jack',
                'raceId': 1L,
                'rawStatistics': {'RawHP': 81920L,
                                  'RawMA': 234215L,
                                  'RawMP': 65536L,
                                  'RawPA': 520200L,
                                  'RawSpeed': 98304L},
                'userId': 1L}],
'classes': [{'classSpecifics': {'Actor.Class.HPC': '11',
                                'Actor.Class.HPM': '100',
                                'Actor.Class.MAC': '50',
                                'Actor.Class.MAM': '80',
                                'Actor.Class.MPC': '15',
                                'Actor.Class.MPM': '75',
                                'Actor.Class.PAC': '60',
                                'Actor.Class.PAM': '90',
                                'Actor.Class.SpC': '100',
                                'Actor.Class.SpM': '100'},
             'description': 'Basic job for all units. The starting point to becoming a fine warrior.',
             'id': 1L,
             'name': 'Squire'}],
'details': {'description': 'FFT clone.',
            'id': 1,
            'shortName': 'fft',
            'title': 'FFT'},
'mechanics': [{'childId': None,
               'formulas': None,
               'id': 1L,
               'type': 'Permanent Statistic',
               'uniqueName': 'CurrentCT'},
              {'childId': 1L,
               'formulas': None,
               'id': 2L,
               'type': 'Permanent Statistic',
               'uniqueName': 'MaxCT'},
              {'childId': None,
               'formulas': None,
               'id': 3L,
               'type': 'Permanent Statistic',
               'uniqueName': 'ClockticksToResolution'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '1638400 Actor.Class.SpM RawSpeed INPUT_VALUE * * //',
                                            'id': 1L,
                                            'mechanicFunctionId': 1L}],
                             'evaluationType': 'Proc on Load',
                             'id': 1L,
                             'mechanicId': 4L}],
               'id': 4L,
               'type': 'Permanent Statistic',
               'uniqueName': 'CurrentSpeed'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': 'Actor.Race-and-Gender.SpM INPUT_VALUE *',
                                            'id': 2L,
                                            'mechanicFunctionId': 2L}],
                             'evaluationType': 'Character Create',
                             'id': 2L,
                             'mechanicId': 5L}],
               'id': 5L,
               'type': 'Raw Statistic',
               'uniqueName': 'RawSpeed'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'Value',
                                            'defaultValue': 1L,
                                            'formula': 'INPUT_VALUE',
                                            'id': 8L,
                                            'mechanicFunctionId': 8L}],
                             'evaluationType': 'Proc on Load',
                             'id': 8L,
                             'mechanicId': 6L}],
               'id': 6L,
               'type': 'Class-Specific',
               'uniqueName': 'FlatClassMultiplier'},
              {'childId': None,
               'formulas': None,
               'id': 7L,
               'type': 'Scalar',
               'uniqueName': 'ClassDivisor',
               'value': '1638400'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '98304 INPUT_VALUE *',
                                            'id': 3L,
                                            'mechanicFunctionId': 3L}],
                             'evaluationType': 'Character Create',
                             'id': 3L,
                             'mechanicId': 8L}],
               'id': 8L,
               'type': 'Scalar',
               'uniqueName': 'HumanSpeedConstant',
               'value': '98304'},
              {'childId': None,
               'formulas': None,
               'id': 9L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.SpM'},
              {'childId': None,
               'formulas': None,
               'id': 10L,
               'type': 'Programming-Supplied Value',
               'uniqueName': 'Actor.Race-and-Gender.SpM'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '81920 INPUT_VALUE *',
                                            'id': 4L,
                                            'mechanicFunctionId': 4L}],
                             'evaluationType': 'Character Create',
                             'id': 4L,
                             'mechanicId': 11L}],
               'id': 11L,
               'type': 'Scalar',
               'uniqueName': 'HumanMalePAConstant',
               'value': '81920'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '65536 INPUT_VALUE *',
                                            'id': 5L,
                                            'mechanicFunctionId': 5L}],
                             'evaluationType': 'Character Create',
                             'id': 5L,
                             'mechanicId': 12L}],
               'id': 12L,
               'type': 'Scalar',
               'uniqueName': 'HumanMaleMAConstant',
               'value': '65536'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'RandomLowRange',
                                            'defaultValue': 491520L,
                                            'formula': '524287 491520 R 1 INPUT_VALUE * *',
                                            'id': 6L,
                                            'mechanicFunctionId': 6L}],
                             'evaluationType': 'Character Create',
                             'id': 6L,
                             'mechanicId': 13L}],
               'id': 13L,
               'type': 'Scalar',
               'uniqueName': 'HumanMaleHPRange',
               'value': '491520'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'RandomLowRange',
                                            'defaultValue': 229376L,
                                            'formula': '245759 229376 R 1 INPUT_VALUE * *',
                                            'id': 7L,
                                            'mechanicFunctionId': 7L}],
                             'evaluationType': 'Character Create',
                             'id': 7L,
                             'mechanicId': 14L}],
               'id': 14L,
               'type': 'Scalar',
               'uniqueName': 'HumanMaleMPRange',
               'value': '229376'},
              {'childId': None,
               'formulas': None,
               'id': 15L,
               'type': 'Raw Statistic',
               'uniqueName': 'RawHP'},
              {'childId': None,
               'formulas': None,
               'id': 16L,
               'type': 'Raw Statistic',
               'uniqueName': 'RawMP'},
              {'childId': None,
               'formulas': None,
               'id': 17L,
               'type': 'Raw Statistic',
               'uniqueName': 'RawPA'},
              {'childId': None,
               'formulas': None,
               'id': 18L,
               'type': 'Raw Statistic',
               'uniqueName': 'RawMA'},
              {'childId': None,
               'formulas': None,
               'id': 19L,
               'type': 'Scalar',
               'uniqueName': 'HumanMaleHPRangeHigh',
               'value': '524287'},
              {'childId': None,
               'formulas': None,
               'id': 20L,
               'type': 'Scalar',
               'uniqueName': 'HumanMaleMPRangeHigh',
               'value': '245759'},
              {'childId': None,
               'formulas': None,
               'id': 21L,
               'type': 'Scalar',
               'uniqueName': 'One',
               'value': '1'},
              {'childId': None,
               'formulas': None,
               'id': 22L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.HPM'},
              {'childId': None,
               'formulas': None,
               'id': 23L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.MPM'},
              {'childId': None,
               'formulas': None,
               'id': 24L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.PAM'},
              {'childId': None,
               'formulas': None,
               'id': 25L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.MAM'},
              {'childId': None,
               'formulas': None,
               'id': 26L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.HPC'},
              {'childId': None,
               'formulas': None,
               'id': 27L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.MPC'},
              {'childId': None,
               'formulas': None,
               'id': 28L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.SpC'},
              {'childId': None,
               'formulas': None,
               'id': 29L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.PAC'},
              {'childId': None,
               'formulas': None,
               'id': 30L,
               'type': 'Class-Specific Programming-Supplied Value',
               'uniqueName': 'Actor.Class.MAC'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '1638400 Actor.Class.HPM RawHP INPUT_VALUE * * //',
                                            'id': 9L,
                                            'mechanicFunctionId': 9L}],
                             'evaluationType': 'Proc on Load',
                             'id': 9L,
                             'mechanicId': 31L}],
               'id': 31L,
               'type': 'Permanent Statistic',
               'uniqueName': 'HP'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '1638400 Actor.Class.MPM RawMP INPUT_VALUE * * //',
                                            'id': 10L,
                                            'mechanicFunctionId': 10L}],
                             'evaluationType': 'Proc on Load',
                             'id': 10L,
                             'mechanicId': 32L}],
               'id': 32L,
               'type': 'Permanent Statistic',
               'uniqueName': 'MP'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '1638400 Actor.Class.PAM RawPA INPUT_VALUE * * //',
                                            'id': 11L,
                                            'mechanicFunctionId': 11L}],
                             'evaluationType': 'Proc on Load',
                             'id': 11L,
                             'mechanicId': 33L}],
               'id': 33L,
               'type': 'Permanent Statistic',
               'uniqueName': 'PA'},
              {'childId': None,
               'formulas': [{'arguments': [{'argumentName': 'MultiplyBaseBy',
                                            'defaultValue': 1L,
                                            'formula': '1638400 Actor.Class.MAM RawMA INPUT_VALUE * * //',
                                            'id': 12L,
                                            'mechanicFunctionId': 12L}],
                             'evaluationType': 'Proc on Load',
                             'id': 12L,
                             'mechanicId': 34L}],
               'id': 34L,
               'type': 'Permanent Statistic',
               'uniqueName': 'MA'}]}


"//" is "Floor Division". In other words, it divides the two operands and discards the remainder. This falls in line with FFT's behavior.

Now that I have a place in the programming to store and retrieve Speed (Sp) from, I think the CT demo is not far off.
Title: Re: Bars
Post by: Kivutar on November 07, 2011, 05:32:33 am
I get this error when trying to setup the database:

[kivutar@macbook:~]$ mysql -uroot < Downloads/tethical.sql
ERROR 1280 (42000) at line 47: Incorrect index name 'game'
Title: Re: Bars
Post by: lirmont on November 07, 2011, 07:30:36 am
Re-download the .sql file. There appears to be a bug with newer versions of MySQL. Thanks.
Title: Re: Bars
Post by: Kivutar on November 08, 2011, 03:47:39 am
Thanks, now I get this one

[kivutar@macbook:~]$ mysql -uroot < Downloads/tethical.sql
ERROR 1133 (42000) at line 1382: Can't find any matching row in the user table
Title: Re: Bars
Post by: lirmont on November 08, 2011, 01:47:54 pm
That one's my fault. Re-download one more time.
Title: Re: Bars
Post by: Kivutar on November 09, 2011, 04:41:18 am
Now I get the old error again
[kivutar@macbook:~]$ mysql -uroot < Downloads/tethical.sql
ERROR 1280 (42000) at line 47: Incorrect index name 'game'
Title: Re: Bars
Post by: lirmont on November 09, 2011, 05:01:16 am
Re-download one more time.

But also, you'll need to drop the user like:

drop user tethicalProxy;

--

The .mwb file is for the user interface "MySQL Workbench" (http://www.mysql.com/downloads/workbench/) which let's you pick and choose which parts you want to forward engineer into the production environment (Database -> Forward Engineer). The .sql is supposed to just be a backup for that (since you can't tell it not to load a certain part) and was generated by MySQL Workbench loading everything into the database. To edit data once you already have it up and running, I suggest you use a tool like phpMyAdmin that lets you see what's going on.
Title: Re: Bars
Post by: Kivutar on November 09, 2011, 11:10:51 am
Thanks, this time I have been able to restaure it.
I also installed mysql-workbench on my linux (I prefer this to phpmyadmin). It is a chance that we can use the same tools!
Title: Re: Bars
Post by: lirmont on November 09, 2011, 03:33:27 pm
That workbench is a designer's best friend. The problem is that it doesn't operate (well, that I know of) on a database that's already up and running. That's why I suggest phpMyAdmin for that, since it'll let you click through to your data, and you can change it in place to test things when you see them go wrong. However, you can use workbench to edit inserts and just forward engineer the table you want (in filters on the Forward Engineer's first page). Either way, the point is that database clients (i.e. the command line) haven't come very far at all over the period of time they've existed, and those tools (workbench and/or phpmyadmin) will let you have a better idea of what things actually look like. phpMyAdmin also has a very cool feature that let's you click through the actual relationship between two objects, taking you to the object that's being linked to; this is an incredible time saver (as opposed to finding the value, changing tables, using the search feature, putting the value in, and then hitting "Go"). It also has quick tools that let you get rid of everything, rename, view space storage, manage users (though, I like workbench for this one), and export to other formats.
Title: Re: Bars
Post by: Kivutar on November 09, 2011, 04:28:22 pm
For my everyday job, I use the command line, wich is not useless if you know the tips and tricks. But designing using a graphical tool with arrows and all, this is very great!
This week end, I have 4 free days to test your code.

EDIT: I'm reading your code. It looks good so far! As it is a big piece of work, I need time to fully understand it to integrate it in the trunk.
Title: Re: Bars
Post by: Pickle Girl Fanboy on December 09, 2011, 01:49:30 pm
Quote from: Atma on December 09, 2011, 01:19:32 pm
I'm curious... with the hack to edit the failure rate of Teleport past the unit's move... is there a way to display the range of Teleport?  What i'm thinking is only allowing 100% chance in range and 0% beyond.  Essentially using it much like Fly, but with the Teleport animation.  I don't want the entire screen covered with selectable spaces, when i can only go so far.  Possible?

I wonder, is it possible to have a semi-transparency in things like range, linked to certain things?  Like, you could have 100% opaque for movement range, but with vanilla Teleport, you could have 100% opaque where there is a 100% chance for a sucessful teleport, and then increase the transparency by the same rate at which teleport success falls.
Title: Re: Bars
Post by: lirmont on December 10, 2011, 08:02:27 am
So, you're asking if it's possible to feed the % chance of an equation into the colored square target feature to show the likelihood of success? I suppose it is possible, but are we just talking success % here (which would be one of the sub-formulas attached to the skill)? I don't remember, but isn't that covered in vanilla on the confirm screen already per square (showing 00 -> 100%)?
Title: Re: Bars
Post by: Pickle Girl Fanboy on December 10, 2011, 01:35:15 pm
Nah, there isn't a confirm screen for vanilla teleport.  I imagine there'll be a confirm screen for a modified 100% sucess teleport which costs you your Action and your Move on your turn (as in it works just like Equip Change and Defend, but also uses up your Move).  Though that's a good idea - much better than mine - teleport, no matter what form it takes, should display a success rate on the confirm screen.
Title: Re: Bars
Post by: Pickle Girl Fanboy on December 30, 2011, 06:11:57 pm
Sorry for the double post, but what are you doing in regards to battle event scripting?  Because if you intend to have any kind of story, you'll need something to manipulate sprites, sound effects, music, weather, lighting, and animations on the battlefield.

Do you plan to have any sort of world map?  The world map in FFT is basically just a bunch of (paths/lines) and (dots/links to battle events) that the player sprite follows, in a layer above an image of the world map.

One last thing: menu design and access.  Will you allow the modder to make custom menus to access and view different aspects of the game's mechanics, or will you just go with a generalized menu that can process all possible game mechanic combinations?

I don't know enough about battle or world menu event scripting to be helpful, but there are plenty of people here who do and likely will help you.
Title: Re: Bars
Post by: lirmont on December 30, 2011, 07:30:37 pm
Well, I don't know how far past multiplayer Tethical was originally intended to go (if at all), so I can't provide an answer for that. What I can say is events/states/savegames/etc is something I want to see happen. However, I've never considered writing something like that, though integrating something that's sequential (like an event script) into Panda3d is completely practical. It will literally let you set up a list of things (like rotation, scale, camera zoom, etc) to run against the current environment without needing to write any other code than telling it to do so (re: rotate command, scale command, camera zoom command). More complicated things, like chaning maps could be made into commands. That is, you might name it something like "ChangeMapTo" in Python and have the code needed inside of that to do what you expect. Now, in something like an event script, you could then call that function like: ChangeMapTo("map001"). However, I think it would get tricky to juggle that between Python's syntax and some arbitrary event syntax. So, I think it would be a good idea (and is completely possible) to simply write out the python code for the sequence AS the event itself. The PTF files that configure the particle effects do just that (with other aspects of Python). The point is, in Panda3d, you get access to -- wait for it -- simultaneous commands. Meaning, if you want two things to happen at once, you've only got to say the word. Want it to only happen for X amount of time? Same thing. Want it to change over the time it's running? Same thing. That is, you just have to use the right blocking to encompass what you're asking of Panda3d.

Anyway, Tethical really doesn't have anything in the way of a comprehensive written to-do list or anything, but I'd guess that that feature would need to be at least after solid multiplayer using FFT rules is working. As you know, I'm working on the control panel so it will be viable for people other than myself to add FFT rules in. However, I'm writing parts of the database that use that information still as I go along (re: classes, items, etc). So, I'm kind of the bottleneck at the moment, but, admittedly, FFT is a feature-rich game and creating the right storage for it is lengthy when you consider that it's all in relation to itself. Again, that's what the control panel will be for as it matures. The backend already has the form of what exists in FFT correctly (in my opinion), and now we just need something to dumb it down so it isn't as confusing for everyday usage, considering adding one thing may also mean you should add three or four other things at the same time (which the control panel would conceivably guide you through).

About the world map, I think there'd have to be more information about what actually happens to continue to plan for it. An incomplete version is easy to come up with: draw the map, pull a list of available points, compare that list to points you can actually visit, and then run some script based on selection of the point (re: the events I mentioned). However, that ties each point to exactly one script. While that's not unusable (because you could choose to call some other script from within that script based on game mechanic flags you set up), I don't know if it's viable. Drawing lines between points is easy to accomplish with bezier lines where you have a list of control points, and those lists can be stored in a database and referenced behind the scenes. However, doing it now would take time away from the more important aspects.

About menu designs, as you know, only the actual images that make up the box model are configurable at the moment (and would affect every menu). To enable a non-standard menu, I think you're looking at writing the Python code to make it available on your own. I don't recall exactly how the menu functions are called within Python, but this is certainly something that can be abstracted into an event-friendly CallMenu("menuWithExtraStuffInIt") command. As to actually writing the Python code for such a menu, Panda3d abstracts just about everything into something you can read, and Kivutar already wrote the scrolling and gamepad code (so you don't have to write that again).

Basically, I think at this point, if it's a feature you want, you might best serve that purpose by writing a battle mechanics guide lite version of what you see it doing. It doesn't have to be technical on the level that that guide was, but it should be structured. This happens, then this happens, then this happens, then we return to point X; that makes up Y thing. This name means this, this name means that, this is how you come up with this number. That way, someone from inside or outside the project doesn't have to come up with the bulk of the idea; they can just volunteer code it, make it available, and use it. You don't have anything to lose by posting in this forum a walkthrough of a feature you want. I can say I won't be doing it right now, because I have to finish making the backend of the software viable for use via the control panel. However, when I'm finished with that, I intend to prepare for other features that I want to see happen.
Title: Re: Bars
Post by: RandMuadDib on December 30, 2011, 07:40:30 pm
on the subject of single player (and i know this is not anywhere near important right now, but i think the idea should at least be documented)

Letting temporary (i.e. guest) characters join random battles. that way if the player is a grindwhore, they don't fall behind and become useless. I also think that guest characters should be allowed to be both player and AI controlled, set by whichever user is creating the single-player content. Might be an issue since i dont think anyone has even started thinking about AI yet, but the suggestion is here all the same.
Title: Re: Bars
Post by: lirmont on December 30, 2011, 08:18:23 pm
I have a feeling AI will be one of the easiest parts. Consider this. If you can define what a "good move" is for a given difficulty level, I can guarantee you I can write code that goes through and evaluates the damage formula(s) over every option the particular character has until it finds a move that qualifies as a "good move", and then it's just a matter of telling the game to do it. It only takes writing that process once for it to be repeat over and over. Technically, a player could do the same, evaluating every possible move his or her current character has based on what the game tells you your hit% and damage will be.
Title: Re: Bars
Post by: Pickle Girl Fanboy on December 31, 2011, 01:28:22 pm
I don't see any reason not to use Python to script events.  If anything, that will help everyone, because it will introduce non-programmers to Python (and thus would increase our pool of knowledgeable people), and it will allow interested Python programmers to walk in and contribute to the project.  Virtuous Cycle for the win!

You're right (of course); designing the player menu (or making the tools which let the modder design the player menu) should wait until you have the database and playable game at 1.0.  I'll mentally bookmark this conversation, and make a few topics in Help or Hacking seeking detailed explanations of these things when we reach that point.
Title: Re: Bars
Post by: Kivutar on January 03, 2012, 09:30:21 am
I agree about writting the events using Panda3D Sequences directly in Python. It is the best way to build a powerfull event system.

Concerning the player menu. For now this menu is hardcoded, but in the future it will be build on a dict sent by the server. Customizing the menu views and behaviour should be possible with a mechanism like extending the GUI module and overriding its Menu method. But it may be a naïve approach....

@lirmont I don't know design patterns but maybe you do. What would be the best way to provide GUI customization?
Title: Re: Bars
Post by: lirmont on January 03, 2012, 12:08:26 pm
The only thing I could think of when I read the suggestion was a format for menu coordinates, because I saw how those are written during the scrollable list feature. A lot of rich web development libraries (and GTK) use a model-and-view approach. So, this could be the view, where you set up columns with renderers (in Tethical's case, probably one for text and one for images) which render out a specific offset in a data model (i.e. an array or dictionary). One I'm familiar with in a library called ExtJS also has a feature called "XTemplate" where a column renderer is set to "template" and you feed it the offsets manually and have the ability to execute Javascript right from the template. The point is, you end up with something that is incredibly customizable. However, this depends on what data/columns you already have in the model, meaning you'd still be bound by what's returned. That is, if the data isn't in the model, you can't reference it in a column renderer.

Now, I think things like statistics are a good example of what you can and can't do here. Let's say the programming is changed to follow the above model-and-view approach. If everytime a certain character menu is asked, you get back ALL character statistics, you can choose at the view-level which ones you want displayed and how they will be displayed. However, if you want a kill count (a la Tactics Ogre), you would need to also change it (or tell Tethical) that it needs to load this character's gameplay statistics, and then you would reference the offset in a column renderer.

Don't be confused about the power of such a feature. The character "cards" FFT uses to display data are better known as "rows" (even though they're presented side-by-side). A solid feature like this would have several row models: default (list), horizontal, wrapped (ex: unit list with sprites and hp/mp/level/etc.), and cards (ex: one or more rows displayed at a time). With something like this, I can feed it into the C# control panel prototype without needing to link into Tethical/Panda3d. Otherwise, menus/themes will have to wait for the Python final product which will always use Tethical/Panda3d (where applicable).
Title: Re: Bars
Post by: Pickle Girl Fanboy on January 26, 2012, 11:39:59 am
I just realized, you'll need something to keep track of an actor's original stats during battle, for some weapon formulas a modder might use, and in case a modder decides to have stat buffs and debuffs decay during battle.

The weapon formula in question is a modified version the unarmed attack formula, which some believe is less broken than the vanilla version.  Here is the modified version:
damage = (original PA * current PA) * (Brave / 100)

Stat buffs and debuffs decay back to original should decay 1 stat point over (n) clockticks.

So you need to keep track of the original stats (which are a function of actor raw stats (HP/MP/PA/MA/SP), and Class Stat Modifiers.  Class Growths don't matter for this, since growths only matter when you gain a level.

Once this is accomplished, you must keep track of current stats (which are wrought by stat buffs and debuffs), and equipment stat bonuses (which change the hardcoded minimum stat, since the only way to remove their stat bonuses is by removing the equipment).

If you plan to include a timed delay, you need to keep track of the clockticks since the stat buff or debuff occurred, for HP/MP/PA/MA/SP, for every actor on the battlefield.

Possible uses for each of these stats:
*HP
**An ability or status which temporarily increases or reduces Maximum HP.
*MP
**An ability or status which temporarily increases or reduces Maximum HP.
**An ability, status, or mechanic which checks if Max MP = Current MP, and then increments MP by a static amount or a percentage, every (n) clockticks.
*PA/MA/SP
**A mechanic which decays artificial stat changes back to their original values over a period of time.

EDIT

Basically, just read this topic (http://ffhacktics.com/smf/index.php?topic=8351) to find out what I'm talking about.  Also, a lot of people think that support ability bonuses and elemental bonuses/penalties should be applied after base damage is calculated.  So please give us the means to modify these battle mechanics in tethical, so we can make a game that's better than FFT.
Title: Re: Bars
Post by: lirmont on January 26, 2012, 03:28:40 pm
If that forumla is not part of the original FFT platform, it will be up to a user to change it to that.

I know I'm a broken record at this point in saying it's not currently done yet, though. My current plan is to support a transaction-based structure so games can be documented and reviewed (like you'd document a game of Chess, except more verbose). Meaning, the system will snapshot everything related to characters and skills used, and games will be able to be rewatched. I want database queries against part of this structure to be how win/loss/draw totals are determined. The important part is that changes to original statistics (re: permanent statistics; not to be confused with raw statistics, unless you're wearing no armor, have no race bonus, and are not effected by magic) will be able to be watched just like in a game. It's a big endeavor though, and, since I've never done anything coding-wise with savestates before, I haven't come up with a solid plan for how I'll store the data.

One option is to do it in a spectator-style, human-readable sentences, then parse the sentence to know what's going on (like how someone might describe an event):

1. Red team is lirmont.
2. Blue team is someone else.
3. Red team places some character at some starting location as some class with some stats.
...
7. Blue team places some character at some starting location as some class with some stats.
...
11. Moving. Red team's character moves to location some location. CT is now some CT.
12. Move and act. Blue team's character moves to location some location. Blue team's character begins casting Holy. CT is now some CT. CTR is now some CTR.
...
100. Some team wins. Some team's win-loss-draw record is now some win-some loss-some draw.
101. Some team loses. Some team's win-loss-draw record is now some win-some loss-some draw.

(or)

...
50. Some team has disconnected without rejoining for more than X minutes.
51. Some team wins by default.
52. Some team wins. Some team's win-loss-draw record is now some win-some loss-some draw.
53. Some team loses. Some team's win-loss-draw record is now some win-some loss-some draw.


I say this because responsibly taking a snapshot of ALL data would mean making a copy of every table just for use with this feature, which is not a bad thing, but it would certainly be more of a final step (i.e. "this game will never change starting now"), which will never happen inside of a engine.
Title: Re: Bars
Post by: Pickle Girl Fanboy on January 26, 2012, 03:39:33 pm
Quote from: lirmont on January 26, 2012, 03:28:40 pmIf that forumla is not part of the original FFT platform, it will be up to a user to change it to that.

As long as you don't have to be a Python programmer to change it, I'm happy.
Title: Re: Bars
Post by: lirmont on January 26, 2012, 04:00:57 pm
This is an example of changing a formula: http://ffhacktics.com/smf/index.php?topic=8157.msg162571#msg162571

At the moment, it only supports evaluation, but it is just a prototype. The final version (and probably the prototype version) will support changing formulas right there.
Title: Re: Bars
Post by: Choto on January 27, 2012, 09:56:57 am
Hey Lirmont and Kivutar, I'd like to help out with tethical where I can. I read through the control panel and bars threads, and admittedly am a bit lost on where the current progress is at. I have a decent idea of what your goals are, but I couldn't quite follow everything you posted about lirmont, as my programming knowledge is limited. Right now I'm taking programming in C++, Java, and learning ASM on my own, so I know pretty much the basics of each language. I'm not opposed to learning python as well but can't guarantee i'll be successful learning all the languages at once. What I can offer is a decent familiarity with vanilla FFT, what some of the ASM or logic processes look like behind the mechanics, and opinions and ideas about how different mechanics could be handled. In farting around with my own patch, I also have ideas for new things I'd like to see incorporated which I can subject to your judgement for implementation. The majority of my effort has gone into class design, about which I have some philosophies, so when the time comes I may be able to contribute there.

I can't say how much time I will have to devote, but as FFT is a big interest to me I will try to do what I can when I can. Let me know what you need ideas or opinions about, or what you would like me to investigate and i'll help where I can. Thanks!
Title: Re: Bars
Post by: Kivutar on January 29, 2012, 06:03:32 am
Hi Choto.
Thank you for your proposal.

I'm about to leave to India for 1 month. So I won't be able to work on tethical for a while. But I can spend some time on the forums to get you started.

Do you know how to use Git?

Anyway, having a team member who can contribute to the code and understand ASM in the same time would be a plus for some tricky parts of the project (like coding the artificial intelligence).

Tell me more about what you like to code please.

(And yes, you need to know Python and Panda3d API well to understand the code and contribute to it)
Title: Re: Bars
Post by: Choto on January 29, 2012, 08:57:47 am
Hey Kivutar,

Sadly, I don't know python whatsoever, so I can't really contribute to coding unless I can pick it up pretty easily, nor do I know Panda3d API. Even my knowledge of ASM is quite limited. I can see how the game handles some routines and may be able to provide descriptions of what original FFT does, but i'm not nearly as skilled as the ASM'ers of FFH. I'm not exactly sure what Git is either. I am a decently quick learner, so I may be able to pick things up. I'm good at asking questions ^_^

Thus far, I've downloaded blender, panda3d, the tethical UI, and the sprite animator tool, although the UI and sprite animator won't open for some reason (Windows XP). I messed around with blender a bit to learn how it works... its a little awkward at first but i'm getting there, I made a couple little maps just messing around.

I wrote down a list of FFT mechanics as well as ideas for future development. I'm sure you have considered most things, but I thought it may be beneficial to start a thread listing these ideas/mechanics. This would also be a thread that people could post in with their ideas so that you guys can decide what you would like to implement. I tried to thumb through Aerostars Battle Mechanics guide, as I thought I saw you or Lirmont mentioning that you were unfamiliar with it, and took down whatever info would be relevant.

Let me know where you think I can be helpful, I realize at this stage of development coding is a pretty big thing and my lack of knowledge hinders my ability to contribute. Do you know any tutorials of python that I could at least take a look at the structure? I'll look into this in the meantime.

Edit: I found a good tutorial at http://docs.python.org/tutorial/introduction.html , it looks like its not too far off from other programming languages, but to be honest I doubt I can tackle learning this during my school semester. Perhaps after having taken C++ and JAVA, it will be easier for me to learn python. Anyway, let me know if theres any other way I can be of use if coding is above my head.