#============================================================================== # # 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: # # = Gives bonus elemental damage to the object # Positive: Damage done increases # Negative: Damage done decreases # = 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 tag # actor1's class has a tag # actor1's armor has a 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: # # = Gives bonus elemental damage to the object # Positive: Damage done increases # Negative: Damage done decreases # = 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 tag # actor1's class has a tag # actor1's armor has a 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: # # # # 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 # # # # y => rate (1.0 = 100%, 0.5 = 50%, 2.0 = 200%) # # If this tag is not used, all elements defined by 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 = //i SKILL_ELER = //i ATK_ELE = //i DEF_ELE = //i ATK_B_ELE = //i 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