전투

에너미를 아이템으로 변화하는 스킬

by Evangelista posted May 27, 2009
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

자작은 아니고 KGC의 훔치기 스킬 스크립트를 개조한 물건입니다.

KGC 몬스터도감과 병용 (몬스터도감에 변화하는 아이템도 표시)도 완료했습니다.

사용하실 때에는 가급적 사용보고를 해 주시면 감사하겠으며

버그보고나 리퀘스트 등 역시 메일이나 쪽지, 리플로 부탁드립니다.

 

################################################################################
#                                                                              #
# DEST21C : 에너미 아이템변화 시스템 스크립트 V1.0                             #
#                                                                              #
# 버그보고 및 리퀘스트 : dest21c@nate.com                                      #
#                                                                              #
################################################################################
=begin

@ 에너미를 해당 스킬로 해치웠을 때 특정 확률로
  아이템을 입수하는 스킬을 제작할 수 있습니다.
 
@ 본 스크립트는 KGC의 훔치기 스킬 스크립트를 개조하여 만든 것입니다.
  KGC의 이용규약상 개조 후 2차배포는 문제가 없으므로 배포합니다.
  다만 사용하실 경우 가능한 사용보고를 해 주시면 감사하겠습니다.

@ 주요기능
  1. 스킬에 특성을 주어 변화용 스킬로 만들 수 있음
  2. 적에게 특성을 주어 변화시 입수 아이템과 확률을 지정할 수 있음
  3. 장비에 특성을 주어 장비시 변화 확률 보정을 지정할 수 있음
 
@ 주의
  1. 메모란 기입시 퍼센트 문자는 반각 %입니다.
  2. 몬스터 도감과의 병용에서 드롭아이템, 훔치기, 변화의 아이템은
     총 3개 이후로는 불균형적으로 표시됩니다. 3항목 이내로 설정해 주십시오.
     (한 행은 여유가 있으므로 리퀘스트가 있을 시 한 항목을 4행분으로
      수정하는 것은 가능하므로 연락해 주십시오.)
  3. 몬스터 도감과의 병용화시 커스터마이즈 항목은 399행입니다.

=end
$imported = {} if $imported == nil
$imported["Morph"] = true

module DEST21C
  module ENEMY_MORPH
    module BASEITEM
      # 커스터마이즈 항목
      # KGC의 모듈을 참고하였습니다.
      # 도입방법
      # 장비 데이터베이스 메모란에
      # <변화보정 +n%> 혹은 <MORPHREV +n%> (마이너스도 가능합니다.)
      MORPH_REV = /<(?:MORPHREV|변화보정)s*([+-]d+)[%]?>/i
    end
    module ENEMY
      # 커스터마이즈 항목
      # KGC의 모듈을 참고하였습니다.
      # 도입방법
      # 에너미 데이터베이스의 메모란에
      # <변화 종류(IWA):ID 입수확률> 혹은 <MORPH 종류(IWA):ID 입수확률>
      MORPH_ENEMY = /<(?:MORPH|변화)s*([IWA]):(d+)s+(d+)([%])?>/i
    end
    module SKILL
      # 커스터마이즈 항목
      # KGC의 모듈을 참고하였습니다.
      # 도입방법
      # 스킬 데이터베이스의 메모란에
      # <변화> 혹은 <MORPH>
      MORPH_SKILL = /<(?:MORPH|변화)>/i
    end
  end
end

################################################################################

module Vocab
  # 커스터마이즈 항목
  # 설정되지 않아 변화불가능한 적일 때
  NoMorph = "변화시킬 수 없는 적이다."
  # 적을 해치웠으나 변화시키지 못했을 때
  CantMorph = "변화시키지 못했다!"
  # 적을 해치우지 못해 변화시키지 못했을 떄
  CantMorph2 = "변화시킬만큼 충분히 공격하지 못했다!"
  # 변화에 성공했을 때
  SucMorph = "%s을(를) %s(으)로 변화시켰다!"
end

################################################################################

class RPG::BaseItem
  # 변화 캐시의 생성
  def create_morph_cache
    @__morph_prob_plus = 0
    self.note.each_line { |line|
      case line
      when DEST21C::ENEMY_MORPH::BASEITEM::MORPH_REV
        @__morph_prob_plus += $1.to_i
      end
    }
  end
  # 변화성공률보정
  def morph_prob_plus
    create_morph_cache if @__morph_prob_plus == nil
    return @__morph_prob_plus
  end
end

################################################################################

class RPG::Skill < RPG::UsableItem
  # 변화 캐시의 생성
  def create_morph_cache
    super
    @__morph = false
    self.note.each_line { |line|
      case line
      when DEST21C::ENEMY_MORPH::SKILL::MORPH_SKILL
        @__morph = true
      end
    }
  end
  # 변화
  def morph?
    create_morph_cache if @__morph == nil
    return @__morph
  end
