Changes

Jump to navigation Jump to search

FF7/DamageFormula

10,772 bytes added, 16:16, 20 May 2021
m
0: Physical Accuracy Check: There is an enemy check on the Dex bonus that I didn't notice before. Physical Chance is unaffected.
== Damage Formula's description Accuracy Function considerations==Each of the upper nybble of the damage calculation determines what checks are done to accuracy of the action and whether or not it will connect, be critical or miss. Here are the functions in order processed based on the upper nybble:
{| border="1" cellspacing="1" cellpadding="3" style="border: 1px solid black; border-collapse: collapse;"
! style="background:rgb(204,204,204)" | Upper Nybble
! style="background:rgb(204,204,204)" | Functions
|-
| 0
| None (always hits)
|-
| 1
| [[FF7/DamageFormula#0:_Physical_Accuracy_Check|Physical Accuracy]], [[FF7/DamageFormula#2:_Critical_Hit_Check|Critical Check]]
|-
| 2
| [[FF7/DamageFormula#1:_Magical_Accuracy_Check|Magical Accuracy]]
|-
| 3
| Dummy [3] (always hits)
|-
| 4
| Dummy [4] (always hits)
|-
| 5
| Dummy [5] (always hits)
|-
| 6
| [[FF7/DamageFormula#0:_Physical_Accuracy_Check|Physical Accuracy]], [[FF7/DamageFormula#2:_Critical_Hit_Check|Critical Check]]
|-
| 7
| [[FF7/DamageFormula#1:_Magical_Accuracy_Check|Magical Accuracy]]
|-
| 8
| [[FF7/DamageFormula#7:_Level-based_Accuracy|Level-based Accuracy]]
|-
| 9
| [[FF7/DamageFormula#6:_Manipulate_Accuracy_.28intended_solely_for_playable_characters.29|Manipulate]]
|-
| A
| [[FF7/DamageFormula#0:_Physical_Accuracy_Check|Physical Accuracy]], [[FF7/DamageFormula#2:_Critical_Hit_Check|Critical Check]]
|-
| B
| [[FF7/DamageFormula#0:_Physical_Accuracy_Check|Physical Accuracy]]
|-
| C
| None (always hits)
|-
| D
| None (always hits)
|-
| E
| None (always hits)
|-
| F
| None (always hits)
|}
0xA0=Damage Calculations=These are the damage functions according to an unmodded FF7-ENG 1.02 (1998)==Standard Formulae=====X0:===''0x5DE5C0''<pre>Sets Target's 02h flag to 1. (Unknown effect)</pre>
Prepare Function 0x0===X1:===''0x5DE5DF''<pre>If Attack Property "Always Critical" is Set Set Critical Damage FlagEnd If
Prepare Function 0x2x = ( Actor's Level * Actor's (M)Attack ) / 32y = ( Actor's Level + Actor's (M)Attack ) / 32z = Actor's (M)Attack + ( x * y )z = z * ( 512 - target's defense ) * Attack's PowerDamage = z >> 13//This is a bit-shift left by 13 which is mathematically equivalent to dividing by 8192, but it's important to note that it doesn't actually divide as this is the source of the damage overflow glitch
If Critical Damage Function 0x1Flag is set Damage = Damage * 2End If
damage If Actor's Statuses include Berserk Damage = damage Damage * (1 + number_of_status1 + 3 / 2 * number_of_status2).End If
number_of_status1 are calculated as sum of attacker statuses darkness, slow, silence, sadness, poison, near death.Long_Range = 0If Target is in Back Row Set Long_Range = 1End If
number_of_status2 are calculated as sum of attacker statuses death sentence, slow-numb.If Attack is Short Range OR Command is Enemy Attack If Actor is in Back Row Long_Range = 1 End IfElse Long_Range = 0End If
If Long_Range != 0
Damage = Damage / 2
End If
If Target is Defending
Damage = Damage / 2
End If
0xA1:If Target's Back is exposed Damage = Damage * ( Target's Back Attack Modifier / 8 )End If
Prepare Function 0x0If Actor's Statuses includes Frog Damage = Damage / 4End If
Prepare Function 0x2Damage = Sadness( Damage )Damage = Split( Damage, 0 )Damage = Barrier( Damage ) If Actor's Statuses include Mini Damage = 0End IfDamage = Variance( Damage )</pre>
===X2:===''0x5DE9B8''<pre>multiNoSplit = ( ( ( Attack's Target Flags AND Ch ) - 4 ) == 0 ? 1 : 0 )Base = (Actor's Attack + Actor's Level) * 6Damage Function 0x1= (512 - Target's Defense) * Base * Attack's Power / 8192Damage = Sadness( Damage )Damage = SplitDamage( Damage, multiNoSplit )Damage = Barrier( Damage )Damage = Variance( Damage )</pre>
if current hp less then max hp / 4 then damage = damage * 2.==X3:===''0x5DEA6D''<pre>If Attack Properties Damage MP is clear Damage = Target's HPElse Damage = Target's MPEnd If
if attacker in death sentence then damage Damage = damage Damage * 4.Attack's Power / 32
If ActionData[AC] != 0 (?)
Damage = Damage / 2
End If</pre>
===X4:===
''0x5DEAF7''
<pre>If Attack Properties Damage MP is clear
Damage = Target's MHP
Else
Damage = Target's MMP
End If
0xA2:Damage = Damage * Attack's Power / 32
Prepare Function 0x0If ActionData[AC] != 0 (?) Damage = Damage / 2End If</pre>
Prepare Function 0x2===X5:===''0x5DEB81''<pre>Damage = (Actor's (M)Attack + Actor's Level) * 6 + (Attack's Power * 22)Damage = SplitDamage( Damage )Damage = Barrier( Damage )Damage = Variance( Damage )</pre>
===X6:===''0x5DEBE5''<pre>Damage Function 0x1= Attack's Power * 20</pre>
damage = damage ==X7:===''0x5DEC0A''<pre>Damage = ( ( 512 - Target's Def ) * Attack's Power / 32 )Damage = Variance(1 + number_of_dead_player_unitsDamage ).</pre>
===X8:===
''0x5DEC52''
<pre>
If ActionData[0x230] AND 40h
ActionData[0x230] = 1
Else
ActionData[0x230] = 80h
End If
//presumably this checks if the target heals from restore element and will either recover or kill based on the result</pre>
===X9:===
''0x5DEC8A''
<pre>
Actor's Attack = Actor's Strength * 2
Use Damage X1 with adjusted stat
</pre>
0xA3===XA:===''0x5DECAA''<pre>Damage = ( Attack's Power + Number of Targets - 1 ) / Number of Targets</pre>
Prepare Function 0x0==Additional Checks=====Sadness( Damage )===''0x5DE958''<pre>If Target's Status includes Sadness Damage = Damage - (Damage * 3 / 10)End IfReturn Damage</pre>
Prepare Function 0x2===SplitDamage( Damage, multiNoSplit )===''0x5DE8F4''<pre>If multiNoSplit == 0 If No. of Attack's Targets >= 2 Set Attack's split damage Target Flag Else Set multiNoSplit == 1 End IfEnd If
power_modifier If ActionData[0xAC] = total_level_of_all_enemy_target = 0 Damage = Damage / 2Else If multiNoSplit == 0 Damage = Damage * 3 / 2 End IfEnd IfReturn Damage</ number_of_enemy_target.pre>
===Barrier(this only use enemy units from 4 to 10 that includes in target mask after all preparationDamage )===''0x5DE82C''<pre>If Attack Property "Physical" is 0 If Target's Statuses include MBarrier Set ActionData "MBarrier Active" flag End IfElse If Target's Statuses include Barrier Set ActionData "Barrier Active" flag End IfEnd If
If ActionData "MBarrier Active" or "Barrier Active" flags are set Damage Function 0x1= Damage / 2End If
If attack is Magic and EnabledMagic[7] == 0 (?)
Damage = Damage + ( Damage * ( EnabledMagic[7] * (10 / 32) ) / 100 )
End If
Return Damage
</pre>
===Variance( Damage ):===
''0x5DE988''
<pre>
Damage = Damage ([0..255] + 3841) >> 12 //from RNGLUT in KERNEL.BIN
//Again, we have another chance for overflow.
0xA4:If Damage == 0 Damage == 1End IfReturn Damage</pre>
Prepare Function 0x0==Secondary Damage Formulae=====X0:===''0x5DECFB''<pre>Damage = Attacker's HP</pre>===X1:===''5DED1E''<pre>Damage = Attacker's MHP - Attacker's HP</pre>===X8:===''0x5DED73''<pre>Dice_Count = Attacker's Level / 10
Prepare Function 0x2If Dice_Count < 2 then Dice_Count = 2Elseif Dice_Count > 6 Dice_Count = 6End If
power_modifier total_dice_roll = 1 0For ( d_loop = 0; d_loop < Dice_Count; d_loop++ (((current_hp * 3) / max_hp) * power_modifier) die = [0..5] all_dice[d_loop] = die total_dice_roll += die + 1
Damage Function 0x1 set die visualization based on rollLoop
value_repeat = 0
For ( d_value = 0; d_value < 6; d_value++ )
repeat_count = 0
For ( d_loop = 0; d_loop < Dice_Count; d_loop++ )
0xA5: If all_dice[d_loop] = d_value then repeat_count++ End If Loop
Prepare Function 0x0 If repeat_count > value_repeat then value_repeat = repeat_count End If
Prepare Function 0x2Loop
power_modifier Damage = value_repeat * 100 * total_dice_roll</pre>===X9===''0x5DEEEF''<pre>Damage = Number of Successful Escapes</pre>===XA===''0x5DEF1D''<pre>Damage = Target's HP - 1 </pre>===XB===''0x5DEF44''<pre>Damage = (Game Time Hours * 100) + (((current_mp Game Time Minutes)</pre>===XC===''0x5DEF88''<pre>Damage = Target's Kill Count * 3) 10//This is intended to be used only on players//This will cause a memory leak if done on enemies</ max_mppre>===XD===''0x5DEFDD''<pre>If target is playable character MateriaCount = 0; For ( MateriaLoop = 0; MateriaLoop < 8; MateriaLoop++ ) If target has materia in weapon slot [MateriaLoop] then MateriaCount++ If target has materia in armor slot [MateriaLoop] then MateriaCount++ Loop Damage = MateriaCount * power_modifier).1111End If</pre>
Damage Function 0x1=Accuracy Functions=The point of these is to set the "attack will miss" flag in the current action memory structure.
===0: Physical Accuracy Check===
''0x5DDBB0''
<pre>;For the purposes of this code, "Dex" means the adjusted Dexterity of the actor/target if any in-battle dex bonuses have been granted.
;Same holds for the Physical Evade. Physical Hit rate has no in-game bonus opportunities.
Check_For_Cover()
0xA6:HitChance = -1;
Prepare Function 0x0If "Always connect" flag set then HitChance = 255;
Prepare Function 0x2If target has one of the following statuses (Death, Sleep, Confu, Stop, Petrify, Manipulate, Paralysis) then Remove Sleep status Remove Confu status Remove Manipulate status HitChance = 255End If
power_modifier If action is flagged as "always hit" then HitChance = 1 + (((total_ap / 10000) * power_modifier) / 16).255;
Physical Chance = (total_ap Actor's Dex >> 2) + action physical hit rateIf Actor is no more than ap needed for max star, so underwater materia wonenemy then Actor's evade = Actor's Physical evadeelse Actor's evade = (Actor't works Dex >> 2)+ Actor's Physical evadeEnd IfIf Target is enemy then Target's evade = Target's Physical evadeElse Target's evade = (Target's Dex >> 2) + Target's Physical evadeEnd If
Damage Function 0x1If HitChance = -1 Then HitChance = Physical Chance + Actor's evade - Target's evade HitChance = FuryAdjust(HitChance)End If
If HitChance = 0 then HitChance = 1
Luck Chance = [0..99]
If (Actor's Luck / 4) > Luck Chance Then
HitChance = 255 ;Lucky Hit
Else
If Actor is Player Character targetting an enemy Then
If (Target's Luck / 4) > Luck Chance
HitChance = 0 ;Lucky Dodge
End If
End If
End If
Miss Chance = (([0..65535] * 99) / 65535) + 1 ;essentially [1..100]
if HitChance < Miss Chance then
Set Miss flag
End If</pre>
0xA7:====Check_For_Cover==== This is where the game checks if the target is covered under a "cover"ing ally. It only applies to Player Characters It might be more complicated than I'm seeing, but that is definitely ONE of its functions
Prepare Function 0x0====FuryAdjust(HitChance)====<pre> If HitChance < 255 then If Actor is in Fury Status HitChance = HitChance - ((HitChance * 3) / 10) End If End If return HitChance </pre>
Prepare Function 0x2===1: Magical Accuracy Check===''0x5DDE5E''<pre>acc = Action's Accuracytar_save = level / 2; //rounded downacc_bonus = actor's level - tar_saverand_0 = [0..99]rand_1 = [0..99]if acc < 255 then if target does not have instant-death, null, or heal properties to current attack then if attack is not (reflectable and target in reflect status) then if attack does not inflict statuses or inflicting status include: Death, Sleep, Confu, Stop, Petrify, or Paralysis then acc = Fury_Adj( acc ); if target's M_Evade > rand_0 OR acc + acc_bonus < rand_1 then Set action miss flag end if end if end if end ifend if</pre>
power_modifier = 10 ==2: Critical Hit Check===''0x5DDF8E''<pre>If attack does not miss then if actor in lucky girl status then critical_chance = 255 else critical_chance = ((actor's luck + actor's level) - target's level ) >> 2; if actor is playable character then critical_chance + = weapon's critical bonus //? end if Critical_random = (((number_of_kills / 128) [0..65535] * power_modifier99 ) / 1665535 ).+ 1; if critical_chance > critical_random then attack set to critical end if end ifend if</pre>
Damage Function 0x13, 4, and 5 don't exist. Since they don't set miss they will always hit.
===6: Manipulate Accuracy (intended solely for playable characters)===
''0x5DE0D0''
<pre>
int ally_loop;
ManipSuccess = 0;
for ( ally_loop = 0; ally_loop < 3; ally_loop++ )
{
if target is currently under manipulation by an actor then
break;
end if
}
if target is not currently being manipulated AND
target is not a playable character AND
target is an enemy AND
actor is not currently manipulating an enemy AND
target is not under manipulate status AND
target's timer bar is running AND //like they're not stopped, petrified, etc
target's attack resistance is "always-hit" then //?
Manip_Chance = actor's level + 50 - target's level; //no less than 0
if target count > 1 then
Manip_Chance = ( Manip_Chance << 2 ) / 5;
end if
if actor's [0xAC] == 0 then
Manip_Chance >> 1;
end if
if target's attack resistance is "always-hit" then
Manip_Chance = 255;
end if
if actor's accessory property == 5 //"Increase manip rate" property on Hypnocrown
if Manip_Chance < 100 then
Manip_Chance = 100;
end if
end if
If Manip_Chance > [0..99] then
ManipSuccess = 1;
end if
end if
If ManipSuccess == 1 then
Set actor's manipulated enemy to target
Display String 5Ah {"Manipulated <Enemy>"}
Clear Actor's 0xE4 value //unknown
else
Set attack missed
end if
</pre>
This doesn't actually place the target in the manipulate status. That happens elsewhere.
 0xA8===7:Level-based Accuracy===''0x5DE08A''Prepare Function 0x0 Prepare Function 0x2<pre>If Action's Accuracy > 0 thenpower_modifier = 1 + (((limit_bar_value * If the remainder of (limit_level + 1) Target's level / 16) * power_modifierAction accuracy ) is non-zero then Set attack missed end ifend if</ 16)pre>So if the accuracy IS 0, then it will always hit. This is to prevent a divide by zero errorDamage Function 0x1
6
edits

Navigation menu