Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Tirlititi

Pages: [1] 2 3 ... 26
1
That's the ID of Dagger's entry in the script.

In concrete terms, you go in the script, in the function "Main_Init" and search for the code line initializing Dagger's model:
"InitObject( ID, [Some other number, surely 0] )"
When selecting those lines, you have the drop-down menu of entries that appear on the right of the window. You know that the line concerns Dagger's entry when it's written there on the right.

The script entry ID is that number given as the 1st parameter of "InitObject".

Alternatively, you can simply write a line "InitObject( 0, 0 )" in any function of the field and search for Dagger's entry in the drop-down menu (it will update the ID automatically in the textual part then). And then exit without parsing.

2
There are 2 problems about that when modding the PSX version:

1) Not all the models are available in every field. Most of the time, the models and animations are packed in each field (so there are actually many duplicates in the game's datas) and you can use only the models that are there already.
Fortunatly, there are exceptions and Dagger's models are amongst them: the models of the party members (including the temporary party members) are always available, whatever the field. However, her full set of animations is not available, only the basic ones (stand, walk, run, turn left/right). It might be that the animations of both of Dagger's models (short/long hair) can be used on both models though.

2) You need to register the models and animations that you use in order to have them available. That's probably the problem you have there.
Outside of the script, there's a button "Preloading datas": go there and add Dagger's models and animations to the list of datas to use. You also need to link the model to Dagger's script entry ID there.

3
@Dorklord: Yes, that seemed weird to me as well... but I've double-checked the code several times and didn't see a bug, so I guess that's just because of damage roll. I didn't see that fleeing was problematic with the Moguri mod though; maybe that's because of controller compatibility? I guess they tweaked it since they at least changed the movement directions.
Strange anyway... but I have no solution.

@Ddeathscythe: No, I don't think so, unfortunatly.
Indeed, the new versions (PC, PS4, Switch, phones...) are very similar but not similar enough to do a port, even if we had the tools for these versions. I think that, let aside compressions, the "p0data" archives are called something like "s0data" for the Switch version, which is not a big deal, but the most important file, the Assembly-CSharp.dll, is different from a version to the other and I am not sure if someone could even use Hades Workshop on a non-PC version.

4
Thanks a bunch Dorklord! I fixed it :)

5
Thanks Dorklord.
However, I won't update the mod anymore except maybe for Moguri/Snouz mod compatibility.
So, no, party members don't join at lvl 1 (unless all your other characters are lvl1 as well) and Transcend's SFX will still be the same (and I like that :p). You can use the Memoria save editor without problem though.

Most bosses should be slightly easier in v5.0 due to the battle mechanics allowing more things to the player. However:
- Steiner's first battle was made even easier. I think that he was already nerfed in v4.5 because he could kill you too easily on bad RNG. He can still hit hard but that's less RNG-dependant now so he won't always use his best attacks.
- There is a reliable way to cure doom as soon as you fight Beatrix for the first time... On top of that, a doom-immunity supporting skill was added in v5.0 and is available for Freya/Steiner at that point.
- Necron is noticeably harder now, even though there are many possible strategies against it.

6
By the way, I'm french ;p

