Код:
	#----------------------------------------------------------------------------
# * [ACE] Caveman Battle Stands
#----------------------------------------------------------------------------
# * Автор - caveman
# * Версия: 1.1 RU
# * Релиз: 31/07/2015
#
# * Описание:
# * Добавляет в игру стойки, в которые герои могут вставать в бою
# *  
#----------------------------------------------------------------------------
module StandParams
  SHOW_WINDOWSKIN = true
  NONESKINNAME = "NoneSkin"
  OPACITY = 128
  USE_ICONS = true
end
module Vocab
  def self.stand;       "Стойки";   end   # Стойка
end
  
#----------------------------------------------------------------------------
# Класс стойки
#----------------------------------------------------------------------------
class Stand
  # список параметров, на которые могут влиять стойки
  # тут только базовые параметры
  # при желании можно добавить свои
  # от второстепенных типа GRD до шанса на деньги и лут или защит/атак определенным
  # типом дамага
  attr_accessor :name
  attr_accessor :description
  attr_accessor :type
  attr_accessor :hp
  attr_accessor :mp
  attr_accessor :atk
  attr_accessor :mat
  attr_accessor :pdf
  attr_accessor :mdf
  attr_accessor :agi
  attr_accessor :luk
  attr_accessor :lvl
  
  attr_accessor :xparam
  attr_accessor :sparam
  
  def initialize(name,description,type,hp,mp,atk,mat,pdf,mdf,agi,luk,lvl)
    @name = name
    @description = description
    @type = type
    @hp = hp
    @mp = mp
    @atk = atk
    @mat = mat
    @pdf = pdf
    @mdf = mdf
    @agi = agi
    @luk = luk
    @lvl = lvl
    add_params
  end
  
  def add_params 
    # fill xparam {id => default val}
    # HIT, EVA, CRI, CEV, MEV, MRF, CNT, HRG, MRG, TRG
    @xparam = {0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 
                 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0 }
    # fill sparam {id => default val}
    # TGR, GRD, REC, PHA, MCR, TCR, PDR, MDR, FDR, EXR
    @sparam = {0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 
                 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0 }
                 
    # описание в Game_BattlerBase
  end
end
  
#----------------------------------------------------------------------------
# Тут набиваются стойки
#----------------------------------------------------------------------------
class Data_Stands
  attr_accessor :items
  attr_accessor :icons
  
  def initialize
    @items = []
    # иконки для стоек, в порядке очереди
    @icons = [132,136,139]
    # заполнение 
    # name,description,type,
    # hp,mp,atk,mat,pdf,mdf,agi,luk,lvl
    
    # стойка воина +HP, +ATK, -MDF, +CRI (на высоких уровнях)
    stand1 = Stand.new("Стойка воина", "Удобна для сильных атак", 1,
      10,0,2,0,0,-1,0,0,1)
    @items.push(stand1.clone)
    stand1 = Stand.new("Стойка воина", "Удобна для сильных атак", 1,
      15,0,4,0,0,-2,0,0,2)
    @items.push(stand1.clone)
    stand1 = Stand.new("Стойка воина", "Удобна для сильных атак", 1,
      20,0,8,0,0,-4,0,0,3)
    @items.push(stand1.clone)
    stand1 = Stand.new("Стойка воина", "Удобна для сильных атак", 1,
      30,0,10,0,0,-6,0,0,4)
    stand1.xparam[2] = 5 
    @items.push(stand1.clone)
    stand1 = Stand.new("Стойка воина", "Удобна для сильных атак", 1,
      50,0,15,0,0,-10,0,0,5)
    stand1.xparam[2] = 90 
    @items.push(stand1.clone)
    
    # Стойка мага +MP, +MAT, -PDF 
    stand2 = Stand.new("Стойка мага", "Удобна для магических атак", 2,
      0,5,0,1,-1,0,0,0,1)
    @items.push(stand2.clone)
    stand2 = Stand.new("Стойка мага", "Удобна для магических атак", 2,
      0,10,0,3,-2,0,0,0,2)
    @items.push(stand2.clone)
    stand2 = Stand.new("Стойка мага", "Удобна для магических атак", 2,
      0,15,0,6,-3,0,0,0,3)
    @items.push(stand2.clone)
    stand2 = Stand.new("Стойка мага", "Удобна для магических атак", 2,
      0,20,0,10,-5,0,0,0,4)
    @items.push(stand2.clone)
    stand2 = Stand.new("Стойка мага", "Удобна для магических атак", 2,
      0,30,0,15,-10,0,0,0,5)
    @items.push(stand2.clone)
    
    # Стойка клерика  +HP, +MP -MAT, -ATK, +PDF, +MDF, +GRD (4-5 уровни) 
    stand3 = Stand.new("Стойка клерика", "Удобна для защиты", 3,
      5,3,-1,-1,2,2,0,0,1)
    @items.push(stand3.clone)
    stand3 = Stand.new("Стойка клерика", "Удобна для защиты", 3,
      10,6,-3,-3,4,4,0,0,2)
    @items.push(stand3.clone)
    stand3 = Stand.new("Стойка клерика", "Удобна для защиты", 3,
      15,10,-5,-5,8,8,0,0,3)
    @items.push(stand3.clone)
    stand3 = Stand.new("Стойка клерика", "Удобна для защиты", 3,
      25,15,-10,-10,12,12,0,0,4)
    stand3.sparam[1] = 125 
    @items.push(stand3.clone)
    stand3 = Stand.new("Стойка клерика", "Удобна для защиты", 3,
      40,25,-15,-15,18,18,0,0,5)
    stand3.sparam[1] = 200
    @items.push(stand3.clone)
  end
