code:
;-------------------------------------------------
;キャラクターの行動制御(モジュールの使用や視界の判定など)
;
;-------------------------------------------------
;;; キャラクターが現在いるエリア内の設備の使用を試みる
;;; 使用させたい用途または属性またはモジュールリスト上のインデックス番号のいずれか一つを指定して使用する
;;; - ARGS
;;;     - CHARA_ID {int}: キャラクターID
;;;     - USAGE {string}: 設備の用途
;;;     - ELEMENT {string}: 設備の属性
;;;     - MODULE_IDX {int}: 設備のIDX
;;;     - RANDOM {int}: ランダム選択フラグ 0 スロットの上の設備を優先して使用 1 ランダムに使用
;;;     - OPTION {string(DICTIONARY)}: その他の指定オプション
;;;         - [CAPACITY:n] 設備の空き容量がn以上の場合のみ使用
;;; - RETURN
;;;     - RESULT:0 {int}: 0 失敗 1 成功
;;;     - RESULT:1 {int}: 設備のスロット番号(0番始まり)
;-------------------------------------------------
@HO_TRY_USE_MODULE(CHARA_ID, USAGE = "", ELEMENT = "", MODULE_IDX = -1, RANDOM = 0, OPTION = "")
#DIM CHARA_ID
#DIMS USAGE
#DIMS ELEMENT
#DIM  MODULE_IDX
#DIM  RANDOM
#DIMS OPTION
#DIM  DYNAMIC MODULE_ID
#DIM  DYNAMIC CHARA_IDX
#DIM  DYNAMIC OWNER_ID
#DIM  DYNAMIC USER_ID
#DIMS DYNAMIC _LIST_MODULE
#DIMS DYNAMIC _LIST_CHARA_ID
#DIMS DYNAMIC _LIST_OPTIONS
#DIM  DYNAMIC MODULE_SLOT_IDX
#DIM  DYNAMIC ROOM_IDX
#DIM  DYNAMIC IS_ACCEPTABLE

CALL HO_GET_CHARAIDX(CHARA_ID)
CHARA_IDX = RESULT
CALL HO_GET_CHARADATA(CHARA_IDX, "ROOM_IDX")
ROOM_IDX = RESULT
CALL HO_GET_MAPDATA(HO_有効マップID, ROOM_IDX, "MODULE_SLOT")
_LIST_MODULE = %RESULTS%

;用途に合致しているモジュールの一覧を作成
IF MODULE_IDX == -1
    FOR MODULE_SLOT_IDX, 0, LIST_COUNT(_LIST_MODULE)
        CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_SLOT_IDX)
        MODULE_ID = RESULT
        IF USAGE != ""
            CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
            IF LIST_INDEXOF(RESULTS, USAGE) != -1
                _LIST_OPTIONS = %LIST_ADD(_LIST_OPTIONS, TOSTR(MODULE_SLOT_IDX))%
            ENDIF
        ELSEIF ELEMENT != ""
            CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
            IF LIST_INDEXOF(RESULTS, ELEMENT) != -1
                _LIST_OPTIONS = %LIST_ADD(_LIST_OPTIONS, TOSTR(MODULE_SLOT_IDX))%
            ENDIF
        ENDIF
    NEXT
    ;使用するモジュールをIDX値で直接指定している場合
ELSE
    CALL HO_GET_MODULE_LIST(MODULE_IDX, "ROOM_IDX")
    ;キャラの現在地とモジュールの所在地が不一致ならRETURN
    IF ROOM_IDX != RESULT
        RETURN -1
    ENDIF
    CALL HO_GET_MODULE_LIST(MODULE_IDX, "MODULE_SLOT_IDX")
    _LIST_OPTIONS = %LIST_ADD(_LIST_OPTIONS, TOSTR(RESULT))%
ENDIF

IF LIST_COUNT(_LIST_OPTIONS) > 0
    ;条件を満たす設備が複数あり、ランダム指定の場合は候補リストをシャッフル
    SIF RANDOM
        CALL LIST_SHUFFLE(_LIST_OPTIONS)
    ;キャラが明示的な設備の指定なしに客室の使用を試みた場合、自身の部屋だけを使うように
    IF MODULE_IDX == -1
        CALL HO_CHECK_ROOM_TAG(ROOM_IDX, "客室")
        IF RESULT
            _LIST_OPTIONS '= ""
            _LIST_OPTIONS = %LIST_ADD(_LIST_OPTIONS, TOSTR(CHARA_IDX))%
        ENDIF
    ENDIF
ENDIF

VARI CAPACITY
FOR LOCAL, 0, LIST_COUNT(_LIST_OPTIONS)
    MODULE_SLOT_IDX = TOINT(LIST_GET(_LIST_OPTIONS, LOCAL))
    ;満員のモジュールは使えない
    CALL HO_CHECK_MODULE_CAPACITY(ROOM_IDX, MODULE_SLOT_IDX)
    CAPACITY = RESULT
    SIF CAPACITY == 0
        CONTINUE
    IF OPTION != ""
        ;空き容量が指定されている場合はその容量以上の空き容量があるかを確認
        IF DIC_CONTAINSKEY(OPTION, "CAPACITY")
            IF CAPACITY < DIC_GETINT(OPTION, "CAPACITY")
                CONTINUE
            ENDIF
        ENDIF
    ENDIF
    ;;施錠されているモジュールは使えないが、同行中なら判定をバイパス
    ;同行中は常にMASTERを追随している前提なので、MASTER側で判定する
    IS_ACCEPTABLE = 1
    CALL HO_GET_CHARADATA(CHARA_IDX, "ACTION")
    IF RESULTS == "同行中"
    ELSE
        CALL HO_IS_MODULE_LOCKED(ROOM_IDX, MODULE_SLOT_IDX)
        ;施錠中の場合
        IF RESULT == 1
            IS_ACCEPTABLE = 0
            ;MODULE_IDXを指定しての設備利用の場合
            IF MODULE_IDX != -1
                ;その設備の所有者である、その設備の所有者に招かれている
                IF !IS_ACCEPTABLE
                    CALL HO_GET_MODULE_LIST(MODULE_IDX, "OWNER_ID")
                    OWNER_ID = RESULT
                    IF OWNER_ID == CHARA_ID || TCVAR:CHARA_ID:勧誘されたキャラID == OWNER_ID
                        IS_ACCEPTABLE = 1
                    ENDIF
                ENDIF
                ;利用権があれば施錠されても使用可能とする
                IF !IS_ACCEPTABLE
                    CALL HO_GET_MODULE_LIST(MODULE_IDX, "VISITOR_ID")
                    IF LIST_INDEXOF(RESULTS, TOSTR(CHARA_ID)) != -1
                        IS_ACCEPTABLE = 1
                    ENDIF
                ENDIF
                ;施錠されている設備のなかに勧誘者または恋人がいる
                IF !IS_ACCEPTABLE
                    CALL HO_GET_CHARA_USE_THIS_MODULE(MODULE_IDX, 1)
                    _LIST_CHARA_ID = %RESULTS%
                    FOR LOCAL, 0, LIST_COUNT(_LIST_CHARA_ID)
                        USER_ID = LIST_GETINT(_LIST_CHARA_ID, LOCAL)
                        IF TCVAR:CHARA_ID:勧誘されたキャラID == USER_ID || CFLAG:CHARA_ID:カップル相手キャラID == USER_ID
                            IS_ACCEPTABLE = 1
                        ENDIF
                    NEXT
                ENDIF
            ELSE ;MODULE_IDX未指定の場合は設備利用不可
                IS_ACCEPTABLE = 0
            ENDIF
        ENDIF
    ENDIF
    ;設備使用前に既に同じ時点でウフフ目撃フラグが立っている場合、設備利用を許可しない
    ;(既に乱入判定に失敗しているはずなので)
    IF TCVAR:CHARA_ID:ウフフ目撃フラグ == 1 && TCVAR:CHARA_ID:ウフフ目撃場所 == ROOM_IDX
        IS_ACCEPTABLE = 0
    ENDIF
    IF IS_ACCEPTABLE
        ;チェック結果に問題がなければ設備を使用状態にする
        CALL HO_USE_MODULE(CHARA_ID, ROOM_IDX, MODULE_SLOT_IDX)
        ;設備使用後の再チェック
        ;情事目撃判定
        CALL HO_CHECK_UFUFU(CHARA_ID)
        IF RESULT == 1
            ;情事強制加入判定,設備が使用可能であることは既に判定できているので内部チェックは省略(BYPASS_CHECK = 1)
            CALL HO_CHECK_FORCE_JOIN_UFUFU(CHARA_ID, 1)
            ;乱入したならウフフ目撃フラグを消去
            IF RESULT
                CALL HO_FORCE_JOIN_UFUFU(CHARA_ID, 0)
                TCVAR:CHARA_ID:ウフフ目撃フラグ = 0
            ELSE
                CALL HO_STOP_USE_MODULE(CHARA_ID)
                RETURN -1
            ENDIF
        ENDIF
        RESULT:1 = MODULE_SLOT_IDX
        RETURN 1
    ENDIF
NEXT

RETURN -1

;モジュールの空きを調べる
@HO_CHECK_MODULE_CAPACITY(ROOM_IDX, MODULE_IDX)
#DIM ROOM_IDX
#DIM MODULE_IDX
#DIM MODULE_ID
#DIM DYNAMIC USER_COUNT
#DIM DYNAMIC CAPACITY

CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX)
MODULE_ID = RESULT
SIF RESULT == -1
    RETURN

IF HO_MASTER現在地 == ROOM_IDX
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    SIF MODULE_IDX == RESULT
        USER_COUNT ++
ENDIF
LOCAL:1 = 0
WHILE _DIC_HO_CHARALIST:(LOCAL:1) != "-1"
    CALL HO_GET_CHARADATA(LOCAL:1, "ROOM_IDX")
    IF RESULT != ROOM_IDX
        LOCAL:1 ++
        CONTINUE
    ENDIF
    CALL HO_GET_CHARADATA(LOCAL:1, "MODULE_USAGE")
    IF MODULE_IDX == RESULT
        USER_COUNT ++
    ENDIF
    LOCAL:1 ++
WEND
CALL HO_GET_MODULE_DATA(MODULE_ID, "人数")
CAPACITY = RESULT - USER_COUNT

RESULT:1 = USER_COUNT
RESULT:2 = RESULT
RETURN CAPACITY

;キャラデータにモジュールの使用状態を登録
@HO_USE_MODULE(CHARA_ID, ROOM_IDX, MODULE_IDX)
#DIM CHARA_IDX
#DIM ROOM_IDX
#DIM MODULE_IDX
#DIM MODULE_LIST_IDX
#DIM DYNAMIC CHARA_ID
#DIMS DYNAMIC ACTION
#DIMS DYNAMIC MODULE_ID

CALL HO_GET_CHARAIDX(CHARA_ID)
CHARA_IDX = RESULT
CALL HO_GET_MODULE_LIST_IDX(ROOM_IDX, MODULE_IDX)
MODULE_LIST_IDX = RESULT
;MODULE_LISTを後付で追加したのでCHARADATAにMODULE_(SLOT)_IDXを"MODULE_USAGE"として保持する理由がない。
;既実装処理のリファクタリングがしんどいので存置
CALL HO_SET_CHARADATA(CHARA_IDX, "MODULE_USAGE", TOSTR(MODULE_IDX))
CALL HO_SET_CHARADATA(CHARA_IDX, "USE_MODULE_IDX", TOSTR(MODULE_LIST_IDX))

;自動施錠指定のモジュールは使用時に施錠
CALL HO_CHECK_MODULE_ELEMENT(ROOM_IDX, MODULE_IDX, "自動施錠")
IF RESULT
    CALL HO_LOCK_ROOM_MODULE(CHARA_ID, ROOM_IDX, MODULE_IDX, 1)
ENDIF

;マスターが対象のモジュールを既に使っている場合は相席モード
CALL HO_GET_CHARAACT(CHARA_ID)
ACTION = %RESULTS%
CALL HO_GET_MASTER_DATA("MODULE_USAGE")
IF HO_MASTER現在地 == ROOM_IDX && RESULT == MODULE_IDX && ACTION != "同行中"
    CALL COLOR_PRINTL(@"%ANAME(CHARA_ID)%が%ANAME(MASTER)%のそばにやってきた", カラー_黄緑)
    SIF !TCVAR:CHARA_ID:交流顔合わせ済
        TCVAR:CHARA_ID:交流顔合わせ済 = 1
    TCVAR:CHARA_ID:相席フラグ = 1
    CALL HO_ADD_COMPANION(CHARA_ID, 1)
ENDIF

IF ACTION == "逢瀬中"
    IF TFLAG:覗き見モード && TFLAG:覗き見対象設備IDX == MODULE_LIST_IDX
        TFLAG:参加者数 ++
        CFLAG:CHARA_ID:調教参加フラグ  = 1
        TCVAR:CHARA_ID:覗き見対象 = 1
        CALL COLOR_PRINTL(@"%ANAME(CHARA_ID)%が情事の場に加わった…", カラー_ピンク)
    ENDIF
ENDIF

CALL C_COND_SET_INFO_TO_MAP(CHARA_ID, "USE_MODULE")

;モジュールの利用停止
@HO_STOP_USE_MODULE(CHARA_ID, SHOW_MESSAGE = 1)
#DIM CHARA_ID
#DIM SHOW_MESSAGE
#DIM DYNAMIC CHARA_IDX
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC MODULE_IDX
#DIM DYNAMIC CHARA_GROUP_LIST_IDX

CALL HO_GET_CHARAIDX(CHARA_ID)
CHARA_IDX = RESULT
CALL HO_GET_CHARADATA(CHARA_IDX, "ROOM_IDX")
ROOM_IDX = RESULT
CALL HO_GET_CHARADATA(CHARA_IDX, "MODULE_USAGE")
MODULE_IDX = RESULT
SIF MODULE_IDX == -1
    RETURN
CALL HO_GET_CHARADATA(CHARA_IDX, "CHARA_GROUP")
CHARA_GROUP_LIST_IDX = RESULT

;移動する前に身だしなみを整える
CALL HO_REDRESS(CHARA_ID)
IF RESULT && SHOW_MESSAGE > 0
    CALL HO_IS_TARGET_VISIBLE(MASTER, CHARA_ID)
    IF RESULT
        PRINTFORMW 移動する前に%ANAME(CHARA_ID, RESULT)%は%SPLIT_RAND("衣服の乱れ/着衣の乱れ/身だしなみ",1)%をそっと整えた……
    ENDIF
ENDIF

IF C_COND("設備用途:搾乳",,CHARA_ID) && IS_EQUIP_TARGET(CHARA_ID, T_N("搾乳機"))
    CALL RELEASE_EQUIP_EX(T_N("搾乳機"), -1, CHARA_ID)
ENDIF

;使用していたモジュールを解放
CALL HO_LOCK_ROOM_MODULE(CHARA_ID, ROOM_IDX, MODULE_IDX, 0)
;キャラデータのモジュール使用状況を更新
CALL HO_SET_CHARADATA(CHARA_IDX, "MODULE_USAGE", "-1")
CALL HO_SET_CHARADATA(CHARA_IDX, "USE_MODULE_IDX", "-1")
;グループに属していた場合、グループから離脱
IF CHARA_GROUP_LIST_IDX != -1
    CALL HO_LEAVE_CHARA_GROUP(CHARA_GROUP_LIST_IDX, CHARA_ID)
ENDIF
;相席モードの場合コンパニオンから離脱
IF TCVAR:CHARA_ID:相席フラグ == 1
    CALL HO_REMOVE_COMPANION(CHARA_ID)
    IF SHOW_MESSAGE > 0
        CALL COLOR_PRINTL(@"%ANAME(CHARA_ID, RESULT)%は%ANAME(MASTER)%に別れを告げて立ち去った", カラー_黄緑)
    ENDIF
    TCVAR:CHARA_ID:相席フラグ = 0
    TCVAR:CHARA_ID:同行解除フラグ = 1
ENDIF
CALL C_COND_SET_INFO_TO_MAP(CHARA_ID, "STOP_USE_MODULE")

;引数に指定した用途に合致し使用可能なモジュールをリストで返す
@HO_GET_USABLE_MODULE(USAGE, ROOM_IDX, USER_NUM = 1)
#DIMS USAGE
#DIM ROOM_IDX
#DIM USER_NUM
#DIMS DYNAMIC _LIST_MODULE
#DIMS DYNAMIC _LIST_OPTIONS
#DIM DYNAMIC MODULE_IDX
#DIM DYNAMIC MODULE_ID

VARSET RESULTS
CALL HO_GET_MAPDATA(HO_有効マップID, ROOM_IDX, "MODULE_SLOT")
_LIST_MODULE = %RESULTS%

;用途に合致しているモジュールの一覧を作成
FOR MODULE_IDX, 0, LIST_COUNT(_LIST_MODULE)
    CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX)
    MODULE_ID = RESULT
    CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
    IF LIST_INDEXOF(RESULTS, USAGE) != -1
        CALL HO_CHECK_MODULE_CAPACITY(ROOM_IDX, MODULE_IDX)
        SIF USER_NUM <= RESULT
            _LIST_OPTIONS = %LIST_ADD(_LIST_OPTIONS, TOSTR(MODULE_IDX))%
    ENDIF
NEXT
IF LIST_COUNT(_LIST_OPTIONS) != 0
    RESULTS = %_LIST_OPTIONS%
    RETURN LIST_COUNT(_LIST_OPTIONS)
ELSE
    RETURN 0