7
Thank you :)
Indeed, I decided to give only a minimal description of what the abilities do, following the principle of the original (I mean, Lucky 7's or Limit Glove's descriptions are basically "It deals damage"... very informative!). I made that choice mainly by laziness: it would have taken a lot of time to decide how to formulate complete descriptions of the abilities in all the languages and make sure that they are small enough to be contained in the battle help (in the menus, there isn't really a limitation of space but there is in the battles).

In the spreadsheet, I could write things in english only and use a formal description that would be a bit dry in-game. I agree that it's far from ideal though.

I look forward to see how you will fare against the new bosses! A couple of people commented them but they didn't make a video out of the fights :D
Until then, good luck!

8
Hum. I guess that you forgot to put the "sharedassets1.assets" which wasn't a modded file in the previous versions.

9
In the PSX version, I'm not sure. However, in the Steam version, it shouldn't last after the fight.
Dying indeed doesn't remove that status but being dead prevents from it to be applied.
So the only ways to remove that "Easy Kill" status (which should better be named "Easy Kill Proof" as it prevents different spells to affect the wearer) are (1) to finish the fight and (2) to use a Esuna-like spell that can remove it.

Normally, it is only used as an "Initial status" on the enemies so an Esuna-like spell may also remove it if it can target the enemies or be reflected. Removing it is unsafe as it can softlock the battle if something bad happens to an enemy that normally has that status (if it gets eaten, for instance).

10
The PSX version mainly lacks Beatrix recruitability, the new bosses and the rework of the battle mechanics when comparing to the PC version.

In more details,
Spoiler: show
A few dialogs that were suppressed during the game's development were put back in this mod. It includes the dialogs from the "Hidden Dialogs" patch plus a few others for which only the texts were kept.

Abilities, be it the player characters' or the enemies' ones, have been modified.
One of the point of the mod is too enhance the statuses. Some basic spells deal statuses additionnally to their damage.

Here is a list of the principal changes for the player's abilities:

Zidane
------
Trance skills deal much less damage
What's that?! inflicts Blind to everyone now
Annoy has been replaced by Free Energy: a regular attack with 100% accuracy and no backrow reduce
Sacrifice has been replaced by Regenerate: use an ether on the team
Lucky Seven has been replaced by Warm Up: increase Zidane's strength by 25%
Thievery has been replaced by Transcend: bring Zidane to Trance

Vivi
----
Fire spells have a chance to inflict Heat (base: 5%, 10% and then 20%)
Ice spells have a chance to inflict Freeze (base: 5%, 10% and then 20%)
Thunder spells have a chance to inflict Slow (base: 10%, 20% and then 40%)
Slow has been replaced by Annoy (80% of inflicting trouble)
Demi has been balanced from 30% of max HP with 40% accuracy to 25% of max HP for 80% accuracy
Death has been replaced by Gradual Petrify (75% accuracy)
Break is now an Earth elemental attack in addition to inflicting Petrify (30% accuracy)
Water sometimes inflict Shell to its targets
Meteor has been replaced by Waterga: Water damage plus Silence (50% accuracy)

White Magic
-----------
Panacea only cures Poison but is multi-targeting
Stona only cures Gradual Petrify but is multi-targeting
Confuse and Berserk are now magical attacks in addition to inflicting statuses
Most of status-inflicting spells have their accuracy upscaled
Holy sometimes inflict Regen to its target

Dagger
------
The full powered Ark now deal damage twice, allowing to deal more than 9999

Eiko
----
Fenril is a wind eidolon by default

Quina
-----
LV5 Death has been replaced by LV5 Flare: inflict non-elemental damage to enemies with lvl multiple of 5
LV4 Holy has been replaced by LV4 Def-less: randomly decrease defence of enemies with lvl multiple of 4
LV3 Def-less has been replaced by LV3 Aerial Slash: inflict Wind damage to enemies with lvl multiple of 3
Doom has been replaced by Lightning: Thunder damage plus Silence to one target (50% accuracy)
Roulette has been replaced by Self-Destruct: convert Quina's current HP into damage on all the enemies
Aqua Breath has 75% accuracy instead of 50%
Matra Magic has been replaced by Zombie Breath: non-elemental damage plus Zombie on one target (20% accuracy)
Limit Glove has been replaced by HP Switching: switch Quina's current HP with an ally's ones
Twister has 50% to inflict Float in addition to its Wind damage
Earth Shake has 100% to inflict Slow in addition to its Earth damage
Frog Drop has been replaced by Devil's Snack: use a Dead Pepper on all enemies
Freeze has been replaced by Cocytos: Ice damage and inflict Slow on one target (100%)
Mustard Bomb has been replaced by Phlegethon: Fire damage and inflict Haste on one target (100%)

Freya
-----
Lancer's damage are increased, as well as its MP cost
Dragon Breath has been replaced by Dragon Life: apply Auto-Life on Freya
Six Dragons has became single-targeting for 15 MP
Cherry Blossom is more powerful
Dragon's Crest has been replaced by Ikari: deal physical damage and Trouble to all the enemies (50%)

Amarant
-------
Aura has been replaced by Starburst: deal 60 times an enemy's level as damage
Demi Shock's accuracy has been upscaled from 50% to 80%
Countdown has been replaced by Concentrate: increase an ally's Magic by 33% for 28 MP

Steiner
-------
Iai Strike has been replaced by Quadraslash: a physical attack using the elemental power of Fire, Ice, Thunder and Water
The accuracy of the 4 break abilities have been upscaled
Thunder Slash now inflict 21% of target's max HP as thunder damage
Climhazzard has been replaced by a weaker Shock: deal 2 times the physical damage on one target
Shock has been replaced by Sword Dance: deal 2 times the physical damage on all enemies ; it's a magical attack

Marcus
------
Added 2 abilities for the time he is with you on the disc 2: Strong Hit (more damage but harm Marcus) and Contaminate (100% to inflict Poison)

Also,
Ragtime Mouses Quizz has been refreshed
The Cotton Robe money trick was removed (they sell a bit less)
The enemies are stronger and more resistant
Few weapons can be used by several characters (for instance, Dagger can use the dagger)
The ultimate weapons give a big boost to main characteristics (Strength, Magic, Speed and Spirit)
Enemies' spells have been modified using similar principles as the player's spells
Phoenix Pinions cure Doom ; they also cost and sell cheaper
A mini-game has been re-added at the beginning of disc 3
Excalibur II can be acquired by two different methods:
1) Reach and beat Hades in less than 14 hours,
2) Get all the collectable treasures of the game (there are 3 little mistakes allowed) to obtain the higher treasure rank. Including a few Mimics, that makes 404 unique treasures to find.
And a few other things...

