mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
Update from dev.
This commit is contained in:
@@ -1287,7 +1287,6 @@
|
||||
#include "code\modules\power\antimatter\containment_jar.dm"
|
||||
#include "code\modules\power\antimatter\control.dm"
|
||||
#include "code\modules\power\antimatter\shielding.dm"
|
||||
#include "code\modules\power\rust\areas.dm"
|
||||
#include "code\modules\power\rust\circuits_and_design.dm"
|
||||
#include "code\modules\power\rust\core_control.dm"
|
||||
#include "code\modules\power\rust\core_field.dm"
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
return level in config.station_levels
|
||||
|
||||
/proc/isNotStationLevel(var/level)
|
||||
return !isStationLevel()
|
||||
return !isStationLevel(level)
|
||||
|
||||
/proc/isPlayerLevel(var/level)
|
||||
return level in config.player_levels
|
||||
|
||||
@@ -288,6 +288,7 @@ datum/controller/game_controller/proc/process_machines_process()
|
||||
last_thing_processed = Machine.type
|
||||
if(Machine.process() != PROCESS_KILL)
|
||||
if(Machine)
|
||||
Machine.power_change()
|
||||
if(Machine.use_power)
|
||||
Machine.auto_use_power()
|
||||
continue
|
||||
|
||||
@@ -34,14 +34,17 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
|
||||
|
||||
/datum/wires/airlock/GetInteractWindow()
|
||||
var/obj/machinery/door/airlock/A = holder
|
||||
var/haspower = A.arePowerSystemsOn() //If there's no power, then no lights will be on.
|
||||
|
||||
. += ..()
|
||||
. += text("<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
|
||||
(A.lights ? "The door bolt lights are on." : "The door bolt lights are off!"),
|
||||
((A.hasPower()) ? "The test light is on." : "The test light is off!"),
|
||||
((A.aiControlDisabled==0 && !A.emagged) ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
|
||||
(A.safe==0 ? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
|
||||
(A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
|
||||
(A.aiDisabledIdScanner==0 ? "The IDScan light is on." : "The IDScan light is off."))
|
||||
. += text("<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]",
|
||||
(A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
|
||||
((A.lights && haspower) ? "The door bolt lights are on." : "The door bolt lights are off!"),
|
||||
((haspower) ? "The test light is on." : "The test light is off!"),
|
||||
((A.aiControlDisabled==0 && !A.emagged && haspower)? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
|
||||
((A.safe==0 && haspower)? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
|
||||
((A.normalspeed==0 && haspower)? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
|
||||
((A.aiDisabledIdScanner==0 && haspower)? "The IDScan light is on." : "The IDScan light is off."))
|
||||
|
||||
/datum/wires/airlock/UpdateCut(var/index, var/mended)
|
||||
|
||||
@@ -127,7 +130,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
|
||||
switch(index)
|
||||
if(AIRLOCK_WIRE_IDSCAN)
|
||||
//Sending a pulse through flashes the red light on the door (if the door has power).
|
||||
if(A.hasPower() && A.density)
|
||||
if(A.arePowerSystemsOn() && A.density)
|
||||
A.do_animate("deny")
|
||||
if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2)
|
||||
//Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter).
|
||||
@@ -139,7 +142,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
|
||||
A.locked = 1
|
||||
A.audible_message("You hear a click from the bottom of the door.", null, 1)
|
||||
else
|
||||
if(A.hasPower()) //only can raise bolts if power's on
|
||||
if(A.arePowerSystemsOn()) //only can raise bolts if power's on
|
||||
A.locked = 0
|
||||
A.audible_message("You hear a click from the bottom of the door.", null, 1)
|
||||
A.update_icon()
|
||||
|
||||
@@ -11,7 +11,7 @@ var/const/AALARM_WIRE_AALARM = 16
|
||||
|
||||
/datum/wires/alarm/CanUse(var/mob/living/L)
|
||||
var/obj/machinery/alarm/A = holder
|
||||
if(A.wiresexposed)
|
||||
if(A.wiresexposed && A.buildstage == 2)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -17,17 +19,12 @@ var/const/VENDING_WIRE_IDSCAN = 8
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/wires/vending/Interact(var/mob/living/user)
|
||||
if(CanUse(user))
|
||||
var/obj/machinery/vending/V = holder
|
||||
V.attack_hand(user)
|
||||
|
||||
/datum/wires/vending/GetInteractWindow()
|
||||
var/obj/machinery/vending/V = holder
|
||||
. += ..()
|
||||
. += "<BR>The orange light is [V.seconds_electrified ? "off" : "on"].<BR>"
|
||||
. += "The red light is [V.shoot_inventory ? "off" : "blinking"].<BR>"
|
||||
. += "The green light is [V.extended_inventory ? "on" : "off"].<BR>"
|
||||
. += "The green light is [(V.categories & CAT_HIDDEN) ? "on" : "off"].<BR>"
|
||||
. += "The [V.scan_id ? "purple" : "yellow"] light is on.<BR>"
|
||||
|
||||
/datum/wires/vending/UpdatePulsed(var/index)
|
||||
@@ -36,7 +33,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 +45,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
|
||||
|
||||
@@ -679,11 +679,16 @@ var/list/datum/dna/hivemind_bank = list()
|
||||
//////////
|
||||
|
||||
/mob/proc/sting_can_reach(mob/M as mob, sting_range = 1)
|
||||
if(M.loc == src.loc) return 1 //target and source are in the same thing
|
||||
if(!isturf(src.loc) || !isturf(M.loc)) return 0 //One is inside, the other is outside something.
|
||||
if(AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, sting_range)) //If a path exists, good!
|
||||
return 1
|
||||
return 0
|
||||
if(M.loc == src.loc)
|
||||
return 1 //target and source are in the same thing
|
||||
if(!isturf(src.loc) || !isturf(M.loc))
|
||||
src << "<span class='warning'>We cannot reach \the [M] with a sting!</span>"
|
||||
return 0 //One is inside, the other is outside something.
|
||||
// Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising
|
||||
if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail
|
||||
src << "<span class='warning'>We cannot find a path to sting \the [M] by!</span>"
|
||||
return 0
|
||||
return 1
|
||||
|
||||
//Handles the general sting code to reduce on copypasta (seeming as somebody decided to make SO MANY dumb abilities)
|
||||
/mob/proc/changeling_sting(var/required_chems=0, var/verb_path)
|
||||
|
||||
@@ -921,8 +921,13 @@ table tr:first-child th:first-child { border: none;}
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if (wiresexposed && ((istype(W, /obj/item/device/multitool) || istype(W, /obj/item/weapon/wirecutters))))
|
||||
return attack_hand(user)
|
||||
if (wiresexposed && istype(W, /obj/item/weapon/wirecutters))
|
||||
user.visible_message("<span class='warning'>[user] has cut the wires inside \the [src]!</span>", "You have cut the wires inside \the [src].")
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 5)
|
||||
buildstage = 1
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
@@ -1309,7 +1314,7 @@ FIRE ALARM
|
||||
/obj/machinery/firealarm/proc/delayed_reset()
|
||||
var/area/A = get_area(src)
|
||||
if (!A) return
|
||||
|
||||
|
||||
src = null
|
||||
spawn(600)
|
||||
A.firereset()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// Allows remote operation of electrical systems on station (SMESs and Breaker Boxes)
|
||||
|
||||
/obj/machinery/computer/rcon
|
||||
name = "\improper RCON remote control console"
|
||||
name = "\improper RCON console"
|
||||
desc = "Console used to remotely control machinery on the station."
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "ai-fixer"
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Control Console", 600, 400)
|
||||
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Console", 600, 400)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
@@ -330,7 +330,7 @@ About the new airlock wires panel:
|
||||
return ((src.aiControlDisabled==1) && (!hackProof) && (!src.isAllPowerLoss()));
|
||||
|
||||
/obj/machinery/door/airlock/proc/arePowerSystemsOn()
|
||||
if (stat & NOPOWER)
|
||||
if (stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0)
|
||||
|
||||
@@ -451,7 +451,7 @@ About the new airlock wires panel:
|
||||
if(density)
|
||||
flick("door_spark", src)
|
||||
if("deny")
|
||||
if(density && !(stat & (BROKEN|NOPOWER)))
|
||||
if(density && src.arePowerSystemsOn())
|
||||
flick("door_deny", src)
|
||||
return
|
||||
|
||||
@@ -900,12 +900,7 @@ About the new airlock wires panel:
|
||||
var/obj/item/weapon/pai_cable/cable = C
|
||||
cable.plugin(src, user)
|
||||
else if(!repairing && istype(C, /obj/item/weapon/crowbar))
|
||||
var/beingcrowbarred = null
|
||||
if(istype(C, /obj/item/weapon/crowbar) )
|
||||
beingcrowbarred = 1 //derp, Agouri
|
||||
else
|
||||
beingcrowbarred = 0
|
||||
if( beingcrowbarred && src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) )
|
||||
if(src.p_open && (operating < 0 || (!operating && welded && !src.arePowerSystemsOn() && density && (!src.locked || (stat & BROKEN)))) )
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
|
||||
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics from the airlock assembly.")
|
||||
if(do_after(user,40))
|
||||
@@ -936,7 +931,7 @@ About the new airlock wires panel:
|
||||
|
||||
del(src)
|
||||
return
|
||||
else if(arePowerSystemsOn() && !(stat & BROKEN))
|
||||
else if(arePowerSystemsOn())
|
||||
user << "\blue The airlock's motors resist your efforts to force it."
|
||||
else if(locked)
|
||||
user << "\blue The airlock's bolts prevent it from being forced."
|
||||
@@ -946,22 +941,22 @@ About the new airlock wires panel:
|
||||
else
|
||||
spawn(0) close(1)
|
||||
|
||||
else if(istype(C, /obj/item/weapon/twohanded/fireaxe) && (!arePowerSystemsOn() || (stat & BROKEN)))
|
||||
else if(istype(C, /obj/item/weapon/twohanded/fireaxe) && !arePowerSystemsOn())
|
||||
if(locked)
|
||||
user << "\blue The airlock's bolts prevent it from being forced."
|
||||
else if( !welded && !operating )
|
||||
if(density)
|
||||
var/obj/item/weapon/twohanded/fireaxe/F = C
|
||||
if(F:wielded)
|
||||
if(F.wielded)
|
||||
spawn(0) open(1)
|
||||
else
|
||||
user << "\red You need to be wielding the Fire axe to do that."
|
||||
user << "\red You need to be wielding \the [C] to do that."
|
||||
else
|
||||
var/obj/item/weapon/twohanded/fireaxe/F = C
|
||||
if(F:wielded)
|
||||
if(F.wielded)
|
||||
spawn(0) close(1)
|
||||
else
|
||||
user << "\red You need to be wielding the Fire axe to do that."
|
||||
user << "\red You need to be wielding \the [C] to do that."
|
||||
|
||||
else
|
||||
..()
|
||||
@@ -1007,7 +1002,9 @@ About the new airlock wires panel:
|
||||
if(operating || welded || locked)
|
||||
return
|
||||
if(!forced)
|
||||
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) )
|
||||
//despite the name, this wire is for general door control.
|
||||
//Bolts are already covered by the check for locked, above
|
||||
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
|
||||
return
|
||||
if(safe)
|
||||
for(var/turf/turf in locs)
|
||||
@@ -1131,9 +1128,6 @@ About the new airlock wires panel:
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/airlock/proc/hasPower()
|
||||
return ((src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) && !(stat & (NOPOWER|BROKEN)))
|
||||
|
||||
/obj/machinery/door/airlock/proc/prison_open()
|
||||
src.unlock()
|
||||
src.open()
|
||||
|
||||
@@ -8,11 +8,6 @@ obj/machinery/door/airlock
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/cur_command = null //the command the door is currently attempting to complete
|
||||
|
||||
obj/machinery/door/airlock/proc/can_radio()
|
||||
if(!arePowerSystemsOn())
|
||||
return 0
|
||||
return 1
|
||||
|
||||
obj/machinery/door/airlock/process()
|
||||
..()
|
||||
if (arePowerSystemsOn())
|
||||
@@ -21,8 +16,6 @@ obj/machinery/door/airlock/process()
|
||||
obj/machinery/door/airlock/receive_signal(datum/signal/signal)
|
||||
if (!arePowerSystemsOn()) return //no power
|
||||
|
||||
if (!can_radio()) return //no radio
|
||||
|
||||
if(!signal || signal.encryption) return
|
||||
|
||||
if(id_tag != signal.data["tag"] || !signal.data["command"]) return
|
||||
|
||||
@@ -70,7 +70,7 @@ datum/track/New(var/title_name, var/audio)
|
||||
return
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
usr << "\the [src] doesn't appear to function."
|
||||
usr << "\The [src] doesn't appear to function."
|
||||
return
|
||||
|
||||
if(href_list["change_track"])
|
||||
@@ -109,7 +109,7 @@ datum/track/New(var/title_name, var/audio)
|
||||
|
||||
/obj/machinery/media/jukebox/interact(mob/user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
usr << "\the [src] doesn't appear to function."
|
||||
usr << "\The [src] doesn't appear to function."
|
||||
return
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
@@ -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,68 +42,107 @@
|
||||
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
|
||||
var/status_message = "" // Status screen messages like "insufficient funds", displayed in NanoUI
|
||||
var/status_error = 0 // Set to 1 if status_message is an error
|
||||
|
||||
/*
|
||||
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!
|
||||
var/obj/item/weapon/spacecash/ewallet/ewallet
|
||||
|
||||
|
||||
/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
|
||||
@@ -118,37 +178,30 @@
|
||||
|
||||
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 && vendor_account && !vendor_account.suspended)
|
||||
var/paid = 0
|
||||
var/handled = 0
|
||||
if(istype(W, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/C = W
|
||||
paid = pay_with_card(C)
|
||||
handled = 1
|
||||
else if (istype(W, /obj/item/weapon/spacecash/ewallet))
|
||||
var/obj/item/weapon/spacecash/ewallet/C = W
|
||||
paid = pay_with_ewallet(C)
|
||||
handled = 1
|
||||
else if (istype(W, /obj/item/weapon/spacecash))
|
||||
var/obj/item/weapon/spacecash/C = W
|
||||
paid = pay_with_cash(C, user)
|
||||
handled = 1
|
||||
|
||||
if(paid)
|
||||
src.vend(currently_vending, usr)
|
||||
return
|
||||
else if(handled)
|
||||
nanomanager.update_uis(src)
|
||||
return // don't smack that machine with your 2 thalers
|
||||
|
||||
if (istype(W, /obj/item/weapon/card/emag))
|
||||
src.emagged = 1
|
||||
user << "You short out the product lock on [src]"
|
||||
@@ -159,7 +212,8 @@
|
||||
src.overlays.Cut()
|
||||
if(src.panel_open)
|
||||
src.overlays += image(src.icon, "[initial(icon_state)]-panel")
|
||||
src.updateUsrDialog()
|
||||
|
||||
nanomanager.update_uis(src) // Speaker switch is on the main UI, not wires UI
|
||||
return
|
||||
else if(istype(W, /obj/item/device/multitool)||istype(W, /obj/item/weapon/wirecutters))
|
||||
if(src.panel_open)
|
||||
@@ -169,19 +223,11 @@
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
coin = W
|
||||
categories |= CAT_COIN
|
||||
user << "\blue You insert the [W] into the [src]"
|
||||
nanomanager.update_uis(src)
|
||||
return
|
||||
else if(istype(W, /obj/item/weapon/card) && currently_vending)
|
||||
var/obj/item/weapon/card/I = W
|
||||
scan_card(I)
|
||||
else if (istype(W, /obj/item/weapon/spacecash/ewallet))
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
ewallet = W
|
||||
user << "\blue You insert the [W] into the [src]"
|
||||
|
||||
else if(istype(W, /obj/item/weapon/wrench))
|
||||
|
||||
if(do_after(user, 20))
|
||||
if(!src) return
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
@@ -204,162 +250,205 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/vending/proc/scan_card(var/obj/item/weapon/card/I)
|
||||
if(!currently_vending) return
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/C = I
|
||||
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
|
||||
var/datum/money_account/CH = get_account(C.associated_account_number)
|
||||
if (CH) // Only proceed if card contains proper account number.
|
||||
if(!CH.suspended)
|
||||
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
|
||||
if(vendor_account)
|
||||
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
|
||||
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
|
||||
transfer_and_vend(D)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
|
||||
else
|
||||
//Just Vend it.
|
||||
transfer_and_vend(CH)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Connected account has been suspended.</span>"
|
||||
/**
|
||||
* Receive payment with cashmoney.
|
||||
*
|
||||
* usr is the mob who gets the change.
|
||||
*/
|
||||
/obj/machinery/vending/proc/pay_with_cash(var/obj/item/weapon/spacecash/cashmoney, mob/user)
|
||||
if(currently_vending.price > cashmoney.worth)
|
||||
|
||||
// This is not a status display message, since it's something the character
|
||||
// themselves is meant to see BEFORE putting the money in
|
||||
usr << "\icon[cashmoney] <span class='warning'>That is not enough money.</span>"
|
||||
return 0
|
||||
|
||||
if(istype(cashmoney, /obj/item/weapon/spacecash/bundle))
|
||||
// Bundles can just have money subtracted, and will work
|
||||
|
||||
visible_message("<span class='info'>[usr] inserts some cash into [src].</span>")
|
||||
var/obj/item/weapon/spacecash/bundle/cashmoney_bundle = cashmoney
|
||||
cashmoney_bundle.worth -= currently_vending.price
|
||||
|
||||
if(cashmoney_bundle.worth <= 0)
|
||||
usr.drop_from_inventory(cashmoney_bundle)
|
||||
del(cashmoney_bundle)
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Error: Unable to access your account. Please contact technical support if problem persists.</span>"
|
||||
|
||||
/obj/machinery/vending/proc/transfer_and_vend(var/datum/money_account/acc)
|
||||
if(acc)
|
||||
var/transaction_amount = currently_vending.price
|
||||
if(transaction_amount <= acc.money)
|
||||
|
||||
//transfer the money
|
||||
acc.money -= transaction_amount
|
||||
vendor_account.money += transaction_amount
|
||||
|
||||
//create entries in the two account transaction logs
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "[vendor_account.owner_name] (via [src.name])"
|
||||
T.purpose = "Purchase of [currently_vending.product_name]"
|
||||
if(transaction_amount > 0)
|
||||
T.amount = "([transaction_amount])"
|
||||
else
|
||||
T.amount = "[transaction_amount]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
acc.transaction_log.Add(T)
|
||||
//
|
||||
T = new()
|
||||
T.target_name = acc.owner_name
|
||||
T.purpose = "Purchase of [currently_vending.product_name]"
|
||||
T.amount = "[transaction_amount]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
vendor_account.transaction_log.Add(T)
|
||||
|
||||
// Vend the item
|
||||
src.vend(src.currently_vending, usr)
|
||||
currently_vending = null
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have that much money!</span>"
|
||||
cashmoney_bundle.update_icon()
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Error: Unable to access your account. Please contact technical support if problem persists.</span>"
|
||||
// Bills (banknotes) cannot really have worth different than face value,
|
||||
// so we have to eat the bill and spit out change in a bundle
|
||||
// This is really dirty, but there's no superclass for all bills, so we
|
||||
// just assume that all spacecash that's not something else is a bill
|
||||
|
||||
visible_message("<span class='info'>[usr] inserts a bill into [src].</span>")
|
||||
var/left = cashmoney.worth - currently_vending.price
|
||||
usr.drop_from_inventory(cashmoney)
|
||||
del(cashmoney)
|
||||
|
||||
if(left)
|
||||
spawn_money(left, src.loc, user)
|
||||
|
||||
// Vending machines have no idea who paid with cash
|
||||
credit_purchase("(cash)")
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Scan a chargecard and deduct payment from it.
|
||||
*
|
||||
* Takes payment for whatever is the currently_vending item. Returns 1 if
|
||||
* successful, 0 if failed.
|
||||
*/
|
||||
/obj/machinery/vending/proc/pay_with_ewallet(var/obj/item/weapon/spacecash/ewallet/wallet)
|
||||
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
|
||||
if(currently_vending.price > wallet.worth)
|
||||
src.status_message = "Insufficient funds on chargecard."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
else
|
||||
wallet.worth -= currently_vending.price
|
||||
credit_purchase("[wallet.owner_name] (chargecard)")
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Scan a card and attempt to transfer payment from associated account.
|
||||
*
|
||||
* Takes payment for whatever is the currently_vending item. Returns 1 if
|
||||
* successful, 0 if failed
|
||||
*/
|
||||
/obj/machinery/vending/proc/pay_with_card(var/obj/item/weapon/card/id/I)
|
||||
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
|
||||
var/datum/money_account/customer_account = get_account(I.associated_account_number)
|
||||
if (!customer_account)
|
||||
src.status_message = "Error: Unable to access account. Please contact technical support if problem persists."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
|
||||
if(customer_account.suspended)
|
||||
src.status_message = "Unable to access account: account suspended."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
|
||||
// Have the customer punch in the PIN before checking if there's enough money. Prevents people from figuring out acct is
|
||||
// empty at high security levels
|
||||
if(customer_account.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
|
||||
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
|
||||
customer_account = attempt_account_access(I.associated_account_number, attempt_pin, 2)
|
||||
|
||||
if(!customer_account)
|
||||
src.status_message = "Unable to access account: incorrect credentials."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
|
||||
if(currently_vending.price > customer_account.money)
|
||||
src.status_message = "Insufficient funds in account."
|
||||
src.status_error = 1
|
||||
return 0
|
||||
else
|
||||
// Okay to move the money at this point
|
||||
|
||||
// debit money from the purchaser's account
|
||||
customer_account.money -= currently_vending.price
|
||||
|
||||
// create entry in the purchaser's account log
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "[vendor_account.owner_name] (via [src.name])"
|
||||
T.purpose = "Purchase of [currently_vending.product_name]"
|
||||
if(currently_vending.price > 0)
|
||||
T.amount = "([currently_vending.price])"
|
||||
else
|
||||
T.amount = "[currently_vending.price]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
customer_account.transaction_log.Add(T)
|
||||
|
||||
// Give the vendor the money. We use the account owner name, which means
|
||||
// that purchases made with stolen/borrowed card will look like the card
|
||||
// owner made them
|
||||
credit_purchase(customer_account.owner_name)
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Add money for current purchase to the vendor account.
|
||||
*
|
||||
* Called after the money has already been taken from the customer.
|
||||
*/
|
||||
/obj/machinery/vending/proc/credit_purchase(var/target as text)
|
||||
vendor_account.money += currently_vending.price
|
||||
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = target
|
||||
T.purpose = "Purchase of [currently_vending.product_name]"
|
||||
T.amount = "[currently_vending.price]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
vendor_account.transaction_log.Add(T)
|
||||
|
||||
/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
|
||||
user.set_machine(src)
|
||||
|
||||
if(src.seconds_electrified != 0)
|
||||
if(src.shock(user, 100))
|
||||
return
|
||||
|
||||
var/vendorname = (src.name) //import the machine's name
|
||||
wires.Interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
if(src.currently_vending)
|
||||
var/dat = "<TT><center><b>[vendorname]</b></center><hr /><br>" //display the name, and added a horizontal rule
|
||||
dat += "<b>You have selected [currently_vending.product_name].<br>Please swipe your ID to pay for the article.</b><br>"
|
||||
dat += "<a href='byond://?src=\ref[src];cancel_buying=1'>Cancel</a>"
|
||||
user << browse(dat, "window=vending")
|
||||
onclose(user, "")
|
||||
return
|
||||
|
||||
var/dat = "<TT><center><b>[vendorname]</b></center><hr /><br>" //display the name, and added a horizontal rule
|
||||
dat += "<b>Select an item: </b><br><br>" //the rest is just general spacing and bolding
|
||||
|
||||
if (premium.len > 0)
|
||||
dat += "<b>Coin slot:</b> [coin ? coin : "No coin inserted"] (<a href='byond://?src=\ref[src];remove_coin=1'>Remove</A>)<br>"
|
||||
|
||||
if (ewallet)
|
||||
dat += "<b>Charge card's credits:</b> [ewallet ? ewallet.worth : "No charge card inserted"] (<a href='byond://?src=\ref[src];remove_ewallet=1'>Remove</A>)<br><br>"
|
||||
|
||||
if (src.product_records.len == 0)
|
||||
dat += "<font color = 'red'>No product loaded!</font>"
|
||||
/**
|
||||
* Display the NanoUI window for the vending machine.
|
||||
*
|
||||
* See NanoUI documentation for details.
|
||||
*/
|
||||
/obj/machinery/vending/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
|
||||
var/list/data = list()
|
||||
if(currently_vending)
|
||||
data["mode"] = 1
|
||||
data["product"] = currently_vending.product_name
|
||||
data["price"] = currently_vending.price
|
||||
data["message_err"] = 0
|
||||
data["message"] = src.status_message
|
||||
data["message_err"] = src.status_error
|
||||
else
|
||||
var/list/display_records = list()
|
||||
display_records += src.product_records
|
||||
data["mode"] = 0
|
||||
var/list/listed_products = list()
|
||||
|
||||
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 += "<FONT color = '[R.display_color]'><B>[R.product_name]</B>:"
|
||||
dat += " <b>[R.amount]</b> </font>"
|
||||
if(R.price)
|
||||
dat += " <b>(Price: [R.price])</b>"
|
||||
if (R.amount > 0)
|
||||
var/idx=GetProductIndex(R)
|
||||
dat += " <a href='byond://?src=\ref[src];vend=[idx];cat=[R.category]'>(Vend)</A>"
|
||||
else
|
||||
dat += " <font color = 'red'>SOLD OUT</font>"
|
||||
dat += "<br>"
|
||||
|
||||
dat += "</TT>"
|
||||
|
||||
if(panel_open)
|
||||
dat += wires()
|
||||
|
||||
if(product_slogans != "")
|
||||
dat += "The speaker switch is [shut_up ? "off" : "on"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a>"
|
||||
|
||||
user << browse(dat, "window=vending")
|
||||
onclose(user, "")
|
||||
return
|
||||
|
||||
// returns the wire panel text
|
||||
/obj/machinery/vending/proc/wires()
|
||||
return wires.GetInteractWindow()
|
||||
for(var/key = 1 to src.product_records.len)
|
||||
var/datum/data/vending_product/I = src.product_records[key]
|
||||
|
||||
if(!(I.category & src.categories))
|
||||
continue
|
||||
|
||||
listed_products.Add(list(list(
|
||||
"key" = key,
|
||||
"name" = I.product_name,
|
||||
"price" = I.price,
|
||||
"color" = I.display_color,
|
||||
"amount" = I.amount)))
|
||||
|
||||
data["products"] = listed_products
|
||||
|
||||
if(src.coin)
|
||||
data["coin"] = src.coin.name
|
||||
|
||||
if(src.panel_open)
|
||||
data["panel"] = 1
|
||||
data["speaker"] = src.shut_up ? 0 : 1
|
||||
else
|
||||
data["panel"] = 0
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "vending_machine.tmpl", src.name, 440, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/vending/Topic(href, href_list)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
@@ -377,19 +466,9 @@
|
||||
usr.put_in_hands(coin)
|
||||
usr << "\blue You remove the [coin] from the [src]"
|
||||
coin = null
|
||||
|
||||
if(href_list["remove_ewallet"] && !istype(usr,/mob/living/silicon))
|
||||
if (!ewallet)
|
||||
usr << "There is no charge card in this machine."
|
||||
return
|
||||
ewallet.loc = src.loc
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(ewallet)
|
||||
usr << "\blue You remove the [ewallet] from the [src]"
|
||||
ewallet = null
|
||||
categories &= ~CAT_COIN
|
||||
|
||||
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
|
||||
usr.set_machine(src)
|
||||
if ((href_list["vend"]) && (src.vend_ready) && (!currently_vending))
|
||||
|
||||
if(istype(usr,/mob/living/silicon))
|
||||
@@ -407,43 +486,32 @@
|
||||
flick(icon_deny,src)
|
||||
return
|
||||
|
||||
var/idx=text2num(href_list["vend"])
|
||||
var/cat=text2num(href_list["cat"])
|
||||
|
||||
var/datum/data/vending_product/R = GetProductByID(idx,cat)
|
||||
if (!R || !istype(R) || !R.product_path || R.amount <= 0)
|
||||
var/key = text2num(href_list["vend"])
|
||||
var/datum/data/vending_product/R = product_records[key]
|
||||
|
||||
// This should not happen unless the request from NanoUI was bad
|
||||
if(!(R.category & src.categories))
|
||||
return
|
||||
|
||||
if(R.price == null)
|
||||
|
||||
if(R.price <= 0)
|
||||
src.vend(R, usr)
|
||||
else
|
||||
if (ewallet)
|
||||
if (R.price <= ewallet.worth)
|
||||
ewallet.worth -= R.price
|
||||
src.vend(R, usr)
|
||||
else
|
||||
usr << "\red The ewallet doesn't have enough money to pay for that."
|
||||
src.currently_vending = R
|
||||
src.updateUsrDialog()
|
||||
src.currently_vending = R
|
||||
if(!vendor_account || vendor_account.suspended)
|
||||
src.status_message = "This machine is currently unable to process payments due to problems with the associated account."
|
||||
src.status_error = 1
|
||||
else
|
||||
src.currently_vending = R
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
src.status_message = "Please swipe a card or insert cash to pay for the item."
|
||||
src.status_error = 0
|
||||
|
||||
else if (href_list["cancel_buying"])
|
||||
else if (href_list["cancelpurchase"])
|
||||
src.currently_vending = null
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
else if ((href_list["togglevoice"]) && (src.panel_open))
|
||||
src.shut_up = !src.shut_up
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
else
|
||||
usr << browse(null, "window=vending")
|
||||
return
|
||||
return
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/proc/vend(datum/data/vending_product/R, mob/user)
|
||||
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
|
||||
@@ -451,8 +519,11 @@
|
||||
flick(src.icon_deny,src)
|
||||
return
|
||||
src.vend_ready = 0 //One thing at a time!!
|
||||
|
||||
if (R in coin_records)
|
||||
src.status_message = "Vending..."
|
||||
src.status_error = 0
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
if (R.category & CAT_COIN)
|
||||
if(!coin)
|
||||
user << "\blue You need to insert a coin to get this item."
|
||||
return
|
||||
@@ -462,8 +533,10 @@
|
||||
else
|
||||
user << "\blue You weren't able to pull the coin out fast enough, the machine ate it, string and all."
|
||||
del(coin)
|
||||
categories &= ~CAT_COIN
|
||||
else
|
||||
del(coin)
|
||||
categories &= ~CAT_COIN
|
||||
|
||||
R.amount--
|
||||
|
||||
@@ -477,17 +550,18 @@
|
||||
flick(src.icon_vend,src)
|
||||
spawn(src.vend_delay)
|
||||
new R.product_path(get_turf(src))
|
||||
src.status_message = ""
|
||||
src.status_error = 0
|
||||
src.vend_ready = 1
|
||||
return
|
||||
|
||||
src.updateUsrDialog()
|
||||
currently_vending = null
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
|
||||
if(src.panel_open)
|
||||
user << "\blue You stock the [src] with \a [R.product_name]"
|
||||
R.amount++
|
||||
|
||||
src.updateUsrDialog()
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
/obj/machinery/vending/process()
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
@@ -545,7 +619,7 @@
|
||||
new dump_path(src.loc)
|
||||
R.amount--
|
||||
break
|
||||
|
||||
|
||||
stat |= BROKEN
|
||||
src.icon_state = "[initial(icon_state)]-broken"
|
||||
return
|
||||
@@ -793,35 +867,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"
|
||||
|
||||
@@ -141,9 +141,10 @@
|
||||
if(isliving(src.loc))
|
||||
return
|
||||
user.next_move = max(user.next_move+2,world.time + 2)
|
||||
src.pickup(user)
|
||||
add_fingerprint(user)
|
||||
user.put_in_active_hand(src)
|
||||
if(src.loc == user)
|
||||
src.pickup(user)
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
return
|
||||
|
||||
..()
|
||||
take_damage(Proj.damage * 4)
|
||||
take_damage(Proj.damage)
|
||||
return
|
||||
|
||||
|
||||
@@ -484,10 +484,12 @@
|
||||
animate(src, color="#222222", time=5)
|
||||
SetOpacity(1)
|
||||
|
||||
|
||||
|
||||
/obj/machinery/button/windowtint
|
||||
name = "window tint control"
|
||||
icon = 'icons/obj/power.dmi'
|
||||
icon_state = "light1"
|
||||
icon_state = "light0"
|
||||
desc = "A remote control switch for polarized windows."
|
||||
var/range = 7
|
||||
|
||||
@@ -495,13 +497,24 @@
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
toggle_tint()
|
||||
|
||||
/obj/machinery/button/windowtint/proc/toggle_tint()
|
||||
use_power(5)
|
||||
|
||||
active = !active
|
||||
icon_state = "light[active]"
|
||||
update_icon()
|
||||
|
||||
for(var/obj/structure/window/reinforced/polarized/W in range(src,range))
|
||||
if (W.id == src.id || !W.id)
|
||||
spawn( 0 )
|
||||
spawn(0)
|
||||
W.toggle()
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/button/windowtint/power_change()
|
||||
..()
|
||||
if(active && !powered(power_channel))
|
||||
toggle_tint()
|
||||
|
||||
/obj/machinery/button/windowtint/update_icon()
|
||||
icon_state = "light[active]"
|
||||
|
||||
@@ -1174,15 +1174,22 @@ var/global/floorIsLava = 0
|
||||
switch(detail)
|
||||
if(0)
|
||||
return "<b>[key_name(C, link, name, highlight_special)]</b>"
|
||||
if(1)
|
||||
|
||||
if(1) //Private Messages
|
||||
return "<b>[key_name(C, link, name, highlight_special)](<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</A>)</b>"
|
||||
if(2)
|
||||
|
||||
if(2) //Admins
|
||||
var/ref_mob = "\ref[M]"
|
||||
return "<b>[key_name(C, link, name, highlight_special)](<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>)</b>"
|
||||
if(3)
|
||||
|
||||
if(3) //Devs
|
||||
var/ref_mob = "\ref[M]"
|
||||
return "<b>[key_name(C, link, name, highlight_special)](<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>)(<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>)</b>"
|
||||
|
||||
if(4) //Mentors
|
||||
var/ref_mob = "\ref[M]"
|
||||
return "<b>[key_name(C, link, name, highlight_special)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>)</b>"
|
||||
|
||||
|
||||
/proc/ishost(whom)
|
||||
if(!whom)
|
||||
|
||||
@@ -87,7 +87,11 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
|
||||
var/ai_cl
|
||||
if(ai_found)
|
||||
ai_cl = " (<A HREF='?_src_=holder;adminchecklaws=\ref[mob]'>CL</A>)"
|
||||
var/mentor_msg = "\blue <b><font color=red>Request for Help: </font>[get_options_bar(mob, 0, 0, 1, 0)][ai_cl]:</b> [msg]"
|
||||
|
||||
//Options bar: mob, details ( admin = 2, dev = 3, mentor = 4, character name (0 = just ckey, 1 = ckey and character name), link? (0 no don't make it a link, 1 do so),
|
||||
// highlight special roles (0 = everyone has same looking name, 1 = antags / special roles get a golden name)
|
||||
|
||||
var/mentor_msg = "\blue <b><font color=red>Request for Help: </font>[get_options_bar(mob, 4, 1, 1, 0)][ai_cl]:</b> [msg]"
|
||||
msg = "\blue <b><font color=red>Request for Help:: </font>[get_options_bar(mob, 2, 1, 1)][ai_cl]:</b> [msg]"
|
||||
|
||||
var/admin_number_afk = 0
|
||||
|
||||
@@ -197,8 +197,8 @@
|
||||
target_mob = H
|
||||
|
||||
if(target_mob != H)
|
||||
H << "<span class='danger'>You inject [target_mob] with [chems_to_use] unit[chems_to_use == 1 ? "" : "s"] of [charge.display_name].</span>"
|
||||
target_mob << "<span class='danger'>You feel a rushing in your veins as [chems_to_use] unit[chems_to_use == 1 ? "" : "s"] of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.</span>"
|
||||
H << "<span class='danger'>You inject [target_mob] with [chems_to_use] unit\s of [charge.display_name].</span>"
|
||||
target_mob << "<span class='danger'>You feel a rushing in your veins as [chems_to_use] unit\s of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.</span>"
|
||||
target_mob.reagents.add_reagent(charge.display_name, chems_to_use)
|
||||
|
||||
charge.charges -= chems_to_use
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
|
||||
if(prob(90))
|
||||
set_trait(TRAIT_REQUIRES_NUTRIENTS,1)
|
||||
set_trait(TRAIT_NUTRIENT_CONSUMPTION,rand(100)*0.1)
|
||||
set_trait(TRAIT_NUTRIENT_CONSUMPTION,rand(25)/25)
|
||||
else
|
||||
set_trait(TRAIT_REQUIRES_NUTRIENTS,0)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"exotic matter" = 0
|
||||
)
|
||||
|
||||
for(var/turf/T in oview(3,get_turf(user)))
|
||||
for(var/turf/T in range(3,get_turf(user)))
|
||||
|
||||
if(!T.has_resources)
|
||||
continue
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
return
|
||||
else
|
||||
if(language)
|
||||
message = language.scramble(language)
|
||||
message = language.scramble(message)
|
||||
else
|
||||
message = stars(message)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define SCRAMBLE_CACHE_LEN 20
|
||||
|
||||
/*
|
||||
Datum based languages. Easily editable and modular.
|
||||
*/
|
||||
@@ -35,11 +37,21 @@
|
||||
|
||||
return "[trim(full_name)]"
|
||||
|
||||
/datum/language
|
||||
var/list/scramble_cache = list()
|
||||
|
||||
/datum/language/proc/scramble(var/input)
|
||||
|
||||
if(!syllables || !syllables.len)
|
||||
return stars(input)
|
||||
|
||||
// If the input is cached already, move it to the end of the cache and return it
|
||||
if(input in scramble_cache)
|
||||
var/n = scramble_cache[input]
|
||||
scramble_cache -= input
|
||||
scramble_cache[input] = n
|
||||
return n
|
||||
|
||||
var/input_size = length(input)
|
||||
var/scrambled_text = ""
|
||||
var/capitalize = 1
|
||||
@@ -64,6 +76,13 @@
|
||||
var/input_ending = copytext(input, input_size)
|
||||
if(input_ending in list("!","?","."))
|
||||
scrambled_text += input_ending
|
||||
|
||||
// Add it to cache, cutting old entries if the list is too long
|
||||
scramble_cache[input] = scrambled_text
|
||||
if(scramble_cache.len > SCRAMBLE_CACHE_LEN)
|
||||
scramble_cache.Cut(1, scramble_cache.len-SCRAMBLE_CACHE_LEN-1)
|
||||
|
||||
|
||||
return scrambled_text
|
||||
|
||||
/datum/language/proc/format_message(message, verb)
|
||||
@@ -496,4 +515,6 @@
|
||||
"al", "an", "ar", "as", "at", "ea", "ed", "en", "er", "es", "ha", "he", "hi", "in", "is", "it",
|
||||
"le", "me", "nd", "ne", "ng", "nt", "on", "or", "ou", "re", "se", "st", "te", "th", "ti", "to",
|
||||
"ve", "wa", "all", "and", "are", "but", "ent", "era", "ere", "eve", "for", "had", "hat", "hen", "her", "hin",
|
||||
"his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi")
|
||||
"his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi")
|
||||
|
||||
#undef SCRAMBLE_CACHE_LEN
|
||||
@@ -434,7 +434,8 @@
|
||||
|
||||
|
||||
step(pulling, get_dir(pulling.loc, T))
|
||||
M.start_pulling(t)
|
||||
if(t)
|
||||
M.start_pulling(t)
|
||||
else
|
||||
if (pulling)
|
||||
if (istype(pulling, /obj/structure/window))
|
||||
|
||||
@@ -893,6 +893,11 @@
|
||||
if(!can_use(usr, 1))
|
||||
return 1
|
||||
|
||||
if(!istype(usr, /mob/living/silicon) && locked)
|
||||
// Shouldn't happen, this is here to prevent href exploits
|
||||
usr << "You must unlock the panel to use this!"
|
||||
return 1
|
||||
|
||||
if (href_list["lock"])
|
||||
coverlocked = !coverlocked
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var/power_output = 1
|
||||
|
||||
/obj/machinery/power/port_gen/proc/IsBroken()
|
||||
return (crit_fail || (stat & BROKEN|EMPED))
|
||||
return (crit_fail || (stat & (BROKEN|EMPED)))
|
||||
|
||||
/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check.
|
||||
return 1
|
||||
@@ -68,7 +68,7 @@
|
||||
if(3)
|
||||
if(prob(10)) stat &= BROKEN
|
||||
duration = 300
|
||||
|
||||
|
||||
stat |= EMPED
|
||||
if(duration)
|
||||
spawn(duration)
|
||||
@@ -84,12 +84,12 @@
|
||||
//A power generator that runs on solid plasma sheets.
|
||||
/obj/machinery/power/port_gen/pacman
|
||||
name = "\improper P.A.C.M.A.N.-type Portable Generator"
|
||||
desc = "A power generator that runs on solid plasma sheets. Rated for 80 kW max safe output."
|
||||
|
||||
var/sheet_name = "solid plasma sheet"
|
||||
desc = "A power generator that runs on solid phoron sheets. Rated for 80 kW max safe output."
|
||||
|
||||
var/sheet_name = "Phoron Sheets"
|
||||
var/sheet_path = /obj/item/stack/sheet/mineral/phoron
|
||||
var/board_path = "/obj/item/weapon/circuitboard/pacman"
|
||||
|
||||
var/board_path = "/obj/item/weapon/circuitboard/pacman"
|
||||
|
||||
/*
|
||||
These values were chosen so that the generator can run safely up to 80 kW
|
||||
A full 50 phoron sheet stack should last 20 minutes at power_output = 4
|
||||
@@ -98,15 +98,16 @@
|
||||
*/
|
||||
power_gen = 20000 //Watts output per power_output level
|
||||
var/max_power_output = 5 //The maximum power setting without emagging.
|
||||
var/max_safe_output = 4 // For UI use, maximal output that won't cause overheat.
|
||||
var/time_per_sheet = 96 //fuel efficiency - how long 1 sheet lasts at power level 1
|
||||
var/max_sheets = 100 //max capacity of the hopper
|
||||
var/max_temperature = 300 //max temperature before overheating increases
|
||||
var/temperature_gain = 50 //how much the temperature increases per power output level, in degrees per level
|
||||
|
||||
|
||||
var/sheets = 0 //How many sheets of material are loaded in the generator
|
||||
var/sheet_left = 0 //How much is left of the current sheet
|
||||
var/temperature = 0 //The current temperature
|
||||
var/overheating = 0 //if this gets high enough the generator explodes
|
||||
var/temperature = 0 //The current temperature
|
||||
var/overheating = 0 //if this gets high enough the generator explodes
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/initialize()
|
||||
..()
|
||||
@@ -122,8 +123,6 @@
|
||||
component_parts += new /obj/item/stack/cable_coil(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
||||
component_parts += new board_path(src)
|
||||
var/obj/sheet = new sheet_path(null)
|
||||
sheet_name = sheet.name
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/Del()
|
||||
@@ -137,20 +136,20 @@
|
||||
max_sheets = SP.rating * SP.rating * 50
|
||||
else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor))
|
||||
temp_rating += SP.rating
|
||||
|
||||
|
||||
var/temp_reliability = 0
|
||||
var/part_count = 0
|
||||
for(var/obj/item/weapon/CP in component_parts)
|
||||
temp_reliability += CP.reliability
|
||||
part_count++
|
||||
|
||||
|
||||
reliability = min(round(temp_reliability / part_count), 100)
|
||||
power_gen = round(initial(power_gen) * (max(2, temp_rating) / 2))
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/examine(mob/user)
|
||||
..(user)
|
||||
user << "\The [src] appears to be producing [power_gen*power_output] W."
|
||||
user << "There are [sheets] [sheet_name]\s left in the hopper."
|
||||
user << "There [sheets == 1 ? "is" : "are"] [sheets] sheet\s left in the hopper."
|
||||
if(IsBroken()) user << "<span class='warning'>\The [src] seems to have broken down.</span>"
|
||||
if(overheating) user << "<span class='danger'>\The [src] is overheating!</span>"
|
||||
|
||||
@@ -179,7 +178,7 @@
|
||||
|
||||
//how much material are we using this iteration?
|
||||
var/needed_sheets = power_output / time_per_sheet
|
||||
|
||||
|
||||
//HasFuel() should guarantee us that there is enough fuel left, so no need to check that
|
||||
//the only thing we need to worry about is if we are going to rollover to the next sheet
|
||||
if (needed_sheets > sheet_left)
|
||||
@@ -192,7 +191,7 @@
|
||||
//This should probably depend on the external temperature somehow, but whatever.
|
||||
var/lower_limit = 56 + power_output * temperature_gain
|
||||
var/upper_limit = 76 + power_output * temperature_gain
|
||||
|
||||
|
||||
/*
|
||||
Hot or cold environments can affect the equilibrium temperature
|
||||
The lower the pressure the less effect it has. I guess it cools using a radiator or something when in vacuum.
|
||||
@@ -205,16 +204,16 @@
|
||||
var/ambient = environment.temperature - T20C
|
||||
lower_limit += ambient*ratio
|
||||
upper_limit += ambient*ratio
|
||||
|
||||
|
||||
var/average = (upper_limit + lower_limit)/2
|
||||
|
||||
|
||||
//calculate the temperature increase
|
||||
var/bias = 0
|
||||
if (temperature < lower_limit)
|
||||
bias = min(round((average - temperature)/TEMPERATURE_DIVISOR, 1), TEMPERATURE_CHANGE_MAX)
|
||||
else if (temperature > upper_limit)
|
||||
bias = max(round((temperature - average)/TEMPERATURE_DIVISOR, 1), -TEMPERATURE_CHANGE_MAX)
|
||||
|
||||
|
||||
temperature += rand(-7 + bias, 7 + bias)
|
||||
|
||||
if (temperature > max_temperature)
|
||||
@@ -229,13 +228,16 @@
|
||||
var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
|
||||
var/ambient = environment.temperature - T20C
|
||||
cooling_temperature += ambient*ratio
|
||||
|
||||
|
||||
if (temperature > cooling_temperature)
|
||||
var/temp_loss = (temperature - cooling_temperature)/TEMPERATURE_DIVISOR
|
||||
temp_loss = between(2, round(temp_loss, 1), TEMPERATURE_CHANGE_MAX)
|
||||
temperature = max(temperature - temp_loss, cooling_temperature)
|
||||
src.updateDialog()
|
||||
|
||||
if(overheating)
|
||||
overheating--
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/proc/overheat()
|
||||
overheating++
|
||||
if (overheating > 60)
|
||||
@@ -249,7 +251,7 @@
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
if (environment)
|
||||
environment.adjust_gas_temp("phoron", phoron/10, temperature + T0C)
|
||||
|
||||
|
||||
sheets = 0
|
||||
sheet_left = 0
|
||||
..()
|
||||
@@ -261,7 +263,7 @@
|
||||
if(amount < 1)
|
||||
user << "\blue The [src.name] is full!"
|
||||
return
|
||||
user << "\blue You add [amount] [addstack.singular_name]\s to the [src.name]."
|
||||
user << "\blue You add [amount] sheet\s to the [src.name]."
|
||||
sheets += amount
|
||||
addstack.use(amount)
|
||||
updateUsrDialog()
|
||||
@@ -305,11 +307,46 @@
|
||||
..()
|
||||
if (!anchored)
|
||||
return
|
||||
interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob)
|
||||
interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(IsBroken())
|
||||
return
|
||||
|
||||
var/data[0]
|
||||
data["active"] = active
|
||||
if(istype(user, /mob/living/silicon/ai))
|
||||
data["is_ai"] = 1
|
||||
else if(istype(user, /mob/living/silicon/robot) && !Adjacent(user))
|
||||
data["is_ai"] = 1
|
||||
else
|
||||
data["is_ai"] = 0
|
||||
data["output_set"] = power_output
|
||||
data["output_max"] = max_power_output
|
||||
data["output_safe"] = max_safe_output
|
||||
data["output_watts"] = power_output * power_gen
|
||||
data["temperature_current"] = src.temperature
|
||||
data["temperature_max"] = src.max_temperature
|
||||
data["temperature_overheat"] = overheating
|
||||
// 1 sheet = 1000cm3?
|
||||
data["fuel_stored"] = round((sheets * 1000) + (sheet_left * 1000))
|
||||
data["fuel_capacity"] = round(max_sheets * 1000, 0.1)
|
||||
data["fuel_usage"] = active ? round((power_output / time_per_sheet) * 1000) : 0
|
||||
data["fuel_type"] = sheet_name
|
||||
|
||||
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "pacman.tmpl", src.name, 500, 560)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
|
||||
/*
|
||||
/obj/machinery/power/port_gen/pacman/interact(mob/user)
|
||||
if (get_dist(src, user) > 1 )
|
||||
if (!istype(user, /mob/living/silicon/ai))
|
||||
@@ -329,12 +366,13 @@
|
||||
dat += text("Current stack: [stack_percent]% <br>")
|
||||
dat += text("Power output: <A href='?src=\ref[src];action=lower_power'>-</A> [power_gen * power_output] Watts<A href='?src=\ref[src];action=higher_power'>+</A><br>")
|
||||
dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]<br>")
|
||||
|
||||
|
||||
var/tempstr = "Temperature: [temperature]°C<br>"
|
||||
dat += (overheating)? "<span class='danger'>[tempstr]</span>" : tempstr
|
||||
dat += "<br><A href='?src=\ref[src];action=close'>Close</A>"
|
||||
user << browse("[dat]", "window=port_gen")
|
||||
onclose(user, "port_gen")
|
||||
*/
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/Topic(href, href_list)
|
||||
if(..())
|
||||
@@ -346,33 +384,26 @@
|
||||
if(!active && HasFuel() && !IsBroken())
|
||||
active = 1
|
||||
icon_state = "portgen1"
|
||||
src.updateUsrDialog()
|
||||
if(href_list["action"] == "disable")
|
||||
if (active)
|
||||
active = 0
|
||||
icon_state = "portgen0"
|
||||
src.updateUsrDialog()
|
||||
if(href_list["action"] == "eject")
|
||||
if(!active)
|
||||
DropFuel()
|
||||
src.updateUsrDialog()
|
||||
if(href_list["action"] == "lower_power")
|
||||
if (power_output > 1)
|
||||
power_output--
|
||||
src.updateUsrDialog()
|
||||
if (href_list["action"] == "higher_power")
|
||||
if (power_output < max_power_output || (emagged && power_output < round(max_power_output*2.5)))
|
||||
power_output++
|
||||
src.updateUsrDialog()
|
||||
if (href_list["action"] == "close")
|
||||
usr << browse(null, "window=port_gen")
|
||||
usr.unset_machine()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/super
|
||||
name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator"
|
||||
desc = "A power generator that utilizes uranium sheets as fuel. Can run for much longer than the standard PACMAN type generators. Rated for 80 kW max safe output."
|
||||
icon_state = "portgen1"
|
||||
sheet_path = /obj/item/stack/sheet/mineral/uranium
|
||||
sheet_name = "Uranium Sheets"
|
||||
time_per_sheet = 576 //same power output, but a 50 sheet stack will last 2 hours at max safe power
|
||||
board_path = "/obj/item/weapon/circuitboard/pacman/super"
|
||||
|
||||
@@ -390,26 +421,28 @@
|
||||
//should really fall with the square of the distance, but that makes the rads value drop too fast
|
||||
//I dunno, maybe physics works different when you live in 2D -- SM radiation also works like this, apparently
|
||||
L.apply_effect(max(20, round(rads/get_dist(L,src))), IRRADIATE)
|
||||
|
||||
|
||||
explosion(src.loc, 3, 3, 5, 3)
|
||||
del(src)
|
||||
del(src)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/mrs
|
||||
name = "M.R.S.P.A.C.M.A.N.-type Portable Generator"
|
||||
desc = "An advanced power generator that runs on tritium. Rated for 200 kW maximum safe output!"
|
||||
icon_state = "portgen2"
|
||||
sheet_path = /obj/item/stack/sheet/mineral/tritium
|
||||
|
||||
sheet_path = /obj/item/stack/sheet/mineral/tritium
|
||||
sheet_name = "Tritium Fuel Sheets"
|
||||
|
||||
//I don't think tritium has any other use, so we might as well make this rewarding for players
|
||||
//max safe power output (power level = 8) is 200 kW and lasts for 1 hour - 3 or 4 of these could power the station
|
||||
power_gen = 25000 //watts
|
||||
max_power_output = 10
|
||||
max_safe_output = 8
|
||||
time_per_sheet = 576
|
||||
max_temperature = 800
|
||||
temperature_gain = 90
|
||||
board_path = "/obj/item/weapon/circuitboard/pacman/mrs"
|
||||
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/mrs/explode()
|
||||
//no special effects, but the explosion is pretty big (same as a supermatter shard).
|
||||
explosion(src.loc, 3, 6, 12, 16, 1)
|
||||
del(src)
|
||||
del(src)
|
||||
|
||||
@@ -63,8 +63,10 @@
|
||||
if(!src.loc)
|
||||
return 0
|
||||
|
||||
if(!use_power)
|
||||
return 1
|
||||
//Don't do this. It allows machines that set use_power to 0 when off (many machines) to
|
||||
//be turned on again and used after a power failure because they never gain the NOPOWER flag.
|
||||
//if(!use_power)
|
||||
// return 1
|
||||
|
||||
var/area/A = src.loc.loc // make sure it's in an area
|
||||
if(!A || !isarea(A) || !A.master)
|
||||
|
||||
@@ -315,7 +315,7 @@
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "smes.tmpl", "SMES Power Storage Unit", 540, 380)
|
||||
ui = new(user, src, ui_key, "smes.tmpl", "SMES Unit", 540, 380)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
|
||||
@@ -462,10 +462,10 @@
|
||||
if(prob(75))
|
||||
I.loc = src
|
||||
for(var/mob/M in viewers(src))
|
||||
M.show_message("\the [I] lands in \the [src].", 3)
|
||||
M.show_message("\The [I] lands in \the [src].", 3)
|
||||
else
|
||||
for(var/mob/M in viewers(src))
|
||||
M.show_message("\the [I] bounces off of \the [src]'s rim!", 3)
|
||||
M.show_message("\The [I] bounces off of \the [src]'s rim!", 3)
|
||||
return 0
|
||||
else
|
||||
return ..(mover, target, height, air_group)
|
||||
|
||||
@@ -56,6 +56,14 @@ should be listed in the changelog upon commit though. Thanks. -->
|
||||
|
||||
<!-- DO NOT REMOVE, MOVE, OR COPY THIS COMMENT! THIS MUST BE THE LAST NON-EMPTY LINE BEFORE THE LOGS #ADDTOCHANGELOGMARKER# -->
|
||||
|
||||
<div class='commit sansserif'>
|
||||
<h2 class='date'>12 February 2015</h2>
|
||||
<h3 class='author'>Daranz updated:</h3>
|
||||
<ul class='changes bgimages16'>
|
||||
<li class='rscadd'>Vending machines now use NanoUI and accept cash. The vendor account can now be suspended to disable all sales in all machines on station.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class='commit sansserif'>
|
||||
<h2 class='date'>4 February 2015</h2>
|
||||
<h3 class='author'>RavingManiac updated:</h3>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 71 KiB |
2296
maps/exodus-1.dmm
2296
maps/exodus-1.dmm
File diff suppressed because it is too large
Load Diff
113
nano/templates/pacman.tmpl
Normal file
113
nano/templates/pacman.tmpl
Normal file
@@ -0,0 +1,113 @@
|
||||
<h3>Status</h3>
|
||||
<div class='item'>
|
||||
<div class="itemLabel">
|
||||
Generator Status:
|
||||
</div>
|
||||
<div class = "itemContent">
|
||||
{{if data.active}}
|
||||
<span class="good">Online</span>
|
||||
{{else}}
|
||||
<span class="average">Offline</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="itemLabel">
|
||||
Generator Control:
|
||||
</div>
|
||||
<div class = "itemContent">
|
||||
{{if data.active}}
|
||||
{{:helper.link('STOP', 'power', {'action' : "disable"})}}
|
||||
{{else}}
|
||||
{{:helper.link('START', 'power', {'action' : "enable"})}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<h3>Fuel</h3>
|
||||
<div class='item'>
|
||||
<div class="itemLabel">
|
||||
Fuel Type:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
<span class="good">{{:data.fuel_type}}</span>
|
||||
</div>
|
||||
<div class="itemLabel">
|
||||
Fuel Level:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{if data.fuel_stored >= 5000}}
|
||||
{{:helper.displayBar(data.fuel_stored, 0, data.fuel_capacity, 'good')}}
|
||||
<br><span class="good">{{:data.fuel_stored}}/{{:data.fuel_capacity}} cm3</span>
|
||||
{{else data.fuel_stored >= 1000}}
|
||||
{{:helper.displayBar(data.fuel_stored, 0, data.fuel_capacity, 'average')}}
|
||||
<br><span class="average">{{:data.fuel_stored}}/{{:data.fuel_capacity}} cm3</span>
|
||||
{{else}}
|
||||
{{:helper.displayBar(data.fuel_stored, 0, data.fuel_capacity, 'bad')}}
|
||||
<br><span class="bad">{{:data.fuel_stored}}/{{:data.fuel_capacity}} cm3</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="itemLabel">
|
||||
Fuel Usage:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
<span class="good">{{:data.fuel_usage}} cm3/s</span>
|
||||
</div>
|
||||
{{if !data.is_ai}}
|
||||
<div class="itemLabel">
|
||||
Control:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{:helper.link('EJECT FUEL', 'arrowupthick-1-s', {'action' : "eject"}, data.active ? 'disabled' : null)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<h3>Output</h3>
|
||||
<div class='item'>
|
||||
<div class="itemLabel">
|
||||
Power setting:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{if data.output_set > data.output_safe}}
|
||||
<span class="bad">{{:data.output_set}} / {{:data.output_max}} ({{:data.output_watts}} W)</span>
|
||||
{{else}}
|
||||
<span class="good">{{:data.output_set}} / {{:data.output_max}} ({{:data.output_watts}} W)</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="itemLabel">
|
||||
Control:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{:helper.link('+', null, {'action' : "higher_power"})}}
|
||||
{{:helper.link('-', null, {'action' : "lower_power"})}}
|
||||
</div>
|
||||
</div>
|
||||
<h3>Temperature</h3>
|
||||
<div class='item'>
|
||||
<div class="itemLabel">
|
||||
Temperature:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{if data.temperature_current < (data.temperature_max * 0.8)}}
|
||||
{{:helper.displayBar(data.temperature_current, 0, (data.temperature_max * 1.5), 'good')}}
|
||||
<br><span class="good">{{:data.temperature_current}} C</span>
|
||||
{{else data.temperature_current < data.temperature_max}}
|
||||
{{:helper.displayBar(data.temperature_current, 0, (data.temperature_max * 1.5), 'average')}}
|
||||
<br><span class="average">{{:data.temperature_current}} C</span>
|
||||
{{else}}
|
||||
{{:helper.displayBar(data.temperature_current, 0, (data.temperature_max * 1.5), 'bad')}}
|
||||
<br><span class="bad">{{:data.temperature_current}} C</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="itemLabel">
|
||||
Generator Status:
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
{{if data.temperature_overheat > 50}}
|
||||
<span class="bad">DANGER: CRITICAL OVERHEAT! Deactivate generator immediately!</span>
|
||||
{{else data.temperature_overheat > 20}}
|
||||
<span class="average">WARNING: Overheating!</span>
|
||||
{{else data.temperature_overheat > 1}}
|
||||
<span class="average">Temperature High</span>
|
||||
{{else}}
|
||||
<span class="good">Optimal</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
56
nano/templates/vending_machine.tmpl
Normal file
56
nano/templates/vending_machine.tmpl
Normal file
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
Interface for vending machines
|
||||
See: code/game/machinery/vending.dm
|
||||
-->
|
||||
|
||||
{{if data.mode == 0}} <!-- Listing -->
|
||||
<h2>Items available</h2>
|
||||
<div class='item'>
|
||||
{{for data.products}}
|
||||
<div class='item'>
|
||||
<div style='float'>
|
||||
{{if value.price > 0}}
|
||||
{{:helper.link('Buy (' + value.price + ')', 'cart', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}}
|
||||
{{else}}
|
||||
{{:helper.link('Vend', 'circle-arrow-s', { "vend" : value.key }, value.amount > 0 ? null : 'disabled')}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='itemContent'>
|
||||
{{if value.color}}<span style='color:{{:value.color}}'>{{:value.name}}</span>
|
||||
{{else}}{{:value.name}}
|
||||
{{/if}}
|
||||
({{:value.amount ? value.amount : "NONE LEFT"}})
|
||||
</div>
|
||||
</div>
|
||||
{{empty}}
|
||||
No items available!
|
||||
{{/for}}
|
||||
</div>
|
||||
{{if data.coin}}
|
||||
<h2>Coin</h2>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Coin deposited:</div>
|
||||
<div class='itemContent'>{{:helper.link(data.coin, 'eject', {'remove_coin' : 1})}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else data.mode == 1}} <!-- Payment screen -->
|
||||
<h2>Item selected</h2>
|
||||
<div class='item'>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Item selected:</div> <div class='itemContent'>{{:data.product}}</div>
|
||||
<div class='itemLabel'>Charge:</div> <div class='itemContent'>{{:data.price}}</div>
|
||||
</div>
|
||||
<div class='statusDisplay' style='overflow: auto;'>
|
||||
{{if data.message_err}} <span class='uiIcon16 icon-alert' ></span>{{/if}} {{:data.message}}
|
||||
</div>
|
||||
<div class='item'>
|
||||
{{:helper.link('Cancel', 'arrowreturn-1-w', {'cancelpurchase' : 1})}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{if data.panel}}
|
||||
<h2>Maintenance panel</h2>
|
||||
<div class='item'>
|
||||
<div class='itemLabel'>Speaker</div><div class='item'>{{:helper.link(data.speaker ? 'Enabled' : 'Disabled', 'gear', {'togglevoice' : 1})}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
Reference in New Issue
Block a user