ENDIF
;-------------------------------------------------
;ルームモジュールを施錠
;LOCK = 1:ロック, LOCK = 0:アンロック
;施錠済みのモジュールを再度施錠したり、解錠済みのモジュールを再度解錠しても問題はない
;-------------------------------------------------
@HO_LOCK_ROOM_MODULE(CHARA_ID, ROOM_IDX, MODULE_IDX, LOCK = 1, MAP_ID = -1)
#DIM  CHARA_ID
#DIM  ROOM_IDX
#DIM  MODULE_IDX
#DIM  LOCK
#DIM  MAP_ID
#DIM  DYNAMIC MODULE_ID
#DIMS DYNAMIC _LIST_LOCKED_MODULE

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

VARSET RESULTS
IF LOCK == 1
    ;施錠権限がない場合施錠できない
    CALL HO_CHECK_MODULE_OWNER(ROOM_IDX, MODULE_IDX)
    SIF CHARA_ID != RESULT && RESULT != -1
        RETURN
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "LOCKED_MODULE")
    _LIST_LOCKED_MODULE = %RESULTS%
    IF RESULT == -1 ;対象ROOM_IDXに施錠リストが存在しない
        _LIST_LOCKED_MODULE = %LIST_ADD(_LIST_LOCKED_MODULE, TOSTR(MODULE_IDX))%
        CALL HO_SET_MAPDATA(ROOM_IDX, "LOCKED_MODULE", _LIST_LOCKED_MODULE)
    ELSE
        ;対象ROOM_IDXに施錠リストがあるが、対象MODULE_IDXは施錠リストに登録されていない
        IF LIST_INDEXOF(_LIST_LOCKED_MODULE, TOSTR(MODULE_IDX)) == -1
            _LIST_LOCKED_MODULE = %LIST_ADD(_LIST_LOCKED_MODULE, TOSTR(MODULE_IDX))%
            CALL HO_SET_MAPDATA(ROOM_IDX, "LOCKED_MODULE", _LIST_LOCKED_MODULE)
        ENDIF
    ENDIF
ELSE ;アンロック処理
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "LOCKED_MODULE")
    _LIST_LOCKED_MODULE = %RESULTS%
    SIF RESULT == -1
        RETURN
    IF LIST_INDEXOF(_LIST_LOCKED_MODULE, TOSTR(MODULE_IDX)) != -1
        _LIST_LOCKED_MODULE = %LIST_REMOVEAT(_LIST_LOCKED_MODULE, LIST_INDEXOF(_LIST_LOCKED_MODULE, TOSTR(MODULE_IDX)))%
        CALL HO_SET_MAPDATA(ROOM_IDX, "LOCKED_MODULE", _LIST_LOCKED_MODULE)
    ENDIF
ENDIF

;ルームモジュールの施錠判定
; RETURN 1 = 施錠中,RETURN = 0 施錠なし
@HO_IS_MODULE_LOCKED(ROOM_IDX, MODULE_IDX, MAP_ID = -1)
#DIM  ROOM_IDX
#DIM  MODULE_IDX
#DIM  MAP_ID
#DIMS DYNAMIC _LIST_LOCKED_MODULE

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
VARSET RESULTS
CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "LOCKED_MODULE")
_LIST_LOCKED_MODULE = %RESULTS%
IF LIST_INDEXOF(_LIST_LOCKED_MODULE, TOSTR(MODULE_IDX)) != -1
    RETURN 1
ELSE
    RETURN 0
ENDIF

;-------------------------------------------------
;;MPLYからMTARは視認可能か？
; MPLY_ID 主体のCHARA_ID
; MTAR_ID ターゲットのCHARA_ID
; RETURN 1 = 視認可,RETURN = 0 視認不可
;-------------------------------------------------
@HO_IS_TARGET_VISIBLE(MPLY_ID, MTAR_ID)
#DIM MTAR_ID
#DIM MPLY_ID
#DIM DYNAMIC MTAR_IDX
#DIM DYNAMIC MPLY_IDX
#DIM DYNAMIC MTAR_ROOM_IDX
#DIM DYNAMIC MPLY_ROOM_IDX
#DIM DYNAMIC MTAR_MODULE_IDX
#DIM DYNAMIC MPLY_MODULE_IDX
#DIM DYNAMIC MTAR_MODULE_ID
#DIM DYNAMIC MPLY_MODULE_ID

;ハウジングモード外から呼び出されたなら、見えてる扱いにする
IF !FLAG:ハウジングモード
    RETURN 1
ENDIF

;MPLYの設定
IF MPLY_ID == MASTER
    MPLY_ROOM_IDX = HO_MASTER現在地
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    MPLY_MODULE_IDX = RESULT
ELSE
    CALL HO_GET_CHARAIDX(MPLY_ID)
    MPLY_IDX = RESULT
    CALL HO_GET_CHARADATA(MPLY_IDX, "ROOM_IDX")
    MPLY_ROOM_IDX = RESULT
    CALL HO_GET_CHARADATA(MPLY_IDX, "MODULE_USAGE")
    MPLY_MODULE_IDX = RESULT
ENDIF

;MTARの設定
IF MTAR_ID == MASTER
    MTAR_ROOM_IDX = HO_MASTER現在地
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    MTAR_MODULE_IDX = RESULT
ELSE
    CALL HO_GET_CHARAIDX(MTAR_ID)
    MTAR_IDX = RESULT
    CALL HO_GET_CHARADATA(MTAR_IDX, "ROOM_IDX")
    MTAR_ROOM_IDX = RESULT
    CALL HO_GET_CHARADATA(MTAR_IDX, "MODULE_USAGE")
    MTAR_MODULE_IDX = RESULT
ENDIF
;MTARとMPLYが同じ部屋にいない
SIF MPLY_ROOM_IDX != MTAR_ROOM_IDX
    RETURN 0
;MASTERがMTARを覗いている
IF TFLAG:覗き見モード
    IF TCVAR:MTAR_ID:覗き見対象
        RETURN 1
    ENDIF
ENDIF
;MTARとMPLYがどちらもモジュールを使用しておらず、同じ部屋にいる
SIF MTAR_MODULE_IDX == -1 && MPLY_MODULE_IDX == -1 && MPLY_ROOM_IDX == MTAR_ROOM_IDX
    RETURN 1
RESULT = 0
SIF MTAR_MODULE_IDX != -1
    CALL HO_CHECK_MODULE_ELEMENT(MTAR_ROOM_IDX, MTAR_MODULE_IDX, "遮蔽")
;MTARがモジュールを使用しており、かつ遮蔽されている
IF RESULT == 1
    ;;MTARが遮蔽されている
    ;MPLY,MTARが同じルームのモジュールを使っているなら見えていると判断
    IF MPLY_ROOM_IDX == MTAR_ROOM_IDX && MPLY_MODULE_IDX == MTAR_MODULE_IDX
        RETURN 1
    ELSE
        RETURN 0
    ENDIF
    ;MTARが遮蔽されていない
ELSE
    ;MPLYがモジュールを使っておらず同じ部屋にいるならば見えていると判断
    SIF MPLY_MODULE_IDX == -1 && MPLY_ROOM_IDX == MTAR_ROOM_IDX
        RETURN 1
    ;MPLYが遮蔽されているなら見えていないと判断
    CALL HO_CHECK_MODULE_ELEMENT(MPLY_ROOM_IDX, MPLY_MODULE_IDX, "遮蔽")
    IF RESULT == 1
        RETURN 0
    ELSE
        ;MTAR,MPLYともに遮蔽されていない
        RETURN 1
    ENDIF
ENDIF

RETURN 0

;-------------------------------------------------
;;モジュールのオーナーを調べる
; 現状ではクルーの私室が誰のものかを判別する以外の用途がない
; 個別のモジュールに持ち主を指定する場合、拡張する必要がでてくるかも
; RETURN CHARA_ID(OWNER指定なし = -1)
;-------------------------------------------------
@HO_CHECK_MODULE_OWNER(ROOM_IDX, MODULE_IDX, MAP_ID = -1)
#DIM ROOM_IDX
#DIM MODULE_IDX
#DIM MAP_ID
#DIM DYNAMIC MODULE_ID
#DIM DYNAMIC CHARA_IDX

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX, MAP_ID)
MODULE_ID = RESULT
IF MODULE_ID == HO_CREW_PRIVATE_ROOM_ID
    CHARA_IDX = MODULE_IDX
    CALL HO_GET_CHARADATA(CHARA_IDX, "CHARA_ID")
    RETURN RESULT
ENDIF

RETURN -1

;-------------------------------------------------
;プレイヤーのモジュール使用に関する処理
; RESULT: -1=利用不可, 0=利用不可だが成功, 1=利用成功
;-------------------------------------------------
;;使用
@HO_MASTER_USE_MODULE(ROOM_IDX, MODULE_IDX)
#DIM ROOM_IDX
#DIM MODULE_IDX
#DIM DYNAMIC MODULE_LIST_IDX
#DIM DYNAMIC MODULE_ID
#DIM DYNAMIC MODULE_CAPACITY
#DIM DYNAMIC CHARA_ID
#DIM DYNAMIC NUM_COMPANION
#DIMS DYNAMIC MODULE_NAME
#DIMS DYNAMIC _LIST_COMPANION
#DIMS DYNAMIC _LIST_ADD_MEMBER
#DIMS DYNAMIC _LIST_PERMISSION
#DIMS DYNAMIC _LIST_USAGE
#DIM DYNAMIC HAS_PERMISSION
#DIM DYNAMIC ADD_MEMBER_NUM
#DIMS DYNAMIC ACTION
#DIM DYNAMIC SEDUCTION_LV
#DIM DYNAMIC CUT_DESCRIPTION

CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX)
MODULE_ID = RESULT
CALL HO_GET_FOLLOWER_LIST
NUM_COMPANION = RESULT
_LIST_COMPANION = %RESULTS%
CALL HO_GET_MODULE_DATA(MODULE_ID, "MODULE_NAME")
MODULE_NAME = %RESULTS%
CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
_LIST_USAGE = %RESULTS%

;インテリアなら使用時効果処理が定義されていれば呼び出す
;インテリアは基本的にキャパシティ0で継続使用できないので効果処理後RETURN
IF LIST_INDEXOF(_LIST_USAGE, "インテリア") != -1
    TRYCCALLFORM HO_MODULE_USE_INTERIOR_{MODULE_ID}
    CATCH
    ENDCATCH
    RETURN 0
ENDIF

;既にこのモジュールを使っている
CALL HO_GET_MASTER_DATA("MODULE_USAGE")
IF RESULT == MODULE_IDX
    CALL HO_MASTER_STOP_USE_MODULE(ROOM_IDX, MODULE_IDX)
    RETURN -1
ENDIF

;覗き見判定
;RESULT補足
;1 は情事を覗き見
;2 は情事が起きているが覗き見しない
;いずれも設備は使用しないのでRETURN
IF !FLAG:ウフフフラグ
    CALL HO_CHECK_PEEPING(ROOM_IDX, MODULE_IDX)
    IF RESULT
        RETURN 0
    ENDIF
ENDIF

;モジュールに空きはあるか
CALL HO_CHECK_MODULE_CAPACITY(ROOM_IDX, MODULE_IDX)
MODULE_CAPACITY = RESULT
IF MODULE_CAPACITY == 0
    CALL COLOR_PRINTW("ここは満員のようだ", カラー_注意)
    CLEARLINE 1
    RETURN -1
ENDIF

IF MODULE_CAPACITY < NUM_COMPANION + 1
    CALL COLOR_PRINTW(@"この場所を使うには同行者の数が多すぎるようだ(空席:{MODULE_CAPACITY})", カラー_注意)
    CLEARLINE 1
    RETURN -1
ENDIF

;所有権判定
HAS_PERMISSION = 0
CALL HO_GET_MODULE_LIST_IDX(ROOM_IDX, MODULE_IDX)
MODULE_LIST_IDX = RESULT
CALL HO_GET_MODULE_LIST(MODULE_LIST_IDX, "PERMISSION_LIST")
IF RESULT != -1
    _LIST_PERMISSION = %RESULTS%
    ;MASTERに権限がない
    IF LIST_INDEXOF(_LIST_PERMISSION, TOSTR(MASTER)) == -1
        ;権限を持つメンバーが同行しているか？
        CALL HO_GET_COMPANION_LIST
        _LIST_COMPANION = %RESULTS%
        FOR LOCAL, 0, LIST_COUNT(_LIST_COMPANION)
            IF LIST_INDEXOF(_LIST_PERMISSION, LIST_GET(_LIST_COMPANION, LOCAL)) != -1
                HAS_PERMISSION ++
            ENDIF
        NEXT
        ; IF !HAS_PERMISSION
        ;     CALL COLOR_PRINTW("この場所を使うには所有者と一緒にいるか、所有者の許可がいる", カラー_注意)
        ;     CLEARLINE 1
        ;     RETURN
        ; ENDIF
    ELSE
        HAS_PERMISSION ++
    ENDIF
ENDIF

;モジュールの施錠確認
CALL HO_IS_MODULE_LOCKED(ROOM_IDX, MODULE_IDX)
IF RESULT == 1
    IF !HAS_PERMISSION
        CALL FL_PLAYSE("Door_close_0.mp3")
        CALL COLOR_PRINTW("ここは鍵が掛かっているようだ", カラー_注意)
        CALL HOUSING_UNLOCK_DOOR(ROOM_IDX, MODULE_IDX, 500)
        SIF RESULT != 1
            RETURN -1
    ELSE
        CALL FL_PLAYSE("Door_open_0.mp3")
        CALL COLOR_PRINTL("ここは鍵が掛かっているようだ", カラー_注意)
        CALL COLOR_PRINTW(@"%ANAME(MASTER)%は鍵を使って錠を外した…", カラー_注意)
    ENDIF
ENDIF

;モジュールの用途別の利用可能判定
IF LIST_GMATCH(_LIST_USAGE, "OR", "売春", "触手")
    FOR LOCAL, 0, LIST_COUNT(_LIST_COMPANION)
        CHARA_ID = TOINT(LIST_GET(_LIST_COMPANION, LOCAL))
        CALL SKILL_GET_LEVEL(CHARA_ID, スキル_大分類_性技, "SEDUCTION")
        SEDUCTION_LV = RESULT
        {
            IF CFLAG:CHARA_ID:捕虜先
                || IS_SLAVE(CHARA_ID)
                || IS_NASTY(CHARA_ID, 素質_淫乱_精液便女)
                || IS_NASTY(CHARA_ID, 素質_淫乱_娼婦)
                || CFLAG:CHARA_ID:スケベモブ
                || (TALENT:CHARA_ID:合意 && SEDUCTION_LV >= 2)
        }
        ELSE
            CALL COLOR_PRINTW(@"%ANAME(CHARA_ID)%はここに一緒に入るのを嫌がっているようだ", カラー_注意)
            CLEARLINE 1
            RETURN -1
        ENDIF
    NEXT
ELSE
    IF LIST_GMATCH(_LIST_USAGE, "OR", "入浴", "排泄") || (MODULE_NAME == "サウナルーム")
        FOR LOCAL, 0, LIST_COUNT(_LIST_COMPANION)
            CHARA_ID = TOINT(LIST_GET(_LIST_COMPANION, LOCAL))
            IF (TALENT:CHARA_ID:合意 != 1 || TALENT:CHARA_ID:親友) && !CFLAG:CHARA_ID:捕虜先 && !CFLAG:CHARA_ID:スケベモブ
                CALL COLOR_PRINTW(@"%ANAME(CHARA_ID)%はここに一緒に入るのを嫌がっているようだ", カラー_注意)
                CLEARLINE 1
                RETURN -1
            ENDIF
        NEXT
    ENDIF
ENDIF
;;モジュールが使用可能な場合
;-------------------------------------------------
;コマンド継続状況を解除
FOR CHARA_ID, 0, CHARANUM
    IF IS_PARTICIPATE_TRAIN(CHARA_ID)
        ;EQUIP解除
        CALL RELEASE_ALL_EQUIP(CHARA_ID, 1)
    ENDIF
NEXT

;既に別のモジュールを使用中だった場合は使用を中止
CALL HO_GET_MASTER_DATA("MODULE_USAGE")
IF RESULT != -1
    CALL HO_MASTER_STOP_USE_MODULE()
ENDIF

