iPhone App Directory
RPG Maker VX
 
Gallery Members Search Calendar Help


Welcome Guest ( Log In | Register )

Collapse

>Announcement

Keep an eye out for the upcoming 3rd Quarter Contest!
 
Reply to this topicStart new topic
> New Element Rates, Changes the stacking of elemental values on multiple element attacks.
Mithran
post Dec 11 2008, 05:37 AM
Post #1


Scripter
Group Icon


Type: Coder
Alignment: True Neutral




Element Rates v 2.0
by Mithran


Introduction
Personally, the default stacking on the element system is one of the base features of the game I find particularly annoying. I mean, it just takes the most effecitve element and uses that one. What kind of system is that? The original script (now called 'unique' mode) was originally requested by Hesufo. Even after creating this script, it felt like a little something was missing. I have since expanded the script to include four different ways you can stack your elements - Unique, True Average, Multiplicative, or Advanced.

Features
- four modes to choose from, three which require almost no changes
- all modes no longer have you RESIST (from armor or state) something that you were going to ABSORB anyway
- A fourth 'advanced' mode, featuring six subsets of elements with different properties

How to Use
This is a new system designed to replace the default. As such, it should be copied above main and all other custom scripts and below defaults. Detailed instructions are in the script itself.

Script
Spoiler:
CODE
#<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><
#-  Element Rates v 2.0 by Mithran (last update December 14, 2008)
#-  "Unique" mode concept by Hesufo
#-  This is a complete rewrite of the default so-called element system
#-  that comes stock with RPG Maker VX
#-  
#-  Usage:  Contains four 'modes'
#-  Each mode calculates element stacking differently
#-  Simply set change the number after SYSTEM_TYPE =
#-  In the customization section to use that mode
#-  Modes 1 through 3 require no additional work
#-  Explanation of the modes in the customization section
#-  SYSTEM_TYPE = 1
#-  Mode 1 uses a unique and fairly balanced system to combine all elements
#-  SYSTEM_TYPE = 2
#-  Mode 2 averages every element in the attack (yeah, just an average of them)
#-  SYSTEM_TYPE = 3
#-  Mode 3 uses multiplicative stacking (every element rate is multiplied)
#-  More info and examples in the customization section
#-  
#-  
#-  Usage - Mode 4 *Advanced Mode* - Requires some setup
#-  Instructions are in the customization section
#-
#-  
#-  
#-  Install: Insert above Main and all other custom scripts
#<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><

#==============================================================================#
#                           * Customization *                                  #
#==============================================================================#


module Mithran
  module ElementRates
    SYSTEM_TYPE = 4
    ## Set the system type variable to use the different systems included in the
      #~ script
    ## 0 - RPGVX Standard Mode
    ## 1 - Unique Mode
      #~ Default element rate is 100 (100% damage)
      #~ --
      #~ each element rate that is above 100 is added to the rate, then subtract
      #~ 100
      #~ --
      #~ each element rate that is below 0 (negative) is subtracted by 100 and
      #~ added to the calculation
      #~ --
      #~ if the result of this calculation is negative, it cannot be bigger
      #~ (lower) than the value of highest negative element
      #~ --
      #~ if the result so far is negative, it is not reduced further by mixing
      #~ in elements between 0 and 100
      #~ --
      #~ apply a weighted avarage for the rates between 0 and 100
      #~ --
      #~ example: Slash is 50% effective and Fire is 200% effective.  
      #~ Using fire slash would result in 125% damage.
      #~ --
      #~ example 2: slash is 200% effective and fire is 200% effective.  
      #~ Using fire slash would result in 300% damage.
      #~ --
      #~ example 3: slash is 150% effective, fire is 150% effective,
      #~ and wind is 0% effective.  A combination of the three elements would
      #~ deal 133% damage (weighted average)
      #~ --
      #~ example 4: wind and fire are both -100% rate (F).  A wind/fire attack
      #~ would be 100% absorbed.
      #~ --
    ## 2 - True Average Mode
      #~ the rate of every element is avaraged
      #~ example: Fire is 50% effecitve (D) and ice is 150% effective (B).  
      #~ Using a fire/ice attack would result in 100% damage
      #~ --
      #~ example 2: Fire is 100% effective (C) and ice is -100% effective (F).  
      #~ Using a fire/ice attack would result in no damage
      #~ --
      #~ example 3: Fire is 0% effective (E) and ice is -100% effective.  
      #~ Using a fire/ice attack would result in 50% damage absorbed
      #~ --
    ## 3 - Multiplicative Mode
      #~ the rate of every positive and zero element is multiplied together as a
      #~ percentage value
      #~
      #~ the rate of the first negative (absorbed) element, if any, sets the
      #~ base negative rate
      #~
      #~ the rate of every other every negative (absorbed) element is subtracted
      #~ by 100 and multiplied together, with the result set to negative
      #~
      #~ example 1: Fire is 50% effective and ice is 150% effective.  
      #~ Using a fire/ice attack would result in 75% damage
      #~
      #~ example 2: Fire is 50% effective and ice is 100% absorbed.  
      #~ Using a fire/ice attack would absorb 50% damage
      #~
      #~ example 3: Fire is 200% effective and ice is 200% effective.  
      #~ Using a fire/ice attack would result in 400% damage
      #~
      #~ example 4: Fire is 200% effective, ice is 200% effective, wind is 100%
      #~ absorbed, earth is 100% absorbed, darkness is 100% absorbed
      #~ An attack with all five of these elements would do zero damage
      #~
    ## 4 - Advanced Mode
      #~ See Below
