Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Element Affinity

Another script by me, how exciting.

This script basically allows you to become alligned with elements (for those of you who use element tagging you'll be pleased to know you have to tell it which elements to work with).

Features include:
Opposite Elements
Improved/Worsened Resistences
Quarter/Half/Double/Quadruple Spell Cost (based on allignment)
Quarter/Half/Double/Quadruple Spell Damage (based on allignment)

For resistences assuming you have C set if you are perfectly alligned positively you will absorb 100% of the damage, however if you are perfectly negatively alligned it does double damage.

All features can be turned off/worked around.

And without further ado here is the script.
Code:
#--------------------------------------------------------------------------
  # Element Affinity
  # Script by Fomar0153
  #--------------------------------------------------------------------------
class Game_Actor < Game_Battler
  #--------------------------------------------------------------------------
  # Constants
  #--------------------------------------------------------------------------
  Elements = [
  {'name'=>'Fire', 'id'=>1, 'opp'=>'Ice'},
  {'name'=>'Ice', 'id'=>2, 'opp'=>'Fire'},
  {'name'=>'Thunder', 'id'=>3, 'opp'=>'Water'},
  {'name'=>'Water', 'id'=>4, 'opp'=>'Thunder'},
  {'name'=>'Earth', 'id'=>5, 'opp'=>'Wind'},
  {'name'=>'Wind', 'id'=>6, 'opp'=>'Earth'},
  {'name'=>'Light', 'id'=>7, 'opp'=>'Darkness'},
  {'name'=>'Darkness', 'id'=>8, 'opp'=>'Light'}
  ]
  # The maximum you can be aligned with an element
  Max_Affinity = 1000
  # The minimum you can be aligned with an element
  Min_Affinity = -1000
  # How much alignment you gain with the element used
  Element_Usage = 1
  # How much the opposing alignment loses
  Opposite_Cost = 1
  # How much all other alignments not linked to the used alignment lose
  All_Cost = 0
  # How much you must be aligned with an element for half spell cost
  # Note: 0 means the feature won't happen
  Half_Spell_Cost = 250
  # How much you must be aligned with an element for quarter spell cost
  # Note: 0 means the feature won't happen
  Quarter_Spell_Cost = 750
  # How much you must be aligned with an element to do double damage
  # Note: 0 means the feature won't happen
  Double_Spell_Damage = 500
  # How much you must be aligned with an element to do quadruple damage
  # Note: 0 means the feature won't happen
  Quad_Spell_Damage = 1000
  # How little you must be aligned with an element for double spell cost
  # Note: 0 means the feature won't happen
  Double_Spell_Cost = -250
  # How little you must be aligned with an element for quardruple spell cost
  # Note: 0 means the feature won't happen
  Quad_Spell_Cost = -750
  # How little you must be aligned with an element to do half damage
  # Note: 0 means the feature won't happen
  Half_Spell_Damage = -500
  # How little you must be aligned with an element to do quarter damage
  # Note: 0 means the feature won't happen
  Quarter_Spell_Damage = -1000
  # If set to true your allignments will positively affect your elemental resistences (> 0)
  Affect_Resistences_Pos = true
  # If set to true your allignments will negatively affect your elemental resistences (< 0)
  Affect_Resistences_Neg = true
  #--------------------------------------------------------------------------
  # End Of Constants
  #--------------------------------------------------------------------------
  alias old_setup setup
  def setup(actor_id)
    old_setup(actor_id)
    @element_affinity = []
    for i in 0...Elements.size
      @element_affinity.push(0)
    end
  end
  
  def is_element?(element)
    for i in 0...Elements.size
      hash = Elements[i]
      if hash['id'] == element
        return true
      end
    end
    return false
  end
  
  def element_affinity_adjust(element)
    if is_element?(element)
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['id'] == element
          k = i
          opp_name = hash['opp']
        end
      end
      
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['name'] = opp_name
          j = i
        end
      end
      if @element_affinity[k] < Max_Affinity
        @element_affinity[k] += Element_Usage
      end
      
      if @element_affinity[k] > Max_Affinity
        @element_affinity[k] = Element_Usage
      end
      
      
      if @element_affinity[j] > Min_Affinity
        @element_affinity[j] -= Opposite_Cost
      end
      
      if @element_affinity[j] < Min_Affinity
        @element_affinity[j] = Opposite_Cost
      end
      
      unless All_Cost == 0
        for i in 0...Elements.size
          Elements[i] -= All_Cost
        end
        Elements[k] += All_Cost
        Elements[j] += All_Cost
      end
      
    end
  end
    
  def affinity(element)
    if is_element?(element)
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['id'] == element
          return @element_affinity[i]
        end
      end
    end
    return 0
  end
  
  def element_rate(element_id)
    # Get values corresponding to element effectiveness
    table = [0,200,150,100,50,0,-100]
    result = table[$data_classes[@class_id].element_ranks[element_id]]
    # For each 1% of max affinity you get +2 resistence
    # meaning at 50% you take no damage and at 100%
    # you absorb the damage (assuming you start at C (100))
    if is_element?(element_id)
      x = affinity(element_id)
      x /= Max_Affinity
      x *= 200
      if x > 0 and Affect_Resistences_Pos == true
        result -= x
      end
      if x < 0 and Affect_Resistences_Neg == true
        result -= x/2
      end
    end
    # If this element is protected by armor, then it's reduced by half
    for i in [@armor1_id, @armor2_id, @armor3_id, @armor4_id]
      armor = $data_armors[i]
      if armor != nil and armor.guard_element_set.include?(element_id)
        result /= 2
      end
    end
    # If this element is protected by states, then it's reduced by half
    for i in @states
      if $data_states[i].guard_element_set.include?(element_id)
        result /= 2
      end
    end
    # End Method
    return result
  end
    
  def half_spell_cost_is
    return Half_Spell_Cost
  end
  
  def quarter_spell_cost_is
    return Quarter_Spell_Cost
  end
  
  def double_spell_damage_is
    return Double_Spell_Damage
  end
  
  def quad_spell_damage_is
    return Quad_Spell_Damage
  end
    
  def double_spell_cost_is
    return Double_Spell_Cost
  end
  
  def quad_spell_cost_is
    return Quad_Spell_Cost
  end
  
  def half_spell_damage_is
    return Half_Spell_Damage
  end
  
  def quarter_spell_damage_is
    return Quarter_Spell_Damage
  end
  
  def is_actor?
    return true
  end
  
end





class Game_Enemy < Game_Battler
  def is_actor?
    return false
  end
end





class Game_Battler
  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)
      
      # For you merging this only the code in this method that is new
      if user.is_actor? and skill.element_set != []
        
        for i in skill.element_set
          affinity = user.affinity(i)
          
          if affinity >= user.double_spell_damage_is and user.double_spell_damage_is != 0
            rate *= 2
          end
          
          if affinity >= user.quad_spell_damage_is and user.quad_spell_damage_is != 0
            rate *= 2
          end
          
          if affinity <= user.half_spell_damage_is and user.half_spell_damage_is != 0
            rate /= 2
          end
          
          if affinity <= user.quarter_spell_damage_is and user.quarter_spell_damage_is != 0
            rate /= 2
          end
          
        end
      end
      
      # 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
