adiktuzmiko icon

Element EX v1.06

adiktuzmiko | PRO | 05/31/13 05:58:36 PM UTC | 0 ⭐ | 1669 👁️ | Never ⏰ | []
Ruby |

26.05 KB

|

None

|

0 👍

/

0 👎

#==============================================================================
# 
# Element EX v1.06
# by AdiktuzMiko
# --- Date Created: 06/01/2013
# --- Last Date Updated: 09/20/2014
# --- Level: Easy
#
# Basically it allows you to give elemental damage bonuses/penalty and 
# protection/weakness tags to objects. Also allows you to assign multiple
# elements to an object.
#
# You can now also show a scene that shows the elemental bonuses of each actor
#
# Added two new methods for those who want to have more control over damage
#
# adik_modify_damage(user,item,damage)
# -> If you want to further modify the damage
# -> Should return the new damage value
# -> Processed after all the default + Elements EX modifications are done
# adik_damage_extension(user,item,damage)
# -> If you want to do something else during damage calculations
# -> Processed after modify damage
#
# Example: A fire ring should increase the damage of all fire element 
#          attacks/skills of it's wearer.
#          An anti-fire ring should reduce the damage the user takes from
#          fire element attacks/skills. But it can/will also increase the damage
#          taken by the user from water element attacks/skills.
#
#          A sword that is both of the fire and ice elements. 
#
# Note: Once you import this system, you need to use the given tags
#       in order to assign elements and elemental resistances to objects
#       because this system bypasses the elements and elemental resistances
#       that are set using traits.
#          
#==============================================================================
#   ++ Notetags ++
#==============================================================================
#
# These tags goes into Actors, Classes, Skills, Weapons, Armors, Enemies
# and States
# 
# The following tags are for percent bonuses:
#
# <atk ele x:y> = Gives bonus elemental damage to the object
#  Positive: Damage done increases
#  Negative: Damage done decreases
# <def ele x:y> = Gives bonus elemental defense to the object
#  Positive: Damage taken decreases
#  Negative: Damage taken increases
#
# x => element id
# y => bonus amount (can be +/-, real numbers)
# 1.0 = 100% bonus damage/defense
#
# The bonus values add up for all object tags working on the actor
#
# Example: If actor1 has a <def ele 1:0.2> tag
#             actor1's class has a <def ele 1:0.2> tag
#             actor1's armor has a <def ele 1:0.6> tag
#          Then the actor will have a total reduction of 1.0, which is
#             100% damage reduction for element 1.
#
# The following tags are for direct bonuses: 
#
# <atk b ele x:y> = Gives bonus elemental damage to the object
#  Positive: Damage done increases
#  Negative: Damage done decreases
# <def b ele x:y> = Gives bonus elemental defense to the object
#  Positive: Damage taken decreases
#  Negative: Damage taken increases
#
# x => element id
# y => bonus amount (can be +/-, real numbers)
# 1.0 = 1 bonus damage/defense
#
# The bonus values add up for all object tags working on the actor
#
# Example: If actor1 has a <def ele b 1:0.2> tag
#             actor1's class has a <def ele b 1:0.2> tag
#             actor1's armor has a <def ele b 1:0.6> tag
#          Then the actor will have a total reduction of 1.0, which is
#             1 damage reduction for element 1.
#
# The following tags are for applying elements to objects:
#
# <obj ele x>
#
# x => element id
#
# use 0 for skills that you want to use the character's attack elements
#
# To set the distribution percent of each element defined, use
#
# <obj eler x:y>
#
# y => rate (1.0 = 100%, 0.5 = 50%, 2.0 = 200%)
#
# If this tag is not used, all elements defined by <obj ele x> will be set at 1.0 rate
#
#==============================================================================
#   ++ Script Calls ++
#==============================================================================
#
# To open up the ElementsEX scene:
#
# SceneManager.call(Scene_ElementsEX)
#
# Note: Doing this call from some scenes might cause problems
#       i.e. when called from a battle scene
#
# If you want to add it into the main menu or equip menu
# just add a command which uses the command handler:
#
# command_elementex
#
# ex: If you have Yanfly's Menu Engine or Equip Engine, just add 
# this to the custom commands list
#
# :elementex => [ "ElementEx",            0,        0, :command_elementex]
#
# then add :elementex to the menu commands list
# 
#==============================================================================
#   ++ Installation ++
#==============================================================================
# Install this script in the Materials section in your project's
# script editor and start tagging.
#
# There are also some configurables on the upper part of the script.
#
#==============================================================================
#   ++ Compatibility ++
#==============================================================================
# This script aliases the following default VXA methods:
#
#     DataManager: Load_Database
#     Game_Battler: item_element_rate
#    
# Overwrites:
#  
#     Game_Battler: make_damage_value
#     Yanfly Element PopUp: element_popup_tag? -> for compatibility fix
#
# Notes: For the attack tags + Yanfly's Battle Engine
#
# Damages that deal bonuses due to positive attack tags will be considered
# as weakpoint elements if you're using Yanfly's battle engine and the 
# resulting damage rate is greater than 1.0 (100%).
# 
# Also, if damages deal weakened damage due negative to attack tags, it will be
# considered as resisted damaged if you're using Yanfly's battle engine and the 
# resulting damage rate is lower than 1.0 (100%).
#
#==============================================================================
#   ++ Terms and Conditions ++
#==============================================================================
#
# Read this: http://lescripts.wordpress.com/terms-and-conditions/
#
#==============================================================================
 
