共有スキル 〆 制作していただきありがとうございました。

なたね
記事: 30
登録日時: 2017年1月11日(水) 00:34

共有スキル 〆 制作していただきありがとうございました。

投稿記事by なたね » 2017年1月11日(水) 00:46

RGSS3で制作中のなたねと申します。
私の作成しているゲームは多人数の為、スクリプトに頼りたいと思い、リクエストさせていただきました。
要望としては特定のスキルを1人のアクターが習得した際に全てのアクターにそのスキルを習得させるようなスクリプトを作成していただきたいです。ご検討のほど、よろしくお願いします。
最後に編集したユーザー なたね on 2017年1月15日(日) 18:53 [ 編集 1 回目 ]

奈々(なな)
記事: 103
登録日時: 2016年11月06日(日) 16:57

Re: 共有スキル

投稿記事by 奈々(なな) » 2017年1月11日(水) 22:05

とりあえず試作品です。
メモ欄に<共有スキル>タグを入れたスキルの習得と喪失を共有します。
習得はレベルアップやイベントコマンド、アイテムなどで行うもので
特徴によって一時的に得るスキルとは別扱いです。なので特徴のものは共有しません。
(但し、私の公開素材の中にはそれを習得扱いにするものがあります)

コード: 全て選択

#==============================================================================
#                        「共有スキル」(ACE) Ver.0.5a
#   製作者:奈々(なな)
#   へぷたなすくろーる http://heptanas.mamagoto.com/
#
#   ◇使用規約
#   使用される場合はスクリプト作成者として「奈々」を明記して下さい。
#   スクリプトの改変は自由に行って頂いて構いませんが
#   その場合も元のスクリプトの作成者として名前を載せて下さい。
#   また配布前に必ず、ブログにある利用規約を確認して下さい。
#
#------------------------------------------------------------------------------
#   
#   ツクマテのリクエスト品になります。
#   規約は「へぷたなすくろーる」の素材利用規約に準じるものとし
#   サポートに関してもそれらと同様に受け付けます。
#   
#   スキルのメモ欄に<共有スキル>と入れると
#   誰かがそのスキルを習得した時点で、全アクターが習得します。喪失も同様。
#   
#==============================================================================
#==============================================================================
# ■ Game_Actor
#------------------------------------------------------------------------------
#  アクターを扱うクラスです。このクラスは Game_Actors クラス($game_actors)
# の内部で使用され、Game_Party クラス($game_party)からも参照されます。
#==============================================================================

class Game_Actor < Game_Battler
  #--------------------------------------------------------------------------
  # ● スキルを覚える
  #--------------------------------------------------------------------------
  alias shareskill_learn_skill learn_skill
  def learn_skill(skill_id)
    if $data_skills[skill_id].note.include?("<共有スキル>")
      unless skill_learn?($data_skills[skill_id])
        for i in 1...$data_actors.size
          $game_actors[i].shareskill_learn_skill(skill_id)
        end
      end
    else
      shareskill_learn_skill(skill_id)
    end
  end
  #--------------------------------------------------------------------------
  # ● スキルを忘れる
  #--------------------------------------------------------------------------
  alias shareskill_forget_skill forget_skill
  def forget_skill(skill_id)
    if $data_skills[skill_id].note.include?("<共有スキル>")
      for i in 1...$data_actors.size
        $game_actors[i].shareskill_forget_skill(skill_id)
      end
    else
      @skills.delete(skill_id)
    end
  end
end

さて、これが試作品である理由なのですが、現状1つだけ致命的なエラーを抱えているからです。
レベルアップ習得で共有スキルを一定数以上覚えるアクターが存在する場合
エラーを起こして止まります。
具体的にはデフォルトの僧侶・魔術師・賢者ですね。
流石にこれは改善予定ですが、すんなり直せるかは分かりません。
------------------------------------------------------------------------------------
へぷたなすくろーる
http://heptanas.mamagoto.com/

VXAceのスクリプト素材及びイベント講座などをやっています。
------------------------------------------------------------------------------------
TOMO
記事: 343
登録日時: 2015年11月16日(月) 20:12
連絡を取る:

