About addressing the follower bow issue

Post » Mon Feb 18, 2013 8:50 am

I don't expect this to be of very wide interest, but I have had this approach in my head for a long time about how to deal with the follower-specific hunting bows (and iron arrows). So I thought I'd post it here this once, even if stuff like this soon falls over the edge into the abyss.

The intention has been to create a simple script, that does the following:
- Follower hunting bows do not accumulate to overburden the follower.
- Follower items are always available as a fallback if nothing else has been provided, as the game planners apparently intended.
- If any replacement item is provided, the follower items are automatically removed.
- No plugin edits are to be required, so the potential scope for mod conflicts would be relatively small.

This is the original version:
Spoiler
;  --- Add this code segment to the end of FollowerAliasScript ---;;  Every time your follower's inventory of bows or arrows changes, this script will compare their;  total number to the number of follower-specific ones carried.;;  If other bows or arrows are found, follower-specific hunting bows or iron arrows are removed.;  Otherwise, the amount of follower-specific equipment is adjusted to the standard number.;;  As no new properties are introduced in the script, no plugin edits are required.Event OnItemAdded(Form akBaseItem, int Par2, ObjectReference Par3, ObjectReference Par4)	Form KeyW = Game.GetForm(0x01E715)			; FormID: WeapTypeBow (keyword)	if akBaseItem.HasKeyword(KeyW as Keyword)		Adjust(Game.GetForm(0x10E2DD),KeyW,1)		; FormID: FollowerHuntingBow (weapon)	endif	KeyW = Game.GetForm(0x10E2DE)				; FormID: VendorItemArrow (keyword)	if akBaseItem.HasKeyword(KeyW as Keyword)		Adjust(Game.GetForm(0x0917E7),KeyW,12)		; FormID: FollowerIronArrow (ammo)	endifEndEventEvent OnItemRemoved(Form akBaseItem, int Par2, ObjectReference Par3, ObjectReference Par4)	Form KeyW = Game.GetForm(0x01E715)			; FormID: WeapTypeBow (keyword)	if akBaseItem.HasKeyword(KeyW as Keyword)		Adjust(Game.GetForm(0x10E2DD),KeyW,1)		; FormID: FollowerHuntingBow (weapon)	endif	KeyW = Game.GetForm(0x10E2DE)				; FormID: VendorItemArrow (keyword)	if akBaseItem.HasKeyword(KeyW as Keyword)		Adjust(Game.GetForm(0x0917E7),KeyW,12)		; FormID: FollowerIronArrow (ammo)	endifEndEventFunction Adjust(Form Item, Form KeyW, int Norm)	int N = FRef.GetItemCount(Item)				; Set N to number of follower items held	if FRef.GetItemCount(KeyW) == N				; No other items with the same keyword?		N = N - Norm					; Set N to excess number of items held	endif	if N							; Any adjustment required?		AddInventoryEventFilter(Game.GetForm(0xF))	; FormID: Gold001 (miscitem)		if N > 0			FRef.Removeitem(Item,N)			; Remove excess		else			FRef.Additem(Item,-N)			; Fill up		endif		RemoveAllInventoryEventFilters() 	endifEndFunction
It should work in principle, and it does so with housecarls, for example. But it fails to work properly with followers having bows (or arrows) in their original inventory as defined by the Creation Kit. The apparent reason is a game bug with GetItemCount() not counting CK-defined items (in any type of container) when used with a keyword parameter.

This is a modified version, intended to compensate for the bug:
Spoiler
;  --- Add this code segment to the end of FollowerAliasScript ---;;  Every time your follower's inventory of bows or arrows changes, this script will compare their;  total number to the number of follower-specific ones carried.;;  If other bows or arrows are found, follower-specific hunting bows or iron arrows are removed.;  Otherwise, the amount of follower-specific equipment is adjusted to the standard number.;;  As no new properties are introduced in the script, no plugin edits are required.;;  Note: The script has been modified to take into account a bug, where GetItemCount(), when used;  with a keyword parameter, does not count CK-defined items in a containerObjectReference FRef = None	; Follower reference, also used to check initialization statusint BoCK			; Initialized by DoInit(), follower's CK inventory of bowsint ArCK			; Initialized by DoInit(), follower's CK inventory of arrowsEvent OnItemAdded(Form akBaseItem, int Par2, ObjectReference Par3, ObjectReference Par4)	Form BoKW = Game.GetForm(0x01E715)			; FormID: WeapTypeBow (keyword)	Form ArKW = Game.GetForm(0x10E2DE)			; FormID: VendorItemArrow (keyword)	if !FRef		DoInit(BoKW,ArKW)	endif	if akBaseItem.HasKeyword(BoKW as Keyword)		Adjust(Game.GetForm(0x10E2DD),BoKW,BoCK,1)	; FormID: FollowerHuntingBow (weapon)	endif	if akBaseItem.HasKeyword(ArKW as Keyword)		Adjust(Game.GetForm(0x0917E7),ArKW,ArCK,12)	; FormID: FollowerIronArrow (ammo)	endifEndEventEvent OnItemRemoved(Form akBaseItem, int Par2, ObjectReference Par3, ObjectReference Par4)	Form BoKW = Game.GetForm(0x01E715)			; FormID: WeapTypeBow (keyword)	Form ArKW = Game.GetForm(0x10E2DE)			; FormID: VendorItemArrow (keyword)	if !FRef		DoInit(BoKW,ArKW)	endif	if akBaseItem.HasKeyword(BoKW as Keyword)		Adjust(Game.GetForm(0x10E2DD),BoKW,BoCK,1)	; FormID: FollowerHuntingBow (weapon)	endif	if akBaseItem.HasKeyword(ArKW as Keyword)		Adjust(Game.GetForm(0x0917E7),ArKW,ArCK,12)	; FormID: FollowerIronArrow (ammo)	endifEndEventFunction DoInit(Form BoKW, Form ArKW)	FRef = Self.GetReference()	ObjectReference Cont = FRef.PlaceAtMe(Game.GetForm(0x0EA299),1,false,true) ; FormID: UnownedChest (container)	ObjectReference Base = FRef.PlaceAtMe(FRef.GetBaseObject(),1,false,true)	Base.RemoveAllItems(Cont)	Base.Delete()	BoCK = Cont.GetItemCount(BoKW)	ArCK = Cont.GetItemCount(ArKW)	Cont.Delete()EndFunctionFunction Adjust(Form Item, Form KeyW, int Bias, int Norm)	int N = FRef.GetItemCount(Item)				; Set N to number of follower items held	if FRef.GetItemCount(KeyW) + Bias == N			; No other items with the same keyword?		N = N - Norm					; Set N to excess number of items held	endif	if N							; Any adjustment required?		AddInventoryEventFilter(Game.GetForm(0xF))	; FormID: Gold001 (miscitem)		if N > 0			FRef.Removeitem(Item,N)			; Remove excess		else			FRef.Additem(Item,-N)			; Fill up		endif		RemoveAllInventoryEventFilters() 	endifEndFunction
Based on my initial testing, it would seem to work better. There is a potential issue, however, in that nobody else has ever really bothered to verify the exact nature of the bug I am compensating for.

If you might happen to be interested in the approach enough to test it, I would appreciate your comments on whether you see it working or not.
User avatar
Jeffrey Lawson
 
Posts: 3485
Joined: Tue Oct 16, 2007 5:36 pm

Return to V - Skyrim