Jump to content

[LE] Is it possible to copy player's weapon(s) into some NPCs and make them equip it?


Recommended Posts

I'm currently finishing my WIP script which i have posted in some topic in this forum thread. I stumbled into something i have no clue about yet: copying the player's weapons (or gears in general) into a NPC (or more NPCs) and they'll equip it. It's probably possible using properties which call for the weapons, but i don't think it's applicable to any weapons (eg. weapons from mods).

So, is there any way to do it? If so, any clue or guide on it are really appreciated. Thanks in advance! :smile:

Link to comment
Share on other sites

Slow and cumbersome but gets everything.

Cycle the player's inventory, get their currently equipped gear, add a copy of that to the target NPC. Then either let the NPC equip as desired based on whether it is better than their current gear or force equip (but might get removed if they have something better in their inventory).

REQUIRES SKSE

Function CopyAndGivePlayerGearToTarget(Actor akTarget)
  Actor PlayerRef = Game.GetPlayer()
  Int Num = PlayerRef.GetNumItems()
  While Num > 0
    Num -= 1
    Form Entry = PlayerRef.GetNthForm(Num)
    If Entry as Weapon || Entry as Armor || Entry as Ammo ;only deal with equip-able gear
      If Entry.IsEquipped()
        akTarget.AddItem(Entry,1)
        ;force equip here if desired
      EndIf
    EndIf
  EndWhile
EndFunction

Please note that this method will take longer and longer to process depending upon how much stuff the player may be carrying. NOT hoarder friendly.

Link to comment
Share on other sites

Thanks Ishara,

I actually figured it out myself last night, but couldn't update it here yet. So here's what i wrote in the script:

Scriptname Berserk_Loose_Control_Script extends Quest Conditional
;...other stuffs in the script
;...other stuffs in the script
;...other stuffs in the script
function copy_player_gears_to_replacement ()
  ObjectReference PlayerRef = Game.GetPlayer()
  If BerserkerRef == NONE
    return
  EndIf
  If (PlayerRef.GetWornForm(0x00000200) != None)
	  Armor Shield = PlayerRef.GetWornForm(0x00000200) as Armor
	  BerserkerRef.AddItem(Shield, absilent=true)
	  BerserkerRef.EquipItem(Shield, true, true)
;     Debug.MessageBox("...")
  EndIf
  If (PlayerRef.GetEquippedWeapon() != None)
	  Weapon Weapons = PlayerRef.GetEquippedWeapon() as Weapon
	  BerserkerRef.AddItem(Weapons, absilent=true)
	  BerserkerRef.EquipItem(Weapons, true, true)
;     Debug.MessageBox("...")
  EndIf
  If (PlayerRef.GetEquippedSpell(0) != None)
	  Spell LSpell = PlayerRef.GetEquippedSpell(0) as Spell
	  BerserkerRef.AddSpell(LSpell)
	  BerserkerRef.EquipSpell(LSpell, 0)
;     Debug.MessageBox("...")
  EndIf
  If (PlayerRef.GetEquippedSpell(1) != None)
	  Spell RSpell = PlayerRef.GetEquippedSpell(1) as Spell
	  BerserkerRef.AddSpell(RSpell)
	  BerserkerRef.EquipSpell(RSpell, 1)
;     Debug.MessageBox("...")
  EndIf
  If (PlayerRef.GetEquippedSpell(2) != None)
	  Spell OSpell = PlayerRef.GetEquippedSpell(2) as Spell
	  BerserkerRef.AddSpell(OSpell)
	  BerserkerRef.EquipSpell(OSpell, 2)
;     Debug.MessageBox("...")
  EndIf
  If (PlayerRef.GetEquippedShout() != None)
	  Shout Shouts = PlayerRef.GetEquippedShout() as Shout
	  BerserkerRef.AddShout(Shouts)
	  BerserkerRef.EquipShout(Shouts)
;     Debug.MessageBox("...")
  EndIf
endfunction

It's different with your method above. How does it sound?

 

Note: BerserkerRef is the NPC replacer i was talking about. I want to copy the player's equipped things into him/her.

 

Edit: I noticed that your method has ammo check while mine doesn't. Will it work if i only use GetEquippedWeapon() for ammo? Or how do i check it if it doesn't?

Edited by qwertypol012
Link to comment
Share on other sites

If all you want are the hand held items, then what you've got looks fine. What I posted would not include spells but then spells were not mentioned in the first post.

Yeah, sorry for not telling about spell because i initially didn't think about adding it. But after finding some functions to get spells and even shouts, i decided to include it. Now, do i need to add your function for Ammo check only since i couldn't see any ammo check in my script?

Link to comment
Share on other sites

Slow and cumbersome but gets everything.

