Help - Search - Members - Calendar
Full Version: MP Death and reviving items.
RPG RPG Revolution Forums > Scripting > Script Development and Support
heisenman
*namedrops scripter with actual skill while typing out script introduction*

Hello Kread-EX.

...



I've sort of put stuff together to make an MP Death script as an add-on for Melody. It works for what it was is intended to do.
The problem is that if I use a reviving item that only restores HP or MP, the actor will invariably only recover 1 HP and 1 MP regardless of the values in the Recovery Effect fields in the database.
I don't think it's a difficult thing but I don't know where to look anymore in the scripts.

spoiler tag is my friend


CODE
#==============================================================================
# MP Death v 1.0 - YEM Add-On
#------------------------------------------------------------------------------
# Description:
# Actors and enemies will be flagged with Incapacitated status if their MP is
# brought down to 0 similarly to what happens with HP.
# Upon death BOTH HP and MP will be brought down to 0.
#==============================================================================

#==============================================================================
# ** Game_Battler
#------------------------------------------------------------------------------
#  Summary of changes:
# Battler dies if MP reach 0.
# Return dead? if MP reach 0.
# Incapacitated state also brings actors MP down to 0.
# Revived actors are brought back to life with 1 MP at minimum.
# Cannot perform skills that bring MP down to 0. MP suicide is bad.
# MP poisoning can kill.
#==============================================================================

class Game_Battler
  #--------------------------------------------------------------------------
  # * Change MP
  #--------------------------------------------------------------------------
  def mp=(mp)
    @mp = [[mp, maxmp].min, 0].max
    if @mp == 0 and not state?(1) and not @immortal                   # ADDED
      add_state(1)                # Add incapacitated (state #1)      # ADDED
      @added_states.push(1)                                           # ADDED
    elsif @mp > 0 and state?(1)                                       # ADDED
      remove_state(1)             # Remove incapacitated (state #1)   # ADDED
      @removed_states.push(1)                                         # ADDED
    end                                                               # ADDED
  end
  #--------------------------------------------------------------------------
  # * Determine Incapacitation
  #--------------------------------------------------------------------------
  def dead?
#   return (not @hidden and @hp == 0 and not @immortal)
    return (not @hidden and (@hp == 0 or @mp == 0) and not @immortal) # EDITED
  end
  #--------------------------------------------------------------------------
  # * Add State
  #--------------------------------------------------------------------------
  def add_state(state_id)
    state = $data_states[state_id]        # Get state data
    return if state == nil                # Is data invalid?
    return if state_ignore?(state_id)     # Is it a state should be ignored?
    unless state?(state_id)               # Is this state not added?
      unless state_offset?(state_id)      # Is it a state should be offset?
        @states.push(state_id)            # Add the ID to the @states array
      end
      if state_id == 1                    # If it is incapacitated (state 1)
        @hp = 0                           # Change HP to 0
        @mp = 0                           # Change MP to 0            # ADDED
      end
      unless inputable?                   # If the character cannot act
        @action.clear                     # Clear battle actions
      end
      for i in state.state_set            # Take the [States to Cancel]
        remove_state(i)                   # And actually remove them
        @removed_states.delete(i)         # It will not be displayed
      end
      sort_states                         # Sort states with priority
    end
    @state_turns[state_id] = state.hold_turn    # Set the number of turns
  end
  #--------------------------------------------------------------------------
  # * Remove State
  #--------------------------------------------------------------------------
  def remove_state(state_id)
    return unless state?(state_id)        # Is this state not added?
#   if state_id == 1 and @hp == 0         # If it is incapacitated (state 1)
    if state_id == 1 and (@hp == 0 or @mp == 0)                       # EDITED
      @hp = 1                             # Change HP to 1
      @mp = 1                             # Change MP to 1            # ADDED
    end
    @states.delete(state_id)              # Remove the ID from the @states
    @state_turns.delete(state_id)         # Remove from the @state_turns
  end
  
  #--------------------------------------------------------------------------
  # new method: custom_skill_costs
  #--------------------------------------------------------------------------
  def custom_skill_costs(skill, type)
    hash = YEM::BATTLE_ENGINE::SKILL_SETTINGS
    calc_cost = 0; use_icon = 0; suffix = "%s"; text_cost = "0"
    colour = hash[:mp_colour]; font_size = hash[:mp_size]
    can_use = false
    perform = (type == :perform)
    case skill.skill_cost
    
    #------------------------------------------------------------------------
    # <cost: x mp>
    #------------------------------------------------------------------------
    when /(\d+)[ ](?:MP|SP)/i
      #---
      calc_cost = $1.to_i
      calc_cost = apply_skill_cost_changes(skill, calc_cost, "MP")
      calc_cost /= 2 if half_mp_cost
      #---
      text_cost = calc_cost.to_s
      use_icon = Icon.mp_cost
      suffix = hash[:mp_suffix]
      colour = hash[:mp_colour]
      font_size = hash[:mp_size]
