• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
April 26, 2024, 03:57:24 pm

Bars

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

Pickle Girl Fanboy

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.

lirmont

October 23, 2011, 02:25:36 am #41 Last Edit: October 23, 2011, 02:55:20 am by lirmont
Here's where I'm at so far in pulling out information from the database: "game" structure (current db structure).

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.

Kivutar

Tethical, an online FFT clone

lirmont

October 29, 2011, 03:06:10 am #43 Last Edit: October 29, 2011, 03:59:39 am by lirmont
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 (current db structure).

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.
MySQL Workbench: http://www.mysql.com/downloads/workbench/.


RandMuadDib

lol i didnt even think about races, that adds so many possibilities
I will show you the power of SARDIIIIINES!!!!

Pickle Girl Fanboy

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?

lirmont

October 29, 2011, 01:02:33 pm #46 Last Edit: October 29, 2011, 01:17:02 pm by lirmont
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.

RandMuadDib

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.
I will show you the power of SARDIIIIINES!!!!

Pickle Girl Fanboy

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

lirmont

October 29, 2011, 04:16:36 pm #49 Last Edit: October 29, 2011, 05:44:00 pm by lirmont
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 + + * == ==

Pickle Girl Fanboy

October 29, 2011, 10:19:23 pm #50 Last Edit: October 29, 2011, 10:20:00 pm by Pickle Girl Fanboy
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.

lirmont

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.

RandMuadDib

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?
I will show you the power of SARDIIIIINES!!!!

lirmont

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

Kivutar

I can't wait to see the result :) Keep up the good work!
Tethical, an online FFT clone

lirmont

November 01, 2011, 08:06:49 am #55 Last Edit: November 02, 2011, 03:45:27 am by lirmont
Wheee: CT Test (video; Zelda theme), CT Test (video; neon theme), test_db.zip, 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.

Kivutar

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

lirmont

Re-download the .sql file. There appears to be a bug with newer versions of MySQL. Thanks.

Kivutar

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

lirmont

That one's my fault. Re-download one more time.