qwertypol012 Posted January 13, 2019 Share Posted January 13, 2019 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 More sharing options...
IsharaMeradin Posted January 13, 2019 Share Posted January 13, 2019 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 EndFunctionPlease 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 More sharing options...
qwertypol012 Posted January 14, 2019 Author Share Posted January 14, 2019 (edited) 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 January 14, 2019 by qwertypol012 Link to comment Share on other sites More sharing options...
IsharaMeradin Posted January 14, 2019 Share Posted January 14, 2019 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. Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 14, 2019 Author Share Posted January 14, 2019 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 More sharing options...
foamyesque Posted January 14, 2019 Share Posted January 14, 2019 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 EndFunctionPlease 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 More sharing options...
IsharaMeradin Posted January 14, 2019 Share Posted January 14, 2019 @foamyesqueOriginal 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. @qwertypol012You 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 More sharing options...
foamyesque Posted January 15, 2019 Share Posted January 15, 2019 (edited) @foamyesqueOriginal 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 January 15, 2019 by foamyesque Link to comment Share on other sites More sharing options...
qwertypol012 Posted January 15, 2019 Author Share Posted January 15, 2019 @ IsharaMeradin Thanks :smile: @foamyesque yeah i'm glad i stumbled into those functions, really useful Link to comment Share on other sites More sharing options...
Recommended Posts