じ☆ve冰风 发表于 2026-8-2 12:30:19

Layered States

Credits: Harosata

Terms of Use:Free To Use, though a spot on the credit roll would be nice.

Here's a script if you want to layer some of your states like a sandwich.Think of this like Himework's Permanent States and Neon Black's Stacking States having a well-behaved baby.

Okay, let me give you a better example.Barrier States (tagged with <LayerState>) will go into one array while your normal states do their own business.The latest layered state plus other layered <LayerActive> stateswill give you a multiplicative boost, though only the latest layered state will be affected by sources of removals.You can also add on other tags to change when you can apply these states, for example, adding on Level 2 Barriers when you have Level 1 Barriers present.Also features <LayerPurge> if you care little about the stacking feature.

While this script is affected by adding/removing states normally, the Layered States were designed not to be removed on Death (unless you use <LayerPurgeDeath>).

                Ruby:       
module DL
module LAYERSTATE
    MAXLAYER = 10
   
=begin
#==============================================================================
** Layered States
Author: Harosata
------------------------------------------------------------------------------
Ever want to place layers upon layers of protection spells?
Any State you notetag with <LayerState> will head into a shared array where the
latest state plus any <LayerActive> states will be effective.Damage will remove
the latest state, though you can place <LayerRemove: n> on a Skill
to remove more layers at once!Set MAXLAYER to the max amount of Layered States.
------------------------------------------------------------------------------
You can also tag both layered and regular states to limit when they apply.
Use <ApplyWhen: state_ids> once you have a required state or
<RestrictWhen: state_ids> to stop adding more when you have that state.
Use <ApplyCurrent: state_ids> to add a state or <RestrictCurrent: state_ids>
to prevent a state based on the latest layered state. You can also place
<FinalLayer> to stop adding more Layered States!
------------------------------------------------------------------------------
Finaly, you can place <LayerPurge> on a layered state or skill if you want
to remove all the involved Layered States when that state is removed.
Or you can place <LayerPurgeDeath> on a state if you want them gone when you die.
------------------------------------------------------------------------------
And also, there are a few methods for battlers if you need some information.
.layer_state_count can count your layered states or used with a (state_id)
for a specific counter..layer_state_current will return the id of the latest
layered state..layer_state_clear will clean up your layered states quickly!
------------------------------------------------------------------------------
=end
    #use commas on Restrict/Apply for more states.
    Regex1 = /<LayerState>/i #Marks this state for Layer Array
    Regex2 = /<RestrictWhen:\s*(.*)\s*>/i #Cannot add when one of these states is present.
    Regex2a = /<ApplyWhen:\s*(.*)\s*>/i #Add only when one of these states present
    Regex3 = /<ApplyCurrent:\s*(.*)\s*>/i #add if the current layer is one of these.
    Regex3a = /<RestrictCurrent:\s*(.*)\s*>/i #don't add if the current layer is not one of these.
    Regex4 = /<LayerRemove:\s*(\d+)\s*>/i #remove this many layers with the skill
    Regex5 = /<LayerPurge>/i #Remove states regardless of position
    Regex5a = /<LayerPurgeDeath>/i #remove states on death regardless of position
    Regex6 = /<LayerActive>/i #remove states on death regardless of position
    Regex7 = /<FinalLayer>/i #No other layered states can be applied after this.
end
end

module RPG
class BaseItem
   
    def layered?
      res = self.note.match(DL::LAYERSTATE::Regex1)
      return res
    end
   
    def restrict_when
      if @note =~ DL::LAYERSTATE::Regex2
      ints = []
      for x in $1.split(",")
          ints.push(x.to_i)
      end
      return ints
      else
      return []
      end
    end
    def apply_when
      if @note =~ DL::LAYERSTATE::Regex2a
      ints = []
      for x in $1.split(",")
          ints.push(x.to_i)
      end
      return ints
      else
      return []
      end
    end
      
    def current_apply
      if @note =~ DL::LAYERSTATE::Regex3
      ints = []
      for x in $1.split(",")
          ints.push(x.to_i)
      end
      return ints
      else
      return []
      end
    end
    def current_restrict
      if @note =~ DL::LAYERSTATE::Regex3a
      ints = []
      for x in $1.split(",")
          ints.push(x.to_i)
      end
      return ints
      else
      return []
      end
    end
   
    def layer_remove
      bob = 1
      res = self.note.match(DL::LAYERSTATE::Regex4)
      bob = res.to_i if res
      return bob
    end
    def layer_purge
      res = self.note.match(DL::LAYERSTATE::Regex5)
      return res
    end
    def layer_purge_death
      res = self.note.match(DL::LAYERSTATE::Regex5a)
      return res
    end
    def active_layer?
      res = self.note.match(DL::LAYERSTATE::Regex6)
      return res
    end
    def final_layer?
      res = self.note.match(DL::LAYERSTATE::Regex7)
      return res
    end
   
