| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- FFVII.Battle = {}
- FFVII.Battle.Action = {
- MONSTER_ACTION = 32,
- }
- FFVII.Battle.Row = {
- BACK = 0,
- FRONT = 1,
- }
- FFVII.Battle.Type = {
- ENEMY = 0,
- ALLY = 1,
- LOGIC = 2,
- }
- FFVII.Battle.ActionDefaults = {
- [ FFVII.Battle.Action.MONSTER_ACTION ] = { animation_script = "0" }
- }
- FFVII.Battle.AttackHitChance = {
- PhysicalCritical = 1, -- 0x01 upper 4 bits of formula
- }
- FFVII.Battle.Damage = {
- Physical = 1, -- 0x01 lower 4 bits of formula
- }
- FFVII.Battle.logic_script = {
- unit_type = FFVII.Battle.Type.LOGIC,
- battle_speed = 0,
- game_timer = 0,
- enemy_number = 0,
- ally_number = 0,
- command_queue = {},
- temp_data = {
- attacker = nil, -- 0x00
- -- 0x04 attacker level. We don't this. Instead we use direct data from copied attacker (0x00)
- -- 0x10 attack index. We don't this. Instead we use direct data from copied attack (0x2c)
- target = nil, -- 0x18
- attack = nil, -- 0x2c
- -- 0x40 formula. We don't this. Instead we use direct data from copied attack (0x2c)
- -- 0x48 power modifier. We don't this. Instead we use direct data from copied attack (0x2c)
- base_damage = 0, -- 0x4c
- -- 0xa0 upper formula. We don't this. Instead we use direct data from copied attack (0x2c)
- -- 0xa4 lower formula. We don't this. Instead we use direct data from copied attack (0x2c)
- calculated_defense = 0, -- 0x210
- calculated_damage = 0, -- 0x214
- },
- on_update = function( self )
- local timer = timer:get_game_time_total()
- local delta = timer - self.game_timer
- -- update timers
- for key, value in pairs( EntityContainer ) do
- if value.unit_type ~= FFVII.Battle.Type.LOGIC then
- if value.timer < 65535 then
- value.timer = value.timer + delta * 30 * value.battle_speed
- --print( tostring( key ) .. ".timer " .. tostring( value.timer ) )
- if value.timer > 65535 then
- print( tostring( key ) .. " performs script \"on_action\"" )
- script:request( Script.ENTITY, key, "on_action", 2 )
- end
- end
- end
- end
- self.game_timer = timer
- -- update command queue
- for key_p, value_p in pairs( self.command_queue ) do
- for key_c, value_c in pairs( value_p ) do
- FFVII.Battle.run_command( self, value_c )
- value_c.self.timer = 0
- table.remove( value_p, key_c )
- end
- end
- return 0
- end,
- }
- FFVII.Battle.init = function()
- EntityContainer.BattleLogic = FFVII.Battle.logic_script
- entity_manager:add_entity_script( "BattleLogic" )
- -- load players
- EntityContainer.Cloud = FFVII.Characters.Cloud
- entity_manager:add_entity( "Cloud", "models/ffvii/battle/units/first_ray.mesh", 0, 2, 0, 0 -1)
- -- init timer with start value
- EntityContainer.BattleLogic.game_timer = timer:get_game_time_total()
- -- init battle speed calculated from menu settings
- EntityContainer.BattleLogic.battle_speed = 65536 / ( ( ( FFVII.MenuSettings.battle_speed * 480 / 256 ) + 120 ) * 2 )
- local party_speed = 0
- for key, value in pairs( EntityContainer ) do
- if value.unit_type == FFVII.Battle.Type.ALLY then
- EntityContainer.BattleLogic.ally_number = EntityContainer.BattleLogic.ally_number + 1
- party_speed = party_speed + value.dexterity
- value.speed = value.dexterity + 50
- elseif value.unit_type == FFVII.Battle.Type.ENEMY then
- EntityContainer.BattleLogic.enemy_number = EntityContainer.BattleLogic.enemy_number + 1
- end
- end
- print( "ally_number = " .. tostring( EntityContainer.BattleLogic.ally_number ) )
- print( "enemy_number = " .. tostring( EntityContainer.BattleLogic.enemy_number ) )
- if EntityContainer.BattleLogic.ally_number > 0 then
- party_speed = ( party_speed - 1 + EntityContainer.BattleLogic.ally_number ) / EntityContainer.BattleLogic.ally_number + 50;
- for key, value in pairs( EntityContainer ) do
- if value.unit_type ~= FFVII.Battle.Type.LOGIC then
- value.battle_speed = EntityContainer.BattleLogic.battle_speed * value.speed / party_speed
- value.battle_speed = value.battle_speed * 2 -- normal speed (initial value calculated for slow)
- end
- end
- end
- end
- FFVII.Battle.run_command = function( self, command )
- print( "Command: attack = \"" .. command.attack.name .. "\", target = \"" .. tostring( command.target[ 1 ] ) .. "\"" )
- -- todo a lot of preparation
- EntityContainer.BattleLogic.temp_data.attacker = command.self
- EntityContainer.BattleLogic.temp_data.attack = command.attack
- EntityContainer.BattleLogic.temp_data.target = command.target
- -- todo a lot of preparation
- if command.action == FFVII.Battle.Action.MONSTER_ACTION then
- -- todo action_type_07
- -- todo action_type_0C
- FFVII.Battle.calculate_and_apply_damage() -- action_type_09
- end
- end
- -- action_type_09
- FFVII.Battle.calculate_and_apply_damage = function()
- -- todo mp check
- -- todo a lot of fuctions
- FFVII.Battle.set_base_damage()
- -- todo a lot of fuctions
- -- attack every unit in target
- for key, value in pairs( EntityContainer.BattleLogic.temp_data.target ) do
- FFVII.Battle.main_damage_calculation( value )
- end
- -- todo a lot of functions
- end
- FFVII.Battle.set_base_damage = function()
- -- todo force physical attack settings in physical formula
- -- todo use special settings for special attacks
- -- todo use another base damage for magic attack
- EntityContainer.BattleLogic.temp_data.base_damage = EntityContainer.BattleLogic.temp_data.attacker.physical_power
- -- todo apply damage modifier
- end
- FFVII.Battle.main_damage_calculation = function( target )
- -- todo a lot of fuctions
- FFVII.Battle.calculate_target_stats( target )
- -- todo a lot of fuctions
- FFVII.Battle.damage_formula_run()
- -- todo a lot of fuctions
- end
- FFVII.Battle.calculate_target_stats = function( target )
- -- todo a lot of initialization
- -- todo a lot of initialization
- -- todo defense check and modification
- EntityContainer.BattleLogic.temp_data.calculated_defense = target.physical_defense
- -- todo a lot of initialization
- if EntityContainer.BattleLogic.temp_data.calculated_defense > 512 then
- EntityContainer.BattleLogic.temp_data.calculated_defense = 512
- end
- -- todo sadness check
- end
- FFVII.Battle.damage_formula_run = function()
- -- run high formula
- if EntityContainer.BattleLogic.temp_data.attack.hit_chance_formula == FFVII.Battle.AttackHitChance.PhysicalCritical then
- FFVII.Battle.HighFormula.Physical()
- FFVII.Battle.HighFormula.Critical()
- end
- -- run low formula
- if EntityContainer.BattleLogic.temp_data.attack.power_modifier ~= 0 then
- -- todo add additional conditions for special attacks (A0 = 0;funca8e84;)
- if EntityContainer.BattleLogic.temp_data.attack.damage_formula == FFVII.Battle.Damage.Physical then
- FFVII.Battle.LowFormula.Physical()
- end
- -- todo add additional conditions for special attacks (A0 = 1;funca8e84;)
- end
- end
- FFVII.Battle.HighFormula = {}
- FFVII.Battle.HighFormula.Physical = function()
- -- todo add physical hit
- end
- FFVII.Battle.HighFormula.Critical = function()
- -- todo add critical hit
- end
- FFVII.Battle.LowFormula = {}
- FFVII.Battle.LowFormula.Physical = function()
- local damage = EntityContainer.BattleLogic.temp_data.base_damage
- -- calculate base damage
- damage = damage + ( ( EntityContainer.BattleLogic.temp_data.attacker.level + damage ) / 32 ) * ( ( EntityContainer.BattleLogic.temp_data.attacker.level * damage ) / 32 )
- -- apply attack data power
- damage = damage * EntityContainer.BattleLogic.temp_data.attack.power
- -- apply defense
- damage = damage * ( 512 - EntityContainer.BattleLogic.temp_data.calculated_defense ) / 512
- -- todo add always critical check
- -- todo critical damage
- -- todo berserk modificator
- -- todo back row modificator
- -- todo target defend
- -- todo attack from back
- -- todo a lot of status modifiers
- damage = FFVII.Battle.add_random_modifier_and_zero_check( damage )
- EntityContainer.BattleLogic.temp_data.calculated_damage = damage
- print( "Command: damage = \"" .. damage .. "\"." )
- end
- FFVII.Battle.add_random_modifier_and_zero_check = function( damage )
- local random_damage = damage * ( 15 + math.random() ) / 16;
- if random_damage == 0 then
- random_damage = 1
- end
- return random_damage
- end
|