end

################################################################################

class RPG::Enemy
  # 변화 캐시의 생성
  def create_morph_cache
    @__morph_objects = []
    self.note.each_line { |line|
      case line
      when DEST21C::ENEMY_MORPH::ENEMY::MORPH_ENEMY
        # 변화시키는 오브젝트
        obj = RPG::Enemy::MorphObject.new
        case $1.upcase
        when "I"  # 아이템
          obj.kind = 1
          obj.item_id = $2.to_i
        when "W"  # 무기
          obj.kind = 2
          obj.weapon_id = $2.to_i
        when "A"  # 방어구
          obj.kind = 3
          obj.armor_id = $2.to_i
        else
          next
        end
        # 성공율
        if $4 != nil
          obj.success_prob = $3.to_i
        else
          obj.denominator = $3.to_i
        end
        @__morph_objects << obj
      end
    }
  end
  # 변화시키는 오브젝트
  def morph_objects
    create_morph_cache if @__morph_objects == nil
    return @__morph_objects
  end
end

################################################################################

class RPG::Enemy::MorphObject < RPG::Enemy::DropItem
  # 정수
  KIND_ITEM   = 1
  KIND_WEAPON = 2
  KIND_ARMOR  = 3
  # 공개 인스턴스 변수
  attr_accessor :success_prob             # 성공율
  # 오브젝트의 초기화
  def initialize
    super
    @success_prob = 0
  end
  # 동식판정
  def equal?(obj)
    return false unless obj.is_a?(RPG::Enemy::MorphObject)
    return false if self.success_prob != obj.success_prob
    return true
  end
  # 등식연산자
  def ==(obj)
    return self.equal?(obj)
  end
end

################################################################################

class Game_Battler
  # 공개 인스턴스 변수
  attr_accessor :morph_objects             # 변화시키는 오브젝트
  attr_accessor :morphen_object            # 전회에 변화시킨 오브젝트
  # 오브젝트 초기화
  alias dest21c_initialize_battler_morph initialize
  def initialize
    dest21c_initialize_battler_morph
    @morph_objects = []
    @morphen_object = nil
  end
  # 변화성공율 보정
  def morph_prob_plus
    return 0
  end
  # ● 스킬의 효과 적용
  #     user  : 스킬의 사용자
  #     skill : 스킬
  alias dest21c_skill_effect_morph skill_effect
  def skill_effect(user, skill)
    dest21c_skill_effect_morph(user, skill)
    make_obj_morph_result(user, skill)
  end
  # ○ 스킬 또는 아이템에 의한 변화 효과
  #     user : 스킬 또는 아이템의 사용자
  #     obj  : 스킬 또는 아이템
  #    결과는 @morphen_item에 대입된다.
  def make_obj_morph_result(user, obj)
    return unless obj.morph?                  # 변화효과없음
    return if @missed || @evaded ||@skipped  # 변화없음
    # 변화불가능한 적이다.
    if self.morph_objects.compact.empty?
      @morphen_object = :no_item
      return
    end
    @morphen_object = nil
    morphen_index = -1
    self.morph_objects.each_with_index { |mobj, i|
      next if mobj == nil
      # 변화성공판정
      if mobj.success_prob > 0
        # 확율판정
        next if mobj.success_prob + user.morph_prob_plus < rand(100)
      else
        # 분모지정
        if rand(mobj.denominator) != 0
          next if user.morph_prob_plus < rand(100)
        end
      end
      # 변화성공
      @morphen_object = mobj
      morphen_index = i
      if $imported["EnemyGuide"]
        # 도감용의 변화성공플래그를 ON
        # KGC 몬스터도감과 병용가(단 몬스터도감 스크립트를 수정해야 함
        self_id = (self.actor? ? self.id : self.enemy_id)
        KGC::Commands.set_enemy_object_morphen(self_id, morphen_index)
      end
      break
    }
  end
end

################################################################################

class Game_Actor < Game_Battler
  # 변화성공율보정치
  def morph_prob_plus
    n = 0
    equips.compact.each { |item| n += item.morph_prob_plus }
    return n
  end
end

################################################################################

class Game_Enemy < Game_Battler
  # ● 오브젝트의 초기화
  #     index    : 적 그룹의 인덱스
  #     enemy_id : 적 캐릭터 ID
  alias dest21c_initialize_enemy_morph initialize
  def initialize(index, enemy_id)
    dest21c_initialize_enemy_morph(index, enemy_id)
    @morph_objects = enemy.morph_objects.clone
  end
end

################################################################################