end
end


class Game_Battler < Game_BattlerBase
alias :dl_layer_initialize :initialize
def initialize
    @layer_states ||= []
    @layer_turns ||= []
    dl_layer_initialize
end

def feature_objects
    layer_states + super
end

def layer_states(pure = false)
    return @layer_states.collect {|i| $data_states} if pure
    bob = @layer_states.select{|i| $data_states.active_layer?}
    bob = bob.collect{|i| $data_states}
    bob << $data_states[@layer_states.last] if @layer_states.count > 0 and !$data_states[@layer_states.last].active_layer?
    return bob
end

alias :dl_layer_die :die
def die
    dl_layer_die
    @layer_states.count.times.each do |i|
      if $data_states[@layer_states].layer_purge_death
      @layer_states = nil
      @layer_turns = nil
      end
    end
    @layer_states = @layer_states.compact
    @layer_turns = @layer_turns.compact
end

def layer_states_apply(state_id, full = true)
    if full
      return false if @layer_states.count >= DL::LAYERSTATE::MAXLAYER
      return false if layer_states(true).any? {|s| s.final_layer?}
      return false if states.any? {|s| s.final_layer?}
    end
    bob = $data_states
    sam = @states + @layer_states
    return false ifbob.restrict_when.count > 0 and bob.restrict_when.any? {|s| sam.include?(s)}
    return true ifbob.apply_when.count > 0 and bob.apply_when.any? {|s| sam.include?(s)}
    return false ifbob.current_restrict.count > 0 and @layer_states.count > 0 and bob.current_restrict.any? {|s| @layer_states.last == s}
    return true ifbob.current_apply.count > 0 and @layer_states.count > 0 and bob.current_apply.any?{|s| @layer_states.last == s}
    return (bob.apply_when.count > 0or bob.current_apply.count > 0 ) ? false : true
end

alias :dl_layer_remove_battle_states :remove_battle_states
def remove_battle_states
    dl_layer_remove_battle_states
    layer_states(true).reverse.each do |state|
      state.remove_at_battle_end ? remove_state(state.id) : break
    end
    bob = []
    layer_states(true).each do |s|
      if s.layer_purge and s.remove_at_battle_end
      bob << s.id
      end
    end
    bob = bob.uniq
    if bob.count > 0
      @layer_states.count.times.each do |i|
      @layer_turns = nil if bob.include?(@layer_states)
      @layer_states = nil if bob.include?(@layer_states)
      end
      @layer_states = @layer_states.compact
      @layer_turns = @layer_turns.compact
    end
end

def item_effect_test(user, item, effect)
    case effect.code
    when EFFECT_RECOVER_HP
      hp < mhp || effect.value1 < 0 || effect.value2 < 0
    when EFFECT_RECOVER_MP
      mp < mmp || effect.value1 < 0 || effect.value2 < 0
    when EFFECT_ADD_STATE
      $data_states.layered? ? (layer_states_apply(effect.data_id)) : (!state?(effect.data_id) and layer_states_apply(effect.data_id, false))
    when EFFECT_REMOVE_STATE
      if @layer_states.count > 0 and $data_states.layered?
      return true if @layer_states.include?(effect.data_id) and (item.layer_purge or $data_states.layer_purge)
      return true if @layer_states.last == effect.data_id
      return false
      else
      return state?(effect.data_id)
      end
    when EFFECT_ADD_BUFF
      !buff_max?(effect.data_id)
    when EFFECT_ADD_DEBUFF
      !debuff_max?(effect.data_id)
    when EFFECT_REMOVE_BUFF
      buff?(effect.data_id)
    when EFFECT_REMOVE_DEBUFF
      debuff?(effect.data_id)
    when EFFECT_LEARN_SKILL
      actor? && !skills.include?($data_skills)
    else
      true
    end
end

alias :dl_layer_add_state :add_state
def add_state(state_id)
    if layer_state_addable?(state_id)
      if layer_states_apply(state_id)
      add_new_layer_state(state_id)
      @result.added_states.push(state_id)
      end
    elsif layer_states_apply(state_id, false)
      dl_layer_add_state(state_id)
    end
end

def add_new_layer_state(state_id)
    bob = $data_states
    @layer_states.push(state_id)
    @layer_turns.push(.max), bob.steps_to_remove])
    on_restrict if restriction > 0
    refresh
end