#==============================================================================#
#                       * ADVANCED MODE SETTINGS*                              #
#==============================================================================#
      
    ## Six element categories follow here.  The numbers in each one coorespond
    ## to the element IDs in the database.  To add a number, type within the
    ## brackes and be sure to seperate each number with a comma
    WEAPON_ELEMENTS = [ 1, 2, 3, 4, 5, 6 ]
      #~ Weapon type elements.  The MOST EFFECTIVE RATE will be taken for each
      #~ set with the rest ignored for the final formula.
    PHYSICAL_ELEMENTS = [17]
      #~ the element for all physical attack (more than one may be defined, but
      #~ not necessary)
      #~ if more than one is assigned, they will be averaged using the true
      #~ average formula for the final calculation
    MAGICAL_ELEMENTS = [18]
      #~ the element for all magical attack (more than one may be defined, but
      #~ not necessary)
      #~ if more than one is assigned, they will be averaged using the true
      #~ average formula for the final calculation
    BANE_ELEMENTS = [19, 20, 21, 22] # uses the BANE system
      #~ Banes use their own rate definitions (see below).  Bane elements are
      #~ intended to work with body types.
      #~
      #~ To set a bodytype on an enemy, simply type <bodytype n> in the note
      #~ section, where n is the number ID of the associated bane element.
      #~
      #~ Multiple bodytypes can be set for each enemy.  Only the MOST EFFECTIVE
      #~ bane value will be use.  
      #~
      #~ Any state that resists a bane element will make the rate (of the bane
      #~ in question only) equal 100
    INDIVIDUAL_ELEMENTS = [23, 24]
      #~ These elements are mixed using the Multiplicative Mode formula.
      #~
      #~ They also use their own rate set (See below). As such, if you wanted
      #~ someone to be immune to an attack with any of these elements mixed in
      #~ them at all, you would set their effectivness of this value to F.
      #~
      #~ By default are NO absorb values for indiviudal elements letter values
      #~
      #~ If a state or equipment resists an indiviudal element, its letter value
      #~ is increased by 1, (A becomes B, B becomes C, etc.) rather than halving
      #~ its current rate like the default system
      #~
      #~ The intended usage is for things like a "Gravity" element (for, say,
      #~ KGC_RateDamage) that you want bosses to be immune to.  
      #~
      #~ This allows you to mix these attacks that would otherwise be overpowered
      #~ with other elements.  It also allows multiplicative stacking within the
      #~ system.
      #~
      #~ Example: Static Field (gravity + lightning), enemy is C vs lightning
      #~ and F vs gravity, damage will be nullified
  ## ELEMENTAL_ELEMENTS (or normal elements)
    #~ Elemental elements set, or the normal element set, is any element not
    #~ already defined above.  Elements in this category are combined using
    #~ the True Average formula for the final calculation
  ## THE FINAL FORMULA
    #~ The six element subsets are resolved as indicated above
    #~ Any empty subset has a value of 100
    #~ If any of the subsets are negative, use the best absorbtion rate in the subsets as the final result
    #~ If not, the final result is a product of all six subsets as percentages
    
    
    # Editing the following values is intended only for advanced users.
    # I figure, if you read this far, you hopefully know what you are doing,
    # so have at it :)
    ElementValues = [ # normal element definitions
    0, # null value, not used in game
    200,  # value of A element efficency
    150,  # value of B element efficency
    100,  # value of C element efficency
    50,   # value of D element efficency
    0,    # value of E element efficency
    -100 ]# value of F element efficency
    
    BaneValues = [ # "Bane" elements definitons
    0, # null value, not used in game
    400,  # value of A element efficency
    300,  # value of B element efficency
    250,  # value of C element efficency
    200,   # value of D element efficency
    150,    # value of E element efficency
    100 ] # value of F element efficency  
    
    IndividualValues = [ #
    0, # null value, not used in game
    200,  # value of A element efficency
    150,  # value of B element efficency
    100,  # value of C element efficency
    50,   # value of D element efficency
    25,    # value of E element efficency
    0 ] # value of F element efficency  
  end
