Sephnroth Posted January 22, 2018 Share Posted January 22, 2018 (edited) UPDATE: Just as an update, during my afternoon break today I found Cpsics wonderful beginners tutorial which although basic was plenty to understand how Papyrus works. Roaming through Bethesda's script reference and especially the event reference I'm getting ideas for how I could begin to implement some of the ideas in my head but one thing I am still searching for is a way I could detect transactions with merchants so I can support ALL game merchants (included ones added by other mods!) without instead manually attaching my script to existing merchants in the CK. Ideally I would find a way to tell if the akDestContainer var passed by the OnItemRemoved removed event belonged to a merchant and if so which one (with a ref, so I can alter their avail gold etc - although I do that just by putting in or removing gold coins from the merchant inventory right? IE akDestContainer?) that way I could detect player trades and do it all that way. Thoughts? Original Post: Just having a browse around on my phone and struggling to find information on script based interactions with merchants and trades. I am a programer by trade and have been musing on the idea of creating an economics mod, starting nice and simple, that allows merchants to become richer as they become more successful. So, for example, you take a truck load of stuff to one merchant and sell it all then presumably they will sell it on and take a profit right? It makes no sense they always reset to their default money + investment perk. Would love to make a mod that tracks their weekly (or maybe 48hrly to sync with inventory reset) profit and adds that value to their avail cash. But yeah, I would need to catch the player selling items and see their default value + npc buy price (to work out potential profit), a way to add money to merchants via script (everyone seems to do this manually in CK which is why everything is so static..) and a way to store persistent variables to track it all for the merchants. Not asking for anyone to write this for me but can anyone point me at a good place to start learning how to hook these events? Most promising google result so far led to a forbidden page error! Edited January 22, 2018 by Sephnroth Link to comment Share on other sites More sharing options...
icecreamassassin Posted January 22, 2018 Share Posted January 22, 2018 https://www.creationkit.com/index.php?title=Category:Papyrus everything you need is there. Sounds like something like a script which looks for you to enter the barter menu and then targets the person you are in that barter menu with and totals the value of their stock. Then upon exit, totals it again for the net gain/loss. You could then take that net gain or loss alter a global variable which you start at 100 and drop by 5 for every 10k gold worth of profit they have (or something like that). Then you simply add more leveled lists of more valuable items and even very rare items and more vendor gold in the form of leveled lists which use the global and have "Chance None" (chance the container will not have the item; starts at 100% chance based on your global) set to that global. Anyhoo, that's really just a rough off the top of my head, there are certainly tons of functions that would be helpful for this. and just as a jumping off point, here is a script I developed for a sell cart which you put items in and it sells a random number of stacks between a certain range each day, calculates the gold value and runs a formula to calculate enchanted values, adds it all up and gives you a percentage of the value based on a value which goes up slightly after every so many uses. I'm sure you will find some useful functionality there import math ObjectReference Property SellPile Auto Float Property TotalSale Auto Float Property ValueMod Auto ObjectReference Property MoneyBox Auto MiscObject Property Gold001 Auto Int ItmCnt Int GoldValue Int ItemTotal Int Index Int RandomItm Int NumSell Enchantment E Form SellItem Weapon SellWeap Armor SellArm GlobalVariable Property SellChestUses Auto GlobalVariable Property MinSell Auto GlobalVariable Property MaxSell Auto Int MinS Int MaxS Event OnUpdateGameTime() ItemTotal = SellPile.GetNumItems() MinS = MinSell.Value as int MaxS = MaxSell.Value as int NumSell = Utility.RandomInt(MinS, MaxS) if NumSell > ItemTotal Numsell = ItemTotal Endif While NumSell > 0 NumSell -= 1 RandomItm = Utility.RandomInt(0, ItemTotal) if SellPile.GetNthForm(RandomItm) as weapon SellWeap = SellPile.GetNthForm(RandomItm) as weapon ItmCnt = SellPile.GetItemCount(SellWeap) if SellWeap.GetEnchantment() TotalSale += GetEnchantedGoldValue() * ItmCnt Endif Int ItemValue = SellWeap.GetGoldValue() * ItmCnt TotalSale += ItemValue Sellpile.Removeitem(SellWeap, ItmCnt) ItemTotal = SellPile.GetNumItems() Elseif SellPile.GetNthForm(RandomItm) as armor SellArm = SellPile.GetNthForm(RandomItm) as armor ItmCnt = SellPile.GetItemCount(SellArm) if SellArm.GetEnchantment() TotalSale += GetEnchantedGoldValue() * ItmCnt Endif Int ItemValue = SellArm.GetGoldValue() * ItmCnt TotalSale += ItemValue Sellpile.Removeitem(SellArm, ItmCnt) ItemTotal = SellPile.GetNumItems() Else SellItem = SellPile.GetNthForm(RandomItm) if SellItem != NONE ItmCnt = SellPile.GetItemCount(SellItem) Int ItemValue = SellItem.GetGoldValue() * ItmCnt TotalSale += ItemValue Sellpile.Removeitem(SellItem, ItmCnt) ItemTotal = SellPile.GetNumItems() Endif Endif EndWhile TotalSale *= ValueMod MoneyBox.Additem(Gold001, TotalSale as Int) TotalSale = 0 if ValueMod < 0.5 SellChestUses.Value += 1 if SellChestUses.Value == 10 Valuemod += 0.02 SellChestUses.Value = 0 Endif Endif RegisterForSingleUpdateGameTime(24) EndEvent Int Function GetEnchantedGoldValue() GoldValue = 0 if SellPile.GetNthForm(RandomItm) as weapon E = SellWeap.GetEnchantment() Elseif SellPile.GetNthForm(RandomItm) as Armor E = SellArm.GetEnchantment() Endif Index = 0 While Index < E.GetNumEffects() MagicEffect ME = E.GetNthEffectMagicEffect(Index) Float MEBaseCost = ME.GetBaseCost() Float Mag = E.GetNthEffectMagnitude(Index) Int Dur = E.GetNthEffectDuration(Index) Float Calc = Calc + ((MEBaseCost*8) * (pow(Mag,1.1)) * (pow(Dur/10,1.1) )) GoldValue = GoldValue + Calc as int Index += 1 EndWhile Return GoldValue EndFunction Link to comment Share on other sites More sharing options...
Sephnroth Posted January 22, 2018 Author Share Posted January 22, 2018 That's a pretty neat way of doing it! In fact that's a lot more sensible than where I was headed which was to have a an active/inactive state for the script, switch to active when barter is open and assume that any OnItemRemoved events triggered whilst in active state MUST be items sold to a shop and track that items specific value etc. That would allow me in the future to remember what items were sold to an npc and then decide myself when its likely that item has been sold on and if it has NOT been yet then make sure its always in the npc's inventory for a bit of realism but I'm not too worried about that atm - Maybe in the future! I will have a proper look when I'm back at my home office but browsing around wiki on phone I don't see any particular way to detect a barter menu being opened? I see Actor.ShowBarterMenu() but nothing to indicate that the method fires an event for me to catch when it's called. Same for an npc merchants inventory restock - I'm aware in game they happen every 48 hrs but not sure I can catch that (unless its handled by the generic Reset event?). But really that's fine - I shouldn't need that for anything I'm intending if I write my code properly for when a player interacts with a shop. Link to comment Share on other sites More sharing options...
Sephnroth Posted January 22, 2018 Author Share Posted January 22, 2018 got it! Event OnMenuOpen(String MenuName) if MenuName == "BarterMenu" ;do stuff endif EndEvent Google tells me this is a thing. I think i'll have some fun when i get home. Link to comment Share on other sites More sharing options...
icecreamassassin Posted January 22, 2018 Share Posted January 22, 2018 Yep, just make sure you register for the menu with: Event OnInit() RegisterForMenu("BarterMenu") EndEvent you can put it in a quest script which handles the processes Link to comment Share on other sites More sharing options...
Recommended Posts