khulse Posted May 13, 2014 Share Posted May 13, 2014 (edited) You know, I think the most annoying thing about papyrus is that the really stupidly simple stuff seems to be the hardest things to figure out. I want to start a quest when an unmodified non-specific vanilla instance of an item is picked up. A bee (critterbeeingredient) to start the quest, to bee specific. Then I want to set the next stage when the character picks up a glowing mushroom. When the player picks up a giant lichen, it moves to the next stage- and so on. Then, the player will craft something and use it. That ends the quest. The problem I'm running into is that I can't figure out how to do this without either specifying a specific instance of an object or having the player talking to an actor (which this quest is not supposed to involve in any way). I think I can start the quest with an sm event node. I know how to set things up so that the quest progresses when the character acquires an alias. So I need to know how to either: 1) assign a base item to an alias without it being a specific base item (ANY glowing mushroom, not the Extra Special Dark Green Glowing Mushroom growing in the left nostril of the king of the falmers).or2) assign the player to an alias with scrips that will progress the game when a specified non-specific item is picked upor3) just assign an [if Game.GetPlayer()picksup(anyoldglowingfungusfromanywhere)/ setstage insertmyquesthere 9000/ endif] several times to the quest script itself. Anyone know how to do this? Thanks in advance. Edited May 13, 2014 by khulse Link to comment Share on other sites More sharing options...
lofgren Posted May 13, 2014 Share Posted May 13, 2014 (edited) 1) You can't assign forms to aliases. Aliases are always object references or location references. 2) To assign the player to an alias, create a new object reference alias. Select "specific reference" "any cell" "player" Once you've done that, you can use the InventoryEventFilter function inside an OnInit() event to make your script only trigger when the player acquires bees (or other items you are interested in). http://www.creationkit.com/AddInventoryEventFilter_-_ObjectReference Note that you can use a formlist as a parameter, so you can detect whenever the player acquires any item in the formlist. Then use OnItemAdded to detect which of the items on your list the player has acquired. http://www.creationkit.com/OnItemAdded_-_ObjectReference 3) This would be ugly. I think #2 is the way to go. Alternatively, you can just create an SM Event quest that goes off and then resets itself each time the player acquires one of the items, and then sets the tracking quest to appropriate stage depending on which item is acquired. (It's never been clear to me why you wouldn't do that, honestly, because I have to assume tracking inventory events is a pretty heavy script burden, even properly filtered.) Edited May 13, 2014 by lofgren Link to comment Share on other sites More sharing options...
khulse Posted May 13, 2014 Author Share Posted May 13, 2014 Thank you for the quick response! I'm sort of leaning towards #2 myself. A couple of questions- Why is the inventoryeventfilter needed, if you can set the onitemadded to a base object? Or am I missing something? I understand how to set up the onitemadded, but I'm a little fuzzy on what to do with the inventoryeventfilter. Where do I put this in relation to the rest of the script? Do you know of any scripts in the game or good example scripts that have a set up something like this? I'm better at assembling the pieces if I can look at an example. I'm not quite sure I follow your alternative suggestion. Sm event nodes only seem able to activate a quest, not the stages. In any case, thank you for pointing me in the right direction. At least no I have an idea of what I need research :thumbsup: Link to comment Share on other sites More sharing options...
lofgren Posted May 13, 2014 Share Posted May 13, 2014 (edited) The inventoryeventfilter will make it so the script only fires when the actor acquires items you are interested in, rather than any time the actor acquires any item whatsoever. It reduces the amount of resources your script uses and also makes it a little easier to script the ItemAdded event. The inventory event filter function would go in the OnInit() event of the alias or the quest, so it would fire as soon as the alias is filled. To use the SM event node alternative, you would have two quests. One quest would be triggered by the story manager. It would then set the appropriate stage in the second quest, then stop itself and reset so that it would fire again when the next item on the list was acquired. This way you would not need any aliases at all, and the game engine would do more of the work, significantly reducing the size and complexity of scripts. I don't know of any quests that use either method exactly, but I would suggest you look at the Elgrim's Elixirs quest that asks for three ingredients, the quest from Temba Wide Arm to acquire bear skins, or the red nirnroot quest for hints. Edited May 13, 2014 by lofgren Link to comment Share on other sites More sharing options...
lofgren Posted May 13, 2014 Share Posted May 13, 2014 As an analogy, an alias without an inventory filter would be like, "Is that a bee? Is that a bee? Is that a bee? Is that a bee? Is that a bee? Is that a bee?" An alias with an inventory filter would be like, "Let me know when you find a bee." Link to comment Share on other sites More sharing options...
IsharaMeradin Posted May 13, 2014 Share Posted May 13, 2014 An example of a good reason to use an inventory event filter when you are looking for only a few items... If you were to run Hearthfire without the appropriate USKP patches, you would end up with log spam such as the following every time an item is added. [05/13/2014 - 02:06:23PM] [BYOHHouseBuildingPlayerScript <alias Player on quest BYOHHouseBuilding (0300305D)>]OnItemRemoved [Form < (08032192)>], itemCount=1 [05/13/2014 - 02:06:23PM] [byohhousebuildingscript <BYOHHouseBuilding (0300305D)>] UpdateLogCount [05/13/2014 - 02:06:23PM] [byohhousebuildingscript <BYOHHouseBuilding (0300305D)>] logcount=0 The reason this happens is that Bethesda intended to use an inventory filter but forgot to fill the property value. Because there was nothing to filter, it ends up looking at every item that gets passed into the player inventory. In essence the house building script was going.. Is that a log? Is that a log? Is that a log? etc...After USKP filled that property, it shuts up and only does its thing when it is a log. Here is a quick example, it might even do what you want... but I'm sure it could be improved upon ScriptName SomeScript Extends ReferenceAlias FormList Property TargetItems Auto ;list of 4 items Int ItemsGotten = 0 Event OnInit() AddInventoryEventFilter(TargetItems) EndEvent Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) If GetOwningQuest.GetStage() < 20 && GetOwningQuest.GetStage() > 10 If akBaseItem == TargetItems.GetAt(0) ;first object found GetOwningQuest().SetStage(11) ItemsGotten += 1 ElseIf akBaseItem == TargetItems.GetAt(1) ;second object found GetOwningQuest().SetStage(12) ItemsGotten += 1 ElseIf akBaseItem == TargetItems.GetAt(2) ;third object found GetOwningQuest().SetStage(13) ItemsGotten += 1 ElseIf akBaseItem == TargetItems.GetAt(3) ;fourth object found GetOwningQuest().SetStage(14) ItemsGotten += 1 EndIf If ItemsGotten == 4 GetOwningQuest().SetStage(20) ;go on to the next step EndIf EndIf EndEvent Link to comment Share on other sites More sharing options...
lofgren Posted May 13, 2014 Share Posted May 13, 2014 Don't forget that the player might also remove the items eventually... Link to comment Share on other sites More sharing options...
khulse Posted May 14, 2014 Author Share Posted May 14, 2014 That makes sense. I'll make sure to include an inventory even filter so I don't gum up peoples games with pointless script activity. @IsharaMeridan That's pretty close to what I have managed to put together, but it clarifies several things for me. Thank you very much. @lofgren It doesn't really matter if they remove the items. The idea is that they are 'researching' a formula. Each stage identifies a component, and gives a hint at what the next component needs to be. Once they have everything identified, the player can see the recipe and finish the quest any time they like by making the item. I'll be 'locking' each stage as they go so they don't wind of changing stages every time they pick up one of the items. That would get a little annoying. Link to comment Share on other sites More sharing options...
khulse Posted May 14, 2014 Author Share Posted May 14, 2014 (edited) Would this work? ScriptName myspecialrecipescript Extends ReferenceAliasMiscObject Property itemAAA Auto ConditionalIngredient Property itemBBB Auto ConditionalIngredient Property itemCCC Auto ConditionalIngredient Property itemDDD Auto ConditionalMiscObject Property itemEEE Auto ConditionalMiscObject Property itemXXX Auto ConditionalQuest Property myspecialrecipe Auto ConditionalEvent OnInit()AddInventoryEventFilter(itemAAA)EndEventEvent OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) If akBaseItem == itemAAA && GetOwningQuest.GetStage() == 10 RemoveInventoryEventFilter(itemAAA) AddInventoryEventFilter(itemBBB) GetOwningQuest().SetStage(20) ; ElseIf akBaseItem == itemBBB && GetOwningQuest.GetStage() == 20 RemoveInventoryEventFilter(itemBBB) AddInventoryEventFilter(itemCCC) GetOwningQuest().SetStage(30) ; ElseIf akBaseItem == itemCCC && GetOwningQuest.GetStage() == 30 RemoveInventoryEventFilter(itemCCC) AddInventoryEventFilter(itemDDD) GetOwningQuest().SetStage(40) ; ElseIf akBaseItem == itemDDD && GetOwningQuest.GetStage() == 40 RemoveInventoryEventFilter(itemDDD) AddInventoryEventFilter(itemEEE) GetOwningQuest().SetStage(50) ; ElseIf akBaseItem == itemEEE && GetOwningQuest.GetStage() == 50 RemoveInventoryEventFilter(itemEEE) AddInventoryEventFilter(itemXXX) GetOwningQuest().SetStage(60) ; ElseIf akBaseItem == itemXXX && GetOwningQuest.GetStage() == 60 RemoveInventoryEventFilter(itemXXX) GetOwningQuest().SetStage(70) endifendevent Note on the formatting: For some reason all the indents most people use make my eyes cross. This is much easier to read for me. Will it still work set up this way? In some game modding it seems to matter, in some it doesn't. Edited May 14, 2014 by khulse Link to comment Share on other sites More sharing options...
lofgren Posted May 14, 2014 Share Posted May 14, 2014 whether or not spaces matter depends on the compiler. Luckily for papyrus they do not, so space it however you feel comfortable. Your inventory filter should be set to a formlist that contains each of these items. right now you are only looking for the first ingredient on the list, so the conditions for subsequent ingredients will never be true. Link to comment Share on other sites More sharing options...
Recommended Posts