$imported ||= {}
$imported["ElementEX"] = true
 
module Adiktuz
  module ElementEX
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # ? Script Settings
    #-------------------------------------------------------------------------- 
    # This is where you adjust the settings for the script 
    #-------------------------------------------------------------------------- 
  
    #-------------------------------------------------------------------------- 
    # Determines how do you detect damage element for use with Yanfly's
    # Element Pop Up script: 
    #(basically, how to determine the color of the pop-up)
    #
    # 0 = highest percent bonus, 1 = highest direct bonus
    #
    #-------------------------------------------------------------------------- 
    ELEMENT_DETECTION = 0
    
    #-------------------------------------------------------------------------- 
    # X offset per letter of actor name on the elements window
    # used for adjusting the name position on the window
    #-------------------------------------------------------------------------- 
    X_PER_LETTER = 5
    
    #-------------------------------------------------------------------------- 
    # Font size of the elements window
    #-------------------------------------------------------------------------- 
    FONT_SIZE = 16
    
    #-------------------------------------------------------------------------- 
    # Input here all of the element ids that your game uses.
    #-------------------------------------------------------------------------- 
    ELEMENTS = [0,1,3,4,7,8,9,10,11,12,13,14,18]
    # do not remove the 0
    
    #-------------------------------------------------------------------------- 
    # Input here the icons that each element ids should use
    #-------------------------------------------------------------------------- 
    ELEMENTS_ICONS = {
    1 => 116, # Physical
    3 => 130, # Pierce
    4 => 135, # Blunt
    7 => 131, # Cut
    8 =>  96, # Fire
    9 =>  99, # Water
   10 => 101, # Wind
   11 => 100, # Earth
   12 => 103, # Dark
   13 => 102, # Holy
   14 =>  98, # Electric
   18 => 119, # Ether
   # Add more element definitions here.
   
  } # <- Do not delete.
    #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    # ? Notetag Settings
    #-------------------------------------------------------------------------- 
    # This is where you adjust the settings for the notetags used in all 
    # notetaggable items. 
    #-------------------------------------------------------------------------- 
    SKILL_ELE = /<obj ele (.*)>/i
    SKILL_ELER = /<obj eler (.*):(.*)>/i
    ATK_ELE = /<atk ele (.*):(.*)>/i
    DEF_ELE = /<def ele (.*):(.*)>/i
    ATK_B_ELE = /<atk b ele (.*):(.*)>/i
    DEF_B_ELE = /<def b ele (.*):(.*)>/i
  end #module ElementEX
end #module Adiktuz
 