#     can_use = @mp >= calc_cost
      can_use = @mp > calc_cost                                       # EDITED
      @mp -= calc_cost if perform
      
    #------------------------------------------------------------------------
    # <cost: x% maxmp>
    #------------------------------------------------------------------------
    when /(\d+)([%%])[ ](?:MP|SP|MAXMP|MAXSP)/i
      #---
      calc_cost = maxmp * $1.to_i / 100
      calc_cost = apply_skill_cost_changes(skill, calc_cost, "MP")
      calc_cost /= 2 if half_mp_cost
      #---
      text_cost = calc_cost.to_s
      use_icon = Icon.mp_cost
      suffix = hash[:mp_suffix]
      colour = hash[:mp_colour]
      font_size = hash[:mp_size]
#     can_use = @mp >= calc_cost
      can_use = @mp > calc_cost                                       # EDITED
      @mp -= calc_cost if perform
      
    #------------------------------------------------------------------------
    # <cost: x hp>
    #------------------------------------------------------------------------
    when /(\d+)[ ](?:HP|LP)/i
      #---
      calc_cost = $1.to_i
      calc_cost = apply_skill_cost_changes(skill, calc_cost, "HP")
      #---
      text_cost = calc_cost.to_s
      use_icon = Icon.hp_cost
      suffix = hash[:hp_suffix]
      colour = hash[:hp_colour]
      font_size = hash[:hp_size]
      can_use = @hp > calc_cost
      @hp -= calc_cost if perform
      
    #------------------------------------------------------------------------
    # <cost: x% maxhp>
    #------------------------------------------------------------------------
    when /(\d+)([%%])[ ](?:HP|LP|MAXHP|MAXLP)/i
      #---
      calc_cost = maxhp * $1.to_i / 100
      calc_cost = apply_skill_cost_changes(skill, calc_cost, "HP")
      #---
      text_cost = calc_cost.to_s
      use_icon = Icon.hp_cost
      suffix = hash[:hp_suffix]
      colour = hash[:hp_colour]
      font_size = hash[:hp_size]
      can_use = @hp > calc_cost
      @hp -= calc_cost if perform
      
    #------------------------------------------------------------------------
    # <cost: x gold>
    #------------------------------------------------------------------------
    when /(\d+)[ ](?:GOLD|money)/i
      #---
      if self.actor?
        calc_cost = $1.to_i
        calc_cost = apply_skill_cost_changes(skill, calc_cost, "GOLD")
      else
        calc_cost = 0
      end
      #---
      text_cost = calc_cost.to_s
      use_icon = Icon.gold_cost
      suffix = hash[:gold_suffix]
      colour = hash[:gold_colour]
      font_size = hash[:gold_size]
      can_use = $game_party.gold > calc_cost
      $game_party.lose_gold(calc_cost) if perform
      
    #------------------------------------------------------------------------
    # <cost: x% gold>
    #------------------------------------------------------------------------
    when /(\d+)([%%])[ ](?:GOLD|money)/i
      #---
      if self.actor?
        calc_cost = $game_party.gold * $1.to_i / 100
        calc_cost = apply_skill_cost_changes(skill, calc_cost, "GOLD")
      else
        calc_cost = 0
      end
      #---
      text_cost = $1.to_s
      use_icon = Icon.gold_cost
      suffix = hash[:gold_suffixp]
      colour = hash[:gold_colour]
      font_size = hash[:gold_size]
      can_use = $game_party.gold > calc_cost
      $game_party.lose_gold(calc_cost) if perform
      
    #------------------------------------------------------------------------
    # <cost: x rage>
    #------------------------------------------------------------------------
    when /(\d+)[ ]RAGE/i
      #---
      calc_cost = $1.to_i
      calc_cost = apply_skill_cost_changes(skill, calc_cost, "RAGE")
      #---
      text_cost = calc_cost.to_s
      use_icon = Icon.rage_cost
      suffix = hash[:rage_suffix]
      colour = hash[:rage_colour]
      font_size = hash[:rage_size]
      @rage = 0 if @rage == nil
      can_use = @rage >= calc_cost
      @rage -= calc_cost if perform
      
    #------------------------------------------------------------------------
    # <cost: x item:y>
    #------------------------------------------------------------------------
    when /(\d+)[ ]ITEM:(\d+)/i
      #---
      calc_cost = self.enemy? ? 0 : $1.to_i
      name = $data_items[$2.to_i].name.upcase
      calc_cost = apply_skill_cost_changes(skill, calc_cost, name)
      #---
      item = $data_items[$2.to_i]
      text_cost = calc_cost.to_s
      use_icon = item.icon_index
      can_use = $game_party.item_number(item) >= calc_cost
      if perform and self.actor?
        calc_cost.times do; $game_party.consume_item(item); end
      end
      
    #------------------------------------------------------------------------
    # Stop editting past this point.
    #------------------------------------------------------------------------
    end
    use_icon = skill.cost_icon if skill.cost_icon != nil
    case type
    when :perform;   return
    when :calc_cost; return calc_cost
    when :text_cost; return text_cost
    when :can_use;   return can_use
    when :use_icon;  return use_icon
    when :suffix;    return suffix
    when :font_size; return font_size
    when :colour;    return colour
    end
  end
  
  #--------------------------------------------------------------------------
  # new method: perform_slip_effect
  #--------------------------------------------------------------------------
  def perform_slip_effect(state)
    return if state == nil
    return unless exist?
    return unless state.slip_damage
    hp_dmg = 0; mp_dmg = 0
    hash = state.slip_effect
    #---
    hp_dmg += maxhp * hash[:hp_degen_per] / 100 if hash [:hp_degen_per] != nil
    hp_dmg += hash[:hp_degen_set] if hash[:hp_degen_set] != nil
    hp_dmg *= stack(state) if hp_dmg != 0
    mp_dmg += maxmp * hash[:mp_degen_per] / 100 if hash [:mp_degen_per] != nil
    mp_dmg += hash[:mp_degen_set] if hash[:mp_degen_set] != nil
    mp_dmg *= stack(state) if mp_dmg != 0
    #---
    hp_dmg = [hp_dmg, @hp - 1].min
    hp_dmg = 0 if anti_hp_regen if hp_dmg < 0
    hp_dmg = 0 if anti_hp_degen if hp_dmg > 0
    mp_dmg = 0 if anti_mp_regen if mp_dmg < 0
    mp_dmg = 0 if anti_mp_degen if mp_dmg > 0
    #---
    if hp_dmg != 0
      @hp = [[@hp - hp_dmg, maxhp].min, 0].max
      if hp_dmg > 0
        rules = "HP_DMG"
        value = hp_dmg
        sprint = YEM::BATTLE_ENGINE::POPUP_SETTINGS[:hp_dmg]
      else
        rules = "HP_HEAL"
        value = -hp_dmg
        sprint = YEM::BATTLE_ENGINE::POPUP_SETTINGS[:hp_heal]
      end
      create_popup(value, rules) if $scene.is_a?(Scene_Battle)
    end
    if mp_dmg != 0
      @mp = [[@mp - mp_dmg, maxmp].min, 0].max
      if mp_dmg > 0
        rules = "MP_DMG"
        value = mp_dmg
        sprint = YEM::BATTLE_ENGINE::POPUP_SETTINGS[:mp_dmg]
      else
        rules = "MP_HEAL"
        value = -mp_dmg
        sprint = YEM::BATTLE_ENGINE::POPUP_SETTINGS[:mp_heal]
      end
      value = sprintf(sprint, value)
      create_popup(value, rules) if $scene.is_a?(Scene_Battle)
    end    
    if @hp == 0 or @mp == 0; add_state(1); perform_collapse; end      # ADDED
  end
  
