Jump to content

NPC Loot Bodies / Pickup Items?


TheNorthStar

Recommended Posts

  • 1 year later...

I actually added this function to a companion script where he would keep track of ammo usable by the guns he was carrying and move to dead bodies that had one or more of the ammo types on them, play a "grab" animation, and move the ammo to his inventory. The script is a LOT more complex than it sounds, and NVSE is definitely required.

 

It involves ref-walking for corpses and checking for a form list of ammo types and placing an x-marker at the corpse's location that is used as the target of a travel package and add the package to the NPC. At the end of the travel package it runs a script to play the "npc take" animation, move all ammo on the corpse to a temporary container, move everything except ammo that the NPC claimed to back to the corpse (using a form list filter for RemoveAllTypedItems), and then move everything in the temporary container to the NPC. The NPC would then ref-walk for corpses again to check for another target.

 

I'll extract the ammo-looting code from the script:

 

 

; 2 form lists are used. 'NPCweapons; holds all of the weapons the NPC is carrying.
; 'NPCammo' holds all ammo types that can be used for each of the guns in 'NPCweapons'.


; First, we populate our weapon and ammo lists. 
; The following IF block is triggered by a game restart or setting the 'invupdate' variable to 1.
; It is set to 1 any time the game enters MenuMode 1075 (companion wheel), 1008 (container), or 1053 (barter).
if((invupdate || getgameloaded) && isincombat == 0)

; Empty the weapon list
label 10
if(listgetcount NPCweapons)
	listremoventhform NPCweapons 0
	goto 10
endif

; Empty the ammo list.
label 20
if(listgetcount NPCammo)
	listremoventhform NPCammo 0
	goto 10
endif

; Next, we walk the NPC's inventory to find guns and add them to the weapon list.
set invcount to NPCref.getnumitems - 1
label 30
if(invcount > 0)

	set invitem to NPCref.getinventoryobject invcount
	set itemtype to gettype invitem
	if(itemtype == 40)					; 40 denotes a weapon of any type.
		set weaptype to getweaptype invitem
	else
		set weaptype to 0
	endif
	
	if(weaptype > 2 && weaptype < 9)	; This excludes weapons that do not use ammo.
		listaddform NPCweapons invitem
		set ammolist to getweaponammo invitem
		
		; We found a weapon that uses ammo, so now we walk the ammo list for that weapon and add all entries to the 'NPCammo' list.
		set listcount to 0
		label 40
		if(listcount < listgetcount ammolist)
			set ammoitem to listgetnthform ammolist listcount
			listaddform NPCammo ammoitem
			set listcount to listcount + 1
			goto 40
		endif
		
	endif
	
	set invcount to invcount - 1
	goto 30
endif

set invupdate to 0

endif

; Now we have our ammo list populated. Here's the section where we add the travel package to the NPC.
; 'loottarget' is a ref variable that points to the corpse where we want to place the travel target x-marker.
; Our travel package is named 'NPClootTravel'.

if(loottarget && getiscurrentpackage NPClootTravel == 0)
NPClootTravelMarkerREF.moveto loottarget
addscriptpackage NPClootTravel
else
; If the NPC isn't currently looting a target, find one to loot.
; This is done with a ref-walk in the current cell for actors.
; 'corpseref' is a reference variable for the current actor in the walk.
; 'corpsedist' is the distance from the NPC to the actor.
; 'playerdist' is the distance from the player, to leash the NPC from chaining from corpse to corpse too far away.
set numrefs to getnumrefs 200 1 0
if(numrefs > 0)
	set corpseref to getfirstref 200 1 0
	label 50
	if(corpseref && corpseref != this)	; Exclude the NPC from his own search.
		set corpsedist to getdistace corpseref
		set playerdist to player.getdistance corpsref
		if(corpsedist < 500 && playerdist < 500 && corpseref.getdead && corpseref.getitemcount NPCammo)
			set loottarget to corpseref
		endif
	endif
	set corpseref to Pencil01
	set corpseref to getnextref
	set nurmefs to numrefs -1
	if(numrefs > 0)
		goto 50
	endif
endif
endif

 

 

 

All that's left is the travel package. It has a destination set to the x-marker moved in the script above. In the Begin/End/Change tab, it sets the OnEnd idle to LooseNPCTaking and has the following result script:

 

 

 

; We need to declare a local variable here to call functions on.
ref loottarget
set lootarget to NPCref.loottarget

; Because RemoveAllTypedItems uses the 'blacklist' method for filtering using a list, we use a temporary container.

loottarget.removealltypeditems NPClootTempBoxREF 0 1 41
NPClootTempBoxREF.removealltypeditems NPCref 01 41 NPCammo
NPClootTempBoxREF.removeallitems NPCref

set NPCref.loottarget to 0

 

 

 

This is the skeleton of the method I devised, and there's probably an easier/faster way to get the same thing done. The script I use is a bit more complex, with the NPC looting ammo for the player also and either bringing it to them or throwing it to them if they are some distance away.

 

If you want to see it in action, you can download LCWE (FNV) from the link in my signature and hire the "Mysterious Kid" companion. It's a work-in-progress.

Edited by luthienanarion
Link to comment
Share on other sites

  • 1 year later...

I actually added this function to a companion script where he would keep track of ammo usable by the guns he was carrying and move to dead bodies that had one or more of the ammo types on them, play a "grab" animation, and move the ammo to his inventory. The script is a LOT more complex than it sounds, and NVSE is definitely required.

 

It involves ref-walking for corpses and checking for a form list of ammo types and placing an x-marker at the corpse's location that is used as the target of a travel package and add the package to the NPC. At the end of the travel package it runs a script to play the "npc take" animation, move all ammo on the corpse to a temporary container, move everything except ammo that the NPC claimed to back to the corpse (using a form list filter for RemoveAllTypedItems), and then move everything in the temporary container to the NPC. The NPC would then ref-walk for corpses again to check for another target.

 