#===============================================================================
module DataManager
#===============================================================================
 
  #---------------------------------------------------------------------------
  # alias: load_database
  #---------------------------------------------------------------------------
  class << self; alias :load_unique_element_base :load_database; end
  def self.load_database
    load_unique_element_base
    load_unique_element
  end
  #--------------------------------------------------------------------------
  # new method: load_elemental_control
  #--------------------------------------------------------------------------
  def self.load_unique_element
    classes = [$data_weapons, $data_armors, $data_skills , $data_items,
               $data_actors , $data_classes, $data_enemies, $data_states ]
    for classe in classes
      for obj in classe
        next if obj.nil?
        obj.load_elemental_control
      end
    end
  end
  
end # DataManager
 
#===============================================================================
class RPG::BaseItem
#===============================================================================
 
  #---------------------------------------------------------------------------
  # public instance Variables
  #---------------------------------------------------------------------------
  attr_accessor :atk_ele
  attr_accessor :def_ele
  attr_accessor :atk_b_ele
  attr_accessor :def_b_ele
  attr_accessor :skill_ele
  attr_accessor :skill_eler
  
  #--------------------------------------------------------------------------
  # new method: load_elemental_control
  #--------------------------------------------------------------------------
  def load_elemental_control
    @atk_ele     = [0] * $data_system.elements.size
    @def_ele     = [0] * $data_system.elements.size
    @atk_b_ele     = [0] * $data_system.elements.size
    @def_b_ele     = [0] * $data_system.elements.size
    @skill_ele     = [0] * $data_system.elements.size
    @skill_eler    = [1] * $data_system.elements.size
    set_elemental_bonus
  end
  #--------------------------------------------------------------------------
  # common cache : load_notetags_critex
  #--------------------------------------------------------------------------
  def set_elemental_bonus
    self.note.split(/[\r\n]+/).each do |line|
      case line
      when Adiktuz::ElementEX::ATK_ELE then @atk_ele[$1.to_i] = $2.to_f 
      when Adiktuz::ElementEX::DEF_ELE then @def_ele[$1.to_i] = $2.to_f 
      when Adiktuz::ElementEX::ATK_B_ELE then @atk_b_ele[$1.to_i] = $2.to_f 
      when Adiktuz::ElementEX::DEF_B_ELE then @def_b_ele[$1.to_i] = $2.to_f 
      when Adiktuz::ElementEX::SKILL_ELE then @skill_ele[$1.to_i] = 1
      when Adiktuz::ElementEX::SKILL_ELER then @skill_eler[$1.to_i] = $2.to_f
      end
    end
  end
  
end # << RPG::BaseItem
 