Cycle the player's inventory, get their currently equipped gear, add a copy of that to the target NPC. Then either let the NPC equip as desired based on whether it is better than their current gear or force equip (but might get removed if they have something better in their inventory).

REQUIRES SKSE

Function CopyAndGivePlayerGearToTarget(Actor akTarget)
  Actor PlayerRef = Game.GetPlayer()
  Int Num = PlayerRef.GetNumItems()
  While Num > 0
    Num -= 1
    Form Entry = PlayerRef.GetNthForm(Num)
    If Entry as Weapon || Entry as Armor || Entry as Ammo ;only deal with equip-able gear
      If Entry.IsEquipped()
        akTarget.AddItem(Entry,1)
        ;force equip here if desired
      EndIf
    EndIf
  EndWhile
EndFunction

Please note that this method will take longer and longer to process depending upon how much stuff the player may be carrying. NOT hoarder friendly.

 

If you're using SKSE, there's GetWornForm() and some bitmask magic that will save you needing to cycle through the entire inventory. You can also speed your approach up without using GetNthForm and replacing it with GetContainerForms, a (undocumented on wiki, last I looked) function that dumps the entire form list into a Form array, which you can then iterate through much much faster.

 

Also, once complete, you could then just run incrementals whenever a player equips or unequips something, if you wanted to maintain a continuously updated setup.

Link to comment
Share on other sites

@foamyesque

Original poster already noted all that. I too was aware of those functions but have not really used them to fully understand them and find that the "bitmask magic" is confusing to say the least especially when one considers mod added gear or gear that uses more than one body slot.

 

@qwertypol012

You won't need to loop through the player inventory to just get ammo. That would be a waste of processing for just one item. Plus that block is more for those situations where the mod was just added and you need to know "right now" what is equipped. In the long run, it is smarter to maintain an updated database of equipped items. GetEquippedWeapon only works on weapons. Ammo is its own thing and cannot be captured by any of the "GetEquipped" functions.

 

Something you could do for ammo

 

 

Player alias script

Scriptname PlayerAliasScript Extends ReferenceAlias

Formlist Property WornAmmoList Auto
;this list starts out empty, gets filled as ammo is equipped by the player

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
	If akBaseObject as Ammo 
		WornAmmoList.AddForm(akBaseObject)
	EndIf
EndEvent

Your quest script

Scriptname Berserk_Loose_Control_Script extends Quest Conditional
;...other stuffs in the script
;...other stuffs in the script
;...other stuffs in the script

Formlist Property WornAmmoList Auto

Form Function GetWornAmmo(Formlist AmmoList)
	Form Entry = NONE
	Int index = 0
	While index < AmmoList.GetSize()
		Entry = AmmoList.GetAt(Index)
		If Entry.IsEquipped()
			index = AmmoList.GetSize() 	; got what we need stop loop
		Else
			Entry = NONE	; erase stored entry as we do not need it
		EndIf
		index += 1
	EndWhile
	Return Entry
EndFunction


function copy_player_gears_to_replacement ()
	ObjectReference PlayerRef = Game.GetPlayer()
	If BerserkerRef == NONE
		return
	EndIf
	
	Form WornAmmo = GetWornAmmo(WornAmmoList)
	If WornAmmo ;valid ammo
		BerserkerRef.AddItem(WornAmmo,100) ;could get count of ammo on player or just give a fixed ammount that should last the durration of the berseker status
		BerserkerRef.EquipItem(WornAmmo)
	EndIf

	; other stuff
EndFunction

 

 

 

 

Link to comment
Share on other sites

@foamyesque

Original poster already noted all that. I too was aware of those functions but have not really used them to fully understand them and find that the "bitmask magic" is confusing to say the least especially when one considers mod added gear or gear that uses more than one body slot.

 

That's the beauty of the SKSE slotmask stuff: It will work on anything added by mods or occupying multiple slots; that's what it is designed to do. Conceptually it's just a stack of boolean values, one for each slot, that says whether the armour in question uses that slot. Consider it like a one-dimensional bool array, with 32 elements.

 

You check and see if the first slot has anything equipped into it. If it does, you get a list of all the slots that item occupies, and set all those booleans to true. Then you check the next slot. If it's already been set to true, move to the next. If it hasn't, check and see if there's anything equipped in it, etc. Using a bitmask instead of an array means you can do these operations with simple arithmetic and bitwise ANDs instead of array-specifc indices and loops and so on. They're a very useful tool to learn -- both for modding Skyrim and for programmatic stuff in general.

 

(I just got done building a full-on ASCII text display thingie in Factorio that makes extensive use of these, for example)

Edited by foamyesque
Link to comment
Share on other sites

  • Recently Browsing   0 members

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