Jump to content

Checking Items Added to Player Inventory as a Repeatable Trigger


lucidaxe

Recommended Posts

Hello all,

 

I've made a few basic mods in Skyrim's Creation Kit that modified items and item lists, but now I wanted to dig into making a scripted mod. I've never used scripting before and I have to say the amount of material on it is very overwhelming... and the amount of topics that are 'kinda sorta but not really' about what I want to achieve just end up making me more uncertain. So, I figured I'd ask for help directly.

 

For info, the general idea of my mod is: I'd like low damage arrows in the player inventory to automatically be converted over to the highest damage arrow present in the player inventory, according to the conversion rate below.

 

1 Dragonbone Arrow = 2 Daedric Arrow = 4 Ebony Arrow (or Stalhrim Arrow) = 8 Glass Arrow = 16 Elven Arrow (or variant) = 32 Dwarven Arrow (or Nordic Arrow) = 64 Orcish Arrow = 128 Steel Arrow (or Ancient Nord Arrow/Riekling Spear) = 256 Iron Arrow = 512 Falmer Arrow (or Forsworn Arrow)

 

I started this topic specifically based on the fact that I want a script to run whenever one of the aforementioned types of arrows is added to the player inventory. The script should then check how many of each arrow type the player has in their inventory, and whether they have enough of said arrows that a conversion can occur. As a side note, I foresee several challenges with the general concept and I know that the mod will need tweaking and testing. Right now I am only interested in learning how best to go about creating such a trigger.

 

Goals:

- The trigger should only activate if one or more Daedric Arrow, Ebony Arrow, Stalhrim Arrow, Glass Arrow, Elven Arrow, Bloodcursed Elven Arrow, Sunhallowed Elven Arrow, Dwarven Arrow, Nordic Arrow, Orcish Arrow, Steel Arrow, Ancient Nord Arrow, Riekling Spear, Iron Arrow, Falmer Arrow, or Forsworn Arrow are added to the player inventory. No other items should cause the script to activate.

- The script should perform that trigger check every time one of those items is added to the player inventory (repeatable!).

 

Questions/Remarks:

- I would like to create the mod using only CreationKit. Is this feasible or is SKSE is necessary for this kind of functionality?

- Is it necessary to create a quest to support the scripting? I'm hesitant to add this because I feel like it creates the possibility for missing data to stay behind floating in someone's savegame if they remove the mod - I just like to keep things clean. Can the script be attached to an object and asked to run when an event occurs instead, without the need for a dummy quest?

