Jump to content

I need help trying to port a Fallout 4 mod to Skyrim where npcs can loot bodies.


Recommended Posts

Hello. I'm trying to port this Fallout 4 mod called "NPC Loot bodies", which is quite effective and works all the time. I know there is this mod https://www.nexusmods.com/skyrimspecialedition/mods/33826  but i've never seen an npc to loot any bodies, even when i removed the condition for "banditfaction" so everyone can loot, but it just doesn't work. "NPC Loot bodies" works always, well as long as there is a living npc around the area.

I'm struggling with this script that goes attached to the quest that controls the looting:

Scriptname TEMP_S extends Quest

Group Looters
ReferenceAlias Property Alias_Looter Auto Const
endGroup

Group Corpses
ReferenceAlias Property Alias_Body01 Auto Const
endGroup

Group Quests
Quest Property TEMP_Q_for_Aliases Auto Const
Quest Property TEMP_Q Auto Const
endGroup

Group Globals
GlobalVariable Property TEMP_G_01 Auto Const
GlobalVariable Property TEMP_G_PackageFinished Auto Const
endGroup

Group Keywords
Keyword Property TEMP_K_Looted Auto Const
endGroup


Event OnQuestInit()
	StartAliasQuest()		;START the quest TEMP_Q_for_Aliases. Corpse alias fill conditions are there. The Alias_Body01 ref alias on this quest is linked to that ref alias.
EndEvent


Function StartAliasQuest()

	if TEMP_Q_for_Aliases.IsRunning() == 1		;failsafe
		TEMP_Q_for_Aliases.Stop()
	endif

	Utility.Wait(0.5)		;wait for stopping...

	if TEMP_Q_for_Aliases.IsRunning() == 0		;Start the alias quest
		TEMP_Q_for_Aliases.Start()
		debug.notification("Alias quest started")
	endif

	Utility.Wait(0.5)		;wait for the aliases to get filled...

	If Alias_Body01.GetReference() == none
		;Alias has not been filled (fill conditions are not met)
		debug.notification("Alias is NOT filled, start loot timer")
		StartTimer(20, 255)			;try to start the alias quest again. (LOOP timer)
	Else
		debug.notification("Alias is filled, StartLoot()")
		StartLoot()
	EndIf

EndFunction




Event OnTimer(int aiTimerID)
	if aiTimerID == 255		;LOOP timer
		StartAliasQuest()
		debug.notification("LOOP timer expired")
	EndIf
	If aiTimerID == 555		;FALSE TIMER: if the actor can't loot the body in 60 seconds, abort the package
		End_Loot()
		debug.notification("aiTimerID 555 expired")
	Endif
EndEvent






Function StartLoot()

	TEMP_G_01.SetValueInt(1)		;for the packages

	(Alias_Looter.GetReference() as Actor).EvaluatePackage()

	StartTimer(60, 555)		;failsafe: if the looter can't path to the body, abort the package

	;WAIT FOR PACKAGE STOP

EndFunction



Function End_loot()		;called from package "on end" fragment / falsafe timer (ID: 555)

	If TEMP_G_PackageFinished.GetValueInt() == 0					;function was called from the falsafe timer
	
		debug.notification("END loot called from FALSAFE TIMER")
	
		if TEMP_Q_for_Aliases.IsRunning() == 1
			TEMP_Q_for_Aliases.Stop()
			debug.notification("Alias quest stopped")
		endif
	
		TEMP_G_01.SetValueInt(0)

		TEMP_G_PackageFinished.SetValueInt(0)

		StartTimer(2, 255)			;start again LOOP timer. For the failsafe timer, no need for 20 seconds.

	ElseIf TEMP_G_PackageFinished.GetValueInt() == 1		;		;function was called from the package "on end" fragment

		LootProcedure()

		MarkBodyAsLooted()

		debug.notification("END loot called from PACKAGE")
	
		if TEMP_Q_for_Aliases.IsRunning() == 1
			TEMP_Q_for_Aliases.Stop()
			debug.notification("Alias quest stopped")
		endif
	
		TEMP_G_01.SetValueInt(0)

		StartTimer(10, 255)			;start again LOOP timer

	EndIf

EndFunction




