code:
;-------------------------------------------------
;汎用関数仮置
;-------------------------------------------------
;リスト型配列のシャッフル関数
@LIST_SHUFFLE(_LIST, 回数 = 1)
#DIMS REF _LIST
#DIM 回数
#DIM LIST_LENGTH
LIST_LENGTH = LIST_COUNT(_LIST)
FOR LOCAL:0, 0, 回数
    WHILE LIST_LENGTH > 1
        LIST_LENGTH --
        LOCAL:1 = RAND(0, LIST_LENGTH + 1)
        LOCALS:0 = %LIST_GET(_LIST, LOCAL:1)%
        _LIST = %LIST_SET(_LIST, LOCAL:1, LIST_GET(_LIST, LIST_LENGTH))%
        _LIST = %LIST_SET(_LIST, LIST_LENGTH, LOCALS:0)%
    WEND
NEXT
RETURN

;与えられたリスト型変数からランダムに要素を選出して返す
@LIST_RAND(_LIST)
#FUNCTIONS
#DIMS _LIST
RETURNF LIST_GET(_LIST, RAND(0, LIST_COUNT(_LIST)))

;ARGS:1～5のいずれかに合致する場合1を返す
@LIST_GMATCH(_LIST, AND_OR = "OR", ARGS:2, ARGS:3 = "", ARGS:4 = "", ARGS:5 = "", ARGS:6 = "")
#FUNCTION
#DIMS _LIST
#DIMS AND_OR
#DIM DYNAMIC MATCHED

FOR LOCAL, 2, 6
    IF ARGS:LOCAL == ""
        IF LOCAL == 2
            RETURNF 0
        ENDIF
        BREAK
    ENDIF
    IF LIST_INDEXOF(_LIST, ARGS:LOCAL) == -1
        SIF AND_OR == "AND"
            RETURNF 0
    ELSE
        IF AND_OR == "OR"
            RETURNF 1
        ELSEIF AND_OR == "AND"
            MATCHED ++
        ELSE ;"AND,OR以外"
            RETURNF 0
        ENDIF
    ENDIF
NEXT

IF MATCHED
    RETURNF 1
ENDIF
RETURNF 0

;-------------------------------------------------
; 単発コマンドまたは継続状態をみて、対象のキャラが指定の部位を使用して奉仕しているか判定する
;-------------------------------------------------
@IS_SERVEAT(CHARA_ID, 部位, オプション定義 = "")
#FUNCTION
#DIM CHARA_ID
#DIMS 部位
#DIMS オプション定義
SELECTCASE 部位
    CASE "口"
        ;キスのみ
        SELECTCASE オプション定義
            CASE "キス"
                IF GROUPMATCH(SELECTCOM, 20, 340, 341, 342) || IS_EQUIP(CHARA_ID, 20, 342)
                    RETURNF 1
                ELSE
                    RETURNF 0
                ENDIF
            CASE "フェラ", "口淫"
                IF (GROUPMATCH(SELECTCOM, 11, 19, 107, 330) && IS_MPLY(CHARA_ID)) || IS_EQUIP_PLAYER(CHARA_ID, 11, 19, 107, 330)
                    RETURNF 1
                ELSE
                    RETURNF 0
                ENDIF
            CASEELSE
        ENDSELECT
        ;口を使う動作全般
        SIF IS_M_HOLD(CHARA_ID)
            RETURNF 1
        IF (IS_MTAR(CHARA_ID) ||  IS_MPLY(CHARA_ID))
            SIF GROUPMATCH(SELECTCOM, 20, 340, 341, 342)
                RETURNF 1
            SIF IS_MTAR(CHARA_ID) && GROUPMATCH(SELECTCOM, 86, 90, 101, 102, 105, 132, 210)
                RETURNF 1
            SIF IS_MPLY(CHARA_ID) && GROUPMATCH(SELECTCOM, 2, 8, 9, 11, 19, 20, 24, 28, 104, 107, 117, 330)
                RETURNF 1
        ENDIF
    CASE "手"
        ;手淫
        SELECTCASE オプション定義
            CASE "手コキ"
                {
                    SIF (GROUPMATCH(SELECTCOM, T_N("亀頭責め手コキ"), T_N("手コキ"), T_N("玉揉み")) && IS_MPLY(CHARA_ID))
                        || IS_EQUIP_PLAYER(CHARA_ID, T_N("亀頭責め手コキ"), T_N("手コキ"), T_N("玉揉み"))
                }
                    RETURNF 1
            CASEELSE
        ENDSELECT
    CASE "胸"
        {
            SIF (GROUPMATCH(SELECTCOM, T_N("パイズリ")) && IS_MPLY(CHARA_ID))
                || IS_EQUIP_PLAYER(CHARA_ID, T_N("パイズリ"))
        }
            RETURNF 1
    CASEELSE
        RETURNF 0
ENDSELECT
RETURNF 0

;-------------------------------------------------
;CHARA_IDの継続中コマンドの相手のうち、先頭のキャラ番号を返す
;COM_ARRAYに確認対象のコマンドを格納したLISTを渡す
;-------------------------------------------------
@GET_EQUIP_TARGET(CHARA_ID, _LIST_COM)
#FUNCTION
#DIM CHARA_ID
#DIMS _LIST_COM

FOR LOCAL:0, 0, MEQUIP_NUM
    IF LIST_INDEXOF(_LIST_COM, TOSTR(MEQUIP:(LOCAL:0))) != -1
        FOR LOCAL:1, 0, MEQUIP_PLAYER_NUM:(LOCAL:0)
            IF MEQUIP_PLAYER:(LOCAL:0):(LOCAL:1) == CHARA_ID
                RETURNF MEQUIP_TARGET:(LOCAL:0):0
            ENDIF
        NEXT
    ENDIF
NEXT
RETURNF -1

;-------------------------------------------------
;CHARA_IDの継続中コマンドの実行者のうち、先頭のキャラ番号を返す
;_LIST_COMに確認対象のコマンドを格納したLISTを渡す
;-------------------------------------------------
@GET_EQUIP_PLAYER(CHARA_ID, _LIST_COM)
#FUNCTION
#DIM CHARA_ID
#DIMS _LIST_COM

FOR LOCAL:0, 0, MEQUIP_NUM
    IF LIST_INDEXOF(_LIST_COM, TOSTR(MEQUIP:(LOCAL:0))) != -1
        FOR LOCAL:1, 0, MEQUIP_TARGET_NUM:(LOCAL:0)
            IF MEQUIP_TARGET:(LOCAL:0):(LOCAL:1) == CHARA_ID
                RETURNF MEQUIP_PLAYER:(LOCAL:0):0
            ENDIF
        NEXT
    ENDIF
NEXT
RETURNF -1

;-------------------------------------------------
;TARGETを性的対象とみなすかを判定する
;異性またはBL,レズが一定のしきい値以上なら性的対象とみなす
;-------------------------------------------------
@IS_SEXUAL(PLAYER_ID, TARGET_ID)
#FUNCTION
#DIM PLAYER_ID
#DIM TARGET_ID

IF IS_SAMESEX(PLAYER_ID, TARGET_ID)
    IF IS_MALE(PLAYER_ID)
        IF IS_MALE(TARGET_ID)
            IF ABL:PLAYER_ID:ＢＬ >= 3
                RETURNF 1
            ELSE
                RETURNF 0
            ENDIF
        ELSE
            RETURNF 1
        ENDIF
    ELSEIF IS_FEMALE(PLAYER_ID) && ABL:PLAYER_ID:レズ >= 3
        RETURNF 1
    ELSEIF TALENT:PLAYER_ID:両刀
        RETURNF 1
    ENDIF
ELSE
    RETURNF 1
ENDIF
RETURNF 0

;-------------------------------------------------
;MPLYとMTARの双方が全員合意持ち
;-------------------------------------------------
@ACCEPT_EACH()
#FUNCTION
#DIM DYNAMIC ITER_I

FOR ITER_I, 0, MPLY_NUM
    IF !TALENT:(MPLY:ITER_I):合意 && (MPLY:ITER_I) != MASTER
        RETURNF 0
    ENDIF
NEXT
FOR ITER_I, 0, MTAR_NUM
    IF !TALENT:(MTAR:ITER_I):合意 && (MTAR:ITER_I) != MASTER
        RETURNF 0
    ENDIF
NEXT
RETURNF 1

;-------------------------------------------------
;MPLYとMTARの双方にSM関係が成立するか判定
;IS_MPLY_SADISTが0の場合TARGET側がSか判定
;-------------------------------------------------
@REL_SM(IS_MPLY_SADIST = 1)
#FUNCTION
#DIM IS_MPLY_SADIST
#DIM DYNAMIC ITER_I
FOR ITER_I, 0, MPLY_NUM
    IF IS_MPLY_SADIST
        SIF !IS_NASTY(MPLY:ITER_I, 素質_淫乱_サド) && !ABL:(MPLY:ITER_I):サド < 4
            RETURNF 0
    ELSE
        SIF !IS_NASTY(MPLY:ITER_I, 素質_淫乱_マゾ) && !ABL:(MPLY:ITER_I):マゾ < 4
            RETURNF 0
    ENDIF
NEXT
FOR ITER_I, 0, MTAR_NUM
    IF IS_MPLY_SADIST
        SIF !IS_NASTY(MTAR:ITER_I, 素質_淫乱_マゾ) && !ABL:(MTAR:ITER_I):マゾ < 4
            RETURNF 0
    ELSE
        SIF !IS_NASTY(MTAR:ITER_I, 素質_淫乱_サド) && !ABL:(MTAR:ITER_I):サド < 4
            RETURNF 0
    ENDIF
NEXT
RETURNF 1

;-------------------------------------------------
;売春実行可能か
;-------------------------------------------------
@CAN_PROSTITUTE(CHARA_ID)
#FUNCTION
#DIM CHARA_ID

SIF JOB_NAME:(TALENT:CHARA_ID:職業) == "娼婦"
    RETURNF 1
SIF IS_NASTY(CHARA_ID, 素質_淫乱_娼婦)
    RETURNF 1
SIF IS_SLAVE(CHARA_ID)
    RETURNF 1
SIF CFLAG:CHARA_ID:捕虜先 == 所属_プレイヤー
    RETURNF 1
SIF SKILL_GET_LEVELF(CHARA_ID, スキル_大分類_性技, "SEDUCTION") > 0
    RETURNF 1

RETURNF 0

;-------------------------------------------------
; 淫乱系素質の有無を判定
; ARG:1は 素質_淫乱_生ハメ依存 など淫乱系素質の番号を与える
;-------------------------------------------------
@IS_NASTY(CHARA_ID, 淫乱系素質番号)
#FUNCTION
#DIM CHARA_ID
#DIM 淫乱系素質番号

RETURNF GETBIT(TALENT:(CHARA_ID):淫乱系, 淫乱系素質番号)

;-------------------------------------------------
; 陥落深度版GROUPMATCH
; ARG:0 CHARA_ID
; ARG:1 陥落度文字列。以下の文字列を指定可
; ','で複数条件判定可能(OR判定)、頭に'!'をつけることで真偽反転
; EX1. "恋人,烙印" -> 恋人または烙印
; EX2. "!LOVER, "恋人" -> 恋慕、親愛、恋人以外、ただし恋人は可
; 使用可能な文字列
; TALENTの陥落値(恋慕、親愛など)の他に以下の表記が使用できます
; LOVER(恋慕、親愛、恋人のいずれか)
; SLAVE(服従、隷属、烙印のいずれか)
; SLAVED_BY(主人、所有者のいずれか)
; FALLEN（上記二つまたは誰かの奴隷）
;-------------------------------------------------
@GMATCH_FALLEN(CHARA_ID, STR_FALLEN)
#FUNCTION
#DIM CHARA_ID
#DIMS STR_FALLEN
#DIMS DYNAMIC VALUES, 10
#DIM  DYNAMIC IS_NOT
#DIM  DYNAMIC IS_MATCH

SPLIT STR_FALLEN, ",", VALUES
FOR LOCAL, 0, RESULT
    IF REGEXPMATCH(VALUES:LOCAL, "!")
        IS_NOT = 1
        VALUES:LOCAL = %REPLACE(VALUES:LOCAL, "[!\\s]", "")%
    ELSE
        IS_NOT = 0
    ENDIF
    SELECTCASE VALUES:LOCAL
        CASE "恋慕", "親愛", "服従", "隷属", "烙印", "主人", "所有者"
            IF GETVAR(@"TALENT:CHARA_ID:%VALUES:LOCAL%") && !IS_NOT
                IS_MATCH ++
            ELSEIF !GETVAR(@"TALENT:CHARA_ID:%VALUES:LOCAL%") && IS_NOT
                IS_MATCH ++
            ENDIF
        CASE "LOVER"
            IF IS_LOVER(CHARA_ID) && !IS_NOT
                IS_MATCH ++
            ELSEIF !IS_LOVER(CHARA_ID) && IS_NOT
                IS_MATCH ++
            ENDIF
        CASE "FALLEN"
            IF IS_FALLEN(CHARA_ID) && !IS_NOT
                IS_MATCH ++
            ELSEIF !IS_FALLEN(CHARA_ID) && IS_NOT
                IS_MATCH ++
            ENDIF
        CASE "SLAVE"
            IF IS_SLAVE(CHARA_ID) && !IS_NOT
                IS_MATCH ++
            ELSEIF !IS_SLAVE(CHARA_ID) && IS_NOT
                IS_MATCH ++
            ENDIF
        CASE "SLAVED_BY"
            IF IS_SLAVED_BY(CHARA_ID) && !IS_NOT
                IS_MATCH ++
            ELSEIF !IS_SLAVED_BY(CHARA_ID) && IS_NOT
                IS_MATCH ++
            ENDIF
    ENDSELECT
NEXT
IF IS_MATCH
    RETURNF 1
ELSE
    RETURNF 0
ENDIF

;-------------------------------------------------
;主にCOM実行時の口上制御などで用いる関数
;-------------------------------------------------
;region
;-------------------------------------------------
;;;口上で参照できる補助的なシチュエーションタグをセットする
;;;セットしたタグは @AT_SITU でアクセスする
;;;※このリストはTRAINループの開始時( @SHOW_STATUS )に初期化される
;;;あくまで使い切りで補助的な情報を与える目的で使用される
;;;@ARGS
;;;- ARG {string} :付帯するシチュエーションタグ(ex."セクハラ")
;-------------------------------------------------
@ADD_SITU(VALUES)
#DIMS VALUES

TSTR:COM_SITUATION = %LIST_ADD(TSTR:COM_SITUATION, VALUES)%

;-------------------------------------------------
;;;セットされたシチュエーションタグの存否を確認する
;;;@ARGS
;;;- ARG {string}:シチュエーションタグ名
;;;@RETURN
;;;- RESULT
;;;  - RESULT:0 {bool} :タグの有無
;;;  - RESULT:1 {int}  :タグのリスト上のインデックス
;-------------------------------------------------
;RESULTS:0で要素の有無を返す。要素のインデックスをREUSLT:1で返す
@AT_SITU(VALUES)
#FUNCTION
#DIMS VALUES
#DIM INDEX
INDEX = LIST_INDEXOF(TSTR:COM_SITUATION, VALUES)
IF INDEX != -1
    RESULT:1 = INDEX
    RETURNF 1
ELSE
    RETURNF 0
ENDIF
;#endregion

;-------------------------------------------------
; ハウジングモードのキャラデータに口上や地の文からアクセスするための式中関数
;-------------------------------------------------
;口上の式中関数が参照できるよう、口上出力の直前でハウジングモードの諸キャラデータをまとめてCSTRに格納する
@HOKJ_SET_CHARADATA_TO_CSTR(CHARA_ID)
#DIM CHARA_ID
#DIM DYNAMIC CHARA_IDX
#DIM DYNAMIC ROOM_IDX
#DIM DYNAMIC ROOM_ID
#DIM DYNAMIC MODULE_LIST_IDX
#DIM DYNAMIC MODULE_ID

SIF !FLAG:ハウジングモード
    RETURN 0

CALL HO_GET_CHARAIDX(CHARA_ID)
IF RESULT != -1
    CHARA_IDX = RESULT
    CALL HO_GET_CHARADATA(CHARA_IDX, "ROOM_IDX")
    ROOM_IDX = RESULT
ELSEIF CHARA_ID == MASTER
    ROOM_IDX = HO_MASTER現在地
ELSE
    RETURN 0
ENDIF
;使用しているエリアに関する情報
CSTR:CHARA_ID:USE_ROOM_IDX = %TOSTR(ROOM_IDX)%
CALL HO_GET_ROOM_ID(ROOM_IDX)
CSTR:CHARA_ID:USE_ROOM_ID = %TOSTR(RESULT)%
ROOM_ID = RESULT
CALL HO_GET_ROOM_NAME(ROOM_IDX)
CSTR:CHARA_ID:USE_ROOM_NAME = %RESULTS%
CALL HO_GET_ROOM_DATA(ROOM_ID,"ROOM_TAG")
CSTR:CHARA_ID:_LIST_USE_ROOM_TAG = %RESULTS%
;使用している設備に関する情報
IF FLAG:クエストモード
    MODULE_ID = TFLAG:クエスト_ダミー設備ID
ELSE
    CALL HO_GET_USE_MODULE_INFO(CHARA_ID)
    MODULE_ID = RESULT
ENDIF
CSTR:CHARA_ID:USE_MODULE_ID = %TOSTR(MODULE_ID)%

IF MODULE_ID == HO_CREW_PRIVATE_ROOM_ID
    CSTR:CHARA_ID:USE_MODULE_NAME '= @"%SNAME(CHARA_ID)%の部屋"
ELSE
    CALL HO_GET_MODULE_DATA(MODULE_ID, "MODULE_NAME")
    CSTR:CHARA_ID:USE_MODULE_NAME = %RESULTS%
ENDIF

CALL HO_GET_MODULE_DATA(MODULE_ID, "用途")
CSTR:CHARA_ID:_LIST_USE_MODULE_USAGE = %RESULTS%
CALL HO_GET_MODULE_DATA(MODULE_ID, "属性")
CSTR:CHARA_ID:_LIST_USE_MODULE_ELEMENT = %RESULTS%
IF CHARA_ID != MASTER
    CALL HO_GET_CHARADATA(CHARA_IDX, "USE_MODULE_IDX")
    CSTR:CHARA_ID:USE_MODULE_IDX = %TOSTR(RESULT)%
ELSE
    CSTR:CHARA_ID:USE_MODULE_IDX = %TOSTR(HO_MASTER_USE_MODULE_LIST_IDX)%
ENDIF

;キャラクターの実行中のアクションを式中関数として取得する
@HOKJ_IS_DOING(CHARA_ID)
#FUNCTIONS
#DIM CHARA_ID
#DIM DYNAMIC CHARA_IDX
SIF !FLAG:ハウジングモード
    RETURNF ""
CHARA_IDX = HO_GET_CHARAIDXF(CHARA_ID)
CALLF HO_GET_CHARADATAF(CHARA_IDX, "ACTION")
RETURNF RESULTS