;相席者を交流対象に加える
CALL HO_GET_MODULE_USE_MEMBER(ROOM_IDX, MODULE_IDX)
_LIST_ADD_MEMBER = %RESULTS%
ADD_MEMBER_NUM = RESULT
FOR LOCAL, 0, ADD_MEMBER_NUM
    CHARA_ID = TOINT(LIST_GET(_LIST_ADD_MEMBER, LOCAL))

    ;交流対象追加前処理
    ;-------------------------------------------------

    ;ラッキースケベ
    CALL HO_GET_CHARAACT(CHARA_ID)
    ACTION = %RESULTS%
    SELECTCASE ACTION
        CASE "自慰中"
            IF RAND:2
                CALLF TAG_PRINT(@"%ANAME(MASTER)%の目に一心不乱に痴態に耽る%ANAME(CHARA_ID)%の姿が飛び込んできた…", 1)
                WAIT
            ELSE
                IF !HAS_PENIS(CHARA_ID)
                    CALLF TAG_PRINT(@"%ANAME(MASTER)%は%ANAME(CHARA_ID)%が物陰で下腹部を弄って快楽に耽っているのを目撃してしまった…", 1)
                    WAIT
                ELSE
                    CALLF TAG_PRINT(@"%ANAME(MASTER)%は%ANAME(CHARA_ID)%が物陰で陰茎を扱き上げて快楽に耽っているのを目撃してしまった…", 1)
                    WAIT
                ENDIF
            ENDIF
        CASEELSE
            CALL HO_CHECK_NAKED(CHARA_ID)
            SELECTCASE RESULT
                CASE 1
                    CALLF TAG_PRINT(@"%ANAME(MASTER)%の目に%ANAME(CHARA_ID)%の@C:{カラー_ピンク}@%STR_BODY("胸：長", CHARA_ID)%@/C@が飛び込んできた…", 1)
                    WAIT
                CASE 2
                    CALLF TAG_PRINT(@"%ANAME(MASTER)%の目に%ANAME(CHARA_ID)%の@C:{カラー_ピンク}@一糸まとわぬ%SPLIT_RAND("下腹部/陰部/秘所")%@/C@が飛び込んできた…", 1)
                    WAIT
                CASE 3
                    CALLF TAG_PRINT(@"%ANAME(MASTER)%の目に%ANAME(CHARA_ID)%の@C:{カラー_ピンク}@一糸まとわぬ%STR_BODY("身体", CHARA_ID)%@/C@が飛び込んできた…", 1)
                    WAIT
            ENDSELECT
    ENDSELECT

    ;交流対象追加
    ;-------------------------------------------------
    IF LOCAL == 0
        IF CUT_DESCRIPTION
            CALL COLOR_PRINTW(@"%ANAME(CHARA_ID, ADD_MEMBER_NUM)%と一緒になった", カラー_黄緑)
        ENDIF
    ENDIF
    SIF !TCVAR:CHARA_ID:交流顔合わせ済
        TCVAR:CHARA_ID:交流顔合わせ済 = 1
    TCVAR:CHARA_ID:相席フラグ = 1
    CALL HO_ADD_COMPANION(CHARA_ID, 1)

NEXT

;同行者にも使用させる
CALL HO_GET_COMPANION_LIST()
NUM_COMPANION = RESULT
_LIST_COMPANION = %RESULTS%
FOR LOCAL:0, 0, NUM_COMPANION
    CALL HO_USE_MODULE(TOINT(LIST_GET(_LIST_COMPANION, LOCAL:0)), ROOM_IDX, MODULE_IDX)
NEXT

;自動施錠指定のモジュールは使用時に施錠
CALL HO_CHECK_MODULE_ELEMENT(ROOM_IDX, MODULE_IDX, "自動施錠")
IF RESULT
    CALL HO_LOCK_ROOM_MODULE(MASTER, ROOM_IDX, MODULE_IDX)
ENDIF

;MASTERのモジュール使用状態を更新する
CALL HO_CHECK_MODULE_OWNER(ROOM_IDX, MODULE_IDX)
CALL HO_SET_MASTER_DATA("MODULE_USAGE", TOSTR(MODULE_IDX))
;広域変数にMASTERが使用中のモジュールの情報を更新する。
CALL HO_GET_MODULE_LIST_IDX(ROOM_IDX, MODULE_IDX)
HO_MASTER_USE_MODULE_LIST_IDX = RESULT
;MASTERのC_COND更新
CALL C_COND_SET_INFO_TO_MAP(MASTER, "USE_MODULE")

;モジュール使用時の押し倒し判定
IF NUM_COMPANION == 1
    CHARA_ID = TOINT(LIST_GET(_LIST_COMPANION, 0))
    CALL HO_CHARAACT_CHECK_NPC_PUSHDOWN_MASTER(CHARA_ID)
ENDIF

RETURN 1

;;モジュールの使用を止める
@HO_MASTER_STOP_USE_MODULE(ROOM_IDX = -1, MODULE_IDX = -1, SHOW_MESSAGE = 1)
#DIM ROOM_IDX
#DIM MODULE_IDX
#DIM SHOW_MESSAGE
#DIM DYNAMIC CHARA_ID
#DIM DYNAMIC MODULE_ID
#DIM DYNAMIC NUM_COMPANION
#DIMS DYNAMIC _LIST_COMPANION
#DIMS DYNAMIC _LIST_REMOVE_MEMBER
#DIM DYNAMIC REMOVE_MEMBER_NUM
#DIM DYNAMIC MESSAGE_PRINTED_FLAG

SIF ROOM_IDX == -1
    ROOM_IDX = HO_MASTER現在地
IF MODULE_IDX == -1
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    MODULE_IDX = RESULT
ENDIF

;コマンド継続状況を解除
FOR CHARA_ID, 0, CHARANUM
    IF IS_PARTICIPATE_TRAIN(CHARA_ID)
        ;EQUIP解除
        CALL RELEASE_ALL_EQUIP(CHARA_ID, 1)
    ENDIF
NEXT

;相席者を交流対象から除外する
CALL HO_GET_MODULE_USE_MEMBER(ROOM_IDX, MODULE_IDX)
_LIST_REMOVE_MEMBER = %RESULTS%
REMOVE_MEMBER_NUM = RESULT
FOR LOCAL, 0, REMOVE_MEMBER_NUM
    CHARA_ID = TOINT(LIST_GET(_LIST_REMOVE_MEMBER, LOCAL))
    IF TCVAR:CHARA_ID:相席フラグ == 1
        IF SHOW_MESSAGE > 0
            CALL COLOR_PRINTL(@"%ANAME(CHARA_ID)%と別れた", カラー_黄緑)
        ENDIF
        CALL HO_REMOVE_COMPANION(CHARA_ID)
        TCVAR:CHARA_ID:相席フラグ = 0
        MESSAGE_PRINTED_FLAG = 1
    ENDIF
NEXT
SIF MESSAGE_PRINTED_FLAG
    WAIT
;コンパニオンリストを更新
IF MODULE_IDX != -1
    ;施錠している場合は解錠
    CALL HO_IS_MODULE_LOCKED(ROOM_IDX, MODULE_IDX)
    SIF RESULT && REMOVE_MEMBER_NUM == 0
        CALL HO_LOCK_ROOM_MODULE(MASTER, ROOM_IDX, MODULE_IDX, 0)
    ; ;MODULE_IDに設定されている使用中止メッセージを出力 -> いらない気がする
    ; CALL HO_GET_MODULE_ID2(HO_MASTER現在地, MODULE_IDX)
    ; MODULE_ID = RESULT
    ; CALL HO_CHECK_MODULE_OWNER(ROOM_IDX, MODULE_IDX)
    ; IF RESULT == -1
    ;     TRYCALLFORM HO_MODULE_USE_MESSAGE_{MODULE_ID}(MASTER, 1)
    ; ELSE
    ;     TRYCALLFORM HO_MODULE_USE_MESSAGE_{MODULE_ID}(MASTER, 1, RESULT)
    ; ENDIF
    ; CALL HO_PRINT_LOG(RESULTS)
ENDIF
CALL HO_GET_COMPANION_LIST
NUM_COMPANION = RESULT
_LIST_COMPANION = %RESULTS%

;MASTERのモジュール使用状態を未使用に
CALL HO_SET_MASTER_DATA("MODULE_USAGE", "-1")
;広域変数のMASTERが使用中のモジュールの情報を初期化
HO_MASTER_USE_MODULE_LIST_IDX = -1

;同行者の使用状態も解除
FOR LOCAL:0, 0, NUM_COMPANION
    CALL HO_STOP_USE_MODULE(TOINT(LIST_GET(_LIST_COMPANION, LOCAL:0)))
NEXT

;特定のエリアエフェクトの解除判定
CALL HO_ROOM_EFFECT_REMOVE_CHECK(HO_MASTER現在地)

;行動不能状態になったマスターを強制的に移動させる
@HO_FORCE_MASTER_REST
#DIM DYNAMIC NUM_COMPANION
#DIMS DYNAMIC _LIST_COMPANION
#DIM DYNAMIC OPTION_NUM
#DIMS DYNAMIC _LIST_OPTIONS

;全エリアの施錠フラグをクリア
FOR LOCAL:0, 0, HO_MAX_ROOMNUM
    CALL HO_SET_MAPDATA(LOCAL:0, "IS_LOCKED", "0")
NEXT

CALL HO_MASTER_STOP_USE_MODULE

;お持ち帰りイベント発生なら以降の処理を中断
CALL HO_TAKE_AWAY_EVENT()
SIF RESULT
    RETURN

CALL HO_GET_COMPANION_LIST
NUM_COMPANION = RESULT
_LIST_COMPANION = %RESULTS%

FOR LOCAL:0, 0, NUM_COMPANION
    CALL HO_REMOVE_COMPANION(TOINT(LIST_GET(_LIST_COMPANION, LOCAL:0)))
NEXT

CALL HO_FIND_ROOM_BY_TAG("プレイヤー私室")
CALL HO_MOVE_MASTER(RESULT, 1)
CALL HO_GET_USABLE_MODULE("仮眠", HO_MASTER現在地)
OPTION_NUM = RESULT
_LIST_OPTIONS = %RESULTS%
IF TCVAR:MASTER:離脱フラグ == 離脱フラグ_睡眠
    CALL HO_MASTER_USE_MODULE(HO_MASTER現在地, TOINT(LIST_GET(_LIST_OPTIONS, RAND(0, OPTION_NUM))))
    CALL COLOR_PRINTW(@"すっかり酔い潰れてしまった%ANAME(MASTER)%はいつの間にか私室で横になっていた…", カラー_注意)
    TCVAR:MASTER:離脱フラグ = 0
    IF IS_DRUNK(MASTER) > 2
        PALAM:MASTER:酔い = 6000
    ENDIF
    BASE:(MASTER):体力 = LIMIT(BASE:(MASTER):体力 + 600, BASE:(MASTER):体力, MAXBASE:(MASTER):体力)
    BASE:(MASTER):気力 = LIMIT(BASE:(MASTER):気力 + 450, BASE:(MASTER):気力, MAXBASE:(MASTER):気力)
ELSE
    IF OPTION_NUM != 0
        CALL HO_MASTER_USE_MODULE(HO_MASTER現在地, TOINT(LIST_GET(_LIST_OPTIONS, RAND(0, OPTION_NUM))))
        CALL COLOR_PRINTW(@"疲れ切った%ANAME(MASTER)%は私室で横になり仮眠をとることにした", カラー_注意)
        TCVAR:MASTER:行動不能フラグ = 0
        TCVAR:MASTER:失神フラグ = 0
        BASE:(MASTER):体力 = LIMIT(BASE:(MASTER):体力 + 1200, BASE:(MASTER):体力, MAXBASE:(MASTER):体力)
        BASE:(MASTER):気力 = LIMIT(BASE:(MASTER):気力 + 900, BASE:(MASTER):気力, MAXBASE:(MASTER):気力)
    ELSE
        CALL COLOR_PRINTW(@"疲れ切った%ANAME(MASTER)%は私室に戻り休憩することにした。……が、部屋に寝具が無いためあまりきちんと休めなかった", カラー_注意)
        TCVAR:MASTER:行動不能フラグ = 0
        TCVAR:MASTER:失神フラグ = 0
        BASE:(MASTER):体力 = LIMIT(BASE:(MASTER):体力 + 600, BASE:(MASTER):体力, MAXBASE:(MASTER):体力)
        BASE:(MASTER):気力 = LIMIT(BASE:(MASTER):気力 + 450, BASE:(MASTER):気力, MAXBASE:(MASTER):気力)
    ENDIF
ENDIF
;3時間経過させる
CALL HOUSING_TIME_PROGRESS(180 / HO_単位時間, 1)

;-------------------------------------------------
; 条件を満たすメンバーをマスターが使用しているモジュールに招待する
;-------------------------------------------------
@HO_MASTER_TRY_INVITE(CHARA_ID, FORCE_INVITE = 0)
#DIM  CHARA_ID
#DIM  FORCE_INVITE
#DIM  DYNAMIC ROOM_IDX
#DIM  DYNAMIC MODULE_IDX
#DIM  DYNAMIC MODULE_ID
#DIMS DYNAMIC MODULE_NAME
#DIMS DYNAMIC _LIST_USAGE
#DIM DYNAMIC SEDUCTION_LV

ROOM_IDX = HO_MASTER現在地
CALL HO_GET_MASTER_DATA("MODULE_USAGE")
MODULE_IDX = RESULT
SIF MODULE_IDX == -1
    RETURN 0
CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX)
MODULE_ID = RESULT
CALL HO_GET_MODULE_DATA(MODULE_ID, "MODULE_NAME")
MODULE_NAME = %RESULTS%
CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
_LIST_USAGE = %RESULTS%

;モジュールに空きがあるかチェック
CALL HO_CHECK_MODULE_CAPACITY(ROOM_IDX, MODULE_IDX)
IF RESULT == 0 && !FORCE_INVITE
    CALL COLOR_PRINTW(@"%ANAME(CHARA_ID)%を同じ席に誘おうとしたが、席に空きがない", カラー_注意)
    RETURN 0
ELSEIF RESULT == 0 && FORCE_INVITE
    PRINTFORMW エラー：キャパシティに空きのない設備に対してFORCE_INVITEが実行されました
    RETURN 0
ENDIF

IF !FORCE_INVITE
    ;キャラが招待可能な行動状態かチェック。とりあえず待機ならOK
    CALL HO_GET_CHARAACT(CHARA_ID)
    IF !GROUPMATCH(RESULTS, "待機", "休憩中", "拘束中")
        CALL COLOR_PRINTW(@"%ANAME(CHARA_ID)%を同じ席に誘おうとしたが、取込中のようだ", カラー_注意)
        RETURN 0
    ENDIF

    ;モジュールの用途別の利用可能判定
    IF LIST_GMATCH(_LIST_USAGE, "OR", "売春", "触手")
        CALL SKILL_GET_LEVEL(CHARA_ID, スキル_大分類_性技, "SEDUCTION")
        SEDUCTION_LV = RESULT
        {
            IF CFLAG:CHARA_ID:捕虜先
                || IS_SLAVE(CHARA_ID)
                || IS_NASTY(CHARA_ID, 素質_淫乱_精液便女)
                || IS_NASTY(CHARA_ID, 素質_淫乱_娼婦)
                || CFLAG:CHARA_ID:スケベモブ
                || (TALENT:CHARA_ID:合意 && SEDUCTION_LV >= 2)
        }
        ELSE
            CALL COLOR_PRINTW(@"%ANAME(CHARA_ID)%はここに一緒に入るのを嫌がっているようだ", カラー_注意)
            RETURN 0
        ENDIF
    ELSE
        IF LIST_GMATCH(_LIST_USAGE, "OR", "入浴", "排泄") || (MODULE_NAME == "サウナルーム")
            IF TALENT:CHARA_ID:合意 != 1 && !CFLAG:CHARA_ID:捕虜先 && !CFLAG:CHARA_ID:スケベモブ
                CALL COLOR_PRINTW(@"%ANAME(CHARA_ID)%はここに一緒に入るのを嫌がっているようだ", カラー_注意)
                RETURN 0
            ENDIF
        ENDIF
    ENDIF
ENDIF

;CHARA_IDをコンパニオンに加える
CALL HO_ADD_COMPANION(CHARA_ID,,FORCE_INVITE)
;コンパニオン追加条件を満たしていなかった
SIF RESULT == 0
    RETURN 1
;MASTERと同じモジュールを使わせる
CALL HO_USE_MODULE(CHARA_ID, ROOM_IDX, MODULE_IDX)
RETURN 1

;-------------------------------------------------
;;; キャラのステータスを取得・変更する関数
;;; - ARGS
;;;   - CHARA_ID: キャラID
;;;   - OPTIONS: オプション文字列
;;;     - "" : 各部位精液量をそのまま返却
;;;     - "体外のみ": 身体の外側の精液のみをカウント
;;;     - "体内のみ": 身体の内側の精液のみをカウント
;;; - RETURN
;;;   精液量
;-------------------------------------------------
@HO_CHECK_CUM_AMOUNT(CHARA_ID, OPTIONS = "")
#DIM  CHARA_ID
#DIMS OPTIONS
#DIM  DYNAMIC CUM_AMOUNT
#FUNCTION
FOR LOCAL,0, CUM_SLOT_NUM
    SIF OPTIONS == "体内のみ" && !GROUPMATCH(LOCAL:0, 射精部位_アナル, 射精部位_膣内, 射精部位_尿道, 射精部位_オナホ, 射精部位_触手, 射精部位_ゴム, 射精部位_口)
        CONTINUE
    SIF OPTIONS == "体外のみ" && GROUPMATCH(LOCAL:0, 射精部位_アナル, 射精部位_膣内, 射精部位_尿道, 射精部位_オナホ, 射精部位_触手, 射精部位_ゴム, 射精部位_口)
        CONTINUE
    CUM_AMOUNT += CUM_GET_AMOUNT:CHARA_ID:(LOCAL:0)
NEXT
RETURNF CUM_AMOUNT

;-------------------------------------------------
;;; 汚れを洗浄する処理。入浴などから呼ばれる
;;; 体内とみなす部位はデフォルトで値をクリアしない
;-------------------------------------------------
@HO_WASH(CHARA_ID, 体内を除外 = 1)
#DIM CHARA_ID
#DIM 体内を除外
#DIM DYNAMIC CUM_AMOUNT
#DIM DYNAMIC MODULE_ID

FOR LOCAL,0, CUM_SLOT_NUM
    IF 体内を除外 && GROUPMATCH(LOCAL:0, 射精部位_アナル, 射精部位_膣内, 射精部位_尿道, 射精部位_オナホ, 射精部位_触手, 射精部位_ゴム, 射精部位_口)
        CONTINUE
    ENDIF
    IF C_COND("設備用途:精液風呂",, CHARA_ID)
        CUM_GET_AMOUNT:CHARA_ID:(LOCAL:0) += RAND(8, 15)
    ELSE
        CUM_GET_AMOUNT:CHARA_ID:(LOCAL:0) = 0
    ENDIF