Re: 共有スキル

投稿記事by TOMO » 2017年1月12日(木) 04:34

私の方で作ってみました

コード: 全て選択

# ※共有スキルを忘れたい場合
# $game_party.forget_shareskill(スキルID)

class Game_Actor < Game_Battler
  #--------------------------------------------------------------------------
  # ● スキルオブジェクトの配列取得
  #--------------------------------------------------------------------------
  alias shareskill_skills skills
  def skills
    shareskill_skills |
    $game_party.shareskills.sort.collect{|id| $data_skills[id] }
  end
  #--------------------------------------------------------------------------
  # ● スキルを覚える
  #--------------------------------------------------------------------------
  alias shareskill_learn_skill learn_skill
  def learn_skill(skill_id)
    if $data_skills[skill_id].note.include?("<共有スキル>")
      $game_party.learn_shareskill(skill_id)
    else
      shareskill_learn_skill(skill_id)
    end
  end
end

class Game_Party < Game_Unit
  attr_accessor   :shareskills
  #--------------------------------------------------------------------------
  # ● 共有スキルの取得
  #--------------------------------------------------------------------------
  def shareskills
    @shareskills = [] if @shareskills.nil?
    @shareskills
  end
  #--------------------------------------------------------------------------
  # ● 共有スキルを覚える
  #--------------------------------------------------------------------------
  def learn_shareskill(skill_id)
    @shareskills = [] if @shareskills.nil?
    unless @shareskills.include?(skill_id)
      @shareskills.push(skill_id)
      @shareskills.sort!
    end
  end
  #--------------------------------------------------------------------------
  # ● 共有スキルを忘れる
  #--------------------------------------------------------------------------
  def forget_shareskill(skill_id)
    @shareskills = [] if @shareskills.nil?
    @shareskills.delete(skill_id)
  end
end


同じように、メモ欄に<共有スキル>と入れれば出来ます

忘れたい場合は

コード: 全て選択

$game_party.forget_shareskill(i)

で出来ます(iはスキルID)

欠点としては共有スキルがリストの後ろの方に来る事ですが、
競合対策なしでいいなら、「def skills」の所を↓のに置き換えれば出来ます

コード: 全て選択

  def skills
    (@skills | added_skills |
    $game_party.shareskills).sort.collect{|id| $data_skills[id] }
  end
TOMO
記事: 343
登録日時: 2015年11月16日(月) 20:12
連絡を取る:

Re: 共有スキル

投稿記事by TOMO » 2017年1月12日(木) 19:02

ついでに奈々さんのを勝手に修正してみました

コード: 全て選択

#==============================================================================
#                        「共有スキル」(ACE) Ver.0.5a
#   製作者:奈々(なな)
#   へぷたなすくろーる http://heptanas.mamagoto.com/
#
#   ◇使用規約
#   使用される場合はスクリプト作成者として「奈々」を明記して下さい。
#   スクリプトの改変は自由に行って頂いて構いませんが
#   その場合も元のスクリプトの作成者として名前を載せて下さい。
#   また配布前に必ず、ブログにある利用規約を確認して下さい。
#
#------------------------------------------------------------------------------
#   
#   ツクマテのリクエスト品になります。
#   規約は「へぷたなすくろーる」の素材利用規約に準じるものとし
#   サポートに関してもそれらと同様に受け付けます。
#   
#   スキルのメモ欄に<共有スキル>と入れると
#   誰かがそのスキルを習得した時点で、全アクターが習得します。喪失も同様。
#   
#==============================================================================
#==============================================================================
# ■ Game_Actor
#------------------------------------------------------------------------------
#  アクターを扱うクラスです。このクラスは Game_Actors クラス($game_actors)
# の内部で使用され、Game_Party クラス($game_party)からも参照されます。
#==============================================================================