class Game_Battler < Game_BattlerBase
  
  #--------------------------------------------------------------------------
  # new method: get_elements
  #--------------------------------------------------------------------------
  def get_elements(item)
    elements = []
    for id in Adiktuz::ElementEX::ELEMENTS
      elements.push(id) if item.skill_ele[id] == 1
    end  
    elements
  end   
  
  #--------------------------------------------------------------------------
  # new method: count_elements
  #--------------------------------------------------------------------------
  def count_elements(item)
    elements = get_elements(item)
    elements.size
  end
 
  #--------------------------------------------------------------------------
  # new method: get_battler_elements
  #--------------------------------------------------------------------------
  def get_battler_elements(user)
    elements = []
    if user.actor?
      for id in Adiktuz::ElementEX::ELEMENTS
        elements.push(id) if user.actor.skill_ele[id] == 1 && !elements.include?(id)
        elements.push(id) if user.class.skill_ele[id] == 1 && !elements.include?(id)
        for equip in user.equips
          next if equip.nil?
          elements.push(id) if equip.skill_ele[id] == 1 && !elements.include?(id)
        end
        for state in user.states
          next if state.nil?
          elements.push(id) if state.skill_ele[id] == 1 && !elements.include?(id)
        end
      end  
    elsif user.enemy?
      for id in Adiktuz::ElementEX::ELEMENTS
        elements.push(id) if user.enemy.skill_ele[id] == 1 && !elements.include?(id)
      end 
      for state in user.states
          next if state.nil?
          elements.push(id) if state.skill_ele[id] == 1 && !elements.include?(id)
        end
    end
    elements
  end   
 
  #--------------------------------------------------------------------------
  # Alias method: item_element_rate
  #--------------------------------------------------------------------------
  alias adik_item_element_rate item_element_rate
  def item_element_rate(user, item)
    rate =  1.0
    item_elements_ex = get_elements(item)
    if item_elements_ex.empty?
      item_elements_ex = get_battler_elements(user)
      rate = elements_ex_max_rate(user,item_elements_ex,item) unless item_elements_ex.empty? 
    else
      item_elements_ex.each do |id|
        rate += (get_atk_element_multi(user,id) - get_def_element_multi(id))*item.skill_eler[id]
      end
    end
    rate
  end
  
  #--------------------------------------------------------------------------
  # new method: elements_ex_bonus
  #--------------------------------------------------------------------------
  def elements_ex_bonus(user,elements)
    bonus = 0
    elements.each do |elem|
      bonus += get_atk_element_bonus(user,elem) - get_def_element_bonus(elem)
    end
    bonus
  end
 
  #--------------------------------------------------------------------------
  # new method: elements_ex_max_rate
  #--------------------------------------------------------------------------
  def elements_ex_max_rate(user,elements,item)
    rate = 1.0
    elements.each do |elem|
      rate += (get_atk_element_multi(user,elem) - get_def_element_multi(elem))*item.skill_eler[elem]
    end
    rate
  end
  
  #--------------------------------------------------------------------------
  # new method: elements_max_rate2
  #--------------------------------------------------------------------------
  def elements_max_rate2(user,elements)
    elements.inject([0.0]) {|r, i| r.push((get_atk_element_multi(user,i)) -( get_def_element_multi(i))) }.max
  end
 
  #--------------------------------------------------------------------------
  # new method: elements_max_rate3
  #--------------------------------------------------------------------------
  def elements_max_rate3(user,elements)
    elements.inject([0.0]) {|r, i| r.push((get_atk_element_bonus(user,i)) -( get_def_element_bonus(i))) }.max
  end
  
  #--------------------------------------------------------------------------
  # new method: get_atk_element_multi
  #--------------------------------------------------------------------------
  def get_atk_element_multi(user,id)
    multi = 0.0
    if user.actor?
      multi += user.actor.atk_ele[id]
      multi += user.class.atk_ele[id]
      for equip in user.equips
        next if equip.nil?
        multi += equip.atk_ele[id]
      end
      for state in user.states
        next if state.nil?
        multi += state.atk_ele[id]
      end
    end
    if user.enemy? then
      multi += user.enemy.atk_ele[id]
      for state in user.states
        next if state.nil?
        multi += state.atk_ele[id]
      end
    end
    return multi
  end
 
  #--------------------------------------------------------------------------
  # new method: get_atk_element_bonus
  #--------------------------------------------------------------------------
  def get_atk_element_bonus(user,id)
    bonus = 0.0
    if user.actor?
      bonus += user.actor.atk_b_ele[id]
      bonus += user.class.atk_b_ele[id]
      for equip in user.equips
        next if equip.nil?
        bonus += equip.atk_b_ele[id]
      end
      for state in user.states
        next if state.nil?
        bonus += state.atk_b_ele[id]
      end
    end
    if user.enemy? then
      bonus += user.enemy.atk_b_ele[id]
      for state in user.states
        next if state.nil?
        bonus += state.atk_b_ele[id]
      end
    end
    return bonus
  end
 
  #--------------------------------------------------------------------------
  # new method: get_def_element_multi
  #--------------------------------------------------------------------------
  def get_def_element_multi(id)
    multi = 0.0
    if actor?
      multi += self.actor.def_ele[id]
      multi += self.class.def_ele[id]
      for equip in self.equips
        next if equip.nil?
        multi += equip.def_ele[id]
      end
      for state in self.states
        next if state.nil?
        multi += state.def_ele[id]
      end
    end
    if enemy? then
      multi += self.enemy.def_ele[id]
      for state in self.states
        next if state.nil?
        multi += state.def_ele[id]
      end
    end
    return multi
  end
  
  #--------------------------------------------------------------------------
  # new method: get_def_element_bonus
  #--------------------------------------------------------------------------
  def get_def_element_bonus(id)
    bonus = 0.0
    if actor?
      bonus += self.actor.def_b_ele[id]
      bonus += self.class.def_b_ele[id]
      for equip in self.equips
        next if equip.nil?
        bonus += equip.def_b_ele[id]
      end
      for state in self.states
        next if state.nil?
        bonus += state.def_b_ele[id]
      end
    end
    if enemy? then
      bonus += self.enemy.def_b_ele[id]
      for state in self.states
        next if state.nil?
        bonus += state.def_b_ele[id]
      end
    end
    return bonus
  end
  
  #--------------------------------------------------------------------------
  # new method: adik_modify_damage
  #--------------------------------------------------------------------------
  def adik_modify_damage(user,item,damage)
    return damage
  end
  
  #--------------------------------------------------------------------------
  # new method: adik_damage_extension
  #--------------------------------------------------------------------------
  def adik_damage_extension(user,item,damage)
    #Do nothing
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: make_damage_value
  #--------------------------------------------------------------------------
  def make_damage_value(user, item)
    value = item.damage.eval(user, self, $game_variables)
    value *= item_element_rate(user, item)
    value *= pdr if item.physical?
    value *= mdr if item.magical?
    value *= rec if item.damage.recover?
    item_elements_ex = get_elements(item)
    same_normal = item_elements_ex.size == 1 and item_elements_ex[0] == 0
    item_elements_ex = get_battler_elements(user) if item_elements_ex.empty? or same_normal
    value += elements_ex_bonus(user,item_elements_ex)
    value = apply_variance(value, item.damage.variance)
    value = apply_guard(value)
    if $imported["CriticalEX"] 
      value = apply_critical_ex(value,user,item) if @result.critical
    else
      value = apply_critical(value) if @result.critical
    end
    value = adik_modify_damage(user,item,value)
    @result.make_damage(value.to_i, item)
    adik_damage_extension(user,item,value)
  end
  
  #--------------------------------------------------------------------------
  # overwrite Yanfly's method: element_popup_tag?
  #--------------------------------------------------------------------------
  def element_popup_tag?(user, item)
    return "HP_DMG" if item.nil?
    text = "ELEMENT_"
    item_elements_ex = get_elements(item)
    same_normal = item_elements_ex.size == 1 and item_elements_ex[0] == 0
    if item_elements_ex.empty? or same_normal
      item_elements_ex = get_battler_elements(user)
    end
    return "HP_DMG" if item_elements_ex.empty? or Adiktuz::ElementEX::ELEMENT_DETECTION > 1
    if Adiktuz::ElementEX::ELEMENT_DETECTION == 0 then 
      rate = elements_max_rate2(user,item_elements_ex)
      for i in Adiktuz::ElementEX::ELEMENTS
        next unless get_atk_element_multi(user,i)-get_def_element_multi(i) == rate
        text += i.to_s
        break
      end
    else
      rate = elements_max_rate3(user,item_elements_ex)
      for i in Adiktuz::ElementEX::ELEMENTS
        next unless get_atk_element_bonus(user,i)-get_def_element_bonus(i) == rate
        text += i.to_s
        break
      end
    end
    text = "HP_DMG" unless YEA::BATTLE::POPUP_RULES.include?(text)
    return text
  end