NEXT
TCVAR:CHARA_ID:汗量 = 0

;-------------------------------------------------
;;; 特定のアクションをしているメンバーをリスト形式で返却
;;; ACTIONは','区切りで10個まで複数指定できる
;-------------------------------------------------
@HO_CHECK_PLAY_WITH(ACTION)
#DIMS ACTION
#DIMS DYNAMIC _LIST_MEMBER
#DIM DYNAMIC MEMBER_NUM
#DIMS DYNAMIC _LIST_PLAY_WITH
#DIM DYNAMIC CHARA_ID

VARS ACTIONS, 10
VARI ACTIONNUM
SPLIT ACTION, ",", ACTIONS
ACTIONNUM = RESULT

LOCAL:1 = 0
VARSET RESULTS
CALL HO_GET_COMPANION_LIST
SIF RESULT == 0
    RETURN 0
MEMBER_NUM = RESULT
_LIST_MEMBER = %RESULTS%
FOR LOCAL, 0, MEMBER_NUM
    CHARA_ID = TOINT(LIST_GET(_LIST_MEMBER, LOCAL))
    IF TCVAR:CHARA_ID:相席フラグ != 1
        LOCAL:1 ++
        _LIST_PLAY_WITH = %LIST_ADD(_LIST_PLAY_WITH, TOSTR(CHARA_ID))%
    ELSE
        CALL HO_GET_CHARAACT(CHARA_ID)
        VARI I
        FOR I, 0, ACTIONNUM
            IF RESULTS == ACTIONS:I
                LOCAL:1 ++
                _LIST_PLAY_WITH = %LIST_ADD(_LIST_PLAY_WITH, TOSTR(CHARA_ID))%
            ENDIF
        NEXT
    ENDIF
NEXT
RESULTS = %_LIST_PLAY_WITH%
RETURN LOCAL:1

;指定したエリアと同じエリアにいるキャラをリスト形式で取得
@HO_GET_MEMBER_IN_ROOM(ROOM_IDX, INCLUDE_MASTER = 1)
#DIM ROOM_IDX
#DIM INCLUDE_MASTER
#DIM  DYNAMIC IDX
#DIM  DYNAMIC CHARA_ID
#DIMS DYNAMIC _LIST_MEMBER

IF INCLUDE_MASTER
    IF HO_MASTER現在地 == ROOM_IDX
        _LIST_MEMBER = %LIST_ADD(_LIST_MEMBER, TOSTR(MASTER))%
    ENDIF
ENDIF

WHILE _DIC_HO_CHARALIST:IDX != "-1"
    CALL HO_GET_CHARADATA(IDX, "ROOM_IDX")
    IF RESULT == ROOM_IDX
        CALL HO_GET_CHARADATA(IDX, "CHARA_ID")
        CHARA_ID = RESULT
        _LIST_MEMBER = %LIST_ADD(_LIST_MEMBER, TOSTR(CHARA_ID))%
    ENDIF
    IDX ++
WEND

RESULTS = %_LIST_MEMBER%
RETURN LIST_COUNT(_LIST_MEMBER)

;指定したエリアと同じエリアいてかつ指定した行動をとっているキャラをリスト形式で取得
@HO_GET_MEMBER_IN_ROOM_BY_ACTION(ROOM_IDX, ACTION, INCLUDE_MASTER = 1)
#DIM  ROOM_IDX
#DIMS ACTION
#DIM  INCLUDE_MASTER
#DIM  DYNAMIC IDX
#DIM  DYNAMIC CHARA_ID
#DIMS DYNAMIC _LIST_ALL_MEMBER
#DIMS DYNAMIC _LIST_MEMBER

IF INCLUDE_MASTER
    IF HO_MASTER現在地 == ROOM_IDX
        _LIST_ALL_MEMBER = %LIST_ADD(_LIST_MEMBER, TOSTR(MASTER))%
    ENDIF
ENDIF

CALL HO_GET_MEMBER_IN_ROOM(ROOM_IDX, INCLUDE_MASTER)
_LIST_ALL_MEMBER += RESULTS
FOR LOCAL, 0, LIST_COUNT(_LIST_ALL_MEMBER)
    CHARA_ID = TOINT(LIST_GET(_LIST_ALL_MEMBER, LOCAL))
    CALL HO_GET_CHARAACT(CHARA_ID)
    IF ACTION == RESULTS
        _LIST_MEMBER = %LIST_ADD(_LIST_MEMBER, TOSTR(CHARA_ID))%
    ENDIF
NEXT
RESULTS = %_LIST_MEMBER%
RETURN LIST_COUNT(_LIST_MEMBER)


code:
;-------------------------------------------------
;キャラクターグループリスト
;-------------------------------------------------
@HO_SET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, DATANAME, VALUES)
#DIM  CHARA_GROUP_LIST_IDX
#DIMS DATANAME
#DIMS VALUES
#DIM  MAP_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
SIF _DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX == "-1"
    _DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX '= ""

_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX = %DIC_SET(_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX, DATANAME, VALUES)%
RETURN

@HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, DATANAME)
#DIM MAP_ID
#DIM  CHARA_GROUP_LIST_IDX
#DIM ROOM_IDX
#DIMS DATANAME

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

VARSET RESULTS
SIF DIC_GET(_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX, DATANAME) == ""
    RETURN -1

ISNUMERIC DIC_GET(_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX, DATANAME)
IF RESULT
    RETURN TOINT(DIC_GET(_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX, DATANAME))
ELSE
    RESULTS = %DIC_GET(_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX, DATANAME)%
    RETURN
ENDIF

@HO_FORM_CHARA_GROUP(ACTION, MODULE_LIST_IDX, CHARA_ID)
#DIMS ACTION
#DIM MODULE_LIST_IDX
#DIM CHARA_ID
#DIM CHARA_IDX
#DIM DYNAMIC CHARA_GROUP_LIST_IDX
#DIMS DYNAMIC _LIST_CHARA_ID

CALL HO_GET_CHARAIDX(CHARA_ID)
CHARA_IDX = RESULT

FOR CHARA_GROUP_LIST_IDX, 0, HO_MAX_GROUPNUM
    IF _DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX == ""
        CALL HO_SET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "ACTION", ACTION)
        CALL HO_SET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "MODULE_LIST_IDX", TOSTR(MODULE_LIST_IDX))
        CALL HO_SET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST", LIST_ADD(_LIST_CHARA_ID, TOSTR(CHARA_ID)))
        CALL HO_SET_CHARADATA(CHARA_IDX, "CHARA_GROUP", TOSTR(CHARA_GROUP_LIST_IDX))
        RETURN
    ENDIF
NEXT

@HO_JOIN_CHARA_GROUP(CHARA_GROUP_LIST_IDX, CHARA_ID)
#DIM CHARA_ID
#DIM CHARA_GROUP_LIST_IDX
#DIMS DYNAMIC _LIST_CHARA_ID
#DIM DYNAMIC CHARA_IDX

CALL HO_GET_CHARAIDX(CHARA_ID)
CHARA_IDX = RESULT

CALL HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST")
_LIST_CHARA_ID = %RESULTS%

;グループ参加時に関係性の値を加算
VARI TARGET_ID
VARI I
FOR I, 0, LIST_COUNT(_LIST_CHARA_ID)
    TARGET_ID = LIST_GETINT(_LIST_CHARA_ID, I)
    CALL REL_ADD(CHARA_ID, TARGET_ID, RAND(3, 5))
    CALL REL_ADD(TARGET_ID, CHARA_ID, RAND(3, 5))
NEXT

;同一CHARA_IDの重複登録を容認しない。ただし同一CHARA_IDはこの関数の前段で弾かれている想定
IF LIST_INDEXOF(_LIST_CHARA_ID, TOSTR(CHARA_ID)) != -1
    DEBUGPRINTFORM @HO_JOIN_CHARA_GROUP:CHARA_ID{CHARA_ID}をCHARA_GROUP_LIST:{CHARA_GROUP_LIST_IDX}に多重に登録しようとしました
    RETURN -1
ENDIF
CALL HO_SET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST", LIST_ADD(_LIST_CHARA_ID, TOSTR(CHARA_ID)))
CALL HO_SET_CHARADATA(CHARA_IDX, "CHARA_GROUP", TOSTR(CHARA_GROUP_LIST_IDX))

;グループ離脱
@HO_LEAVE_CHARA_GROUP(CHARA_GROUP_LIST_IDX, CHARA_ID)
#DIM CHARA_GROUP_LIST_IDX
#DIM CHARA_ID
#DIMS DYNAMIC _LIST_CHARA_ID
#DIM  DYNAMIC CHARA_IDX
#DIM  DYNAMIC LIST_IDX

CALL HO_GET_CHARAIDX(CHARA_ID)
CHARA_IDX = RESULT

CALL HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST")
_LIST_CHARA_ID = %RESULTS%

LIST_IDX = LIST_INDEXOF(_LIST_CHARA_ID, TOSTR(CHARA_ID))

IF LIST_IDX != -1
    _LIST_CHARA_ID = %LIST_REMOVEAT(_LIST_CHARA_ID, LIST_IDX)%
    ;自分が離脱してもグループに誰か残っている
    IF LIST_COUNT(_LIST_CHARA_ID) != 0
        CALL HO_SET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST", _LIST_CHARA_ID)
        ;一緒に行動するか判定
        ;CALL HO_TRY_ACT_TOGETHER(CHARA_ID, _LIST_CHARA_ID)
    ELSE
        CALL HO_DISMISS_CHARA_GROUP(CHARA_GROUP_LIST_IDX)
    ENDIF
    CALL HO_SET_CHARADATA(CHARA_IDX, "CHARA_GROUP", "-1")
ELSE
    RETURN -1
ENDIF

CALL HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST")
_LIST_CHARA_ID = %RESULTS%

;グループの解散
@HO_DISMISS_CHARA_GROUP(CHARA_GROUP_LIST_IDX)
#DIM CHARA_GROUP_LIST_IDX
_DIC_HO_CHARA_GROUP_LIST:CHARA_GROUP_LIST_IDX '= ""

;キャラが加入しているグループリストのIDXを確認
@HO_CHECK_CHARA_JOINED_GROUP(CHARA_ID)
#DIM CHARA_ID
#DIM  DYNAMIC CHARA_GROUP_LIST_IDX
#DIMS DYNAMIC _LIST_CHARA

FOR CHARA_GROUP_LIST_IDX, 0, HO_MAX_GROUPNUM
    CALL HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST")
    SIF RESULT == -1
        CONTINUE
    _LIST_CHARA = %RESULTS%
    IF LIST_INDEXOF(_LIST_CHARA, TOSTR(CHARA_ID)) != -1
        RETURN CHARA_GROUP_LIST_IDX
    ENDIF
NEXT

RETURN -1

;対象モジュールでグループが形成されているか確認。結果はリスト形式で返却
@HO_CHECK_GROUP_FORMED(MODULE_LIST_IDX)
#DIM MODULE_LIST_IDX
#DIM  DYNAMIC CHARA_GROUP_LIST_IDX
#DIMS DYNAMIC _LIST_GROUP

VARSET RESULTS
FOR CHARA_GROUP_LIST_IDX, 0, HO_MAX_GROUPNUM
    CALL HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "MODULE_LIST_IDX")
    SIF RESULT == -1
        CONTINUE
    IF MODULE_LIST_IDX == RESULT
        _LIST_GROUP = %LIST_ADD(_LIST_GROUP, TOSTR(CHARA_GROUP_LIST_IDX))%
    ENDIF
NEXT

IF LIST_COUNT(_LIST_GROUP) != 0
    RESULTS = %_LIST_GROUP%
    RETURN 1
ELSE
    RETURN -1
ENDIF

;-------------------------------------------------
;;;グループから離脱する際にグループ内の仲間に一緒に行動するか働きかける
;;;@ARGS
;;;- CHARA_ID {int} :実行するキャラID
;;;- LIST_CHARA_ID {string(list)} :対象とするキャラクターのIDリスト
;;;@RETURN
;;;- RESULT
;;;  - RESULT:0 {bool} :誰かを誘ったか
;-------------------------------------------------
@HO_TRY_ACT_TOGETHER(CHARA_ID, LIST_CHARA_ID)
;region
#DIM  CHARA_ID
#DIMS LIST_CHARA_ID
#DIM  DYNAMIC TARGET_ID
;設定されているスケジュール行動がフリーでありすでに誰かを勧誘済みでないこと
CALL HO_GET_TASK_SCH(CHARA_ID)
IF !GROUPMATCH(RESULTS, "自由", "休憩") || TCVAR:CHARA_ID:勧誘したキャラID != -1
    RETURN 0
ENDIF

FOR LOCAL, 0, LIST_COUNT(LIST_CHARA_ID)
    TARGET_ID = LIST_GETINT(LIST_CHARA_ID, LOCAL)
    CALL HO_GET_TASK_SCH(TARGET_ID)
    ;設定されているスケジュール行動がフリーでありすでに誰かに勧誘されていないこと
    IF !GROUPMATCH(RESULTS, "自由", "休憩") || TCVAR:CHARA_ID:勧誘されたキャラID != -1
        CONTINUE
    ENDIF

    TCVAR:CHARA_ID:勧誘したキャラID = TARGET_ID
    TCVAR:TARGET_ID:勧誘されたキャラID = CHARA_ID

    TCVAR:CHARA_ID:予約済行動 = ACT_休憩
    TCVAR:TARGET_ID:追随相手ID = CHARA_ID
    DEBUGPRINTFORML ;-------------------------------------------------
    DEBUGPRINTFORML %ANAME(CHARA_ID)%は%ANAME(TARGET_ID)%を勧誘した
    DEBUGPRINTFORML 予約済行動 = {TCVAR:CHARA_ID:予約済行動}
    DEBUGPRINTFORML ;-------------------------------------------------
    BREAK
NEXT
;#endregion
;ペア行動のリセット
@HO_RESET_PAIR_ACT(CHARA_ID)
#DIM CHARA_ID
#DIM DYNAMIC TARGET_ID

TARGET_ID = TCVAR:CHARA_ID:勧誘したキャラID

TCVAR:CHARA_ID:グループ活動フラグ = 0
TCVAR:CHARA_ID:勧誘したキャラID = -1
IF TARGET_ID == -1
    RETURN
ENDIF
TCVAR:TARGET_ID:勧誘されたキャラID = -1
TCVAR:TARGET_ID:追随相手ID = -1

repo_name: napo/erafl

license: unknown


code:
;-------------------------------------------------
;コンパニオンの制御
;-------------------------------------------------
;-------------------------------------------------
;同行者を追加する
; 相席だけの場合はSHARE_MODE = 1で追加する
; RESULT 失敗 = 0, 成功 = 1
;-------------------------------------------------
@HO_ADD_COMPANION(CHARA_ID, SHARE_MODE = 0, FORCE_ADD = 0)
#DIM CHARA_ID
#DIM SHARE_MODE
#DIM FORCE_ADD
#DIMS DYNAMIC _LIST_COMPANION

VARSET RESULTS

SIF CHARA_ID == MASTER
    RETURN 0
;同行可能かを判定。相席モードの場合判定バイパス
IF SHARE_MODE != 1 && !FORCE_ADD
    CALL HO_IS_ADDABLE_COMPANION(CHARA_ID)
    SIF RESULT == 0
        RETURN 0
ENDIF

;調教一時参加扱いならば同行者/相席判定前にフラグを消す
;参加者数は調教一時参加扱いにした際加算されているはずなので加算しない
IF TCVAR:CHARA_ID:調教一時参加扱い
    TCVAR:CHARA_ID:調教一時参加扱い = 0
    CFLAG:CHARA_ID:調教参加フラグ = 0
ELSE
    TFLAG:参加者数 ++
ENDIF

;相席状態から同行に遷移する場合
IF TCVAR:CHARA_ID:相席フラグ == 1 && CFLAG:CHARA_ID:調教参加フラグ == 1
    TCVAR:CHARA_ID:相席フラグ = 0
    CALL HO_SET_CHARAACT(CHARA_ID, "同行中")
    TCVAR:CHARA_ID:行動待機時間 = 0
    TCVAR:CHARA_ID:予約済行動 = 0
    HO_同行者数 ++
    ;対象キャラクターの行動描写文字列を更新
    CALL HO_CHARAACT_DESC_SETSTR(,CHARA_ID)
    RETURN 1
ENDIF

CFLAG:CHARA_ID:調教参加フラグ = 1
;MASTERが独立して行動している場合の考慮
IF MTAR:0 == MASTER && MPLY:0 == MASTER
    CALL DEL_MTAR(MASTER)
ENDIF
;相席モードの場合は行動は書き換えない
IF SHARE_MODE == 0
    CALL HO_SET_CHARAACT(CHARA_ID, "同行中")
    CALL HO_STOP_USE_MODULE(CHARA_ID)
    TCVAR:CHARA_ID:行動待機時間 = 0
    TCVAR:CHARA_ID:予約済行動 = 0
    HO_同行者数 ++
ENDIF

;リストの管理
CALL HO_GET_MASTER_DATA("COMPANION_LIST")
_LIST_COMPANION = %RESULTS%
IF LIST_INDEXOF(_LIST_COMPANION, TOSTR(CHARA_ID)) == -1
    _LIST_COMPANION = %LIST_ADD(_LIST_COMPANION, TOSTR(CHARA_ID))%
    CALL HO_SET_MASTER_DATA("COMPANION_LIST", _LIST_COMPANION)