end # Game_Battler

#===============================================================================
# Scene_Battle
#------------------------------------------------------------------------------
#  Summary of changes:
# In Test Mode F8 will bring MP down to 1 to avoid MP Death.
#===============================================================================

class Scene_Battle < Scene_Base
  
  #--------------------------------------------------------------------------
  # overwrite method: update_actor_command_selection
  #--------------------------------------------------------------------------
  def update_actor_command_selection
    if @selected_battler.battle_command_index != @actor_command_window.index
      @selected_battler.battle_command_index = @actor_command_window.index
      if (dtb? or ctb?) and !@selected_battler.auto_battle
        $game_troop.clear_ctb_cache
        last_action = @selected_battler.action.clone
        case @actor_command_window.item
        when :attack;  @selected_battler.action.set_attack
        when :guard;   @selected_battler.action.set_guard
        else
          item = @actor_command_window.item
          array = YEM::BATTLE_ENGINE::SKILL_COMMANDS[item]
          if array != nil
            skill = $data_skills[array[0]]
            @selected_battler.action.set_skill(skill.id) if skill != nil
          end
        end
        make_action_orders
        @selected_battler.action = last_action
      end
      make_action_orders if @selected_battler.auto_battle and (dtb? or ctb?)
    end
    #---
    if Input.trigger?(Input::B)
      Sound.play_cancel
      cancel_action
    elsif Input.trigger?(Input::C)
      actor_command_case
    elsif Input.repeat?(Input::LEFT)
      Sound.play_cursor
      prior_actor
    elsif Input.repeat?(Input::RIGHT)
      Sound.play_cursor
      next_actor
    elsif Input.trigger?(Input::L)
      Sound.play_cursor
      @status_shortcut_index = @status_window.index
      start_party_command_selection
    elsif Input.trigger?(Input::R)
      Sound.play_cursor
      @status_shortcut_index = @status_window.index
      start_confirm_command_selection
    #--- Debug Shortcuts ---
    elsif ($TEST or $BTEST) and Input.trigger?(Input::F5)
      Sound.play_recovery
      @selected_battler.recover_all
      @selected_battler.gain_rage(@selected_battler.max_rage)
    elsif ($TEST or $BTEST) and Input.trigger?(Input::F6)
      Sound.play_use_item
      if Input.press?(Input::SHIFT)
        @selected_battler.hp += @selected_battler.maxhp/5
      else
        @selected_battler.hp = @selected_battler.maxhp
      end
    elsif ($TEST or $BTEST) and Input.trigger?(Input::F7)
      Sound.play_use_skill
      if Input.press?(Input::SHIFT)
        @selected_battler.mp += @selected_battler.maxmp/5
        @selected_battler.gain_rage(@selected_battler.max_rage/5)
      else
        @selected_battler.mp = @selected_battler.maxmp
        @selected_battler.gain_rage(@selected_battler.max_rage)
      end
    elsif ($TEST or $BTEST) and Input.trigger?(Input::F8)
      Sound.play_actor_damage
      if Input.press?(Input::SHIFT)
        @selected_battler.hp -= @selected_battler.maxhp/4 + 4
        @selected_battler.perform_collapse
      elsif Input.press?(Input::CTRL)
        @selected_battler.mp -= @selected_battler.maxmp/4 + 4
        @selected_battler.lose_rage(@selected_battler.max_rage/4)
      else
        @selected_battler.hp = 1