Function MarkBodyAsLooted()

	debug.notification("MarkBodyAsLooted() running")

	;AliasColl_LootedBodies.AddRef((Alias_Looter.GetReference() as Actor))		;add looted bodies to a ref coll alias. Ref coll actors have a keyword that prevents the looter from looting them again. Remove the looted bodies one by one with a Game Timer.

	LootedBody_01_Actor = (Alias_Body01.GetReference() as Actor)

	LootedBody_01_Actor.AddKeyword(TEMP_K_Looted)

	StartTimerGameTime(0.5, 355)		;looted body has to have this keyword for at least two hours. (so looter won't loot this body in this period).

EndFunction


Actor LootedBody_01_Actor


Event OnTimerGameTime(int aiTimerID)		
	If aiTimerID == 355

		RemoveLootedBody()

	EndIf
EndEvent

Function RemoveLootedBody()

	debug.notification("RemoveLootedBody() Timer expired")

	LootedBody_01_Actor.RemoveKeyword(TEMP_K_Looted)

EndFunction




Function LootProcedure()		;called rom package "on end" fragment. This is the actual "loot function".

	If (Alias_Body01.GetReference()) != none && (Alias_Looter.GetReference()) != none

		(Alias_Body01.GetReference() as Actor).RemoveAllItems((Alias_Looter.GetReference() as actor))

		debug.notification("Looted!")

	;DEBUGGING...

	ElseIf (Alias_Body01.GetReference()) == none && (Alias_Looter.GetReference()) != none

		debug.notification("Alias_Body01 is none!")

	ElseIf (Alias_Body01.GetReference()) != none && (Alias_Looter.GetReference()) == none

		debug.notification("Alias_Looter is none!")

	ElseIf (Alias_Body01.GetReference()) == none && (Alias_Looter.GetReference()) == none

		debug.notification("Alias_Body01 AND Looter are none!")

	EndIf

EndFunction




Since there are no "Timers" in Skyrim's engine, and i don't know much about coding, i feel lost. I wonder if someone knows of a way to replace the timer functions with some Skyrim equivalent to make this madness work, if it's possible.

I love how it works in FO4, npcs just run and get the looting, wherever the bodies are. Makes for some quite hilarious circumstances, my favorite one is when i kill someone and put a mine in his body and just wait 😛.

Here i attach the mod in question. Remember it's a Fallout4 mod, the use i get from it is to check how the aliases get filled, the quest that makes all the magic and the package involved for the looting, plus the scripts.

NPCLootBodies.zip

Link to comment
Share on other sites

Likely won't be able to "port" the mod, but rather reproduce it as feasible

If I was tackling this project today, first approach I would go with, is AI ObserveDead routine where the NPC using this routine, will approach lootable bodies and perhaps perform a search animation like they will when saying "What happened?" etc. Let scripts handle the actual looting, and also have the script apply some sort of tag to prevent NPCs from trying to repeat loot, etc

I was curious so played with above for a little bit. ObserveDead override pack apparently is a dud or has quirks and too many hoops to jump through to be a viable approach. Aside, I found a mod you can use as a template for the concept you want. Haven't tried it myself but it can at least get you started, if not completely do what you are wanting

https://www.nexusmods.com/skyrimspecialedition/mods/4744

 

Edited by Sphered
Link to comment
Share on other sites

Thank you for the response, but i feel like the other mod i checked already try to use this method, but npcs almost never loot bodies, the other mod i checked is this by the same author of "looting bandits" https://www.nexusmods.com/skyrimspecialedition/mods/34597. I've seen several animals eating bodies with that mod, and i even changed the script so they remove all items from the corpes they eat (they are gone forever), but they have to literally step onto a body to do the looting, they won't run to eat a corpse and that's what i love from the "npc loot bodies" mod from FO4, they ran from a distance just to get the body, they are interrupted by combat so they don't go blindly and foolishly to try to loot. I even added once a bait item that when dropped spawned an invisible corpse that could attract surrounding animals, but i lost it a couple years ago.

I don't know, maybe it's not possible. My question was more about if it was possible to port the mod as it is rather than change the method because as i said before other similar mods already do this but they don't work the way i hope, it's too much a hit or miss at least on my end.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...