ELSE
    THROW 同一キャラを多重に登録しようとしました CHARA_ID{CHARA_ID}
ENDIF

;対象キャラクターの行動描写文字列を更新
CALL HO_CHARAACT_DESC_SETSTR(,CHARA_ID)

RETURN 1

;-------------------------------------------------
;同行者を削除する
; SHARE_MODE = 1の場合は同行状態から相席状態に移行する
; RESULT 失敗 = 0, 成功 = 1, 対象が同行者でない = -1
;-------------------------------------------------
@HO_REMOVE_COMPANION(CHARA_ID, SHARE_MODE = 0)
#DIM CHARA_ID
#DIMS DYNAMIC _LIST_COMPANION
#DIM DYNAMIC LIST_INDEX
#DIM DYNAMIC SHARE_MODE

;リストの管理
CALL HO_GET_MASTER_DATA("COMPANION_LIST")
_LIST_COMPANION = %RESULTS%

LIST_INDEX = LIST_INDEXOF(_LIST_COMPANION, TOSTR(CHARA_ID))
;同行者リスト内にキャラIDが存在しない場合は何もしない
SIF LIST_INDEX == -1
    RETURN -1

; 同行状態の時
IF TCVAR:CHARA_ID:相席フラグ != 1
    HO_同行者数 --
    TCVAR:CHARA_ID:行動待機時間 = 0
    TCVAR:CHARA_ID:HO直前の行動 = 0
    CALL HO_SET_CHARAACT(CHARA_ID, "待機")
    ;SHARE_MODE=1の場合は相席状態に移行して終了
    IF SHARE_MODE == 1
        TCVAR:CHARA_ID:相席フラグ = 1
        RETURN 1
    ENDIF
    ;同行状態のときのみ実行(相席状態の時にHO_STOP_USE_MODULE関数内でこの関数が呼ばれるため)
    CALL HO_STOP_USE_MODULE(CHARA_ID)
ELSEIF SHARE_MODE == 1
    RETURN -1
ENDIF

TFLAG:参加者数 --
TCVAR:CHARA_ID:相席フラグ = 0
CFLAG:CHARA_ID:調教参加フラグ = 0
TCVAR:CHARA_ID:同行解除フラグ = 1
SIF FLAG:主導権所有者 == CHARA_ID
    FLAG:主導権所有者 = -1
CALL DEL_MTAR(CHARA_ID)
CALL DEL_MPLY(CHARA_ID)
CALL RELEASE_ALL_EQUIP(CHARA_ID, 1)
IF MTAR_NUM == 0
    CALL RESET_ACTOR
ENDIF

;同行者データの更新
_LIST_COMPANION = %LIST_REMOVEAT(_LIST_COMPANION, LIST_INDEX)%
CALL HO_SET_MASTER_DATA("COMPANION_LIST", _LIST_COMPANION)

;対象キャラクターの行動描写文字列を更新
CALL HO_CHARAACT_DESC_SETSTR(,CHARA_ID)

;-------------------------------------------------
;同行者（相席含む）の情報を取得する
; RESULTS:0  同行者のリスト
; RETURN     同行者の数
;-------------------------------------------------
@HO_GET_COMPANION_LIST
#DIMS DYNAMIC _LIST_COMPANION

VARSET RESULTS
CALL HO_GET_MASTER_DATA("COMPANION_LIST")
_LIST_COMPANION = %RESULTS%

RESULTS = %_LIST_COMPANION%
RETURN LIST_COUNT(_LIST_COMPANION)

;-------------------------------------------------
;同行者（相席含まず）の情報を取得する
; RESULTS:0  同行者のリスト
; RETURN     同行者の数
;-------------------------------------------------
@HO_GET_FOLLOWER_LIST
#DIMS DYNAMIC _LIST_COMPANION
#DIMS DYNAMIC _LIST_FOLLOWER
#DIM DYNAMIC CHARA_ID

VARSET RESULTS
CALL HO_GET_MASTER_DATA("COMPANION_LIST")
_LIST_COMPANION = %RESULTS%
FOR LOCAL, 0, LIST_COUNT(_LIST_COMPANION)
    CHARA_ID = TOINT(LIST_GET(_LIST_COMPANION, LOCAL))
    SIF TCVAR:CHARA_ID:相席フラグ != 1
        _LIST_FOLLOWER = %LIST_ADD(_LIST_FOLLOWER, TOSTR(CHARA_ID))%
NEXT
RESULTS = %_LIST_FOLLOWER%
RETURN LIST_COUNT(_LIST_FOLLOWER)

;-------------------------------------------------
;同行可能かを判定する
; CHARA_ID :追加対象キャラID
; RETURN 失敗 = -0, 成功 = 1
;-------------------------------------------------
@HO_IS_ADDABLE_COMPANION(CHARA_ID)
#DIM CHARA_ID

CALL HO_GET_COMPANION_LIST
IF RESULT > HO_同行者上限
    CALL COLOR_PRINTW(@"同行者の数が多すぎるようだ(上限:{HO_同行者上限}人まで)", カラー_注意)
    RETURN 0
ENDIF

;MASTERから見えてないキャラは同行不可
CALL HO_IS_TARGET_VISIBLE(MASTER, CHARA_ID)
IF !RESULT
    CALL COLOR_PRINTW(@"ここからでは相手の様子がわからない……", カラー_注意)
    RETURN 0
ENDIF
IF !CFLAG:CHARA_ID:捕虜先
    ;;「COMF:390 二人で出掛ける」の判定処理をそのまま流用
    ;判定値初期化
    TCVAR:(CHARA_ID):24 = 0
    SETCOLOR カラー_注釈
    CALL COM_ORDER_TARGET390(CHARA_ID)
    ;実行値をマウント
    TCVAR:(CHARA_ID):25 = 25
    ;判定結果を表示
    PRINTFORML  = {TCVAR:(CHARA_ID):24} %TOSTR_COMPARE(TCVAR:(CHARA_ID):24, TCVAR:(CHARA_ID):25)% 実行値 {TCVAR:(CHARA_ID):25}
    RESETCOLOR
    IF TCVAR:(CHARA_ID):24 >= TCVAR:(CHARA_ID):25
        CALL KOJO_EVENT(CHARA_ID, 300)
        PRINTFORMW %ANAME(MASTER)%の誘いに%ANAME(CHARA_ID)%は応じ、同行に加わった
        PRINTL
        SIF !TCVAR:CHARA_ID:交流顔合わせ済
            TCVAR:CHARA_ID:交流顔合わせ済 = 1
        RETURN 1
    ELSE
        CALL KOJO_EVENT(CHARA_ID, 301)
        PRINTFORMW %ANAME(CHARA_ID)%を同行に誘ったものの、断られてしまった……
        PRINTL
        SIF !TCVAR:CHARA_ID:交流顔合わせ済
            TCVAR:CHARA_ID:交流顔合わせ済 = 1
        RETURN 0
    ENDIF
ELSE ;捕虜は無条件で連れ出し可能
    CALL KOJO_EVENT(CHARA_ID, 302)
    PRINTFORMW 虜囚の%ANAME(CHARA_ID)%を無理やり連れ出した……
    PRINTL
    SIF !TCVAR:CHARA_ID:交流顔合わせ済
        TCVAR:CHARA_ID:交流顔合わせ済 = 1
    RETURN 1
ENDIF

;-------------------------------------------------
; 同じモジュールを共有しているメンバーを取得する
;-------------------------------------------------
@HO_GET_MODULE_SHARE_MEMBER(CHARA_ID, INCLUDE_MASTER = 0)
#DIM CHARA_ID
#DIM INCLUDE_MASTER
#DIM DYNAMIC CHARA_IDX
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC MODULE_IDX
#DIMS DYNAMIC _LIST_CHARA_ID

VARSET RESULTS
IF CHARA_ID != MASTER
    CALL HO_GET_CHARAIDX(CHARA_ID)
    CHARA_IDX = RESULT
    CALL HO_GET_CHARADATA(CHARA_IDX, "ROOM_IDX")
    ROOM_IDX = RESULT
    CALL HO_GET_CHARADATA(CHARA_IDX, "MODULE_USAGE")
    MODULE_IDX = RESULT
ELSE
    CHARA_IDX = HO_MASTER現在地
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    MODULE_IDX = RESULT
ENDIF
IF INCLUDE_MASTER == 1
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    SIF ROOM_IDX == HO_MASTER現在地 && MODULE_IDX == RESULT
        _LIST_CHARA_ID = %LIST_ADD(_LIST_CHARA_ID, TOSTR(MASTER))%
ENDIF

LOCAL:0 = 0
WHILE _DIC_HO_CHARALIST:(LOCAL:0) != "-1"
    CALL HO_GET_CHARADATA(LOCAL:0, "ROOM_IDX")
    IF RESULT != ROOM_IDX
        LOCAL:0 ++
        CONTINUE
    ENDIF
    CALL HO_GET_CHARADATA(LOCAL:0, "MODULE_USAGE")
    IF MODULE_IDX == RESULT
        CALL HO_GET_CHARADATA(LOCAL:0, "CHARA_ID")
        _LIST_CHARA_ID = %LIST_ADD(_LIST_CHARA_ID, TOSTR(RESULT))%
    ENDIF
    LOCAL:0 ++
WEND
RESULTS = %_LIST_CHARA_ID%
RETURN LIST_COUNT(_LIST_CHARA_ID)

;-------------------------------------------------
;;;対象の設備を使用しているメンバーを取得する
;;;@ARGS
;;;- MODULE_LIST_IDX {int} :
;;;- INCLUDE_MASTER  {int} :主人公をメンバーとして含むか
;;;@RETURN
;;;- RESULT
;;;  - RESULT:0 {int} :設備を利用しているキャラの数
;;;- RESULTS
;;;  - RESULTS:0 {string(list)} :設備を利用しているキャラのIDリスト
;-------------------------------------------------
@HO_GET_CHARA_USE_THIS_MODULE(MODULE_LIST_IDX, INCLUDE_MASTER = 0)
;region
#DIM  MODULE_LIST_IDX
#DIM  INCLUDE_MASTER
#DIM  DYNAMIC CHARA_IDX
#DIMS DYNAMIC _LIST_CHARA_ID

VARSET RESULTS
IF INCLUDE_MASTER == 1
    SIF MODULE_LIST_IDX == HO_MASTER_USE_MODULE_LIST_IDX
        _LIST_CHARA_ID = %LIST_ADD(_LIST_CHARA_ID, TOSTR(MASTER))%
ENDIF

CHARA_IDX = 0
WHILE _DIC_HO_CHARALIST:(CHARA_IDX) != "-1"
    CALL HO_GET_CHARADATA(CHARA_IDX, "USE_MODULE_IDX")
    IF RESULT != MODULE_LIST_IDX
        CHARA_IDX ++
        CONTINUE
    ENDIF
    CALL HO_GET_CHARADATA(CHARA_IDX, "CHARA_ID")
    _LIST_CHARA_ID = %LIST_ADD(_LIST_CHARA_ID, TOSTR(RESULT))%
    CHARA_IDX ++
WEND

LOCAL = LIST_COUNT(_LIST_CHARA_ID)
RESULTS = %_LIST_CHARA_ID%
RETURN LOCAL

;新しく使用することは非推奨。@HO_GET_CHARA_USE_THIS_MODULE をつかうこと
@HO_GET_MODULE_USE_MEMBER(ROOM_IDX, MODULE_IDX, INCLUDE_MASTER = 0)
#DIM INCLUDE_MASTER
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC MODULE_IDX
#DIMS DYNAMIC _LIST_CHARA_ID

VARSET RESULTS
IF INCLUDE_MASTER == 1
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    SIF ROOM_IDX == HO_MASTER現在地 && MODULE_IDX == RESULT
        _LIST_CHARA_ID = %LIST_ADD(_LIST_CHARA_ID, TOSTR(MASTER))%
ENDIF

LOCAL:0 = 0
WHILE _DIC_HO_CHARALIST:(LOCAL:0) != "-1"
    CALL HO_GET_CHARADATA(LOCAL:0, "ROOM_IDX")
    IF RESULT != ROOM_IDX
        LOCAL:0 ++
        CONTINUE
    ENDIF
    CALL HO_GET_CHARADATA(LOCAL:0, "MODULE_USAGE")
    IF MODULE_IDX == RESULT
        CALL HO_GET_CHARADATA(LOCAL:0, "CHARA_ID")
        _LIST_CHARA_ID = %LIST_ADD(_LIST_CHARA_ID, TOSTR(RESULT))%
    ENDIF
    LOCAL:0 ++
WEND
RESULTS = %_LIST_CHARA_ID%
RETURN LIST_COUNT(_LIST_CHARA_ID)
;#endregion


code:
;-------------------------------------------------
;マップデータに関する関数
;-------------------------------------------------
@HO_GET_MAPDATA(MAP_ID, ROOM_IDX, DATANAME, FROM_SAVEDATA = 0)
#DIM  MAP_ID
#DIM  ROOM_IDX
#DIMS DATANAME
#DIM  FROM_SAVEDATA

VARSET RESULTS
IF !FROM_SAVEDATA
    SIF DIC_GET(_DIC_HO_MAPDATA:MAP_ID:ROOM_IDX, DATANAME) == ""
        RETURN -1

    ISNUMERIC DIC_GET(_DIC_HO_MAPDATA:MAP_ID:ROOM_IDX, DATANAME)
    IF RESULT
        RETURN TOINT(DIC_GET(_DIC_HO_MAPDATA:MAP_ID:ROOM_IDX, DATANAME))
    ELSE
        RESULTS = %DIC_GET(_DIC_HO_MAPDATA:MAP_ID:ROOM_IDX, DATANAME)%
        RETURN
    ENDIF
ELSE
    SIF DIC_GET(_DIC_HO_SAVED_MAPDATA:MAP_ID:ROOM_IDX, DATANAME) == ""
        RETURN -1
    ISNUMERIC DIC_GET(_DIC_HO_SAVED_MAPDATA:MAP_ID:ROOM_IDX, DATANAME)
    IF RESULT
        RETURN TOINT(DIC_GET(_DIC_HO_SAVED_MAPDATA:MAP_ID:ROOM_IDX, DATANAME))
    ELSE
        RESULTS = %DIC_GET(_DIC_HO_SAVED_MAPDATA:MAP_ID:ROOM_IDX, DATANAME)%
        RETURN
    ENDIF
ENDIF

@HO_SET_MAPDATA(ROOM_IDX, DATANAME, VALUES, MAP_ID = -1)
#DIM  ROOM_IDX
#DIMS DATANAME
#DIMS VALUES
#DIM  MAP_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

_DIC_HO_MAPDATA:MAP_ID:ROOM_IDX = %DIC_SET(_DIC_HO_MAPDATA:MAP_ID:ROOM_IDX, DATANAME, VALUES)%
RETURN

@HO_SAVE_MAPDATA(MAP_ID = -1)
#DIM MAP_ID
#DIMS DYNAMIC WRITE_DATA
IF MAP_ID == -1
    MAP_ID = HO_有効マップID
ENDIF

FOR LOCAL, 0, HO_MAX_ROOMNUM
    IF DIC_CONTAINSKEY(_DIC_HO_MAPDATA:MAP_ID:LOCAL, "ROOM_ID")
        WRITE_DATA '= ""
        WRITE_DATA = %DIC_SET(WRITE_DATA, "ROOM_ID",DIC_GET(_DIC_HO_MAPDATA:MAP_ID:LOCAL, "ROOM_ID"))%
        WRITE_DATA = %DIC_SET(WRITE_DATA, "MODULE_SLOT",DIC_GET(_DIC_HO_MAPDATA:MAP_ID:LOCAL, "MODULE_SLOT"))%
        WRITE_DATA = %DIC_SET(WRITE_DATA, "ROOM_PATH",DIC_GET(_DIC_HO_MAPDATA:MAP_ID:LOCAL, "ROOM_PATH"))%
        _DIC_HO_SAVED_MAPDATA:HO_有効マップID:LOCAL = %WRITE_DATA%
    ELSE
        _DIC_HO_SAVED_MAPDATA:HO_有効マップID:LOCAL '= "-1"
    ENDIF
NEXT

;;セーブデータに保存されたマップデータを読み出す
@HO_LOAD_MAPDATA(MAP_ID)
#DIM MAP_ID

FOR LOCAL, 0, HO_MAX_ROOMNUM
    _DIC_HO_MAPDATA:MAP_ID:LOCAL = %_DIC_HO_SAVED_MAPDATA:MAP_ID:LOCAL%
NEXT
;セーブデータが空なら初期設定マップデータを読み出し、モジュールリストとモジュールスロットデータを生成する
IF _DIC_HO_MAPDATA:MAP_ID:0 == ""
    CALL HO_SET_MAPDATA_DEFAULT(MAP_ID)
    CALL HO_INIT_MODULE_LIST(MAP_ID)
    CALL HO_INIT_MODULE_SLOT(MAP_ID)
    ;"MODULE_LIST"は初回読み出し時のみ使用するため、設定完了後に削除する
    FOR LOCAL, 0, HO_MAX_ROOMNUM
        _DIC_HO_MAPDATA:HO_有効マップID:LOCAL = %DIC_REMOVE(_DIC_HO_MAPDATA:HO_有効マップID:LOCAL, "MODULE_LIST")%
    NEXT
ENDIF

