Difference between revisions of "FF7/DamageFormula"

From Final Fantasy Inside
< FF7
Jump to navigation Jump to search
my_wiki>NFITC1
m (Damage Calculations: Woah! Missed that. Makes a big difference.)
my_wiki>NFITC1
(Did I really type that?!!?! Also a little reformatting)
Line 146: Line 146:
  
 
=Damage Calculations=
 
=Damage Calculations=
For standard damage functions
+
These are the damage functions according to an unmodded FF7-ENG 1.02 (1998)
 +
==Standard Formulae==
 +
===X0:===
 +
<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:
 
 
<pre>If Attack Property "Always Critical" is Set
 
<pre>If Attack Property "Always Critical" is Set
 
Set Critical Damage Flag
 
Set Critical Damage Flag
Line 207: Line 207:
 
End If
 
End If
 
Damage = Variance( Damage )</pre>
 
Damage = Variance( Damage )</pre>
----
+
 
X2:
+
===X2:===
 
<pre>
 
<pre>
 
multiNoSplit = ( ( ( Attack's Target Flags AND Ch ) - 4 ) == 0 ? 1 : 0 )
 
multiNoSplit = ( ( ( Attack's Target Flags AND Ch ) - 4 ) == 0 ? 1 : 0 )
Line 218: Line 218:
 
Damage = Variance( Damage )
 
Damage = Variance( Damage )
 
</pre>
 
</pre>
----
+
 
X3:
+
===X3:===
 
<pre>
 
<pre>
 
If Attack Properties Damage MP is clear
 
If Attack Properties Damage MP is clear
Line 232: Line 232:
 
Damage = Damage / 2
 
Damage = Damage / 2
 
End If</pre>
 
End If</pre>
----
+
 
X4:
+
===X4:===
 
<pre>If Attack Properties Damage MP is clear
 
<pre>If Attack Properties Damage MP is clear
 
Damage = Target's MHP
 
Damage = Target's MHP
Line 246: Line 246:
 
End If
 
End If
 
</pre>
 
</pre>
----
+
 
X5:
+
===X5:===
 
<pre>
 
<pre>
 
Damage = (Actor's (M)Attack + Actor's Level) * 6 + (Attack's Power * 22)
 
Damage = (Actor's (M)Attack + Actor's Level) * 6 + (Attack's Power * 22)
Line 253: Line 253:
 
Damage = Barrier( Damage )
 
Damage = Barrier( Damage )
 
Damage = Variance( Damage )</pre>
 
Damage = Variance( Damage )</pre>
----
+
 
X6:
+
===X6:===
 
<pre>Damage = Attack's Power * 20</pre>
 
<pre>Damage = Attack's Power * 20</pre>
----
+
 
X7:
+
===X7:===
 
<pre>
 
<pre>
 
Damage = ( ( 512 - Target's Def ) * Attack's Power / 32 )
 
Damage = ( ( 512 - Target's Def ) * Attack's Power / 32 )
 
Damage = Variance( Damage )
 
Damage = Variance( Damage )
 
</pre>
 
</pre>
----
+
 
X8:
+
===X8:===
 
<pre>
 
<pre>
 
If ActionData[0x230] AND 40h
 
If ActionData[0x230] AND 40h
Line 271: Line 271:
 
End If
 
End If
 
//presumably this checks if the target heals from restore element and will either recover or kill based on the result</pre>
 
//presumably this checks if the target heals from restore element and will either recover or kill based on the result</pre>
----
+
 
X9:
+
===X9:===
 
<pre>
 
<pre>
 
Actor's Attack = Actor's Strength * 2
 
Actor's Attack = Actor's Strength * 2
 
Use Damage X1 with adjusted stat
 
Use Damage X1 with adjusted stat
 
</pre>
 
</pre>
----
+
 
XA:
+
===XA:===
 
<pre>Damage = ( Attack's Power + Number of Targets - 1 ) / Number of Targets</pre>
 
<pre>Damage = ( Attack's Power + Number of Targets - 1 ) / Number of Targets</pre>
  
 
==Additional Checks==
 
==Additional Checks==
Sadness( Damage ):
+
===Sadness( Damage )===
 
<pre>
 
<pre>
 
If Target's Status includes Sadness
 
If Target's Status includes Sadness
Line 288: Line 288:
 
End If
 
End If
 
Return Damage</pre>
 
Return Damage</pre>
----
+
 
SplitDamage( Damage, multiNoSplit ):
+
===SplitDamage( Damage, multiNoSplit )===
 
<pre>
 
<pre>
 
If multiNoSplit == 0
 
If multiNoSplit == 0
Line 308: Line 308:
 
Return Damage
 
Return Damage
 
</pre>
 
</pre>
----
+
 
Barrier( Damage ):
+
===Barrier( Damage )===
 
<pre>
 
<pre>
 
If Attack Property "Physical" is 0
 
If Attack Property "Physical" is 0
Line 330: Line 330:
 
Return Damage
 
Return Damage
 
</pre>
 
</pre>
----
+
 
 
Variance( Damage ):
 
Variance( Damage ):
 
<pre>
 
<pre>
Line 341: Line 341:
 
</pre>
 
</pre>
  
=Secondary Damage Formulae=
+
==Secondary Damage Formulae==
X0:
+
===X0:===
 
<pre>
 
<pre>
 
Damage = Attacker's HP
 
Damage = Attacker's HP
 
</pre>
 
</pre>
X1:
+
===X1:===
 
<pre>
 
<pre>
Damage = Target's MHP - Target's HP
+
Damage = Attacker's MHP - Attacker's HP
 
</pre>
 
</pre>
X8:
+
===X8:===
 
<pre>
 
<pre>
 
Dice_Count = Attacker's Level / 10
 
Dice_Count = Attacker's Level / 10
Line 388: Line 388:
 
Damage = value_repeat * 100 * total_dice_roll
 
Damage = value_repeat * 100 * total_dice_roll
 
</pre>
 
</pre>
X9:
+
===X9===
 
<pre>
 
<pre>
 
Damage = Number of Successful Escapes
 
Damage = Number of Successful Escapes
 
</pre>
 
</pre>
XA:
+
===XA===
 
<pre>
 
<pre>
 
Damage = Target's HP - 1
 
Damage = Target's HP - 1
 
</pre>
 
</pre>
XB:
+
===XB===
 
<pre>
 
<pre>
 
Damage = (Game Time Hours * 100) + (Game Time Minutes)
 
Damage = (Game Time Hours * 100) + (Game Time Minutes)
 
</pre>
 
</pre>
XC:
+
===XC===
 
<pre>
 
<pre>
 
Damage = Target's Kill Count * 10
 
Damage = Target's Kill Count * 10
Line 411: Line 411:
 
The point of these is to set the "attack will miss" flag in the current action memory structure.
 
The point of these is to set the "attack will miss" flag in the current action memory structure.
  
0: Physical Accuracy Check
+
===0: Physical Accuracy Check===
 
<pre>
 
<pre>
 
todo
 
todo
Line 417: Line 417:
 
</pre>
 
</pre>
  
1: Magical Accuracy Check
+
===1: Magical Accuracy Check===
 
<pre>
 
<pre>
 
acc = Action's Accuracy
 
acc = Action's Accuracy
Line 439: Line 439:
 
</pre>
 
</pre>
  
2: Critical Hit Check
+
===2: Critical Hit Check===
 
<pre>
 
<pre>
 
If attack does not miss then
 
If attack does not miss then
Line 459: Line 459:
 
3, 4, and 5 don't exist. Since they don't set miss they will always hit.
 
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)
+
===6: Manipulate Accuracy (intended solely for playable characters)===
 
<pre>
 
<pre>
 
int ally_loop;
 
int ally_loop;
Line 505: Line 505:
 
This doesn't actually place the target in the manipulate status. That happens elsewhere.
 
This doesn't actually place the target in the manipulate status. That happens elsewhere.
  
7: Level-based Accuracy
+
===7: Level-based Accuracy===
 
<pre>
 
<pre>
 
If Action's Accuracy > 0 then
 
If Action's Accuracy > 0 then

Revision as of 16:35, 5 June 2013

Damage Formula's description

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 = damage * (1 + number_of_status1 + 2 * number_of_status2).

number_of_status1 are calculated as sum of attacker statuses darkness, slow, silence, sadness, poison, near death.

number_of_status2 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 in death sentence then damage = damage * 4.


0xA2:

Prepare 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


Damage Calculations

These are the damage functions according to an unmodded FF7-ENG 1.02 (1998)

Standard Formulae

X0:

Sets Target's 02h flag to 1. (Unknown effect)

X1:

If Attack Property "Always Critical" is Set
	Set Critical Damage Flag
End If

x = ( Actor's Level * Actor's (M)Attack ) / 32
y = ( Actor's Level + Actor's (M)Attack ) / 32
z = Actor's (M)Attack + ( x * y )
z = z * ( 512 - target's defense ) * Attack's Power
Damage = z / 4096

If Critical Damage Flag is set
	Damage = Damage * 2
End If

If Actor's Statuses include Berserk
	Damage = Damage * 3 / 2
End If

Long_Range = 0
If Target is in Back Row
	Set Long_Range = 1
End If

If Attack is Short Range OR Command is Enemy Attack
	If Actor is in Back Row
		Long_Range = 1
	End If
Else
	Long_Range = 0
End If

If Long_Range != 0
	Damage = Damage / 2
End If

If Target is Defending
	Damage = Damage / 2
End If

If Target's Back is exposed
	Damage = Damage * ( Target's Back Attack Modifier / 8 )
End If

If Actor's Statuses includes Frog
	Damage = Damage / 4
End If

Damage = Sadness( Damage )
Damage = Split( Damage, 0 )
Damage = Barrier( Damage )
  
If Actor's Statuses include Mini
	Damage = 0
End If
Damage = Variance( Damage )

X2:

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 = Barrier( Damage )
Damage = Variance( Damage )

X3:

If Attack Properties Damage MP is clear
	Damage = Target's HP
Else
	Damage = Target's MP
End If

Damage = Damage * Attack's Power / 32

If ActionData[AC] != 0 (?)
	Damage = Damage / 2
End If

X4:

If Attack Properties Damage MP is clear
	Damage = Target's MHP
Else
	Damage = Target's MMP
End If

Damage = Damage * Attack's Power / 32

If ActionData[AC] != 0 (?)
	Damage = Damage / 2
End If

X5:

Damage = (Actor's (M)Attack + Actor's Level) * 6 + (Attack's Power * 22)
Damage = SplitDamage( Damage )
Damage = Barrier( Damage )
Damage = Variance( Damage )

X6:

Damage = Attack's Power * 20

X7:

Damage = ( ( 512 - Target's Def ) * Attack's Power / 32 )
Damage = Variance( Damage )

X8:

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

X9:

Actor's Attack = Actor's Strength * 2
Use Damage X1 with adjusted stat

XA:

Damage = ( Attack's Power + Number of Targets - 1 ) / Number of Targets

Additional Checks

Sadness( Damage )

If Target's Status includes Sadness
	Damage = Damage - (Damage * 3 / 10)
End If
Return Damage

SplitDamage( Damage, multiNoSplit )

If multiNoSplit == 0
	If No. of Attack's Targets >= 2
		Set Attack's split damage Target Flag
	Else
		Set multiNoSplit == 1
	End If
End If

If ActionData[0xAC] == 0
	Damage = Damage / 2
Else
	If multiNoSplit == 0
		Damage = Damage * 3 / 2
	End If
End If
Return Damage

Barrier( Damage )

If Attack Property "Physical" is 0
	If Target's Statuses include MBarrier
		Set ActionData "MBarrier Active" flag
	End If
Else
	If Target's Statuses include Barrier
		Set ActionData "Barrier Active" flag
	End If
End If

If ActionData "MBarrier Active" or "Barrier Active" flags are set
	Damage = Damage / 2
End If

If attack is Magic and EnabledMagic[7] == 0 (?)
	Damage = Damage + ( Damage * ( EnabledMagic[7] * (10 / 32) ) / 100 )
End If
Return Damage

Variance( Damage ):

Damage = Damage ([0..255] + 3841) / 4096  //from RNGLUT in KERNEL.BIN

If Damage == 0
	Damage == 1
End If
Return Damage

Secondary Damage Formulae

X0:

Damage = Attacker's HP

X1:

Damage = Attacker's MHP - Attacker's HP

X8:

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

X9

Damage = Number of Successful Escapes

XA

Damage = Target's HP - 1

XB

Damage = (Game Time Hours * 100) + (Game Time Minutes)

XC

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


Accuracy Functions

The point of these is to set the "attack will miss" flag in the current action memory structure.

0: Physical Accuracy Check

todo
It's long so I'll tackle it when I have a lot of time on my hands

1: Magical Accuracy Check

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

2: Critical Hit Check

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

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)

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

This doesn't actually place the target in the manipulate status. That happens elsewhere.

7: Level-based Accuracy

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

So if the accuracy IS 0, then it will always hit. This is to prevent a divide by zero error.