end

#==============================================================================#
#                           * End Customization *                                                            #
#==============================================================================#


class RPG::BaseItem
  def bodytype
    get_item_bodytype if @bodytype == nil
    return @bodytype
  end
  def get_item_bodytype
    @bodytype = 0
    self.note.gsub(/<bodytype (\d+)>/i, "")
    @bodytype = $1.to_i
  end
end

class Game_Actor < Game_Battler
  alias element_rate_orig_mith element_rate
  def element_rate(element_id)
    case Mithran::ElementRates::SYSTEM_TYPE
    when 1, 2, 3
      return element_rate_standard(element_id)
    when 4
      return element_rate_advanced(element_id)
    else
      return element_rate_orig_mith(element_id)
    end
  end
  
  def bodytypes
    result = []
    for equip in equips.compact
      result.push(equip.bodytype) unless equip.bodytype == 0
    end
    return result
  end
    
  def element_rate_standard(element_id)
    rank = self.class.element_ranks[element_id]
    result = Mithran::ElementRates::ElementValues[rank]
    return result if result < 0 # the only difference between standard and the default method
    # is that states or armors that resist an element will NOT affect it if it is already negative
    for armor in armors.compact
      result /= 2 if armor.element_set.include?(element_id)
    end
    for state in states
      result /= 2 if state.element_set.include?(element_id)
    end
    return result
  end
  
  def element_rate_advanced(element_id)
    case element_type(element_id)
    when 'bane'
      return element_rate_bane(element_id)
    when 'individual'
      return element_rate_individual(element_id)
    else
      return element_rate_standard(element_id)
    end
  end
  
  def element_rate_bane(element_id)
    return 100 unless self.bodytypes.include?(element_id) # bane rates will only be applied if the bodytype matches
    rank = self.class.element_ranks[element_id]
    result = Mithran::ElementRates::BaneValues[rank]
    for armor in armors.compact
      return 100 if armor.element_set.include?(element_id) # resisting a bane nullifies it in the equation
    end
    for state in states.compact
      return 100 if state.element_set.include?(element_id) # resisting a bane nullifies it in the equation
    end
    return result
  end
  
  def element_rate_individual(element_id)
    rank = self.class.element_ranks[element_id]
    for armor in armors.compact
      rank += 1 if armor.element_set.include?(element_id)
    end
    for state in states
      rank += 1 if state.element_set.include?(element_id)
    end
    rank = 6 if rank > 6
    result = Mithran::ElementRates::IndividualValues[rank]
  end
  
  
end