;MODULE_LISTからMODULE_SLOTデータを生成する。
@HO_INIT_MODULE_SLOT(MAP_ID = -1)
#DIM MAP_ID
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC MODULE_PLACED_ROOM_IDX
#DIM DYNAMIC MODULE_LIST_IDX
#DIM DYNAMIC MODULE_SLOT_IDX
#DIMS DYNAMIC _LIST_MODULE_SLOT

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

FOR ROOM_IDX, 0, HO_MAX_ROOMNUM
    VARSET _LIST_MODULE_SLOT
    FOR MODULE_LIST_IDX, 0, HO_MAX_MODULENUM
        CALL HO_GET_MODULE_LIST(MODULE_LIST_IDX, "ROOM_IDX",MAP_ID)
        MODULE_PLACED_ROOM_IDX = RESULT
        IF MODULE_PLACED_ROOM_IDX == ROOM_IDX
            CALL HO_GET_MODULE_LIST(MODULE_LIST_IDX, "MODULE_SLOT_IDX",MAP_ID)
            IF RESULT != -1
                MODULE_SLOT_IDX = RESULT
                _LIST_MODULE_SLOT = %LIST_INSERTAT(_LIST_MODULE_SLOT, MODULE_SLOT_IDX, TOSTR(MODULE_LIST_IDX))%
            ENDIF
        ENDIF
    NEXT
    CALL HO_SET_MAPDATA(ROOM_IDX, "MODULE_SLOT", _LIST_MODULE_SLOT, MAP_ID)
NEXT

@HO_GET_ROOM_DATA(ROOM_ID, DATANAME)
#DIM ROOM_ID
#DIMS DATANAME
#DIMS DYNAMIC _DIC_ROOM_DATA
#DIMS DYNAMIC STR_DATA

TRYCCALLFORM HO_ROOM_DATA_{ROOM_ID}
    _DIC_ROOM_DATA = %RESULTS%
CATCH
    RETURN -1
ENDCATCH

STR_DATA = %DIC_GET(_DIC_ROOM_DATA, DATANAME)%
ISNUMERIC STR_DATA
IF RESULT
    RETURN TOINT(STR_DATA)
ELSE
    RESULTS = %STR_DATA%
    RETURN
ENDIF

;ROOM_IDを取得
@HO_GET_ROOM_ID(ROOM_IDX, MAP_ID = -1)
#DIM ROOM_IDX
#DIM MAP_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "ROOM_ID")
RETURN RESULT

@HO_GET_ROOM_NAME(ROOM_IDX)
#DIM ROOM_IDX
#DIM ROOM_ID
#DIM MAP_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "ROOM_NAME")
IF RESULT == -1
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "ROOM_ID")
    ROOM_ID = RESULT
    CALL HO_GET_ROOM_DATA(ROOM_ID, "ROOM_NAME")
ENDIF
RETURN

;ROOM_TAGを取得
@HO_GET_ROOM_TAG(ROOM_IDX, FROM_SAVEDATA = 0)
#DIM ROOM_IDX
#DIM MAP_ID
#DIM FROM_SAVEDATA

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "ROOM_ID", FROM_SAVEDATA)
CALL HO_GET_ROOM_DATA(RESULT, "ROOM_TAG")
RETURN

@HO_CHECK_ROOM_TAG(ROOM_IDX, ROOM_TAG)
#DIM ROOM_IDX
#DIM MAP_ID
#DIMS ROOM_TAG
#DIMS _LIST_TAG
CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "ROOM_ID")
CALL HO_GET_ROOM_DATA(RESULT, "ROOM_TAG")
_LIST_TAG = %RESULTS%
IF LIST_INDEXOF(_LIST_TAG, ROOM_TAG) != -1
    RETURN 1
ELSE
    RETURN 0
ENDIF

;-------------------------------------------------
;;;@HO_FIND_ROOM_BY_TAG
;;;概要 :ROOM_TAGに該当する部屋をIDXで取得
;;;ARGS:1 = ROOM_TAG,ARG:2 = 0(複数合致する場合最初の要素を返却),1(ランダムに返却), ARG:3 = MAP_ID
;;;@RETURN  ROOM_IDX
;;;@RESULTS 合致したROOMのROOM_IDXリスト
;-------------------------------------------------
@HO_FIND_ROOM_BY_TAG(ROOM_TAG, RANDOM = 0, MAP_ID = -1, FROM_SAVEDATA = 0)
#DIMS ROOM_TAG
#DIM  MAP_ID
#DIM  RANDOM
#DIM  FROM_SAVEDATA
#DIM  DYNAMIC ROOM_IDX
#DIMS DYNAMIC _LIST_ROOM
VARSET RESULTS
SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
WHILE ROOM_IDX < HO_MAX_ROOMNUM
    CALL HO_GET_ROOM_TAG(ROOM_IDX, FROM_SAVEDATA)
    IF LIST_INDEXOF(RESULTS, ROOM_TAG) != -1
        _LIST_ROOM = %LIST_ADD(_LIST_ROOM, TOSTR(ROOM_IDX))%
    ENDIF
    ROOM_IDX ++
WEND

RESULTS '= ""
IF LIST_COUNT(_LIST_ROOM) > 0
    RESULTS = %_LIST_ROOM%
    IF !RANDOM
        RETURN TOINT(LIST_GET(_LIST_ROOM, 0))
    ELSE
        LOCAL = LIST_COUNT(_LIST_ROOM)
        RETURN TOINT(LIST_GET(_LIST_ROOM, RAND(0, LOCAL)))
    ENDIF
ELSE
    ;タグに該当する部屋が見つからなかった場合
    RETURN -1
ENDIF

;ROOM_TAGに該当するFROMから最も近い部屋をIDXで取得
@HO_FIND_NEAREST_ROOM_BY_TAG(ROOM_TAG, ROOM_IDX_FROM, MAP_ID = -1)
#DIMS ROOM_TAG
#DIM ROOM_IDX_FROM
#DIM MAP_ID
#DIM DYNAMIC DIST
#DIM  DYNAMIC ROOM_IDX
#DIM  DYNAMIC LIST_IDX
#DIMS DYNAMIC _DIC_ROOM_LIST, HO_MAX_ROOMNUM + 1

VARSET _DIC_ROOM_LIST, "-1"
SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
WHILE ROOM_IDX < HO_MAX_ROOMNUM
    CALL HO_GET_ROOM_TAG(ROOM_IDX)
    IF LIST_INDEXOF(RESULTS, ROOM_TAG) != -1
        _DIC_ROOM_LIST:LIST_IDX '= ""
        _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "ROOM_IDX", TOSTR(ROOM_IDX))%
        CALL HO_GET_ROUTE(ROOM_IDX_FROM, ROOM_IDX)
        DIST = RESULT
        _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "DISTANCE", TOSTR(DIST))%
        LIST_IDX++
    ENDIF
    ROOM_IDX ++
WEND
IF FINDELEMENT(_DIC_ROOM_LIST, "-1") > 0
    CALL ARRAYSORT_DIC(_DIC_ROOM_LIST, "DISTANCE")
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:0, "ROOM_IDX"))
    RETURN ROOM_IDX
ELSE
    ;タグに該当する部屋が見つからなかった場合
    RETURN -1
ENDIF

;-------------------------------------------------
; 設備を条件としたエリア探索
;-------------------------------------------------
;-------------------------------------------------
;使用したいモジュールの用途から条件を満たす最も近い部屋を探す
;MODULE_USAGE
; 設備用途を指定("入浴"など)
;ROOM_IDX_FROM
; 現在のエリアIDXを指定
;CONDS
; 最も近いエリア  = "NEAREST"
; 最も遠いエリア  = "FARTHEST"
; ランダムなエリア = "RANDOM"
;OPTION
; 現在地を含む = 0
; 現在地を除外 = 1
; 現在地のみ = 2
;-------------------------------------------------
@HO_FIND_ROOM_BY_MODULE_USAGE(MODULE_USAGE, ROOM_IDX_FROM, CONDS = "NEAREST", OPTION = 0, MAP_ID = -1)
; #region
#DIMS MODULE_USAGE
#DIM  ROOM_IDX_FROM
#DIM  OPTION
#DIMS CONDS
#DIM  MAP_ID

#DIM  CONST 現在地を含む = 0
#DIM  CONST 現在地を除外 = 1
#DIM  CONST 現在地のみ = 2

#DIM  DYNAMIC DIST
#DIM  DYNAMIC ROOM_IDX
#DIM  DYNAMIC LIST_IDX
#DIM  DYNAMIC MODULE_ID
#DIMS DYNAMIC _LIST_MODULE
#DIMS DYNAMIC _LIST_USAGE
#DIMS DYNAMIC _DIC_ROOM_LIST, HO_MAX_ROOMNUM + 1
#DIM  DYNAMIC MATCHED_ROOMNUM

VARSET _DIC_ROOM_LIST, "-1"
SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
WHILE ROOM_IDX < HO_MAX_ROOMNUM
    IF ROOM_IDX == ROOM_IDX_FROM && OPTION == 現在地を除外
        ROOM_IDX ++
        CONTINUE
    ELSEIF ROOM_IDX != ROOM_IDX_FROM && OPTION == 現在地のみ
        ROOM_IDX ++
        CONTINUE
    ENDIF
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_SLOT")
    _LIST_MODULE = %RESULTS%
    FOR LOCAL, 0, LIST_COUNT(_LIST_MODULE)
        CALL HO_GET_MODULE_ID2(ROOM_IDX, LOCAL)
        MODULE_ID = RESULT
        CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
        _LIST_USAGE = %RESULTS%
        ;探索対象のルームに一つでも条件を満たすモジュールがあれば、その部屋のIDXと距離を取って次の部屋を探索
        IF LIST_INDEXOF(_LIST_USAGE, MODULE_USAGE) != -1
            CALL HO_GET_ROUTE(ROOM_IDX_FROM, ROOM_IDX)
            DIST = RESULT
            SIF DIST == -1
                CONTINUE
            _DIC_ROOM_LIST:LIST_IDX '= ""
            _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "ROOM_IDX", TOSTR(ROOM_IDX))%
            _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "DISTANCE", TOSTR(DIST))%
            LIST_IDX ++
            BREAK
        ENDIF
    NEXT
    ROOM_IDX ++
WEND

MATCHED_ROOMNUM = FINDELEMENT(_DIC_ROOM_LIST, "-1")
IF MATCHED_ROOMNUM < 1
    RETURN -1
ENDIF
IF CONDS == "NEAREST"
    CALL ARRAYSORT_DIC(_DIC_ROOM_LIST, "DISTANCE")
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:0, "ROOM_IDX"))
    RETURN ROOM_IDX
ELSEIF CONDS == "FARTHEST"
    CALL ARRAYSORT_DIC(_DIC_ROOM_LIST, "DISTANCE", 1)
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:0, "ROOM_IDX"))
    RETURN ROOM_IDX
ELSEIF CONDS == "RANDOM"
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:(RAND(0, MATCHED_ROOMNUM)), "ROOM_IDX"))
    RETURN ROOM_IDX
ENDIF
; #endregion

;-------------------------------------------------
;使用したいモジュールの設備から条件を満たす最も近い部屋を探す
;MODULE_ELEMENT
; 設備属性を指定("遮蔽"など)
; '/'で区切られている場合は全条件を満たすモジュールのある部屋を返す
;ROOM_IDX_FROM
; 現在のエリアIDXを指定
;CONDS
; 最も近いエリア  = "NEAREST"
; 最も遠いエリア  = "FARTHEST"
; ランダムなエリア = "RANDOM"
;OPTION
; 現在地を含む = 0
; 現在地を除外 = 1
; 現在地のみ = 2
;-------------------------------------------------
@HO_FIND_ROOM_BY_MODULE_ELEMENT(MODULE_ELEMENT, ROOM_IDX_FROM, CONDS = "NEAREST", OPTION = 0, MAP_ID = -1)
; #region
#DIMS MODULE_ELEMENT
#DIM  ROOM_IDX_FROM
#DIM  OPTION
#DIMS CONDS
#DIM  MAP_ID

#DIM  CONST 現在地を含む = 0
#DIM  CONST 現在地を除外 = 1
#DIM  CONST 現在地のみ = 2

#DIMS DYNAMIC ELEMENT, 10
#DIM  DYNAMIC ELEMENT_NUM
#DIM  DYNAMIC ELEMENT_COUNT
#DIM  DYNAMIC UNMATCH_FLAG

#DIM  DYNAMIC DIST
#DIM  DYNAMIC ROOM_IDX
#DIM  DYNAMIC LIST_IDX
#DIM  DYNAMIC MODULE_ID
#DIMS DYNAMIC _LIST_MODULE
#DIMS DYNAMIC _LIST_ELEM
#DIMS DYNAMIC _DIC_ROOM_LIST, HO_MAX_ROOMNUM + 1
#DIM  DYNAMIC MATCHED_ROOMNUM

VARSET _DIC_ROOM_LIST, "-1"
SPLIT MODULE_ELEMENT, "/", ELEMENT
ELEMENT_NUM = RESULT

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
WHILE ROOM_IDX < HO_MAX_ROOMNUM
    IF ROOM_IDX == ROOM_IDX_FROM && OPTION == 現在地を除外
        ROOM_IDX ++
        CONTINUE
    ELSEIF ROOM_IDX != ROOM_IDX_FROM && OPTION == 現在地のみ
        ROOM_IDX ++
        CONTINUE
    ENDIF
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_SLOT")
    _LIST_MODULE = %RESULTS%
    FOR LOCAL, 0, LIST_COUNT(_LIST_MODULE)
        CALL HO_GET_MODULE_ID2(ROOM_IDX, LOCAL)
        MODULE_ID = RESULT
        CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
        _LIST_ELEM = %RESULTS%
        ;'/'で区切られている全条件を満たすかを確認
        UNMATCH_FLAG = 0
        FOR ELEMENT_COUNT, 0, ELEMENT_NUM
            IF LIST_INDEXOF(_LIST_ELEM, ELEMENT:ELEMENT_COUNT) == -1
                UNMATCH_FLAG ++
            ENDIF
        NEXT
        ;探索条件を満たす設備があれば、その部屋のIDXと距離を取って次の部屋を探索
        IF UNMATCH_FLAG == 0
            CALL HO_GET_ROUTE(ROOM_IDX_FROM, ROOM_IDX)
            DIST = RESULT
            SIF DIST == -1
                CONTINUE
            _DIC_ROOM_LIST:LIST_IDX '= ""
            _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "ROOM_IDX", TOSTR(ROOM_IDX))%
            _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "DISTANCE", TOSTR(DIST))%
            LIST_IDX ++
            BREAK
        ENDIF
    NEXT
    ROOM_IDX ++
WEND

MATCHED_ROOMNUM = FINDELEMENT(_DIC_ROOM_LIST, "-1")
IF MATCHED_ROOMNUM < 1
    RETURN -1
ENDIF
IF CONDS == "NEAREST"
    CALL ARRAYSORT_DIC(_DIC_ROOM_LIST, "DISTANCE")
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:0, "ROOM_IDX"))
    RETURN ROOM_IDX
ELSEIF CONDS == "FARTHEST"
    CALL ARRAYSORT_DIC(_DIC_ROOM_LIST, "DISTANCE", 1)
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:0, "ROOM_IDX"))
    RETURN ROOM_IDX
ELSEIF CONDS == "RANDOM"
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:(RAND(0, MATCHED_ROOMNUM)), "ROOM_IDX"))
    RETURN ROOM_IDX
ENDIF
; #endregion

;-------------------------------------------------
;使用したいモジュールの属性から条件を満たす最も近い部屋を探す
;MODULE_ELEMENT'/'で区切られている場合は全条件を満たすモジュールのある部屋を返す
;OPTIONの値は
;現在地を含む = 0
;現在地を除外 = 1
;現在地のみ = 2
;-----------------------------------------------
@HO_FIND_NEAREST_ROOM_BY_MODULE_ELEMENT(MODULE_ELEMENT, ROOM_IDX_FROM, OPTION = 0, MAP_ID = -1)
#DIMS MODULE_ELEMENT
#DIM ROOM_IDX_FROM
#DIM OPTION
#DIM MAP_ID

#DIM CONST 現在地を含む = 0
#DIM CONST 現在地を除外 = 1
#DIM CONST 現在地のみ = 2

#DIMS DYNAMIC ELEMENT, 10
#DIM  DYNAMIC ELEMENT_NUM
#DIM  DYNAMIC ELEMENT_COUNT
#DIM  DYNAMIC UNMATCH_FLAG

#DIM DYNAMIC DIST
#DIM  DYNAMIC ROOM_IDX
#DIM  DYNAMIC LIST_IDX
#DIM  DYNAMIC MODULE_ID
#DIMS DYNAMIC _LIST_MODULE
#DIMS DYNAMIC _LIST_ELEM
#DIMS DYNAMIC _DIC_ROOM_LIST, HO_MAX_ROOMNUM + 1