end



class Window_Skill < Window_Selectable
  
  def draw_item(index)
    skill = @data[index]
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + index % 2 * (288 + 32)
    y = index / 2 * 32
    rect = Rect.new(x, y, self.width / @column_max - 32, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    bitmap = RPG::Cache.icon(skill.icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
    self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
    sp_cost = skill.sp_cost
    
    unless skill.element_set == []
      for i in skill.element_set
        affinity = @actor.affinity(i)
        if affinity >= @actor.half_spell_cost_is and @actor.half_spell_cost_is != 0
          sp_cost /= 2
        end
        
        if affinity >= @actor.quarter_spell_cost_is and @actor.quarter_spell_cost_is != 0
          sp_cost /= 2
        end

        if affinity <= @actor.double_spell_cost_is and @actor.double_spell_cost_is != 0
          sp_cost *= 2
        end
        
        if affinity <= @actor.quad_spell_cost_is and @actor.quad_spell_cost_is != 0
          sp_cost *= 2
        end
        
      end
    end
    
    
    self.contents.draw_text(x + 232, y, 48, 32, sp_cost.to_s, 2)
  end
  
end





class Scene_Battle
  def make_skill_action_result
    # Get skill
    @skill = $data_skills[@active_battler.current_action.skill_id]
    # If not a forcing action
    unless @active_battler.current_action.forcing
      # If unable to use due to SP running out
      unless @active_battler.skill_can_use?(@skill.id)
        # Clear battler being forced into action
        $game_temp.forcing_battler = nil
        # Shift to step 1
        @phase4_step = 1
        return
      end
    end
    # Use up SP
    sp_cost = @skill.sp_cost
    if @active_battler.is_actor? and @skill.element_set != []
      
      for i in @skill.element_set
        affinity = @active_battler.affinity(i)
        
        if affinity >= @active_battler.half_spell_cost_is and @active_battler.half_spell_cost_is != 0
          sp_cost /= 2
        end
        
        if affinity >= @active_battler.quarter_spell_cost_is and @active_battler.quarter_spell_cost_is != 0
          sp_cost /= 2
        end

        if affinity <= @active_battler.double_spell_cost_is and @active_battler.double_spell_cost_is != 0
          sp_cost *= 2
        end
        
        if affinity <= @active_battler.quad_spell_cost_is and @active_battler.quad_spell_cost_is != 0
          sp_cost *= 2
        end
      end
    end
    @active_battler.sp -= sp_cost
    # Refresh status window
    @status_window.refresh
    # Show skill name on help window
    @help_window.set_text(@skill.name, 1)
    # Set animation ID
    @animation1_id = @skill.animation1_id
    @animation2_id = @skill.animation2_id
    # Set command event ID
    @common_event_id = @skill.common_event_id
    # Set target battlers
    set_target_battlers(@skill.scope)
    # Apply skill effect
    for target in @target_battlers
      target.skill_effect(@active_battler, @skill)
    end
    
    if @active_battler.is_actor? and @skill.element_set != []
      for i in @skill.element_set
        @active_battler.element_affinity_adjust(i)
      end
    end
    
    
  end
  
end

The only help I can see you needing is with the hash table.
Elements = [
{'name'=>'Fire', 'id'=>1, 'opp'=>'Ice'},
{'name'=>'Ice', 'id'=>2, 'opp'=>'Fire'},
{'name'=>'Thunder', 'id'=>3, 'opp'=>'Water'},
{'name'=>'Water', 'id'=>4, 'opp'=>'Thunder'},
{'name'=>'Earth', 'id'=>5, 'opp'=>'Wind'},
{'name'=>'Wind', 'id'=>6, 'opp'=>'Earth'},
{'name'=>'Light', 'id'=>7, 'opp'=>'Darkness'},
{'name'=>'Darkness', 'id'=>8, 'opp'=>'Light'}
]
Name is the name of the element, id is the id in the database of the element you want it to apply to and opp is the opposing element.
If for some reason you want an element with no opposite add an extra one to the database (and never use it anywhere) and make that the opposite.
Otherwise you should be able to do almost everything with just the constants at the start of the script.

Any errors post here please.
To use the script paste above main.
I'll merge it with the RTAB in a bit so be patient if you want a RTAB version.

Any feedback will be appreciated.

Edit: Ok for the RTAB:
Place the script above main and below the RTAB scripts then paste this extra bit below the main section of this script.
Code:
class Game_Battler
  def skill_effect(user, skill)
    # クリティカルフラグをクリア
    self.critical[user] = false
    state_p[user] = []
    state_m[user] = []
    # スキルの効果範囲が HP 1 以上の味方で、自分の HP が 0、
    # またはスキルの効果範囲が HP 0 の味方で、自分の HP が 1 以上の場合
    if ((skill.scope == 3 or skill.scope == 4) and self.hp == 0) or
       ((skill.scope == 5 or skill.scope == 6) and self.hp >= 1)
      # メソッド終了
      return false
    end
    # 有効フラグをクリア
    effective = false
    # コモンイベント ID が有効の場合は有効フラグをセット
    effective |= skill.common_event_id > 0
    # 第一命中判定
    hit = skill.hit
    if skill.atk_f > 0
      hit *= user.hit / 100
    end
    hit_result = (rand(100) < hit)
    # 不確実なスキルの場合は有効フラグをセット
    effective |= hit < 100
    # 命中の場合
    if hit_result == true
      # 威力を計算
      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
      # 倍率を計算
      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)
      if user.is_actor? and skill.element_set != []
        
        for i in skill.element_set
          affinity = user.affinity(i)
          
          if affinity >= user.double_spell_damage_is and user.double_spell_damage_is != 0
            rate *= 2
          end
          
          if affinity >= user.quad_spell_damage_is and user.quad_spell_damage_is != 0
            rate *= 2
          end
          
          if affinity <= user.half_spell_damage_is and user.half_spell_damage_is != 0
            rate /= 2
          end
          
          if affinity <= user.quarter_spell_damage_is and user.quarter_spell_damage_is != 0
            rate /= 2
          end
          
        end
      end
      # 基本ダメージを計算
      self.damage[user] = power * rate / 20
      # 属性修正
      self.damage[user] *= elements_correct(skill.element_set)
      self.damage[user] /= 100
      # ダメージの符号が正の場合
      if self.damage[user] > 0
        # 防御修正
        if self.guarding?
          self.damage[user] /= 2
        end
      end
      # 分散
      if skill.variance > 0 and self.damage[user].abs > 0
        amp = [self.damage[user].abs * skill.variance / 100, 1].max
        self.damage[user] += rand(amp+1) + rand(amp+1) - amp
      end
      # 第二命中判定
      eva = 8 * self.agi / user.dex + self.eva
      hit = self.damage[user] < 0 ? 100 : 100 - eva * skill.eva_f / 100
      hit = self.cant_evade? ? 100 : hit
      hit_result = (rand(100) < hit)
      # 不確実なスキルの場合は有効フラグをセット
      effective |= hit < 100
    end
    # 命中の場合
    if hit_result == true
      # 威力 0 以外の物理攻撃の場合
      if skill.power != 0 and skill.atk_f > 0
        # ステート衝撃解除
        remove_states_shock
        # 有効フラグをセット
        effective = true
      end
      # HP の変動判定
      last_hp = [[self.hp - self.damage[user], self.maxhp].min, 0].max
      # 効果判定
      effective |= self.hp != last_hp
      # ステート変化
      @state_changed = false
      effective |= states_plus(user, skill.plus_state_set)
      effective |= states_minus(user, skill.minus_state_set)
      unless $game_temp.in_battle
        self.damage_effect(user, 1)
      end
      # 威力が 0 の場合
      if skill.power == 0
        # ダメージに空文字列を設定
        self.damage[user] = ""
        # ステートに変化がない場合
        unless @state_changed
          # ダメージに "Miss" を設定
          self.damage[user] = "Miss"
        end
      end
    # ミスの場合
    else
      # ダメージに "Miss" を設定
      self.damage[user] = "Miss"
    end
    # 戦闘中でない場合
    unless $game_temp.in_battle
      # ダメージに nil を設定
      self.damage[user] = nil
    end
    # メソッド終了
    return effective
  end

end






class Scene_Battle
    def make_skill_action_result(battler)
    # スキルを取得
    @skill = $data_skills[battler.current_action.skill_id]
    # 連携スキルであるかどうか確認
    speller = synthe?(battler)
    # 強制アクションでなければ
    unless battler.current_action.forcing
      # SP 切れなどで使用できなくなった場合
      if speller == nil
        unless battler.skill_can_use?(@skill.id)
          # ステップ 6 に移行
          battler.phase = 6
         return
        end
      end
    end
    # SP 消費
    temp = false
    if speller != nil
      for spell in speller
        if spell.current_action.spell_id == 0
              sp_cost = @skill.sp_cost
    if spell.is_actor? and @skill.element_set != []
      
      for i in @skill.element_set
        affinity = spell.affinity(i)
        
        if affinity >= spell.half_spell_cost_is and spell.half_spell_cost_is != 0
          sp_cost /= 2
        end
        
        if affinity >= spell.quarter_spell_cost_is and spell.quarter_spell_cost_is != 0
          sp_cost /= 2
        end

        if affinity <= spell.double_spell_cost_is and spell.double_spell_cost_is != 0
          sp_cost *= 2
        end
        
        if affinity <= spell.quad_spell_cost_is and spell.quad_spell_cost_is != 0
          sp_cost *= 2
        end
      end
    end
          spell.sp -= sp_cost
        else
          sp_cost = $data_skills[spell.current_action.spell_id].sp_cost
          
    if spell.is_actor? and $data_skills[spell.current_action.spell_id].element_set != []
      
      for i in $data_skills[spell.current_action.spell_id].element_set
        affinity = spell.affinity(i)
        
        if affinity >= spell.half_spell_cost_is and spell.half_spell_cost_is != 0
          sp_cost /= 2
        end
        
        if affinity >= spell.quarter_spell_cost_is and spell.quarter_spell_cost_is != 0
          sp_cost /= 2
        end

        if affinity <= spell.double_spell_cost_is and spell.double_spell_cost_is != 0
          sp_cost *= 2
        end
        
        if affinity <= spell.quad_spell_cost_is and spell.quad_spell_cost_is != 0
          sp_cost *= 2
        end
      end
    end
    
          spell.sp -= sp_cost
        end
        # ステータスウィンドウをリフレッシュ
        status_refresh(spell)
      end
    else
      battler.sp -= @skill.sp_cost
      # ステータスウィンドウをリフレッシュ
      status_refresh(battler)
    end
    # アニメーション ID を設定
    battler.anime1 = @skill.animation1_id
    battler.anime2 = @skill.animation2_id
    # コモンイベント ID を設定
    battler.event = @skill.common_event_id
    # 対象側バトラーを設定
    set_target_battlers(@skill.scope, battler)
    # スキルの効果を適用
    for target in battler.target
      if speller != nil
        damage = 0
        effective = false
        state_p = []
        state_m = []
        for spell in speller
          if spell.current_action.spell_id != 0
            @skill = $data_skills[spell.current_action.spell_id]
          end
          effective |= target.skill_effect(spell, @skill)
          if target.damage[spell].class != String
            damage += target.damage[spell]
          elsif effective == true
            effect = target.damage[spell]
          end
          state_p += target.state_p[spell]
          state_m += target.state_m[spell]
          target.damage.delete(spell)
          target.state_p.delete(spell)
          target.state_m.delete(spell)
        end
        if damage != 0
          target.damage[battler] = damage
        elsif effective = true
          target.damage[battler] = effect
        end
        target.state_p[battler] = state_p
        target.state_m[battler] = state_m
      else
        target.skill_effect(battler, @skill)
      end
    end
    if if battler.current_action.spell_id == 0
    if battler.is_actor? and @skill.element_set != []
      for i in @skill.element_set
        battler.element_affinity_adjust(i)
      end
    end
    else
    if battler.is_actor? and $data_skills[spell.current_action.spell_id].element_set != []
      for i in $data_skills[spell.current_action.spell_id].element_set
        battler.element_affinity_adjust(i)
      end
    end
  end
end

    
  end

end
And it should work.
Wow a script that works with the RTAB.
 
Hey can you set them to affect more than one thing?
Like Fire effects ice and earth
And wind and water effect fire
thunder and earth effect water

And things like that?


oh and very kool script.
 
It was requested before:
Code:
  #--------------------------------------------------------------------------
  # Element Affinity
  # Script by Fomar0153
  #--------------------------------------------------------------------------
class Game_Actor < Game_Battler
  #--------------------------------------------------------------------------
  # Constants
  #--------------------------------------------------------------------------
  Elements = [
  {'name'=>'Fire', 'id'=>1, 'opp'=>'Ice', 'opp2'=>'Water'},
  {'name'=>'Ice', 'id'=>2, 'opp'=>'Fire', 'opp2'=>'Water'},
  {'name'=>'Thunder', 'id'=>3, 'opp'=>'Water', 'opp2'=>'Water'},
  {'name'=>'Water', 'id'=>4, 'opp'=>'Thunder', 'opp2'=>'Water'},
  {'name'=>'Earth', 'id'=>5, 'opp'=>'Wind', 'opp2'=>'Water'},
  {'name'=>'Wind', 'id'=>6, 'opp'=>'Earth', 'opp2'=>'Water'},
  {'name'=>'Light', 'id'=>7, 'opp'=>'Darkness', 'opp2'=>'Water'},
  {'name'=>'Darkness', 'id'=>8, 'opp'=>'Light', 'opp2'=>'Water'}
  ]
  # The maximum you can be aligned with an element
  Max_Affinity = 1000
  # The minimum you can be aligned with an element
  Min_Affinity = -1000
  # How much alignment you gain with the element used
  Element_Usage = 1
  # How much the opposing alignment loses
  Opposite_Cost = 1
  # How much all other alignments not linked to the used alignment lose
  All_Cost = 0
  # How much you must be aligned with an element for half spell cost
  # Note: 0 means the feature won't happen
  Half_Spell_Cost = 250
  # How much you must be aligned with an element for quarter spell cost
  # Note: 0 means the feature won't happen
  Quarter_Spell_Cost = 750
  # How much you must be aligned with an element to do double damage
  # Note: 0 means the feature won't happen
  Double_Spell_Damage = 500
  # How much you must be aligned with an element to do quadruple damage
  # Note: 0 means the feature won't happen
  Quad_Spell_Damage = 1000
  # How little you must be aligned with an element for double spell cost
  # Note: 0 means the feature won't happen
  Double_Spell_Cost = -250
  # How little you must be aligned with an element for quardruple spell cost
  # Note: 0 means the feature won't happen
  Quad_Spell_Cost = -750
  # How little you must be aligned with an element to do half damage
  # Note: 0 means the feature won't happen
  Half_Spell_Damage = -500
  # How little you must be aligned with an element to do quarter damage
  # Note: 0 means the feature won't happen
  Quarter_Spell_Damage = -1000
  # If set to true your allignments will positively affect your elemental resistences (> 0)
  Affect_Resistences_Pos = true
  # If set to true your allignments will negatively affect your elemental resistences (< 0)
  Affect_Resistences_Neg = true
  #--------------------------------------------------------------------------
  # End Of Constants
  #--------------------------------------------------------------------------
  alias old_setup setup
  def setup(actor_id)
    old_setup(actor_id)
    @element_affinity = []
    for i in 0...Elements.size
      @element_affinity.push(0)
    end
  end
  
  def is_element?(element)
    for i in 0...Elements.size
      hash = Elements[i]
      if hash['id'] == element
        return true
      end
    end
    return false
  end
  
  def element_affinity_adjust(element)
    if is_element?(element)
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['id'] == element
          k = i
          opp_name = hash['opp']
          opp_name2 = hash['opp2']
        end
      end
      
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['name'] = opp_name
          j = i
        end
      end
      
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['name'] = opp_name2
         l = i
        end
      end
      
      if @element_affinity[k] < Max_Affinity
        @element_affinity[k] += Element_Usage
      end
      
      if @element_affinity[k] > Max_Affinity
        @element_affinity[k] = Element_Usage
      end
      
      
      if @element_affinity[j] > Min_Affinity
        @element_affinity[j] -= Opposite_Cost
      end
      
      if @element_affinity[j] < Min_Affinity
        @element_affinity[j] = Opposite_Cost
      end
      
      if @element_affinity[l] > Min_Affinity
        @element_affinity[l] -= Opposite_Cost
      end
      
      if @element_affinity[l] < Min_Affinity
        @element_affinity[l] = Opposite_Cost
      end
      
      unless All_Cost == 0
        for i in 0...Elements.size
          Elements[i] -= All_Cost
        end
        Elements[k] += All_Cost
        Elements[j] += All_Cost
        Elements[l] += All_Cost
      end
      
    end
  end
    
  def affinity(element)
    if is_element?(element)
      for i in 0...Elements.size
        hash = Elements[i]
        if hash['id'] == element
          return @element_affinity[i]
        end
      end
    end
    return 0
  end
  
  def element_rate(element_id)
    # Get values corresponding to element effectiveness
    table = [0,200,150,100,50,0,-100]
    result = table[$data_classes[@class_id].element_ranks[element_id]]
    # For each 1% of max affinity you get +2 resistence
    # meaning at 50% you take no damage and at 100%
    # you absorb the damage (assuming you start at C (100))
    if is_element?(element_id)
      x = affinity(element_id)
      x /= Max_Affinity
      x *= 200
      if x > 0 and Affect_Resistences_Pos == true
        result -= x
      end
      if x < 0 and Affect_Resistences_Neg == true
        result -= x/2
      end
    end
    # If this element is protected by armor, then it's reduced by half
    for i in [@armor1_id, @armor2_id, @armor3_id, @armor4_id]
      armor = $data_armors[i]
      if armor != nil and armor.guard_element_set.include?(element_id)
        result /= 2
      end
    end
    # If this element is protected by states, then it's reduced by half
    for i in @states
      if $data_states[i].guard_element_set.include?(element_id)
        result /= 2
      end
    end
    # End Method
    return result
  end
    
  def half_spell_cost_is
    return Half_Spell_Cost
  end
  
  def quarter_spell_cost_is
    return Quarter_Spell_Cost
  end
  
  def double_spell_damage_is
    return Double_Spell_Damage
  end
  
  def quad_spell_damage_is
    return Quad_Spell_Damage
  end
    
  def double_spell_cost_is
    return Double_Spell_Cost
  end
  
  def quad_spell_cost_is
    return Quad_Spell_Cost
  end
  
  def half_spell_damage_is
    return Half_Spell_Damage
  end
  
  def quarter_spell_damage_is
    return Quarter_Spell_Damage
  end
  
  def is_actor?
    return true
  end
  
end





class Game_Enemy < Game_Battler
  def is_actor?
    return false
  end
end





class Game_Battler
  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)
      
      # For you merging this only the code in this method that is new
      if user.is_actor? and skill.element_set != []
        
        for i in skill.element_set
          affinity = user.affinity(i)
          
          if affinity >= user.double_spell_damage_is and user.double_spell_damage_is != 0
            rate *= 2
          end
          
          if affinity >= user.quad_spell_damage_is and user.quad_spell_damage_is != 0
            rate *= 2
          end
          
          if affinity <= user.half_spell_damage_is and user.half_spell_damage_is != 0
            rate /= 2
          end
          
          if affinity <= user.quarter_spell_damage_is and user.quarter_spell_damage_is != 0
            rate /= 2
          end
          
        end
      end
      
      # 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