class Game_Enemy < Game_Battler
  alias element_rate_orig_mith element_rate
  def element_rate(element_id)
    case Mithran::ElementRates::SYSTEM_TYPE
    when 1, 2, 3
      return element_rate_standard(element_id)
    when 4
      return element_rate_advanced(element_id)
    else
      return element_rate_orig_mith(element_id)
    end
  end
  
  def element_rate_standard(element_id)
    rank = enemy.element_ranks[element_id]
    result = Mithran::ElementRates::ElementValues[rank]
    return result if result < 0
    for state in states
      result /= 2 if state.element_set.include?(element_id)
    end
    return result
  end
  
  def element_rate_advanced(element_id)
    case element_type(element_id)
    when 'bane'
      return element_rate_bane(element_id)
    when 'individual'
      return element_rate_individual(element_id)
    else
      return element_rate_standard(element_id)
    end
  end
  
  def element_rate_bane(element_id)
    return 100 unless self.bodytypes.include?(element_id) # bane rates will only be applied if the bodytype matches
    rank = enemy.element_ranks[element_id]
    result = Mithran::ElementRates::BaneValues[rank]
    for state in states.compact
      return 100 if state.element_set.include?(element_id) # resisting a bane nullifies it in the equation
    end
    return result
  end
  
  def bodytypes
    make_enemy_bodytypes if @bodytypes == nil
    return @bodytypes
  end
  
  def make_enemy_bodytypes
    @bodytypes = []
    text = enemy.note
    text.split(/[\r\n]+/).each { |line|
    if line =~ /<bodytype (\d+)>/i
      @bodytypes.push($1.to_i)
    end
    }
  end
  
  def element_rate_individual(element_id)
    rank = enemy.element_ranks[element_id]
    for state in states
      rank += 1 if state.element_set.include?(element_id)
    end
    rank = 6 if rank > 6
    result = Mithran::ElementRates::IndividualValues[rank]
  end
end

