WIDeadBodyCleanupScript
このスクリプトはユニークなNPCなどを死体置き場のセル(WIDeadBodyCleanupCell)へ移動させ、
インベントリ内のアイテムを棺などに移動させるスクリプトです。(ついでに自動的に盗品属性が付く)
このスクリプトの使用条件は以下のとおり。
・条件1:ユニークなActorであること(非ユニークなActorの場合、死体消去の処理と競合するからだと思われます)
・条件2:生きている状態で生成されること(死んだ状態で生成されると回収されるためのフラグが立たない)
<設定方法>
ActorのEdit画面左中央にある「Script」のところでAdd⇒WIDeadBodyCleanupScriptを指定
追加されたら選択してPropertiesをクリック
・DaysBeforeCleanup
・死体が回収される経過時間。未指定の場合0.5(12時間)
・DeathContainer
・死体を収めるコンテナ。Pick Reference in Render Window⇒Render Windowに表示されている棺などを指定
・WI
・WIを選択しておく
<スクリプト解説>
Scriptname WIDeadBodyCleanupScript extends Actor
;**** This should ONLY BE USED ON UNIQUE ACTORS!!! ****
;This script cleans up dead actors, enables a container (ie grave/crypt) and moves all their inventory, after it Loads/unloads after a certain period of time.
;If you need to temporarily stop someone from being cleaned up, put them in the WINoBodyCleanupFaction faction.
;please do not modify this script without talking to jduvall
WIFunctionsScript Property WI Auto
{Pointer to WIFunctionsScript attached to WI quest. You MUST set this or things will be broken.}
float Property DaysBeforeCleanUp = 0.5 Auto
{Default = 0.5: What's the minimum amount of time (in days) that the body should stick around before being cleaned up. (Clean up happens during while loop.)}
ObjectReference Property DeathContainer Auto
{Container to move all the items the actor has in his inventory when cleaned up.}
actor SelfRef ;used to keep me persistent so I get UnLoad events while I exist
state Dead
;do nothing
Event OnDeath(Actor akKiller)
EndEvent
EndState
Event OnDeath(Actor akKiller)
GoToState("Dead")
if DeathContainer
bool cleanedUp = false
while cleanedUp == false
; debug.trace("WIDeadBodyCleanupScript" + self + "OnDeath() In While Loop, will try cleaning up after waiting " + DaysBeforeCleanUp)
utility.waitGameTime(DaysBeforeCleanUp * 24) ;設定された時間経過まで待機(default:0.5 = 12時間)
cleanedUp = checkForCleanup()
endWhile
else
; debug.trace("WIDeadBodyCleanupScript" + self + " WARNING: NO DeathContainer!", 2)
endif
EndEvent
;死体をコンテナに送るかどうかのチェック処理
;WINoBodyCleanupFanctionがついているActorの場合は条件を満たしても送られない(チェック済みにして呼び元のループからは抜ける)
;時間経過をしても死体のあるセルが読み込まれている状態の場合は送られない
bool function checkForCleanup()
if IsInFaction(WI.WINoBodyCleanupFaction)
; debug.trace("WIDeadBodyCleanupScript" + self + "In Faction WINoBodyCleanupFaction so NOT cleaning up body.", 1)
;do nothing
return true ;bail out of while loop
Elseif Is3DLoaded() == False
; debug.trace("WIDeadBodyCleanupScript" + self + "Cleaning up body.")
cleanUpBody()
return true
Else
; debug.trace("WIDeadBodyCleanupScript" + self + "Not cleaning up body, because my 3D is loaded.")
EndIf
return false
endfunction
;実際に死体をコンテナに送る処理
function cleanUpBody()
; debug.trace("WIDeadBodyCleanupScript" + self + "cleanUpBody() moving to WIDeadBodyCleanupCellMarker in WIDeadBodyCleanupCell and Calling RemoveAllItems() to DeathContainer, and enabling it:" + DeathContainer)
;Disable()
;*** It has been decided it's safer to move them to a holding cell, for quests that might be filling allowing for dead actors but not allowing checking for disabled actors
MoveTo(WI.WIDeadBodyCleanupCellMarker) ;死体そのものは専用セルへ送る
DeathContainer.SetActorOwner(GetActorBase()) ;ここで所有権を付けているので「盗む」と表示される
DeathContainer.Enable() ;あらかじめ非表示しておいたオブジェクトの場合、ここで表示がされる
RemoveAllItems(DeathContainer)
EndFunction
神経衰弱スクリプト(bwpMatchCardMasterSCRIPT、bpwMatchCardScript)
このスクリプトは先に引いたカードと後から引いたカードを一致させるゲーム、ようは神経衰弱です。
未実装エリア:OLDBluePalaceWing01に置かれているのですが、これはそのままだと「先に選んだカードが消えない」という問題があり、
もう一度まったく同じカードをactivateすると一致したことになってしまうという穴があってまともなミニゲームになっていません。
スクリプトを改変することでちゃんとしたミニゲームにすることができます。
自作MOD:MorePlacesByYossieにてこのスクリプトをほぼそのまま使っている場所がありますので、
実際の動きを見たい方はそちらで試してみてください。該当の場所はバーレイダーク遺跡になります。
なお、設定は少々面倒です。
カードが10枚あるので、それらすべてに全カードの所在と、どれがどのカードなのかをCreation Kit上で指定してあげる必要があります。
<スクリプト解説>
Scriptname bwpMatchCardMasterSCRIPT extends ObjectReference
;0 = NULL
;1 = Spades
;2 = Hearts
;3 = Diamonds
;4 = Clubs
;5 = Sheo
INT PROPERTY flippedCard=0 AUTO HIDDEN ;選んだカードがどれなのかのフラグ(番号の内訳は上のコメントの通り)
INT PROPERTY flippedNum=0 AUTO HIDDEN ;新規追加 選んだカードが1番目なのか2番目なのかのフラグ
Scriptname bpwMatchCardScript extends ObjectReference
;each of the possible cards faces when flipped
OBJECTREFERENCE PROPERTY HeartsA AUTO ;カードのオブジェクト群 所在を全部CK上で指定する
OBJECTREFERENCE PROPERTY HeartsB AUTO
OBJECTREFERENCE PROPERTY ClubsA AUTO
OBJECTREFERENCE PROPERTY ClubsB AUTO
OBJECTREFERENCE PROPERTY SpadesA AUTO
OBJECTREFERENCE PROPERTY SpadesB AUTO
OBJECTREFERENCE PROPERTY DiamondsA AUTO
OBJECTREFERENCE PROPERTY DiamondsB AUTO
OBJECTREFERENCE PROPERTY SheoA AUTO
OBJECTREFERENCE PROPERTY SheoB AUTO
BOOL PROPERTY HEARTS AUTO ;カードの種類 CK上で該当のものだけtrueにする
BOOL PROPERTY CLUBS AUTO
BOOL PROPERTY SPADES AUTO
BOOL PROPERTY DIAMONDS AUTO
BOOL PROPERTY SHEO AUTO
BOOL PROPERTY first AUTO ;新規追加 1番目のカードならtrueにしておく
BOOL PROPERTY second AUTO ;新規追加 2番目のカードならtrueにしておく
;the script keeping track
OBJECTREFERENCE PROPERTY controllerScript AUTO
;the master script
bwpMatchCardMasterSCRIPT mainScript
;the door
OBJECTREFERENCE PROPERTY portDoor AUTO ;ミニゲーム成立時にオープンする扉
OBJECTREFERENCE PROPERTY skeevDoor AUTO
EVENT onLoad()
mainScript = controllerScript as bwpMatchCardMasterSCRIPT ;ここでロードされたときに初期化しています。つまりロードをはさまないと正しく動きません。
ENDEVENT
EVENT onACTIVATE(objectReference obj)
IF(obj as ACTOR == game.getPlayer())
; //////////////////////
; If it's a Hearts card
IF(HEARTS)
;1枚目を選んだ時の処理
IF(mainScript.flippedCard == 0)
mainScript.flippedCard = 2
IF(first) ;処理追加&変更 選んだカードのほうをdisableして選べなくする
mainScript.flippedNum = 1
HeartsA.disable()
ELSE
mainScript.flippedNum = 2
HeartsB.disable()
ENDIF
debug.messageBox("Heart")
;2枚目を選んで同じ種類だった時の処理
ELSEIF(mainScript.flippedCard == 2)
HeartsA.disable()
HeartsB.disable()
debug.messageBox("Match")
mainScript.flippedCard = 0
mainScript.flippedNum = 0
;2枚目を選んで違う種類だった時の処理
ELSE
EnableBeforeSelectedCard() ;処理追加 消したカードを元に戻す(サブ関数 詳細は後述)
mainScript.flippedCard = 0
mainScript.flippedNum = 0
debug.messageBox("Reset")
ENDIF
; /////////////////////
; If it's a clubs card
ELSEIF(CLUBS)
IF(mainScript.flippedCard == 0)
mainScript.flippedCard = 4
IF(first)
mainScript.flippedNum = 1
ClubsA.disable()
ELSE
mainScript.flippedNum = 2
ClubsB.disable()
ENDIF
debug.messageBox("Clubs")
ELSEIF(mainScript.flippedCard == 4)
ClubsA.disable()
ClubsB.disable()
debug.messageBox("Match")
mainScript.flippedCard = 0
mainScript.flippedNum = 0
ELSE
EnableBeforeSelectedCard()
mainScript.flippedCard = 0
mainScript.flippedNum = 0
debug.messageBox("Reset")
ENDIF
; //////////////////////
; If it's a spades card
ELSEIF(SPADES)
IF(mainScript.flippedCard == 0)
mainScript.flippedCard = 1
IF(first)
mainScript.flippedNum = 1
SpadesA.disable()
ELSE
mainScript.flippedNum = 2
SpadesB.disable()
ENDIF
debug.messageBox("Spades")
ELSEIF(mainScript.flippedCard == 1)
SpadesA.disable()
SpadesB.disable()
debug.messageBox("Match")
mainScript.flippedCard = 0
mainScript.flippedNum = 0
ELSE
EnableBeforeSelectedCard()
mainScript.flippedCard = 0
mainScript.flippedNum = 0
debug.messageBox("Reset")
ENDIF
; ////////////////////////
; If it's a diamonds card
ELSEIF(DIAMONDS)
IF(mainScript.flippedCard == 0)
mainScript.flippedCard = 3
IF(first)
mainScript.flippedNum = 1
DiamondsA.disable()
ELSE
mainScript.flippedNum = 2
DiamondsB.disable()
ENDIF
debug.messageBox("Diamond")
ELSEIF(mainScript.flippedCard == 3)
DiamondsA.disable()
DiamondsB.disable()
debug.messageBox("Match")
mainScript.flippedCard = 0
mainScript.flippedNum = 0
ELSE
EnableBeforeSelectedCard()
mainScript.flippedCard = 0
mainScript.flippedNum = 0
debug.messageBox("Reset")
ENDIF
; ////////////////////
; If it's a sheo card
ELSEIF(SHEO)
IF(mainScript.flippedCard == 0)
mainScript.flippedCard = 5
IF(first)
mainScript.flippedNum = 1
SheoA.disable()
ELSE
mainScript.flippedNum = 2
SheoB.disable()
ENDIF
debug.messageBox("Sheo")
ELSEIF(mainScript.flippedCard == 5)
SheoA.disable()
SheoB.disable()
debug.messageBox("Match")
mainScript.flippedCard = 0
mainScript.flippedNum = 0
ELSE
EnableBeforeSelectedCard()
mainScript.flippedCard = 0
mainScript.flippedNum = 0
debug.messageBox("Reset")
ENDIF
ELSE
debug.messageBox("we haven't been set!")
ENDIF
;puzzle is complete, open the door
IF(HeartsA.isEnabled() == FALSE && SpadesA.isEnabled() == FALSE && DiamondsA.isEnabled() == FALSE && ClubsA.isEnabled() == FALSE && SheoA.isEnabled() == FALSE && HeartsB.isEnabled() == FALSE && SpadesB.isEnabled() == FALSE && DiamondsB.isEnabled() == FALSE && ClubsB.isEnabled() == FALSE && SheoB.isEnabled() == FALSE)
;debug.messageBox("Open Door!!")
portDoor.activate(controllerScript)
skeevDoor.activate(controllerScript)
ENDIF
ENDIF
ENDEVENT
;新規追加のサブ関数
;MASTERscript側に覚えさせた「先に選んで消えたカード」を復活させる処理
;覚えたカードがどれなのか判定してenable()しているだけです。
Function EnableBeforeSelectedCard()
IF(mainScript.flippedCard == 2)
IF(mainScript.flippedNum == 1)
HeartsA.enable()
ELSE
HeartsB.enable()
ENDIF
ELSEIF(mainScript.flippedCard == 4)
IF(mainScript.flippedNum == 1)
ClubsA.enable()
ELSE
ClubsB.enable()
ENDIF
ELSEIF(mainScript.flippedCard == 1)
IF(mainScript.flippedNum == 1)
SpadesA.enable()
ELSE
SpadesB.enable()
ENDIF
ELSEIF(mainScript.flippedCard == 3)
IF(mainScript.flippedNum == 1)
DiamondsA.enable()
ELSE
DiamondsB.enable()
ENDIF
ELSE
IF(mainScript.flippedNum == 1)
SheoA.enable()
ELSE
SheoB.enable()
ENDIF
ENDIF
EndFunction
<必要なもの>
扉 NorPortcullisなど
鎖 NorPullChainなど
<設定方法>
扉のActivate Parentsに鎖を指定するだけです。
Delayについては引いた瞬間に発動させたければ0でOK。
通常の扉にLockをかけておいて初回は必ず鎖で開かせたい、というような場合は、
扉のscriptにdefault2StateActivatorを設定しましょう。
(scriptのPropertiesは何もいじらなくてOK)