11
Your error is perfectly understandable: that's because of me.
I decided to automatically name several functions with "XXX_Loop" (the functions with ID 1) because that's what they do most of the time. However, it's not because they are called like that that they loop: they loop because they have the lines "Wait(1)" and "loop" at the end most of the time.

In this case, "Lich_Loop" doesn't have those lines but simply returns at the end. You don't want to just replace the "return" by a "Wait(1) + loop" either because it would run the dialog again everytime.
The easiest solution there is to put the looping part in an infinite "while" loop:
Code: [Select]
    // ...
    RunBattleCode( 35, 0 )
    while ( GetBattleState != 4 ) {
        Wait( 1 )
    }
    while ( 1 ) {
        if ( #( SV_FunctionEnemy[HP] <$ 10000 ) ) {
            if ( VAR_LocUInt8_60 < 1 ) {
                set VAR_LocUInt8_60++
                set SV_FunctionEnemy[HP] =$ 40000
            }
        }
        Wait( 1 ) // If you forget that, the game will freeze
    }
    return

More generally:
‣ The "XXX_Main" function runs as soon as the entry is initialized; the script level is set to 0 until it returns, which means that you shouldn't use any RunSync or similars inside the main function that would run a script of the same entry (you can use a RunSync on another entry though, provided that entry was initialized and its main function already returned),
‣ The "XXX_Loop" function runs right after the main function ends; the script level is defaulted to 7 so you can use RunSync codes inside. It runs only once.

In Field and World Map scripts:
‣ The "XXX_Reinit" function runs after returning to the field from a battle. Several datas are flushed when a battle triggers and this function set them back.
‣ The "XXX_Range" function runs every frame when the player's character is close to an object (determined with the collision radius set by SetObjectLogicalSize) or inside a region. It should only be used with entries initialized by InitRegion or InitObject.
‣ The "XXX_SpeakBTN" function runs when pressing the "confirm" button while the player's character is next to the object and facing it (the radius is determined with the talk radius set by SetObjectLogicalSize) or inside a region. In Steam, its presence adds an icon over the player's character. It should only be used with entries initialized by InitRegion or InitObject.
‣ The "XXX_CardBTN" function works the same as "XXX_SpeakBTN" except that it's triggered by the "card/moogle" button.
‣ The "Main_Unk" function runs when a menu opens on a World Map (either the player opens the main menu or the script issues a Menu code).

In Battle scripts:
‣ The "XXX_ATB" function runs when the enemy's ATB gets full. Attacks issued inside are added as "Enemy Command" at the end of the command queue. It has to issue an attack command.
‣ The "XXX_Counter" function runs when the enemy has been affected by an attack from a player character that was not a counter-attack or a Charge!, etc... and if it still has more than 0 HP. Attacks issued inside are added as "Enemy Counter" commands and take priority over most of the other commands.
‣ The "XXX_Death" function runs when the enemy has been affected by an attack from a player character, if it has 0 HP and if the related flag is enabled. Attacks issued inside take priority over most of the other commands. Attacks issued inside are added as "Enemy Death" commands and take priority over most of the other commands.
‣ The "XXX_CounterEx" function runs when the enemy has been affected by any attack.