VARSET _DIC_ROOM_LIST, "-1"
SPLIT MODULE_ELEMENT, "/", ELEMENT
ELEMENT_NUM = RESULT

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
WHILE ROOM_IDX < HO_MAX_ROOMNUM
    IF ROOM_IDX == ROOM_IDX_FROM && OPTION == 現在地を除外
        ROOM_IDX ++
        CONTINUE
    ELSEIF ROOM_IDX != ROOM_IDX_FROM && OPTION == 現在地のみ
        ROOM_IDX ++
        CONTINUE
    ENDIF
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_SLOT")
    _LIST_MODULE = %RESULTS%
    FOR LOCAL, 0, LIST_COUNT(_LIST_MODULE)
        CALL HO_GET_MODULE_ID2(ROOM_IDX, LOCAL)
        MODULE_ID = RESULT
        CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
        _LIST_ELEM = %RESULTS%
        UNMATCH_FLAG = 0
        ;探索対象のルームに一つでも条件を満たすモジュールがあれば、その部屋のIDXと距離を取って次の部屋を探索
        FOR ELEMENT_COUNT, 0, ELEMENT_NUM
            IF LIST_INDEXOF(_LIST_ELEM, ELEMENT:ELEMENT_COUNT) == -1
                UNMATCH_FLAG ++
            ENDIF
        NEXT
        IF !UNMATCH_FLAG
            _DIC_ROOM_LIST:LIST_IDX '= ""
            _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "ROOM_IDX", TOSTR(ROOM_IDX))%
            CALL HO_GET_ROUTE(ROOM_IDX_FROM, ROOM_IDX)
            DIST = RESULT
            _DIC_ROOM_LIST:LIST_IDX = %DIC_SET(_DIC_ROOM_LIST:LIST_IDX, "DISTANCE", TOSTR(DIST))%
            LIST_IDX ++
            BREAK
        ENDIF
    NEXT
    ROOM_IDX ++
WEND
IF FINDELEMENT(_DIC_ROOM_LIST, "-1") > 0
    CALL ARRAYSORT_DIC(_DIC_ROOM_LIST, "DISTANCE")
    ROOM_IDX = TOINT(DIC_GET(_DIC_ROOM_LIST:0, "ROOM_IDX"))
    RETURN ROOM_IDX
ELSE
    ;条件に該当する部屋が見つからなかった場合
    RETURN -1
ENDIF

;-------------------------------------------------
;マップデータから対象の部屋との接続情報を取得しLIST形式で返却
;-------------------------------------------------
@HO_GET_PATH(ROOM_IDX, MAP_ID = -1)
#DIM MAP_ID
#DIM ROOM_IDX

VARSET RESULTS
SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "ROOM_PATH")
RETURN

;-------------------------------------------------
;互換用ラッパ。OBSOLETED
;-------------------------------------------------
@HO_FIND_NEAREST_ROOM_BY_MODULE_USAGE(MODULE_USAGE, ROOM_IDX_FROM, OPTION = 0, MAP_ID = -1)
#DIMS MODULE_USAGE
#DIM  ROOM_IDX_FROM
#DIM  OPTION
#DIMS DISTS
#DIM  MAP_ID

CALL HO_FIND_ROOM_BY_MODULE_USAGE(MODULE_USAGE, ROOM_IDX_FROM, "NEAREST", OPTION, MAP_ID)
RETURN RESULT

;-------------------------------------------------
;ルームモジュールに関する関数
;-------------------------------------------------
;マップデータに保持している対象の部屋のモジュールリストよりモジュールIDを取得する
; @HO_GET_MODULE_ID(ROOM_IDX, MODULE_IDX, MAP_ID = -1)
; #DIM ROOM_IDX
; #DIM MODULE_IDX
; #DIM MAP_ID
; #DIMS DYNAMIC _LIST_MODULE_LIST
; #DIMS DYNAMIC MODULE_LIST_IDX

; SIF MAP_ID == -1
;     MAP_ID = HO_有効マップID

; CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_LIST")
; _LIST_MODULE_LIST = %RESULTS%

; IF LIST_COUNT(_LIST_MODULE_LIST) == 0
;     RETURN -1
; ELSE
;     LOCALS = %LIST_GET(_LIST_MODULE_LIST, MODULE_IDX)%
;     SIF LOCALS == ""
;         RETURN -1
;     RETURN TOINT(LOCALS)
; ENDIF

@HO_GET_MODULE_LIST_IDX(ROOM_IDX, MODULE_SLOT_IDX, MAP_ID = -1)
#DIM ROOM_IDX
#DIM MODULE_SLOT_IDX
#DIM MAP_ID
#DIMS DYNAMIC _LIST_MODULE_SLOT
#DIM DYNAMIC MODULE_LIST_IDX

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_SLOT")
_LIST_MODULE_SLOT = %RESULTS%

IF LIST_COUNT(_LIST_MODULE_SLOT) == 0
    RETURN -1
ELSE
    MODULE_LIST_IDX = TOINT(LIST_GET(_LIST_MODULE_SLOT, MODULE_SLOT_IDX))
    RETURN MODULE_LIST_IDX
ENDIF

@HO_GET_MODULE_ID2(ROOM_IDX, MODULE_SLOT_IDX, MAP_ID = -1)
#DIM ROOM_IDX
#DIM MODULE_SLOT_IDX
#DIM MAP_ID
#DIMS DYNAMIC _LIST_MODULE_SLOT
#DIMS DYNAMIC MODULE_LIST_IDX

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_SLOT")
_LIST_MODULE_SLOT = %RESULTS%

IF LIST_COUNT(_LIST_MODULE_SLOT) == 0
    RETURN -1
ELSE
    MODULE_LIST_IDX = %LIST_GET(_LIST_MODULE_SLOT, MODULE_SLOT_IDX)%
    SIF MODULE_LIST_IDX == ""
        RETURN -1
    CALL HO_GET_MODULE_LIST(TOINT(MODULE_LIST_IDX), "MODULE_ID", MAP_ID)
ENDIF
RESULT:1 = TOINT(MODULE_LIST_IDX)
RETURN RESULT

;-------------------------------------------------
;モジュールIDからモジュール情報定義を取得
;-------------------------------------------------
@HO_GET_MODULE_DATA(MODULE_ID, DATANAME)
#DIM MODULE_ID
#DIMS DATANAME
#DIMS _DIC_MODULE_DATA
#DIMS STR_DATA

TRYCCALLFORM HO_MODULE_DATA_{MODULE_ID}
    _DIC_MODULE_DATA = %RESULTS%
CATCH
    ;THROW MODULE_ID{MODULE_ID}に該当するモジュールデータが存在しません
    RETURN -1
ENDCATCH

STR_DATA = %DIC_GET(_DIC_MODULE_DATA, DATANAME)%
ISNUMERIC STR_DATA
IF RESULT
    RETURN TOINT(STR_DATA)
ELSE
    RESULTS = %STR_DATA%
    RETURN
ENDIF

;-------------------------------------------------
;部屋番号およびモジュールスロット番号からモジュール情報定義を取得
;-------------------------------------------------
@HO_GET_MODULE_DATA_BY_IDX(ROOM_IDX, MODULE_SLOT_IDX, DATANAME)
#DIM ROOM_IDX
#DIM MODULE_SLOT_IDX
#DIMS DATANAME
#DIM MODULE_ID

CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_SLOT_IDX)
MODULE_ID = RESULT
CALL HO_GET_MODULE_DATA(MODULE_ID, DATANAME)

RETURN

;モジュール属性を取得
@HO_CHECK_MODULE_ELEMENT(ROOM_IDX, MODULE_IDX, ELEMENT_NAME)
#DIM  ROOM_IDX
#DIM  MODULE_IDX
#DIM  MODULE_ID
#DIMS ELEMENT_NAME

CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX)
MODULE_ID  = RESULT
SIF RESULT == -1
    RETURN 0

CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
IF LIST_INDEXOF(RESULTS, ELEMENT_NAME) != -1
    RETURN 1
ENDIF

RETURN 0

;キャラが使っているモジュール情報を取得する
@HO_GET_USE_MODULE_INFO(CHARA_ID)
#DIM DYNAMIC CHARA_ID
#DIM DYNAMIC CHARA_IDX
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC MODULE_IDX
#DIM DYNAMIC MODULE_ID

VARSET RESULTS
IF CHARA_ID != MASTER
    CALL HO_GET_CHARAIDX(CHARA_ID)
    CHARA_IDX = RESULT
    CALL HO_GET_CHARADATA(CHARA_IDX, "ROOM_IDX")
    ROOM_IDX = RESULT
    CALL HO_GET_CHARADATA(CHARA_IDX, "MODULE_USAGE")
    MODULE_IDX = RESULT
    SIF RESULT == -1
        RETURN -1
ELSE
    ROOM_IDX = HO_MASTER現在地
    CALL HO_GET_MASTER_DATA("MODULE_USAGE")
    MODULE_IDX = RESULT
    SIF RESULT == -1
        RETURN -1
ENDIF

CALL HO_GET_MODULE_ID2(ROOM_IDX, MODULE_IDX)
MODULE_ID = RESULT
CALL HO_GET_MODULE_DATA(MODULE_ID, "MODULE_NAME")
RETURN MODULE_ID

;対象キャラクターが使っているモジュールの用途が引数と合致してるか確認
@HO_CHECK_USE_MODULE_USAGE(CHARA_ID, USAGE)
#DIM CHARA_ID
#DIMS USAGE
#DIM DYNAMIC MODULE_ID

CALL HO_GET_USE_MODULE_INFO(CHARA_ID)
MODULE_ID = RESULT
SIF MODULE_ID == -1
    RETURN 0
CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
IF LIST_INDEXOF(RESULTS, USAGE) != -1
    RETURN 1
ELSE
    RETURN 0
ENDIF

;対象キャラクターが使っているモジュールの属性が引数と合致してるか確認
@HO_CHECK_USE_MODULE_ELEMENT(CHARA_ID, ELEMENT_NAME)
#DIM CHARA_ID
#DIMS ELEMENT_NAME
#DIM DYNAMIC MODULE_ID

CALL HO_GET_USE_MODULE_INFO(CHARA_ID)
MODULE_ID = RESULT
SIF MODULE_ID == -1
    RETURN 0
CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
IF LIST_INDEXOF(RESULTS, ELEMENT_NAME) != -1
    RETURN 1
ELSE
    RETURN 0
ENDIF
;-------------------------------------------------
;キャラデータに関する関数
;-------------------------------------------------
;-------------------------------------------------
;CHARA_IDに指定したキャラクターと同所属のキャラを取得しリスト形式で返却する
;RESULT:0  対象キャラクターの数
;RESULTS:0 対象しているキャラクターID(_LIST形式)
;-------------------------------------------------
@GET_MEMBER_LIST(CHARA_ID = -1, 非捕虜をカウント = 1, 捕虜をカウント = 1)
#DIM CHARA_ID
#DIM 非捕虜をカウント
#DIM 捕虜をカウント
#DIM TARGET_CHARA_ID
#DIMS DYNAMIC _LIST_MEMBER
VARSET RESULTS
SIF CHARA_ID == -1
    CHARA_ID = MASTER
FOR TARGET_CHARA_ID, 0, CHARANUM
    SIF CHARA_ID == TARGET_CHARA_ID
        CONTINUE
    ;非捕虜(同所属のキャラ)
    IF 非捕虜をカウント > 0 && (CFLAG:CHARA_ID:所属 == CFLAG:TARGET_CHARA_ID:所属)
        _LIST_MEMBER = %LIST_ADD(_LIST_MEMBER, TOSTR(TARGET_CHARA_ID))%
    ;捕虜
    ELSEIF 捕虜をカウント > 0 && (CFLAG:CHARA_ID:所属 == CFLAG:TARGET_CHARA_ID:捕虜先)
        _LIST_MEMBER = %LIST_ADD(_LIST_MEMBER, TOSTR(TARGET_CHARA_ID))%
    ENDIF
NEXT

RESULTS = %_LIST_MEMBER%
RETURN LIST_COUNT(_LIST_MEMBER)

@HO_GET_CHARADATA(IDX, DATANAME)
#DIM IDX
#DIMS DATANAME
VARSET RESULTS
SIF IDX < 0
    RETURN -1
SIF DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME) == ""
    RETURN -1

ISNUMERIC DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME)
IF RESULT
    RETURN TOINT(DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME))
ELSE
    RESULTS = %DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME)%
    RETURN
ENDIF

;式中関数版
@HO_GET_CHARADATAF(IDX, DATANAME)
#FUNCTION
#DIM IDX
#DIMS DATANAME
VARSET RESULTS
IF IDX < 0
    RETURNF -1
ENDIF
IF DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME) == ""
    RETURNF -1
ENDIF
ISNUMERIC DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME)
IF RESULT
    RETURNF TOINT(DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME))
ELSE
    RESULTS = %DIC_GET(_DIC_HO_CHARALIST:IDX, DATANAME)%
    RETURNF
ENDIF

@HO_SET_CHARADATA(CHARA_IDX, DATANAME, VALUES)
#DIM CHARA_IDX
#DIMS DATANAME
#DIMS VALUES
_DIC_HO_CHARALIST:CHARA_IDX = %DIC_SET(_DIC_HO_CHARALIST:CHARA_IDX, DATANAME, VALUES)%
RETURN

@HO_SET_CHARAACT(CHARA_ID, ACTION)
#DIM CHARA_ID
#DIMS ACTION
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_SET_CHARADATA(RESULT, "ACTION", ACTION)

@HO_GET_CHARAACT(CHARA_ID)
#DIM CHARA_ID
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_GET_CHARADATA(RESULT, "ACTION")

@HO_SET_CHARAPLACE(CHARA_ID, ROOM_IDX)
#DIM CHARA_ID
#DIM ROOM_IDX
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_SET_CHARADATA(RESULT, "ROOM_IDX", TOSTR(ROOM_IDX))

@HO_GET_CHARAPLACE(CHARA_ID)
#DIM CHARA_ID
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_GET_CHARADATA(RESULT, "ROOM_IDX")
RETURN RESULT

@HO_SET_MOVELIST(CHARA_ID, _LIST_MOVELIST)
#DIM CHARA_ID
#DIMS _LIST_MOVELIST
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_SET_CHARADATA(RESULT, "MOVELIST", _LIST_MOVELIST)

@HO_GET_MOVELIST(CHARA_ID)
#DIM CHARA_ID
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_GET_CHARADATA(RESULT, "MOVELIST")

@HO_GET_CHARAIDX(CHARA_ID)
#DIM CHARA_ID
#DIM DYNAMIC IDX
WHILE _DIC_HO_CHARALIST:IDX != "-1"
    CALL HO_GET_CHARADATA(IDX, "CHARA_ID")
    SIF CHARA_ID == RESULT
        RETURN IDX
    IDX ++
WEND
;キャラリストに存在しないIDなら-1を返す
RETURN -1

;式中関数版
@HO_GET_CHARAIDXF(CHARA_ID)
#FUNCTION
#DIM CHARA_ID
#DIM DYNAMIC IDX
WHILE _DIC_HO_CHARALIST:IDX != "-1"
    SIF CHARA_ID == HO_GET_CHARADATAF(IDX, "CHARA_ID")
        RETURNF IDX
    IDX ++
WEND
;キャラリストに存在しないIDなら-1を返す
RETURNF -1

@HO_SET_CHARADATA_BY_ID(CHARA_ID, DATANAME, VALUES)
#DIM CHARA_ID
#DIMS DATANAME
#DIMS VALUES
CALL HO_GET_CHARAIDX(CHARA_ID)
SIF RESULT == -1
    RETURN -1
CALL HO_SET_CHARADATA(RESULT, DATANAME, VALUES)
RETURN RESULT

@HO_GET_CHARADATA_BY_ID(CHARA_ID, DATANAME)
#DIM CHARA_ID
#DIMS DATANAME
CALL HO_GET_CHARAIDX(CHARA_ID)
CALL HO_GET_CHARADATA(RESULT, DATANAME)
RETURN RESULT

;特定の条件に合致するキャラのIDをリストで返却する
;DATANAME未指定の場合は領内活動に参加している全キャラクター(ゲスト含む)
@HO_FIND_CHARA(DATANAME = "", DATAVALUES = "")
#DIMS DATANAME
#DIMS DATAVALUES
#DIMS DYNAMIC VALUES
#DIMS DYNAMIC _LIST_CHARA
FOR LOCAL, 0, FINDELEMENT(_DIC_HO_CHARALIST, "-1",,,1)
    SIF _DIC_HO_CHARALIST:LOCAL == "DELETED"
        CONTINUE
    IF DATANAME != ""
        CALL HO_GET_CHARADATA(LOCAL, DATANAME)
        VALUES = %RESULTS%
        SIF RESULT == -1
            CONTINUE
        IF DATAVALUES == VALUES
            CALL HO_GET_CHARADATA(LOCAL, "CHARA_ID")
            _LIST_CHARA = %LIST_ADD(_LIST_CHARA, TOSTR(RESULT))%
        ENDIF
    ELSE
        CALL HO_GET_CHARADATA(LOCAL, "CHARA_ID")
        _LIST_CHARA = %LIST_ADD(_LIST_CHARA, TOSTR(RESULT))%
    ENDIF
NEXT
RESULTS = %_LIST_CHARA%
RETURN LIST_COUNT(_LIST_CHARA)

;-------------------------------------------------
;プレイヤーデータに関する関数
;-------------------------------------------------
@HO_GET_MASTER_DATA(DATANAME)
#DIMS DATANAME

VARSET RESULTS
SIF DIC_GET(_DIC_HO_MASTER_DATA, DATANAME) == ""
    RETURN -1

ISNUMERIC DIC_GET(_DIC_HO_MASTER_DATA, DATANAME)
IF RESULT
    RETURN TOINT(DIC_GET(_DIC_HO_MASTER_DATA, DATANAME))
ELSE
    RESULTS = %DIC_GET(_DIC_HO_MASTER_DATA, DATANAME)%
    RETURN
ENDIF

@HO_SET_MASTER_DATA(DATANAME, VALUES)
#DIMS DATANAME
#DIMS VALUES

_DIC_HO_MASTER_DATA = %DIC_SET(_DIC_HO_MASTER_DATA, DATANAME, VALUES)%
RETURN

