GrimGrim31 Posted March 29, 2021 Share Posted March 29, 2021 (edited) Does anyone know if there is a way to activate the "Harvest" of a flora? This would include the vegetables grown in settlements as well as the edible wild flora throughout the Commonwealth. I want a player to be able to eat the flora ingredient (corn, tato, gourd, melon, thistle, etc) fresh off the plant without having to take it and then go into the inventory to use it. It is easy to get the object reference for the plant but I can't figure out how to get at the ingredient so that I can script its use by the player and then removal so that it is consumed. Edited March 30, 2021 by GrimGrim31 Link to comment Share on other sites More sharing options...
SKKmods Posted March 29, 2021 Share Posted March 29, 2021 There is no harvest function or script queryable ingredient, you will have to provide base object lookup tables (forms/arrays) to do that. Plus there is no IsHarvested state query :sad: This is a workaround I have used: FormList Property pSKK_MWFloraList Auto Const Mandatory FormList Property pSKK_MWFoodList Auto Const Mandatory GlobalVariable Property pSKK_MWFoodScalar Auto Const Mandatory ActorValue Property pSKK_MWIsHarvested Auto Const Mandatory ActorValue Property pSKK_MWTimeStamp Auto Const Mandatory Function HarvestPlant(ObjectReference ThisPlant) If (ThisPlant.GetBaseObtect() is Flora) && (ThisPlant.GetValue(pSKK_MWIsHarvested) == 0) Flora ThisFlora = ThisPlant.GetBaseObject() Int iIndex = pSKK_MWFloraList.Find(ThisFlora) If (iIndex > -1) Potion ThisFood = pSKK_MWFoodList.GetAt(iIndex) as Potion Int iFoodCount = pSKK_MWFoodScalar.GetValue() as Int pPlayerREF.AddItem(ThisFood, aiCount = iFoodCount, abSilent = False) ThisPlant.SetHarvested(TRUE) ;There is no IsHarvested query :( ThisPlant.SetValue(pSKK_MWIsHarvested, 1) ;So managing regrowth in script ThisPlant.SetValue(pSKK_MWTimeStamp, Utility.GetCurrentGameTime()) ;On a per workshop ResetWorkshop timer EndIf EndIf Function UnharvestPlant(ObjectReference ThisPlant) ; called by ResetWorkshop on GetRefsLinkedToMe array. If (Utility.GetCurrentGameTime() >= (ThisPlant.GetValue(pSKK_MWTimestamp) + 1)) ;One game day regrowth regardless of Timescale ThisPlant.SetHarvested(False) ThisPlant.SetValue(pSKK_MWIsHarvested, 0) ThisPlant.SetValue(pSKK_MWTimeStamp, -1) EndIf EndFunction Link to comment Share on other sites More sharing options...
AnishaDawn Posted March 29, 2021 Share Posted March 29, 2021 (edited) Activate()(I feel as though this will activate anything that has an activation prompt of some kind(harvest, sit, take, open, etc)) will harvest flora and is a way to check if they were harvested because it returns a boolean. The issue with that though is that you can't simply check the return value just to see if it's ready to be harvested because it'll harvest if the return value is true, and you might not want that. For snatching the ingrediant and using it immediately, OnItemAdded? I don't know how to go about "using" something straight from the inventory through script, sounds like a fun little thing to try an accomplish. Edited March 29, 2021 by AnishaDawn Link to comment Share on other sites More sharing options...
GrimGrim31 Posted March 29, 2021 Author Share Posted March 29, 2021 Thank you. You have both given me some ideas to try. My script already triggers some of the desired effects for the player (a nice chewing sound and reduction of hunger). I will try some script changes based on your suggestions. A successful end state is when the player no longer gets that harvest activation button, the flora plant is set to a harvested state, and no ingredient from that harvest is left in the player's inventory. Right now, the button doesn't turn off so the player can trigger it as many times as he/she wants. While that will satisfy world hunger, it is not very immersive. The script as currently written is in the spoiler below. It is a perk script added to the perk (not as a fragment). While NPCBrahminIdleChew is the name of the sound descriptor variable, I actually fill the property with a different chewing sound FX that is much longer and noisier. Apparently, Brahmins are quiet chewers. The script works great for loose fruits and vegetables since I built a form list for them to use as a condition of perk activation. The form list also includes the flora plants so that the activator button is overwritten, but you know that I still have to solve the problem of getting the flora plants to turn off. ActorValue Property Hunger Auto Actor Property Owner AutoActor Property Target Auto sound Property NPCBrahminIdleChew Auto Const{plays each bite} int PlayEatingSound = 0 ;-- Functions --------------------------------------- Event OnEntryRun(int auiEntryID, ObjectReference akTarget, Actor akOwner)Form baseForm = akTarget.GetBaseObject()Potion itemPotion = baseForm as PotionGame.GetPlayer().EquipItem(itemPotion as Form, False, True)akTarget.SendStealAlarm(akOwner)Game.GetPlayer().AddItem(akTarget as Form, 1, True)PlayEatingSound = NPCBrahminIdleChew.play(akOwner)Sound.SetInstanceVolume(PlayEatingSound, 1) Hunger = Game.getformfromfile(0x000801, "SurvivetheWasteland.esp") as ActorValueDebug.Notification("You eat the " + akTarget.GetDisplayName() + ".")Game.GetPlayer().ModValue(Hunger, 10)Game.GetPlayer().RemoveItem(baseForm, 1, True, None)EndEvent Link to comment Share on other sites More sharing options...
SKKmods Posted March 29, 2021 Share Posted March 29, 2021 Thats all in the script I posted above. All of it done for you. Well, unless you have blocked me and cant see the messages. Link to comment Share on other sites More sharing options...
GrimGrim31 Posted March 29, 2021 Author Share Posted March 29, 2021 (edited) Thats all in the script I posted above. All of it done for you. Well, unless you have blocked me and cant see the messages.How are you able to compare an object reference to Flora? If (ThisPlant is Flora) I get a type mismatch when I try to do that. EDIT: I was able to set the condition using If akTarget.GetBaseObject() as Flora Do you use your own script to regrow the plants so that they can be harvested again? Oh wait, you have it set so they regrow every 24 hours. Your script seems to have a lot more going on than just harvesting an ingredient from a plant. It looks like I need to create two formlists, two actor values, and a global value. Is your food scalar usually set to one in your ESP? Do the plants in game get harvested? It looks like you set up an alternate system for harvesting. I don't see where it changes the plant objects' condition so that the game knows that the plant is harvested. EDIT: OK, sorry, I figured it out. I feel silly now that I see that setharvested is a function in the game. Edited March 30, 2021 by GrimGrim31 Link to comment Share on other sites More sharing options...
GrimGrim31 Posted March 30, 2021 Author Share Posted March 30, 2021 (edited) OK, thanks to both of you I was able to get an almost satisfactory solution to my problem. The new script is in the spoiler. It is a bit long now and still includes lines for my failed attempt to use an AddInventoryEventFilter paired with the Event OnItemAdded. I commented them out but did not delete them yet. The compiler wasn't happen with them. It wanted me to make them native but when I did that, it would not accept any of my functions in the OnAddedItem Event. Formlist Property _MY_FloraList Auto ConstFormlist Property _MY_FoodList Auto Const ActorValue Property Hunger AutoActorValue Property _MY_FloraIsHarvested Auto Const MandatoryActorValue Property _MY_FloraHarvestTimestamp Auto Mandatory Actor Property Owner AutoActor Property Target AutoActor Property pPlayerREF Auto sound Property NPCBrahminIdleChew Auto Const{plays each bite} int PlayEatingSound = 0 ;-- Functions --------------------------------------- Event OnEntryRun(int auiEntryID, ObjectReference akTarget, Actor akOwner)Hunger = Game.getformfromfile(0x000801, "SurvivetheWasteland.esp") as ActorValue If (Utility.GetCurrentGameTime() >= (akTarget.GetValue(_MY_FloraHarvestTimestamp) + 1)) ;One game day regrowth regardless of Timescale akTarget.SetValue(_MY_FloraIsHarvested, 0) akTarget.SetValue(_MY_FloraHarvestTimestamp, -1)EndIf If Game.GetPlayer().GetValue(Hunger) < 0.0 && akTarget.GetBaseObject() as Flora ; AddInventoryEventFilter(_MY_FoodList) akTarget.Activate(Game.GetPlayer(), True) ; akTarget.SendStealAlarm(akOwner) Debug.Notification("You eat the " + akTarget.GetDisplayName() + ".") akTarget.setharvested(True) akTarget.SetValue(_MY_FloraIsHarvested, 1) akTarget.SetValue(_MY_FloraHarvestTimestamp, Utility.GetCurrentGameTime()) Flora ThisFlora = akTarget.GetBaseObject() as Flora Int iIndex = _MY_FloraList.Find(ThisFlora) If (iIndex > -1) Potion ThisFood = _MY_FoodList.GetAt(iIndex) as Potion Debug.Notification("Tried to remove " + ThisFood.GetDisplayName() + ".") pPlayerREF.RemoveItem(ThisFood, 1, abSilent = False) pPlayerREF.AddItem(ThisFood, 1, abSilent = False) EndIf PlayEatingSound = NPCBrahminIdleChew.play(akOwner) Sound.SetInstanceVolume(PlayEatingSound, 1) Game.GetPlayer().ModValue(Hunger, 10) ElseIf Game.GetPlayer().GetValue(Hunger) < 0.0 && akTarget.GetBaseObject() as Potion Form baseForm = akTarget.GetBaseObject() Potion itemPotion = baseForm as Potion Game.GetPlayer().EquipItem(itemPotion as Form, False, True) Game.GetPlayer().AddItem(akTarget as Form, 1, True) Debug.Notification("You eat the " + akTarget.GetDisplayName() + ".") Game.GetPlayer().RemoveItem(baseForm, 1, True, None) PlayEatingSound = NPCBrahminIdleChew.play(akOwner) Sound.SetInstanceVolume(PlayEatingSound, 1) Game.GetPlayer().ModValue(Hunger, 10) Else Debug.Notification("You are not hungry now.")EndIfEndEvent ; Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer); Debug.Notification("You eat the " + akItemReference.GetDisplayName() + "."); Game.GetPlayer().RemoveItem(akBaseItem, aiItemCount); EndEvent The only thing that isn't working correctly is the removal of the flora ingredient once I have activated the flora. The problem is that the formlists for Food and Flora contain different numbers of items. Food has 30 items and Flora has 53. This disparity is because Flora includes multiple plants of the same type whenever Bethesda had more than one mesh for that plant. For example, the corn stalk in Flora has two versions but they both produce the same ingredient, Corn. So using the index from the Flora list to remove the right item from the Food List isn't working yet. Using OnItemAdded would be a lot simpler because it would have the form and object ref of the food item added to the inventory which would make removal easy. Edited March 30, 2021 by GrimGrim31 Link to comment Share on other sites More sharing options...
AnishaDawn Posted March 30, 2021 Share Posted March 30, 2021 Variables or properties of a desired type can have those types assigned them through casting of the base object as demonstrated in his script. It's not needed to use SetHarvested() on Flora that was harvested through Activate() because it sets that "flag" by nature of the activation. Activate() basically allows one to activate things remotely. He gets around using Activate() by searching through a list of flora that was found and then adding the ingredient to the inventory and calling SetHarvest() on the Flora. On to the thing about the 30 things and 53 things - well I would just add as many ingredients to the foodlist that are the same as the number of Flora that has multiple versions if that makes sense. 53 foods = 53 flora. Link to comment Share on other sites More sharing options...
GrimGrim31 Posted March 30, 2021 Author Share Posted March 30, 2021 Last night before bed I suddenly realized how to solve this puzzle. It's easy. I don't actually need to activate the plant since I don't want the ingredient added to my inventory or the message that it was added. All I want are the effects of eating the ingredient and the flora to be harvested so that my character cannot eat the ingredient again until the right amount of time has passed. So I don't need the Activate command in this script but I will need the actor values for harvested and the time stamp as well as the setharvested() and the effects already in my script. It should be a few simple edits to the existing script. I just need to remove the Activate and make sure that the plant Actor Values are correct for harvested and then resetting the plant after the right amount of time has passed (similar to SKK50's unharvest function). Casting is something that I am still learning. I have used it correctly a few times but also experience some errors on other attempts. I wasn't able to do it the same way that SKK50 did. I had to use "as Flora" instead of "is Flora". Link to comment Share on other sites More sharing options...
AnishaDawn Posted March 30, 2021 Share Posted March 30, 2021 There's one thing you can be sure of: Objectreferences can always be cast to the types of their base objects. This is necessary for functions that will not take ObjectReferences in their params but their types instead or for functions that cant be called on objectreferences but their types. Link to comment Share on other sites More sharing options...
Recommended Posts