end
#----------------------------------------------------------------------------
# Для вызова в событиях игры
#----------------------------------------------------------------------------
class Game_Interpreter
  # поднять герою с actor_id стойку type_id
  def lvlup_stand(actor_id, type_id)
    $game_actors[actor_id].lvlup_stand(type_id)
  end
  
  # посмотреть уровень стойки героя
  def get_stand_lvl(actor_id, type_id)
    return $game_actors[actor_id].get_stand_lvl(type_id)
  end
end
#----------------------------------------------------------------------------
# Стойки в классе актора
#----------------------------------------------------------------------------
class Game_Actor
  attr_accessor :last_stand # Текущая выбранная стойка
  attr_accessor :stands     # Все его прокачанные стойки
    
  alias cs10_setup setup
  def setup(actor_id)
    @stands = []
    cs10_setup(actor_id)
  end
  
  def stands
    @stands
  end
  
  # если активна стойка, считаем плюсы и минусы с неё
  def param_plus(param_id)
    plus = equips.compact.inject(super) {|r, item| r += item.params[param_id] }
    if last_stand != nil
      case param_id
        when 0 
          plus += last_stand.hp
        when 1
          plus += last_stand.mp
        when 2 
          plus += last_stand.atk
        when 3 
          plus += last_stand.pdf
        when 4 
          plus += last_stand.mat
        when 5 
          plus += last_stand.mdf
        when 6 
          plus += last_stand.agi
        when 7 
          plus += last_stand.luk
      end
    end
    return plus
  end
  def xparam(xparam_id)
    sum = features_sum(FEATURE_XPARAM, xparam_id)
    if last_stand != nil
      sum += last_stand.xparam[xparam_id]
    end
    sum
  end
  def sparam(sparam_id)
    pi = features_pi(FEATURE_SPARAM, sparam_id)
    if last_stand != nil && last_stand.sparam[sparam_id] != 0
      pi *= last_stand.sparam[sparam_id]
    end
    pi
  end
  
  def lvlup_stand(type_id)
    for i in 0..@stands.length-1
      if @stands[i].type == type_id
        # если уже была стойка - повышаем левел
        lvl = @stands[i].lvl
        for k in 0..$data_stands.items.length
          if $data_stands.items[k].type == type_id && $data_stands.items[k].lvl == lvl+1
            @stands[i] = $data_stands.items[k].clone
            break
          end
        end
        return
      end
    end
    # так и не нашли стойки - значит новая, 1го уровня
    for k in 0..$data_stands.items.length-1
      if $data_stands.items[k].type == type_id && $data_stands.items[k].lvl == 1
        @stands.push($data_stands.items[k].clone)
        break
      end
    end
  end
  
  def get_stand_lvl(type_id)
    for i in 0..@stands.length-1
      if @stands[i].type == type_id
        return @stands[i].lvl
      end
    end
    return 0
  end