12
@gledson999: Here are the offsets of the charmap file, in the PSX US version.
Disc 1: 0x3C5478 and 0x7B59AC
Disc 2: 0x3C5DA8 and 0x7B62DC
Disc 3: 0x3C5DA8 and 0x7B62DC
Disc 4: 0x3C5478 and 0x7AA1EC
The first offset is for the charmap of the "Picture 1" of the "Generic UI" in HW, while the second offset is the important one, for the "Picture 1" of "Charmap" in HW.

As said, the format is given by this stucture:
Code: [Select]
Unknown, usually 0 (4 bytes)
Unknown short int (2 bytes)
Unknown short int (2 bytes)
Number of characters, short unsigned int (2 bytes)
Padding, usually 0 (2 bytes)
[
    Img_x (1 byte)
    Img_y (1 byte)
    Img_width (1 byte)
    Width (1 byte)
] (x Number of characters)
Also, you need to know that these font images are compressed in a 2:3 format, ie. 2 colors produce 3 pixels (a mean color is computed and the middle pixel in the x-axis is given that mean color). The coordinates reflect this compression: a width of 6 in the charmap file actually means a width of 9 pixels in the bitmap.

13
I can do that but in 2 weeks only, once I return home.

14
@gledson999: The VWF is not in a standard format (you can see its format here).
I don't have all my FF9 datas available for some time, but the file is a 0x0D chunk that is approximately at position 0x3cb048 (it depends on the disk and the language; 0x3cb048 is the disk 3 of the french version). For informations on chunks and cluster datas, you can check Qhimm's wiki.

@rpg-lad: As I said, you can't mod on top of the Beatrix mod if you don't use the source files of the Beatrix mod. That's this download link.