class Game_Battler
  #--------------------------------------------------------------------------
  # * Get Maximum Elemental Adjustment Amount
  #     element_set : Elemental alignment
  #    Returns the most effective adjustment of all elemental alignments.
  #--------------------------------------------------------------------------
  alias elements_max_rate_orig_mith elements_max_rate
  def elements_max_rate(element_set)
    case Mithran::ElementRates::SYSTEM_TYPE
    when 1
      return elements_max_rate_unique(element_set)
    when 2
      return elements_max_rate_trueavg(element_set)
    when 3
      return elements_max_rate_multiplicative(element_set)
    when 4
      return elements_max_rate_sysadvanced(element_set)
    else
      return elements_max_rate_orig_mith(element_set)
    end
  end
    
  def elements_max_rate_unique(element_set)
    return 100 if element_set.empty?              
    current_rate = 100
    element_rates = []  # array of the rate of all the elements
    increaser_rates = []  # array of rates which will add
    decreaser_rates = [] # array of rates that will divide
    negative_rates = [] # array of rates that will subtract
    element_set.each { |n|
    element_rates.push(element_rate(n)) # gets element rates and put them in an array
    }
    for er in element_rates
      if er >= 100 # if the rate is bigger than 100 or equal to 100
        increaser_rates.push(er)
      elsif er < 100 and er > 0 # if the rate is between 0 and 100
        decreaser_rates.push(er)
      elsif er < 0
        negative_rates.push(er) # if the rate is negative
      end
    end
    for er in increaser_rates
      current_rate += er - 100 # add all the rates with values greater than 100 and
      # less than zero together and subtract 100 for each one.  
    end
    for er in negative_rates
      current_rate += er - 100
      current_rate = [current_rate, negative_rates.min].max # cannot absorb more
      # than the biggest negative rate
    end
    return current_rate if current_rate <= 0 # decreasers wont be applied if absorbing
    decreaser_value = 0
    for er in decreaser_rates
      decreaser_value += er
    end
    current_rate *= increaser_rates.size
    current_rate += decreaser_value
    current_rate /= element_set.size
    return current_rate
  end
  
  def elements_max_rate_trueavg(element_set)
    return 100 if element_set.empty?
    result = 0
    element_set.each { |i|
    result += element_rate(i)
    }
    result /= element_set.size
    return result
  end
  
  def elements_max_rate_multiplicative(element_set)
    return 100 if element_set.empty?
    current_rate = 100
    element_rates = []  # array of the rate of all the elements
    positive_rates = []  # array of positive rates or zero
    negative_rates = [] # array of negative rates
    total_negative_rate = 0
    element_set.each { |n|
    element_rates.push(element_rate(n)) # gets element rates and put them in an array
    }
    for er in element_rates
      negative_rates.push(er) if er < 0
      positive_rates.push(er) if er >= 0
    end
    negative_rates.each_index { |i|
      negative_rates[i] -= 100
    }
    for er in negative_rates
      if total_negative_rate == 0
        total_negative_rate = er.abs
        next
      end
      total_negative_rate = total_negative_rate * er / 100
      total_negative_rate = total_negative_rate.abs
    end
    for er in positive_rates
      current_rate = current_rate * er / 100
    end
    return (current_rate - total_negative_rate)
  end
  
  def elements_max_rate_sysadvanced(element_set)
    return 100 if element_set.empty?
    current_rate = 100
    weapon_elements = get_matching_array_elements(element_set, Mithran::ElementRates::WEAPON_ELEMENTS)
    physical_elements = get_matching_array_elements(element_set, Mithran::ElementRates::PHYSICAL_ELEMENTS)
    magical_elements = get_matching_array_elements(element_set, Mithran::ElementRates::MAGICAL_ELEMENTS)
    bane_elements = get_matching_array_elements(element_set, Mithran::ElementRates::BANE_ELEMENTS)
    individual_elements = get_matching_array_elements(element_set, Mithran::ElementRates::INDIVIDUAL_ELEMENTS)
    elemental_elements = element_set - (weapon_elements | physical_elements | magical_elements |
      bane_elements)
    weapon_rate = elements_max_rate_orig_mith(weapon_elements)
    physical_rate = elements_max_rate_trueavg(physical_elements)
    magical_rate = elements_max_rate_trueavg(magical_elements)
    bane_rate = elements_max_rate_orig_mith(bane_elements)
    elemental_rate = elements_max_rate_trueavg(elemental_elements)
    individual_rate = elements_max_rate_multiplicative(individual_elements)
    minimum_rate = [weapon_rate, physical_rate, magical_rate, bane_rate, elemental_rate, individual_rate].min
    if minimum_rate <= 0
      return minimum_rate
    end
    current_rate = current_rate * weapon_rate / 100
    current_rate = current_rate * physical_rate / 100
    current_rate = current_rate * magical_rate / 100
    current_rate = current_rate * bane_rate / 100
    current_rate = current_rate * elemental_rate / 100
    current_rate = current_rate * individual_rate / 100
    return current_rate
  end


  def element_type(element_id)
    return 'weapon' if Mithran::ElementRates::WEAPON_ELEMENTS.include?(element_id)
    return 'physical' if Mithran::ElementRates::PHYSICAL_ELEMENTS.include?(element_id)
    return 'magical' if Mithran::ElementRates::MAGICAL_ELEMENTS.include?(element_id)
    return 'bane' if Mithran::ElementRates::BANE_ELEMENTS.include?(element_id)
    return 'individual' if Mithran::ElementRates::INDIVIDUAL_ELEMENTS.include?(element_id)
    return 'elemental'
  end
  
  def get_matching_array_elements(array1, array2)
    result = []
    for i in array1
      result.push(i) if array2.include?(i)
    end
    return result
  end

end


FAQ
Q: I don't understand the forumla!
A: For the first three, its pretty much as simple as this: True Average is just an average of all the element rates. Multiplicative is basically the product of the percentage values of all the rates (unless you are stacking mutiple negatives). Unique is a bit more complicated, but it works closer to True Average but allows some upward stacking on positive elements.

Q: I still dont get it...
A: Well, try it out. Modes 1 and 2 will generally yeild moderate values. Mode 3's values will vary hugely based on the element set.

Q: Whats all this about advanced modes?
A: The instructions are conveniently located in the script in the customization section, along with examples of what each one does.

Q: That is far too much to read, and far far too complicated..
A: If there is something you don't get from the instructions, feel free to post or PM me and I'll try to better explain the feature. If you don't want to bother, that's why I put the alternate 'modes' in the script, which can be activated by typing a single number.

Credit and Thanks
- Mithran (the script)
- Hesufo (unique mode concept)

Author's Notes
Feedback is welcome.

This post has been edited by Mithran: Feb 1 2011, 01:07 AM


--------------------
Go to the top of the page
 
+Quote Post
   
Hesufo
post Dec 11 2008, 05:52 AM
Post #2


Back, I guess.
Group Icon






Ohhai.

Thanks again for this script, Mithran! I've bombarded you with enough thanks for now, I guess! XD