end
#----------------------------------------------------------------------------
# Инициализация, данные о стойках
#----------------------------------------------------------------------------
module DataManager
    def self.load_normal_database
    $data_actors        = load_data("Data/Actors.rvdata2")
    $data_classes       = load_data("Data/Classes.rvdata2")
    $data_skills        = load_data("Data/Skills.rvdata2")
    $data_items         = load_data("Data/Items.rvdata2")
    $data_weapons       = load_data("Data/Weapons.rvdata2")
    $data_armors        = load_data("Data/Armors.rvdata2")
    $data_enemies       = load_data("Data/Enemies.rvdata2")
    $data_troops        = load_data("Data/Troops.rvdata2")
    $data_states        = load_data("Data/States.rvdata2")
    $data_animations    = load_data("Data/Animations.rvdata2")
    $data_tilesets      = load_data("Data/Tilesets.rvdata2")
    $data_common_events = load_data("Data/CommonEvents.rvdata2")
    $data_system        = load_data("Data/System.rvdata2")
    $data_mapinfos      = load_data("Data/MapInfos.rvdata2")
    $data_stands = Data_Stands.new
  end
  #--------------------------------------------------------------------------
  # * Load Battle Test Database
  #--------------------------------------------------------------------------
  def self.load_battle_test_database
    $data_actors        = load_data("Data/BT_Actors.rvdata2")
    $data_classes       = load_data("Data/BT_Classes.rvdata2")
    $data_skills        = load_data("Data/BT_Skills.rvdata2")
    $data_items         = load_data("Data/BT_Items.rvdata2")
    $data_weapons       = load_data("Data/BT_Weapons.rvdata2")
    $data_armors        = load_data("Data/BT_Armors.rvdata2")
    $data_enemies       = load_data("Data/BT_Enemies.rvdata2")
    $data_troops        = load_data("Data/BT_Troops.rvdata2")
    $data_states        = load_data("Data/BT_States.rvdata2")
    $data_animations    = load_data("Data/BT_Animations.rvdata2")
    $data_tilesets      = load_data("Data/BT_Tilesets.rvdata2")
    $data_common_events = load_data("Data/BT_CommonEvents.rvdata2")
    $data_system        = load_data("Data/BT_System.rvdata2")
    $data_stands = Data_Stands.new
  end
end
class Game_BaseItem
  def is_stand?;   @class == Stand;        end  
    
  def object
    return $data_skills[@item_id]  if is_skill?
    return $data_items[@item_id]   if is_item?
    return $data_weapons[@item_id] if is_weapon?
    return $data_armors[@item_id]  if is_armor?
    return $data_stands[@item_id]  if is_stand?
    return nil
  end  
end
class Game_Battler
  # ------------------------------------------------------------------
  # Дамаг с учетом стоек
  #--------------------------------------------------------------------------
  def make_damage_value(user, item)
    # user - атакующий self - защищающийся
    value = item.damage.eval(user, self, $game_variables)
    value *= item_element_rate(user, item) # защиты self / или лечение - user
    value *= pdr if item.physical?
    value *= mdr if item.magical?
    value *= rec if item.damage.recover?
    value = apply_critical(value) if @result.critical
    value = apply_variance(value, item.damage.variance)
    value = apply_guard(value)
    
    @result.make_damage(value.to_i, item)
  end
end 
#==============================================================================
# GUI
#==============================================================================
# ** Сцена для стоек
#==============================================================================
class Scene_Stand < Scene_ItemBase
  def start
    super
    create_background
    create_help_window
    create_item_window
    create_info_window
    @item_window.info_window = @info_window
    @item_window.activate
    @item_window.select_last
    @help_window.opacity = StandParams::OPACITY
    
    @help_window.windowskin = Cache.system(StandParams::NONESKINNAME) if !StandParams::SHOW_WINDOWSKIN
    @item_window.windowskin = Cache.system(StandParams::NONESKINNAME) if !StandParams::SHOW_WINDOWSKIN
    @info_window.windowskin = Cache.system(StandParams::NONESKINNAME) if !StandParams::SHOW_WINDOWSKIN
  end
  
  def create_background
    @background_sprite = Sprite.new(@viewport1)
    @background_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height) 
    background = Bitmap.new("Graphics/Pictures/StandBack")
    screen = Rect.new(0, 0, Graphics.width, Graphics.height)
    @background_sprite.bitmap.stretch_blt(screen, background, background.rect) 
  end
  
  def create_item_window
    wx = 0
    wy = @help_window.height
    ww = Graphics.width / 2
    wh = Graphics.height - wy
    @item_window = Window_StandList.new(wx, wy, ww, wh)
    @item_window.actor = @actor
    @item_window.viewport = @viewport
    @item_window.help_window = @help_window
    @item_window.set_handler(:ok,     method(:on_item_ok))
    @item_window.set_handler(:cancel, method(:on_item_cancel))
    @item_window.opacity = StandParams::OPACITY
  end
  def create_info_window
    wx = @item_window.width
    wy = @help_window.height
    ww = Graphics.width / 2
    wh = Graphics.height - wy
    @info_window = Window_StandInfo.new(wx, wy, ww, wh)
    @info_window.viewport = @viewport
    @info_window.opacity = StandParams::OPACITY
  end
  def user
    @actor
  end
  def on_item_ok
    if @actor.last_stand == nil || @actor.last_stand.type != item.type
      @actor.last_stand = item
    else
      @actor.last_stand = nil
    end
    @item_window.refresh
  end
  def on_item_cancel
    SceneManager.return
  end
  def on_actor_change
    @item_window.actor = @actor
  end