@anxietymafia: Not to my knowledge, no. You can try to find that icon in the "Environment -> Texts -> Generic UI" and edit the image to remove the icon (I don't remember for sure but I think that you can draw pixel by pixel in HW on these images).

15
I don't know why that's happening to you.
Your planned order of work looks fine if "Beatrix Mode Import" means that you import the AFBeatrixOnly_v5.0.hws on a clean non-modded game.

You should do this:
1) Import the Beatrix HWS file, do the modifications you want, save as HWS (the .hws will contain both Beatrix's changes and your own),
rather than that:
2) Do the modifications that you want, save as HWS (your modifications only), import the Beatrix HWS and then your modifications again.
Indeed, it is possible to import several HWS one after the other but the latest import will have priority for everything that is common to both mods. For instance, if you modify any of party's spells, all of them will be stored in the HWS file (not only the bit you've changed). You can see in the "Tools -> Mod Manager" how each section is splitted (for instance, if you modify an enemy's HP, all the other enemies are not stored in the HWS and even that enemy's AI script won't be).

16
@Clem Fandango: You're welcome :)
I'm out of modding, but I really wish that FF9 modding doesn't die with me (well, it won't because Albeoris, Snouz and a few others are doing great without me anyway).

About the resources.assets, it contains various files. Most of them are the text and dialog files. It may be that a wrong text formatting (like missing a [ENDN] or [TIME=-1] at the end of a text) would make the game softlock at the logo.

@rpg-lad: I don't really understand what you're doing, but it is usually safer to open HW on an un-modded version of the game (though the files p0dataX.bin should not be a problem and the robustness to Assembly-CSharp.dll modifications was improved). If the program crashes before reading the enemy datas or while reading the enemy datas, that means these datas are problematic, even if it happens when trying to open a .hws file (the program first reads the datas from the game before doing anything with the .hws).

The correct way to create a mod based on my "Alternate Fantasy: Beatrix only version" is actually to download the source files of the mod (the link is in AF's topic) and read the Readme.txt to see how to use the files there (there are the source files of each version of the AF mod in that archive).

17
Yes Clem Fandango, I've encountered such kind of crash before... and when I did, I tried to fix the problem ^^"

If you want to know where it comes from, the first thing is to try launching the game with all the files modded except p0data7.bin (which is the file containing the field scripts). If it doesn't crash with the base p0data7, that's a good point in favor of that Ash/Veteran change having triggered the problem. If it still crashes, then it was something else.

The field scripts are in p0data7 but if it crashes at the logo, then it's not really about the script itself but rather about how the files are packed inside the archive p0data7. I'm afraid you may have encountered a rare bug that happens only at specific settings (a file having a special position in the archive, replaced by an update with a special file size...). I'm not aware of such bug in the latest version of HW, but I expect it to work like that from experience...

Another possibility, that wouldn't make the issue comes from HW, is that you somehow replaced one of the game's files (p0data7 for instance) while HW was opened (and had loaded those game's files). If you do that, then HW will compile the Steam mod files wrongly and pack complete nonsense in the archives. The .hws would not be damaged in that scenario though.

@ApolloGrimoire: Sorry, I don't know about Quina in that cutscene. It's too specific and I don't remember how it is coded in that field :/

@ToraCarol: Text opcodes are things like "[STRT=...]" or "[TIME=-1]" or "[ZDNE]". Basically, everything inside brackets: they are handled specially by the game's text parser and transformed into something else.

18
Yes, if there is a case 144...
Otherwise, you need to set it back to whatever value you jumped from.

Did you understand the purpose of the variable "VAR_GlobInt16_47"? That's what I've been talking about in my last 4 messages.

19
You are definitely doing (or missing) something wrong with the cutscene progression variable (VAR_GlobInt16_47), but without further indications, I can't guess what.

20
I don't know why nothing is working anymore, but the cutscene didn't resume simply because you forgot to add a line "set VAR_GlobInt16_47 = 50" in that "case 143". You need to put that variable back on the track of the normal cutscene.

21
At the top of the function, in the "switchex" line, you need to increment the 1st number by 1.
Like "switchex X ( VAR_GlobInt16_47 ) {" -> "switchex X+1 ( VAR_GlobInt16_47 ) {".

The need of specifying the number of switch cases is bothering... I planned to make it optional at some point (and also make sure that the operation priorities are taken into account when parsing) but I never did in the end.

22
2 solutions:

- The simplest, you don't add any case and you just add a "WindowSyncEx" line right after Kuja's line. With the "Ex" variant, you can choose the speaker so you don't need to have that line in a function of Zidane. There are a few things that can't be done with that solution thoug (I think there's no "RunAnimationEx" for instance).

- The cleanest, you add a case 142 indeed with your extra line and whatever happens at that time. You may add a case 142 to the other characters too (if people are reacting with an animation at the same time for instance). Then, you need to reroute the cutscene progression flow that is handled by a variable (surely "VAR_GlobInt16_47" in this case):
1) You want the new reaction to come right after Kuja's "case 49" script, so replace the "set VAR_GlobInt16_47 = 50" by "set VAR_GlobInt16_47 = 142",
2) In your new reaction case (142 but in only one character's script, Zidane's in this case), make it so the cutscene gets back on track after the added dialog by using "set VAR_GlobInt16_47 = 50".
That way, the cutscene's progression counter does not increase linearly but does something like "... 47, 48, 49, 142, 50, 51...". That's not optimal but that's less tedious than inserting a case and shift all the others. There *might* be side-effects because of that but I don't think there is (I've never seen a cutscene's script where it could be a problem).

23
You can't add new battles unfortunatly.
However, there are a few dummied battles (that's what I've used to add the 4 extra bosses):
- 2 dummy vices that have nonsensical names (the names are actually raw japanese glyphs),
- 1 Zorn/Thorn battle that is dummied (it doesn't have the "Marthym" dialogs and only dummy attacks).
Also, you may delete a few redundant battles (Grand Dragons...) and replace them in the World maps battle lists. The two Ozma battles are also nearly the same as the only difference is the "Out of reach" flag, etc...

You can copy/paste single enemies and single attacks with a right-click (so right-clicking "Kuja" -> copy -> go to a dummied battle -> right-click -> paste).

24
You need to use the Unity Assets Viewer for that.
Open the resources.assets archive, search for the file "BtlEncountBgmMetaData.txt", export it, modify it and then re-import it.
Inside that file, there's a list of field IDs (so the Queen's Chamber in which you fight Beatrix is 1223) and for each field, a list of battles that can trigger in that field with the music ID of the battle ran. If a battle is missing there, the ambiant music doesn't stop when entering a battle.

So just find the field (1223), the battle (73) and put the correct music ID for it (117, "The Wavering Blade").

Here's a list of music IDs. I don't think that you can actually see it in Hades Workshop (only in the UAV when you open the music archive p0data62).
Code: [Select]
34: Zidane's Theme
70: Unrequited Love
9: Vivi's Theme
82: Black Mage Village
76: Fleeting Life
10: Steiner's Theme
62: Steiner's Delusion
29: Garnet's Theme
113: Melodies of Life
69: Over the Hill
77: Awaking Song // A Song from Her Memory, probably sung in Dali
115: Zidane and Dagger's Song
106: A Song from Her Memory
59: Distant Memory
124: Light of Destiny
32: Freya's Theme
68: Burmecia
50: Unforgettable Silhouette
15: Quina's Theme
88: Eiko's Theme
139: Girl of Madain Sari
2: Amarant's Theme
116: Roses of May
117: The Wavering Blade
125: Protecting My Devotion
30: The Evil Within
53: Court Jesters
133: Cid's Theme
118: Master of Time
84: Pandemonium
95: Kuja's Theme
96: Desert Palace // Kuja's Theme, played during the exploration of the Desert Palace
97: Devil's Ambition
98: Bahamut is Summoned
94: Wicked Melody
134: Dark Messenger
73: Moogle's Theme
4: Danger in the Forest
60: Ice Cavern
3: Village of Dali
67: Beyond the Twilight
74: Lindblum
49: Out of the Frying Pan
57: Qu's Marsh
108: South Gate
85: Dark City Treno
92: Cleyra's Trunk
80: Cleyra Settlement
91: Gargan Roo
79: Fossil Roo
90: Conde Petie
99: Before the Altar
130: Ruins of Madain Sari
81: Eidolon Wall
109: Iifa, the Ancient Tree of Life
112: Aboard the Hilda Garde
144: Esto Gaza
110: Mount Gulug
129: Daguerreo, the Hermit's Library
87: Bran Bal, the Soulless Village
132: Memoria
121: Crystal World
24: Aloha De Chocobo
100: Ukulele de Chocobo
22: Vamo Alla Flamenco
58: A Place to Call Home
36: Oeilvert
105: Chamber of a Thousand Faces
103: Ipsen's Castle
101: The Four Mirrors
131: Terra
44: Outlaws
138: Peaceful City // Outlaws, when controlling Vivi early disc 3
18: Swords of Fury
27: Find the Princess
20: Eye to Eye
17: The Fateful Hour
33: Thy Warmth
25: Tragic Love
143: Star-Crossed Lovers
41: Kiss of Betrayal
145: I Want to be Your Canary
142: Inseparable Hearts
65: Prima Vista Orchestra
75: Rufus' Welcoming Ceremony
12: The Meeting
140: The Black Waltz
83: Eternal Harvest
7: The Extraction
141: Foolproof Love Letter Scheme
86: Look Back, See the Frog!
146: Broken Spell, Healed Hearts
72: Guardians
48: You're Not Alone
147: Assault of the Silver Dragons
1: Unforgettable Sorrow
89: Mourning in the Sky
45: Another Nightmare
52: RUN!
111: Hunter's Chance
66: Tetra Master
0: Battle
35: Boss Battle
61: Faerie Battle
71: Final Battle
5: Victory Fanfare
6: Game Over
156: Prelude
148: Doga and Une

25
Yes. In the script of "Environment -> Fields -> A. Castle/East Tower", there are these lines near the 2 thirds of the function "Zidane_Loop":
Code: [Select]
        ChangeTimerTime( 1801 )
        ShowTimer( 1 )
        RunTimer( 1 )
1800 seconds = 30 x 60 seconds = 30 minutes. Just put any number you want there to change the initial time limit.
Then, while it is running, you may use a line like "ChangeTimerTime( GetTimerTime + 60 )" to give a time bonus or whatever, for instance after defeating Tantarian in the Library.

Tip: this kind of setting, done in a cutscene, is usually either in the "Main_Loop" function of the cutscene's field or inside a function of the character doing the action at the same time the setup occurs. There, Zidane is the one speaking ("Yeah! We've got 30 minutes...") when the timer shows up, so that's in his function.

Pages: [1] 2 3 ... 26