AddExperience¶
AddExperience is a terminal coroutine that is invoked whenever most battles are won with EXP gain. This coroutine will be the step between the battle finishing and ExitBattle which is a wrapper around ReturnToOverworld.
The coroutine yield breaks immediately if alreadyending is true (meaning AddExperience or GameOver was already invoked) or gameover is in progress.
NOTE: The vast majority of the logic in this coroutine concerns very verbose animations and UI rendering. For the sake of brevity, they will be paraphrased and details will be kept at a high level. All other logic will still be mentioned in granular details.
Setup¶
alreadyendingis set to true which prevents double invocationsactionandcancelupdateare set to true changing to a terminal flowenemyis set to false, but this doesn't do anything because we just changed to a terminal flow- If the
HealingBuzzmedal is equipped:- All player party members with an
hpabove 0 has Heal called on them for an ammount of 2 with nosound - The
Healsound is played (the reason the Heal calls didn't had sound is to avoid playing healing sounds multiple times)
- All player party members with an
- 0.5 seconds are yielded if any player party members were healed as a result of the
HealingBuzzlogic above - If the
VictoryBuzzmedal is equipped:- HealTP is called which plays a
Heal2sound followed by a heal of instance.tpby 4 followed by a ShowDamageCounter with type 2, the amount being 4, the start position beingplayerdata[GetRandomAvaliablePlayer()].battleentityposition + (2.0, 2.0, 2.0) and the end position being (5.0, 5.0, 5.0) - 0.5 seconds are yielded
- HealTP is called which plays a
- If
exprewardis above 5:checkingdeadis set to a new UseCharm coroutine starting withExpUpas the type- All frames are yielded while
checkingdeadis in progress
- The
switchiconandfronticonare destroyed - If flags 613 is true (RUIGEE is active),
exprewardis set to 0 - Otherwise, if
exprewardwas already 0 whileenemyfledis false and instance.partylevelis less than 27 (the normal max rank),exprewardis set to 1 - RefreshEXP is called
- AddExperience determines if a
BattleWonsound should be played. it will be ifmusicvolumeis above 0.0 andmusic[0].name isBattle0orBattle6(meaning that the music we were just playing was one of the 2 regular battle themes). If that is the case:- FadeMusic is called with a fadespeed of 0.05
- The
BattleWonsound is played and the AudioSource is kept track locally - If the
BattleWonAudioSource indeed exists, its volume is set tomusicvolume(this is needed because it's a sound so it wouldn't get the music volume by default)
- flagvar 0 is set to
expreward(this will be used for rendering later) - instance.
hudcooldownis set to -1.0 - All frames are yielded while there are still any enemy party members
- 0.45 seconds are yielded
- All player party members has their matching instance.
hud's child has its local position set to Vector3.zero - For every player party members whose
hpis above 0: - instance.
camtargetposis set to (-4.5, 0.0, 2.5)
EXP gain visuals setup¶
The process to render the expereince gain screen is very verbose and complex so the procedure is paraphrased a lot here:
- A
textholderGameObject gets created with aDelAftBtltag (destroyed on ReturnToOverworld) childed to the GUICamera with a z local position of 5.0 - SetText is called in non dialogue mode using the following string:
|sort,10000||color,4||center||dropshadow,0.05,-0.05||backbox,6|followed bymenutext[117](a message informing the player they gained EXP where the number is|var,0|). The call has the following properties:- fonttype of 2 (UNUSED, but gets overriden to
D3Streetism) - No linebreak
- No tridimensional
- position of (0.0, 3.0, 5.0)
- No cameraoffset
- size of Vector3.one
- parent being the
textholder - No caller
- fonttype of 2 (UNUSED, but gets overriden to
- A new UI object called
ExpBarwith aDelAftBtltag (destroyed on ReturnToOverworld), a DialogueAnim and a pure yellow color usingguisprites[4](the HUD background sprite) is created as the background of the EXP text lviconis set to a new UI object namedIconusingguisprites[27](the EXP icon sprite) childed to theExpBar- A DynamicFont is setup childed to the
ExpBarwith a layer of 5 (UI) with a pure white color with the starting text being the following appended together:- instance.
partyexppadded to the left with 30 /- instance.
neededexp
- instance.
- All player party members with an
hpabove 0 has their battleentity.spinzeroed out leveledis set to false- 0.15 seconds are yielded
EXP orbs counting and wait¶
This sub section concerns the counting of the EXP gained and the management of its fast version if requested by the player.
- instance.skiptext is set to false (this isn't used for its SetText use since it will be managed manually)
- A new GetSkip coroutine is started and stored localled which will yield all frames until input 4 (Confirm) is pressed which wil cause instance.
skiptextto be set to true - The EXP orbs are counted starting with
bigexporbsthen moving tosmallexporbsthat exists (there is a frame yield between the 2 types's counting). A big one will have 1 EXP counted 10 times while a small one will only have it counted once. This is how the counting happens each time:- The orb gets destroyed
- AddExp(1) is called to add the exp (more details below)
- If the AddExp call resulted in a rank up, Leveled is called which sets
leveledto true, but if it wasn't true before, a SpinAround component added tolviconwith itsitselfset to (0.0, 20.0, 0.0) followed by aLazersound being played at 1.2 pitch - The DynamicFont of the EXP's text is refreshed using the new instance.
partyexp - If instance.
skiptextis still false, a yield is done. The time of the yield is 0.075 seconds unlessexprewardwas at least 10 where it will be 0.045 seconds instead
- At this point, the GetSkip coroutine call earlier is stopped since it no longer has any use
- If instance.
skiptextwas set to true by the end of the counting, the DynamicFont of the EXP's text is refreshed using the new instance.partyexpfollowed by 0.2 seconds being yielded - A frame is yielded
- instance.
skiptextis set back to false - For a maximum of 50.0 frames (tracked with a local counter starting at 0.0 and incremented by 1/50 of the game's frametime until it reaches 1.0), all frames are yielded until any input is pressed which interupts this wait early
- If the
BattleWonsound was played earlier, all frames are yielded while it's still playing and hasn't reached 2.35 seconds - A second is yielded if no
BattleWonsound was played
AddExp¶
The method mentioned above called AddExp belongs to MainManager and it adds the exploration points and determines if a rank up happened as a result:
public static bool AddExp(int ammount)
Increases partyexp by ammount. If this resulted in a rank up, true is returned, false otherwise. A rank up is detected if after the increase, partyexp becomes at least neededexp. When that happens, partyexp is decreased by neededexp.
Before returning, a PlaySound call happens to play the the Exp2 sound with a volume of 1.0 and a pitch of 1.5 + a random number between -0.1 and 0.1. The sounds element to use is the first among sounds[4], sounds[5], sounds[6] and sounds[7] in that order that isn't playing (always falsback to sounds[7] even if it is playing).
Text UI teardown¶
- A DialogueAnim is added on the
ExpBarobject to move it to the left offscreen - 0.5 seconds are yielded
- The
textholderobject is destroyed - A frame is yielded
Rank up logic¶
This logic only happens if leveled is true and instance.partylevel is less than 27 (the normal max rank).
The logic in here is very complex and mostly contains verbose animations so it will be paraphrased a lot.
Setup¶
- instance.
partylevelis incremented - 0.25 seconds are yielded
- instance.
neededexpis increased to a certain amount to indicate the new amount required to rank up. The first increase that applies in the following ones is the one that will occur (they are mutually exclusive):- +5 If flags 656 is true (MOREFARM is active)
- +3 if instance.
partylevelis at least 24 - +2 if instance.
partylevelis at least 15 - +1 if none of the above applied
- ChangeMusic is called with the
LevelUpmusic Prefabs/Particles/Flowerettiparticles are instantiated childed to thebattlemapand played- All
Sprites/GUI/BattleMessage/rankXare loaded whereXis the languageid (it falls back to English if no Sprites exists for it) - All objects with tag
Enemyare destroyed - SetDefaultCamera is called
- MainManager.Heal is called
- instance.
hudcooldownis set to -1 - instance.
optionis set to 0 and instance.maxoptionsto 3
Rank up animation¶
- All player party members has their battleentity.
animstateset to 4 (ItemGet) and theirspinto (0.0, 20.0, 0.0) - All player party members are move to be centered on the screen using MiddlePos via lerping their battleentity.position for a maximum of 34 frames (tracked via a local framecounter advancing by 0.03 of the game's frametime from 0.0 to 1.0)
- All player party members gets their battleentity.
spinzeroed out and their battleentity has a SpecialAnimation started with thelevelupanimation - The letters of the Rank up messages appears in the following fashion:
- A
LetterHolderobject is created and childed to GUICamera - New UI objects called
letterXwhere X is the index of the letter sprite loaded earlier are created all childed to theLetterHolderwith a FontEffects using just the rainbow effect - The letters appear from offscreen at 99.0 in Y and 5.0 in Z using a lerp off their local position. This is done over a maximum of 200.0 frames and it is porportional to the amount of letters to show
- 0.65 seconds are yielded
- All letters have their local scale lerped from Vector3.one to (0.0, 1.25, 1.0) and their angle increased by Vector3.up * 5x the game's frametime continuoudly over the course of maximum 34 frames (tracked via a local framecounter advancing by 0.03 of the game's frametime from 0.0 to 1.0)
- The
LetterHolderis destroyed
- A
Rank up bonus UI setup¶
- 3
Prefabs/Objects/Vineare created using layer 15 (3DUI) childed to thebattlemapwith each their own UI icon. The vines are positioned centered to the screen using MiddlePos and they have a DialogueAnim with a tsize being Vector3.one * 2.0. Each has aguisprites[42](a hexagon) on the background of a newOvericonobject with a SpriteRenderer childed to their vine. The sprites used for the icons are:- 0: HP icon
- 1: TP icon
- 2: MP icon
- An MP count HUD element is created:
- New UI object called
medalhudchilded to thetextholderwith a pure yellow color using the HUD background sprite - New UI object called
medaliconchiled to themedalhudusing the MP icon sprite - A DynamicFont is setup on the
medalhudas parent withdropshadowand with the text being the following appended together:- instance.
bppadded to the left by 20 /- instance.
maxbppadded to the left by 20
- instance.
- A DialogueAnim is added on the
medalhudso it appears from the top of the screen
- New UI object called
- 0.8 seconds are yielded
- A 9Box is created with a DialogueAnim to make it grow
- A SetText call happens in non dialogue mode with the text being
|single|followed bymenutext[122](a prompt message to pick a stat boost) and the following properties:- fonttype of 0 (
BubblegumSans) - No linebreak
- No tridimensional
- position of (-7.5, 0.15, 0.0)
- No cameraoffset
- size of Vector3.one
- parent being the 9Box
- No caller
- fonttype of 0 (
- A new UI object is created named
tchilded to the GUICamera using thecursorsprite[0]with a SpriteBounce - 5 frames are yielded (counted by MainManager.
framestep)
Rank up bonus UI naviguation and confirmation¶
- All frames are yielded while Input 4 (Confirm) isn't pressed
- A
Confirmsound is played - A frame is yielded
- The cursor gets childed to the
battlemapthen moved offscreen and DestroyText is called with it - instance.
hudcooldownis set to -1 - A SetText call happens in non dialogue mode with the text being
|single|followed bymenutext[119](the HP rank up bonus description) and the following properties:- fonttype of 0 (
BubblegumSans) - No linebreak
- No tridimensional
- position of (-7.5, 0.15, 0.0)
- No cameraoffset
- size of Vector3.one
- parent being the 9Box
- No caller
- fonttype of 0 (
- 5 frames are yielded (counted by MainManager.
framestep) - From here, an infinite loop is entered with a frame yield each iteration that won't exit until one of the 3 rank up bonuses have been chosen. Each iterations features the selected instance.
option's vine's sprites being rotated and scaled via a lerp continuously propotional to the games frametime. It also feature another SetText call just like the above when instance.optionchanges, but the text ismenutext[119 + X]whereXis instance.option:- If
caninputcooldownisn't expired, it is decreased by the MainManager.framestepand no input can be taken until it expires - Otherwise, the logic depends on the input:
- 2 / 3 (Left / Right): changes instance.
optionaccordingly with wrap around to 2 followed by a scroll sound followed bycaninputcooldownbeing set to 3.0 - 4 (confirm): The UI loop is exited (the option chosen is indicated by instance.
option)
- 2 / 3 (Left / Right): changes instance.
- If
- The
LevelUpsound is played - For a maximum of 40 frames (tracked with a local counter starting at 0.0 and incremented by 1/40 of the game's frametime until it reaches 1.0):
- All other vines than the instance.
optionone have their local Y position lerped to 20.0 and their Z to 0.0 which moves them offscreen - The instance.
optionvine gets their angles reset
- All other vines than the instance.
- The
CrowdClapsound is played onsounds[9]with 0.5 volume
Rank Up bonus application¶
The logic to apply the bonus depends on instance.option:
- 0 (HP): All player party members gets their
basehpandmaxhpgets incremented and a 1HPbonus to the party is added to instance.statbonusvia AddStatBonus - 1 (TP): A 1
TPbonus to the party is added to instance.statbonusvia AddStatBonus - 2 (MP): instance.
maxbpand instance.bpgets increased by 3 and a 3MPbonus to the party is added to instance.statbonusvia AddStatBonus. It also causes themedalhud's DynamicFont text to be refreshed with the new instance.bpand instance.maxbp
After, the following happens:
- ApplyStatBonus is called
- Each player party member has a unique animation played there that sets their battleentity.animstate to a value that depends on the
trueid:Bee: 111, also comes with a SlowSpinStop of (0.0, -20.0, 0.0) for 30.0 frametime on the battleentityBeetle: 114, also comes with a battleentity.fliptoggleMoth: 115
- A frame is yielded
- ApplyBadges is called
LevelUpMessage and teardown¶
- instance.
hudcooldownis set to -1 medalhud's DialogueAnim'stargetposis set to (3.7, 10.0, 5.0) which moves it along with the rest of the HUDmedalhudis destroyed in 0.5 seconds- 0.5 seconds is yielded
- The 9Box is destroyed
- flagvar 0 is set to 0 (this will be used to track whenever a coroutine gets done)
- A LevelUpMessage coroutine is started (this will set flagvar 0 to 1 when it's complete)
- All frames are yielded while flagvar 0 is 0 (meaning the LevelUpMessage isn't done yet)
- ApplyBadges is called
- A frame is yielded
- MainManager.Heal is called with noparticle and with nosound
- instance.
hudcooldownis set to -1
Special heal¶
If the rank up logic didn't happen, but instance.partylevel is at least 99 (which normally can never happen), Heal is called.
Last steps¶
- A frame is yielded
sounds[9]is stopped with a 0.002 delay- ExitBattle is called