#       @selected_battler.mp = 0
        @selected_battler.mp = 1                                      # EDITED
        @selected_battler.lose_rage(@selected_battler.max_rage)
      end
    elsif ($TEST or $BTEST) and Input.press?(Input::CTRL) and
    Input.press?(Input::SHIFT)
      for enemy in $game_troop.existing_members
        enemy.hp = 0
        enemy.perform_collapse
      end
    end
  end
  
end # Scene_Battle





Also, the code is full of junk. I fear it has to do with my inability to understand aliases?
Pillanious
Off the top of my head, I'd say this:

"# if state_id == 1 and @hp == 0 # If it is incapacitated (state 1)
if state_id == 1 and (@hp == 0 or @mp == 0) # EDITED
@hp = 1 # Change HP to 1
@mp = 1 # Change MP to 1 # ADDED"

is your problem. It's setting HP/MP to 1, regardless of the item's healing properties once the state is removed.
heisenman
The "@hp = 1" bit is part of the original code (Game_Battler 497), as in if you're revived, your HP have to forcefully be at least at 1 point.
My guess was that if I copied the same line, but for MP, reviving would automatically bring your MP to 1 at minimum, because death is either upon HP or MP depleting, so having any of those parameters below 1 would still flag you as dead.

Though if I have an item that revives, heals 10 HP and 5 MP, it works normally and dead actors recover said amount of HP and MP, so "@hp = 1/@mp = 1" are not permanent things.
The problem arises only when the reviving item just heals one parameter.
Night_Runner
I changed the 2 lines Pillanious mentioned to:
CODE
      @hp = [1, @hp].max                  # Change HP to 1
      @mp = [1, @mp].max                  # Change MP to 1            # ADDED

So far it seems to work smile.gif
heisenman
I changed it and now it works, but only when the reviving item heals MP only. It still has the same problem when it heals HP only.
Weird...

It works properly both ways in your project?

Thanks fot your help (:
Night_Runner
  • Zero HP & zero MP: Works fine, gives the actor 1 HP & 1 MP
  • Zero HP & non-zero MP: Works fine
  • Non-zero HP & non-zero MP: Works fine
  • Non-zero HP & zero MP: Doesn't work, so you need to set the MP value to at least 1, and this seems to solve it happy.gif


Seems like a weird bug, but the work-around seems simple enough.
heisenman
Yup the workaround is really quite simple.
Still, I thought this was interesting enough to submit in Script Submissions but didn't want to knowing there's a bug.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2013 Invision Power Services, Inc.