end



class Window_Skill < Window_Selectable
  
  def draw_item(index)
    skill = @data[index]
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + index % 2 * (288 + 32)
    y = index / 2 * 32
    rect = Rect.new(x, y, self.width / @column_max - 32, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    bitmap = RPG::Cache.icon(skill.icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
    self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
    sp_cost = skill.sp_cost
    
    unless skill.element_set == []
      for i in skill.element_set
        affinity = @actor.affinity(i)
        if affinity >= @actor.half_spell_cost_is and @actor.half_spell_cost_is != 0
          sp_cost /= 2
        end
        
        if affinity >= @actor.quarter_spell_cost_is and @actor.quarter_spell_cost_is != 0
          sp_cost /= 2
        end

        if affinity <= @actor.double_spell_cost_is and @actor.double_spell_cost_is != 0
          sp_cost *= 2
        end
        
        if affinity <= @actor.quad_spell_cost_is and @actor.quad_spell_cost_is != 0
          sp_cost *= 2
        end
        
      end
    end
    
    
    self.contents.draw_text(x + 232, y, 48, 32, sp_cost.to_s, 2)
  end
  
end





class Scene_Battle
  def make_skill_action_result
    # Get skill
    @skill = $data_skills[@active_battler.current_action.skill_id]
    # If not a forcing action
    unless @active_battler.current_action.forcing
      # If unable to use due to SP running out
      unless @active_battler.skill_can_use?(@skill.id)
        # Clear battler being forced into action
        $game_temp.forcing_battler = nil
        # Shift to step 1
        @phase4_step = 1
        return
      end
    end
    # Use up SP
    sp_cost = @skill.sp_cost
    if @active_battler.is_actor? and @skill.element_set != []
      
      for i in @skill.element_set
        affinity = @active_battler.affinity(i)
        
        if affinity >= @active_battler.half_spell_cost_is and @active_battler.half_spell_cost_is != 0
          sp_cost /= 2
        end
        
        if affinity >= @active_battler.quarter_spell_cost_is and @active_battler.quarter_spell_cost_is != 0
          sp_cost /= 2
        end

        if affinity <= @active_battler.double_spell_cost_is and @active_battler.double_spell_cost_is != 0
          sp_cost *= 2
        end
        
        if affinity <= @active_battler.quad_spell_cost_is and @active_battler.quad_spell_cost_is != 0
          sp_cost *= 2
        end
      end
    end
    @active_battler.sp -= sp_cost
    # Refresh status window
    @status_window.refresh
    # Show skill name on help window
    @help_window.set_text(@skill.name, 1)
    # Set animation ID
    @animation1_id = @skill.animation1_id
    @animation2_id = @skill.animation2_id
    # Set command event ID
    @common_event_id = @skill.common_event_id
    # Set target battlers
    set_target_battlers(@skill.scope)
    # Apply skill effect
    for target in @target_battlers
      target.skill_effect(@active_battler, @skill)
    end
    
    if @active_battler.is_actor? and @skill.element_set != []
      for i in @skill.element_set
        @active_battler.element_affinity_adjust(i)
      end
    end
    
    
  end
  
end
And no I do not hate water it was control v's fault.
 
Excellent Script, Fomar. Really usefull if you're trying to create some "elemental" in your game. Nice job! Is there any possiblity to get the affinity higher sometimes and lower other time? Ex: If i use a spell (Water affinity) i'll get water affinity and fire "problem". Is it possible? Thanks.
 
Does this help you:
Code:
class Game_Battler
  alias element_skill skill_effect
  def skill_effect(user, skill)
    
    if skill.id == 1 # Let's call this Water Affinity
      user.element_affinity[3] += 5
      # And now to destroy the fire element
      user.element_affinity[0] -= 5
    end
    
    return element_skill(user, skill)
  end
end

class Game_Actor < Game_Battler
  attr_accessor :element_affinity
end
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top