;キャラクターが使用している設備の属性を取得する
@HOKJ_CHECK_ELEMENT(CHARA_ID, ELEMENT)
#FUNCTION
#DIM CHARA_ID
#DIMS ELEMENT
SIF !FLAG:ハウジングモード
    RETURNF 0
IF LIST_INDEXOF(CSTR:CHARA_ID:_LIST_USE_MODULE_ELEMENT, ELEMENT) != -1
    RETURNF 1
ELSE
    RETURNF 0
ENDIF

;-------------------------------------------------
;ハウジングモードの汎用関数
;-------------------------------------------------
@HO_GET_STR_CLOCK()
#DIM CLOCK
RESULT = (HO_TIME / 60) * 100 + (HO_TIME % 60)
RESULTS = %TOSTR(HO_TIME / 60, "00")%:%TOSTR(HO_TIME % 60, "00")%

;時刻を分換算
@HO_CLOCK(OCLOCK)
#FUNCTION
#DIM OCLOCK
RETURNF (((OCLOCK / 100) * 60) + (OCLOCK % 100))

;現在時刻を0700,2200など数値型の時刻で返す
@HO_OCLOCK()
#FUNCTION
RETURNF (HO_TIME / 60) * 100 + (HO_TIME % 60)

@HO_WEEK()
#FUNCTION
#DIM WEEK
WEEK = DAY % 8
RETURNF WEEK != 0 ? WEEK # 8

@HO_SEASON()
#FUNCTION
#DIM SEASON
SEASON = (DAY - 1) / 8
SEASON %= 4
RETURNF SEASON

;-------------------------------------------------
;重み付き乱択@COM_AUTO_RANDOMIZED_WEIGHTEDの利用頻度が高いため
;短縮形ラッパー関数を用意
;-------------------------------------------------
@RAND_WT_INIT()
CALL COM_AUTO_RANDOMIZED_WEIGHTED_START

;-------------------------------------------------
; 同RESULT値を許容 = 1の場合オリジナルと同じ挙動をする
; 0の場合、同じLOCAL_RESULTにLOCAL_NUM(重み)を2回セットした場合、元のLOCAL_RESULTのLOCAL_NUM(重み)が上書きされる
;-------------------------------------------------
@RAND_WT_SET(LOCAL_RESULT, LOCAL_NUM, 同RESULT値を許容 = 0)
#DIM LOCAL_RESULT
#DIM LOCAL_NUM
#DIM 同RESULT値を許容
#DIM DYNAMIC IDX
IF 同RESULT値を許容
    CALL COM_AUTO_RANDOMIZED_WEIGHTED_VALUE(LOCAL_RESULT, LOCAL_NUM)
ELSE
    IDX = FINDELEMENT(COM_AUTO_RANDOMIZED_NUM, LOCAL_RESULT)
    IF IDX != -1 && COM_AUTO_RANDOMIZED_COUNTER
        COM_AUTO_RANDOMIZED_WEIGHTED:IDX = LOCAL_NUM
    ELSE
        CALL COM_AUTO_RANDOMIZED_WEIGHTED_VALUE(LOCAL_RESULT, LOCAL_NUM)
    ENDIF
ENDIF

RETURN 0

@RAND_WT_RESET()
VARSET COM_AUTO_RANDOMIZED_WEIGHTED

@RAND_WT_RESULT()
#FUNCTION
RETURNF COM_AUTO_RANDOMIZED_WEIGHTED_RESULT()

;-------------------------------------------------
; メッセージ関連
;-------------------------------------------------
@KJ_PRINT(CHARA_ID, MESSAGE, DO_WAIT = 0)
#DIM CHARA_ID
#DIMS MESSAGE
#DIM  DO_WAIT
#DIM  F_COL
IF CFLAG:CHARA_ID:口上カラーコード
    F_COL = CFLAG:CHARA_ID:口上カラーコード
ELSE
    F_COL = GETCOLOR()
ENDIF
CALLF TAG_PRINTH(@"@C:{F_COL}@%MESSAGE%@/C@", 1)
SIF DO_WAIT
    WAIT

@PRINT_NOTICE(MESSAGE, COLOR = カラー_注意, NO_WAIT = 0)
#DIMS MESSAGE
#DIM  COLOR
#DIM  NO_WAIT
CALLF TAG_PRINT(@"@C:{COLOR}@―― %MESSAGE%@/C@", 1)
SIF !NO_WAIT
    WAIT

;引数分の文字列からランダムに一つ出力
@PRINT_RAND(ARGS:0 = "" ,ARGS:1 = "" ,ARGS:2 = "" ,ARGS:3 = "" ,ARGS:4 = "" ,ARGS:5 = "" ,ARGS:6 = "" ,ARGS:7 = "" , ARGS:8 = "" ,ARGS:9 = "")
#FUNCTIONS
#DIMS DYNAMIC LIST_TEXT
FOR LOCAL, 0, 10
    IF ARGS:LOCAL != ""
        LIST_TEXT = %LIST_ADD(LIST_TEXT, ARGS:LOCAL)%
    ENDIF
NEXT
CALLF TAG_PRINTH(@"%LIST_RAND(LIST_TEXT)%", 0)

;引数分の文字列から条件を満たすもののみランダムに一つ出力
@PRINT_RANDC(ARGS:0 = "" ,ARG:0 = 1 ,ARGS:1 = "", ARG:1 = 1 ,ARGS:2 = "", ARG:2 = 1 ,ARGS:3 = "", ARG:3 = 1 ,ARGS:4 = "", ARG:4 = 1 ,ARGS:5 = "", ARG:5 = 1 ,ARGS:6 = "", ARG:6 = 1 ,ARGS:7 = "", ARG:7 = 1 , ARGS:8 = "", ARG:8 = 1 ,ARGS:9 = "", ARG:9 = 1,ARGS:14 = "" ,ARG:14 = 1 ,ARGS:15 = "", ARG:15 = 1 ,ARGS:16 = "", ARG:16 = 1 ,ARGS:17 = "", ARG:17 = 1 ,ARGS:18 = "", ARG:18 = 1,ARGS:19 = "", ARG:19 = 1)
#FUNCTIONS
#DIMS DYNAMIC LIST_TEXT
FOR LOCAL, 0, 20
    SIF !ARG:LOCAL
        CONTINUE
    IF ARGS:LOCAL != ""
        LIST_TEXT = %LIST_ADD(LIST_TEXT, ARGS:LOCAL)%
    ENDIF
NEXT
SIF LIST_COUNT(LIST_TEXT) == 0
    RETURNF
CALLF TAG_PRINTH(@"%LIST_RAND(LIST_TEXT)%", 0)

;引数分の文字列から条件を満たすもののみランダムに一つ返却
@TEXT_RANDC(ARGS:0 = "" ,ARG:0 = 1 ,ARGS:1 = "", ARG:1 = 1 ,ARGS:2 = "", ARG:2 = 1 ,ARGS:3 = "", ARG:3 = 1 ,ARGS:4 = "", ARG:4 = 1 ,ARGS:5 = "", ARG:5 = 1 ,ARGS:6 = "", ARG:6 = 1 ,ARGS:7 = "", ARG:7 = 1 , ARGS:8 = "", ARG:8 = 1 ,ARGS:9 = "", ARG:9 = 1,ARGS:14 = "" ,ARG:14 = 1 ,ARGS:15 = "", ARG:15 = 1 ,ARGS:16 = "", ARG:16 = 1 ,ARGS:17 = "", ARG:17 = 1 ,ARGS:18 = "", ARG:18 = 1,ARGS:19 = "", ARG:19 = 1)
#FUNCTIONS
#DIMS DYNAMIC LIST_TEXT
FOR LOCAL, 0, 20
    SIF !ARG:LOCAL
        CONTINUE
    IF ARGS:LOCAL != ""
        LIST_TEXT = %LIST_ADD(LIST_TEXT, ARGS:LOCAL)%
    ENDIF
NEXT
SIF LIST_COUNT(LIST_TEXT) == 0
    RETURNF
RETURNF LIST_RAND(LIST_TEXT)

;引数分の文字列を結合して出力
@PRINT_CONCATE(ARGS:0 = "" ,ARGS:1 = "" ,ARGS:2 = "" ,ARGS:3 = "" ,ARGS:4 = "" ,ARGS:5 = "" ,ARGS:6 = "" ,ARGS:7 = "" , ARGS:8 = "" ,ARGS:9 = "")
#FUNCTIONS
LOCALS '= ""
FOR LOCAL, 0, 10
    IF ARGS:LOCAL != ""
        LOCALS += ARGS:LOCAL
    ENDIF
NEXT
CALLF TAG_PRINTH(@"%LOCALS%", 0)

;テキストを結合して返却
@TEXT_CONCATE(ARGS:0 = "" ,ARGS:1 = "" ,ARGS:2 = "" ,ARGS:3 = "" ,ARGS:4 = "" ,ARGS:5 = "" ,ARGS:6 = "" ,ARGS:7 = "" , ARGS:8 = "" ,ARGS:9 = "")
#FUNCTIONS
LOCALS '= ""
FOR LOCAL, 0, 10
    IF ARGS:LOCAL != ""
        LOCALS += ARGS:LOCAL
    ENDIF
NEXT
RETURNF LOCALS

;引数分の文字列から条件を満たすもののみ結合
@TEXT_CONCATEC(ARGS:0 = "" ,ARG:0 = 1 ,ARGS:1 = "", ARG:1 = 1 ,ARGS:2 = "", ARG:2 = 1 ,ARGS:3 = "", ARG:3 = 1 ,ARGS:4 = "", ARG:4 = 1 ,ARGS:5 = "", ARG:5 = 1 ,ARGS:6 = "", ARG:6 = 1 ,ARGS:7 = "", ARG:7 = 1 , ARGS:8 = "", ARG:8 = 1 ,ARGS:9 = "", ARG:9 = 1,ARGS:14 = "" ,ARG:14 = 1 ,ARGS:15 = "", ARG:15 = 1 ,ARGS:16 = "", ARG:16 = 1 ,ARGS:17 = "", ARG:17 = 1 ,ARGS:18 = "", ARG:18 = 1,ARGS:19 = "", ARG:19 = 1)
#FUNCTIONS
LOCALS '= ""
FOR LOCAL, 0, 20
    SIF !ARG:LOCAL
        CONTINUE
    IF ARGS:LOCAL != ""
        LOCALS += ARGS:LOCAL
    ENDIF
NEXT
RETURNF LOCALS

@PRINT_TITLE(TEXT, TYPE)
#DIMS TEXT
#DIMS TYPE

SELECTCASE TYPE
    CASE "コマンド", "COMMAND"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_白}@@S:1@<< %TEXT% >>@/S@@/C@", 1)
        CALL COLOR_LINE
    CASE "リアクション", "REACTION"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_ピンク}@@S:1@<< ♡ Reaction ♡ %TEXT% >>@/S@@/C@", 1)
        CALL COLOR_LINE
    CASE "割込", "INTERRUPTION"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_黄}@@S:1@<< ♡ Interruption ♡ %TEXT% >>@/S@@/C@", 1)
        CALL COLOR_LINE
    CASE "エロイベント", "ERO"
        CALL COLOR_LINE
        CALLF TAG_PRINTH(@"@C:{カラー_ピンク}@<< @S:1@ ♡ EVENT ♡ @/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
    CASE "エロトラップ", "EROTRAP"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_ピンク}@<< @S:1@♡ TRAP ♡@/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
    CASE "トラップ", "TRAP"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_黄}@<< @S:1@!! TRAP !!@/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
    CASE "戦闘", "BATTLE"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_黄}@<< @S:1@!! BATTLE !!@/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
    CASE "ボス", "BOSS"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_レッド}@<< @S:1@!! ―― BOSS BATTLE ―― !!@/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
    CASE "クエスト", "QUEST"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_白}@@S:1@『 %TEXT% 』@/S@@/C@", 1)
        CALL COLOR_LINE
    CASE "判定", "ROLL"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_白}@@S:1@<< %TEXT% >>@/S@@/C@", 1)
        CALL COLOR_LINE
    CASE "戦利品", "COMBAT_REWARD"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_黄}@@S:1@☆ ―― %TEXT% ―― ☆@/S@@/C@", 1)
        CALL COLOR_LINE
    CASE "季節", "SEASON"
        CALL COLOR_LINE(1, HO_SEASON_COLOR:HO_SEASON())
        CALLF TAG_PRINT(@"@C:{HO_SEASON_COLOR:HO_SEASON()}@@S:1@<< めぐる季節:%HO_SEASON_STR:HO_SEASON()% >>@/S@@/C@", 1)
        CALL COLOR_LINE(1, HO_SEASON_COLOR:HO_SEASON())
    CASE "TIPS"
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_黄}@<< @S:1@ TIPS @/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
    CASEELSE
        CALL COLOR_LINE
        CALLF TAG_PRINT(@"@C:{カラー_白}@<< @S:1@ EVENT @/S@ %TEXT% >>@/C@", 1)
        CALL COLOR_LINE
ENDSELECT

;-------------------------------------------------
;;; 複数行の長文テキストをまとめて出力するPRINT用関数
;;; 500行まで対応
;;; - 書式
;;; \nを改行とみなす
;;; [キャラ識別名]:「テキスト」 のように記述されている場合、そのキャラクターの口上色でテキストを印字する
;;; その他文中の基本的な書式は口上XMLと同じ
;-------------------------------------------------
@PRINT_DIAG(TEXT)
#DIMS TEXT
#DIMS DYNAMIC COLUMN, 500

VARSET COLUMN, "-1"
CALL TEXT_SPLIT_RAWTEXT(TEXT, COLUMN)

CALL PRINT_TEXT_COLUMN(COLUMN)

;-------------------------------------------------
;ARG:0をARG:1倍する。TIMESのような関数
;ARG:1はデフォルト百分率指定。ARG:2で変更可
;-------------------------------------------------
@FTIMES(ARG:0, ARG:1, ARG:2 = 100)
#FUNCTION
RETURNF ARG:0 * ARG:1 / ARG:2

;-------------------------------------------------
;ARG%の判定
;デフォルトは百分率。
;-------------------------------------------------
@PERCENT(ARG, PER = 100)
#FUNCTION
#DIM PER
RETURNF RAND:PER < ARG


code:
;対象キャラクタの引数で指定した部位が衣服で覆われている場合は覆っている衣装の部位とIDを返す
;被覆判定は身体の上から順番に見て、最も表層の衣装を返す
;RESULT:0 衣装部位
;RESULT:1 衣装ID
;RESULTS:0 衣装名
;RESULTS:1 衣装描写（未定義の場合は衣装名）
@IS_COVERED(CHARA_ID, 被覆部位, 下着のみ判定 = 0)
#DIM CHARA_ID
#DIM 被覆部位
#DIM 下着のみ判定
#DIM DYNAMIC 衣装部位
#DIM DYNAMIC CLOTH_ID
#DIM DYNAMIC CLOTH_PART
#DIM DYNAMIC COVERED_PARTS, CLOTH_PART_NUM
#DIMS DYNAMIC 被覆衣装名
#DIMS DYNAMIC 被覆衣装描写

VARSET RESULT
VARSET RESULTS

SELECTCASE 被覆部位
        ;上半身
    CASE 被覆部位_乳房,被覆部位_乳首,被覆部位_腹
        IF 調教用衣装:CHARA_ID:衣装部位_上下服 != 0 && 衣装状態:CHARA_ID:衣装部位_上下服 == 0 && 下着のみ判定 == 0
            衣装部位 = 衣装部位_上下服
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ELSE
                ;服で被覆されていないなら下着を対象に再判定
                CALL IS_COVERED(CHARA_ID, 被覆部位, 1)
                RETURN RESULT
            ENDIF
        ELSEIF 調教用衣装:CHARA_ID:衣装部位_上服 != 0 && 衣装状態:CHARA_ID:衣装部位_上服 == 0 && 下着のみ判定 == 0
            衣装部位 = 衣装部位_上服
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ELSE
                ;服で被覆されていないなら下着を対象に再判定
                CALL IS_COVERED(CHARA_ID, 被覆部位, 1)
                RETURN RESULT
            ENDIF
        ELSEIF 調教用衣装:CHARA_ID:衣装部位_下着上 != 0 && 衣装状態:CHARA_ID:衣装部位_下着上 == 0
            衣装部位 = 衣装部位_下着上
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ENDIF
        ELSEIF 調教用衣装:CHARA_ID:衣装部位_上下下着 != 0 && 衣装状態:CHARA_ID:衣装部位_上下下着 == 0
            衣装部位 = 衣装部位_上下下着
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ENDIF
        ENDIF
        IF CLOTH_ID
            TRYCALLFORM CLOTH_NAME_%CLOTH_PART_NAME_ENG:衣装部位%_{CLOTH_ID}
            被覆衣装名 = %RESULTS%
            TRYCCALLFORM CLOTH_DESC_%CLOTH_PART_NAME_ENG:衣装部位%_{CLOTH_ID}
                被覆衣装描写 = %RESULTS%
            CATCH
                被覆衣装描写 = %被覆衣装名%
            ENDCATCH
            RESULT:1   = 調教用衣装:CHARA_ID:衣装部位
            RESULTS:0  = %被覆衣装名%
            RESULTS:1  = %被覆衣装描写%
        ENDIF
        RETURN 衣装部位
        ;下半身
    CASE 被覆部位_尻,被覆部位_秘部
        IF 調教用衣装:CHARA_ID:衣装部位_上下服 != 0 && 衣装状態:CHARA_ID:衣装部位_上下服 == 0 && 下着のみ判定 == 0
            衣装部位 = 衣装部位_上下服
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ELSE
                ;服で被覆されていないなら下着を対象に再判定
                CALL IS_COVERED(CHARA_ID, 被覆部位, 1)
                RETURN RESULT
            ENDIF
        ELSEIF 調教用衣装:CHARA_ID:衣装部位_下服 != 0 && 衣装状態:CHARA_ID:衣装部位_下服 == 0 && 下着のみ判定 == 0
            衣装部位 = 衣装部位_下服
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ELSE
                ;服で被覆されていないなら下着を対象に再判定
                CALL IS_COVERED(CHARA_ID, 被覆部位, 1)
                RETURN RESULT
            ENDIF
        ELSEIF 調教用衣装:CHARA_ID:衣装部位_下着下 != 0 && 衣装状態:CHARA_ID:衣装部位_下着下 == 0
            衣装部位 = 衣装部位_下着下
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ENDIF
        ELSEIF 調教用衣装:CHARA_ID:衣装部位_上下下着 != 0 && 衣装状態:CHARA_ID:衣装部位_上下下着 == 0
            衣装部位 = 衣装部位_上下下着
            CALL CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, 調教用衣装:CHARA_ID:衣装部位)
            IF COVERED_PARTS:被覆部位 == 1
                CLOTH_ID = 調教用衣装:CHARA_ID:衣装部位
            ENDIF
        ENDIF
        IF CLOTH_ID
            TRYCALLFORM CLOTH_NAME_%CLOTH_PART_NAME_ENG:衣装部位%_{CLOTH_ID}
            被覆衣装名 = %RESULTS%
            TRYCCALLFORM CLOTH_DESC_%CLOTH_PART_NAME_ENG:衣装部位%_{CLOTH_ID}
                被覆衣装描写 = %RESULTS%
            CATCH
                被覆衣装描写 = %被覆衣装名%
            ENDCATCH
            RESULT:1   = 調教用衣装:CHARA_ID:衣装部位
            RESULTS:0  = %被覆衣装名%
            RESULTS:1  = %被覆衣装描写%
        ENDIF
        RETURN 衣装部位
