diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 91a95b47a74..67ca2162513 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -1,3 +1,5 @@ +#define CAT_HIDDEN 2 // Also in code/game/machinery/vending.dm + /datum/wires/vending holder_type = /obj/machinery/vending wire_count = 4 @@ -27,7 +29,7 @@ var/const/VENDING_WIRE_IDSCAN = 8 . += ..() . += "
The orange light is [V.seconds_electrified ? "off" : "on"].
" . += "The red light is [V.shoot_inventory ? "off" : "blinking"].
" - . += "The green light is [V.extended_inventory ? "on" : "off"].
" + . += "The green light is [(V.categories & CAT_HIDDEN) ? "on" : "off"].
" . += "The [V.scan_id ? "purple" : "yellow"] light is on.
" /datum/wires/vending/UpdatePulsed(var/index) @@ -36,7 +38,7 @@ var/const/VENDING_WIRE_IDSCAN = 8 if(VENDING_WIRE_THROW) V.shoot_inventory = !V.shoot_inventory if(VENDING_WIRE_CONTRABAND) - V.extended_inventory = !V.extended_inventory + V.categories ^= CAT_HIDDEN if(VENDING_WIRE_ELECTRIFY) V.seconds_electrified = 30 if(VENDING_WIRE_IDSCAN) @@ -48,7 +50,7 @@ var/const/VENDING_WIRE_IDSCAN = 8 if(VENDING_WIRE_THROW) V.shoot_inventory = !mended if(VENDING_WIRE_CONTRABAND) - V.extended_inventory = 0 + V.categories &= ~CAT_HIDDEN if(VENDING_WIRE_ELECTRIFY) if(mended) V.seconds_electrified = 0 diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 5a8df08c8ae..09608deb5b3 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1,17 +1,38 @@ -#define CAT_NORMAL 0 -#define CAT_HIDDEN 1 -#define CAT_COIN 2 +#define CAT_NORMAL 1 +#define CAT_HIDDEN 2 // also used in corresponding wires/vending.dm +#define CAT_COIN 4 +/** + * Datum used to hold information about a product in a vending machine + */ /datum/data/vending_product - var/product_name = "generic" + var/product_name = "generic" // Display name for the product var/product_path = null - var/amount = 0 - var/price = 0 - var/display_color = "blue" - var/category = CAT_NORMAL - + var/amount = 0 // Amount held in the vending machine + var/price = 0 // Price to buy one + var/display_color = null // Display color for vending machine listing + var/category = CAT_NORMAL // CAT_HIDDEN for contraband, CAT_COIN for premium +/datum/data/vending_product/New(var/path, var/name = null, var/amount = 1, var/price = 0, var/color = null, var/category = CAT_NORMAL) + ..() + + src.product_path = path + + if(!name) + var/atom/tmp = new path + src.product_name = initial(tmp.name) + del(tmp) + else + src.product_name = name + + src.amount = amount + src.price = price + src.display_color = color + src.category = category +/** + * A vending machine + */ /obj/machinery/vending name = "Vendomat" desc = "A generic vending machine." @@ -21,66 +42,105 @@ anchored = 1 density = 1 + var/icon_vend //Icon_state when vending + var/icon_deny //Icon_state when denying access + + // Power use_power = 1 idle_power_usage = 10 var/vend_power_usage = 150 //actuators and stuff + // Vending-related var/active = 1 //No sales pitches if off! var/vend_ready = 1 //Are we ready to vend?? Is it time?? var/vend_delay = 10 //How long does it take to vend? - var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now. - - // To be filled out at compile time + var/categories = CAT_NORMAL // Bitmask of cats we're currently showing + var/datum/data/vending_product/currently_vending = null // What we're requesting payment for right now + + /* + Variables used to initialize the product list + These are used for initialization only, and so are optional if + product_records is specified + */ var/list/products = list() // For each, use the following pattern: var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2) var/list/premium = list() // No specified amount = only one in stock var/list/prices = list() // Prices for each item, list(/type/path = price), items not in the list don't have a price. - var/product_slogans = "" //String of slogans separated by semicolons, optional - var/product_ads = "" //String of small ad messages in the vending screen - random chance + // List of vending_product items available. var/list/product_records = list() - var/list/hidden_records = list() - var/list/coin_records = list() + + + // Variables used to initialize advertising + var/product_slogans = "" //String of slogans spoken out loud, separated by semicolons + var/product_ads = "" //String of small ad messages in the vending screen + + var/list/ads_list = list() + + // Stuff relating vocalizations var/list/slogan_list = list() - var/list/small_ads = list() // small ad messages in the vending screen - random chance of popping up whenever you open it + var/shut_up = 1 //Stop spouting those godawful pitches! var/vend_reply //Thank you for shopping! var/last_reply = 0 var/last_slogan = 0 //When did we last pitch? var/slogan_delay = 6000 //How long until we can pitch again? - var/icon_vend //Icon_state when vending! - var/icon_deny //Icon_state when vending! - //var/emagged = 0 //Ignores if somebody doesn't have card access to that machine. + + // Things that can go wrong + emagged = 0 //Ignores if somebody doesn't have card access to that machine. var/seconds_electrified = 0 //Shock customers like an airlock. var/shoot_inventory = 0 //Fire items at customers! We're broken! - var/shut_up = 1 //Stop spouting those godawful pitches! - var/extended_inventory = 0 //can we access the hidden inventory? + var/scan_id = 1 var/obj/item/weapon/coin/coin var/datum/wires/vending/wires = null - var/check_accounts = 0 // 1 = requires PIN and checks accounts. 0 = You slide an ID, it vends, SPACE COMMUNISM! - /obj/machinery/vending/New() ..() wires = new(src) spawn(4) - src.slogan_list = text2list(src.product_slogans, ";") + if(src.product_slogans) + src.slogan_list += text2list(src.product_slogans, ";") - // So not all machines speak at the exact same time. - // The first time this machine says something will be at slogantime + this random value, - // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. - src.last_slogan = world.time + rand(0, slogan_delay) + // So not all machines speak at the exact same time. + // The first time this machine says something will be at slogantime + this random value, + // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. + src.last_slogan = world.time + rand(0, slogan_delay) - src.build_inventory(products) - //Add hidden inventory - src.build_inventory(contraband, 1) - src.build_inventory(premium, 0, 1) + if(src.product_ads) + src.ads_list += text2list(src.product_ads, ";") + + src.build_inventory() power_change() return return +/** + * Build src.produdct_records from the products lists + * + * src.products, src.contraband, src.premium, and src.prices allow specifying + * products that the vending machine is to carry without manually populating + * src.product_records. + */ +/obj/machinery/vending/proc/build_inventory() + var/list/all_products = list( + list(src.products, CAT_NORMAL), + list(src.contraband, CAT_HIDDEN), + list(src.premium, CAT_COIN)) + + for(var/current_list in all_products) + var/category = current_list[2] + + for(var/entry in current_list[1]) + var/datum/data/vending_product/product = new/datum/data/vending_product(entry) + + product.price = (entry in src.prices) ? src.prices[entry] : 0 + product.amount = (current_list[1][entry]) ? current_list[1][entry] : 1 + product.category = category + + src.product_records.Add(product) + /obj/machinery/vending/Del() del(wires) // qdel wires = null @@ -116,36 +176,6 @@ return -/obj/machinery/vending/proc/build_inventory(var/list/productlist,hidden=0,req_coin=0) - - for(var/typepath in productlist) - var/amount = productlist[typepath] - var/price = prices[typepath] - if(isnull(amount)) amount = 1 - - var/datum/data/vending_product/R = new /datum/data/vending_product() - - R.product_path = typepath - R.amount = amount - R.price = price - R.display_color = pick("red","blue","green") - - if(hidden) - R.category=CAT_HIDDEN - hidden_records += R - else if(req_coin) - R.category=CAT_COIN - coin_records += R - else - R.category=CAT_NORMAL - product_records += R - - var/atom/temp = typepath - R.product_name = initial(temp.name) - -// world << "Added: [R.product_name]] - [R.amount] - [R.product_path]" - return - /obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob) if (currently_vending) var/paid = 0 @@ -207,7 +237,7 @@ else if(src.panel_open) - for(var/datum/data/vending_product/R in product_records) + for(var/datum/data/vending_product/R in product_records) if(istype(W, R.product_path)) stock(R, user) del(W) @@ -346,31 +376,6 @@ /obj/machinery/vending/attack_ai(mob/user as mob) return attack_hand(user) -/obj/machinery/vending/proc/GetProductIndex(var/datum/data/vending_product/P) - var/list/plist - switch(P.category) - if(CAT_NORMAL) - plist=product_records - if(CAT_HIDDEN) - plist=hidden_records - if(CAT_COIN) - plist=coin_records - else - warning("UNKNOWN CATEGORY [P.category] IN TYPE [P.product_path] INSIDE [type]!") - return plist.Find(P) - -/obj/machinery/vending/proc/GetProductByID(var/pid, var/category) - switch(category) - if(CAT_NORMAL) - return product_records[pid] - if(CAT_HIDDEN) - return hidden_records[pid] - if(CAT_COIN) - return coin_records[pid] - else - warning("UNKNOWN PRODUCT: PID: [pid], CAT: [category] INSIDE [type]!") - return null - /obj/machinery/vending/attack_hand(mob/user as mob) if(stat & (BROKEN|NOPOWER)) return @@ -393,28 +398,24 @@ var/dat = "
[vendorname]