I hope this can also help other people! :D


--------------------

A dedicated (?) Lucky Star fan. ∑w∑
A big thanks to Kouki for the banner!


"If there is an exception to every rule, then every rule must have at least one exception, the exception to this one being that it has no exception."


My project, Forgotten Wishes - Demo 1.5 (1/04/2009) now available!

Go to the top of the page
 
+Quote Post
   
Moonlight
post Dec 11 2008, 08:24 AM
Post #3



Group Icon


Type: Coder




Very good idea. I did my own rates in my game so I will not really need it but it is nice to see someone release a script like this.

The default formula is so dumb...

I'll still look how it goes. Thanks. smile.gif

This post has been edited by Moonlight: Dec 11 2008, 08:24 AM
Go to the top of the page
 
+Quote Post
   
Mithran
post Dec 14 2008, 08:21 PM
Post #4


Scripter
Group Icon


Type: Coder
Alignment: True Neutral




*Update*

Version 2.0
Four modes to choose from:
- unique (the original posted script v 1.5b)
- True Average (averages all elements in the set together)
- Multiplicitive (uses multiplicative stacking)
- Advanced Mode

Advanced Mode Features:
- Six element subsets - weapon, elemental, physical, magical, bane, and indiviudal, each with their own rules.
- Combines the best of Multiplicative and True Average modes, as well as even some of the original

Check the original post for the script.


--------------------
Go to the top of the page
 
+Quote Post
   
Hesufo
post Dec 14 2008, 08:51 PM
Post #5


Back, I guess.
Group Icon






Holy crap, Mithran! You really expanded this script to a big, big one!

That's awesome, kudos to you!

Keep up the great work, and I hope you can help me with some other request in the future ^_^

Sky's the limit!


--------------------

A dedicated (?) Lucky Star fan. ∑w∑
A big thanks to Kouki for the banner!


"If there is an exception to every rule, then every rule must have at least one exception, the exception to this one being that it has no exception."


My project, Forgotten Wishes - Demo 1.5 (1/04/2009) now available!

Go to the top of the page
 
+Quote Post
   
Mithran
post May 4 2010, 12:20 PM
Post #6


Scripter
Group Icon


Type: Coder
Alignment: True Neutral




Thanks to Gio and Deadlock for pointing out an error in my script. There is a point in the script where multiplicative is typoed as "multiplicitive". If you don't use multiplicative rates, it wont affect you, and you can correct it with a simple find > multiplicitive and change that one 'i' to an 'a'. The script in the original post has been fixed.


--------------------
Go to the top of the page
 
+Quote Post
   
FantasyLord
post Jan 31 2011, 09:50 PM
Post #7



Group Icon


Type: Undisclosed




Hello.
I found another typing error:

line 481: individual_rate = elements_max_rate_multiplicitive(individual_elements)
correction --> individual_rate = elements_max_rate_multiplicative(individual_elements)

It's not yet fixed in the script in the original post.

This post has been edited by FantasyLord: Jan 31 2011, 09:51 PM
Go to the top of the page
 
+Quote Post
   
Mithran
post Feb 1 2011, 01:08 AM
Post #8


Scripter
Group Icon


Type: Coder
Alignment: True Neutral




QUOTE (FantasyLord @ Jan 31 2011, 01:50 PM) *
Hello.
I found another typing error:

line 481: individual_rate = elements_max_rate_multiplicitive(individual_elements)
correction --> individual_rate = elements_max_rate_multiplicative(individual_elements)

It's not yet fixed in the script in the original post.


And now it is. Thanks.


--------------------
Go to the top of the page
 
+Quote Post
   
Soma43
post Feb 2 2011, 11:36 PM
Post #9



Group Icon


Type: Designer




This is great!
A very unique idea! wink.gif
Keep it up!




-Soma43


--------------------
Go to the top of the page
 
+Quote Post
   
Jay666Dark
post May 10 2011, 01:49 AM
Post #10



Group Icon


Type: Artist




Amazing Script!!!!


--------------------
» Click to show Spoiler - click again to hide... «
Go to the top of the page
 
+Quote Post
   

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 2nd September 2014 - 03:50 PM

RPGMakerVX.net is an Privacy Policy, Legal.