end
#==============================================================================
# ** Окно стоек
#==============================================================================
class Window_StandList < Window_Selectable
   attr_accessor   :info_window              # info window
  def initialize(x, y, width, height)
    super
    @actor = nil
    @data = []
  end
  def actor=(actor)
    return if @actor == actor
    @actor = actor
    refresh
    self.oy = 0
  end
  def col_max
    return 1
  end
  def item_max
    @data ? @data.size : 1
  end
  def item
    @data && index >= 0 ? @data[index] : nil
  end
  def current_item_enabled?
    true
  end
  def make_item_list
    @data = @actor ? @actor.stands.select {|stands| true } : []
  end
  def select_last
    select(@data.index(@actor.last_stand) || 0)
  end
  def draw_item(index)
    stand = @data[index]
    if stand
      rect = item_rect(index)
      rect.width -= 4
      
      if StandParams::USE_ICONS 
        draw_icon($data_stands.icons[stand.type-1], rect.x, rect.y, true)
        rect.x += 24
        rect.width -= 24
      end
      
      contents.font.color = normal_color
      if @actor.last_stand != nil && @actor.last_stand.type == stand.type
        contents.font.color = power_up_color
      end
      draw_text(rect.x, rect.y, rect.width, line_height, stand.name)
    end
  end
  def update_help
    @help_window.set_item(item)
  end
  def refresh
    make_item_list
    create_contents
    draw_all_items
  end
  def index=(index)
    super(index)
    stand = @data[index]
    if stand
      @info_window.stand = stand
    end
  end
  
  # для обработки кнопок
  def update
    if self.active 
      super
      return process_cancel if Input.trigger?(:B)
    end
  end
  
  def process_cancel
    Sound.play_cancel
    Input.update
    deactivate
    @handler[:cancel].call
  end
  
  def set_handler(symbol, method)
    @handler[symbol] = method
  end
  
  def process_ok
    Sound.play_ok
    call_ok_handler
  end
end
#==============================================================================
# ** Окно инфы о стойке (лвл, +, -)
#==============================================================================
class Window_StandInfo < Window_Base
  def initialize(wx, wy, ww, wh)
    super(wx, wy, ww, wh)
    @stand = nil
  end
  def stand=(stand)
    return if @stand == stand
    @stand = stand
    refresh
  end
  def refresh
    contents.clear
    return unless @stand
    contents.font.color = power_up_color
    contents.font.size = 22
    draw_text(60, 4, 200, 24, sprintf("%d %s", @stand.lvl, Vocab::level))
    x = 16
    y = 30
    contents.font.color = normal_color
    draw_text(4, y, 300, 24, "Изменения параметров:")
    y += 28
    contents.font.size = 18
    line_h = 20
    
    if @stand.hp != 0
      if @stand.hp < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(0), @stand.hp))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(0), @stand.hp))
      end
      y += line_h
    end
    if @stand.mp != 0
      if @stand.mp < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(1), @stand.mp))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(1), @stand.mp))
      end
      y += line_h
    end
    if @stand.atk != 0
      if @stand.atk < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(2), @stand.atk))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(2), @stand.atk))
      end
      y += line_h
    end
    if @stand.pdf != 0
      if @stand.pdf < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(3), @stand.pdf))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(3), @stand.pdf))
      end
      y += line_h
    end
    if @stand.mat != 0
      if @stand.mat < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(4), @stand.mat))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(4), @stand.mat))
      end
      y += line_h
    end
    if @stand.mdf != 0
      if @stand.mdf < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(5), @stand.mdf))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200,line_h, sprintf("%s: +%d", Vocab::param(5), @stand.mdf))
      end
      y += line_h
    end
    if @stand.agi != 0
      if @stand.agi < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(6), @stand.agi))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(6), @stand.agi))
      end
      y += line_h
    end
    if @stand.luk != 0
      if @stand.luk < 0
        contents.font.color = power_down_color
        draw_text(x, y, 200, line_h, sprintf("%s: %d", Vocab::param(7), @stand.luk))
      else
        contents.font.color = power_up_color
        draw_text(x, y, 200, line_h, sprintf("%s: +%d", Vocab::param(7), @stand.luk))
      end
      y += line_h
    end
    contents.font.color = normal_color
  end
