/* * Vending machine types - Can be found under /code/modules/vending/ */ /* /obj/machinery/vending/[vendors name here] // --vending machine template :) name = "" desc = "" icon = '' icon_state = "" products = list() contraband = list() premium = list() IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY CANISTER CHARGES in vending_items.dm */ /datum/data/vending_product name = "generic" var/product_path = null var/amount = 0 var/max_amount = 0 /obj/machinery/vending name = "\improper Vendomat" desc = "A generic vending machine." icon = 'icons/obj/vending.dmi' icon_state = "generic" layer = BELOW_OBJ_LAYER density = TRUE verb_say = "beeps" verb_ask = "beeps" verb_exclaim = "beeps" max_integrity = 300 integrity_failure = 100 armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) circuit = /obj/item/circuitboard/machine/vendor var/active = 1 //No sales pitches if off! var/vend_ready = 1 //Are we ready to vend?? Is it time?? // To be filled out at compile time 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/product_slogans = "" //String of slogans separated by semicolons, optional var/product_ads = "" //String of small ad messages in the vending screen - random chance var/list/product_records = list() var/list/hidden_records = list() var/list/coin_records = list() 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/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/seconds_electrified = 0 //Shock customers like an airlock. var/shoot_inventory = 0 //Fire items at customers! We're broken! var/shoot_inventory_chance = 2 var/shut_up = 0 //Stop spouting those godawful pitches! var/extended_inventory = 0 //can we access the hidden inventory? var/scan_id = 1 var/obj/item/coin/coin var/obj/item/stack/spacecash/bill var/global/vending_cache = list() //used for storing the icons of items being vended var/dish_quants = list() //used by the snack machine's custom compartment to count dishes. var/obj/item/vending_refill/refill_canister = null //The type of refill canisters used by this machine. /obj/machinery/vending/Initialize() var/build_inv = FALSE if(!refill_canister) circuit = null build_inv = TRUE . = ..() wires = new /datum/wires/vending(src) if(build_inv) //non-constructable vending machine build_inventory(products, product_records) build_inventory(contraband, hidden_records) build_inventory(premium, coin_records) slogan_list = splittext(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. last_slogan = world.time + rand(0, slogan_delay) power_change() /obj/machinery/vending/Destroy() QDEL_NULL(wires) QDEL_NULL(coin) QDEL_NULL(bill) return ..() /obj/machinery/vending/RefreshParts() //Better would be to make constructable child if(!component_parts) return product_records = list() hidden_records = list() coin_records = list() build_inventory(products, product_records, start_empty = TRUE) build_inventory(contraband, hidden_records, start_empty = TRUE) build_inventory(premium, coin_records, start_empty = TRUE) for(var/obj/item/vending_refill/VR in component_parts) restock(VR) /obj/machinery/vending/deconstruct(disassembled = TRUE) if(!refill_canister) //the non constructable vendors drop metal instead of a machine frame. if(!(flags_1 & NODECONSTRUCT_1)) new /obj/item/stack/sheet/metal(loc, 3) qdel(src) else ..() /obj/machinery/vending/obj_break(damage_flag) if(!(stat & BROKEN) && !(flags_1 & NODECONSTRUCT_1)) stat |= BROKEN icon_state = "[initial(icon_state)]-broken" var/dump_amount = 0 var/found_anything = TRUE while (found_anything) found_anything = FALSE for(var/record in shuffle(product_records)) var/datum/data/vending_product/R = record if(R.amount <= 0) //Try to use a record that actually has something to dump. continue var/dump_path = R.product_path if(!dump_path) continue R.amount-- // busting open a vendor will destroy some of the contents if(found_anything && prob(80)) continue var/obj/O = new dump_path(loc) step(O, pick(GLOB.alldirs)) found_anything = TRUE dump_amount++ if (dump_amount >= 16) return /obj/machinery/vending/proc/build_inventory(list/productlist, list/recordlist, start_empty = FALSE) for(var/typepath in productlist) var/amount = productlist[typepath] if(isnull(amount)) amount = 0 var/atom/temp = typepath var/datum/data/vending_product/R = new /datum/data/vending_product() R.name = initial(temp.name) R.product_path = typepath if(!start_empty) R.amount = amount R.max_amount = amount recordlist += R /obj/machinery/vending/proc/restock(obj/item/vending_refill/canister) if (!canister.products) canister.products = products.Copy() if (!canister.contraband) canister.contraband = contraband.Copy() if (!canister.premium) canister.premium = premium.Copy() . = 0 . += refill_inventory(canister.products, product_records) . += refill_inventory(canister.contraband, hidden_records) . += refill_inventory(canister.premium, coin_records) /obj/machinery/vending/proc/refill_inventory(list/productlist, list/recordlist) . = 0 for(var/R in recordlist) var/datum/data/vending_product/record = R var/diff = min(record.max_amount - record.amount, productlist[record.product_path]) if (diff) productlist[record.product_path] -= diff record.amount += diff . += diff /obj/machinery/vending/proc/update_canister() if (!component_parts) return var/obj/item/vending_refill/R = locate() in component_parts if (!R) CRASH("Constructible vending machine did not have a refill canister") return R.products = unbuild_inventory(product_records) R.contraband = unbuild_inventory(hidden_records) R.premium = unbuild_inventory(coin_records) /obj/machinery/vending/proc/unbuild_inventory(list/recordlist) . = list() for(var/R in recordlist) var/datum/data/vending_product/record = R .[record.product_path] += record.amount /obj/machinery/vending/crowbar_act(mob/living/user, obj/item/I) if(!component_parts) return FALSE default_deconstruction_crowbar(I) return TRUE /obj/machinery/vending/wrench_act(mob/living/user, obj/item/I) if(panel_open) default_unfasten_wrench(user, I, time = 60) return TRUE /obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/I) if(anchored) default_deconstruction_screwdriver(user, icon_state, icon_state, I) cut_overlays() if(panel_open) add_overlay("[initial(icon_state)]-panel") updateUsrDialog() else to_chat(user, "You must first secure [src].") return TRUE /obj/machinery/vending/attackby(obj/item/I, mob/user, params) if(panel_open && is_wire_tool(I)) wires.interact(user) return else if(istype(I, /obj/item/coin)) if(coin) to_chat(user, "[src] already has [coin] inserted") return if(bill) to_chat(user, "[src] already has [bill] inserted") return if(!premium.len) to_chat(user, "[src] doesn't have a coin slot.") return if(!user.transferItemToLoc(I, src)) return coin = I to_chat(user, "You insert [I] into [src].") return else if(istype(I, /obj/item/stack/spacecash)) if(coin) to_chat(user, "[src] already has [coin] inserted") return if(bill) to_chat(user, "[src] already has [bill] inserted") return var/obj/item/stack/S = I if(!premium.len) to_chat(user, "[src] doesn't have a bill slot.") return S.use(1) bill = new S.type(src, 1) to_chat(user, "You insert [I] into [src].") return else if(refill_canister && istype(I, refill_canister)) if (!panel_open) to_chat(user, "You should probably unscrew the service panel first.") else if (stat & (BROKEN|NOPOWER)) to_chat(user, "[src] does not respond.") else //if the panel is open we attempt to refill the machine var/obj/item/vending_refill/canister = I if(canister.get_part_rating() == 0) to_chat(user, "[canister] is empty!") else // instantiate canister if needed var/transferred = restock(canister) if(transferred) to_chat(user, "You loaded [transferred] items in [src].") else to_chat(user, "There's nothing to restock!") return else return ..() /obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/W) if(!istype(W)) return FALSE if((flags_1 & NODECONSTRUCT_1) && !W.works_from_distance) return FALSE if(!component_parts || !refill_canister) return FALSE var/moved = 0 if(panel_open || W.works_from_distance) if(W.works_from_distance) display_parts(user) for(var/I in W) if(istype(I, refill_canister)) moved += restock(I) else display_parts(user) if(moved) to_chat(user, "[moved] items restocked.") W.play_rped_sound() return TRUE /obj/machinery/vending/on_deconstruction() update_canister() . = ..() /obj/machinery/vending/emag_act(mob/user) if(obj_flags & EMAGGED) return obj_flags |= EMAGGED to_chat(user, "You short out the product lock on [src].") /obj/machinery/vending/_try_interact(mob/user) if(seconds_electrified && !(stat & NOPOWER)) if(shock(user, 100)) return return ..() /obj/machinery/vending/ui_interact(mob/user) var/dat = "" dat += "
| [sanitize(R.name)] | " if(R.amount > 0) dat += "[R.amount] | Vend | " else dat += "0 | Vend | " dat += "