end
 
class Window_ElementsEX < Window_Base
  
  
  def initialize(x, actor=$game_actors[1], y=line_height*2.5)
    super(x, y, window_width, window_height)
    @actor = actor
    @temp_actor = nil
    self.windowskin = Cache.system("Window3")
    refresh
  end
  
  def window_width
    return 412
  end
  
  def line_height
    return Adiktuz::ElementEX::FONT_SIZE
  end
  
  def window_height
    fitting_height(visible_line_number)
  end
  
  def visible_line_number
    return Adiktuz::ElementEX::ELEMENTS.size + 2
  end
  
  def actor=(actor)
    return if @actor == actor
    @actor = actor
    refresh
  end
  
  def refresh
    contents.clear
    contents.font.size = Adiktuz::ElementEX::FONT_SIZE
    draw_actor_name(@actor, (width/2) - @actor.name.length*Adiktuz::ElementEX::X_PER_LETTER, 0) if @actor
    draw_columns(48,line_height,82)
    draw_elementsex(48,82)
  end
  
  def set_temp_actor(temp_actor)
    return if @temp_actor == temp_actor
    @temp_actor = temp_actor
    refresh
  end
 
  def draw_elementsex(x,spacing)
    element_set = Adiktuz::ElementEX::ELEMENTS.clone
    element_set.delete(0)
    element_set.each_index do |id2|
      id = element_set[id2]
      draw_icon(Adiktuz::ElementEX::ELEMENTS_ICONS[id], 0, 20 + line_height*(id2+1))
      atk_perc = 100*@actor.get_atk_element_multi(@actor,id)
      def_perc = 100*@actor.get_def_element_multi(id)
      atk_dir = @actor.get_atk_element_bonus(@actor,id)
      def_dir = @actor.get_def_element_bonus(id)
      draw_text(x , 24 + line_height*(id2+1), 64, line_height, atk_perc.to_s)
      draw_text(x + spacing*2, 24 + line_height*(id2+1), 64, line_height, def_perc.to_s)
      draw_text(x + spacing, 24 + line_height*(id2+1), 64, line_height, atk_dir.to_s)
      draw_text(x + spacing*3,24 +  line_height*(id2+1), 64, line_height, def_dir.to_s)
    end
  end
  
  def draw_columns(x,y,spacing)
    draw_text(x, y, 64, line_height, "Attack %")
    draw_text(x + spacing, y, 64, line_height, "Attack +")
    draw_text(x + spacing*2, y, 64, line_height, "Defense %")
    draw_text(x + spacing*3, y, 64, line_height, "Defense +")
  end
