CheckDead¶
This is an action coroutine that runs at specific points during the battle to check the health of every actors and if any are found dead when they weren't before, the coroutine performs the process to kill them properly mainly by calling Death on their battleentity. The coroutine is usually stored on the checkingdead
field which tracks whether or not a CheckDead is in progress, but other coroutines may use this field.
NOTE: This field is shared by other coroutines, but as long as care is taken such that no collisions happens, this is fine. Under normal gameplay, this is normally safe.
The coroutine does nothing if gameover
is in progress. In that case, checkingdead
is set to null followed by a yield break.
Here's the CheckDead procedure:
deadenemypos
is reset to a new listaction
is set to true which changes to an uncontrolled flow- For player party member whose
hp
is 0 or below while their battleentity.death
is false (meaning this member should be dead, but isn't currently), the player death process occurs (see the section below for more details) - From there, if there are no longer any player party members with an
hp
above 0 while noteatenby
, a DeadParty terminal coroutine is started changing to a terminal flow followed by a yield break which abruptly ends this CheckDead - If any player party member were killed, SetLastTurns is called which resets
lastturns
to a new aray with the length being the amount of free players - 1 and all elements being -1 (this resets the player selection cycle) - The enemy death checks occurs (see the section below for details)
- If
deadenemypos
isn't empty (meaning at least one enemy party member died or fled during this CheckDead),extraenemies
isn't empty and there are still player party members with anhp
above 0 while not beingeatenby
, theextraenemies
summons procedure is performed (check the section below for details) - If there are no longer any enemy party members left while
mainturn
isn't in progress,mainturn
is set to a new AdvanceMainTurn call which will take care of detecting the terminal case of winning the battle and act accordingly - Otherwise:
- A frame is yielded
- If EnemyDropping reports that all enemy party members's battleentity.
droproutine
isn't in progress whilemainturn
isn't in progress,action
is set to false which will change to a controlled flow once CheckDead completes. NOTE: It is possible that Chompy is running by this point because it is possible Chompy killed an enemy and if anextraenemies
summon happens later, it can lead into a situation where if the killing this enemy leads to other's hitaction being triggered,action
would be set to false causing a DoAction call to happen BEFORE Chompy sees that CheckDead completed which leads to yet another DoAction so 2 concurent calls will be racing against each other
- If we aren't
inevent
, ReorganizeEnemies is called with order checkingdead
is set to null which reports to the rest of BattleControl that CheckDead is no longer in progress
Player party member death process¶
tired
is set to 0 (removes all exhaustions)charge
is set to 0- StartDeath is called on the battleentity which starts a Death process on it
- If
enemy
is true (the player party member died during the enemy phase, a hitaction or a delproj advance),turnssinedeath
is set to -1 (this is so it gets incremented to 0 on their AdvanceTurnEntity later). - ClearStatus is called on the player party member
- battleentity.
dead
is set to true (the Death process already does that) - If the battleentity.animid matches the battle's
forceattack
, it is reset to -1 (since the target is no longer valid)
Enemy party death checks¶
The following is enclosed in an infinite while loop, but in practice, it will only be iterated a maximum of 2 times.
An enemy party member is considered dead if they have fled or their hp
isn't above 0 while their battleentity isn't dead
yet. For each that are found:
- The battleentity position is added to
deadenemypos
- DestroyConditionIcons is called on the battleentity
From there, the dying process depends if the enemy party member fled
or not.
Die by fleeing¶
The following happened if CheckDead found the enemy party member fled:
- battleentity's position is set to offscreen at (0.0, -1000.0, 0.0)
- If
destroyentity
is true, the battle entity gets disabled
Die by hp
not being above 0¶
The following happens if CheckDead found the enemy hasn't fled meaning they were found dead because their hp
wasn't above 0:
charge
is set to 0- condition is reset to a new list
- LockRigid(false) is called on the battleentity to unlock its
rigid
- If holditem wasn't -1, DropItem is called on the enemy party member with additem true
- If
animid
(the enemy id) is less than the amount of instance.enemyencounter
(normally 256),alreadycounted
is false and battleentity.cotunknown
is false (this isn't a Cave Of Trials's shadow), the corresponding bestiary entry's defeated counter is incremented followed by settingalreadycounted
to true - The EXP amount is obtained by performing a BattleControl.GetEXP call on the
exp
,fixedexp
and theanimid
(the enemy id) clamped from 0 to instance.neededexp
unless battleentity is ahologram
in which case, it's clamped from 0 to 5 instead. This method can change the rewarded exp with a given scaled enemy'sexp
field, check the documentation to learn more expreward
is increased by the amount determined above and then clamped from 0 to instance.neededexp
moneyreward
is increased by the return of GetMoney usingmoney
which is a uniform random number between 0 andmoney
inclusiveexp
is set to 0- If eventondeath is -1:
- Death is called on the battleentity
- entity.
spitexp
is set to the amount of EXP determined earlier money
is set to 0
- Otherwise if
inevent
is false,inevent
is set to true followed by an EventDialogue starting with eventondeath as the id - If the current enemy party member index is still valid (protects against an edgecase that can involve EventDialogue 9 which involves the
Acolyte
enemy):
Cleanup and diebyitself rechecks¶
The following happens after all checks are done:
- UpdateConditionIcons is called which calls UpdateConditionBubbles on the battleentity (all
playerdata
with right to false and allenemydata
withhp
above 0 with right to true) - If any enemy was found to be
dead
or fled earlier, ReorganizeEnemies is called without skip
Finally, this is where all of this section's logic can be reiterated. It happens if all of the reamining enemy party members have their diebyitself
set to true. This means that they should die automatically and in order to do so, their hp
are set to 0 and their diebyitself
set to false to avoid reentering this case.
By reiterating all the enemies check like this, CheckDead will be forced to detect the death of all remaining enemy party members because their hp
were just set to 0. This recheck can only happen once making the loop iterating a maximum of 2 times.
extraenemies
summons¶
This section will move the appropriate amount of extraenemies
to the main enemydata
array so the ones that died can be replaced when applicable. Here's the process:
- All the enemy party members that died or fled during this CheckDead has their
droproutine
stopped then set to null if it was in progress - For each
deadenemypos
(but not more than the amount inextraenemies
):summonnewenemy
is set to true- SummonEnemy is called with type
Offscreen
, the enemy id being theextraenemies
at the same index than thedeadenemypos
and the position being thedeadenemypos
- 0.5 seconds are yielded
- All frames are yielded as long as
summonnewenemy
is true and EnemiesAreNotMoving reports false (meaning at least one enemy party member has their battleentity is in a forcemove) - If instance.
map
is theAbandonedCity
map and flags 400 (temporary slot) is true, all enemy party members have 2 SetCondition calls on them: one with AttackUp for 999999 actor turns and one with DefenseUp for 999999 actor turns - All the corresponding
extraenemies
that were just summoned are removed fromextraenemies
- A frame is yielded