" //display the name, and added a horizontal rule dat += "Select an item:

" //the rest is just general spacing and bolding - if (premium.len > 0) - dat += "Coin slot: [coin ? coin : "No coin inserted"] (Remove)
" - if (src.product_records.len == 0) dat += "No product loaded!" else - var/list/display_records = list() - display_records += src.product_records - if(src.extended_inventory) - display_records += src.hidden_records - if(src.coin) - display_records += src.coin_records - - for (var/datum/data/vending_product/R in display_records) - dat += "[R.product_name]:" - dat += " [R.amount] " - if(R.price) - dat += " (Price: [R.price])" - if (R.amount > 0) - var/idx=GetProductIndex(R) - dat += " (Vend)" + for(var/idx = 1 to src.product_records.len) + var/datum/data/vending_product/product = src.product_records[idx] + if(!(product.category & src.categories)) + continue + + if(product.display_color) + dat += "[product.product_name]:" + dat += " [product.amount] " + else + dat += "[product.product_name]: [product.amount]" + if(product.price) + dat += " (Price: [product.price])" + if (product.amount > 0) + dat += " (Vend)" else dat += " SOLD OUT" dat += "
" @@ -424,7 +425,7 @@ if(panel_open) dat += wires() - if(product_slogans != "") + if(slogan_list.len > 0) dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle" user << browse(dat, "window=vending") @@ -471,14 +472,10 @@ flick(icon_deny,src) return - var/idx=text2num(href_list["vend"]) - var/cat=text2num(href_list["cat"]) + var/key = text2num(href_list["vend"]) + var/datum/data/vending_product/R = product_records[key] - var/datum/data/vending_product/R = GetProductByID(idx,cat) - if (!R || !istype(R) || !R.product_path || R.amount <= 0) - return - - if(R.price == null) + if(R.price <= 0) src.vend(R, usr) else src.currently_vending = R @@ -507,7 +504,7 @@ return src.vend_ready = 0 //One thing at a time!! - if (R in coin_records) + if (R.category & CAT_COIN) if(!coin) user << "\blue You need to insert a coin to get this item." return @@ -848,35 +845,32 @@ contraband = list(/obj/item/seeds/amanitamycelium = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/libertymycelium = 2,/obj/item/seeds/mtearseed = 2, /obj/item/seeds/nettleseed = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/shandseed = 2,) premium = list(/obj/item/toy/waterflower = 1) + +/** + * Populate hydroseeds product_records + * + * This needs to be customized to fetch the actual names of the seeds, otherwise + * the machine would simply list "packet of seeds" times 20 + */ +/obj/machinery/vending/hydroseeds/build_inventory() + var/list/all_products = list( + list(src.products, CAT_NORMAL), + list(src.contraband, CAT_HIDDEN), + list(src.premium, CAT_COIN)) -/obj/machinery/vending/hydroseeds/build_inventory(var/list/productlist,hidden=0,req_coin=0) + for(var/current_list in all_products) + var/category = current_list[2] - for(var/typepath in productlist) - var/amount = productlist[typepath] - var/price = prices[typepath] - if(isnull(amount)) amount = 1 + for(var/entry in current_list[1]) + var/obj/item/seeds/S = new entry(src) + var/name = S.name + var/datum/data/vending_product/product = new/datum/data/vending_product(entry, name) - var/datum/data/vending_product/R = new /datum/data/vending_product() - - R.product_path = typepath - R.amount = amount - R.price = price - R.display_color = pick("red","blue","green") - - if(hidden) - R.category=CAT_HIDDEN - hidden_records += R - else if(req_coin) - R.category=CAT_COIN - coin_records += R - else - R.category=CAT_NORMAL - product_records += R - - var/obj/item/seeds/S = new typepath(src) - R.product_name = S.name - del(S) - return + product.price = (entry in src.prices) ? src.prices[entry] : 0 + product.amount = (current_list[1][entry]) ? current_list[1][entry] : 1 + product.category = category + + src.product_records.Add(product) /obj/machinery/vending/magivend name = "MagiVend"