def layer_state_addable?(state_id)
    $data_states && $data_states.layered? && !state_resist?(state_id)
end

alias :dl_layer_update_state_turns :update_state_turns
def update_state_turns
    dl_layer_update_state_turns
    if @layer_states.count > 0
      @layer_turns.last -= 1 if @layer_turns.last > 0
    end
end

alias :dl_layer_remove_state :remove_state
def remove_state(state_id)
    if @layer_states.count > 0
      if @layer_states.include?(state_id) and $data_states.layer_purge
      @layer_states.count.times.each do |i|
          @layer_turns = nil if@layer_states == state_id
          @layer_states = nil if@layer_states == state_id
      end
      @layer_states = @layer_states.compact
      @layer_turns = @layer_turns.compact
      refresh
      @result.removed_states.push(state_id).uniq!
      elsif @layer_states.last == state_id
      @layer_states.pop
      @layer_turns.pop
      refresh
      @result.removed_states.push(state_id)
      end
    else
      dl_layer_remove_state(state_id)
    end
end

alias :dl_layer_remove_states_auto :remove_states_auto
def remove_states_auto(timing)
    dl_layer_remove_states_auto(timing)
    if @layer_states.count > 0
      if @layer_turns.last == 0 and $data_states[@layer_states.last].auto_removal_timing == timing
      remove_state(@layer_states.last)
      end
    end
end

alias :dl_layer_remove_states_by_damage :remove_states_by_damage
def remove_states_by_damage
    dl_layer_remove_states_by_damage
    if @layer_states.count > 0
      remove_state(@layer_states.last) if $data_states[@layer_states.last].remove_by_damage && rand(100) < $data_states[@layer_states.last].chance_by_damage
    end
end

alias :dl_layer_item_effect_remove_state :item_effect_remove_state
def item_effect_remove_state(user, item, effect)
    if $data_states.layered?
      if ($data_states.layer_purge or item.layer_purge)
      if @layer_states.include?(effect.data_id) and rand < effect.value1
          @layer_states.count.times.each do |i|
            @layer_turns = nil if@layer_states == effect.data_id
            @layer_states = nil if@layer_states == effect.data_id
          end
          @layer_states = @layer_states.compact
          @layer_turns = @layer_turns.compact
          refresh
          @result.removed_states.push(effect.data_id).uniq!
          @result.success = true
      end
      else
      @layer_remove.push()
      end
    else
      dl_layer_item_effect_remove_state(user, item, effect)
    end
end

alias :dl_layer_item_apply :item_apply
def item_apply(user, item)
    @layer_remove = []
    dl_layer_item_apply(user, item)
    if @result.hit? and @layer_remove.count > 0
      item.layer_remove.times.each do |i|
      break if @layer_states.count == 0
      bob = false
      @layer_remove.each do |lr|
          if lr == @layer_states.last and rand < lr
            bob = true
            @success = true
          end
      end
      if bob
          @layer_states.pop
          @layer_turns.pop
      end
      end
    end
end

def layer_state_icons
    bob =
    if @layer_states.count > 0
      @layer_states.each do |s|
      bob.push($data_states.icon_index)
      end
    end
    bob.delete(0)
    return bob
end

alias :dl_layer_most_important_state_text :most_important_state_text
def most_important_state_text
    return layer_states.last.message3 if layer_states.last and !state.message3.empty?
    return dl_layer_most_important_state_text
end

def layer_state_count(type = 0)
    return type > 0 ? @layer_states.count(type) : @layer_states.count
end

def layer_state_current
    return nil if @layer_states == 0
    return @layer_states.last
end
   
def layer_states_clear
    @layer_states = []
    @layer_turns = []
end
end

class Game_Actor < Game_Battler

alias :dl_layer_on_player_walk :on_player_walk
def on_player_walk
    dl_layer_on_player_walk
    if $game_player.normal_walk?
      if @layer_states.count > 0
      @layer_turns.last -= 1 if @layer_turns.last > 0
      remove_state(@layer_states.last) if @layer_turns.last == 0
      end
    end
end

end

class Window_Base < Window
def draw_actor_icons(actor, x, y, width = 96)
    licons = (actor.layer_state_icons)[.max, DL::LAYERSTATE::MAXLAYER]
    licons.each_with_index {|n, i| draw_icon(n, x + 1 * i, y) }
    icons = (actor.state_icons + actor.buff_icons).max]
    icons.each_with_index {|n, i| draw_icon(n, x + (licons.count > 0 ? 24: 0) + 24 * i, y) }
end
end




本贴来自国际rpgmaker官方论坛作者:Harosata处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/layered-states.116528/
页: [1]
查看完整版本: Layered States