class Scene_Battle < Scene_Base
  # 전투행동의 실행 : 스킬
  alias dest21c_execute_action_skill_morph execute_action_skill
  def execute_action_skill
    skill = @active_battler.action.skill
    if skill.morph?
      execute_action_morph
      @status_window.refresh
    else
      dest21c_execute_action_skill_morph
    end
  end
  # 전투행동의 실행 : 변화
  def execute_action_morph
    skill = @active_battler.action.skill
    text = @active_battler.name + skill.message1
    @message_window.add_instant_text(text)
    unless skill.message2.empty?
      wait(10)
      @message_window.add_instant_text(skill.message2)
    end
    targets = @active_battler.action.make_targets
    display_animation(targets, skill.animation_id)
    @active_battler.mp -= @active_battler.calc_mp_cost(skill)
    $game_temp.common_event_id = skill.common_event_id
    for target in targets
      target.skill_effect(@active_battler, skill)
      display_morph_effects(target, skill)
    end
  end
  # ○ 변화시킨 결과의 표시
  #     target : 대상자
  #     obj    : 스킬 또는 아이템
  def display_morph_effects(target, obj = nil)
    unless target.skipped
      line_number = @message_window.line_number
      wait(5)
      if target.hp_damage != 0 || target.mp_damage != 0
        display_critical(target, obj)
        display_damage(target, obj)
      end
      display_state_changes(target, obj)
      display_morphe_object(target, obj)
      if line_number == @message_window.line_number
        display_failure(target, obj) unless target.states_active?
      end
      if line_number != @message_window.line_number
        wait(30)
      end
      @message_window.back_to(line_number)
    end
  end
  # ○ 변화시킨 오브젝트의 표시
  #     target : 대상자
  #     obj    : 스킬 또는 아이템
  def display_morphe_object(target, obj = nil)
    if target.hp > 0
      display_morph_failure2(target, obj)
      return
    end
    case target.morphen_object
    when nil       # 변화실패
      display_morph_failure(target, obj)
    when :no_item  # 변화불가능
      display_morph_no_item(target, obj)
    else
      display_morph_item(target, obj) # 변화한 아이템의 표시
      target.morphen_object = nil
    end
  end
  # ○ 변화실패1의 표시
  #     target : 대상자(액터)
  #     obj    : 스킬 또는 아이템
  def display_morph_failure(target, obj)
    @message_window.add_instant_text(Vocab::CantMorph)
    wait(45)
  end
  # ○ 변화실패2의 표시
  #     target : 대상자(액터)
  #     obj    : 스킬 또는 아이템
  def display_morph_failure2(target, obj)
    @message_window.add_instant_text(Vocab::CantMorph2)
    wait(45)
  end
  # ○ 변화불가능의 표시
  #     target : 대상자(액터)
  #     obj    : 스킬 또는 아이템
  def display_morph_no_item(target, obj)
    text = sprintf(Vocab::NoMorph)
    @message_window.add_instant_text(text)
    wait(45)
  end
  # ○ 아이템으로 변화시킨 경우의 표시
  #     target : 대상자(액터)
  #     obj    : 스킬 또는 아이템
  def display_morph_item(target, obj)
    # 변화시킨 아이템을 취득
    mobj = target.morphen_object
    case mobj.kind
    when RPG::Enemy::MorphObject::KIND_ITEM
      item = $data_items[mobj.item_id]
    when RPG::Enemy::MorphObject::KIND_WEAPON
      item = $data_weapons[mobj.weapon_id]
    when RPG::Enemy::MorphObject::KIND_ARMOR
      item = $data_armors[mobj.armor_id]
    else
      return
    end
    $game_party.gain_item(item, 1)

    text = sprintf(Vocab::SucMorph, target.name, item.name)
    @message_window.add_instant_text(text)
    wait(45)
  end
end

################################################################################
#                           KGC 몬스터도감과 병용화                            #
################################################################################

$data_states = load_data("Data/States.rvdata") if $data_states == nil
$data_system = load_data("Data/System.rvdata") if $data_system == nil

module DEST21C
  module MORPH_JOIN_A
    # 커스터마이즈 항목
    # 몬스터도감에 변화 항목을 표시할 것인가(예 : true / 아니오 : false)
    DISPLAY = true
    # 몬스터도감에 표시될 변화 항목의 제목
    MORPHINDEX = "변화"
    # 몬스터도감에 표시될 변화 항목의 확률이름
    MORPHPROB = "변화율"
  end
end

################################################################################

