mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
## About The Pull Request Stock market events are a system coded into the stock market system in an attempt to keep the stocks unpredictable, at least on paper. They... need work, I'm in full agreement on that, but I haven't been able to get the energy to really fix stocks as of recently. I plan on going and kicking events up and making them a lot cooler, but in the meantime, I've refactored stock market events into their own datum type, `/datum/stock_market_event`. This works like most similar event datum style objects, where an event has a proc called when an event starts, a proc called when an event ends, and a proc called between on subsequent stock market subsystem firings. This does some minor tweaks to the newscaster stories automatically generated after an event fires, namely so that they can be produced quickly while emphasizing the important part of the event, what material is being effected, and a summary of what kind of behavior has happened to the material stock. Additionally, this made for a good excuse to do some code cleanup here while I had the opportunity, swapping to `::` as opposed to `initial()` calls where it seemed cleaner and more appropriate. This should make adding new stock market events as well as more unique events that can effect cargo and the round at large simple to do. This PR shouldn't have any mechanical changes to how stock market behaves in a live round. ## Why It's Good For The Game Improves code quality of stock market, increases readability of stock market events that have happened on the newscaster, and performs some minor cleanup to the TGUI for the stock market while I'm at it, all while keeping balance the same while we're still in the feature freeze. Full disclosure, once the freeze is over I have some pretty easy numbers tweaks planned to help significantly improve the stock market system that I had layered on this branch, but we've shuttled them off this PR for now to get this part ready to ship. ## Changelog 🆑 refactor: Stock market events are now their own objects, and are handled by the stock market individually. /🆑 --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
112 lines
5.4 KiB
Plaintext
112 lines
5.4 KiB
Plaintext
|
|
SUBSYSTEM_DEF(stock_market)
|
|
name = "Stock Market"
|
|
wait = 20 SECONDS
|
|
init_order = INIT_ORDER_DEFAULT
|
|
runlevels = RUNLEVEL_GAME
|
|
|
|
/// Associated list of materials and their prices at the given time.
|
|
var/list/materials_prices = list()
|
|
/// Associated list of materials alongside their market trends. 1 is up, 0 is stable, -1 is down.
|
|
var/list/materials_trends = list()
|
|
/// Associated list of materials alongside the life of it's current trend. After it's life is up, it will change to a new trend.
|
|
var/list/materials_trend_life = list()
|
|
/// Associated list of materials alongside their available quantity. This is used to determine how much of a material is available to buy, and how much buying and selling affects the price.
|
|
var/list/materials_quantity = list()
|
|
/// A list of all currently active stock market events.
|
|
var/list/active_events = list()
|
|
/// HTML string that is used to display the market events to the player.
|
|
var/news_string = ""
|
|
|
|
/datum/controller/subsystem/stock_market/Initialize()
|
|
for(var/datum/material/possible_market as anything in subtypesof(/datum/material)) // I need to make this work like this, but lets hardcode it for now
|
|
if(possible_market.tradable)
|
|
materials_prices += possible_market
|
|
materials_prices[possible_market] = possible_market.value_per_unit * SHEET_MATERIAL_AMOUNT
|
|
|
|
materials_trends += possible_market
|
|
materials_trends[possible_market] = rand(MARKET_TREND_DOWNWARD,MARKET_TREND_UPWARD) //aka -1 to 1
|
|
|
|
materials_trend_life += possible_market
|
|
materials_trend_life[possible_market] = rand(1,10)
|
|
|
|
materials_quantity += possible_market
|
|
materials_quantity[possible_market] = possible_market.tradable_base_quantity + (rand(-(possible_market.tradable_base_quantity) * 0.5, possible_market.tradable_base_quantity * 0.5))
|
|
return SS_INIT_SUCCESS
|
|
|
|
/datum/controller/subsystem/stock_market/fire(resumed)
|
|
for(var/datum/material/market as anything in materials_prices)
|
|
handle_trends_and_price(market)
|
|
for(var/datum/stock_market_event/event as anything in active_events)
|
|
event.handle()
|
|
|
|
/**
|
|
* Handles shifts in the cost of materials, and in what direction the material is most likely to move.
|
|
*/
|
|
/datum/controller/subsystem/stock_market/proc/handle_trends_and_price(datum/material/mat)
|
|
if(prob(MARKET_EVENT_PROBABILITY))
|
|
handle_market_event(mat)
|
|
var/trend = materials_trends[mat]
|
|
var/trend_life = materials_trend_life[mat]
|
|
|
|
var/price_units = materials_prices[mat]
|
|
var/price_minimum = round(mat.value_per_unit * SHEET_MATERIAL_AMOUNT * 0.5)
|
|
if(!isnull(mat.minimum_value_override))
|
|
price_minimum = round(mat.minimum_value_override * SHEET_MATERIAL_AMOUNT)
|
|
var/price_maximum = round(mat.value_per_unit * SHEET_MATERIAL_AMOUNT * 3)
|
|
var/price_baseline = mat.value_per_unit * SHEET_MATERIAL_AMOUNT
|
|
var/quantity_baseline = mat.tradable_base_quantity
|
|
|
|
var/stock_quantity = materials_quantity[mat]
|
|
|
|
if(HAS_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING)) //We hardset to the worst possible price and lowest possible impact if sold
|
|
materials_prices[mat] = price_minimum
|
|
materials_quantity[mat] = stock_quantity * 2
|
|
materials_trends[mat] = MARKET_TREND_DOWNWARD
|
|
trend_life = materials_trend_life[mat] = 1
|
|
return
|
|
|
|
if(trend_life == 0)
|
|
///We want to scale our trend so that if we're closer to our minimum or maximum price, we're more likely to trend the other way.
|
|
if((price_units < price_baseline))
|
|
var/chance_swap = 100 - ((clamp((price_units - price_minimum), 1, 1000) / (price_baseline - price_minimum))*100)
|
|
if(prob(chance_swap))
|
|
materials_trends[mat] = MARKET_TREND_UPWARD
|
|
else
|
|
materials_trends[mat] = MARKET_TREND_STABLE
|
|
else if((price_units > price_baseline))
|
|
var/chance_swap = 100 - ((clamp((price_units - price_maximum), 1, 1000) / (price_maximum - price_baseline))*100)
|
|
if(prob(chance_swap))
|
|
materials_trends[mat] = MARKET_TREND_DOWNWARD
|
|
else
|
|
materials_trends[mat] = MARKET_TREND_STABLE
|
|
materials_trend_life[mat] = rand(3,10) // Change our trend life for x number of fires of the subsystem
|
|
else
|
|
materials_trend_life[mat] -= 1
|
|
|
|
var/price_change = 0
|
|
var/quantity_change = 0
|
|
switch(trend)
|
|
if(MARKET_TREND_UPWARD)
|
|
price_change = ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05)) //If we don't ceil, small numbers will get trapped at low values
|
|
quantity_change = -round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05))
|
|
if(MARKET_TREND_STABLE)
|
|
price_change = round(gaussian(0, price_baseline * 0.01))
|
|
quantity_change = round(gaussian(0, quantity_baseline * 0.01))
|
|
if(MARKET_TREND_DOWNWARD)
|
|
price_change = -ROUND_UP(gaussian(price_units * 0.1, price_baseline * 0.05))
|
|
quantity_change = round(gaussian(quantity_baseline * 0.05, quantity_baseline * 0.05))
|
|
materials_prices[mat] = round(clamp(price_units + price_change, price_minimum, price_maximum))
|
|
materials_quantity[mat] = round(clamp(stock_quantity + quantity_change, 0, quantity_baseline * 2))
|
|
|
|
/**
|
|
* Market events are a way to spice up the market and make it more interesting.
|
|
* Randomly one will occur to a random material, and it will change the price of that material more drastically, or reset it to a stable price.
|
|
* Events are also broadcast to the newscaster as a fun little fluff piece. Good way to tell some lore as well, or just make a joke.
|
|
*/
|
|
/datum/controller/subsystem/stock_market/proc/handle_market_event(datum/material/mat)
|
|
var/datum/stock_market_event/event = pick(subtypesof(/datum/stock_market_event))
|
|
event = new event
|
|
if(event.start_event(mat))
|
|
active_events += event
|