ENDSELECT

@CLOTH_GET_COVERAGE(COVERED_PARTS, 衣装部位, CLOTH_ID)
#DIM REF COVERED_PARTS
#DIM 衣装部位
#DIM CLOTH_ID
VARSET COVERED_PARTS, 0
TRYCALLFORM CLOTH_COVERED_%CLOTH_PART_NAME_ENG:衣装部位%_{CLOTH_ID}(COVERED_PARTS)
RETURN

;各キャラクター用の衣装ボタンIDを生成して返す
;2XXXXYY XXXX = CHARA_ID, YY = 衣装部位
@HO_GET_CLOTH_BTN_ID(CHARA_ID, 部位)
#DIM CHARA_ID
#DIM 部位
#DIM DYNAMIC BTN_ID
#DIMS DYNAMIC STR_BTN_ID
#DIMS DYNAMIC STR_CHARA_ID
#DIMS DYNAMIC STR_部位

STR_CHARA_ID '= TOSTR(CHARA_ID, "0000")
STR_部位 '= TOSTR(部位, "00")
STR_BTN_ID '= STR_CHARA_ID + STR_部位
BTN_ID = HO_キャラボタンID_衣装 + TOINT(STR_BTN_ID)

RETURN BTN_ID

;;;衣装の脱着
@HO_CHANGE_CLOTH_COND(CHARA_ID, 部位)
#DIM BTN_ID
#DIM DYNAMIC 部位
#DIM DYNAMIC CHARA_ID
#DIM DYNAMIC CLOTH_ID
#DIM DYNAMIC 下着部位
#DIM DYNAMIC 下着ID
#DIMS DYNAMIC 衣装描写
#DIMS DYNAMIC 下着描写

#DIM DYNAMIC  人目があるフラグ

;全脱衣、全着衣処理
IF 部位 == 98 ;全脱衣
    CALL HO_JUDGE_STRIP(CHARA_ID)
    CALL HO_CHECK_PUBLIC_EYE(CHARA_ID)
    SIF RESULT == 1
        人目があるフラグ = 1
    IF TCVAR:(CHARA_ID):24 > TCVAR:(CHARA_ID):25 && 人目があるフラグ != 1 || CHARA_ID == MASTER && 人目があるフラグ != 1
        IF CHARA_ID == MASTER || FLAG:クエスト_あなた不参加
            PRINTFORMW %ANAME(CHARA_ID)%は服を%SPLIT_RAND("脱ぎおろした/取り払った",1)%
        ELSE
            PRINTFORMW %ANAME(MASTER)%の頼みに応じて、%ANAME(CHARA_ID)%は%SPLIT_RAND("顔を赤らめ/羞恥に頬染め/羞恥のあまり目を伏せ",1)%つつ服を%SPLIT_RAND("脱ぎおろした/取り払った",1)%
        ENDIF
        CALL HO_UNDRESS(CHARA_ID)
        RETURN 1
    ELSEIF TCVAR:(CHARA_ID):24 > TCVAR:(CHARA_ID):25 && 人目があるフラグ == 1 && CHARA_ID != MASTER && !FLAG:クエスト_あなた不参加
        PRINTFORMW %ANAME(CHARA_ID)%に服を脱いでもらえないか頼んでみたものの、人目があるからと断られてしまった……
        RETURN 0
    ELSEIF 人目があるフラグ == 1 && (CHARA_ID == MASTER || FLAG:クエスト_あなた不参加)
        PRINTFORMW ここで服を脱ぐのは人目が気になる……
        RETURN 0
    ELSE
        PRINTFORMW %ANAME(CHARA_ID)%に服を脱いでもらえないか頼んでみたものの、%SPLIT_RAND("きっぱりと断られて/一笑に付されて/冷ややかな目で見られて/呆れた目で見られて",1)%しまった……
        RETURN 0
    ENDIF
ELSEIF 部位 == 99 ;全着衣
    CALL HO_REDRESS(CHARA_ID)
    RETURN 1
ENDIF

;個別処理
CLOTH_ID = 調教用衣装:CHARA_ID:部位
SELECTCASE 衣装状態:CHARA_ID:部位
    CASE 衣装状態_着
        SELECTCASE 部位
            CASE 衣装部位_上下服,衣装部位_上服,衣装部位_下服,衣装部位_下着下,衣装部位_下着上,衣装部位_上下下着
                CALL GET_CLOTH_DESC(部位, CLOTH_ID)
                衣装描写 '= RESULTS
                CALL HO_JUDGE_STRIP(CHARA_ID)
                CALL HO_CHECK_PUBLIC_EYE(CHARA_ID)
                SIF RESULT == 1
                    人目があるフラグ = 1
                IF TCVAR:(CHARA_ID):24 > TCVAR:(CHARA_ID):25 && 人目があるフラグ != 1 || CHARA_ID == MASTER && 人目があるフラグ != 1
                    衣装状態:CHARA_ID:部位 = 衣装状態_半脱
                    IF CHARA_ID == MASTER || FLAG:クエスト_あなた不参加
                        PRINTFORMW %ANAME(CHARA_ID)%は%衣装描写%を%SPLIT_RAND("脱ぎおろした/取り払った",1)%
                    ELSE
                        PRINTFORMW %ANAME(MASTER)%の頼みに応じて、%ANAME(CHARA_ID)%は%SPLIT_RAND("顔を赤らめ/羞恥に頬染め/羞恥のあまり目を伏せ",1)%つつ%衣装描写%を%SPLIT_RAND("脱ぎおろした/取り払った",1)%
                    ENDIF
                    IF 部位 == 衣装部位_上服 || 部位 == 衣装部位_下着上
                        CALL IS_COVERED(CHARA_ID, 被覆部位_乳首)
                        下着部位 = RESULT:0
                        下着ID = RESULT:1
                        IF 下着ID != 0
                            CALL GET_CLOTH_DESC(下着部位, 下着ID)
                            下着描写 '= RESULTS
                            CALLF TAG_PRINT(@"取り払われた%衣装描写%の下から@C:{カラー_ピンク}@%下着描写%@/C@があらわになった……", 1)
                            WAIT
                        ELSE
                            CALLF TAG_PRINT(@"取り払われた%衣装描写%の下から@C:{カラー_ピンク}@%STR_BODY("胸：長", CHARA_ID)%@/C@があらわになった……", 1)
                            WAIT
                        ENDIF
                    ENDIF
                    IF 部位 == 衣装部位_下服 || 部位 == 衣装部位_下着下
                        CALL IS_COVERED(CHARA_ID, 被覆部位_秘部)
                        下着部位 = RESULT:0
                        下着ID = RESULT:1
                        IF 下着ID != 0
                            CALL GET_CLOTH_DESC(下着部位, 下着ID)
                            下着描写 '= RESULTS
                            CALLF TAG_PRINT(@"取り払われた%衣装描写%の下から@C:{カラー_ピンク}@%下着描写%@/C@があらわになった……", 1)
                            WAIT
                        ELSE
                            IF !HAS_PENIS(CHARA_ID)
                                CALLF TAG_PRINT(@"取り払われた%衣装描写%の下から@C:{カラー_ピンク}@%STR_BODY("クリ：感度：欲情", CHARA_ID)%@/C@があらわになった……", 1)
                            ELSE
                                CALLF TAG_PRINT(@"取り払われた%衣装描写%の下から@C:{カラー_ピンク}@ペニス@/C@があらわになった……", 1)
                            ENDIF
                            WAIT
                        ENDIF
                    ENDIF
                    衣装状態:CHARA_ID:部位 = 衣装状態_半脱
                    RETURN 1
                ELSEIF TCVAR:(CHARA_ID):24 > TCVAR:(CHARA_ID):25 && 人目があるフラグ == 1 && CHARA_ID != MASTER && !FLAG:クエスト_あなた不参加
                    PRINTFORMW %ANAME(CHARA_ID)%に%衣装描写%を脱いでもらえないか頼んでみたものの、人目があるからと断られてしまった……
                    RETURN 0
                ELSEIF 人目があるフラグ == 1 && (CHARA_ID == MASTER || FLAG:クエスト_あなた不参加)
                    PRINTFORMW ここで%衣装描写%を脱ぐのは人目が気になる……
                    RETURN 0
                ELSE
                    PRINTFORMW %ANAME(CHARA_ID)%に%衣装描写%を脱いでもらえないか頼んでみたものの、%SPLIT_RAND("きっぱりと断られて/一笑に付されて/冷ややかな目で見られて/呆れた目で見られて",1)%しまった……
                    RETURN 0
                ENDIF
            CASEELSE
                衣装状態:CHARA_ID:部位 = 衣装状態_半脱
                RETURN 1
        ENDSELECT
    CASE 衣装状態_半脱
        衣装状態:CHARA_ID:部位 = 衣装状態_脱
        RETURN 1
    CASE 衣装状態_脱
        衣装状態:CHARA_ID:部位 = 衣装状態_着
        RETURN 1
ENDSELECT

@HO_JUDGE_STRIP(CHARA_ID, 判定値を表示 = 0)
#DIM CHARA_ID
#DIM 判定値を表示
;実行値の設定
TCVAR:(CHARA_ID):25 = 80

;共通部分
CALL COM_ORDER(CHARA_ID)

CALL COM_ORDER_ELEMENT(CHARA_ID, @"欲望Lv{ABL:(CHARA_ID):欲望}", ABL:(CHARA_ID):欲望 * 3)
CALL COM_ORDER_ELEMENT(CHARA_ID, @"露出Lv{ABL:(CHARA_ID):露出}", ABL:(CHARA_ID):露出 * 5)

LOCAL:0 = GET_PALAMLV(PALAM:(CHARA_ID):欲情)
CALL COM_ORDER_ELEMENT(CHARA_ID, @"欲情Lv{LOCAL:0}", MIN(LOCAL:0 * 3, 30))

IF TCVAR:(CHARA_ID):60
    CALL COM_ORDER_ELEMENT(CHARA_ID, "媚薬", 6)
ENDIF

IF TALENT:(CHARA_ID):恥じらい
    CALL COM_ORDER_ELEMENT(CHARA_ID, "恥じらい", -12)
ENDIF
IF TALENT:(CHARA_ID):恥薄い
    CALL COM_ORDER_ELEMENT(CHARA_ID, "恥薄い", 8)
ENDIF
IF TALENT:(CHARA_ID):自制心
    CALL COM_ORDER_ELEMENT(CHARA_ID, "自制心", -6)
ENDIF
IF TALENT:(CHARA_ID):目立ちたがり
    CALL COM_ORDER_ELEMENT(CHARA_ID, "目立ちたがり", 6)
ENDIF
IF TALENT:(CHARA_ID):自慰しやすい
    CALL COM_ORDER_ELEMENT(CHARA_ID, "自慰しやすい", 10)
ENDIF
IF TALENT:(CHARA_ID):快感の否定
    CALL COM_ORDER_ELEMENT(CHARA_ID, "快感の否定", -2)
ENDIF

IF !TALENT:(CHARA_ID):合意 && !TALENT:(CHARA_ID):親友
    CALL COM_ORDER_ELEMENT(CHARA_ID, "合意なし", -20)
ENDIF
PRINTL
SIF 判定値を表示 == 0
    CLEARLINE 1
RETURN 1

;衣装を初期状態に
@HO_REDRESS(CHARA_ID, 破れを直す = 0)
#DIM CHARA_ID
#DIM 破れを直す
#DIM DYNAMIC 実行フラグ

;無効なプリセットが予約された場合は通常プリセットを適用
IF !CLOTH_PRESET_IS_VALID:CHARA_ID:(CFLAG:CHARA_ID:衣装プリセット変更予約)
    CFLAG:CHARA_ID:衣装プリセット変更予約 = 衣装プリセット_通常
ENDIF

;変更予約フラグが立っており、現在適用中の衣装プリセットと異なる場合は破れを直し、プリセットを適用する
IF CFLAG:CHARA_ID:衣装プリセット変更予約 && CLOTH_PRESET_IS_VALID:CHARA_ID:(CFLAG:CHARA_ID:衣装プリセット変更予約)
    IF CFLAG:CHARA_ID:衣装プリセット != CFLAG:CHARA_ID:衣装プリセット変更予約
        破れを直す = 1
        CFLAG:CHARA_ID:衣装プリセット = CFLAG:CHARA_ID:衣装プリセット変更予約
        実行フラグ = 1
    ENDIF
ENDIF

CALL SET_CHARA_CLOTH_DATA(CHARA_ID)

FOR LOCAL, 0, CLOTH_PART_NUM
    IF 衣装状態:CHARA_ID:LOCAL != 衣装状態_着 && 衣装状態:CHARA_ID:LOCAL != 衣装状態_破
        衣装状態:CHARA_ID:LOCAL = 衣装状態_着
        実行フラグ = 1
    ELSEIF 衣装状態:CHARA_ID:LOCAL != 衣装状態_着 && 破れを直す == 1
        衣装損壊率:CHARA_ID:LOCAL = 0
        衣装状態:CHARA_ID:LOCAL = 衣装状態_着
        実行フラグ = 1
    ENDIF
NEXT
CALL C_COND_SET_CLOTH_COVERRAGE(CHARA_ID)
RETURN 実行フラグ

;問答無用で全裸
@HO_UNDRESS(CHARA_ID)
#DIM CHARA_ID
VARSET 衣装状態:CHARA_ID:0 ,衣装状態_脱
CALL C_COND_SET_CLOTH_COVERRAGE(CHARA_ID)
RETURN 1

;部位指定脱衣
;枚数指定 > 0 の場合指定枚数分実行, 0の場合指定部位が露出するまで実行
;RESULT 実際に脱いだ枚数
@HO_STRIP(CHARA_ID, 被覆部位, 衣装状態指定, 枚数指定 = 0)
#DIM CHARA_ID
#DIM 被覆部位
#DIM 衣装状態指定
#DIM 枚数指定
#DIM DYNAMIC 脱衣カウンタ

WHILE 1
    SIF 枚数指定 != 0 && 脱衣カウンタ >= 枚数指定
        BREAK
    CALL IS_COVERED(CHARA_ID, 被覆部位)
    IF RESULT:1
        衣装状態:CHARA_ID:(RESULT:0) = 衣装状態指定
        脱衣カウンタ ++
    ELSE
        BREAK
    ENDIF
WEND
CALL C_COND_SET_CLOTH_COVERRAGE(CHARA_ID)
RETURN 脱衣カウンタ

;見え判定
;RESULT = 1(乳首露出) 2(秘部露出) 3(全部露出)
@HO_CHECK_NAKED(CHARA_ID)
#DIM CHARA_ID
#DIM DYNAMIC 露出
SIF !FLAG:ハウジングモード && !FLAG:クエストモード && !FLAG:デイリーイベント
    RETURN 0
CALL IS_COVERED(CHARA_ID, 被覆部位_乳首)
SIF !RESULT:1
    露出 += 1
CALL IS_COVERED(CHARA_ID, 被覆部位_秘部)
SIF !RESULT:1
    露出 += 2
RETURN 露出

repo_name: napo/erafl

license: unknown


code:
;-------------------------------------------------
;ハウジングモードでの調教時に使用する関数
;-------------------------------------------------
;;; 一緒に行動できるキャラクターをまとめてMTARに登録する
;;; ACTIONは','区切りで10個まで複数指定できる
;-------------------------------------------------
@HO_SET_MTAR_PLAY_WITH(ACTION, RESET_MTAR = 1, FORCE_ADD_TO_MTAR = 1)
#DIMS ACTION
#DIM  RESET_MTAR
#DIM  FORCE_ADD_TO_MTAR
#DIMS DYNAMIC _LIST_MEMBER
#DIM DYNAMIC MEMBER_NUM
#DIM DYNAMIC CHARA_ID

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

SIF RESET_MTAR
    CALL CLEAR_MTAR
CALL HO_GET_COMPANION_LIST
MEMBER_NUM = RESULT
_LIST_MEMBER = %RESULTS%
FOR LOCAL, 0, MEMBER_NUM
    CHARA_ID = TOINT(LIST_GET(_LIST_MEMBER, LOCAL))
    ;MPLYに既におり、MPLYが単独でない場合、MPLYからは外す
    SIF IS_MPLY(CHARA_ID) && FORCE_ADD_TO_MTAR && MPLY_NUM > 1
        CALL DEL_MPLY(CHARA_ID)
    ;同行者はMPLYでないなら追加
    IF TCVAR:CHARA_ID:相席フラグ != 1 && !IS_MPLY(CHARA_ID) && FORCE_ADD_TO_MTAR
        CALL ADD_MTAR(CHARA_ID)
    ELSE
        ;相席者は引数で指定した行動に合致していたら追加
        CALL HO_GET_CHARAACT(CHARA_ID)
        VARI I
        FOR I, 0, ACTIONNUM
            IF RESULTS == ACTIONS:I && !IS_MPLY(CHARA_ID) && FORCE_ADD_TO_MTAR
                CALL ADD_MTAR(CHARA_ID)
            ENDIF
        NEXT
    ENDIF
NEXT

RETURN

;-------------------------------------------------
;第三者から見られているかを確認
;行為を見られても許容出来る相手かも確認
;RESULT 0:見られていない 1:見られている
;-------------------------------------------------
@HO_CHECK_PUBLIC_EYE(MPLY_ID)
#DIM MPLY_ID
#DIM DYNAMIC CHARA_ID
#DIMS DYNAMIC _LIST_VISIBLE
#DIMS DYNAMIC _LIST_USAGE

;クエスト中でも領内活動中でもない場合は人目を判定することが出来ないので
;誰にも見られていないものとする
SIF !FLAG:ハウジングモード
    RETURN 0

;クエスト中はウフフ許可フラグが立っていない限り、誰かに見られているものとする
SIF FLAG:調教モード == 調教_クエスト && !FLAG:クエスト_ウフフ許可
    RETURN 1

;虜囚は許容の有無を問わない
IF CFLAG:MPLY_ID:捕虜先
    RETURN 0
ENDIF
CALL HO_GET_WHO_VISIBLE(MPLY_ID)
_LIST_VISIBLE = %RESULTS%
IF RESULT == 0
    RETURN 0
ELSE
    FOR LOCAL, 0, LIST_COUNT(_LIST_VISIBLE)
        CHARA_ID = TOINT(LIST_GET(_LIST_VISIBLE, LOCAL))
        ;合意済みであれば見られても問題なし
        IF TALENT:CHARA_ID:合意 == 1
            CONTINUE
            ;カップルに見られても問題なし
        ELSEIF CHARA_ID == CFLAG:MPLY_ID:カップル相手キャラID
            CONTINUE
            ;見られている相手が捕虜の場合、加虐的は人物は視線を意識しない
        ELSEIF (CFLAG:MPLY_ID:捕虜先 || IS_SLAVE(CHARA_ID)) && CAN_RAPE_ACCEPT(MPLY_ID)
            CONTINUE
            ;スケベモブが売春施設で見られても問題なし
        ELSEIF CFLAG:MPLY_ID:スケベモブ
            CALL HO_GET_MODULE_DATA(C_COND_MAP_GET(CHARA_ID, "設備"), "用途")
            _LIST_USAGE = %RESULTS%
            IF LIST_GMATCH(_LIST_USAGE, "OR", "売春", "性行為", "性処理")
                CONTINUE
            ENDIF
        ELSE
            RETURN 1
        ENDIF
    NEXT
ENDIF
RETURN 0
;-------------------------------------------------
;第三者から見られているかを確認
;-------------------------------------------------
@HO_GET_WHO_VISIBLE(MPLY_ID)
#DIM MPLY_ID
#DIM DYNAMIC CHARA_IDX
#DIM DYNAMIC CHARA_ID
#DIMS DYNAMIC _LIST_VISIBLE

VARSET RESULTS
WHILE _DIC_HO_CHARALIST:CHARA_IDX != "-1"
    IF _DIC_HO_CHARALIST:CHARA_IDX == "DELETED"
        CHARA_IDX ++
        CONTINUE
    ENDIF
    CALL HO_GET_CHARADATA(CHARA_IDX, "CHARA_ID")
    CHARA_ID = RESULT
    ;自分自身はチェックしない
    IF MPLY_ID == CHARA_ID
        CHARA_IDX ++
        CONTINUE
    ENDIF
    CALL HO_IS_TARGET_VISIBLE(MPLY_ID, CHARA_ID)
    SIF RESULT
        _LIST_VISIBLE = %LIST_ADD(_LIST_VISIBLE, TOSTR(CHARA_ID))%
    CHARA_IDX ++
WEND

RESULTS = %_LIST_VISIBLE%
RETURN LIST_COUNT(_LIST_VISIBLE)

;-------------------------------------------------
;ウフフ目撃判定
;引数のキャラクタが実行されたコマンドを情事を目撃したと認識するか判定する
;RETURN 0=見ていない、気がついていない 1=情事露見 2=情事ほどではないが意識してしまう行為 3=気がついたが許容
;-------------------------------------------------
@HO_CHECK_UFUFU(CHARA_ID)
#DIM CHARA_ID
#DIM  DYNAMIC キャラ現在地
#DIM  DYNAMIC ウフフチェック済み
#DIMS DYNAMIC _LIST_MEMBER
#DIMS DYNAMIC ACTION
;;許容判定
;当人がコマンドの実行または対象であれば判定しない
IF IS_MPLY(CHARA_ID) || IS_MTAR(CHARA_ID)
    RETURN 3
ENDIF

;意識不明なら判定しない
IF TCVAR:CHARA_ID:離脱フラグ == 離脱フラグ_睡眠
    RETURN 0
ENDIF

;スケベな公演は判定しない
IF TFLAG:公演_趣向 == 1
    RETURN 3
ENDIF

;適切な場所での行為は容認される
IF C_COND("エリアタグ:娼館",,CHARA_ID)
    RETURN 3
ENDIF

CALL HO_GET_CHARAACT(CHARA_ID)
ACTION = %RESULTS%
;特定の行動中
IF GROUPMATCH(ACTION, "搾乳中")
    RETURN 3
ENDIF

;;目撃判定
;キャラが現在いる部屋を取得
CALL HO_GET_CHARAPLACE(CHARA_ID)
キャラ現在地 = RESULT
;ウフフ目撃判定
IF HO_MASTER現在地 == キャラ現在地
    ;覗き見中は判定しない
    SIF TFLAG:覗き見モード
        RETURN 0
    IF ACTION != "同行中" && TCVAR:CHARA_ID:同行解除フラグ != 1
        SIF ACTION == "逢瀬中"
            RETURN 0
        ;見えない位置にいるのなら判定しなくて良い
        CALL HO_IS_TARGET_VISIBLE(CHARA_ID, MASTER)
        SIF RESULT != 1
            RETURN 0
        ;押し倒し中の場合は情事扱い
        IF FLAG:ウフフフラグ == 1
            TCVAR:CHARA_ID:ウフフ目撃フラグ = 1
            TCVAR:CHARA_ID:ウフフ目撃場所 = キャラ現在地
            RETURN 1
        ELSE
            VARI 机使用中
            VARI 卓使用中
            VARI ウフフ隠蔽
            ;;押し倒し以外の情事判定
            ;-------------------------------------------------
            ;単発コマンドの判定 MTARにもMPLYにも絡んでいなければ目撃判定
            IF FINDELEMENT(UFUFU_COM_LIST, SELECTCOM) != -1
                ;一部の机下行為は露見しない
                机使用中 = C_COND("設備属性:机",,MASTER)
                卓使用中 = C_COND("設備属性:卓",,MASTER)
                IF 机使用中 && GROUPMATCH(SELECTCOM, 10, 11, 26, 106, 107, 90, 19, 132, 120, 100)
                    ウフフ隠蔽 = 1
                ENDIF
                IF !ウフフ隠蔽
                    IF 卓使用中 && GROUPMATCH(SELECTCOM, 14)
                        ウフフ隠蔽 = 1
                    ENDIF
                ENDIF
                IF !ウフフ隠蔽
                    IF IS_MTAR(CHARA_ID) != 1 && IS_MPLY(CHARA_ID) != 1
                        TCVAR:CHARA_ID:ウフフ目撃フラグ = 1
                        TCVAR:CHARA_ID:ウフフ目撃場所 = キャラ現在地
                        RETURN 1
                    ENDIF
                ENDIF
                ;ドキドキ判定
            ELSEIF  FINDELEMENT(DOKIDOKI_COM_LIST, SELECTCOM) != -1
                IF IS_MTAR(CHARA_ID) != 1 && IS_MPLY(CHARA_ID) != 1
                    RETURN 2
                ENDIF
            ENDIF
            ;継続中コマンドの判定 MTARにもMPLYにも絡んでいなければ目撃判定
            ;-------------------------------------------------
            机使用中 = C_COND("設備属性:机",,MASTER)
            卓使用中 = C_COND("設備属性:卓",,MASTER)
            ウフフ隠蔽 = 0
            VARSET LOCAL
            FOR LOCAL:0, 0, VARSIZE("UFUFU_COM_LIST")
                ;一部の机下行為は露見しない
                IF 机使用中 && GROUPMATCH(UFUFU_COM_LIST:(LOCAL:0), 10, 11, 26, 106, 107, 90, 19, 132, 120, 100)
                    ウフフ隠蔽 = 1
                    CONTINUE
                ENDIF
                ;一部の卓下行為は露見しない
                IF 卓使用中 && GROUPMATCH(UFUFU_COM_LIST:(LOCAL:0), 14)
                    ウフフ隠蔽 = 1
                    CONTINUE
                ENDIF
                IF IS_EQUIP(MASTER, UFUFU_COM_LIST:(LOCAL:0))
                    ウフフ隠蔽 = 0
                    LOCAL:1 ++
                ENDIF
            NEXT
            ;MASTERがウフフ行為を隠蔽出来ている状況なら以降の判定をスキップ
            IF !ウフフ隠蔽
                ; ;MASTERが情事に該当する行為のMPLYでもMTARでもなければRETURN
                ; SIF LOCAL:1 == 0
                ;     RETURN 0
                机使用中 = C_COND("設備属性:机",,CHARA_ID)
                卓使用中 = C_COND("設備属性:卓",,CHARA_ID)
                ウフフ隠蔽 = 0
                FOR LOCAL:0, 0, VARSIZE("UFUFU_COM_LIST")
                    ;一部の机下行為は露見しない
                    IF 机使用中 && GROUPMATCH(UFUFU_COM_LIST:(LOCAL:0), 10, 11, 26, 106, 107, 90, 19, 132, 120, 100)
                        ウフフ隠蔽 = 1
                        CONTINUE
                    ENDIF
                    IF 卓使用中 && GROUPMATCH(UFUFU_COM_LIST:(LOCAL:0), 14)
                        ウフフ隠蔽 = 1
                        CONTINUE
                    ENDIF
                    IF IS_EQUIP(CHARA_ID, UFUFU_COM_LIST:(LOCAL:0))
                        ウフフ隠蔽 = 0
                        LOCAL:2 ++
                    ENDIF
                NEXT
                ;MASTERが情事に該当する行為のMPLYかMTARで、CHARA_IDが行為に関わっていない第三者であれば目撃者扱い
                IF !ウフフ隠蔽 &&LOCAL:1 > 0 && LOCAL:2 == 0
                    TCVAR:CHARA_ID:ウフフ目撃フラグ = 1
                    TCVAR:CHARA_ID:ウフフ目撃場所 = キャラ現在地
                    RETURN 1
                ENDIF
                VARSET LOCAL
                ;;継続コマンドのドキドキ判定
                FOR LOCAL:0, 0, VARSIZE("DOKIDOKI_COM_LIST")
                    SIF IS_EQUIP(MASTER, DOKIDOKI_COM_LIST:(LOCAL:0))
                        LOCAL:1 ++
                NEXT
                ;MASTERがドキドキに該当する行為のMPLYでもMTARでもなければRETURN
                FOR LOCAL:0, 0, VARSIZE("DOKIDOKI_COM_LIST")
                    SIF IS_EQUIP(CHARA_ID, DOKIDOKI_COM_LIST:(LOCAL:0))
                        LOCAL:2 ++
                NEXT
                ;MASTERがドキドキに該当する行為のMPLYかMTARで、CHARA_IDが行為に関わっていない第三者であれば目撃者扱い
                IF LOCAL:1 > 0 && LOCAL:2 == 0
                    RETURN 2
                ENDIF
            ENDIF
        ENDIF
    ELSE
        ;同行中の行為は許容する
        RETURN 3
    ENDIF
ENDIF
RETURN 0

;-------------------------------------------------
;居住区モードの調教終了処理
;-------------------------------------------------
@HOUSING_EVENTEND
;体力気力を0～最大値の範囲に収める
CALL LIFE_LIMIT

TRAIN_PLACE =

FLAG:夜這い = 0
TFLAG:奉仕モード = 0
TFLAG:売春フラグ = 0

IF FLAG:調教モード == 調教_慰安
    SELECTCASE FLAG:慰安モード
        CASE 1
            CALL EVENTEND_IAN
        CASE 2
            CALL EVENTEND_ATEGAU
    ENDSELECT
    FLAG:慰安モード = 0
ENDIF

SIF FLAG:調教モード == 調教_逆調教特殊 && IS_SP_COUNTRY(CFLAG:MASTER:捕虜先)
    CALL EVENTEND_SP_COUNTRY()

CUSTOMDRAWLINE ─
CALL TITLE_CATEGORY_GENERAL("今回の調教")
PRINTL
CALL COLOR_LINE
FOR LOCAL:0, 0, CHARANUM
    SIF !IS_PARTICIPATE_TRAIN(LOCAL)
        CONTINUE
    PRINTFORML ■%ANAME(LOCAL)%:
    CALL NEW_PRINT_ORGASM(LOCAL)
    CALL COLOR_LINE
NEXT
WAIT

;慰安用のモブはここで削除する。ゲストは残す
;->交流中にキャラを消すと連想配列中のCHARA_IDが齟齬を起こすのでコメントアウト
; LOCAL:2 = CHARANUM
; FOR LOCAL:0, 0, LOCAL:2
;     LOCAL:1 = LOCAL:2 - LOCAL:0 - 1
;     IF CFLAG:(LOCAL:1):慰安モブ && !(CFLAG:(LOCAL:1):ゲストモブ)
;         CALL DELETE_CHARA(LOCAL:1)
;     ENDIF
; NEXT

;体力気力の成長
FOR LOCAL, 0, CHARANUM
    SIF !IS_PARTICIPATE_TRAIN(LOCAL) || IS_SP_CHARA(LOCAL)
        CONTINUE

    LOCAL:1 = MIN(SUM_EX(LOCAL) / 5, 20)
    LOCAL:1 += RAND:MAX(TCVAR:LOCAL:体力上昇最大値, 1)
    SELECTCASE MAXBASE:LOCAL:体力
        CASE IS > 5000
            LOCAL:1 /= 10
        CASE IS > 3000
            LOCAL:1 /= 4
    ENDSELECT

    SIF LOCAL:1 <= 0
        GOTO STR_GROW_END

    PRINTFORML %ANAME(LOCAL)%の体力 + {LOCAL:1}
    MAXBASE:LOCAL:体力 += LOCAL:1

    $STR_GROW_END

    LOCAL:1 = MIN(SUM_EX(LOCAL) / 5, 10)
    LOCAL:1 += RAND:MAX(TCVAR:LOCAL:気絶回数, 1)

    SELECTCASE MAXBASE:LOCAL:気力
        CASE IS > 5000
            LOCAL:1 /= 10
        CASE IS > 3000
            LOCAL:1 /= 4
    ENDSELECT

    SIF LOCAL:1 <= 0
        GOTO WILL_GROW_END

    MAXBASE:LOCAL:気力 += LOCAL:1
    PRINTFORML %ANAME(LOCAL)%の気力 + {LOCAL:1}

    $WILL_GROW_END
NEXT

;初対面のキャラの対面済みフラグをＯＮ
FOR LOCAL:0, 0, CHARANUM
    SIF LOCAL != MASTER && IS_PARTICIPATE_TRAIN(LOCAL) && !CFLAG:(LOCAL:0):面識
        CFLAG:(LOCAL:0):面識 = 1
NEXT

;調教参加者同士の印象値が改善される
FOR LOCAL:0, 0, CHARANUM
    SIF !IS_PARTICIPATE_TRAIN(LOCAL)
        CONTINUE
    FOR LOCAL:1, 0, CHARANUM
        SIF LOCAL:1 == LOCAL || !IS_PARTICIPATE_TRAIN(LOCAL:1)
            CONTINUE
        CALL TRAIN_CHANGE_RELATION(LOCAL:0, LOCAL:1)
    NEXT
NEXT

;現在の酔いを酔い合計値に加算
FOR LOCAL:0, 0, CHARANUM
    SIF IS_PARTICIPATE_TRAIN(LOCAL) && !IS_SP_CHARA(LOCAL)
        CFLAG:(LOCAL:0):酔い累積値 += PALAM:(LOCAL:0):酔い
NEXT

FOR LOCAL:0, 0, CHARANUM
    SIF CFLAG:LOCAL:強制友好化
        CFLAG:LOCAL:強制友好化 = 0
    SIF CFLAG:LOCAL:調教中BASE減らない
        CFLAG:LOCAL:調教中BASE減らない = 0
NEXT

;性知識アップ
FOR LOCAL:0, 0, CHARANUM
    IF IS_PARTICIPATE_TRAIN(LOCAL) && ABL:(LOCAL:0):性知識 < 4
        LOCAL:1 = MIN(SUM_EX(LOCAL:0) / MAX(ABL:(LOCAL:0):性知識 * 2, 1), 100)
        CALL PRINT_ADD_EXP(LOCAL:0, "性知識経験値", LOCAL:1, 1)
        CALL TRAIN_AUTO_ABLUP(LOCAL:0)
    ENDIF
NEXT

FOR LOCAL:0, 0, CHARANUM
    IF IS_PARTICIPATE_TRAIN(LOCAL) && !IS_SP_CHARA(LOCAL:0)
        ;素質変化に関する処理(恋慕の取得など)
        CALL TALENT_CHECK(LOCAL:0)
    ENDIF
NEXT

FOR LOCAL:0, 0, CHARANUM
    IF IS_PARTICIPATE_TRAIN(LOCAL)
        ;性的嗜好の変化
        ;あてがった場合はロックフラグを立てる
        CALL CHECK_SEXUAL_PREFERENCE(LOCAL:0)
    ENDIF
NEXT

IF CONFIG:42
    FOR LOCAL:0, 0, CHARANUM
        CALL 性癖一括変更(LOCAL,10000)
        CALL 性癖一括変更(LOCAL,12000)
        CALL 性癖一括変更(LOCAL,14000)
    NEXT
ENDIF
;追加アイテムの削除
FOR LOCAL:0, 500, 999
    ITEM:(LOCAL:0) = 0
NEXT

;助手記録を削除
FOR LOCAL:0, 0, CHARANUM
    SIF CFLAG:LOCAL:捕虜調教の助手
        CFLAG:LOCAL:捕虜調教の助手 = 0
    SIF CFLAG:LOCAL:夜這いの助手
        CFLAG:LOCAL:夜這いの助手 = 0
    SIF CFLAG:LOCAL:調教中帰らない
        CFLAG:LOCAL:調教中帰らない = 0
NEXT

FOR LOCAL, 0, CHARANUM
    SIF CFLAG:LOCAL:能力固定フラグ
        CFLAG:LOCAL:能力固定フラグ = 0
NEXT

;催眠フラグだけは折る(VIRGIN_COMMONなどにおけるTCVAR:催眠中での強制上書きが、他のところに影響しないよう)
FOR LOCAL:0, 0, CHARANUM
    TCVAR:LOCAL:催眠中 = 0
    TCVAR:LOCAL:催眠経過ターン数 = 0
NEXT

;閨逆調教フラグを折る
FLAG:閨逆調教 = 0

;次回の調教イベントに持ち越さない調教フラグを削除
CVARSET CFLAG, GETNUM(CFLAG, "主導除外") , 0
CVARSET CFLAG, GETNUM(CFLAG, "凌辱被害者フラグ") , 0
CVARSET CFLAG, GETNUM(CFLAG, "慰安参加者非対象化") , 0
CVARSET TCVAR, GETNUM(TCVAR, "奉仕者フラグ") , 0
CVARSET TCVAR, GETNUM(TCVAR, "被奉仕者フラグ") , 0

;プレイヤーとターゲットをクリア
CALL CLEAR_MPLY
CALL CLEAR_MTAR

;捕虜調教のターゲットをクリア
VARSET PRISONER_TARGET, -1

FLAG:調教モード = 調教_居住区
FLAG:ウフフフラグ = 0

RETURN

;-------------------------------------------------
;ハウジングモードで押し倒し実行時の判定
;調教タイプ 押し倒す = 0, 奉仕を要求 = 1, 過激な奉仕を要求= 2, 誘い受ける = 3
;-------------------------------------------------
@HO_JUDGE_PUSHDOWN(MTAR_ID, 調教タイプ = 0)
#DIM MTAR_ID
#DIM 調教タイプ
#DIM CONST 調教タイプ_奉仕 = 1
#DIM CONST 調教タイプ_過激な奉仕 = 2
#DIM CONST 調教タイプ_誘い受け = 3

;実行判定
;寝ているなら強制成功
IF TCVAR:MTAR_ID:睡眠深度 > 0 && TCVAR:(MTAR_ID):53
    CALL KOJO_EVENT(MTAR_ID, 8)
    RETURN 2
ENDIF

;●実行値の計算
CVARSET TCVAR, 24, -10000
CVARSET TCVAR, 25, 10000

;実行値の設定
SELECTCASE 調教タイプ
    CASE 調教タイプ_奉仕
        TCVAR:(MTAR_ID):25 = 150
    CASE 調教タイプ_過激な奉仕,
        TCVAR:(MTAR_ID):25 = 250
    CASE 調教タイプ_誘い受け
        TCVAR:(MTAR_ID):25 = 220
    CASEELSE
        TCVAR:(MTAR_ID):25 = 100
ENDSELECT

CALL COM_ORDER(MTAR_ID)

CALL COM_ORDER_ELEMENT(MTAR_ID, "欲情", GET_PALAMLV(PALAM:(MTAR_ID):欲情))
IF HAS_VAGINA(MTAR_ID)
    CALL COM_ORDER_ELEMENT(MTAR_ID, "潤滑", GET_PALAMLV(PALAM:(MTAR_ID):潤滑))
ENDIF
CALL COM_ORDER_ELEMENT(MTAR_ID, "欲望", ABL:(MTAR_ID):欲望 * 4)
CALL COM_ORDER_ELEMENT(MTAR_ID, "奉仕", ABL:(MTAR_ID):奉仕 * 2)

IF TALENT:(MTAR_ID):貞操観念
    CALL COM_ORDER_ELEMENT(MTAR_ID, "貞操観念", -10)
ENDIF

IF TALENT:(MTAR_ID):貞操無頓着
    CALL COM_ORDER_ELEMENT(MTAR_ID, "貞操無頓着", 10)
ENDIF

IF TALENT:(MTAR_ID):恥じらい
    CALL COM_ORDER_ELEMENT(MTAR_ID, "恥じらい", -6)
ENDIF

IF TALENT:(MTAR_ID):恥薄い
    CALL COM_ORDER_ELEMENT(MTAR_ID, "恥薄い", 3)
ENDIF

IF TALENT:(MTAR_ID):快感に素直
    CALL COM_ORDER_ELEMENT(MTAR_ID, "快感に素直", 5)
ENDIF

IF TALENT:(MTAR_ID):快感の否定
    CALL COM_ORDER_ELEMENT(MTAR_ID, "快感の否定", -5)
ENDIF

IF TALENT:(MTAR_ID):一線越えない
    CALL COM_ORDER_ELEMENT(MTAR_ID, "一線越えない", -15)
ENDIF

IF TALENT:(MTAR_ID):恋慕
    CALL COM_ORDER_ELEMENT(MTAR_ID, "恋慕", 12)
ENDIF

IF TALENT:(MTAR_ID):親友
    CALL COM_ORDER_ELEMENT(MTAR_ID, "親友", 6)
ENDIF

IF TALENT:(MTAR_ID):親愛
    CALL COM_ORDER_ELEMENT(MTAR_ID, "親愛", 20)
ENDIF

IF TALENT:(MTAR_ID):恋人
    CALL COM_ORDER_ELEMENT(MTAR_ID, "恋人", 6)
ENDIF

IF TALENT:(MTAR_ID):キス未経験
    CALL COM_ORDER_ELEMENT(MTAR_ID, "キス未経験", -5)
ENDIF

IF CFLAG:(MTAR_ID):スケベモブ && 調教タイプ_誘い受け
    CALL COM_ORDER_ELEMENT(MTAR_ID, "スケベモブを誘惑", 20)
ENDIF

; ;ムードボーナス
; IF TFLAG:ムード < 60
; 	CALL COM_ORDER_ELEMENT(MTAR_ID, "ムード", 0)
; ELSE
; 	CALL COM_ORDER_ELEMENT(MTAR_ID, "ムード", 5 + TFLAG:ムード / 30)
; ENDIF

;衣服の露出度
CALL HO_CHECK_NAKED(MTAR_ID)
IF RESULT
    CALL COM_ORDER_ELEMENT(MTAR_ID, "衣服露出度", RESULT * 5)
ENDIF
;好感度
IF CFLAG:(MTAR_ID):2 < 700
    IF CFLAG:(MTAR_ID):2 < 300
        LOCAL:0 = -20
    ELSEIF CFLAG:(MTAR_ID):2 < 500
        LOCAL:0 = -10
    ELSE
        LOCAL:0 = -5
    ENDIF
    CALL COM_ORDER_ELEMENT(MTAR_ID, "好感度不足", LOCAL:0)
ENDIF

;第三者　○○に恋慕に関する処理
;CALL JUDGE_PUSHDOWN_SUB

;性知識
IF ABL:(MTAR_ID):性知識 == 0
    CALL COM_ORDER_ELEMENT(MTAR_ID, "性知識なし", 80)
ENDIF

;合意
IF TALENT:(MTAR_ID):合意
    CALL COM_ORDER_ELEMENT(MTAR_ID, "合意", 10)
ENDIF

;判定結果を表示
PRINTFORMW  = {TCVAR:(MTAR_ID):24} %TOSTR_COMPARE(TCVAR:(MTAR_ID):24, TCVAR:(MTAR_ID):25)% 実行値{TCVAR:(MTAR_ID):25}

IF 調教タイプ == 調教タイプ_誘い受け
    CALL ADD_SITU("誘い受け")
ENDIF
IF TCVAR:(MTAR_ID):24 >= TCVAR:(MTAR_ID):25
    ;既に[合意]済み
    IF TALENT:(MTAR_ID):合意
        CALL KOJO_EVENT(MTAR_ID, 7)

        ;酔いによる補正を除いても成功
    ELSEIF TCVAR:(MTAR_ID):24 - PALAM:(MTAR_ID):酔い / 150 >= 100
        TFLAG:酔った勢いで成功 = 0
        CALL KOJO_EVENT(MTAR_ID, 5)
        IF TCVAR:(MTAR_ID):催眠中 <= 0
            PRINTFORMW %ANAME(MTAR_ID)%の<合意>を得た
            TALENT:(MTAR_ID):合意 = 1
        ENDIF

        ;酔った勢いで成功
    ELSE
        TFLAG:酔った勢いで成功 = 1
        CALL KOJO_EVENT(MTAR_ID, 4)
    ENDIF
    RETURN 1

    ;失敗
ELSE
    IF 調教タイプ != 調教タイプ_誘い受け
        CALL KOJO_EVENT(MTAR_ID, 6)
        IF !TALENT:(MTAR_ID):合意 && !TALENT:(MTAR_ID):恋慕 && !TALENT:(MTAR_ID):親友
            PRINTFORMW %CALLNAME:MASTER%の行為に%ANAME(MTAR_ID)%は激しく抵抗している……
            PRINTFORMW %ANAME(MTAR_ID)%の好感度が300下がりました
            CFLAG:(MTAR_ID):2 -= 300
        ELSEIF TALENT:(MTAR_ID):恋慕 || TALENT:(MTAR_ID):親友
            PRINTFORMW %ANAME(MTAR_ID)%は今はそんな気分ではないと%CALLNAME:MASTER%の手をやんわりと払い除けた……
        ELSE
            PRINTFORMW %ANAME(MTAR_ID)%は%CALLNAME:MASTER%の手を払い除けて拒否した……
            PRINTFORMW %ANAME(MTAR_ID)%の好感度が100下がりました
            CFLAG:(MTAR_ID):2 -= 100
        ENDIF
        IF CFLAG:MTAR_ID:捕虜先
            PRINTL
            PRINTFORMW %ANAME(MPLY:0)%は抵抗する%ANAME(MTAR_ID)%を強引に組み伏せた……
            RETURN 2
        ENDIF
        RETURN 0
    ELSEIF 調教タイプ == 調教タイプ_誘い受け
        CALL KOJO_EVENT(MPLY, 6)
        RETURN 0
    ENDIF
ENDIF

;-------------------------------------------------
; 自慰判定
;-------------------------------------------------
@HO_SELF_CHECK(CHARA_ID)
#DIM CHARA_ID

;特殊状態が立っていれば戻る
SIF CFLAG:(CHARA_ID):行動不能状態
    RETURN 0

;虚ろ・崩壊なら戻る
SIF TALENT:(CHARA_ID):虚ろ || TALENT:(CHARA_ID):崩壊
    RETURN 0

;自慰または触手オナニーの知識が必要
LOCAL:0 = 0
CALL CHECK_COM_KNOWLEDGE(CHARA_ID, 100)
LOCAL:0 += RESULT
CALL CHECK_COM_KNOWLEDGE(CHARA_ID, 211)
LOCAL:0 += RESULT
SIF !LOCAL:0
    RETURN 0

;おねだりフラグが立っていれば100%(条件判定をスルー)
IF !TCVAR:(CHARA_ID):27
    ;最低でも欲情が一定値以上必要
    SIF PALAM:(CHARA_ID):欲情 < PALAMLV:6
        RETURN 0

    ;機嫌がある程度良いとき限定
    LOCALS:0 = %TOSTR_EMOTION(CHARA_ID)%
    SIF !GROUPMATCH(LOCALS:0, "幸", "悦", "良", "平")
        RETURN 0

    ;体力・気力がゼロ、もしくは少ないなら行わない
    SIF BASE:(CHARA_ID):体力 <= 500 || BASE:(CHARA_ID):気力 <= 500
        RETURN 0
ENDIF

;●詳細な自慰判定
CALL CALC_SELF_PARAMETER(CHARA_ID)
SIF !RESULT
    RETURN 0

RETURN 1

;-------------------------------------------------
; 母乳量算出
;-------------------------------------------------
@HO_CALC_LACTATION_AMOUNT(CHARA_ID, BASE_AMOUNT)
#DIM BASE_AMOUNT
#DIM CHARA_ID
#DIM DYNAMIC AMOUNT

AMOUNT = (BASE_AMOUNT * (GET_PALAMLV(PALAM:CHARA_ID:噴乳) * 10 + 100)) / 100
CALL LEWDSKILL_MILK_INFLATION(CHARA_ID, AMOUNT)
AMOUNT += RESULT
RETURN AMOUNT


code:
;-------------------------------------------------
;ハウジングモードでの調教描写に使用する関数(文字列の描写中心)
;-------------------------------------------------

;-------------------------------------------------
;キャラの行動を描写する文字列を参加人数分生成
;-------------------------------------------------
@HO_CHARAACT_DESC()
#DIM DYNAMIC CHARA_IDX

SIF !FLAG:ハウジングモード
    RETURN 0

WHILE _DIC_HO_CHARALIST:CHARA_IDX != "-1"
    IF _DIC_HO_CHARALIST:CHARA_IDX == "DELETED"
        CHARA_IDX ++
        CONTINUE
    ENDIF
    CALL HO_CHARAACT_DESC_SETSTR(CHARA_IDX)
    CHARA_IDX ++
WEND

;CHARA_IDXかCHARA_IDからキャラクターの行動描写文字列をセット
;IDXまたはIDを指定
@HO_CHARAACT_DESC_SETSTR(CHARA_IDX = -1, CHARA_ID = -1)
#DIM  CHARA_IDX
#DIM  CHARA_ID

#DIMS DYNAMIC ACTIONTYPE
#DIM  DYNAMIC ROOM_IDX
#DIMS DYNAMIC ROOM_NAME
#DIM  DYNAMIC MODULE_ID
#DIMS DYNAMIC MODULE_NAME
#DIMS DYNAMIC MAP
#DIMS DYNAMIC ACTION_TEXT

#DIM  DYNAMIC CHARA_GROUP_LIST_IDX
#DIMS DYNAMIC _LIST_CHARA_ID
#DIM  DYNAMIC GROUP_MEMBER_NUM
#DIM  DYNAMIC GROUP_MEMBER_ID

#DIM  DYNAMIC TARGET_ID

;各種キャラデータ取得
IF CHARA_IDX == -1
    CALL HO_GET_CHARAIDX(CHARA_ID)
    CHARA_IDX = RESULT
ELSE
    CALL HO_GET_CHARADATA(CHARA_IDX, "CHARA_ID")
    CHARA_ID = RESULT
ENDIF
SIF CHARA_IDX == -1
    RETURN
CALL C_COND_SET_INFO_TO_MAP(CHARA_ID,"CHARAACT_DESC")
ACTIONTYPE  '= @"%C_COND_MAP_GETS(CHARA_ID,"行動")%"
ROOM_IDX     = C_COND_MAP_GET(CHARA_ID,"エリアIDX")
ROOM_NAME   '= @"%C_COND_MAP_GETS(CHARA_ID,"エリア名")%"
MODULE_ID    = C_COND_MAP_GET(CHARA_ID,"設備")
MODULE_NAME '= @"%C_COND_MAP_GETS(CHARA_ID,"設備名")%"
IF MODULE_ID == 1000
    MODULE_NAME '= "部屋"
ENDIF
MAP '= @"MAP_{ROOM_IDX}_ROOM_EFFECT"

;キャラクターが所属しているグループを取得
CALL HO_GET_CHARADATA(CHARA_IDX, "CHARA_GROUP")
CHARA_GROUP_LIST_IDX = RESULT
IF CHARA_GROUP_LIST_IDX != -1
    CALL HO_GET_CHARA_GROUP_LIST(CHARA_GROUP_LIST_IDX, "CHARA_LIST")
    _LIST_CHARA_ID = %RESULTS%
    GROUP_MEMBER_NUM = LIST_COUNT(_LIST_CHARA_ID)
    ;メッセージ描写用に自分以外のグループメンバーのCHARA_IDを1名分抽出
    FOR LOCAL:1, 0, GROUP_MEMBER_NUM
        TARGET_ID = TOINT(LIST_GET(_LIST_CHARA_ID, LOCAL:1))
        SIF TARGET_ID == CHARA_ID
            CONTINUE
        GROUP_MEMBER_ID = TARGET_ID
    NEXT
ENDIF

;共通文字列
ACTION_TEXT '= @"%MODULE_NAME%で"
IF GROUP_MEMBER_NUM > 1
    ACTION_TEXT += @"%ANAME(GROUP_MEMBER_ID, GROUP_MEMBER_NUM - 1)%"
ENDIF

SELECTCASE ACTIONTYPE
    CASE "待機","移動完了"
        ACTION_TEXT '= @"%SPLIT_RAND("あたりをぶらぶらして/あたりをうろうろして/所在なさげにして",1)%いる"
    CASE "移動中"
        ACTION_TEXT '= "どこかに向かって移動している"
    CASE "食事中"
        IF GROUP_MEMBER_NUM <= 1
            ACTION_TEXT '= @"%MODULE_NAME%で食事をしている"
        ELSE
            ACTION_TEXT '= @"%MODULE_NAME%で%ANAME(GROUP_MEMBER_ID, GROUP_MEMBER_NUM - 1)%と%SPLIT_RAND("お喋りしながら/話しながら/一緒に",1)%食事をしている"
        ENDIF
    CASE "炊事中"
        IF GROUP_MEMBER_NUM <= 1
            ACTION_TEXT '= @"%MODULE_NAME%で食事の支度をしている"
        ELSE
            ACTION_TEXT '= @"%MODULE_NAME%で%ANAME(GROUP_MEMBER_ID, GROUP_MEMBER_NUM - 1)%%SPLIT_RAND("を手伝いながら/と分担して/と一緒に",1)%食事の支度をしている"
        ENDIF
    CASE "配膳中"
        ACTION_TEXT '= @"%ROOM_NAME%で食事を運んでいる"
    CASE "休憩中"
        IF C_COND("設備用途:お茶",,CHARA_ID)
            LOCALS '= "お茶を飲んでいる"
        ELSE
            LOCALS '= "休憩している"
        ENDIF
        IF MODULE_NAME != ""
            IF GROUP_MEMBER_NUM <= 1
                ACTION_TEXT '= @"%MODULE_NAME%で%LOCALS%"
            ELSE
                ACTION_TEXT '= @"%MODULE_NAME%で%ANAME(GROUP_MEMBER_ID, GROUP_MEMBER_NUM - 1)%と%SPLIT_RAND("お喋りしながら/話しながら/一緒に",1)%%SPLIT_RAND(@"%LOCALS%/くつろいでいる/休んでいる",1)%"
            ENDIF
        ELSE
            ACTION_TEXT '= @"%LOCALS%"
        ENDIF
    CASE "睡眠中"
        ACTION_TEXT '= @"%MODULE_NAME%ですうすうと寝息をたてて眠っている"
    CASE "同行中"
        IF FLAG:ウフフフラグ != 1
            ACTION_TEXT '= @"%ANAME(MASTER)%と一緒にいる"
        ELSE
            ACTION_TEXT '= @"@C:{カラー_ピンク}@❤%ANAME(MASTER)%と身体を重ねている❤@/C@"
        ENDIF
    CASE "バーテンダー"
        ACTION_TEXT '= @"%MODULE_NAME%でグラスを磨いている"
    CASE "採集中"
        ACTION_TEXT '= @"%MODULE_NAME%で採集をしている"
    CASE "採掘中"
        ACTION_TEXT '= @"%MODULE_NAME%で採掘をしている"
    CASE "飲酒中"
        ACTION_TEXT '= @"%MODULE_NAME%でお酒を飲んでいる"
    CASE "入浴中"
        ACTION_TEXT '= @"%MODULE_NAME%で身体を洗っている"
    CASE "水浴び中"
        ACTION_TEXT '= @"%MODULE_NAME%で%S_R("水を浴びている/身体を洗っている")%"
    CASE "釣り中"
        ACTION_TEXT '= @"%MODULE_NAME%の側に座り込みぼんやりと釣り糸を垂れている"
    CASE "読書中"
        IF GROUP_MEMBER_NUM <= 1
            ACTION_TEXT += "本を読んでいる"
        ELSE
            ACTION_TEXT += @"%SPLIT_RAND("と本について話している/と本の内容について議論している/と一緒に本を読んでいる",1)%"
        ENDIF
    CASE "運動中"
        ACTION_TEXT '= @"%MODULE_NAME%で運動をしている"
    CASE "演奏中"
        ACTION_TEXT '= @"%MODULE_NAME%で演奏をしている"
    CASE "演舞中"
        ACTION_TEXT '= @"%MODULE_NAME%で踊りを披露している"
    CASE "クラフト中"
        ACTION_TEXT '= @"%MODULE_NAME%で何かを作っている"
    CASE "訓練中"
        ACTION_TEXT '= @"%MODULE_NAME%で訓練をしている"
    CASE "遊戯中"
        IF STRFINDU(MODULE_NAME, "テーブル") != -1
            IF GROUP_MEMBER_NUM <= 1
                ACTION_TEXT += "カードゲームをしている"
            ELSE
                ACTION_TEXT += @"%SPLIT_RAND("とカードゲームをしている/と一緒にカードで遊んでいる",1)%"
            ENDIF
        ELSE
            IF GROUP_MEMBER_NUM <= 1
                ACTION_TEXT += "遊んでいる"
            ELSE
                ACTION_TEXT += @"%SPLIT_RAND("と遊んでいる/と楽しそうに遊んでいる",1)%"
            ENDIF
        ENDIF
    CASE "店番中"
        IF GROUP_MEMBER_NUM <= 1
            ACTION_TEXT '= @"%MODULE_NAME%で"
        ELSE
            ACTION_TEXT '= @"%MODULE_NAME%で%ANAME(GROUP_MEMBER_ID, GROUP_MEMBER_NUM - 1)%%SPLIT_RAND("とお喋りしながら/を手伝って/と一緒に",1)%"
        ENDIF
        IF HO_TIME <= HO_CLOCK(1800)
            ACTION_TEXT += "店番をしている"
        ELSE
            ACTION_TEXT += "店じまいをしている"
        ENDIF
    CASE "宿番中"
        IF GROUP_MEMBER_NUM <= 1
            ACTION_TEXT '= @"%MODULE_NAME%で"
        ELSE
            ACTION_TEXT '= @"%MODULE_NAME%で%ANAME(GROUP_MEMBER_ID, GROUP_MEMBER_NUM - 1)%%SPLIT_RAND("とお喋りしながら/を手伝って/と一緒に",1)%"
        ENDIF
        ACTION_TEXT += "宿の番をしている"
    CASE "鑑賞中"
        IF MAP_HAS(MAP, "ピアノの音色")
            ACTION_TEXT '= @"%MODULE_NAME%で"
            ACTION_TEXT += "演奏に聴き入っている"
        ELSEIF MAP_HAS(MAP, "演舞")
            ACTION_TEXT '= @"%MODULE_NAME%で"
            ACTION_TEXT += "踊りに見入っている"
        ELSEIF MAP_HAS(MAP, "歌唱")
            ACTION_TEXT '= @"%MODULE_NAME%で"
            ACTION_TEXT += "歌声に聴き入っている"
        ELSE
            ACTION_TEXT '= @"%MODULE_NAME%で"
            ACTION_TEXT += "余韻に浸っている"
        ENDIF
    CASE "拘束中"
        ACTION_TEXT '= @"拘束され身動きできずにいる"
    CASE "買物中"
        ACTION_TEXT '= @"%MODULE_NAME%で商品を見繕っている"
    CASE "監禁中"
        ACTION_TEXT '= @"牢の中でうなだれている"
    CASE "売春中"
        ACTION_TEXT '= @"%ROOM_NAME%で春をひさいでいる"
    CASE "買春中"
        ACTION_TEXT '= @"%ROOM_NAME%で娼婦を見繕っている"
    CASE "自慰中", "逢瀬中"
        CALL HO_IS_TARGET_VISIBLE(MASTER, CHARA_ID)
        IF RESULT
            ACTION_TEXT '= @"@C:{カラー_ピンク}@❤%MODULE_NAME%で秘事に耽っている❤@/C@"
        ELSE
            ACTION_TEXT '= @"@C:{カラー_選択不可}@ここからではよくわからない……@/C@"
        ENDIF
    CASE "逢瀬待機中"
        ACTION_TEXT '= @"%MODULE_NAME%で誰かを待っている"
    CASEELSE
        ACTION_TEXT '= ""
ENDSELECT

HO_DESC_CHARAACT:CHARA_ID:0 = %ACTION_TEXT%

;空腹度に関する描写
@HO_GET_空腹度描写(CHARA_ID)
#DIM CHARA_ID
IF CHARA_ID == MASTER
    IF TCVAR:CHARA_ID:空腹度 < 150
        LOCALS:0 = は満腹だ
    ELSEIF TCVAR:CHARA_ID:空腹度 < 300
        LOCALS:0 = は小腹が空いている
    ELSE
        LOCALS:0 = は空腹だ
    ENDIF
ELSE
    IF TCVAR:CHARA_ID:空腹度 < 150
        LOCALS:0 = は満腹のようだ
    ELSEIF TCVAR:CHARA_ID:空腹度 < 300
        LOCALS:0 = は小腹が空いているようだ
    ELSE
        LOCALS:0 = は空腹のようだ
    ENDIF
ENDIF
RESULTS = %ANAME(CHARA_ID)%%LOCALS%

@HO_GET_精液描写(CHARA_ID, 射精部位)
#DIM CHARA_ID
#DIM 射精部位

VARSET RESULTS
SELECTCASE 射精部位
    CASE 射精部位_膣内
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_膣内 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_膣内 < 10
            RESULTS = 陰部が白濁液で湿っている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_膣内 < 25
            RESULTS = 雌穴は精液で満たされている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_膣内 < 35
            RESULTS = 雌穴から溢れた精液が大腿を伝って垂れている
        ELSE
            RESULTS = 溢れた精液が雌穴から糸を引いて滴っている
        ENDIF
    CASE 射精部位_アナル
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_アナル == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_アナル < 10
            RESULTS = 肛孔から雄汁が垂れている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_アナル < 25
            RESULTS = 肛孔は雄汁で満たされている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_アナル < 35
            RESULTS = 肛孔から溢れた精液が大腿を伝って垂れている
        ELSE
            RESULTS = 肛孔から止めどなく白濁が溢れている
        ENDIF
    CASE 射精部位_口
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_口 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_口 < 10
            RESULTS = 口元に僅かな量の精液がこびりついている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_口 < 25
            RESULTS = 口内は雄臭を放つ白濁で満たされている
        ELSE
            RESULTS = 口内に大量の白濁汁が注がれている
        ENDIF
    CASE 射精部位_顔
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_顔 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_顔 < 10
            RESULTS = 頬に僅かな量の精液がこびりついている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_顔 < 25
            RESULTS = 顔面に淫らな白濁がべったりとこびりついている
        ELSE
            RESULTS = 白濁がすっかり顔を覆ってしまっている
        ENDIF
    CASE 射精部位_胸
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_胸 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_胸 < 10
            RESULTS = 胸元に僅かな量の淫汁がこびりついている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_胸 < 25
            RESULTS = 胸元に雄臭を放つ白濁がこびりついている
        ELSE
            RESULTS = 胸元は大量の雄汁でぐちゃぐちゃに汚されている
        ENDIF
    CASE 射精部位_髪
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_髪 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_髪 < 10
            RESULTS = 髪に僅かな量の白濁が付着している
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_髪 < 25
            RESULTS = 髪から雄臭を放つ白濁が滴っている
        ELSE
            RESULTS = 髪は大量の雄汁でぐちゃぐちゃに汚されている
        ENDIF
    CASE 射精部位_足
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_足 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_足 < 10
            RESULTS = 足元が僅かな量の精液で濡れている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_足 < 25
            RESULTS = 大腿から雄臭を放つ白濁が滴っている
        ELSE
            RESULTS = 大腿から足先まで白濁でまみれている
        ENDIF
    CASE 射精部位_尻
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_尻 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_尻 < 10
            RESULTS = 尻が少量の精液で濡れている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_尻 < 25
            RESULTS = 尻の曲線に沿って雄臭を放つ白濁が滴っている
        ELSE
            RESULTS = 尻は大量の白濁液でドロドロに濡れている
        ENDIF
    CASE 射精部位_手
        IF CUM_GET_AMOUNT:CHARA_ID:射精部位_手 == 0
            RETURN
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_手 < 10
            RESULTS = 僅かな量の精液が指の間で糸を引いている
        ELSEIF CUM_GET_AMOUNT:CHARA_ID:射精部位_手 < 25
            RESULTS = 手は雄臭を放つ白濁でまみれていれる
        ELSE
            RESULTS = 手は大量の白濁でまみれていれる
        ENDIF
ENDSELECT


code:
;-------------------------------------------------
; クエストで汎用可能なコモンイベント集
; チェスト系イベント
;-------------------------------------------------
;-------------------------------------------------
; チェストが未生成の場合に引数に応じたランダムなチェストを生成する(0~9)
; 引数の値に応じて重み付け抽選
;-------------------------------------------------
@QST_CEV_CREATE_RANDOM_CHEST(ARG:0 = 100, ARG:1 = 0,  ARG:2 = 0, ARG:3 = 0, ARG:4 = 0, ARG:5 = 0, ARG:6 = 0, ARG:7 = 0, ARG:8 = 0, ARG:9 = 0)
#DIM DYNAMIC CHEST_TYPE
CALL QST_GET_EVENT_LIST(QST_NOWEV_LIST_IDX, "CHEST_TYPE")
IF RESULT == -1
    CALL RAND_WT_INIT
    FOR LOCAL, 0, 10
        SIF ARG:LOCAL == 0
            CONTINUE
        CALL RAND_WT_SET(LOCAL, ARG:LOCAL)
    NEXT
    CHEST_TYPE = RAND_WT_RESULT()
    CALL QST_SET_EVENT_LIST(QST_NOWEV_LIST_IDX, "CHEST_TYPE", TOSTR(CHEST_TYPE))
    RETURN CHEST_TYPE
ELSE
    RETURN RESULT
ENDIF
;-------------------------------------------------
; 通常のチェストのコモンイベント
;-------------------------------------------------
@QST_CEV_CHEST(_LIST_REWARD)
#DIMS _LIST_REWARD
#DIMS EVENT_NAME

CALL PRINT_TITLE(EVENT_NAME)
CALL QST_GET_EVENT_LIST(QST_NOWEV_LIST_IDX, "EVENT_SLOT_NAME")
EVENT_NAME = %RESULTS%

PRINTFORML %QST_LEADER_NAME()%は%EVENT_NAME%の前に立った。特段施錠はされておらず、罠もないようだ
PRINTFORMW %ANAME(QST_RANDCHARA())%は中身を開放した……
IF _LIST_REWARD != ""
    CALL QST_CHANGE_ITEM(_LIST_REWARD)
ENDIF
CALL QST_DEACTIVATE_THIS_EVENT()
RETURN 1

;-------------------------------------------------
; 鍵付きチェストのコモンイベント
;-------------------------------------------------
@QST_CEV_LOCKED_CHEST(_LIST_REWARD, DIFFICULTY_RATE = 100, TRAP_RATE = 0, TRAP_PATTERN = "")
#DIMS _LIST_REWARD
#DIM  DIFFICULTY_RATE
#DIM  TRAP_RATE
#DIMS TRAP_PATTERN
#DIMS _LIST_MESSAGE
#DIMS _LIST_JUDGE_VALUE
#DIMS _LIST_DIFFICULTY
#DIMS EVENT_NAME
#DIM  DYNAMIC TARGET_ID
#DIMS DYNAMIC TRAP_TYPE
#DIM  DYNAMIC HAS_TRAP_FOUND
#DIMS DYNAMIC TRAP_NAME
#DIM  DYNAMIC EVENT_FLAG

CALL PRINT_TITLE(EVENT_NAME)
CALL QST_GET_EVENT_LIST(QST_NOWEV_LIST_IDX, "EVENT_SLOT_NAME")
EVENT_NAME = %RESULTS%

;解錠前の描写
CALL QST_GET_EVENT_LIST(QST_NOWEV_LIST_IDX, "TRAP")
HAS_TRAP_FOUND = RESULT
TRAP_NAME = %RESULTS%
IF HAS_TRAP_FOUND == -1
    PRINTFORML %QST_LEADER_NAME()%は%EVENT_NAME%の前に立った。どうやら鍵がかかっているようだ
    PRINTFORML 開けることができれば何か役に立つものが見つかるかもしれない
    PRINTL
    SELECTCASE TRAP_PATTERN
        CASE "LEWD"
            WAIT
            CALLF TAG_PRINT(@"@C:{カラー_ピンク}@%QST_LEADER_NAME()%は%EVENT_NAME%の表面で奇怪な淫紋が明滅するのを目にした@/C@", 1)
            WAIT
            PRINTL
        CASEELSE
    ENDSELECT
ELSE
    PRINTFORML %QST_LEADER_NAME()%は%EVENT_NAME%の前に立った
    IF TRAP_NAME != "なし"
        CALLF TAG_PRINT(@"これには@C:{カラー_注意}@%RESULTS%@/C@の罠が仕掛けられていることが判明している", 1)
    ELSE
        PRINTFORML これには特に罠は仕掛けられていないことが判明している
    ENDIF
    PRINTL
ENDIF

$INPUT_LOOP
PRINTL
PRINTFORML ……さて、どうすべきだろうか？
PRINTL

_LIST_MESSAGE '= "解錠を試みる(器用),力づくでこじ開ける(身体),"
_LIST_JUDGE_VALUE '= "器用,身体,"
_LIST_DIFFICULTY '= @"%TOSTR(DIFFICULTY_RATE)%,%TOSTR((DIFFICULTY_RATE * 150) / 100)%,"

;トラップ未判定の場合は観察判定を追加
IF HAS_TRAP_FOUND == -1 && TRAP_NAME != "なし"
    _LIST_MESSAGE = %LIST_ADD(_LIST_MESSAGE, "罠の有無を調べる(観察)")%
    _LIST_JUDGE_VALUE = %LIST_ADD(_LIST_JUDGE_VALUE, "観察")%
    _LIST_DIFFICULTY = %LIST_ADD(_LIST_DIFFICULTY, @"%TOSTR(DIFFICULTY_RATE)%")%
ENDIF

CALL QST_ROLL_MULTI(_LIST_JUDGE_VALUE, _LIST_MESSAGE, _LIST_DIFFICULTY,,,,, 1, "何も考えず開ける(確定失敗)")
TARGET_ID = RESULT:1
IF RESULT == 1
    IF RESULTS != "観察"
        PRINTFORMW %ANAME(TARGET_ID)%は%EVENT_NAME%の解錠に成功した！
        CALL QST_CHANGE_ITEM(_LIST_REWARD)
        CALL QST_DEACTIVATE_THIS_EVENT()
        RETURN 1
    ELSE
        ;観察判定は解錠はしない
        CALL QST_CEV_GET_TRAP_PATTERN_PRESET(TRAP_PATTERN)
        TRAP_TYPE = %RESULTS%
        CALL QST_SET_EVENT_LIST(QST_NOWEV_LIST_IDX, "TRAP", TRAP_TYPE)
        IF  TRAP_TYPE != "なし"
            PRINTFORML %ANAME(TARGET_ID)%は%EVENT_NAME%の罠を見抜いた
            PRINTL
            CALLF TAG_PRINT(@"どうやら@C:{カラー_注意}@%TRAP_TYPE%@/C@の罠が仕掛けられているようだ……", 1)
            WAIT
        ELSE
            PRINTFORML %ANAME(TARGET_ID)%は%EVENT_NAME%に何も罠が無い事を確認した
        ENDIF
        GOTO INPUT_LOOP
    ENDIF
ELSEIF !RESULT
    IF RESULTS != "観察"
        PRINTFORMW %ANAME(TARGET_ID)%は%EVENT_NAME%の解錠に失敗した……
        PRINTL
        ;罠が生成されていない場合は生成する。生成済みの場合は確定でその罠を発動する
        CALL QST_GET_EVENT_LIST(QST_NOWEV_LIST_IDX, "TRAP")
        IF RESULT != -1
            CALL QST_CEV_TRAP_EVENT(TARGET_ID, RESULTS)
        ELSE
            IF RAND:100 < TRAP_RATE
                CALL QST_CEV_GET_TRAP_PATTERN_PRESET(TRAP_PATTERN)
                TRAP_TYPE = %RESULTS%
                CALL QST_SET_EVENT_LIST(QST_NOWEV_LIST_IDX, "TRAP", TRAP_TYPE)
                CALL QST_CEV_TRAP_EVENT(RESULT:1, TRAP_TYPE)
            ENDIF
        ENDIF
        ;解錠手段が残っている場合は入力ループに戻る
        ;ウフフフラグが立っている場合は入力ループを離脱
        CALL QST_GET_EVENT_FLAG_BY_IDX()
        EVENT_FLAG = RESULT
        SIF !(GETBIT(EVENT_FLAG, 1) && GETBIT(EVENT_FLAG, 2)) && !FLAG:ウフフフラグ
            GOTO INPUT_LOOP
    ELSE
        PRINTFORMW %ANAME(TARGET_ID)%は%EVENT_NAME%を調べて見たものの、何もわからなかったようだ……
        GOTO INPUT_LOOP
    ENDIF
ENDIF
;-------------------------------------------------
; 宝箱のトラップパターン
;-------------------------------------------------
@QST_CEV_GET_TRAP_PATTERN_PRESET(TRAP_PATTERN)
#DIMS TRAP_PATTERN
#DIMS TRAP_TYPE
SELECTCASE TRAP_PATTERN
    CASE "", "COMMON"
        CALL RAND_WT_INIT()
        CALL RAND_WT_SET(0, 40)
        CALL RAND_WT_SET(1, 30)
        CALL RAND_WT_SET(2, 25)
        CALL RAND_WT_SET(3, 5)
        SELECTCASE RAND_WT_RESULT()
            CASE 0
                TRAP_TYPE '= "仕込針"
            CASE 1
                TRAP_TYPE '= "催淫ガス"
            CASE 2
                TRAP_TYPE '= "腐食液"
            CASE 3
                TRAP_TYPE '= "なし"
        ENDSELECT
    CASE "LEWD", "LEWD_LV2"
        CALL RAND_WT_INIT()
        CALL RAND_WT_SET(0, 10)
        CALL RAND_WT_SET(1, 10)
        CALL RAND_WT_SET(2, 10)
        CALL RAND_WT_SET(3, 10)
        IF TRAP_PATTERN == "LEWD_LV2"
            CALL RAND_WT_SET(4, 25)
            CALL RAND_WT_SET(5, 15)
        ENDIF
        SELECTCASE RAND_WT_RESULT()
            CASE 0
                TRAP_TYPE '= "催淫ガス"
            CASE 1
                TRAP_TYPE '= "腐食液"
            CASE 2
                TRAP_TYPE '= "ブラシ触手"
            CASE 3
                TRAP_TYPE '= "Ｃコイン"
            CASE 4
                TRAP_TYPE '= "触手"
            CASE 5
                TRAP_TYPE '= "フェイスハガー"
        ENDSELECT
ENDSELECT
RESULTS = %TRAP_TYPE%

;-------------------------------------------------
; 罠イベント
;-------------------------------------------------
@QST_CEV_TRAP_EVENT(TARGET_ID, TRAP_TYPE)
#DIM  TARGET_ID
#DIMS TRAP_TYPE
#DIM  DYNAMIC MOB_ID

SIF LIST_COUNT(TRAP_TYPE) > 0
    TRAP_TYPE = %LIST_RAND(TRAP_TYPE)%

SELECTCASE TRAP_TYPE
    CASE "仕込針"
        CALL PRINT_TITLE(@"仕込針の罠", "トラップ")
        CALLF TAG_PRINT(@"飛び出した針が%ANAME(TARGET_ID)%を襲う！", 1)
        CALL QST_CHANGE_HP(TARGET_ID, -200)
        WAIT
        RETURN 1
    CASE "催淫ガス"
        CALL PRINT_TITLE(@"催淫ガスの罠", "エロトラップ")
        CALLF TAG_PRINT(@"桃色の霧が%ANAME(TARGET_ID)%の正常な判断力を奪う……", 1)
        CALLF TAG_PRINT(@"@C:{カラー_ピンク}@%ANAME(TARGET_ID)%は発情してしまったようだ……@/C@", 1)
        TCVAR:(TARGET_ID):媚薬 += 1
        WAIT
        RETURN 1
    CASE "腐食液"
        CALL PRINT_TITLE(@"腐食液の罠", "エロトラップ")
        CALLF TAG_PRINT(@"噴出した腐臭を放つ液体が%ANAME(TARGET_ID)%を襲う！", 1)
        IF RAND:2
            CALL QST_ARMOR_BREAK(TARGET_ID, 被覆部位_乳首, 100)
        ELSE
            CALL QST_ARMOR_BREAK(TARGET_ID, 被覆部位_秘部, 100)
        ENDIF
        IF !RESULT
            PRINTFORMW %ANAME(TARGET_ID)%に液体が付着したものの幸い何も起きなかったようだ……
        ENDIF
        WAIT
        RETURN 1
    CASE "ブラシ触手", "触手", "フェイスハガー"
        ;調教イベントの初期設定
        CALL CLEAR_MPLY()
        CALL CLEAR_MTAR()
        FLAG:ウフフフラグ = 1
        FLAG:調教モード = 調教_慰安
        CVARSET CFLAG, GETNUM(CFLAG, "調教参加フラグ") , 0
        CFLAG:TARGET_ID:主導除外 = 1
        CFLAG:TARGET_ID:凌辱被害者フラグ = 1
        CFLAG:TARGET_ID:調教参加フラグ = 1
        SELECTCASE TRAP_TYPE
            CASE "ブラシ触手"
                CALL PRINT_TITLE(@"ブラシ触手の罠", "エロトラップ")
                CALLF TAG_PRINT(@"@C:{カラー_ピンク}@%ANAME(TARGET_ID)%は飛び出してきた無数の突起を持つ触手にたちまち絡め取られてしまった……@/C@", 1)
                WAIT
                TFLAG:調教ターン数 = RAND(5, 7)
                FOR LOCAL, 0, RAND(3, 6)
                    CALL QST_TRAIN_MOB_PRESET("ブラシ触手")
                    MOB_ID = RESULT
                    ;生成した触手モブを触手召喚状態にする
                    CALL ADD_MPLY(MOB_ID)
                    CALL SET_EQUIP(GETNUM(TRAINNAME, "触手召喚"), 1)
                    CALL DEL_MPLY(MOB_ID)
                NEXT
            CASE "フェイスハガー"
                CALL PRINT_TITLE(@"フェイスハガーの罠", "エロトラップ")
                CALLF TAG_PRINT(@"@C:{カラー_ピンク}@突然飛び出してきた肉腫が%ANAME(TARGET_ID)%の顔面にガッチリと張り付いた……！@/C@", 1)
                WAIT
                TFLAG:調教ターン数 = RAND(5, 7)
                FOR LOCAL, 0, 1
                    CALL QST_TRAIN_MOB_PRESET("フェイスハガー")
                    MOB_ID = RESULT
                    ;生成した触手モブを触手召喚状態にする
                    CALL ADD_MPLY(MOB_ID)
                    CALL SET_EQUIP(GETNUM(TRAINNAME, "触手召喚"), 1)
                    CALL DEL_MPLY(MOB_ID)
                NEXT
            CASEELSE
                CALL PRINT_TITLE(@"触手の罠", "エロトラップ")
                CALLF TAG_PRINT(@"@C:{カラー_ピンク}@%ANAME(TARGET_ID)%は飛び出してきた無数の触手にたちまち絡め取られてしまった……@/C@", 1)
                WAIT
                TFLAG:調教ターン数 = RAND(8, 10)
                FOR LOCAL, 0, RAND(3, 6)
                    CALL QST_TRAIN_MOB_PRESET("触手")
                    MOB_ID = RESULT
                    ;生成した触手モブを触手召喚状態にする
                    CALL ADD_MPLY(MOB_ID)
                    CALL SET_EQUIP(GETNUM(TRAINNAME, "触手召喚"), 1)
                    CALL DEL_MPLY(MOB_ID)
                NEXT
        ENDSELECT
        ;慰安モブは調教終了後に削除されてしまうため、名前などの情報を連想配列に退避
        MAP_CREATE "TRAP_EVENT_TRAIN"
        MAP_SET "TRAP_EVENT_TRAIN", "MOB_NAME", "触手"
        MAP_SET "TRAP_EVENT_TRAIN", "TARGET_NAME", ANAME(TARGET_ID)
        CALL QST_ENQUEUE_TRAIN_EXIT_FUNC("QST_CEV_TRAP_EVENT_TRAIN_END")
        RETURN 1
    CASE "Ｃコイン"
        CALL PRINT_TITLE(@"クリーピングコインの罠", "エロトラップ")
        CALLF TAG_PRINT(@"@C:{カラー_ピンク}@%ANAME(TARGET_ID)%は飛び出してきた無数の動き回るコインに足をとられ、転んでしまった……@/C@", 1)
        WAIT
        ;調教イベントの初期設定
        CALL CLEAR_MPLY()
        CALL CLEAR_MTAR()
        FLAG:ウフフフラグ = 1
        FLAG:調教モード = 調教_慰安
        TFLAG:調教ターン数 = RAND(5, 7)
        CVARSET CFLAG, GETNUM(CFLAG, "調教参加フラグ") , 0
        CFLAG:TARGET_ID:主導除外 = 1
        CFLAG:TARGET_ID:凌辱被害者フラグ = 1
        CFLAG:TARGET_ID:調教参加フラグ = 1
        FOR LOCAL, 0, 3
            CALL QST_TRAIN_MOB_PRESET("Ｃコイン")
        NEXT
        ;慰安モブは調教終了後に削除されてしまうため、名前などの情報を連想配列に退避
        MAP_CREATE "TRAP_EVENT_TRAIN"
        MAP_SET "TRAP_EVENT_TRAIN", "MOB_NAME", "クリーピングコイン"
        MAP_SET "TRAP_EVENT_TRAIN", "TARGET_NAME", ANAME(TARGET_ID)
        CALL QST_ENQUEUE_TRAIN_EXIT_FUNC("QST_CEV_TRAP_EVENT_TRAIN_END")
        RETURN 1
ENDSELECT
RETURN 0

@QST_CEV_TRAP_EVENT_TRAIN_END
#DIMS TARGET_NAME
#DIMS MOB_NAME

TARGET_NAME = %MAP_GET("TRAP_EVENT_TRAIN", "TARGET_NAME")%
MOB_NAME = %MAP_GET("TRAP_EVENT_TRAIN", "MOB_NAME")%

CALLF TAG_PRINT(@"@C:{カラー_ピンク}@%TARGET_NAME%は%MOB_NAME%による執拗な辱めからようやく解放された……@/C@", 1)
WAIT
;KOJO_EVENT候補

MAP_RELEASE "TRAP_EVENT_TRAIN"


code:
;-------------------------------------------------
; クエストで汎用可能なコモンイベント集
; 戦闘系イベント
;-------------------------------------------------
;-------------------------------------------------
; 汎用戦闘イベント
;-------------------------------------------------
@QST_CEV_COMBAT(PRESET_NAME)
#DIMS PRESET_NAME
#DIM  DYNAMIC GROUP_SIZE
#DIMS DYNAMIC _LIST_REWARD

;白兵戦参加メンバーの初期化
CALL CC_INIT()
;クエストのパーティメンバー全員を攻撃側として戦闘メンバーに追加
CALL CC_ADDPARTY()
CALL QST_CEV_COMBAT_MOB_PRESET(PRESET_NAME)
CALL CLOSE_COMBAT()
PRINTL
IF RESULT == 1
    CALL CC_APPLY_CHARA_HP()
    CALL CC_GET_LOOT_FROM("DEFENDER")
    CALL PRINT_NOTICE(@"%QST_LEADER_NAME()%は戦闘に勝利した！")
    WAIT
    RETURN 1
ELSE
    CALL CC_APPLY_CHARA_HP()
    CALL PRINT_NOTICE(@"%QST_LEADER_NAME()%は戦闘に敗北してしまった……")
    WAIT
    RETURN 0
ENDIF

@QST_CEV_COMBAT_MOB_PRESET(PRESET_NAME)
#DIMS PRESET_NAME
#DIMS DYNAMIC _LIST_REWARD
#DIM  DYNAMIC GROUP_SIZE
SELECTCASE PRESET_NAME
    CASE "ゴブリン"
        GROUP_SIZE = RAND(3, 4)
        FOR LOCAL, 0, GROUP_SIZE
            CALL CC_ADDMOB_FROM_TABLE("DEFENDER", "ゴブリン", @"ゴブリン%TOFULL(TOSTR(LOCAL + 1))%")
        NEXT
    CASEELSE
        TRYCCALLFORM QST_COMBAT_ENEMY_PARTY_%PRESET_NAME%
        CATCH
            PRINTFORML 指定されたプリセット名 %PRESET_NAME%
            THROW エラー:@QST_CEV_COMBAT_MOB_PRESET　指定されたプリセットに対応するエネミーパーティ定義関数が存在しません
        ENDCATCH

ENDSELECT


code:
;-------------------------------------------------
; クエストで汎用可能なコモンイベント集
; 疑似設備系イベント
;-------------------------------------------------
; DIC_OPTION のパラメータ一覧
; MODULE_ID: 擬似設備として使う設備番号(HOUSING_MODULE_DATA.ERB参照)
; PAUSE_BGM: 1 = BGM停止
; ALLOW_COM: 1 = 通常コマンドを許可
; ALLOW_UFUFUCOM: 1 = ウフフ系コマンドを許可
; MODULE_NAME: 未使用時の設備の表示名
; USE_MODULE_MESSAGE: 設備を使用した際のメッセージ
; MODULE_NAME_AT_USING: 使用時の設備の表示名
; STOP_USE_MODULE_MESSAGE: 設備使用を止めた際のメッセージ
; REDRESS_AT_STOP: 1 = 使用停止時に着衣を元に戻す
; ALLOW_OTHER_EVENT: 1 = 他のイベントの実行を許可
;-------------------------------------------------
@QST_CEV_USE_DUMMY_MODULE(DIC_OPTION)
#DIMS DIC_OPTION
#DIM  DYNAMIC IS_ACTIVE
#DIM  DYNAMIC DUMMY_MODULE_ID
#DIM  DYNAMIC CHARA_ID

CALL QST_GET_EVENT_FLAG(QST_NOWEV)
IS_ACTIVE = RESULT

;ダミーモジュール使用に関するオプション初期化
TFLAG:クエスト_ダミー設備ID = 0
FLAG:クエスト_交流コマンド許可 = 0
FLAG:クエスト_ウフフ許可 = 0
FLAG:移動制限フラグ = 0
QST_イベント選択制限 = -1

;既に使用中なら使用状態を解除
IF IS_ACTIVE
    ;イベント名称を元に戻す
    CALL QST_SET_EVENT_FLAG(QST_NOWEV, 0)
    IF DIC_CONTAINSKEY(DIC_OPTION, "MODULE_NAME")
        CALL QST_SET_EVENT_SLOT_NAME(QST_NOWEV, DIC_GET(DIC_OPTION, "MODULE_NAME"))
    ENDIF
    ;着衣を元に戻す
    IF DIC_CONTAINSKEY(DIC_OPTION, "REDRESS_AT_STOP")
        CALL QST_REDRESSALL()
    ENDIF
    ;使用中止メッセージ
    IF DIC_CONTAINSKEY(DIC_OPTION, "STOP_USE_MODULE_MESSAGE")
        PRINTFORMW %DIC_GET(DIC_OPTION, "STOP_USE_MODULE_MESSAGE")%
    ENDIF
    ;BGMを停止していた場合は再生
    IF TOINT(DIC_GET(DIC_OPTION, "PAUSE_BGM")) == 1
        CALL FL_REPLAYBGM()
    ENDIF

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

;擬似モジュール使用時のフラグ操作
CALL QST_SET_EVENT_FLAG(QST_NOWEV, 1)
;このイベントIDのイベント以外実行不可に
QST_イベント選択制限 = QST_NOWEV
;1=隣接エリアのみ移動可,2=エリア移動不可
FLAG:移動制限フラグ = 2
;交流系コマンドの実行を許可
FLAG:クエスト_交流コマンド許可 = 1

;オプションの適用
;擬似モジュールIDのセット
IF DIC_CONTAINSKEY(DIC_OPTION, "MODULE_ID")
    TFLAG:クエスト_ダミー設備ID = TOINT(DIC_GET(DIC_OPTION, "MODULE_ID"))
ENDIF

;擬似モジュールを使用中の名称に変更
IF DIC_CONTAINSKEY(DIC_OPTION, "MODULE_NAME_AT_USING")
    CALL QST_SET_EVENT_SLOT_NAME(QST_NOWEV, DIC_GET(DIC_OPTION, "MODULE_NAME_AT_USING"))
ENDIF
;通常の交流コマンドの実行可否
IF TOINT(DIC_GET(DIC_OPTION, "ALLOW_COM")) == 1
    FLAG:クエスト_交流コマンド許可 = 1
ENDIF
;ウフフ系コマンドの実行可否
IF TOINT(DIC_GET(DIC_OPTION, "ALLOW_UFUFUCOM")) == 1
    FLAG:クエスト_ウフフ許可 = 1
ENDIF
;他のイベントの実行可否
IF TOINT(DIC_GET(DIC_OPTION, "ALLOW_OTHER_EVENT")) == 1
    QST_イベント選択制限 = -1
ENDIF
;使用メッセージの表示
IF DIC_CONTAINSKEY(DIC_OPTION, "USE_MODULE_MESSAGE")
    PRINTFORMW %DIC_GET(DIC_OPTION, "USE_MODULE_MESSAGE")%
ENDIF
;BGMの再生停止
IF TOINT(DIC_GET(DIC_OPTION, "PAUSE_BGM")) == 1
    CALL FL_PAUSEBGM()
ENDIF


code:
;-------------------------------------------------
; クエストで汎用可能なコモンイベント集
; 抽選系イベント
;-------------------------------------------------
;-------------------------------------------------
; 衣服の脱着
;-------------------------------------------------
@QST_REDRESS(CHARA_ID, SHOW_MESSAGE = 1)
#DIM CHARA_ID
#DIM SHOW_MESSAGE

CALL HO_REDRESS(CHARA_ID)
IF RESULT
    SIF SHOW_MESSAGE
        PRINTFORMW %ANAME(CHARA_ID)%は%SPLIT_RAND("衣服の乱れ/着衣の乱れ/身だしなみ",1)%をそっと整えた……
    RETURN RESULT
ENDIF

@QST_REDRESSALL(SHOW_MESSAGE = 1)
#DIM CHARA_ID
#DIM SHOW_MESSAGE
#DIM DYNAMIC REDRESS_CHARANUM
#DIM DYNAMIC SHOW_NAME_CHARA

FOR LOCAL, 0, LIST_COUNT(_LIST_QST_PARTY)
    CHARA_ID = TOINT(LIST_GET(_LIST_QST_PARTY, LOCAL))
    CALL QST_REDRESS(CHARA_ID, 0)
    IF RESULT
        REDRESS_CHARANUM ++
        SHOW_NAME_CHARA = CHARA_ID
    ENDIF
NEXT
IF REDRESS_CHARANUM > 0 && SHOW_MESSAGE
    PRINTFORMW %ANAME(SHOW_NAME_CHARA, REDRESS_CHARANUM)%は%SPLIT_RAND("衣服の乱れ/着衣の乱れ/身だしなみ",1)%をそっと整えた……
ENDIF
RETURN REDRESS_CHARANUM

;-------------------------------------------------
; エリア効果
;-------------------------------------------------
;指定地点にエリア効果を発生させる
@QST_SET_ROOM_EFFECT(EFFECT_NAME, VALUES, ROOM_IDX = -1)
#DIMS EFFECT_NAME
#DIMS VALUES
#DIM  ROOM_IDX
#DIMS DYNAMIC ROOM_EFFECT_MAP

IF ROOM_IDX == -1
    ROOM_IDX = HO_MASTER現在地
ENDIF
ROOM_EFFECT_MAP '= @"MAP_{ROOM_IDX}_ROOM_EFFECT"

IF !MAP_HAS(ROOM_EFFECT_MAP, EFFECT_NAME) > 0
    MAP_SET ROOM_EFFECT_MAP, EFFECT_NAME, VALUES
    DEBUGPRINTFORML ROOM_EFFECT_MAP = %ROOM_EFFECT_MAP%, EFFECT_NAME = %EFFECT_NAME%, RESULT = {RESULT}
ENDIF

;指定地点のエリア効果を削除
@QST_REMOVE_ROOM_EFFECT(EFFECT_NAME, ROOM_IDX = -1)
#DIMS EFFECT_NAME
#DIM  ROOM_IDX
#DIMS DYNAMIC ROOM_EFFECT_MAP

IF ROOM_IDX == -1
    ROOM_IDX = HO_MASTER現在地
ENDIF
ROOM_EFFECT_MAP '= @"MAP_{ROOM_IDX}_ROOM_EFFECT"
MAP_REMOVE ROOM_EFFECT_MAP, EFFECT_NAME


code:
;-------------------------------------------------
;;; クエストで汎用可能なコモンイベント集
;;; その他イベント
;;; - ARG
;;; _LIST_JUDGE_VALUE (str(list))判定値リスト
;;; _LIST_MESSAGE (str(list))ボタンテキストリスト
;;; _LIST_DIFFICULTY (str(list))難易度リスト
;;; EXP_GAIN (int)経験値獲得量
;;; ALLOW_CANCEL (int(bool))キャンセルを許可するか
;;; CANCEL_MESSAGE (str)キャンセルボタンのテキスト
;;; TARGET_CHARA_ID (int)キャラを明示的に指定する場合、そのキャラID。未指定でパーティメンバから選択
;;; ALLOW_SUICIDE (int(bool))自滅を許可するか
;;; SUICIDE_MESSAGE (str)自滅ボタンのテキスト
;;; ALLOW_RETRY (int(bool))失敗選択肢の再挑戦を許可するか
;;; - RESULT
;;;   - RESULT:0 判定結果: 0=失敗, 1=成功, -1=キャンセル
;;;   - RESULT:1 挑戦したキャラのID
;;;   - RESULT:2 選択肢番号(0～)
;-------------------------------------------------
@QST_ROLL_MULTI(_LIST_JUDGE_VALUE, _LIST_MESSAGE, _LIST_DIFFICULTY, EXP_GAIN = 3, ALLOW_CANCEL = 1, CANCEL_MESSAGE = "何もしない", TARGET_CHARA_ID = -1, ALLOW_SUICIDE = 0, SUICIDE_MESSAGE = "わざと失敗する", ALLOW_RETRY = 0)
#DIMS _LIST_MESSAGE
#DIMS _LIST_JUDGE_VALUE
#DIMS _LIST_DIFFICULTY
#DIM  EXP_GAIN
#DIM  ALLOW_CANCEL
#DIMS CANCEL_MESSAGE
#DIM  TARGET_CHARA_ID
#DIM  REDRAW_MODE
#DIM  ALLOW_SUICIDE
#DIMS SUICIDE_MESSAGE
#DIM  ALLOW_RETRY
#DIMS DYNAMIC JUDGE_TYPE
#DIM  DYNAMIC IS_JUDGED
#DIM  DYNAMIC INPUT_VALUE
#DIM  DYNAMIC EVENT_FLAG
#DIM  DYNAMIC ROLL_RESULT
#DIM  DYNAMIC CHALLENGED_CHARA
#DIM  DYNAMIC CHARA_ID
#DIM  DYNAMIC FIRST_LINE

#DIM CONST COUNT_BIAS = 10000 ; 他の選択肢に被らない値にする為の下駄
#DIM  DYNAMIC MAX_MASSAGE_LEN
#DIM  DYNAMIC MAX_NAME_LEN
#DIM  DYNAMIC MAX_RATE_LEN, 2
#DIMS STR_SPACER

#DIM  DYNAMIC BUTTON_NO
#DIMS DYNAMIC BUTTON_TEXT
#DIMS DYNAMIC SELECT_TEXT
#DIM  DYNAMIC DIFFICULTY
#DIM  DYNAMIC SUCCESS_RATE
#DIM  DYNAMIC SELECT_ROW
#DIM  DYNAMIC SELECT_COL
#DIM  DYNAMIC BEST_ROLL_ALL_MASTER

CURRENTREDRAW
REDRAW_MODE = RESULT
REDRAW 0
VARSET RESULTS
FIRST_LINE = LINECOUNT

;事前処理
;・表示位置調整用に各種表示文字列のなかで一番長い長さを取得
;・最良選出がすべてあなたになるかを判定
MAX_RATE_LEN:0 = 2
MAX_RATE_LEN:1 = 2
BEST_ROLL_ALL_MASTER = 1
FOR LOCAL, 0, LIST_COUNT(_LIST_MESSAGE)
    ;メッセージ
    IF MAX_MASSAGE_LEN < STRLENS(LIST_GET(_LIST_MESSAGE, LOCAL))
        MAX_MASSAGE_LEN = STRLENS(LIST_GET(_LIST_MESSAGE, LOCAL))
    ENDIF
    ;最良選出キャラの名前と成功率
    DIFFICULTY   = TOINT(LIST_GET(_LIST_DIFFICULTY, LOCAL))
    JUDGE_TYPE  '= LIST_GET(_LIST_JUDGE_VALUE, LOCAL)
    CHARA_ID     = BEST_ROLL_CHARA_CHOICE_PARTY(GETNUM(ABL, JUDGE_TYPE))
    SUCCESS_RATE = QST_GET_ROLL_SUCCESS_RATE(ABL:CHARA_ID:JUDGE_TYPE, DIFFICULTY)
    IF MAX_NAME_LEN < STRLENS(ANAME(CHARA_ID))
        MAX_NAME_LEN = STRLENS(ANAME(CHARA_ID))
    ENDIF
    ;成功率が100.0%以上の場合は3桁表示
    SIF SUCCESS_RATE >= 1000
        MAX_RATE_LEN:0 = 3
    ;成功率が100.0%以上の場合は3桁表示
    SIF SUCCESS_RATE >= 1000 && CHARA_ID == MASTER
        MAX_RATE_LEN:1 = 3
    ;最良選出キャラがマスターでない
    SIF CHARA_ID != MASTER
        BEST_ROLL_ALL_MASTER = 0
NEXT
;キャンセルメッセージとの比較
IF MAX_MASSAGE_LEN < STRLENS(CANCEL_MESSAGE)
    MAX_MASSAGE_LEN = STRLENS(CANCEL_MESSAGE)
ENDIF
;自滅用メッセージとの比較
IF MAX_MASSAGE_LEN < STRLENS(SUICIDE_MESSAGE)
    MAX_MASSAGE_LEN = STRLENS(SUICIDE_MESSAGE)
ENDIF

$ASK_LOOP
; 渡された選択肢の表示処理(失敗済みの選択肢は選択不可) ボタンの値は(FOR文で増えていく)LOCALの値
FOR LOCAL, 0, LIST_COUNT(_LIST_MESSAGE)
    ;CALL QST_GET_EVENT_FLAG_BY_IDX()
    ;EVENT_FLAG = RESULT
    IF !ALLOW_RETRY
        EVENT_FLAG = TOINT(QST_GET_FLAGMAP(@"EVENT_{QST_NOWEV_LIST_IDX}_ROLL_RESULT"))
    ELSE
        EVENT_FLAG = 0
    ENDIF
    GETBIT EVENT_FLAG, LOCAL + 1
    IF !RESULT
        ;コマンド
        BUTTON_NO    = LOCAL
        BUTTON_TEXT '= LIST_GET(_LIST_MESSAGE, LOCAL)
        SELECT_TEXT '= @"　@B:{BUTTON_NO}@[%BUTTON_TEXT%]@/B@ "
        ; 既にロールするキャラが決まっているなら自動選出はさせない
        IF TARGET_CHARA_ID == -1
            ;位置調整用スペースの数計算
            STR_SPACER '= " " * (MAX_MASSAGE_LEN - STRLENS(LIST_GET(_LIST_MESSAGE, LOCAL)))
            SELECT_TEXT += STR_SPACER

            ;判定値の取得
            DIFFICULTY   = TOINT(LIST_GET(_LIST_DIFFICULTY, LOCAL))
            JUDGE_TYPE  '= LIST_GET(_LIST_JUDGE_VALUE, LOCAL)

            ;対象ロールの最良キャラ
            CHARA_ID     = BEST_ROLL_CHARA_CHOICE_PARTY(GETNUM(ABL, JUDGE_TYPE))
            SUCCESS_RATE = QST_GET_ROLL_SUCCESS_RATE(ABL:CHARA_ID:JUDGE_TYPE, DIFFICULTY)
            STR_SPACER  '= " " * (MAX_NAME_LEN - STRLENS(ANAME(CHARA_ID)))

            BUTTON_NO    = LOCAL + COUNT_BIAS
            BUTTON_TEXT '= @"最良選出:%ANAME(CHARA_ID)%%STR_SPACER%({MIN(100, SUCCESS_RATE / 10), MAX_RATE_LEN:0}\%)"
            SELECT_TEXT += @"@B:{BUTTON_NO}@[%BUTTON_TEXT%]@/B@"

            ;自分がやる(あなたが実行)
            ;・あなたがパーティに居る場合のみ表示
            ;・最良選出キャラがすべてあなたの場合は表示しない
            IF QST_LEADER_ID() == MASTER && !BEST_ROLL_ALL_MASTER
                SELECT_TEXT += " "
                SUCCESS_RATE = QST_GET_ROLL_SUCCESS_RATE(ABL:MASTER:JUDGE_TYPE, DIFFICULTY)

                BUTTON_NO    = LOCAL + (COUNT_BIAS * 2)
                BUTTON_TEXT '= @"自分がやる({MIN(100, SUCCESS_RATE / 10), MAX_RATE_LEN:1}\%)"
                SELECT_TEXT += @"@B:{BUTTON_NO}@[%BUTTON_TEXT%]@/B@"
            ENDIF

            ;CALLF TAG_PRINT(@"@C:{カラー_白}@@B:{LOCAL}@　[%LIST_GET(_LIST_MESSAGE, LOCAL)%]@/B@@@%STR_SPACER%@@@B:{LOCAL + COUNT_BIAS}@[最良選出:%ANAME(CHARA_ID)%]@/B@@/C@", 5)
            ;ELSE
            ;   BUTTON_TEXT '= @"@C:{カラー_白}@@B:{BUTTON_NO_COMMAND}@　[%BUTTON_TEXT_COMMAND%]@/B@@/C@"
            ;CALLF TAG_PRINT(@"@C:{カラー_白}@@B:{LOCAL}@　[%LIST_GET(_LIST_MESSAGE, LOCAL)%]@/B@@/C@", 5)
        ENDIF
        CALLF TAG_PRINT(SELECT_TEXT, 5)
    ELSE
        CALLF TAG_PRINT(@"@C:{カラー_選択不可}@　[%LIST_GET(_LIST_MESSAGE, LOCAL)%]@/C@", 1)
    ENDIF
NEXT
; 自滅用の選択肢の表示処理(失敗済みの選択肢は選択不可) ボタンの値は9998
IF ALLOW_SUICIDE
    IF !GETBIT(EVENT_FLAG, 16)
        CALLF TAG_PRINT(@"@C:{カラー_白}@@B:9998@　[%SUICIDE_MESSAGE%]@/B@@/C@", 5)
    ELSE
        CALLF TAG_PRINT(@"@C:{カラー_選択不可}@　[%SUICIDE_MESSAGE%]@/C@", 5)
    ENDIF
ENDIF
; キャンセル選択肢の表示処理 ボタンの値は9999
IF ALLOW_CANCEL
    PRINTL
    CALLF TAG_PRINT(@"@C:{カラー_白}@@B:9999@　[%CANCEL_MESSAGE%]@/B@@/C@", 5)
ENDIF

REDRAW REDRAW_MODE
ONEINPUT
INPUT_VALUE = RESULT
CLEARLINE 1

; 入力値に応じた処理 (選択肢は0番目から数えるので最大値は-1しないと渡された選択肢の範囲よりも1つ多い値でも範囲内と判定されてしまう)
IF INRANGE(INPUT_VALUE, 0, LIST_COUNT(_LIST_MESSAGE) - 1)
    ; 渡された選択肢での処理
    JUDGE_TYPE = %LIST_GET(_LIST_JUDGE_VALUE, INPUT_VALUE)%
    IF JUDGE_TYPE != "なし"
        CALL QST_PARTY_ROLL(LIST_GET(_LIST_JUDGE_VALUE, INPUT_VALUE), TOINT(LIST_GET(_LIST_DIFFICULTY, INPUT_VALUE)), 1, EXP_GAIN, , TARGET_CHARA_ID)
        ROLL_RESULT = RESULT
        CHALLENGED_CHARA = RESULT:1
        IF RESULT != -1
            SETBIT EVENT_FLAG, INPUT_VALUE + 1
            ;CALL QST_SET_EVENT_FLAG_BY_IDX(EVENT_FLAG)
            IF !ALLOW_RETRY
                CALL QST_SET_FLAGMAP(@"EVENT_{QST_NOWEV_LIST_IDX}_ROLL_RESULT", TOSTR(EVENT_FLAG))
            ENDIF
        ELSEIF RESULT == -1
            CLEARLINE LINECOUNT - FIRST_LINE
            GOTO ASK_LOOP
        ENDIF
    ENDIF
    RESULT:1 = CHALLENGED_CHARA
    RESULT:2 = INPUT_VALUE
    RESULTS = %LIST_GET(_LIST_JUDGE_VALUE, INPUT_VALUE)%
    RETURN ROLL_RESULT
ELSEIF INPUT_VALUE == 9998
    ; 自滅用の選択肢の処理
    CALL QST_SELECT_CHARA(1, "行動を実行するキャラクターを選択してください")
    SIF RESULT == -1
        RETURN -1
    RESULT:1 = RESULT
    SETBIT EVENT_FLAG, 16
    ;CALL QST_SET_EVENT_FLAG_BY_IDX(EVENT_FLAG)
    IF !ALLOW_RETRY
        CALL QST_SET_FLAGMAP(@"EVENT_{QST_NOWEV_LIST_IDX}_ROLL_RESULT", TOSTR(EVENT_FLAG))
    ENDIF
    RETURN 0
ELSEIF INPUT_VALUE == 9999
    ; キャンセル選択肢の処理
    RETURN -1
ELSEIF TARGET_CHARA_ID == -1 && (INRANGE(INPUT_VALUE - COUNT_BIAS, 0, LIST_COUNT(_LIST_MESSAGE) - 1) || INRANGE(INPUT_VALUE - (COUNT_BIAS * 2), 0, LIST_COUNT(_LIST_MESSAGE) - 1))
    ; キャラ指定ありのコマンド選択
    ;選択したボタンの行(項目)列(キャラ指定)を分解
    SELECT_ROW = INPUT_VALUE % COUNT_BIAS
    SELECT_COL = INPUT_VALUE / COUNT_BIAS
    JUDGE_TYPE = %LIST_GET(_LIST_JUDGE_VALUE, SELECT_ROW)%
    ;押したボタン列にあわせてキャラ指定
    SELECTCASE SELECT_COL
        CASE 0
            ;処理なし(条件的に来ない)
        CASE 1
            ; TARGET_CHARA_IDに最良キャラを入れる
            TARGET_CHARA_ID = BEST_ROLL_CHARA_CHOICE_PARTY(GETNUM(ABL, JUDGE_TYPE))
        CASE 2
            ; TARGET_CHARA_IDにあなたを入れる
            TARGET_CHARA_ID = MASTER
    ENDSELECT
    IF JUDGE_TYPE != "なし"
        ;キャラ指定あり、確認スキップONで関数を呼び出し
        CALL QST_PARTY_ROLL(LIST_GET(_LIST_JUDGE_VALUE, SELECT_ROW), TOINT(LIST_GET(_LIST_DIFFICULTY, SELECT_ROW)), 1, EXP_GAIN, , TARGET_CHARA_ID, 1)
        ROLL_RESULT = RESULT
        CHALLENGED_CHARA = RESULT:1
        IF RESULT != -1
            SETBIT EVENT_FLAG, SELECT_ROW + 1
            ;CALL QST_SET_EVENT_FLAG_BY_IDX(EVENT_FLAG)
            IF !ALLOW_RETRY
                CALL QST_SET_FLAGMAP(@"EVENT_{QST_NOWEV_LIST_IDX}_ROLL_RESULT", TOSTR(EVENT_FLAG))
            ENDIF
        ELSEIF RESULT == -1
            CLEARLINE LINECOUNT - FIRST_LINE
            ; キャンセルした場合には自動選出されたキャラのIDが入ったTARGET_CHARA_IDをリセットする(リセットしないと手動選択ができなくなる)
            TARGET_CHARA_ID = -1
            GOTO ASK_LOOP
        ENDIF
    ENDIF
    RESULT:1 = CHALLENGED_CHARA
    RESULT:2 = SELECT_ROW
    RESULTS = %LIST_GET(_LIST_JUDGE_VALUE, SELECT_ROW)%
    RETURN ROLL_RESULT

ELSE
    GOTO ASK_LOOP
ENDIF

;-------------------------------------------------
; パーティ内におけるロール最良キャラの自動選択
;-------------------------------------------------
@BEST_ROLL_CHARA_CHOICE_PARTY(判定パラメータ)
#FUNCTION
#DIM 判定パラメータ
#DIM CHECK_CHARA_ID
#DIM BEST_CHARA_ID

; 当該するパラメータが存在しない場合にはパーティの0番のキャラを最良と見なして処理する(全員が同じ値のパラメータを持つ場合と同じ結果)
IF 判定パラメータ == -1
    RETURNF TOINT(LIST_GET(_LIST_QST_PARTY, 0))
ENDIF

BEST_CHARA_ID = -1

FOR LOCAL, 0, QST_PARTYNUM
    CHECK_CHARA_ID = TOINT(LIST_GET(_LIST_QST_PARTY, LOCAL))
    ; 「-1番のキャラの能力」を確認させない様に
    IF BEST_CHARA_ID == -1
        BEST_CHARA_ID = CHECK_CHARA_ID
        CONTINUE
    ENDIF
    IF ABL:CHECK_CHARA_ID:判定パラメータ > ABL:BEST_CHARA_ID:判定パラメータ
        BEST_CHARA_ID = CHECK_CHARA_ID
    ENDIF
NEXT

RETURNF BEST_CHARA_ID


code:
;クエスト関連の広域変数
#DIM CONST QST_MAX_QUESTNUM = 100
#DIM CONST QST_MAX_EVENTNUM = 300
#DIM CONST QST_MAX_FLAGNUM = 10

#DIMS QST_QUEST_TYPE
#DIM QST_有効クエストID
#DIM QST_NOWEV
#DIM QST_NOWEV_LIST_IDX
#DIMS QST_MAPNAME
#DIMS _DIC_QST_EVENT_LIST, HO_MAX_MAPNUM, QST_MAX_EVENTNUM

;メニュー関連
#DIM  QST_GUILD_MENU_CATEGORY
#DIM  QST_SELECT_QUEST_ID
#DIM  QST_MENU_PAGE_LEFT
#DIMS QST_DIC_QUEST_FILTER

;クエスト参加メンバーのCHARA_IDを格納
#DIM  CONST QST_MAX_PARTY_PRESET = 6
#DIM  CONST QST_MAX_PARTYNUM = 6
#DIMS SAVEDATA _LIST_QST_PARTY_PRESET, QST_MAX_PARTY_PRESET
#DIM  SAVEDATA QST_SELECT_PARTY_PRESET
#DIMS SAVEDATA _LIST_QST_PARTY
#DIM QST_PARTYNUM

#DIM QST_TRAIN_EXIT_EVENT_ID
#DIMS _LIST_QST_TRAIN_EXIT_EVENT

#DIMS _LIST_INQUEST_MEMBER_EDIT_CANDIDATES
#DIMS _LIST_PARTY_PARTICIPANT_RECORD

;経路描画をコントロールするフラグ
#DIM QST_HIDE_PATH
;クエストイベントの調教ターン数
;TRAINでのターン数初期化時にこの変数から代入される
#DIM QST_調教ターン数
;この変数にイベントIDが格納されている場合(!=-1の場合)対象ID以外のイベントがスロットから実行不可になる
#DIM QST_イベント選択制限
;名誉点
#DIM SAVEDATA QST_PRESTIGE_POINT
;淫堕点
#DIM SAVEDATA QST_LEWD_POINT
;応急治療点
#DIM QST_応急治療点

;各クエストのフラグ管理用変数
;クエスト実行後もゲーム内でフラグを保持し続けたい場合は QST_SV_... を使用する
;繰り返し実行可能なクエストでの宝箱の取得状況管理などに
#DIM QST_FLAG, QST_MAX_QUESTNUM
#DIM SAVEDATA QST_SV_QUEST_FLAG, QST_MAX_QUESTNUM
#DIM SAVEDATA QST_SV_EVENT_FLAG, QST_MAX_QUESTNUM, QST_MAX_EVENTNUM
;クエストの攻略回数をカウント
#DIM SAVEDATA QST_SV_CLEAR_COUNT, QST_MAX_QUESTNUM

;定期性クエストのクールタイム管理
#DIM SAVEDATA QST_COOLTIME, QST_MAX_QUESTNUM

;ギルドメニューの得点引換在庫
#DIMS SAVEDATA QUEST_MENU_DIC_SHOP_STOCK_0, 20

;クエストの探索状態保持設定
#DIM  QST_SAVE_EXPLORED
;探索済ルームリスト
#DIMS SAVEDATA QST_LIST_EXPLORED_ROOM, QST_MAX_QUESTNUM

;グラフィカルマップ管理変数
#DIMS QST_GMAPDATA_PATH
#DIMS QST_GMAPDATA_FILENAME

;クエストで上昇する好感度関連
#DIM CONST QST_MAX_RELATION_UP = 100

;汎用イベント新増
#DIM CONST 汎用イベント_COUNT = 2
;CURRENTLY 1, CHANGE THIS CONST IF MORE IS WRITTEN
;#DIM 逆押し倒し_ID