I'll extract the ammo-looting code from the script:

 

 

; 2 form lists are used. 'NPCweapons; holds all of the weapons the NPC is carrying.
; 'NPCammo' holds all ammo types that can be used for each of the guns in 'NPCweapons'.


; First, we populate our weapon and ammo lists. 
; The following IF block is triggered by a game restart or setting the 'invupdate' variable to 1.
; It is set to 1 any time the game enters MenuMode 1075 (companion wheel), 1008 (container), or 1053 (barter).
if((invupdate || getgameloaded) && isincombat == 0)
	
	; Empty the weapon list
	label 10
	if(listgetcount NPCweapons)
		listremoventhform NPCweapons 0
		goto 10
	endif
	
	; Empty the ammo list.
	label 20
	if(listgetcount NPCammo)
		listremoventhform NPCammo 0
		goto 10
	endif
	
	; Next, we walk the NPC's inventory to find guns and add them to the weapon list.
	set invcount to NPCref.getnumitems - 1
	label 30
	if(invcount > 0)
	
		set invitem to NPCref.getinventoryobject invcount
		set itemtype to gettype invitem
		if(itemtype == 40)					; 40 denotes a weapon of any type.
			set weaptype to getweaptype invitem
		else
			set weaptype to 0
		endif
		
		if(weaptype > 2 && weaptype < 9)	; This excludes weapons that do not use ammo.
			listaddform NPCweapons invitem
			set ammolist to getweaponammo invitem
			
			; We found a weapon that uses ammo, so now we walk the ammo list for that weapon and add all entries to the 'NPCammo' list.
			set listcount to 0
			label 40
			if(listcount < listgetcount ammolist)
				set ammoitem to listgetnthform ammolist listcount
				listaddform NPCammo ammoitem
				set listcount to listcount + 1
				goto 40
			endif
			
		endif
		
		set invcount to invcount - 1
		goto 30
	endif
	
	set invupdate to 0
	
endif

; Now we have our ammo list populated. Here's the section where we add the travel package to the NPC.
; 'loottarget' is a ref variable that points to the corpse where we want to place the travel target x-marker.
; Our travel package is named 'NPClootTravel'.

if(loottarget && getiscurrentpackage NPClootTravel == 0)
	NPClootTravelMarkerREF.moveto loottarget
	addscriptpackage NPClootTravel
else
	; If the NPC isn't currently looting a target, find one to loot.
	; This is done with a ref-walk in the current cell for actors.
	; 'corpseref' is a reference variable for the current actor in the walk.
	; 'corpsedist' is the distance from the NPC to the actor.
	; 'playerdist' is the distance from the player, to leash the NPC from chaining from corpse to corpse too far away.
	set numrefs to getnumrefs 200 1 0
	if(numrefs > 0)
		set corpseref to getfirstref 200 1 0
		label 50
		if(corpseref && corpseref != this)	; Exclude the NPC from his own search.
			set corpsedist to getdistace corpseref
			set playerdist to player.getdistance corpsref
			if(corpsedist < 500 && playerdist < 500 && corpseref.getdead && corpseref.getitemcount NPCammo)
				set loottarget to corpseref
			endif
		endif
		set corpseref to Pencil01
		set corpseref to getnextref
		set nurmefs to numrefs -1
		if(numrefs > 0)
			goto 50
		endif
	endif
endif

 

 

All that's left is the travel package. It has a destination set to the x-marker moved in the script above. In the Begin/End/Change tab, it sets the OnEnd idle to LooseNPCTaking and has the following result script:

 

 

 

; We need to declare a local variable here to call functions on.
ref loottarget
set lootarget to NPCref.loottarget

; Because RemoveAllTypedItems uses the 'blacklist' method for filtering using a list, we use a temporary container.

loottarget.removealltypeditems NPClootTempBoxREF 0 1 41
NPClootTempBoxREF.removealltypeditems NPCref 01 41 NPCammo
NPClootTempBoxREF.removeallitems NPCref

set NPCref.loottarget to 0

 

 

This is the skeleton of the method I devised, and there's probably an easier/faster way to get the same thing done. The script I use is a bit more complex, with the NPC looting ammo for the player also and either bringing it to them or throwing it to them if they are some distance away.

 

If you want to see it in action, you can download LCWE (FNV) from the link in my signature and hire the "Mysterious Kid" companion. It's a work-in-progress.

 

your example helps alot, but i have easier situation when need to find dead bodies around and loot them

only thing what i want to ask :

why you set

 

set invcount to NPCref.getnumitems - 1

why this "-1" is used here?

getnumitems return 0 if npc contain 0 items.

Link to comment
Share on other sites

why this "-1" is used here?

getnumitems return 0 if npc contain 0 items.

The 'invcount' variable is used as an index key for GetInventoryObject, which starts at index 0, so you must subtract 1 from the value returned by GetNumItems. For instance, if a container has 30 items in it, they are numbered 0-29.

The sanity check right below that should actually be:

if(invcount > -1)
(This is a really old script that I should revisit one of these days...)
Link to comment
Share on other sites

  • 5 years later...
  • 1 year later...

Sorry for necro, but it has been 5+ years now, and is there a mod out there now, which makes NPC's go loot corpses?

 

https://www.nexusmods.com/newvegas/mods/35462?tab=description This actually makes npcs to loot corpses but they use ammo instead. I would love to disable this function and leave unlimited ammo as default but able to loot enemy/friend corpses for better weapons, simp packs, food and so on

Link to comment
Share on other sites

  • Recently Browsing   0 members

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