Files
vgstation13/code/modules/trader/trade_system.dm

116 lines
4.3 KiB
Plaintext

//Price fluxuations: swings -20% to +20%
//Prestige: money kept in Shoal account (each $250 gives -1%, max -20%)
//Loyal customer: each $100 spent gives -1% (max -10%)
var/datum/subsystem/trade_system/SStrade
/datum/subsystem/trade_system
name = "Trade System"
init_order = SS_INIT_OBJECT+0.1 //Always initialize just before objects
flags = SS_TICKER
wait = (3*SS_WAIT_ENGINES) //check in no more than once every thirty seconds
var/datum/trade_product/flash_sale_target = null //An extra 30% off!
var/list/all_twindows = list() //All trade windows
var/list/all_trade_merch = list() //The list of all trade products, kept as elements
var/list/trade_databank = list() //The above, converted to associative list format for use in UI
var/list/loyal_customers = list() //Associative list, associates face identities with cash spent.
/datum/subsystem/trade_system/New()
NEW_SS_GLOBAL(SStrade)
/datum/subsystem/trade_system/Initialize(timeofday)
for(var/path in subtypesof(/datum/trade_product))
all_trade_merch += new path
market_flux(FALSE)
..()
/datum/subsystem/trade_system/fire(resumed = FALSE)
if(flags & SS_NO_FIRE)
if(trader_account)
message_admins("Trade subsystem resumed, trader account found.")
flags &= ~SS_NO_FIRE
//if(state == SS_PAUSED)
//state = SS_RUNNING
return
if(trader_account)
if(prob(FLUX_CHANCE))
market_flux()
restock_chance()
flash_sale()
for(var/obj/structure/trade_window/TW in all_twindows)
nanomanager.update_uis(TW)
else
flags |= SS_NO_FIRE
//pause()
message_admins("Trade subsystem was paused due to lack of a trader account.")
/datum/subsystem/trade_system/proc/market_flux(var/update_windows = TRUE)
for(var/datum/trade_product/TP in all_trade_merch)
TP.flux_rate = 1+(rand(-20,20)/100) //Anywhere from 0.8 to 1.2
if(update_windows)
for(var/obj/structure/trade_window/TW in all_twindows)
TW.market_flux()
/datum/subsystem/trade_system/proc/flash_sale()
//Every 10 in the account gives a 1% chance for a flash sale, up to 100% at 1000
flash_sale_target = null
var/prestige = trader_account.money
if(prestige >= 1000 || prob(round(prestige/10)))
var/shuffled = shuffle(all_trade_merch)
for(var/datum/trade_product/TP in shuffled)
if(TP.totalsold >= TP.maxunits)
continue
flash_sale_target = TP
return
/datum/subsystem/trade_system/proc/restock_chance()
//Every 100 in the account gives a 1% chance for a restocked item, up to 10%
//In excess of 1000, you get extra rolls, up to three rolls.
var/sector_prestige = min(3000,trader_account.money)
while(sector_prestige>1000)
restock()
sector_prestige -= 1000
if(sector_prestige && prob(round(sector_prestige/100)))
restock()
/datum/subsystem/trade_system/proc/restock()
var/list/weighted_restocks = list()
for(var/datum/trade_product/TP in all_trade_merch)
if(!TP.can_restock())
continue
weighted_restocks[TP] = TP.restock_weight()
var/datum/trade_product/tostock = pickweight(weighted_restocks)
if(tostock)
tostock.restock()
/datum/subsystem/trade_system/proc/rebuild_databank(mob/user)
trade_databank.Cut() //empty the list
for(var/datum/trade_product/TP in all_trade_merch)
if(TP.totalsold >= TP.maxunits)
continue //Sold out
//Adds a list of lists. BYOND's default behavior is to append the contents of one list to the list
//So the outer list "dissolves", leaving only the list, which is associative and contains name, category, etc data
var/product_to_list = list()
product_to_list["name"] = TP.name
product_to_list["price"] = TP.current_price(user)
product_to_list["marketforces"] = round(100*(TP.flux_rate - 1))
product_to_list["flashed"] = (TP.isflashed() == 1 ? FALSE : TRUE)
product_to_list["category"] = TP.sales_category
product_to_list["remaining"] = TP.maxunits - TP.totalsold
trade_databank += list(product_to_list)
/datum/subsystem/trade_system/proc/shoal_prestige_factor()
if(trader_account.money >= 5000)
return 0.8
return 1-round(trader_account.money / 25000, 0.01)
/datum/subsystem/trade_system/proc/loyal_customer(mob/living/carbon/human/user)
if(!istype(user))
return 1.5
if(!(user.get_face_name() in loyal_customers))
return 1.5
if(loyal_customers[user.get_face_name()] >= 1000)
return 0.9
return 1-round(loyal_customers[user.get_face_name()]/10000,0.01) //1% off per $100 spent, up to 10% off