end
 
class Window_ElementsHelp < Window_Base
  
  def initialize(x, y)
    super(x, y, window_width, window_height)
    self.windowskin = Cache.system("Window3")
    refresh
  end
  
  def window_width
    return 544
  end
  
  def line_height
    return Adiktuz::ElementEX::FONT_SIZE
  end
  
  def window_height
    fitting_height(1)
  end
  
  def refresh
    contents.clear
    contents.font.size = Adiktuz::ElementEX::FONT_SIZE
    draw_text(0, 0, window_width, line_height, "Change actors via the L/R button (Q/W by default)")
  end
  
end
 
class Window_ElementsEXCommand < Window_HorzCommand
  
  def initialize(x, y, width)
    @window_width = width
    super(x, y)
    #self.windowskin = Cache.system("Window3")
  end
  
  def window_width
    @window_width
  end
 
  def col_max
    return 1
  end
  
  def make_command_list
    add_command("Exit", :exit)
  end
end
 
class Scene_ElementsEX < Scene_MenuBase
  
  def start
    super
    create_elementex_window
    create_command_window
    create_help_window
  end
  
  def create_help_window
    @help_window = Window_ElementsHelp.new(0,0)
  end
  
  def create_command_window
    wx = 0
    wy = 124
    ww = 96
    @command_window = Window_ElementsEXCommand.new(wx, wy, ww)
    @command_window.viewport = @viewport
    @command_window.set_handler(:exit,   method(:return_scene))
    @command_window.set_handler(:cancel,   method(:return_scene))
    @command_window.set_handler(:pagedown, method(:next_actor))
    @command_window.set_handler(:pageup,   method(:prev_actor))
  end
  
  def create_elementex_window
    @elementex_window = Window_ElementsEX.new(120,@actor)
    @elementex_window.viewport = @viewport
  end
  
  def on_actor_change
    @elementex_window.actor = @actor
    @command_window.activate
  end
  
end
 
class Scene_Menu < Scene_MenuBase
  
  def command_elementex
    SceneManager.call(Scene_ElementsEX)
  end
  
end
 
class Scene_Equip < Scene_MenuBase
 
  def command_elementex
    SceneManager.call(Scene_ElementsEX)
  end
  
end

Comments