;-------------------------------------------------
; @ARRAYSORT_DIC
;	連想配列を持つ一次元配列を指定したキーで昇順または降順で挿入ソートする
;	指定するデータは数値型に変換可能であること
;	　※一次元配列に-1が格納されていた場合はデータの末尾とみなす
;	引数:1 連想配列を持つ文字列型一次元配列
;	引数:2 ソート対象のキー値
;	引数:3 0 = 昇順, 1 = 降順
;-------------------------------------------------
@ARRAYSORT_DIC(DIC, KEY, IS_DESCEND)
#DIMS REF DIC
#DIMS DYNAMIC KEY
#DIM DYNAMIC IS_DESCEND
#DIM DYNAMIC ELEMENT_COUNT

ELEMENT_COUNT = VARSIZE("DIC")
FINDELEMENT DIC, "-1"
IF RESULT != -1
    ELEMENT_COUNT = RESULT
ENDIF

FOR LOCAL:0, 1, ELEMENT_COUNT
    LOCAL:1 = LOCAL:0
    IF IS_DESCEND == 0
        WHILE (LOCAL:1 > 0) && (TOINT(DIC_GET(DIC:(LOCAL:1 - 1), KEY))) > (TOINT(DIC_GET(DIC:(LOCAL:1), KEY)))
            SWAP DIC:(LOCAL:1 - 1), DIC:(LOCAL:1)
            LOCAL:1 --
        WEND
    ELSE
        WHILE (LOCAL:1 > 0) && (TOINT(DIC_GET(DIC:(LOCAL:1 - 1), KEY))) < (TOINT(DIC_GET(DIC:(LOCAL:1), KEY)))
            SWAP DIC:(LOCAL:1 - 1), DIC:(LOCAL:1)
            LOCAL:1 --
        WEND
    ENDIF
NEXT


code:
;-------------------------------------------------
;モジュールリスト管理関数
;各モジュールを一意に管理する_DIC_HO_MODULE_LISTの管理関数
;[MODULE_ID] : (必須)MODULE_ID
;[ROOM_IDX] : (必須)MODULE配置先のROOM_IDX
;[MODULE_SLOT_IDX] : (必須)配置先スロット番号
;-------------------------------------------------
@HO_SET_MODULE_LIST(MODULE_LIST_IDX, DATANAME, VALUES, MAP_ID = -1)
#DIM  MODULE_LIST_IDX
#DIMS DATANAME
#DIMS VALUES
#DIM  MAP_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
SIF _DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX == "-1"
    _DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX '= ""

_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX = %DIC_SET(_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME, VALUES)%
RETURN

@HO_GET_MODULE_LIST(MODULE_LIST_IDX, DATANAME, MAP_ID = -1, FROM_SAVEDATA = 0)
#DIM  MAP_ID
#DIM  MODULE_LIST_IDX
#DIM  ROOM_IDX
#DIMS DATANAME
#DIM  FROM_SAVEDATA

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

VARSET RESULTS
IF !FROM_SAVEDATA
    SIF DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME) == ""
        RETURN -1

    ISNUMERIC DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME)
    IF RESULT
        RETURN TOINT(DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME))
    ELSE
        RESULTS = %DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME)%
        RETURN
    ENDIF
ELSE
    SIF DIC_GET(_DIC_HO_SAVED_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME) == ""
        RETURN -1

    ISNUMERIC DIC_GET(_DIC_HO_SAVED_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME)
    IF RESULT
        RETURN TOINT(DIC_GET(_DIC_HO_SAVED_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME))
    ELSE
        RESULTS = %DIC_GET(_DIC_HO_SAVED_MODULE_LIST:MAP_ID:MODULE_LIST_IDX, DATANAME)%
        RETURN
    ENDIF
ENDIF

;-------------------------------------------------
;モジュールリストの空きを見つけてモジュール情報を登録
;-------------------------------------------------
@HO_ADD_MODULE_LIST(MODULE_ID, ROOM_IDX, MODULE_SLOT_IDX, MAP_ID = -1)
#DIM  MODULE_ID
#DIM  ROOM_IDX
#DIM  MODULE_SLOT_IDX
#DIM  MAP_ID
#DIM  DYNAMIC MODULE_LIST_IDX

#DIM DYNAMIC TARGET_ROOM_IDX
#DIM DYNAMIC TARGET_MODULE_LIST_IDX
#DIM DYNAMIC TARGET_MODULE_SLOT_IDX

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

MODULE_LIST_IDX = 0
FOR MODULE_LIST_IDX, 0, HO_MAX_MODULENUM
    IF _DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX == "-1"
        _DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX '= "DELETED"
        CALL HO_SET_MODULE_LIST(MODULE_LIST_IDX, "MODULE_ID", TOSTR(MODULE_ID), MAP_ID)
        CALL HO_SET_MODULE_LIST(MODULE_LIST_IDX, "ROOM_IDX", TOSTR(ROOM_IDX), MAP_ID)
        CALL HO_SET_MODULE_LIST(MODULE_LIST_IDX, "MODULE_SLOT_IDX", TOSTR(MODULE_SLOT_IDX), MAP_ID)
        ;追加されたモジュールと同一のルームにあり、かつMODULE_SLOT_IDXと同値以上のSLOT_IDXを持つデータについて、スロット情報を加算する
        FOR TARGET_MODULE_LIST_IDX, 0, HO_MAX_MODULENUM
            CALL HO_GET_MODULE_LIST(TARGET_MODULE_LIST_IDX, "ROOM_IDX", MAP_ID)
            TARGET_ROOM_IDX = RESULT
            IF ROOM_IDX == TARGET_ROOM_IDX
                CALL HO_GET_MODULE_LIST(TARGET_MODULE_LIST_IDX, "MODULE_SLOT_IDX", MAP_ID)
                TARGET_MODULE_SLOT_IDX = RESULT
                IF MODULE_SLOT_IDX <= TARGET_MODULE_SLOT_IDX
                    CALL HO_SET_MODULE_LIST(TARGET_MODULE_LIST_IDX, "MODULE_SLOT_IDX", TOSTR(TARGET_MODULE_SLOT_IDX ++))
                ENDIF
            ENDIF
        NEXT
        RETURN MODULE_LIST_IDX
    ENDIF
NEXT
RETURN -1

;-------------------------------------------------
;指定インデックスのモジュール情報を削除
;-------------------------------------------------
@HO_DELETE_MODULE_LIST(MODULE_LIST_IDX, MAP_ID = -1)
#DIM  MODULE_LIST_IDX
#DIM  MAP_ID

#DIM DYNAMIC DELDATA_ROOM_IDX
#DIM DYNAMIC DELDATA_MODULE_SLOT_IDX
#DIM DYNAMIC TARGET_ROOM_IDX
#DIM DYNAMIC TARGET_MODULE_LIST_IDX
#DIM DYNAMIC TARGET_MODULE_SLOT_IDX
#DIM DYNAMIC CHARA_ID
#DIM DYNAMIC TIMETABLE

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID
SIF _DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX == "-1"
    RETURN 0

;削除されたモジュールと同一のルームにあり、かつ後続のスロットに配置されているデータについて、スロット情報を詰める
CALL HO_GET_MODULE_LIST(MODULE_LIST_IDX, "ROOM_IDX", MAP_ID)
DELDATA_ROOM_IDX = RESULT
CALL HO_GET_MODULE_LIST(MODULE_LIST_IDX, "MODULE_SLOT_IDX", MAP_ID)
DELDATA_MODULE_SLOT_IDX = RESULT

FOR TARGET_MODULE_LIST_IDX, 0, HO_MAX_MODULENUM
    CALL HO_GET_MODULE_LIST(TARGET_MODULE_LIST_IDX, "ROOM_IDX", MAP_ID)
    TARGET_ROOM_IDX = RESULT
    IF DELDATA_ROOM_IDX == TARGET_ROOM_IDX
        CALL HO_GET_MODULE_LIST(TARGET_MODULE_LIST_IDX, "MODULE_SLOT_IDX", MAP_ID)
        TARGET_MODULE_SLOT_IDX = RESULT
        IF DELDATA_MODULE_SLOT_IDX < TARGET_MODULE_SLOT_IDX
            CALL HO_SET_MODULE_LIST(TARGET_MODULE_LIST_IDX, "MODULE_SLOT_IDX", TOSTR(TARGET_MODULE_SLOT_IDX --))
        ENDIF
    ENDIF
NEXT
_DIC_HO_MODULE_LIST:MAP_ID:MODULE_LIST_IDX '= "-1"

;キャラクターの作業場リストから削除対象のモジュールIDXを削除
FOR CHARA_ID, 0, CHARANUM
    FOR TIMETABLE, 0, HO_TIMETABLENUM
        IF LIST_INDEXOF(_LIST_HO_WORKPLACE:CHARA_ID:TIMETABLE, TOSTR(MODULE_LIST_IDX)) != -1
            _LIST_HO_WORKPLACE:CHARA_ID:TIMETABLE = %LIST_REMOVEALL(_LIST_HO_WORKPLACE:CHARA_ID:TIMETABLE, TOSTR(MODULE_LIST_IDX))%
        ENDIF
    NEXT
NEXT

;作業指示を削除
CALL HO_REMOVE_CRAFT_ORDER(MODULE_LIST_IDX)

RETURN 1

;-------------------------------------------------
;セーブデータにモジュールリストを保存
;-------------------------------------------------
@HO_SAVE_MODULE_LIST(MAP_ID = -1)
#DIM MAP_ID
#DIMS DYNAMIC WRITE_DATA
IF MAP_ID == -1
    MAP_ID = HO_有効マップID
ENDIF

FOR LOCAL, 0, HO_MAX_MODULENUM
    IF DIC_CONTAINSKEY(_DIC_HO_MODULE_LIST:MAP_ID:LOCAL, "MODULE_ID")
        WRITE_DATA '= ""
        WRITE_DATA = %DIC_SET(WRITE_DATA, "MODULE_ID",DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:LOCAL, "MODULE_ID"))%
        WRITE_DATA = %DIC_SET(WRITE_DATA, "ROOM_IDX",DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:LOCAL, "ROOM_IDX"))%
        WRITE_DATA = %DIC_SET(WRITE_DATA, "MODULE_SLOT_IDX",DIC_GET(_DIC_HO_MODULE_LIST:MAP_ID:LOCAL, "MODULE_SLOT_IDX"))%
        _DIC_HO_SAVED_MODULE_LIST:MAP_ID:LOCAL = %WRITE_DATA%
    ELSE
        _DIC_HO_SAVED_MODULE_LIST:MAP_ID:LOCAL '= "-1"
    ENDIF
NEXT

;-------------------------------------------------
;セーブデータに保存されたモジュールリストを読み出す
;-------------------------------------------------
@HO_LOAD_MODULE_LIST(MAP_ID = -1)
#DIM MAP_ID
IF MAP_ID == -1
    MAP_ID = HO_有効マップID
ENDIF

SIF _DIC_HO_SAVED_MODULE_LIST:MAP_ID:0 == ""
    RETURN

FOR LOCAL, 0, HO_MAX_MODULENUM
    _DIC_HO_MODULE_LIST:MAP_ID:LOCAL = %_DIC_HO_SAVED_MODULE_LIST:MAP_ID:LOCAL%
NEXT

;-------------------------------------------------
;初期設定マップからモジュールリストを生成する
;-------------------------------------------------
@HO_INIT_MODULE_LIST(MAP_ID = -1)
#DIM MAP_ID
#DIMS DYNAMIC _LIST_MOUDLE
#DIM MODULE_NUM

#DIMS DYNAMIC _LIST_MODULE

#DIM DYNAMIC MODULE_LIST_IDX
#DIM DYNAMIC MODULE_ID
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC MODULE_SLOT_IDX

IF MAP_ID == -1
    MAP_ID = HO_有効マップID
ENDIF

VARSET _DIC_HO_MODULE_LIST:MAP_ID:0, "-1"
FOR ROOM_IDX, 0, HO_MAX_ROOMNUM
    CALL HO_GET_MAPDATA(MAP_ID, ROOM_IDX, "MODULE_LIST")
    _LIST_MODULE = %RESULTS%
    MODULE_NUM = LIST_COUNT(_LIST_MODULE)
    FOR MODULE_SLOT_IDX, 0, MODULE_NUM
        FOR LOCAL, 0, HO_MAX_MODULENUM
            IF _DIC_HO_MODULE_LIST:MAP_ID:LOCAL == "-1"
                MODULE_LIST_IDX = LOCAL
                BREAK
            ENDIF
        NEXT
        MODULE_ID = TOINT(LIST_GET(_LIST_MODULE, MODULE_SLOT_IDX))
        CALL HO_SET_MODULE_LIST(MODULE_LIST_IDX, "MODULE_ID", TOSTR(MODULE_ID), MAP_ID)
        CALL HO_SET_MODULE_LIST(MODULE_LIST_IDX, "ROOM_IDX", TOSTR(ROOM_IDX), MAP_ID)
        CALL HO_SET_MODULE_LIST(MODULE_LIST_IDX, "MODULE_SLOT_IDX", TOSTR(MODULE_SLOT_IDX), MAP_ID)
    NEXT
NEXT

;-------------------------------------------------
;指定したキーと値に合致するモジュールのIDXをリストで返却する
;-------------------------------------------------
@HO_FIND_MODULE(KEYS, VALUES, MAP_ID = -1)
#DIMS KEYS
#DIMS VALUES
#DIM MAP_ID
#DIMS DYNAMIC _LIST_MODULE
#DIM DYNAMIC MODULE_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

FOR LOCAL, 0, HO_ENDIDXOF_MODULE_LIST()
    CALL HO_GET_MODULE_LIST(LOCAL, "MODULE_ID")
    MODULE_ID = RESULT
    SIF MODULE_ID == -1
        BREAK
    CALL HO_GET_MODULE_DATA(MODULE_ID, KEYS)
    IF LIST_INDEXOF(RESULTS, VALUES) != -1
        _LIST_MODULE = %LIST_ADD(_LIST_MODULE, TOSTR(LOCAL))%
    ENDIF
NEXT
RESULTS = %_LIST_MODULE%
RETURN

;-------------------------------------------------
;用途に合致するモジュールのIDXをリストで返却する
;-------------------------------------------------
@HO_FIND_MODULE_BY_USAGE(USAGE,MAP_ID = -1, FROM_SAVEDATA = 0)
#DIMS USAGE
#DIM MAP_ID
#DIM FROM_SAVEDATA
#DIMS DYNAMIC _LIST_MODULE
#DIM DYNAMIC MODULE_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

FOR LOCAL, 0, HO_ENDIDXOF_MODULE_LIST()
    CALL HO_GET_MODULE_LIST(LOCAL, "MODULE_ID",,FROM_SAVEDATA)
    MODULE_ID = RESULT
    CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
    IF LIST_INDEXOF(RESULTS, USAGE) != -1
        _LIST_MODULE = %LIST_ADD(_LIST_MODULE, TOSTR(LOCAL))%
    ENDIF
NEXT
RESULTS = %_LIST_MODULE%
RETURN

;-------------------------------------------------
;属性に合致するモジュールのIDXをリストで返却する
;-------------------------------------------------
@HO_FIND_MODULE_BY_ELEMENT(ELEMENT, MAP_ID = -1, FROM_SAVEDATA = 0)
#DIMS ELEMENT
#DIM MAP_ID
#DIM FROM_SAVEDATA
#DIMS DYNAMIC _LIST_MODULE
#DIM DYNAMIC MODULE_ID

SIF MAP_ID == -1
    MAP_ID = HO_有効マップID

FOR LOCAL, 0, HO_ENDIDXOF_MODULE_LIST()
    CALL HO_GET_MODULE_LIST(LOCAL, "MODULE_ID",,FROM_SAVEDATA)
    MODULE_ID = RESULT
    CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
    IF LIST_INDEXOF(RESULTS, ELEMENT) != -1
        _LIST_MODULE = %LIST_ADD(_LIST_MODULE, TOSTR(LOCAL))%
    ENDIF
NEXT
RESULTS = %_LIST_MODULE%
RETURN

;モジュールリストの末尾IDXを取得する
@HO_ENDIDXOF_MODULE_LIST()
#FUNCTION

;末尾を算出済みならそれを返す
SIF HO_CACHE_ENDIDXOF_MODULE_LIST > 0
    RETURNF HO_CACHE_ENDIDXOF_MODULE_LIST

FOR LOCAL, HO_MAX_MODULENUM - 1, 0, -1
    IF _DIC_HO_MODULE_LIST:0:LOCAL != "-1"
        HO_CACHE_ENDIDXOF_MODULE_LIST = LOCAL + 1
        BREAK
    ENDIF
NEXT
RETURNF HO_CACHE_ENDIDXOF_MODULE_LIST

;-------------------------------------------------
;空き独房数を取得する関数
;RETURN 空き独房数
;-------------------------------------------------
@HO_GET_VACANT_PRISON_CELL_COUNT
#DIMS DYNAMIC PRISON_CELL_LIST
#DIM DYNAMIC PRISON_CELL_COUNT
#DIM DYNAMIC PRISONER_COUNT

;居房リストを取得
CALL HO_FIND_MODULE_BY_USAGE("居房",,1)
PRISON_CELL_LIST = %RESULTS%
PRISON_CELL_COUNT = LIST_COUNT(PRISON_CELL_LIST)

;捕虜数を取得
CALL GET_MEMBER_LIST(MASTER,-1,1)
PRISONER_COUNT = RESULT

RETURN PRISON_CELL_COUNT - PRISONER_COUNT