Changes

Jump to navigation Jump to search

FF7/DamageFormula

5,807 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== <!-- 0X = 8 none (always hit)--><!-- 1X = 0, 2 physical, isCritical--><!-- 2X = 1 magical--><!-- 3X = 3 none (always hit)--><!-- 4X = 4 none (always hit)--><!-- 5X = 5 none (always hit)--><!-- 6X = 0, 2 physical, isCritical--><!-- 7X = 1 magical--><!-- 8X = 7 LevelBasedAccuracy--><!-- 9X = 6 manipulate--><!-- AX = 0, 2 physical, isCritical--><!-- BX = 0 physical--><!-- CX = 8 none (always hit)--><!-- DX = 8 none (always hit)--><!-- EX = 8 none (always hit)--><!-- FX = 8 none (always hit)--> 0x11: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) Damage Function 0x1  0xA0: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) Damage Function 0x1 damage = Each of the upper nybble of the damage * (1 + number_of_status1 + 2 * number_of_status2). number_of_status1 calculation determines what checks are calculated as sum done to accuracy of attacker statuses darknessthe action and whether or not it will connect, slow, silence, sadness, poison, near deathbe critical or missnumber_of_status2 Here are calculated as sum of attacker statuses death sentence, slow-numb.   0xA1: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) Damage Function 0x1 if current hp less then max hp / 4 then damage = damage * 2. if attacker the functions in death sentence then damage = damage * 4.   0xA2order processed based on the upper nybblePrepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) Damage Function 0x1 damage = damage * (1 + number_of_dead_player_units).   0xA3: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) power_modifier = total_level_of_all_enemy_target / number_of_enemy_target. (this only use enemy units from 4 to 10 that includes in target mask after all preparation) Damage Function 0x1   0xA4: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) power_modifier = 1 + (((current_hp * 3) / max_hp) * power_modifier). Damage Function 0x1   0xA5: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) power_modifier = 1 + (((current_mp * 3) / max_mp) * power_modifier). Damage Function 0x1   0xA6: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) power_modifier = 1 + (((total_ap / 10000) * power_modifier) / 16). (total_ap is no more than ap needed for max star, so underwater materia won't work) Damage Function 0x1    0xA7: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) power_modifier = 10 + (((number_of_kills / 128) * power_modifier) / 16). Damage Function 0x1   0xA8: Prepare Function 0x0 (calculate physical hit chance) Prepare Function 0x2 (calculate critical chance) power_modifier = 1 + (((limit_bar_value * (limit_level + 1) / 16) * power_modifier) / 16). Damage Function 0x1
{| 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)
|}
=Damage Calculations=
For standard These are the damage functionsaccording to an unmodded FF7-ENG 1.02 (1998)==Standard Formulae=====X0:===''0x5DE5C0''<pre>Sets Target's 02h flag to 1. (Unknown effect)</pre>
X0===X1:===<pre>Sets Target's 02h flag to 1. (Unknown effect)</pre>----X1:'0x5DE5DF''
<pre>If Attack Property "Always Critical" is Set
Set Critical Damage Flag
z = Actor's (M)Attack + ( x * y )
z = z * ( 512 - target's defense ) * Attack's Power
Damage = z >> 13/ 4096/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 Flag is set
End If
Damage = Variance( Damage )</pre>
----===X2:===''0x5DE9B8''
<pre>
multiNoSplit = ( ( ( Attack's Target Flags AND Ch ) - 4 ) == 0 ? 1 : 0 )
Base = (Actor's Attack + Actor's Level) * 6
Damage = (512 - Target's Defense) * Base * Attack's Power/ 8192
Damage = Sadness( Damage )
Damage = SplitDamage( Damage, multiNoSplit )
Damage = Variance( Damage )
</pre>
----===X3:===''0x5DEA6D''
<pre>
If Attack Properties Damage MP is clear
Damage = Damage / 2
End If</pre>
----===X4:===''0x5DEAF7''
<pre>If Attack Properties Damage MP is clear
Damage = Target's MHP
End If
</pre>
----===X5:===''0x5DEB81''
<pre>
Damage = (Actor's (M)Attack + Actor's Level) * 6 + (Attack's Power * 22)
Damage = Barrier( Damage )
Damage = Variance( Damage )</pre>
----===X6:===''0x5DEBE5''
<pre>Damage = Attack's Power * 20</pre>
----===X7:===''0x5DEC0A''
<pre>
Damage = ( ( 512 - Target's Def ) * Attack's Power / 32 )
Damage = Variance( Damage )
</pre>
----===X8:===''0x5DEC52''
<pre>
If ActionData[0x230] AND 40h
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>
----===XA:===''0x5DECAA''
<pre>Damage = ( Attack's Power + Number of Targets - 1 ) / Number of Targets</pre>
 
==Additional Checks==
===Sadness( Damage ):===''0x5DE958''
<pre>
If Target's Status includes Sadness
End If
Return Damage</pre>
----===SplitDamage( Damage, multiNoSplit ):===''0x5DE8F4''
<pre>
If multiNoSplit == 0
Return Damage
</pre>
----===Barrier( Damage ):===''0x5DE82C''
<pre>
If Attack Property "Physical" is 0
Return Damage
</pre>
----===Variance( Damage ):===''0x5DE988''
<pre>
Damage = Damage ([0..255] + 3841) / 4096 >> 12 //from RNGLUT in KERNEL.BIN//Again, we have another chance for overflow.
If Damage == 0
Return Damage
</pre>
 
==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
 
If Dice_Count < 2 then
Dice_Count = 2
Elseif Dice_Count > 6
Dice_Count = 6
End If
 
total_dice_roll = 0
For ( d_loop = 0; d_loop < Dice_Count; d_loop++ )
die = [0..5]
all_dice[d_loop] = die
total_dice_roll += die + 1
 
set die visualization based on roll
Loop
 
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++ )
 
If all_dice[d_loop] = d_value then
repeat_count++
End If
Loop
 
If repeat_count > value_repeat then
value_repeat = repeat_count
End If
 
Loop
 
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) + (Game Time Minutes)
</pre>
===XC===
''0x5DEF88''
<pre>
Damage = Target's Kill Count * 10
//This is intended to be used only on players
//This will cause a memory leak if done on enemies
</pre>
===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 * 1111
End If
</pre>
 
=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()
 
HitChance = -1;
 
If "Always connect" flag set then HitChance = 255;
 
If 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 = 255
End If
 
If action is flagged as "always hit" then HitChance = 255;
 
Physical Chance = (Actor's Dex >> 2) + action physical hit rate
If Actor is enemy then
Actor's evade = Actor's Physical evade
else
Actor's evade = (Actor's Dex >> 2) + Actor's Physical evade
End If
If Target is enemy then
Target's evade = Target's Physical evade
Else
Target's evade = (Target's Dex >> 2) + Target's Physical evade
End If
 
If 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>
 
====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
 
====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>
 
===1: Magical Accuracy Check===
''0x5DDE5E''
<pre>
acc = Action's Accuracy
tar_save = level / 2; //rounded down
acc_bonus = actor's level - tar_save
rand_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 if
end if
</pre>
 
===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 = ( ( [0..65535] * 99 ) / 65535 ) + 1;
if critical_chance > critical_random then
attack set to critical
end if
end if
end if
</pre>
 
3, 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.
 
===7: Level-based Accuracy===
''0x5DE08A''
<pre>
If Action's Accuracy > 0 then
If the remainder of ( Target's level / Action accuracy ) is non-zero then
Set attack missed
end if
end if
</pre>
So if the accuracy IS 0, then it will always hit. This is to prevent a divide by zero error.
6
edits

Navigation menu