- Should the trigger (if item added to inventory) and the rest of the steps (item count check / conversion of items) all be split up into separate scripts each somehow linking to each other, or can all of the coding be put into one big script ((Event - check - action) attached directly to the player inventory, or indirectly to a reference that forwards to the player inventory?

- Please share example coding schemes if you are willing, and please be as descriptive as possible on the steps to take since it's easy to skip ahead in your mind when you already know how it works, but... I really, really don't know very much just yet. It's not even really clear to me how I should begin.

Link to comment
Share on other sites

You will need a quest record with a player alias entry on that quest. It should be set up to be start game enabled. Quest records are used for so much more than handling the quests that the player can pursue. If you are concerned about the player removing the mod mid-game, do not be. Almost any mod that includes an ESP can screw up a player's game if they remove it. Problems arising from players doing stupid stuff to their game is on them and not you.

 

This is the simplest script, that I can think of, to do what you want for just two arrows. No SKSE involved.

 

 

Scriptname ArrowConvertPlayerScript Extends ReferenceAlias

Ammo Property ArrowOne Auto
Ammo Property ArrowTwo Auto

Int Property ConvertQty Auto
{Enter number of arrows required for ArrowTwo to become ArrowOne}

Actor PlayerRef

Event OnInit()
  PlayerRef = Game.GetPlayer()
  AddInventoryEventFitler(ArrowTwo)
  ConvertArrows(ArrowTwo,ArrowOne,ConvertQty)
EndEvent

Function ConvertArrows(Form OldArrow, Form NewArrow, Int Qty)
  While PlayerRef.GetItemCount(OldArrow) > Qty
    PlayerRef.RemoveItem(OldArrow,Qty)
    PLayerRef.AddItem(NewArrow,1)
  EndWhile
EndFunction


Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
  If akBaseItem as Ammo == ArrowTwo  
  ;the filter should ensure that only the correct arrow triggers the event but best to be safe and double check
  	ConvertArrows(ArrowTwo,ArrowOne,ConvertQty)
  EndIf
EndEvent

 

 

 

But you want to do it with a larger set of arrows and for that you will need even more records. You will need one formlist that has the ammo you want to work with listed in a specific order. You will also need an integer array on the script. The array will contain the quantities for converting. Indexes need to match up. So index 0 on the array will be the number of arrows from index 0 on the formlist required to make the arrow on index 1 of the formlist.

 

 

Scriptname ArrowConvertPlayerScript Extends ReferenceAlias

FormList Property TheArrows Auto
{list of arrows going from lowest damage to highest}

Int[] Property ConvertQty Auto
{array of integers assign the conversion values required for the ammo in the matching formlist index}
;note highest damage arrow should be given a value of 0 so that both the formlist and array can have matching index sizes / lengths

Actor PlayerRef

Event OnInit()
  PlayerRef = Game.GetPlayer()
  AddInventoryEventFilter(TheArrows)
  ConvertArrows()
EndEvent

Function ConvertArrows()
  Int index = 0
  While index < TheArrows.GetSize()
    Form Entry = TheArrows.GetAt(index)
    While (PlayerRef.GetItemCount(Entry) >= ConvertQty[index]) && (ConvertQty[index] != 0)
      PlayerRef.RemoveItem(Entry,ConvertQty[index])
      Int NewArrow = index + 1
      PlayerRef.AddItem(TheArrows.GetAt(NewArrow),1)
    EndWhile
    index += 1
  EndWhile
EndFunction

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
  If TheArrows.HasForm(akBaseItem)
    ConvertArrows()
  EndIf
EndEvent

 

 

 

What this should do is as arrows are added to the player, the ConvertArrows custom function is called. The list is then cycled with a check to determine if the incoming arrow quantity is greater than the conversion amount and that the conversion amount is non-zero. If it is, convert by removing the required amount and adding one of the next arrow. Then the list checks the next arrow and repeats until all arrows have been converted as high as possible.

 

Furthermore calling the ConvertArrows function in the OnInit block allows the players currently held arrows to be converted as soon as the quest is initially started.

 

This is the "simplest". It may be desired to prevent function during combat as on occasion I have noticed arrows added to inventory after being hit. It may also be desired to prevent it from happening until no longer in container menus or shop menus but that would require SKSE to catch the menu closing event.

 

Formlists are a record created and filled in the Creation Kit

Array properties are created by adding [] to the end of the property type when editing the script code. It can then be filled using the Creation Kit's property window. If editing the code inside the Creation Kit be sure to compile and save the script and then exit the quest record and reopen it to ensure the property entries get updated.

Link to comment
Share on other sites

Thanks a lot for that information. I'll need to look into a whole lot more than I have, it seems... and I guess I can't really separate the question into how a trigger should work without taking into account the entirety of what the mod should do.

 

 

What this should do is as arrows are added to the player, the ConvertArrows custom function is called. [...] Then the list checks the next arrow and repeats until all arrows have been converted as high as possible.

 

It may seem unintuitive, but this is not exactly what I'm trying to achieve. I'm not trying to convert all arrows to as high damage arrows as possible, because I'd like to avoid, as much as possible, for any arrow type to appear in the player inventory that wasn't already there. Instead, I'd like the script to establish what is the highest damage arrow present in the inventory, and then once that is established look at each lower damage arrow type present and convert each of those present to that one, highest damage arrow type if the amount reaches the conversion threshold.

 

Rank 1: Forsworn Arrow, Falmer Arrow

Rank 2: Iron Arrow

Rank 3: Steel Arrow, Ancient Nord Arrow, Riekling Spear (DLC)

Rank 4: Orcish Arrow

Rank 5: Dwarven Arrow, Nordic Arrow (DLC)

Rank 6: Elven Arrow, Bloodcursed Elven Arrow (DLC), Sunhallowed Elven Arrow (DLC)

Rank 7: Glass Arrow

Rank 8: Ebony Arrow, Stalhrim Arrow (DLC)

Rank 9: Daedric Arrow

Rank 10: Dragonbone Arrow

 

E.g. the script detects 6 Falmer Arrows and 1 Steel Arrow in the player inventory. The script converts the 6 Falmer Arrows into 1 additional Steel Arrow (= 4 Falmer Arrows) and leaves 2 Falmer Arrows. It does not convert the Falmer arrow to any other type (such as Iron).
I'd like detection and conversion to be step-by-step if possible. As you can see, there's also multiple possible arrow types that are equivalent in damage rank, and so would theoretically all be target arrows 'to convert to'. I figured I could put a few more conversion rules in place in order to allow conversion to follow a relatively straightforward step-by-step (if... else...) branching path, and also to tackle some issues.
RULES REGARDING CONVERSION TARGET: If the player has more than one type of arrow belonging to the same damage rank, and if that damage rank is the highest present in the player's inventory, then for ease of programming I propose that one arrow type will be chosen as the 'standard' conversion target (= arrow type to convert to) depending on the circumstances. Specifically...
Rank 3: Steel Arrow, Ancient Nord Arrow, Riekling Spear (DLC)
The Riekling Spear has inferior velocity and range to the other arrow types and should never be converted to - if the player only has this arrow type as the highest damage one, then lower damage arrow should be converted to Steel Arrows instead. If the player has some Ancient Nord Arrows (but no Steel Arrows) as their highest damage arrow, then lower damage arrows should be converted to Ancient Nord Arrows. But if the player also or exclusively has some Steel Arrows in any capacity, then lower damage arrows should be converted to Steel Arrows.
Riekling Spear -> conversion target Steel Arrow
Riekling Spear + Ancient Nord Arrow -> conversion target Ancient Nord Arrow
Riekling Spear + Steel Arrow -> conversion target Steel Arrow
Ancient Nord Arrow -> conversion target Ancient Nord Arrow
Steel Arrow + Ancient Nord Arrow -> conversion target Steel Arrow
Steel Arrow -> conversion target Steel Arrow
Rank 5: Dwarven Arrow, Nordic Arrow (DLC)
If the player only has Nordic Arrows as their highest damage arrow, then lower damage arrows should be converted to Nordic Arrows. However, if the player also (or exclusively) has some Dwarven Arrows, then lower damage arrows should be converted to Dwarven Arrows.
Nordic Arrow -> conversion target Nordic Arrow
Nordic Arrow + Dwarven Arrow -> conversion target Dwarven Arrow
Dwarven Arrow -> conversion target Dwarven Arrow
Rank 6: Elven Arrow, Bloodcursed Elven Arrow (DLC), Sunhallowed Elven Arrow (DLC)
Elven Arrows can always be converted to the Bloodcursed or Sunhallowed variants by NPCs from the DLC if the player wants it. Thus, if the player has any arrow type from this rank as their highest damage arrow(s), lower damage arrows should always only be converted to Elven Arrows.
Any arrow(s) of this rank -> conversion target Elven Arrow
Rank 8: Ebony Arrow, Stalhrim Arrow (DLC)
f the player only has Stalhrim Arrows as their highest damage arrow, then lower damage arrows should be converted to Stalhrim Arrows. However, if the player also (or exclusively) has some Ebony Arrows, then lower damage arrows should be converted to Ebony Arrows.
Stalhrim Arrow -> conversion target Stalhrim Arrow
Stalhrim Arrow + Ebony Arrow -> conversion target Ebony Arrow
Ebony Arrow -> conversion target Ebony Arrow
I've made an overview of the steps the script would have to walk through in a mindmap software, and exported it to an HTML file that can be viewed in the attachment. Let me know if doing it the 'logical' way I've written out in the overview would be completely idiotic. :tongue:

 

It may be desired to prevent function during combat as on occasion I have noticed arrows added to inventory after being hit. It may also be desired to prevent it from happening until no longer in container menus or shop menus but that would require SKSE to catch the menu closing event.

 

This is however an incredibly important note that I hadn't considered yet. Very valuable feedback as well... now I'm considering perhaps the trigger should not be linked to an event upon an item being added, but perhaps it would be much safer to give the player a manual or semi-manual trigger of some sort to have more control over when and how many times the script activates that isn't during processing-intensive / interface-screwy moments.

 

I'm thinking perhaps it is better to instead give the player an activation item that they must use in order to activate the conversion... that way, they should just be in their own regular inventory menu and nothing else.

 

Perhaps also, the plugin could check how many arrows of each type are left in the player inventory once it has removed the lower damage arrows for conversion (counting up the total amount of high damage arrows it is going to add to the player), and based on that, can increase the conversion rate. So, if the player is left with very few arrows, then instead of awarding 1 high damage arrow per x amount of this arrow and y amount of that arrow, it can award up to 5 or 10 high damage arrows per ..., scaling higher the lower the player arrow count it detects is. This would prevent a player having 250 arrows in their inventory one moment to get only 20 total arrows the next because they are all converted away to a single, much higher damage arrow type.

Link to comment
Share on other sites

Here is a thought.

Take a workstation like the forge anvil and duplicate it.

Remove the keyword that allows forge recipes

Add a new custom keyword that you will use on your recipes

Create recipes designed to require X amount of an arrow with the result being one of the desired arrow.

 

Saves on a lot of scripting, gives a specific location to do the work and allows the player to choose how far they wish to convert. Conditions can even be set up so that recipes will not show if the player does not have at least one of the target arrow in inventory.

Link to comment
Share on other sites

Thanks again for your feedback. That's an interesting idea, but I would really like the player to be able to convert the arrows on-the-fly, so I think I'll look into using an activator object. Perhaps a consumable item that can be re-added once consumed.

 

I'm thinking the object's consumption activates a quest (anytime it is consumed) -> that quest activates the check and conversion script -> when check and conversion are finished, the script also completes the quest and ends.

 

I'm currently a little sick so I'll have to see when I can get to it, but I'm curious to explore in that direction.

Link to comment
Share on other sites

Could use the workstation route and still do it on the fly. Give them a spell or even an object to carry and 'equip / use'. Either way have it activate the workstation. The trick to that is to put the workstation in an unlinked empty interior cell and activate that specific reference. The menu pops up and there is no warping to the workstation.

 

My Mining For Mages Redux mod uses this method to use the smelter menu. Feel free to take a look.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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