• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
April 16, 2024, 06:22:49 pm

News:

Use of ePSXe before 2.0 is highly discouraged. Mednafen, RetroArch, and Duckstation are recommended for playing/testing, pSX is recommended for debugging.


Bars

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

Pickle Girl Fanboy

October 19, 2011, 08:45:41 pm #20 Last Edit: October 19, 2011, 09:00:13 pm by Pickle Girl Fanboy
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.

lirmont

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.

Pickle Girl Fanboy

October 20, 2011, 08:52:11 am #22 Last Edit: October 20, 2011, 10:53:08 am by Pickle Girl Fanboy
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?

lirmont

October 20, 2011, 12:51:48 pm #23 Last Edit: October 20, 2011, 01:12:05 pm by lirmont
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.


Kivutar

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!
Tethical, an online FFT clone

lirmont

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);

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:


  • Pre-Loading all Game Mechanics (i.e. you are entering the "Formation" state)

    • Find all game mechanics (ex: permanent statistics) for game.

    • Which universal mechanic type flag does it have?

      • If "CTMAX", this is the core rule for CTMAX.

        • Assign the "uniqueName" field's value as the dictionary key to reference when updating this core rule in the game.



      • If "CT", this is the core rule for CT.

        • Assign the "uniqueName" field's value as the dictionary key to reference when updating this core rule in the game.



      • ...

      • Else If "NONE", this is not a core rule.



    • Cycle through the mechanics function list:

      • What evaluation type is this?

        • If "Proc on Load", we need to evaluate this now.

          • Load formula string.

          • Split by the space character (" ").

          • Push to stack.

          • For each character,

            • Begin evaluation loop for reverse polish notation:

              • If type of value is "string" AND IN "*", "+", "=", "/", "%":

                • Load to operator register.



              • If type of value is "string" AND NOT "*", "+", "=", "/", "%":

                • Query database for value.

                • Replace value in stack.



              • If type of value is "number":

                • If number register 1 is empty, load to number register 1.

                • Else, load to number register 2.



              • If number registers 1, 2, and operator registers are all not empty,

                • Do operator in register on number registers.

                • Set number register 1 equal to result.

                • Empty number register 2 and operator register.





            • Store numeric value from number register 1 as value of game mechanic for character.





        • If "Proc on Add", we don't need to do anything except prepare storage and store the formula data for later.

        • If "Proc on Turn", we don't need to do anything except prepare storage and store the formula data for later.

        • If "Proc on Add and Turn", we don't need to do anything except prepare storage and store the formula data for later.












Pickle Girl Fanboy

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.

lirmont

October 21, 2011, 02:46:34 pm #28 Last Edit: October 21, 2011, 10:43:02 pm by lirmont
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))


Kivutar

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.
Tethical, an online FFT clone

lirmont

October 21, 2011, 03:23:18 pm #30 Last Edit: October 21, 2011, 03:40:34 pm by lirmont
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.

Pickle Girl Fanboy

October 21, 2011, 03:51:42 pm #31 Last Edit: October 21, 2011, 03:55:06 pm by Pickle Girl Fanboy
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.

lirmont

October 21, 2011, 04:07:49 pm #32 Last Edit: October 21, 2011, 04:08:28 pm by lirmont
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.

Pickle Girl Fanboy

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.

lirmont

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.

Kivutar

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.
Tethical, an online FFT clone

lirmont

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).

This is what the routine for getUserSettings looks like: getUserSettings.


Kivutar

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.
Tethical, an online FFT clone

lirmont

October 22, 2011, 01:02:47 pm #38 Last Edit: October 22, 2011, 01:08:51 pm by lirmont
"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).

Kivutar

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)
Tethical, an online FFT clone