Open Demolish50 opened 8 years ago
We did have auto-restock in one of our later roadmap plans, I was thinking something similar to what you have here; where the server generates "pretend" trades with imaginary traders to maintain stock levels, but the idea of sliding scale prices seems interesting. Converting NPC money into stock would work well where players are doing a lot of buying too, midspace was thinking something similar using NPC trader ships, the price and stock being effected by the success or failure of those ships to arrive and leave the trade base unmolested by pirates.
It certainly can be done. That code can be implemented pretty easily. We would need to decide on how often it ran though, ie., once an hour.
Servers are getting able to handle a lot more players at once, so admins are having issues with particular items like iron ore/ingot getting quite a lot overstocked in NPC markets. Although we planned to do ambient traders for low stock (and probably high stock) in the short term implementing a sliding price scale, at least on NPC markets should be a quick an easy solution here. Other possible solutions is having markets trade automatically with each other to shuffle items around but it is probably more immersive if players do the shuttling. We also planned for transport tycoon style subsidies so it might be a good time to start implementing these as from a logic perspective, it shouldn't be too difficult.
Next questions is should the scales be hardcoded rules or flexible, or simply binary (ie admins can turn it on or off but rules are static)
Suggested logic considerations: 1: the current unit price effects the point that the sliding scales start to occur. This stops high value ores being trashed in price too quickly, and stops junk ores becoming valuable.
2: the amount of sliding should scale based on current stock levels
3: sell prices do not immediately drop, but if the buy price becomes more than half the sell price start dropping those too just not as far.
4: price check runs immediately after a sale eliminating need for timer lag; and reducing "bill shock" as only one price change occurs per sale even if the current price is unsustainable, and would likely scale further on subsequent checks. This creates stockmarket tension too.. (price is dropping sell sell sell, price is too cheap buy buy buy)
5: price changes should be represented as a percentage so that hardcoded pricing do not rig the market
eg. (probably better as a case/switch structure but using if for example purposes)
//buy price scaling (triggered at sell to server event)
if ((buyprice <= 1) && (on hand >= 500000)) { buyprice -= (buyprice * 0.50); return; } //reduce price 50%
if ((buyprice > 1) && (buyprice <= 50) && (on hand >= 200000)) { buyprice = (buyprice * 0.75); return; } //reduce by 25%
if ((buyprice > 50) && (buyprice <= 150) && (on hand >= 150000)) { buyprice = (buyprice * 0.85); return; } //reduce 15%
if ((buyprice > 150) && (buyprice <= 300) && (on hand >= 100000)) { buyprice = (buyprice * 0.90); return; } //reduce 10%
if ((buyprice > 300) && (buyprice <= 1000) && (on hand >= 50000)) { buyprice = (buyprice * 0.95); return; } //reduce 5%
if ((buyprice >1000) && (buyprice <= 5000) && (on hand >= 10000)) { buyprice = (buyprice * 0.97); return; } //reduce 3%
if ((buyprice >5000) && (buyprice <= 15000) && (on hand >= 5000)) { buyprice = (buyprice * 0.98); return; } //reduce 2%
if ((buyprice >15000) && (on hand >= 500)) { buyprice = (buyprice * 0.99); return; } //reduce 1%
//sell to player price scaling (triggered at sell to server event) in theory should never drop below buy
if (sellprice > (buyprice * 2) {
if ((sellprice <= 1) && (on hand >= 500000)) {sellprice = sellprice * 0.60); return; } //reduce price 40%
if ((sellprice > 1) && (sellprice <= 50) && (on hand >= 200000)) { sellprice = (sellprice * 0.85); return; } //reduce by 15%
if ((sellprice > 50) && (sellprice <= 150) && (on hand >= 150000)) { sellprice = (buyprice * 0.90); return; } //reduce 10%
if ((sellprice > 150) && (buyprice <= 300) && (on hand >= 100000)) { sellprice = (buyprice * 0.95); return; } //reduce 5%
if ((sellprice > 300) && (sellprice <= 1000) && (on hand >= 50000)) { sellprice = (sellprice * 0.96); return; } //reduce 4%
if ((sellprice >1000) && (sellprice <= 5000) && (on hand >= 10000)) { sellprice = (sellprice * 0.97); return; } //reduce 3%
if ((sellprice >5000) && (sellprice <= 15000) && (on hand >= 5000)) { sellprice = (sellprice * 0.98); return; } //reduce 2%
if ((sellprice >15000) && (on hand >= 500)) { sellprice = (sellprice * 0.99); return; } //reduce 1%
}
Some sort of buy logic as well that takes price up too if stock gets short etc.. (not had time to write it yet)
Added a floor value for dropping price. Looks like it would be wise to add a price reaction to the size of a sale as well. Not just the stock on hand. To make it react more like a stock market.
note to self - we drop the buy price if there is too much stock we raise the sell price if stock becomes rare we will also need a way to raise the buy price again when stock is low we also need a way to lower the sell price if we are overstocked
@midspace So, I have been bouncing ideas off myself on my (broken) test branch. This morning it occurs to me like divine inspiration.. if I go ahead with reactive pricing as I was.. (See prior post) it would alter the NPC market price in the database. Although IMO that is not a bad idea; admins that set very specific base price might get annoyed... and players will be able to manipulate the price by dumping stock or pumping stock.. which incidentally is quite realistic, that's exactly how the crypto currency exchanges work, and WHY they work. But from our perspective it will become troublesome later on.
What I came up with instead should in theory be slightly simpler but is less manipulable - What if we hang the NPC market sliding price logic off something /like/ the LCD logic which checks price/stock prior to the player seeing it, and the adjusted price is what shows. - almost like your auto markup rules suggestion. Ie, we never actually alter the base price. Instead we have rules similar to my psuedocode above, that takes the base price THEN applies it like a filter automatically based on current stock. This reduces the number of potential price changes, eliminates the need to pay close attention to price, but we can use more dramatic ones.. (using geometric logic even 4 rules are significant, 10%(90% of price) then 50% (half off price) then 75%(25% of price) then 90%(10% of price)- or off base price 90% 45% 11% 1%)
This has some advantages over my previous approach -
Main disadvantages;
Our new logic would be along the lines of Assuming we have an item "fuzzy dice" assuming item(I).qty was 20,000 - So we have too many - assuming item(I).priceGivenToPlayer_sell = $100 assuming item(I).priceGivenToPlayer_buy = $50 assuming pricepoint(x).percentImpact was 0.90 (90%) assuming pricepoint(x).qty was 15,000 and the next price point was at 50,000 (so never applies)
x=0
repeat
if ((item(I).qty > pricepoint(x).qty) and (not pricepoint(x).percentImpact >=1)) then
{
item(I).priceGivenToPlayer.sell=item(I).priceGivenToPlayer_sell*pricepoint(x).percentImpact
item(I).priceGivenToPlayer.buy=item(I).priceGivenToPlayer_buy*pricepoint(x).percentImpact
} else {
if ((item(I).qty <= pricepoint(x).qty) and (pricepoint(x).percentImpact >1)) then
{
item(I).priceGivenToPlayer.sell=item(I).priceGivenToPlayer_sell*pricepoint(x).percentImpact
item(I).priceGivenToPlayer.buy=item(I).priceGivenToPlayer_buy*pricepoint(x).percentImpact
}
}
x++
until (x-1)==number of elements in price point list etc
What the player would get as price for "fuzzy dice" is
Sell price (to player) $90
Buy price (from player) $45
Price Point File sample:
Qty, % Impact
0,2.0 // out of stock! 200%
10,1.5 // Stock is low! 150%
50,1.1 //could be better 110%
1000,1.0 //Stock is just right no change
15000,0.90 //Stock is getting a bit full 90% (10% off)
50000,0.50 //Ok way too much now 50%
100000,0.25 // Getting out of hand 25%
200000,0.10 //Lets dump this stock 10%
@TheEngineer50 We don't have a copy of https://github.com/TheEngineer50/SEPowerShellTools/blob/master/marketmaint.ps1 And it appears it is no longer available.
Note to self - add char field to the price adjustment entry point, to set if it is a buy (b) or sell (s) price being altered. Add some sort of bias - ie Favor buy price reductions on high stock, over sell price drops, and favor sell price increases on low stock. Treat it like a real capitalist is setting the pricing; emphasis on profits. (edit: wow since when is C# dumb as a brick.. it cannot tell when a char is a char without overriding type when you populate it.. nor can it tell the difference between a decimal and a double.. i miss perl lol) more notes to self: convert back to an array int[] terms = termsList.ToArray();
Ok buy or sell price bias implemented crudely.
Now need to add a item price vs size of reaction filter, or track the size of transactions
At the moment if i have 500 displays at 10 each. Then buy them all reducing stuck to under 10, thus increasing buy price, I can immediately sell them all back to make a profit, and repeat until NPC is out of money. Need a way (such as a price change cool off or add further bias based on the value of the goods. Any suggestions?
@midspace are you able to add in the overlap/undercut zone logic:
"lowest (in stock) tradezone sell to player price in range of player/lcd shows as current stock/sell price"
and the
"highest (available funds) tradezone buy from player price shows as current buy/price"
Sundry modifiers: If the lowest sell to player price has no stock show the next one down with stock etc. If they all have no stock show the "sell to player" price from the market with the highest (available funds) buy from player price. (as this is the market the stock will go into anyway)
Effect should also apply to overlapping player zones not just players overlapping npc zones. *should we also check for overlapping npc zones - given this should never happen?
Reactive pricing should not change player price.. but may need to factor in what the npc market adjusted price is, when deciding which price dominates where an npc zone overlaps a player zone.
If the owner of an overlapping player zone tries to trade when it overlaps an npc it should prompt the player to specify the market to trade with.
low/high price should effect /pricelist too unless they specify a market name.
This sort of logic will probably replace the need for the offer/stockmarket #103 so that can be closed too
Also dumb question - did we get around to loading the price scaling rules from a file? I originally coded the logic to decode a csv formatted dataset, but I completely forget if we got around to writing that to a file to read at startup or not.. I know i worked out some test file logic and commented it out as it was writing to global not map folder.. but it has totally slipped my mind if we ended up reading that file if it exists now.
I've left appropriate locations to pick and choose a market for overlapping markets, but the problem I couldn't get my head around was inadequate stock in any or all markets, and instead having it buy part lots from each market zone to fill the entire buy order.
Yes, price scaling is in. I'm sure I documented it, but I cannot find it. The file is called "EconPriceScale.xml" And is easy to read XML.
<?xml version="1.0" encoding="utf-16"?>
<EconReactivePricing xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EconReactivePrices>
<PricePoint>10</PricePoint>
<PriceChange>1.1</PriceChange>
<Description>Critical stock 10 or less 10% increase</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>50</PricePoint>
<PriceChange>1.1</PriceChange>
<Description>Low Stock 11 to 50 10% increase</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>100</PricePoint>
<PriceChange>1.05</PriceChange>
<Description>Could be better 51 to 100 5% increase</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>1000</PricePoint>
<PriceChange>1</PriceChange>
<Description>About right 101 to 5000 no change</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>5000</PricePoint>
<PriceChange>0.95</PriceChange>
<Description>Bit high 5001- 10000 drop price 5%</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>10000</PricePoint>
<PriceChange>0.95</PriceChange>
<Description>Getting fuller 10001 to 50000 drop another 5%</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>50000</PricePoint>
<PriceChange>0.90</PriceChange>
<Description>Way too much now drop another 10%</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>100000</PricePoint>
<PriceChange>0.50</PriceChange>
<Description>Getting out of hand drop another 50%</Description>
</EconReactivePrices>
<EconReactivePrices>
<PricePoint>200000</PricePoint>
<PriceChange>0.25</PriceChange>
<Description>Ok we need to dump this stock now 75% price drop</Description>
</EconReactivePrices>
</EconReactivePricing>
Basically an extra admin command to allow admin to enable/disable the exploitable pricing logic yes? I am considering other ways we can do this and still minimising explotation.. but so far they all require significant more complexity to the pricing logic; and gameplay rules.
(Example when a player sells item X to station Y, they are then restricted from BUYING item X from station Y for 5 minutes or until they go to another trade zone etc)
This wouldnt harm legitimate traders, who would be mostly selling item X and using the money to buy item Z, and would inconvenience players using the stock changes to manipulate the price to clean out the NPC's money,
But it is certainly a lot more complexity since we now need timers and price tables tracking all the items and players..
I went the route of breaking up large transactions into smaller amounts automatically in the code. Testing it on my DS, looks fine. If you want to see it, its [STC] Econ server. Once I get it nice looking and not spamming the chat, I'll submit it here. Not sure how active the development is on this mod.
If you submit some code we will certainly look it over, and add in stuff we like. Temar added some nice ship selling stuff that basically nailed one of the ENH's we already had in our roadmap - midspace did a quick code analysis; tidied up a few rough bits ran it on a dev version of the mod for a few days then we released it in the public version and added Temar to the credits.
We just dont necessarily see right away when a push request is sent - as we (myself/midspace) are often quite busy in real life and cant aways check our email or github but we will get to it.
The current reactive pricing core is deliberately simple to make tweaking easy, and because we hope to add in a "trade contract" mission system at some point, where the first player to transport goods to a particular station gets a bonus contract price. The current system makes it pretty easy to add a contract price bonus.
I plan on it! I've got a lot of internal testing to do, since right now it's absurdly verbose, but basically I just call a do{}while{} for the buy/sell quantity, subtracting X from the qty each time and then set the reactive pricing XML to the same X interval. Stops the exploit, but repeats the transaction chat notifications on each iteration. I'll toss you something once I get it all fixed up!
And yeah I figured you're very busy. I didn't like my original PR so I removed it for further testing before I go there. I'd rather take as much load off of you guys as possible by doing a lot of testing myself and getting the code just about up to snuff before I send it over.
Would it be possible to do real time NPC market price changes based on stock?
It's written for readability. I'm not neither as talented as you two but it does work. Something like this: https://github.com/TheEngineer50/SEPowerShellTools/blob/master/marketmaint.ps1
Here is the output of that: https://www.pastee.org/tgttr
I run this during my server maintenance but if somehow it could be done real time. I'm not familiar enough with C# to make it happen.
EDIT BY DEVELOPER: