pepperman35 Posted November 27, 2020 Share Posted November 27, 2020 I have an infirmary set up in my mod which as five beds. When the player enters the cell I’d like to have between 1-4 npcs spawn in and randomly occupy the available beds, giving the appearance that NPCs are being treated. No player interaction with the “sick” NPCs is required. First: Is the doable? Second: Is anything like this implemented in the game that I could examine? Third: is there a way to make the NPCs lie flat on their backs vice assuming a sleep position. Lastly: Suggestions on implementation are welcomed and appreciated, assuming it is doable. Conceptually I could envision:1. Creating a pool of sick people (approximately 10 “sick” NPCs)2. Randomly spawn between 1 – 4 NPCs from the pool of sick people, ensuring that no sick NPC is selected twice.3. Randomly assign the sick NPCs to the available beds, ensuring that multiple NPCs aren’t assigned to the same bed Link to comment Share on other sites More sharing options...
Pelgar Posted November 27, 2020 Share Posted November 27, 2020 #1, Yes I think it is doable#2, Yes, sort of anyway. The kid in Vault 81, I think it's 81, the vault where you recruit Curie#3, Yes, SnapIntoInteraction(akBed) i.e. SleepPartner02.SnapIntoInteraction(akBed). They are not flat on their back, just a sleeping position. Link to comment Share on other sites More sharing options...
pepperman35 Posted November 28, 2020 Author Share Posted November 28, 2020 Ref #3. After doing some data mining in CK, it looks like NPCBedHospitalNoPlayer might work nicely. Next I'll try to force the NPC into it. Link to comment Share on other sites More sharing options...
Pelgar Posted November 28, 2020 Share Posted November 28, 2020 I don't think the vanilla games uses SnapIntoInteraction on a bed anywhere. They make heavy use of it in vertibirds. I've included the entire script that I have attached to a custom bed in a companion mod that I'm about ready to release. You can see it working at: https://youtu.be/rlnXoJ3nk58 Scriptname CompJennyBedScript extends ObjectReference Armor Property SkinNaked Auto Const Armor Property JennysSkinNaked Auto Const Armor Property SkinNaked_AO Auto Const Armor Property JennysSkinNaked_AO Auto Const Bool Property bPlayerSleeping Auto Bool Property bUndressCompleteSP1 Auto Bool Property bUndressCompleteSP2 Auto Bool Property bSP1NotRomantic Auto Bool Property bSP2NotRomantic Auto Bool Property bBedAssignedToSP1 Auto Actor Property SleepPartner01 Auto Actor Property SleepPartner02 Auto Actor Property Jenny Auto CompJennyStartupQScript Property CJStartUpScript Auto Keyword Property CompJenny_SleepingWithPC Auto Const Keyword Property playerCanStimpak Auto Const Message Property CompJennyReplaceSleepCompMsg Auto Const Message Property CompJennySleepCompNotRomantic Auto Const Message Property CompJennyBedMessage_BothAlreadyAssigned Auto Const ActorValue Property CA_IsRomantic Auto Const GlobalVariable Property CompJennyF4SEVersion Auto Const Int Property nTimerPC Auto Const Int Property nSP1UndressComplete Auto Const Int Property nSP2UndressComplete Auto Const Int Property nTimerSP1 Auto Const Int Property nTimerSP2 Auto Const Int Property nTimerWorker Auto Const ActorBase Property baSupplyLineWorker Auto Const Actor[] RomanceableAry Form[] WornSP1 Form[] WornSP2 int nTempCountArmorSP1 = 0 Int nTmpCountUEFiredSP1 = 0 int nTempCountArmorSP2 = 0 Int nTmpCountUEFiredSP2 = 0 Armor NudeSuitSP1 = None Armor NudeSuitSP2 = None int nTmpCurSlot = 0 Form Function FindActor(Actor akActor) ActorBase CurActor = (akActor.GetBaseObject() as ActorBase) EndFunction Event OnWorkshopObjectPlaced(ObjectReference akReference) ;Debug.MessageBox("OnWorkshopObjectPlaced Fired") RegisterForPlayerSleep() FillRomanceableAry() ;Alias_BedPC.Clear() ;Alias_BedPC.ForceRefTo(Self) StartTimer(2.0, nTimerWorker) Debug.Trace("[CompJenny Bed OnWorkshopObjectPlaced]You have " + RomanceableAry.Length + " romanceable companions.") EndEvent Event OnWorkshopObjectDestroyed(ObjectReference akActionRef) UnregisterForPlayerSleep() UnregisterForRemoteEvent(SleepPartner01, "OnItemUnequipped") ;Player could enter workshop mode after sleep and before it's unregistered UnregisterForRemoteEvent(SleepPartner02, "OnItemUnequipped") Debug.Trace("[CompJenny Bed Destroyed]" + akActionRef + " a reference destroyed and added back into workshop.") EndEvent Event OnActivate(ObjectReference akActionRef) If akActionRef == Game.GetPlayer() If RomanceableAry.Length == 0 FillRomanceableAry() If RomanceableAry.Length == 0 Return EndIf EndIf SetNotRomantic() ;Clears CA_IsRomantic on all but SleepPartner01 and 02 EndIf EndEvent Event OnExitFurniture(ObjectReference akActionRef) int nResult = 0 bool bNotRomantic = False if akActionRef == Game.GetPlayer() SetAllRomantic() ;Set CA_IsRomantic on all in the array Return EndIf If bPlayerSleeping If (akActionRef as Actor) == SleepPartner01 SleepPartner01.RemoveKeyword(CompJenny_SleepingWithPC) ElseIf (akActionRef as Actor) == SleepPartner02 SleepPartner02.RemoveKeyword(CompJenny_SleepingWithPC) EndIf Return EndIf FillRomanceableAry() If RomanceableAry.Length <= 0 Debug.Trace("[CompJenny Bed OnExitFurniture]RomanceableAry is empty.") EndIf bNotRomantic = False Actor ThisActor = (akActionRef as Actor) ;Keyword chk added to prevent messagebox when NPC hangs in bed too long. If ThisActor.HasKeyword(CompJenny_SleepingWithPC) ThisActor.RemoveKeyword(CompJenny_SleepingWithPC) Return EndIf If (ThisActor == SleepPartner01 || ThisActor == SleepPartner02) If ThisActor == SleepPartner01 CJStartUpScript.ShowSP1AssignedMsg(SleepPartner01) Else CJStartUpScript.ShowSP2AssignedMsg(SleepPartner02) EndIf Return EndIf If !IsActorInRomanticArray(akActionRef) ;This person is not romantic, do you want to assign them to this bed anyway? 0 = Yes, 1 = No if CompJennySleepCompNotRomantic.Show() == 1 Return EndIf bNotRomantic = True EndIf If SleepPartner01 == None SleepPartner01 = ThisActor If !bNotRomantic SleepPartner01.SetValue(CA_IsRomantic, 1) Debug.Trace("[CompJenny Bed ExitFurniture] SleepPartner01 CA_IsRomantic = True") Else bSP1NotRomantic = True Debug.Trace("[CompJenny Bed ExitFurniture] SleepPartner01 CA_IsRomantic = False") EndIf bBedAssignedToSP1 = False ;CJStartUpScript.SetSleepPartner1(SleepPartner01) If CJStartUpScript.AssingBedToSp1(SleepPartner01, Self) bBedAssignedToSP1 = True EndIf ElseIf SleepPartner02 == None SleepPartner02 = ThisActor If !bNotRomantic SleepPartner02.SetValue(CA_IsRomantic, 1) Debug.Trace("[CompJenny Bed ExitFurniture] SleepPartner02 CA_IsRomantic Set") Else bSP2NotRomantic = True Debug.Trace("[CompJenny Bed ExitFurniture] SleepPartner02 CA_IsRomantic = False") EndIf CJStartUpScript.SetSleepPartner2(SleepPartner02) If !bBedAssignedToSP1 CJStartUpScript.SetBedSP2(Self) EndIf ElseIf SleepPartner01 != None && SleepPartner02 != None CompJennyBedMessage_BothAlreadyAssigned.Show() Return EndIf bPlayerSleeping = false int nIdx = 0 Actor ACur = None if !RomanceableAry.Length Debug.Trace("[CompJenny Bed ExitFurniture] RomanceableAry is empty") Else Debug.Trace("[CompJenny Bed ExitFurniture] RomanceableAry.Length = " + RomanceableAry.Length as string) EndIf While nIdx < RomanceableAry.Length If RomanceableAry[nIdx] != SleepPartner01 && RomanceableAry[nIdx] != SleepPartner02 ACur = RomanceableAry[nIdx] ACur.SetValue(CA_IsRomantic, 0) EndIf nIdx += 1 EndWhile EndEvent Event OnPlayerSleepStart(float afSleepStartTime, float afDesiredSleepEndTime, ObjectReference akBed) if akBed == Self Debug.Trace("[CompJenny Bed OnPlayerSleepStart] OnPlayerSleepStart Fired") bPlayerSleeping = True bUndressCompleteSP1 = False bUndressCompleteSP2 = False If SleepPartner01 != None nTempCountArmorSP1 = 0 nTmpCountUEFiredSP1 = 0 WornSP1 = New Form[0] SleepPartner01.AddKeyword(CompJenny_SleepingWithPC) RegisterForRemoteEvent(SleepPartner01, "OnItemUnequipped") If bSP1NotRomantic NudeSuitSP1 = SkinNaked_AO Else NudeSuitSP1 = SkinNaked EndIf If SleepPartner01 == Jenny if bSP1NotRomantic NudeSuitSP1 = JennysSkinNaked_AO Else NudeSuitSP1 = JennysSkinNaked EndIf EndIf SleepPartner01.EquipItem(NudeSuitSP1 as Form, True, False) Utility.Wait(0.01) SleepPartner01.Unequipitem(NudeSuitSP1 as Form, False, False) ; Utility.Wait(0.01) ; SleepPartner01.SnapIntoInteraction(akBed) Else Debug.Trace("[CompJenny Bed PCSleepStart] SleepPartner01 = None") EndIf If SleepPartner02 != None nTempCountArmorSP2 = 0 nTmpCountUEFiredSP2 = 0 WornSP2 = New Form[0] SleepPartner02.AddKeyword(CompJenny_SleepingWithPC) RegisterForRemoteEvent(SleepPartner02, "OnItemUnequipped") If bSP2NotRomantic NudeSuitSP2 = SkinNaked_AO Else NudeSuitSP2 = SkinNaked EndIf If SleepPartner02 == Jenny if bSP2NotRomantic NudeSuitSP2 = JennysSkinNaked_AO Else NudeSuitSP2 = JennysSkinNaked EndIf EndIf SleepPartner02.EquipItem(NudeSuitSP2 as Form, True, False) Utility.Wait(0.01) SleepPartner02.Unequipitem(NudeSuitSP2 as Form, False, False) ; Utility.Wait(0.01) ; SleepPartner02.SnapIntoInteraction(akBed) Else Debug.Trace("[CompJenny Bed PCSleepStart] SleepPartner02 = None") EndIf EndIf endEvent Event Actor.OnItemUnequipped(Actor akSender, Form akBaseObject, ObjectReference akReference) If !(akBaseObject as Armor) Return EndIf IF akSender == SleepPartner01 nTmpCountUEFiredSP1 += 1 ElseIf akSender == SleepPartner02 nTmpCountUEFiredSP2 += 1 EndIf if bPlayerSleeping && akSender == SleepPartner01 nTempCountArmorSP1 += 1 If akReference != None Debug.Trace("[CompJenny Bed Unequip] Ref Item Added to WornSP1") WornSP1.Add(akReference) Else Debug.Trace("[CompJenny Bed Unequip] BaseObject Item Added to WornSP1") WornSP1.Add(akBaseObject) EndIf StartTimer(0.05, nSP1UndressComplete) ElseIf bPlayerSleeping && akSender == SleepPartner02 nTempCountArmorSP2 += 1 If akReference != None Debug.Trace("[CompJenny Bed Unequip] Ref Item Added to WornSP2") WornSP2.Add(akReference) Else Debug.Trace("[CompJenny Bed Unequip] BaseObject Item Added to WornSP2") WornSP2.Add(akBaseObject) EndIf StartTimer(0.05, nSP2UndressComplete) EndIf EndEvent Event OnPlayerSleepStop(bool abInterrupted, ObjectReference akBed) if akBed == Self ; UnregisterForPlayerSleep() If SleepPartner01 != None SleepPartner01.SnapIntoInteraction(akBed) Utility.Wait(0.01) if SleepPartner01.GetItemCount(NudeSuitSP1) > 0 SleepPartner01.RemoveItem(NudeSuitSP1, 1) EndIf If WornSP1.Length > 0 StartTimer(Utility.RandomInt(3, 6), nTimerSP1) EndIf Else Debug.Trace("[CompJenny Bed SleepStop] SleepPartner01 = None") EndIf If SleepPartner02 != None SleepPartner02.SnapIntoInteraction(akBed) Utility.Wait(0.01) if SleepPartner02.GetItemCount(NudeSuitSP2) > 0 SleepPartner02.RemoveItem(NudeSuitSP2, 1) EndIf If WornSP2.Length > 0 StartTimer(Utility.RandomInt(3, 6), nTimerSP2) EndIf Else Debug.Trace("[CompJenny Bed SleepStop] SleepPartner02 = None") EndIf SetAllRomantic() RomanceableAry.Clear() StartTimer(5, nTimerPC) EndIf endEvent Event OnTimer(int aiTimerID) If aiTimerID == nTimerPC bPlayerSleeping = False ElseIf aiTimerID == nSP1UndressComplete UnregisterForRemoteEvent(SleepPartner01, "OnItemUnequipped") bUndressCompleteSP1 = True ElseIf aiTimerID == nSP2UndressComplete UnregisterForRemoteEvent(SleepPartner02, "OnItemUnequipped") bUndressCompleteSP2 = True ElseIf aiTimerID == nTimerSP1 If SleepPartner01 != None && WornSP1.Length > 0 Int nIdx = 0 While nIdx < WornSP1.Length if WornSP1[nIdx] != NudeSuitSP1 SleepPartner01.Equipitem(WornSP1[nIdx] as Form, False, True) EndIf Utility.Wait(0.10) nIdx += 1 EndWhile Debug.Trace("[CompJenny Bed Wakeup] SP1 Armor Count = " + (nTempCountArmorSP1 as string) + ", OnUnequip fired count = " + (nTmpCountUEFiredSP1 as string) + ", SP1 Array Length = " + (WornSP1.Length as string), 0) WornSP1.Clear() EndIf ElseIf aiTimerID == nTimerSP2 If SleepPartner02 != None && WornSP2.Length > 0 Int nIdx = 0 While nIdx < WornSP2.Length if WornSP2[nIdx] != NudeSuitSP2 SleepPartner02.Equipitem(WornSP2[nIdx] as Form, False, True) EndIf Utility.Wait(0.10) nIdx += 1 EndWhile Debug.Trace("[CompJenny Bed Wakeup] SP2 Armor Count = " + (nTempCountArmorSP2 as string) + ", OnUnequip fired count = " + (nTmpCountUEFiredSP2 as string) + ", SP2 Array Length = " + (WornSP2.Length as string), 0) WornSP2.Clear() EndIf ElseIf aiTimerID == nTimerWorker If Self.GetActorOwner() == baSupplyLineWorker Self.SetActorOwner(NONE) ;Remove synth supply line worker as owner EndIf EndIf EndEvent Function SetThisNotRomantic(Actor akNotRomantic) If akNotRomantic == SleepPartner01 SleepPartner01 = SleepPartner02 SleepPartner02 = None ElseIf akNotRomantic == SleepPartner02 SleepPartner02 = None EndIf int nIdx = 0 While nIdx < RomanceableAry.Length If RomanceableAry[nIdx] == akNotRomantic RomanceableAry[nIdx].SetValue(CA_IsRomantic, 0) EndIf nIdx += 1 EndWhile EndFunction Function FillRomanceableAry() ;Builds RomanceableAry and fills it will all companions that have CA_IsRomantic set if RomanceableAry.Length > 0 SetAllRomantic() RomanceableAry.Clear() EndIf RomanceableAry = new Actor[0] ObjectReference[] CompAry = Game.GetPlayer().FindAllReferencesWithKeyword(playerCanStimpak, 5000.0) int nIdx = 0 Actor ACur = None While nIdx < CompAry.Length ;Get list of all Romantic companions ACur = (CompAry[nIdx] as Actor) If ACur.GetValue(CA_IsRomantic) > 0 RomanceableAry.Add(ACur) EndIf nIdx += 1 EndWhile EndFunction Function SetAllRomantic() ;Restores CA_IsRomantic on all NPCs in RomanceableAry if RomanceableAry.Length int nIdx = 0 While nIdx < RomanceableAry.Length RomanceableAry[nIdx].SetValue(CA_IsRomantic, 1) nIdx += 1 EndWhile EndIf EndFunction Function SetNotRomantic() ;Clears CA_IsRomantic on all but SleepPartner01 and 02 int nIdx = 0 Actor ACur = None if !RomanceableAry.Length Debug.MessageBox("RomanceableAry is empty") EndIf While nIdx < RomanceableAry.Length If RomanceableAry[nIdx] != SleepPartner01 && RomanceableAry[nIdx] != SleepPartner02 ACur = RomanceableAry[nIdx] ACur.SetValue(CA_IsRomantic, 0) EndIf nIdx += 1 EndWhile EndFunction bool Function IsActorInRomanticArray(ObjectReference akActorRef) ;If actor is in RomanceableAry, returns True, else returns False int nIdx = 0 If !RomanceableAry.Length Return false EndIf While nIdx < RomanceableAry.Length if RomanceableAry[nIdx] == (akActorRef as Actor) Return true EndIf nIdx += 1 EndWhile Return false EndFunction Link to comment Share on other sites More sharing options...
pepperman35 Posted November 28, 2020 Author Share Posted November 28, 2020 (edited) Okay for a quick test I used NPCBedHospitalNoPlayer as the bed, made an NPC, and assigned the NPC to the bed via a standard sit package. No scripting at this point. The NPC lays in the bed sideways. Anyone ever seen such wierdness and know how to fix it? Edited November 28, 2020 by pepperman35 Link to comment Share on other sites More sharing options...
Pelgar Posted November 28, 2020 Share Posted November 28, 2020 I haven't looked at how they force old Shawn into that bed but it's not designed for animated entry. Before doing the following I suggest making a copy of the bed and using it, I don' t like to make changes to vanilla assets if I can help it. Open your copy of the bed in the CK, Find Active Markers section (mid left). Select Interact Point 0 then under Markers Position/Orientation set Rot to 90. This should get the npc laying in the proper direction. If the npc sinks to deep into the bed you can adjust the Z position. You can adj. the pos. from head to foot of bed via the Y pos. Of course side to side is adjusted with X pos. Link to comment Share on other sites More sharing options...
Recommended Posts