class Game_Actor < Game_Battler
  #--------------------------------------------------------------------------
  # ● スキルを覚える
  #--------------------------------------------------------------------------
  alias shareskill_learn_skill learn_skill
  def learn_skill(skill_id)
    shareskill_learn_skill(skill_id)
    if $data_skills[skill_id].note.include?("<共有スキル>")
      for i in 1...$data_actors.size
        if @actor_id != i and !$game_actors[i].skill_learn?($data_skills[skill_id])
          $game_actors[i].shareskill_learn_skill(skill_id)
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● スキルを忘れる
  #--------------------------------------------------------------------------
  alias shareskill_forget_skill forget_skill
  def forget_skill(skill_id)
    shareskill_forget_skill(skill_id)
    if $data_skills[skill_id].note.include?("<共有スキル>")
      for i in 1...$data_actors.size
        $game_actors[i].shareskill_forget_skill(skill_id) if @actor_id != i
      end
    end
  end
end

奈々さんの言う「致命的なエラー」がSystemStackErrorの事ならこれで直ります

原因は自身の再読み込みですね

$game_actorsからやると新メソッドの方を実行するみたいで、
それによる無限ループで抜けられず、エラーが出たようです

【追記】
※今後こちらのスクリプトを使う人へ
使用する際の規約は、奈々さんのブログの通りです
そちらを守って使って下さい
最後に編集したユーザー TOMO on 2017年1月16日(月) 19:14 [ 編集 1 回目 ]
なたね
記事: 30
登録日時: 2017年1月11日(水) 00:34

Re: 共有スキル

投稿記事by なたね » 2017年1月15日(日) 18:51

奈々さん、TOMOさん。スクリプトを作って頂き、ありがとうございました。
今回はTOMOさんの共有スキルのスクリプトを使わせていただきます。
望み通りの物で、嬉しいです。本当にありがとうございました。
奈々(なな)
記事: 103
登録日時: 2016年11月06日(日) 16:57

Re: 共有スキル 〆 制作していただきありがとうございました。

投稿記事by 奈々(なな) » 2018年7月26日(木) 02:18

古い記事に失礼致します。
リクエストは解決済みですが、知識共有のため記載させて下さい。


>>TOMOさん

バグの解析と修正をありがとうございます。
まず、エラーについてはSystemStackErrorで合っています。

確かにTOMOさんの修正版でエラーが収まったため
原因についてもTOMOさんの仰る通りと思っていたのですが
修正作業中の検証で、全く別の事実が発覚しました。


まず、$game_actorsからだと新メソッドを実行するというのは誤解で
pを打って動きを検証したところ、「基本的には」問題なく旧メソッドを実行します。
従って、それによる構造上の無限ループではありませんでした。

検証として「共有スキルに設定したファイアをエリックに習得させる」と
必ずエラーが起きる状況再現が出来るのですが
この際に「イザベルを削除、もしくは戦士等に変更する」とエラーが起きません。

逆に、TOMOさんが修正して下さったものは、同じ状況だとエラーが起きませんが
試しにエリック以外を魔女に変更してみるとスタックエラーが発生します。


結論を言いますと、「職業で初期習得するスキル」が悪さをしています。
今回だと魔女がレベル1で習得するファイア(共有スキルに設定)です。
※この時、スキルの初期化でlearn_skillが呼ばれているはずですが、共有化は起きません。

この状態でファイアを習得させると、forのループが順調に回るものの
i = 9つまりイザベル(魔女)になった途端にlearn_skillの最初に戻ります。
※恐らく、新たなメソッドとしてlearn_skillを呼び出していると思われます。

私の作った初期型は、この状況で無限ループになるため確実にエラーが起きます。
TOMOさんの改良型は、重複防止で無限ループを抑えるためエラーが起きませんが
該当キャラを増やすとループが増えていくため、負荷を超えるとエラーが起きます。


色々と検証して現象は分かりましたが、肝心の原因は今一つ分かりません。
もう少し初期化の処理を掘っていけば糸口が掴めそうな気はします。
スタックの起きない処理にするのが一番安牌なのですが
この一点以外は問題ないので、悩ましいところです。
------------------------------------------------------------------------------------
へぷたなすくろーる
http://heptanas.mamagoto.com/

VXAceのスクリプト素材及びイベント講座などをやっています。
------------------------------------------------------------------------------------

“VX / Ace:スクリプト素材のリクエスト” へ戻る