[XP] Phoenix Engine ~ Alternate Attack Calculations
Version: 1.0
Author: PhoenixFire ~ Script parts used from Xelias
Date: March 15, 2014
Version History
- Version 1.0.0: March 15, 2014 - Initial Release
- Version 1.0.1: March 29, 2014 - Fixed a code problem that caused a syntax error
Description
So part 1 of many.. I went ahead and re-wrote Game_Battler_3 with an included re-write of the Alternate Attack Algorithms originally made by Xelias. Note: You ABSOLUTELY MUST configure the script if you use it. The configuration bit is located at the top of the re-written script, along with an explanation of what each alternate algorithm does. This SHOULD be compatible with EVERYTHING, since it doesn't overwrite anything, but rather completely replaces the atk values that would be overwritten by other scripts..
Features
- Re-write of the Game_Battler_3 standard script, changing the attack calculations.
- Provides several alternate attack algorithms, which can be assigned to several weapons.
- Fully configurable script re-write (you can always use the regular attack methods as well)
ScreenshotsN/A - I wouldn't know how to screenshot this anyways..
InstructionsTo install, simply copy and paste over the default Game_Battler_3 script. IF YOU THINK YOU MAY WANT TO SWITCH BACK~ Always make a backup of scripts before major changes, but, even if you don't, you can "create a new project" and simply copy the default script from the new project, and paste it over the modified one. You absolutely MUST configure the script for it to work properly. Config instructions are within the script, above the configuration variables, at the top of the script.
Script
[spoiler]
#==============================================================================
# ** Game_Battler (part 3)
#------------------------------------------------------------------------------
# This class deals with battlers. It's used as a superclass for the Game_Actor
# and Game_Enemy classes.
#==============================================================================
class Game_Battler
##:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# ALTERNATE ATTACK ALGORITHMS CONFIGURATION
#
##:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# How to use this script :
#
# This allows your weapons to follow different damage algorithms. If your weapon
# uses a normal attack algorithm, you MUST place its ID in the
# NORMAL_WEAPONS_IDS, or else it wouldn't be good for your game. Also place all
# weapons ID except SP damaging and absorbing ones, into the
# "ALL_WEAPONS_IDS", because if you don't, a nasty bug will prevent you from
# dealing damage with normal attack.
#
# ATMA_WEAPON_IDS = [X,X...] : A weapon with an ID equal to X will inflict
# more damage depending on the user's HP. If HP are full, attack power is doubled.
# If HP are at minimum, attack power is normal. If HP are equal to half, attack
# power is equal to 1.5 of the normal Attack power, and so on...
#
# VALIANT_IDS = [X, X...] : The opposite effect of Atma Weapon.
# If HP are at minimum, attack power is doubled, and so on...
#
# WHITE_MOON_IDS = [X, X...] : Follows the same formula than Atma Weapon
# but works with SP
#
# CONFORMER_IDS = [X, X...] : Deals damage based on user's Level.
#
# INTEL_WEAPON_IDS = [X, X...] : Inflicts damage based on user's Intelligence
# instead of Strength
#
# NINJA_IDS = [X, X...] : Inflicts damage based on user's Agility
# instead of Strength
#
# MIND_BLASTER_IDS = [X, X...] : Damage is inflicted to SP. Damage
# relies also on the opponent's Magic Defense and your Intelligence
#
# BLOOD_SWORD_IDS = [X, X...] & PERCENT_DRAINED = X :
# some damage is absorbed from the attack. How many? PERCENT_DRAINED %
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
OTHER_WEAPONS_IDS = [0]
ALL_WEAPONS_IDS = []
ATMA_WEAPON_IDS = []
VALIANT_IDS = []
WHITE_MOON_IDS = []
CONFORMER_IDS = []
INTEL_WEAPON_IDS = []
NINJA_IDS = []
MIND_BLASTER_IDS = []
BLOOD_SWORD_IDS = []
PERCENT_DRAINED = 50
#--------------------------------------------------------------------------
# * Determine Usable Skills
# skill_id : skill ID
#--------------------------------------------------------------------------
def skill_can_use?(skill_id)
# If there's not enough SP, the skill cannot be used.
if $data_skills[skill_id].sp_cost > self.sp
return false
end
# Unusable if incapacitated
if dead?
return false
end
# If silent, only physical skills can be used
if $data_skills[skill_id].atk_f == 0 and self.restriction == 1
return false
end
# Get usable time
occasion = $data_skills[skill_id].occasion
# If in battle
if $game_temp.in_battle
# Usable with [Normal] and [Only Battle]
return (occasion == 0 or occasion == 1)
# If not in battle
else
# Usable with [Normal] and [Only Menu]
return (occasion == 0 or occasion == 2)
end
end
#--------------------------------------------------------------------------
# * Applying Normal Attack Effects
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
# Alternative Attack Algorithms
# Authors: Xelias and PhoenixFire
# Version: 1.00
# Type: Battle Add-ON
# Date v1.00: 7.11.2009
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
#
# This work is protected by the following license:
# #----------------------------------------------------------------------------
# #
# # Creative Commons - Attribution-NonCommercial-ShareAlike 3.0 Unported
# # ( http://creativecommons.org/licenses/by-nc-sa/3.0/ )
# #
# # You are free:
# #
# # to Share - to copy, distribute and transmit the work
# # to Remix - to adapt the work
# #
# # Under the following conditions:
# #
# # Attribution. You must attribute the work in the manner specified by the
# # author or licensor (but not in any way that suggests that they endorse you
# # or your use of the work).
# #
# # Noncommercial. You may not use this work for commercial purposes.
# #
# # Share alike. If you alter, transform, or build upon this work, you may
# # distribute the resulting work only under the same or similar license to
# # this one.
# #
# # - For any reuse or distribution, you must make clear to others the license
# # terms of this work. The best way to do this is with a link to this web
# # page.
# #
# # - Any of the above conditions can be waived if you get permission from the
# # copyright holder.
# #
# # - Nothing in this license impairs or restricts the author's moral rights.
# #
# #----------------------------------------------------------------------------
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
def attack_effect(attacker)
# Clear critical flag
self.critical = false
# First hit detection
hit_result = (rand(100) < attacker.hit)
# If hit occurs
if hit_result == true
# Calculate basic damage
if attacker.is_a?(Game_Actor)
if OTHER_WEAPONS_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.str) / 20
end
if ATMA_WEAPON_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2,0].max
atk2 = atk * (20 + attacker.str) / 20
self.damage = atk2 + ((atk2*((attacker.hp*100)/attacker.maxhp))/100)
end
if VALIANT_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2,0].max
atk2 = atk * (20 + attacker.str) / 20
minushp = attacker.maxhp - attacker.hp
self.damage = atk2 + ((atk2*((minushp*100)/attacker.maxhp))/100)
end
if WHITE_MOON_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2,0].max
atk2 = atk * (20 + attacker.str) / 20
self.damage = atk2 + ((atk2*((attacker.sp*100)/attacker.maxsp))/100)
end
if CONFORMER_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2,0].max
atk2 = atk * (20 + attacker.str) / 20
self.damage = atk2 + (atk2*(((attacker.level*100) / 99)/100))
end
if INTEL_WEAPON_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.int) / 20
end
if NINJA_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.agi) / 20
end
if BLOOD_SWORD_IDS.include?(attacker.weapon_id)
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.str) / 20
end
end
if attacker.is_a?(Game_Enemy)
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.str) / 20
end
# Element correction
self.damage *= elements_correct(attacker.element_set)
self.damage /= 100
# If damage value is strictly positive
if self.damage > 0
# Critical correction
if attacker.is_a?(Game_Actor)
if GENJI_WEAPON_IDS.include?(attacker.weapon_id)
if rand(100) < 8 * attacker.dex / self.agi
self.damage *= 2
self.critical = true
end
end
if KIKU_ICHIMONJI_IDS.include?(attacker.weapon_id)
if rand(100) < 4 * attacker.dex / self.agi
self.damage *= 4
self.critical = true
end
end
elsif rand(100) < 4 * attacker.dex / self.agi
self.damage *= 2
self.critical = true
end
# Guard correction
if self.guarding?
if GUARD_BREAKER_IDS.include?(attacker.weapon_id)
self.damage /=1
end
else
self.damage /=2
end
# Dispersion
if self.damage.abs > 0
amp = [self.damage.abs * 15 / 100, 1].max
self.damage += rand(amp+1) + rand(amp+1) - amp
end
# Second hit detection
eva = 8 * self.agi / attacker.dex + self.eva
hit = self.damage < 0 ? 100 : 100 - eva
hit = self.cant_evade? ? 100 : hit
hit_result = (rand(100) < hit)
end
# If hit occurs
if hit_result == true
# State Removed by Shock
remove_states_shock
# Substract damage from HP
if attacker.is_a?(Game_Actor)
if MIND_BLASTER_IDS.include?(attacker.weapon_id)
self.sp -= self.damage
self.damage = sprintf('%+d %s', -self.damage, $data_system.words.sp)
end
if BLOOD_SWORD_IDS.include?(attacker.weapon_id)
healing = (self.damage*PERCENT_DRAINED)/100
self.hp -= self.damage
attacker.hp += healing
end
if ALL_WEAPONS_IDS.include?(attacker.weapon_id)
self.hp -= self.damage
end
else self.hp -= self.damage
end
end
# State change
@state_changed = false
states_plus(attacker.plus_state_set)
states_minus(attacker.minus_state_set)
# When missing
else
# Set damage to "Miss"
self.damage = "Miss"
# Clear critical flag
self.critical = false
end
# End Method
return true
end
end
#--------------------------------------------------------------------------
# * Apply Skill Effects
# user : the one using skills (battler)
# skill : skill
#--------------------------------------------------------------------------
def skill_effect(user, skill)
# Clear critical flag
self.critical = false
# If skill scope is for ally with 1 or more HP, and your own HP = 0,
# or skill scope is for ally with 0, and your own HP = 1 or more
if ((skill.scope == 3 or skill.scope == 4) and self.hp == 0) or
((skill.scope == 5 or skill.scope == 6) and self.hp >= 1)
# End Method
return false
end
# Clear effective flag
effective = false
# Set effective flag if common ID is effective
effective |= skill.common_event_id > 0
# First hit detection
hit = skill.hit
if skill.atk_f > 0
hit *= user.hit / 100
end
hit_result = (rand(100) < hit)
# Set effective flag if skill is uncertain
effective |= hit < 100
# If hit occurs
if hit_result == true
# Calculate power
power = skill.power + user.atk * skill.atk_f / 100
if power > 0
power -= self.pdef * skill.pdef_f / 200
power -= self.mdef * skill.mdef_f / 200
power = [power, 0].max
end
# Calculate rate
rate = 20
rate += (user.str * skill.str_f / 100)
rate += (user.dex * skill.dex_f / 100)
rate += (user.agi * skill.agi_f / 100)
rate += (user.int * skill.int_f / 100)
# Calculate basic damage
self.damage = power * rate / 20
# Element correction
self.damage *= elements_correct(skill.element_set)
self.damage /= 100
# If damage value is strictly positive
if self.damage > 0
# Guard correction
if self.guarding?
self.damage /= 2
end
end
# Dispersion
if skill.variance > 0 and self.damage.abs > 0
amp = [self.damage.abs * skill.variance / 100, 1].max
self.damage += rand(amp+1) + rand(amp+1) - amp
end
# Second hit detection
eva = 8 * self.agi / user.dex + self.eva
hit = self.damage < 0 ? 100 : 100 - eva * skill.eva_f / 100
hit = self.cant_evade? ? 100 : hit
hit_result = (rand(100) < hit)
# Set effective flag if skill is uncertain
effective |= hit < 100
end
# If hit occurs
if hit_result == true
# If physical attack has power other than 0
if skill.power != 0 and skill.atk_f > 0
# State Removed by Shock
remove_states_shock
# Set to effective flag
effective = true
end
# Substract damage from HP
last_hp = self.hp
self.hp -= self.damage
effective |= self.hp != last_hp
# State change
@state_changed = false
effective |= states_plus(skill.plus_state_set)
effective |= states_minus(skill.minus_state_set)
# If power is 0
if skill.power == 0
# Set damage to an empty string
self.damage = ""
# If state is unchanged
unless @state_changed
# Set damage to "Miss"
self.damage = "Miss"
end
end
# If miss occurs
else
# Set damage to "Miss"
self.damage = "Miss"
end
# If not in battle
unless $game_temp.in_battle
# Set damage to nil
self.damage = nil
end
# End Method
return effective
end
#--------------------------------------------------------------------------
# * Application of Item Effects
# item : item
#--------------------------------------------------------------------------
def item_effect(item)
# Clear critical flag
self.critical = false
# If item scope is for ally with 1 or more HP, and your own HP = 0,
# or item scope is for ally with 0 HP, and your own HP = 1 or more
if ((item.scope == 3 or item.scope == 4) and self.hp == 0) or
((item.scope == 5 or item.scope == 6) and self.hp >= 1)
# End Method
return false
end
# Clear effective flag
effective = false
# Set effective flag if common ID is effective
effective |= item.common_event_id > 0
# Determine hit
hit_result = (rand(100) < item.hit)
# Set effective flag is skill is uncertain
effective |= item.hit < 100
# If hit occurs
if hit_result == true
# Calculate amount of recovery
recover_hp = maxhp * item.recover_hp_rate / 100 + item.recover_hp
recover_sp = maxsp * item.recover_sp_rate / 100 + item.recover_sp
if recover_hp < 0
recover_hp += self.pdef * item.pdef_f / 20
recover_hp += self.mdef * item.mdef_f / 20
recover_hp = [recover_hp, 0].min
end
# Element correction
recover_hp *= elements_correct(item.element_set)
recover_hp /= 100
recover_sp *= elements_correct(item.element_set)
recover_sp /= 100
# Dispersion
if item.variance > 0 and recover_hp.abs > 0
amp = [recover_hp.abs * item.variance / 100, 1].max
recover_hp += rand(amp+1) + rand(amp+1) - amp
end
if item.variance > 0 and recover_sp.abs > 0
amp = [recover_sp.abs * item.variance / 100, 1].max
recover_sp += rand(amp+1) + rand(amp+1) - amp
end
# If recovery code is negative
if recover_hp < 0
# Guard correction
if self.guarding?
recover_hp /= 2
end
end
# Set damage value and reverse HP recovery amount
self.damage = -recover_hp
# HP and SP recovery
last_hp = self.hp
last_sp = self.sp
self.hp += recover_hp
self.sp += recover_sp
effective |= self.hp != last_hp
effective |= self.sp != last_sp
# State change
@state_changed = false
effective |= states_plus(item.plus_state_set)
effective |= states_minus(item.minus_state_set)
# If parameter value increase is effective
if item.parameter_type > 0 and item.parameter_points != 0
# Branch by parameter
case item.parameter_type
when 1 # Max HP
@maxhp_plus += item.parameter_points
when 2 # Max SP
@maxsp_plus += item.parameter_points
when 3 # Strength
@str_plus += item.parameter_points
when 4 # Dexterity
@dex_plus += item.parameter_points
when 5 # Agility
@agi_plus += item.parameter_points
when 6 # Intelligence
@int_plus += item.parameter_points
end
# Set to effective flag
effective = true
end
# If HP recovery rate and recovery amount are 0
if item.recover_hp_rate == 0 and item.recover_hp == 0
# Set damage to empty string
self.damage = ""
# If SP recovery rate / recovery amount are 0, and parameter increase
# value is ineffective.
if item.recover_sp_rate == 0 and item.recover_sp == 0 and
(item.parameter_type == 0 or item.parameter_points == 0)
# If state is unchanged
unless @state_changed
# Set damage to "Miss"
self.damage = "Miss"
end
end
end
# If miss occurs
else
# Set damage to "Miss"
self.damage = "Miss"
end
# If not in battle
unless $game_temp.in_battle
# Set damage to nil
self.damage = nil
end
# End Method
return effective
end
#--------------------------------------------------------------------------
# * Application of Slip Damage Effects
#--------------------------------------------------------------------------
def slip_damage_effect
# Set damage
self.damage = self.maxhp / 10
# Dispersion
if self.damage.abs > 0
amp = [self.damage.abs * 15 / 100, 1].max
self.damage += rand(amp+1) + rand(amp+1) - amp
end
# Subtract damage from HP
self.hp -= self.damage
# End Method
return true
end
#--------------------------------------------------------------------------
# * Calculating Element Correction
# element_set : element
#--------------------------------------------------------------------------
def elements_correct(element_set)
# If not an element
if element_set == []
# Return 100
return 100
end
# Return the weakest object among the elements given
# * "element_rate" method is defined by Game_Actor and Game_Enemy classes,
# which inherit from this class.
weakest = -100
for i in element_set
weakest = [weakest, self.element_rate(i)].max
end
return weakest
end
[/spoiler]
Credit
- PhoenixFire ~ The re-write and editing.
- Xelias ~ The original Alternate Algorithms script. Parts of it were used in this re-write.
Support
If you discover any bugs with this script, please send me a PM, or post on this thread. I do not forsee any issues of this script, but I would always like to know if something does come up.
Known Compatibility IssuesDoes not work with rpgmaker XP version 1.05 ~ Causes the following error:
NoMethodError
Undefined method "*" for nil:NilClass
Unfortunately, I have no idea how to fix this at the moment, but if I find a solution, I will certainly fix it.
Demo
N/A
Author's Notes
Enjoy the script! Really, I'm trying to better my scripting abilities, and this is just a simple start. I know that it's not much of an edit, but in time, I plan to re-write most, if not all, of the default scripts to have added functionality.
RestrictionsNone - You may use this in your game, whether commercial or non-commercial, as long as proper credit is given.
Script and post updated. Fixed a syntax error.