end
#--------------------------------------------------------------------------
# * Отображаем в статусном окне выбранную стойку
# TODO: каждый решит для себя сам, надо ли, и встроит куда нужно
#--------------------------------------------------------------------------
class Window_Status
  def draw_cur_stand(x, y)
    s1 = "Выбранная стойка"
    s2 = "нет"
    
    contents.fill_rect(x, y + line_height * 3 + 2, contents_width-x, 2, line_color)
    if @actor.last_stand != nil 
      s2 = sprintf("%s %d ур.", @actor.last_stand.name, @actor.last_stand.lvl)
    end
    change_color(text_color(12))
    wdt1 = contents.text_size(s1).width
    draw_text(x, y + line_height * 3 + 6, wdt1+16, line_height, s1)
    change_color(normal_color)
    wdt2 = contents.text_size(s2).width
    draw_text(x+wdt1+16, y + line_height * 3 + 6, wdt2+16, line_height, s2)
  end
end
#--------------------------------------------------------------------------
# * Встраиваем в меню
#--------------------------------------------------------------------------
class Window_MenuCommand
  def add_original_commands
    add_command(Vocab::stand,  :stand,  main_commands_enabled)
  end
end
class Scene_Menu
  alias cs10_create_command_window create_command_window
  def create_command_window
    cs10_create_command_window
    @command_window.set_handler(:stand,     method(:command_stand))
  end
  
  def command_stand
    @status_window.select_last
    @status_window.activate
    @status_window.set_handler(:ok,     method(:on_stand_ok)) 
    @status_window.set_handler(:cancel, method(:on_stand_cancel))
  end
  def on_stand_ok
    SceneManager.call(Scene_Stand)
  end
  
  def on_stand_cancel
    @status_window.unselect
    @command_window.activate
  end
end
#--------------------------------------------------------------------------
# * Выбор стойки в бою
#--------------------------------------------------------------------------
class Window_BattleStand < Window_StandList
  def initialize(help_window, info_viewport)
    y = help_window.height
    super(0, y, Graphics.width/2, info_viewport.rect.y - y)
    self.visible = false
    @help_window = help_window
    @info_viewport = info_viewport
    
    wx = self.width
    wy = y
    ww = Graphics.width / 2
    wh = self.height
    @info_window = Window_StandInfo.new(wx, wy, ww, wh)
    @info_window.visible = false
  end
  def show
    select_last
    @help_window.show
    @info_window.show
    super
  end
  def hide
    @help_window.hide
    @info_window.hide
    super
  end
end
class Window_ActorCommand
  def make_command_list
    return unless @actor
    add_attack_command
    add_skill_commands
    add_stand_command
    add_guard_command
    add_item_command
  end
  
  #--------------------------------------------------------------------------
  # * Команда стойки
  #--------------------------------------------------------------------------
  def add_stand_command
    add_command(Vocab::stand, :stand)
  end
end
#--------------------------------------------------------------------------
# * Выбор стойки в бою, процессинг
#--------------------------------------------------------------------------
class Scene_Battle
  alias cs10_create_all_windows create_all_windows
  def create_all_windows
    cs10_create_all_windows
    create_stand_window
  end
  
  def create_stand_window
    @stand_window = Window_BattleStand.new(@help_window, @info_viewport)
    @stand_window.set_handler(:ok,     method(:on_stand_ok))
    @stand_window.set_handler(:cancel, method(:on_stand_cancel))
  end
  
  def create_actor_command_window
    @actor_command_window = Window_ActorCommand.new
    @actor_command_window.viewport = @info_viewport
    @actor_command_window.set_handler(:attack, method(:command_attack))
    @actor_command_window.set_handler(:skill,  method(:command_skill))
    # меняйте положение команды стоек как угодно
    @actor_command_window.set_handler(:stand,  method(:command_stand))
    @actor_command_window.set_handler(:guard,  method(:command_guard))
    @actor_command_window.set_handler(:item,   method(:command_item))
    @actor_command_window.set_handler(:cancel, method(:prior_command))
    @actor_command_window.x = Graphics.width
  end
  
  def command_stand
    @stand_window.actor = BattleManager.actor
    @stand_window.refresh
    @stand_window.show.activate
  end
  def on_stand_ok
    item = @stand_window.item
    if BattleManager.actor.last_stand == nil || BattleManager.actor.last_stand.type != item.type
      BattleManager.actor.last_stand = item
    else
      BattleManager.actor.last_stand = nil
    end
    @stand_window.refresh
    @status_window.refresh
  end
  def on_stand_cancel
    @stand_window.hide
    @actor_command_window.activate
  end
end
 
Социальные закладки