module KGC
  module Commands
  module_function
  # ○ 변화성공상태취득
  #     enemy_id  : 적 ID
  #     obj_index : 오브젝트 번호
  def enemy_object_morphen?(enemy_id, obj_index)
    if $game_system.enemy_object_morphen[enemy_id] == nil
      return false
    end
    result = $game_system.enemy_object_morphen[enemy_id] & (1 << obj_index)
    return (result != 0)
  end
  # ○ 변화성공상태설정
  #     enemy_id  : 적 ID
  #     obj_index : 오브젝트 번호
  #     enabled   : true..성공했음  false..미성공
  def set_enemy_object_morphen(enemy_id, obj_index, enabled = true)
    if $game_system.enemy_object_morphen[enemy_id] == nil
      $game_system.enemy_object_morphen[enemy_id] = 0
    end
    if enabled
      $game_system.enemy_object_morphen[enemy_id] |= (1 << obj_index)
    else
      $game_system.enemy_object_morphen[enemy_id] &= ~(1 << obj_index)
    end
  end
  # ○ 도감 리셋 (재정의)
  def reset_enemy_guide
    $game_system.enemy_encountered = []
    $game_system.enemy_defeated = []
    $game_system.enemy_item_dropped = []
    $game_system.enemy_object_stolen = []
    $game_system.enemy_object_morphen = []
  end
  # ○ 도감완성 (재정의)
  def complete_enemy_guide
    (1...$data_enemies.size).each { |i|
      set_enemy_encountered(i)
      set_enemy_defeated(i)
      enemy = $data_enemies[i]
      items = [enemy.drop_item1, enemy.drop_item2]
      if $imported["ExtraDropItem"]
        items += enemy.extra_drop_items
      end
      items.each_index { |j| set_enemy_item_dropped(i, j) }
      if $imported["Steal"]
        objs = enemy.steal_objects
        objs.each_index { |j| set_enemy_object_stolen(i, j) }
      end
      if $imported["Morph"]
        objs = enemy.morph_objects
        objs.each_index { |j| set_enemy_object_morphen(i, j) }
      end
    }
  end
  end
end

################################################################################

class Game_System
  attr_writer   :enemy_object_morphen      # 변화성공플래그
  # ○ 변화성공플래그를 취득
  def enemy_object_morphen
    @enemy_object_morphen = [] if @enemy_object_morphen == nil
    return @enemy_object_morphen
  end
end

################################################################################

class Window_EnemyGuideStatus < Window_Base
  # ○ 아이템용 페이지를 표시하는가 (재정의)
  def item_page_show?
    return true if KGC::EnemyGuide::SHOW_DROP_ITEM
    return true if $imported["Steal"] && KGC::EnemyGuide::SHOW_STEAL_OBJ
    return true if $imported["Morph"] && DEST21C::MORPH_JOIN_A::DISPLAY
    return false
  end
  # ○ 스테이터스 묘화 (재정의)
  def draw_status
    # Page 1
    dy = draw_basic_info(0, 0)
    dy = draw_parameter2(0, dy)
    dy = draw_element(0, dy, 2)
    dy = draw_state(0, dy, 2)
    draw_prize(0, dy)
    # Page 2 (아이템관련을 표시할 경우에만)
    if item_page_show?
      dx = width - 32
      dy = draw_basic_info(dx, 0)
      max_rows = (self.height - dy - 32) / WLH
      rows = max_rows / 3
      dy = draw_drop_item(dx, dy, rows)
      draw_steal_object(dx, dy, rows)
      draw_morph_item(dx, dy + WLH * rows, rows)
    end
    # Page 3
    dx = (width - 32) * (pages - 1)
    dy = draw_basic_info(dx, 0)
    draw_description(dx, dy)
  end
  # 변화 아이템의 묘화
  #   dx, dy : 묘화처 X, Y
  #   rows   : 행
  def draw_morph_item(dx, dy, rows)
    return by unless DEST21C::MORPH_JOIN_A::DISPLAY
    new_dy = dy + WLH * rows
    dw = (width - 32) / 2
    self.contents.font.color = system_color
    self.contents.draw_text(dx,      dy, 128, WLH,
      DEST21C::MORPH_JOIN_A::MORPHINDEX, 1)
    self.contents.draw_text(dx + dw, dy, 128, WLH,
      DEST21C::MORPH_JOIN_A::MORPHPROB, 2)
    return new_dy unless KGC::Commands.enemy_defeated?(enemy.id)
    # 리스트 작성
    morph_objects = enemy.morph_objects.clone
    if morph_objects.size >= rows
      morph_objects = morph_objects[0...(rows - 1)]
    end
    dy += WLH
    morph_objects.each_with_index { |obj, i|
      case obj.kind
      when 1
        item = $data_items[obj.item_id]
      when 2
        item = $data_weapons[obj.weapon_id]
      when 3
        item = $data_armors[obj.armor_id]
      end
      if KGC::Commands.enemy_object_morphen?(enemy.id, i)
        draw_item_name(item, dx, dy)
      else
        draw_masked_item_name(item, dx, dy)
      end
      # 성공율묘화
      if obj.success_prob > 0
        text = sprintf("%d%%", obj.success_prob)
      else
        text = "1/#{obj.denominator}"
      end
      self.contents.draw_text(dx + dw, dy, 128, WLH, text, 2)
      dy += WLH
    }
    return new_dy
  end
end

################################################################################