Programmable cargo machines

This commit is contained in:
ZomgPonies
2013-11-04 07:48:55 -05:00
parent 8bf368f547
commit b2b623cac8
2 changed files with 1542 additions and 0 deletions

View File

@@ -0,0 +1,797 @@
/datum/cargoprofile
var/name = "All Items"
var/id = "all" // unique ID for the UI
var/enabled = 1
var/eject_speed = 1 // will change when emagged
var/const/BIG_OBJECT_WORK = 10
var/const/MOB_WORK = 10
var/obj/machinery/programmable/master = null
var/universal = 0 // set when both unary and binary machines work
var/mobcheck = 0
var/list/whitelist = list(/obj/item,/obj/structure/closet,/obj/structure/bigDelivery,/obj/machinery/portable_atmospherics)
var/list/blacklist = null
var/dedicated_path = null // When constructing a new machine with this as default program, create a machine of the specified type instead.
//contains: called to determine if an object/mob will be sorted by this profile
//return 1 for any sortable item
proc/contains(var/atom/A)
if(!istype(A,/obj))
if(!mobcheck || !istype(A,/mob))
return 0
else
var/obj/O = A
if(O.anchored)
return 0
//If you are using both white and blacklists, blacklists are absoulte, no matter what is whitelisted.
//I understand this has some limitations. You cannot whitelist all items, blacklist weapons,
// and then whitelist a specific weapon. Them's the breaks, kid.
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
//inlet_reaction: called when a filtered item is chosen by this profile.
//W: Item chosen
//S: input turf location
//remaining: counts down how much more work the unloader wants to do this turn.
//return the amount of work done.
proc/inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(!W || !S || !master)
return 0
if(istype(W,/obj/item))
var/obj/item/I = W
if(I.w_class > remaining)
return 0
I.loc = master
master.types[W.type] = src
return I.w_class
if(istype(W,/obj/structure) || istype(W,/obj/machinery)) // closets, big deliveries, portable atmospherics, unconnected stuff
if(remaining < BIG_OBJECT_WORK)
return 0
var/obj/O = W
O.loc = master
master.types[O.type] = src
return BIG_OBJECT_WORK
//Not item, structure, machinery, or mob
return 0
//outlet_reaction: called when a stored object is ejected
//W: the item in question
//D: the destination turf
proc/outlet_reaction(var/atom/W,var/turf/D)
if(!W || !D || !master)
return
if(master.emagged)
// emagging is not an industry-approved practice.
// some malfunctions may occur.
eject_speed = rand(0,4)
D = get_step(D,master.outdir)
while(prob(20))
if(master.outdir == NORTH || master.outdir == SOUTH)
D = get_step(D,pick(EAST,WEST,master.outdir))
else
D = get_step(D,pick(NORTH,SOUTH,master.outdir))
if(istype(W,/obj))
var/obj/O = W
O.loc = master.loc
O.dir = master.outdir
O.throw_at(D,eject_speed,eject_speed)
return
//----------------------------------------------------------------------------
// Profiles
//----------------------------------------------------------------------------
/datum/cargoprofile/boxes
name = "Move Small Containers"
id = "boxes"
blacklist = null
whitelist = list(/obj/item/weapon/storage, /obj/item/weapon/moneybag, /obj/item/weapon/evidencebag,
/obj/item/weapon/tray, /obj/item/pizzabox, /obj/item/weapon/clipboard,
/obj/item/smallDelivery, /obj/structure/bigDelivery)
/datum/cargoprofile/cargo
name = "Move Large Containers"
id = "cargo"
blacklist = null
whitelist = list(/obj/structure/closet,/obj/structure/ore_box)
// Make an honest attempt to move other things out of the way
outlet_reaction(var/atom/W,var/turf/D)
for(var/obj/O in D)
if(O.density && !O.anchored)
step_away(O,src) // move forward first
if(O.loc == D)
step_away(O,D) // move anywhere
..(W,D)
/datum/cargoprofile/cargo/empty
name = "Move Empty Large Containers"
id = "cargo-empty"
contains(var/atom/A)
return (..(A) && (A.contents.len == 0))
/datum/cargoprofile/cargo/full
name = "Move Full Large Containers"
id = "cargo-full"
contains(var/atom/A)
return (..(A) && (A.contents.len > 0))
/datum/cargoprofile/supplies
name = "Building Supplies"
id = "supplies"
blacklist = null
whitelist = list(/obj/item/weapon/cable_coil,/obj/item/stack/rods,
/obj/item/stack/sheet/metal,/obj/item/stack/sheet/plasteel,
/obj/item/stack/sheet/glass,/obj/item/stack/sheet/rglass,
/obj/item/stack/tile,/obj/item/weapon/light,
/obj/item/weapon/table_parts)
//todo: maybe stack things while we're here?
/datum/cargoprofile/exotics
name = "Exotic materials"
id = "exotics"
blacklist = null
whitelist = list(/obj/item/weapon/coin, /obj/item/weapon/spacecash, /obj/item/seeds,
/obj/item/stack/sheet/mineral,/obj/item/stack/sheet/wood,/obj/item/stack/sheet/leather)
/datum/cargoprofile/organics
name = "Organics, chemicals, and Paraphernalia"
id = "organics"
blacklist = null
whitelist = list(/obj/item/weapon/tank,/obj/item/weapon/reagent_containers,
/obj/item/stack/medical,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/gun/syringe,
/obj/item/weapon/plastique,/obj/item/weapon/grenade,/obj/item/ammo_box,
/obj/item/weapon/gun/grenadelauncher,/obj/item/weapon/flamethrower, /obj/item/weapon/lighter,
/obj/item/weapon/match,/obj/item/weapon/weldingtool)
/datum/cargoprofile/food
name = "Food"
id = "food"
blacklist = null // something should probably go here
whitelist = list(/obj/item/weapon/reagent_containers/food)
/datum/cargoprofile/chemical
name = "Chemicals and Paraphernalia"
id = "chemical"
blacklist = list(/obj/item/weapon/reagent_containers/food)
whitelist = list(/obj/item/weapon/reagent_containers,/obj/item/stack/medical,/obj/item/weapon/storage/pill_bottle,
/obj/item/weapon/gun/syringe,/obj/item/weapon/grenade/chem_grenade,/obj/item/weapon/dnainjector,
/obj/item/weapon/storage/belt/medical,/obj/item/weapon/storage/firstaid,/obj/item/weapon/implanter)
/datum/cargoprofile/pressure
name = "air tanks"
id = "pressure"
blacklist = null
whitelist = list(/obj/item/weapon/tank,/obj/machinery/portable_atmospherics,
/obj/item/weapon/flamethrower)
//Am I missing any?
/datum/cargoprofile/pressure/empty
name = "empty air tanks"
id = "pressure-low"
var/lowpressure = ONE_ATMOSPHERE
contains(var/atom/A)
if(..())
var/pressure = ONE_ATMOSPHERE * 10 // In case of fallthrough, fail test
if(istype(A,/obj/item/weapon/tank))
var/obj/item/weapon/tank/T = A
pressure = T.air_contents.return_pressure()
if(istype(A,/obj/item/weapon/flamethrower))
var/obj/item/weapon/flamethrower/T = A
if(!T.ptank)
return 0
pressure = T.ptank.air_contents.return_pressure()
if(istype(A,/obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = A
pressure = P.air_contents.return_pressure()
if(pressure < lowpressure)
return 1
return 0// Not container or failed low pressure check
/datum/cargoprofile/pressure/full
name = "full air tanks"
id = "pressure-high"
var/highpressure = ONE_ATMOSPHERE * 15 // stolen from canister.dm; Is this right?
contains(var/atom/A)
if(..())
var/pressure = 0 // In case of fallthrough, fail test
if(istype(A,/obj/item/weapon/tank))
var/obj/item/weapon/tank/T = A
pressure = T.air_contents.return_pressure()
if(istype(A,/obj/item/weapon/flamethrower))
var/obj/item/weapon/flamethrower/T = A
if(!T.ptank)
return 0
pressure = T.ptank.air_contents.return_pressure()
if(istype(A,/obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = A
pressure = P.air_contents.return_pressure()
if(pressure > highpressure)
return 1
return 0// Not container or failed high pressure check
/datum/cargoprofile/clothing
name = "Crew Kit"
id = "clothing"
blacklist = list(/obj/item/weapon/tank/plasma,/obj/item/weapon/tank/anesthetic, // the rest are air tanks
/obj/item/clothing/mask/facehugger) // NOT CLOTHING AT ALLLLL
whitelist = list(/obj/item/clothing,/obj/item/weapon/storage/belt,/obj/item/weapon/storage/backpack,
/obj/item/device/radio/headset,/obj/item/device/pda,/obj/item/weapon/card/id,/obj/item/weapon/tank,
/obj/item/weapon/handcuffs, /obj/item/weapon/legcuffs)
/datum/cargoprofile/trash
name = "Trash"
id = "trash"
//Note that this filters out blueprints because they are a paper item. Do NOT throw out the station blueprints unless you be trollin'.
blacklist = null
whitelist = list(/obj/item/trash,/obj/item/toy,/obj/item/weapon/ectoplasm,/obj/item/weapon/bananapeel,/obj/item/weapon/broken_bottle,/obj/item/weapon/bikehorn,
/obj/item/weapon/cigbutt,/obj/item/weapon/contraband,/obj/item/weapon/corncob,/obj/item/weapon/paper,/obj/item/weapon/shard,
/obj/item/weapon/sord,/obj/item/weapon/photo,/obj/item/weapon/folder,
/obj/item/blueprints,/obj/item/weapon/contraband,/obj/item/weapon/kitchen,/obj/item/weapon/book,/obj/item/clothing/mask/facehugger)
/datum/cargoprofile/weapons
name = "Weapons & Illegals"
id = "weapons"
blacklist = null
//This one is hard since 'weapon contains a lot of things better categorized as devices
whitelist = list(/obj/item/weapon/banhammer,/obj/item/weapon/sord,/obj/item/weapon/butch,/obj/item/weapon/claymore,/obj/item/weapon/holo/esword,
/obj/item/weapon/flamethrower,/obj/item/weapon/grenade,/obj/item/weapon/gun,/obj/item/weapon/hatchet,/obj/item/weapon/katana,
/obj/item/weapon/kitchenknife,/obj/item/weapon/melee,/obj/item/weapon/nullrod,/obj/item/weapon/pickaxe,/obj/item/weapon/twohanded,
/obj/item/weapon/plastique,/obj/item/weapon/scalpel,/obj/item/weapon/shield,/obj/item/weapon/grown/deathnettle)
/datum/cargoprofile/tools
name = "Devices & Tools"
id = "tools"
blacklist = null
whitelist = list(/obj/item/device,/obj/item/weapon/card,/obj/item/weapon/cartridge,/obj/item/weapon/cautery,/obj/item/weapon/cell,/obj/item/weapon/circuitboard,
/obj/item/weapon/aiModule,/obj/item/weapon/airalarm_electronics,/obj/item/weapon/airlock_electronics,/obj/item/weapon/circular_saw,
/obj/item/weapon/cloaking_device,/obj/item/weapon/crowbar,/obj/item/weapon/disk,/obj/item/weapon/firealarm_electronics,/obj/item/weapon/hand_tele,
/obj/item/weapon/hand_labeler,/obj/item/weapon/hemostat,/obj/item/weapon/mop,/obj/item/weapon/locator,/obj/item/weapon/minihoe,
/obj/item/weapon/packageWrap,/obj/item/weapon/pen,/obj/item/weapon/pickaxe,/obj/item/weapon/pinpointer,
/obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/retractor,/obj/item/weapon/rsf,/obj/item/weapon/rsp,/obj/item/weapon/scalpel,
/obj/item/weapon/screwdriver,/obj/item/weapon/shovel,/obj/item/weapon/soap,/obj/item/weapon/stamp,/obj/item/weapon/tray,/obj/item/weapon/weldingtool,
/obj/item/weapon/wirecutters,/obj/item/weapon/wrench,/obj/item/weapon/extinguisher)
/datum/cargoprofile/finished
name = "Completed Robots"
id = "finished"
blacklist = null
whitelist = list(/obj/mecha,/obj/machinery/bot,/mob/living/silicon/robot)
mobcheck = 1
//todo: detect and allow finished cyborg endoskeletons with no brain
contains(var/atom/A)
if(..())
return 1
if(istype(A,/mob))
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
return 0
/datum/cargoprofile/stripping
name = "Auto-Frisker"
id = "frisk"
blacklist = null
whitelist = list(/mob/living/carbon/human)
mobcheck = 1
//----------------------------------------------------------------------------
// Overrides (Special Functions)
//----------------------------------------------------------------------------
/datum/cargoprofile/cargo/unload
name = "Unload Cargo Boxes"
id = "cargounload"
enabled = 0
dedicated_path = /obj/machinery/programmable/unloader
//override the detection to only accept crates with something in it.
//if it doesn't, this object may be handled by another handler.
contains(var/atom/A)
if(..(A))
if(istype(A,/obj/structure/closet))
var/obj/structure/closet/C = A
if(!C.can_open() && !C.opened && !master.emagged) // must be able to access the contents
return 0
if(A.contents.len)
return 1
return 0
//instead of moving the box, strip it of its contents
inlet_reaction(var/obj/W,var/turf/S, var/remaining)
//W should only be crate or ore box, although this will work on anything with contents...
var/I = 0
if(istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
if(!C.can_open() && !C.opened) // must be able to access the contents
if(master.emagged && remaining >= BIG_OBJECT_WORK)
if(prob(10))
C.welded = 0
if("broken" in C.vars)
C:broken = 1
C.open()
C.update_icon()
master.visible_message("\red [master] breaks open [C]!")
else
master.visible_message("\blue [master] is trying to force [C] open!")
master.sleep += 1 // mechanical strain
return BIG_OBJECT_WORK
master.visible_message("\blue [master] is trying to open [C], but can't!")
master.sleep = 5
return 0
for(var/obj/item/O in W.contents)
if(I > remaining)
return
if(O.w_class > (remaining - I))
continue
O.loc = master
master.types[O.type] = src
if(O.w_class > 0)
I += O.w_class
else
I++
if(!W.contents.len && istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
C.open()
return I
//Inlet stacker: used when the output is a volatile space (conveyor or another unit's input).
//Does not output a stack until it is full.
/datum/cargoprofile/in_stacker
name = "Hold and Stack"
id = "instacker"
universal = 1
blacklist = null
whitelist = list(/obj/item/stack,/obj/item/weapon/cable_coil)
dedicated_path = /obj/machinery/programmable/stacker
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(!I.amount) // todo: am I making a bad assumption here?
del I
return
for(var/obj/item/stack/O in master.contents)
if(O.type == I.type && O.amount < O.max_amount)
if(I.amount + O.amount <= O.max_amount)
O.amount += I.amount
del I
return O.w_class
var/leftover = I.amount + O.amount - O.max_amount
O.amount = O.max_amount
I.amount = leftover
continue
//end for
I.loc = master
master.types[I.type] = src
return I.w_class
if(istype(W,/obj/item/weapon/cable_coil))
var/obj/item/weapon/cable_coil/I = W
if(!I.amount) // todo: am I making a bad assumption here?
del I
return
for(var/obj/item/weapon/cable_coil/O in master.contents)
if(O.type == I.type && O.amount < MAXCOIL)
if(I.amount + O.amount <= MAXCOIL)
O.amount += I.amount
del I
return O.w_class
var/leftover = I.amount + O.amount - MAXCOIL
O.amount = MAXCOIL
I.amount = leftover
continue
//end for
I.loc = master
master.types[I.type] = src
return I.w_class
//If the stack isn't finished yet, don't eject it
//unless this profile has been disabled.
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(src.enabled && (I.amount < I.max_amount))
return // Still needs to be stacked
..(W,D)
if(istype(W,/obj/item/weapon/cable_coil))
var/obj/item/weapon/cable_coil/I = W
if(src.enabled && (I.amount < MAXCOIL))
return // Still needs to be stacked
..(W,D)
//Outlet stacker: used when the output square can be trusted.
//Outputs immediately, adding to stacks in the outlet.
/datum/cargoprofile/unary/stacker
name = "Stack Items"
id = "ustacker"
blacklist = null
whitelist = list(/obj/item/stack,/obj/item/weapon/cable_coil)
dedicated_path = /obj/machinery/programmable/unary/stacker
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
//Only pick it up if you are going to stack it
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(I.amount >= I.max_amount)
return 0
for(var/obj/item/stack/other in S.contents)
if(other.type == I.type && other != I && other.amount < other.max_amount)
return ..(W,S,remaining)
return 0
if(istype(W,/obj/item/weapon/cable_coil))
var/obj/item/weapon/cable_coil/I = W
if(I.amount >= MAXCOIL)
return 0
for(var/obj/item/weapon/cable_coil/other in S.contents)
if(other != I && other.amount < MAXCOIL)
return ..(W,S,remaining)
return 0
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
for(var/obj/item/stack/O in D.contents)
if(O.type == I.type && O.amount < O.max_amount)
if(I.amount + O.amount <= O.max_amount)
O.amount += I.amount
del I
return
var/leftover = I.amount + O.amount - O.max_amount
O.amount = O.max_amount
I.amount = leftover
continue
//end for
I.loc = D
return
if(istype(W,/obj/item/weapon/cable_coil))
var/obj/item/weapon/cable_coil/I = W
for(var/obj/item/weapon/cable_coil/O in D.contents)
if(O.type == I.type && O.amount < MAXCOIL)
if(I.amount + O.amount <= MAXCOIL) // Why did they make it a #define.
O.amount += I.amount
O.update_icon()
del I
return
var/leftover = I.amount + O.amount - MAXCOIL // That wasn't a question
O.amount = MAXCOIL // It was a complaint
I.amount = leftover
continue
//end for
I.loc = D
return
//----------------------------------------------------------------------------
// Dubious Overrides (For emag use)
//----------------------------------------------------------------------------
//Clogs up the unloader. And, there may be devious uses for it...
/datum/cargoprofile/slow
name = "Slow unloader"
id = "slow"
whitelist = list(/obj/item,/obj/structure/closet,/obj/structure/bigDelivery,/obj/machinery/portable_atmospherics)
blacklist = list()
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(..())
return remaining
/datum/cargoprofile/unary/shredder
name = "Paper Shredder"
id = "shredder"
blacklist = null
whitelist = list(/obj/item/weapon/paper,/obj/item/weapon/book,/obj/item/weapon/clipboard,/obj/item/weapon/folder,/obj/item/weapon/photo)
universal = 1
dedicated_path = /obj/machinery/programmable/unary/shredder
proc/cliptags(var/Text)
//Removes all html tags
var/index
var/index2
index = findtextEx(Text,"<")
while(index)
index2 = findtextEx(Text,">",index)
if(!index2)
return copytext(Text,1,index)
Text = "[copytext(Text,1,index)][copytext(Text,index2+1,0)]"
index = findtextEx(Text,"<")
//should have trimmed that text there pretty good
return Text
//Recurses through the text, removing large chunks
proc/garbletext(var/Text)
var/l = length(Text)
if(l <= 3)
if(prob(20))
return pick("#","|","/","*",".","."," ","."," "," ")
return Text
if(prob(50))
return "[garbletext(copytext(Text,1,l/2))][garbletext(copytext(Text,l/2,0))]"
if(prob(50))
return "[pick("#","|","/","*",".","."," ","."," "," ")][garbletext(copytext(Text,1,l/2))]"
return "[garbletext(copytext(Text,l/2,0))][pick("#","|","/","*",".","."," ","."," "," ")]"
proc/garble_keeptags(var/Text)
var/list/L = stringsplit(Text,">")
var/result = ""
for(var/string in L)
var/index = findtextEx(string,"<")
if(index!=1)
result += "[garbletext(copytext(string,1,index))][copytext(string,index)]>"
else
result += "[string]>"
return copytext(result,1,lentext(result))
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/weapon/paper/crumpled))
del W
return
if(istype(W,/obj/item/weapon/clipboard) || istype(W,/obj/item/weapon/folder))
// destroy folder, various effects on contents
for(var/obj/item/I in W.contents)
if(prob(25))//JUNK IT
del I
else if(prob(50)) //We've been over this. I can't just take it apart with a crowbar.
var/obj/item/weapon/paper/crumpled/P = new(master.loc)
if(I.name)
P.name = garbletext(I.name)
if(prob(66))
P.fingerprints = I.fingerprints
P.fingerprintshidden = I.fingerprintshidden
if(istype(I,/obj/item/weapon/paper))
var/obj/item/weapon/paper/O = I
P.info = garble_keeptags(O.info)
del I
..(P,D)
else
..(I,D) // Eject
del W //destroy container
return
if(prob(50)) //JUNK IT NOW!
var/obj/item/weapon/paper/crumpled/P = new(master.loc)
P.name = W.name
var/obj/item/I = W
if(prob(66))
P.fingerprints = I.fingerprints
P.fingerprintshidden = I.fingerprintshidden
if(istype(I,/obj/item/weapon/paper))
var/obj/item/weapon/paper/O = I
if(O.info)
P.info = garble_keeptags(O.info)
if(istype(I,/obj/item/weapon/book))
var/obj/item/weapon/book/B = I
if(B.dat)
P.info = garble_keeptags(B.dat)
if(B.carved && B.store)
..(B.store,D)
del W
..(P,D)
else //I want it junked
del W
return
/datum/cargoprofile/unary/gibber
name = "human shredding"
id = "flesh"
whitelist = list(/mob/living/carbon,/mob/living/simple_animal)
blacklist = null
mobcheck = 1
contains(var/atom/A)
if(!istype(A,/mob))
return
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
var/mob/living/M = W
if(istype(M) && (remaining > MOB_WORK))
//this is necessarily damaging
var/damage = rand(1,5)
M << "\red <B>The unloading machine grabs you with a hard metallic claw!</B>"
if(M.client)
M.client.eye = master
M.client.perspective = EYE_PERSPECTIVE
M.loc = master
master.types[M.type] = src
M.apply_damage(damage) // todo: ugly
M.visible_message("\red [M.name] gets pulled into the machine!")
return MOB_WORK
outlet_reaction(var/atom/W,var/turf/D)
var/mob/living/M = W
var/bruteloss = M.bruteloss
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/C = M
for(var/datum/organ/external/L in C.organs)
bruteloss += L.brute_dam
if(bruteloss < 100) // requires tenderization
M.apply_damage(rand(5,15),BRUTE)
M << "The machine is tearing you apart!"
master.visible_message("\red [master] makes a squishy grinding noise.")
return
M.loc = master.loc
M.gib()
return
/datum/cargoprofile/people
name = "Manhandling"
id = "people"
whitelist = null
blacklist = list(/mob/camera,/mob/new_player,/mob/living/simple_animal/hostile/blobspore,/mob/living/simple_animal/hostile/creature,
/mob/living/simple_animal/space_worm,/mob/living/simple_animal/shade,/mob/living/simple_animal/hostile/faithless,/mob/dead)
universal = 1
mobcheck = 1
contains(var/atom/A)
if(!istype(A,/mob))
return
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
var/mob/living/M = W
if(remaining > MOB_WORK)
//this is necessarily damaging
var/damage = rand(1,5)
M << "\red <B>The unloading machine grabs you with a hard metallic claw!</B>"
if(M.client)
M.client.eye = master
M.client.perspective = EYE_PERSPECTIVE
M.loc = master
master.types[M.type] = src
M.apply_damage(damage) // todo: ugly
M.visible_message("\red [M.name] gets pulled into the machine!")
return MOB_WORK
outlet_reaction(var/atom/W,var/turf/D)
var/mob/living/M = W
M.loc = master.loc
M.dir = master.outdir
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
D = get_step(D,master.outdir) // throw attempt
eject_speed = rand(0,4)
M.visible_message("\blue [M.name] is ejected from the unloader.")
M.throw_at(D,eject_speed,eject_speed)
return
/datum/cargoprofile/unary/trainer
name = "Boxing Trainer"
id = "trainer"
blacklist = list()
whitelist = list(/mob/living/carbon/human)
mobcheck = 1
var/const/PUNCH_WORK = 6
dedicated_path = /obj/machinery/programmable/unary/trainer
contains(var/atom/A)
if(!istype(A,/mob))
return 0
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
proc/punch(var/mob/living/carbon/human/M,var/maxpunches)
//stolen from holographic boxing gloves code
//This should probably be done BY the mob, however, the attack code will be expecting a source mob.
var/damage
if(prob(75))
damage = rand(0, 6) // pap
else
damage = rand(0, 12) // thwack
if(!damage)
playsound(master.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
master.visible_message("\red \The [src] punched at [M], but whiffed!")
if(maxpunches > 1 && prob(50)) // Follow through on a miss, 50% chance
return punch(M,maxpunches - 1) + 1
return 1
var/datum/organ/external/affecting = M.get_organ(ran_zone("chest",50))
var/armor_block = M.run_armor_check(affecting, "melee")
playsound(master.loc, "punch", 25, 1, -1)
master.visible_message("\red <B>\The [src] has punched [M]!</B>")
if(!master.emagged)
M.apply_damage(damage, HALLOSS, affecting, armor_block) // Clean fight
else
M.apply_damage(damage, BRUTE, affecting, armor_block) // Foul! Foooul!
if(damage >= 9)
master.visible_message("\red <B>\The [src] has weakened [M]!</B>")
M.apply_effect(4, WEAKEN, armor_block)
if(!master.emagged)
master.sleep = 1
return maxpunches // The machine is not so sophisticated as to not gloat
else
if(prob(25)) // Follow through on a hit, 25% chance. Pause after.
return punch(M,maxpunches-1) + 1
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
//stolen from boxing gloves code
var/mob/living/carbon/human/M = W
if((M.lying || (M.health - M.halloss < 25))&& !master.emagged)
M << "\The [src] gives you a break."
master.sleep+=5
return 0 // Be polite
var/punches = punch(M,remaining / PUNCH_WORK)
if(punches>1)master.sleep++
return punches * PUNCH_WORK

View File

@@ -0,0 +1,745 @@
// TODO: Check access
// TODO: Renameable circuit boards
// TODO: Disks? Disassembly?
/obj/machinery/programmable
name = "Programmable Unloader"
icon = 'icons/obj/machines/mining_machines.dmi'
icon_state = "unloader"
density = 1
anchored = 1.0
var/debug = 0 // When set, this WILL spam people around the machine.
// Identifies profile used and on which item.
var/on = 1
var/indir = 8
var/outdir = 4
var/turf/input = null
var/turf/output = null
var/typename = "Unloader"
var/ident = "#1"
var/const/workmax = 20
var/datum/cargoprofile/default = new()
var/list/profiles = list(new/datum/cargoprofile/cargo(),new/datum/cargoprofile/boxes(),new/datum/cargoprofile/supplies(),
new/datum/cargoprofile/exotics(),new/datum/cargoprofile/tools(),new/datum/cargoprofile/weapons(),
new/datum/cargoprofile/pressure(),new/datum/cargoprofile/chemical(),
new/datum/cargoprofile/food(),new/datum/cargoprofile/clothing(),new/datum/cargoprofile/trash())
var/list/overrides = list(new/datum/cargoprofile/cargo/unload(),new/datum/cargoprofile/in_stacker())
var/list/emag_overrides = list(new/datum/cargoprofile/people(),new/datum/cargoprofile/unary/shredder(),new/datum/cargoprofile/unary/trainer())
var/list/types = list()
anchored = 1
var/unwrenched = 0
use_power = 1
var/sleep = 0 // When set, the machine will skip the next however-many updates (to avoid spam)
var/open = 0
var/circuit_removed = 0
/obj/machinery/programmable/New()
..()
if(default)
default.master = src
if(!default.enabled)
default.enabled = 1
for(var/datum/cargoprofile/p in emag_overrides + overrides + profiles)
p.master = src
input = get_step(src.loc,indir)
output = get_step(src.loc,outdir)
var/count = 0
for(var/obj/machinery/programmable/other in world)
if(other.typename == typename)
count++
ident = "#[count]"
name = "[typename] [ident]"
/obj/machinery/programmable/RefreshParts()
//This is called when the machine was constructed.
//Unfortunately, it puts machine parts in our contents list, which we're using.
//Fortunately, we aren't likely to ever need the components list, circuitboard excepted.
for(var/obj/O in contents)
if(istype(O,/obj/item/weapon/circuitboard/programmable))//retrieve settings here
var/obj/item/weapon/circuitboard/programmable/C = O
default = C.default
emagged = C.emagged
profiles = C.profiles
overrides = C.overrides
emag_overrides = C.emag_overrides
//unary and binary methods (one vs two locales) don't mix
if(istype(src,/obj/machinery/programmable/unary))
for(var/datum/cargoprofile/P in profiles)
if(!istype(P,/datum/cargoprofile/unary) && !P.universal)
profiles -= P
for(var/datum/cargoprofile/P in overrides)
if(!istype(P,/datum/cargoprofile/unary) && !P.universal)
overrides -= P
for(var/datum/cargoprofile/P in emag_overrides)
if(!istype(P,/datum/cargoprofile/unary) && !P.universal)
emag_overrides -= P
else
for(var/datum/cargoprofile/P in profiles)
if(istype(P,/datum/cargoprofile/unary) && !P.universal)
profiles -= P
for(var/datum/cargoprofile/P in overrides)
if(istype(P,/datum/cargoprofile/unary) && !P.universal)
overrides -= P
for(var/datum/cargoprofile/P in emag_overrides)
if(istype(P,/datum/cargoprofile/unary) && !P.universal)
emag_overrides -= P
if(default)
default.master = src
for(var/datum/cargoprofile/p in emag_overrides + overrides + profiles)
p.master = src
del C
else
del O
/obj/machinery/programmable/attack_hand(mob/user as mob)
if(stat) // moved, or something else
return
usr.set_machine(src)
interact(user)
/obj/machinery/programmable/proc/printlist(var/list/L)
var/dat
for(var/datum/cargoprofile/p in L)
dat += "[p.name]: <A href='?src=\ref[src];operation=[p.id]'>[p.enabled?"<B>YES</B>":"NO"]</A><BR>"
return dat
/obj/machinery/programmable/proc/buildMenu()
var/dat
dat += "<B>PROGRAMMABLE UNLOADER</B><BR><TT>"
dat += "POWER: <A href='?src=\ref[src];operation=start'>[on ? "ON" : "OFF"]</A><BR>"
dat += "INLET: <A href='?src=\ref[src];operation=inlet'>[capitalize(dir2text(indir))]</A> "
dat += "OUTLET: <A href='?src=\ref[src];operation=outlet'>[capitalize(dir2text(outdir))]</A>"
dat += " (<A href='?src=\ref[src];operation=swapdir'>SWAP</A>)</TT><HR>"
if(default)
dat += "MAIN PROGRAM: "
dat += "<TT>[default.name]: <A href='?src=\ref[src];operation=default'>[default.enabled ? "<B>YES</B>" : "NO"]</A><BR>"
if(profiles.len)
if(!default || !default.enabled)
dat += printlist(profiles)
dat += "</TT>"
if(overrides.len)
dat += "<HR>OVERRIDES:<BR><TT>"
dat += printlist(overrides)
dat += "</TT>"
return dat
/obj/machinery/programmable/interact(mob/user as mob)
var/dat = buildMenu()
user << browse("<HEAD><TITLE>Unloader</TITLE></HEAD>[dat]", "window=progreload")
onclose(user, "progreload")
return
/obj/machinery/programmable/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
switch(href_list["operation"])
if("start")
on = (on ? 0 : 1)
if(on) use_power = 1
else use_power = 0
updateUsrDialog()
return
if("inlet")
indir *= 2 // N S E W
if(indir > 8)
indir = 1 // W N
if(indir == src.outdir)
indir *= 2
if(indir > 8)
indir = 1
input = get_step(src,indir) // todo: check for glasswalls / no path to target?
updateUsrDialog()
return
if("outlet")
outdir *= 2
if(outdir > 8)
outdir = 1
if(outdir == indir)
outdir *= 2
if(outdir > 8)
outdir = 1
output = get_step(src,outdir) // todo: check for walls / glasswalls / invalid output locations
updateUsrDialog()
return
if("swapdir")
var/temp = outdir
outdir = indir
indir = temp
input = get_step(src,indir)
output = get_step(src,outdir)
updateUsrDialog()
return
if("default")
default.enabled = (default.enabled ? 0 : 1)
updateUsrDialog()
return
var/which = href_list["operation"]
for(var/datum/cargoprofile/p in overrides + profiles)
if(which == p.id)
p.enabled = (p.enabled? 0 : 1)
updateUsrDialog()
return
/obj/machinery/programmable/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I,/obj/item/weapon/card/emag))
if(emagged)
return
user << "You swipe the unloader with your card. After a moment's grinding, it beeps in a sinister fashion."
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
emagged = 1
overrides += emag_overrides
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(2, 1, src)
s.start()
return
if(istype(I,/obj/item/weapon/wrench)) // code borrowed from pipe dispenser
if (unwrenched==0)
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to unfasten \the [src] from the floor..."
if (do_after(user, 40))
user.visible_message( \
"[user] unfastens \the [src].", \
"\blue You have unfastened \the [src]. Now it can be pulled somewhere else.", \
"You hear ratchet.")
src.anchored = 0
src.stat |= MAINT
src.unwrenched = 1
if (usr.machine==src)
usr << browse(null, "window=pipedispenser")
else /* unwrenched */
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "\blue You begin to fasten \the [src] to the floor..."
if (do_after(user, 20))
user.visible_message( \
"[user] fastens \the [src].", \
"\blue You fastened \the [src] into place.", \
"You hear ratchet.")
src.anchored = 1
src.input = get_step(src.loc,src.indir)
src.output = get_step(src.loc,src.outdir)
if(!open && !circuit_removed)
src.stat &= ~MAINT
src.unwrenched = 0
power_change()
if(istype(I,/obj/item/weapon/screwdriver))
if(open)
open = 0
if(!unwrenched && !circuit_removed)
src.stat &= ~MAINT
user << "You open the [src]'s maintenance panel."
else
open = 1
src.stat |= MAINT
user << "You close the [src]'s maintenance panel."
if(istype(I,/obj/item/weapon/crowbar))
if(open)
user << "\blue You begin to pry out the [src]'s circuits."
if(do_after(user,40))
user << "\blue You remove the circuitboard."
circuit_removed = 1
use_power = 0
on = 0
var/obj/item/weapon/circuitboard/programmable/P = new(src.loc)
P.emagged = src.emagged
P.default = src.default
src.default = null
P.profiles = src.profiles
src.profiles = null
P.overrides = src.overrides
src.overrides = null
P.emag_overrides = src.emag_overrides
src.emag_overrides = null
return
else
..(I,user)
if(istype(I,/obj/item/weapon/circuitboard/programmable))
if(!open)
user << "You have to open the machine first!"
return
if(!circuit_removed)
user << "There is already a circuitboard present!"
return
circuit_removed = 0
I.loc = src
RefreshParts()
/obj/machinery/programmable/process()
if (!output || !input)
return
if(!on || stat || sleep)
if(sleep > 0) // prevent input or output errors from happening every tick
sleep--
use_power = 0
//Do not let things get stuck inside. That's broken behavior.
for(var/obj/O in contents)
O.loc = loc
for(var/mob/M in contents)
M.loc = loc
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
M << "\blue The machine turns off, and you fall out."
return
//Normal output reaction
if(contents.len)
for(var/atom/movable/A in contents)
var/datum/cargoprofile/p = types[A.type]
if(p)
p.outlet_reaction(A,output)
else
A.loc = output // may have been dropped by a mob, etc
if(types.len > 50)
types = list() // good luck mr. garbage collector
var/work = 0
for(var/mob/M in input.contents)
for(var/datum/cargoprofile/p in overrides + default)
if(p.enabled && p.mobcheck && p.contains(M))
var/done = p.inlet_reaction(M,input,workmax - work)
if(done)
work += done
if(src.debug)
visible_message("[p.name]:[M.name] ([done])")
break
if(sleep)
return // something stopped the machine
for (var/obj/A in input.contents)// I fully expect this to cause unreasonable lag
if(!A)
break
if(work > workmax)
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0) // Beep if the machine is full - testing only probably
break
var/done = 0 // work done - testing only
var/aname // target item name - testing only
for(var/datum/cargoprofile/p in overrides)
if(p.enabled && p.contains(A))
aname = A.name // in case of deletion
done = p.inlet_reaction(A,input,workmax - work)
if(done)
work += done
if(src.debug)
visible_message("[p.name]:[aname] ([done])")
else
break
if(sleep)
break // Something stopped the machine
if(!A || A.loc != input || done)
continue // next item
if(default && default.enabled)
if(default.contains(A))
aname = A.name
done = default.inlet_reaction(A,input,workmax - work)
if(done)
work += done
if(src.debug)
visible_message("[default.name]: [aname] ([done])")
continue
for(var/datum/cargoprofile/p in profiles)
if(p.enabled && p.contains(A))
aname = A.name
done = p.inlet_reaction(A,input,workmax - work)
if(done)
work += done
if(src.debug)
visible_message("[p.name]:[aname] ([done])")
else
break
if(work)
use_power = 2
else
use_power = 1
//----------------------------------------------------------------------------
// Specialty machines
//----------------------------------------------------------------------------
//Uses the inlet stacking profile. Ejects only full stacks.
/obj/machinery/programmable/stacker
name = "Stacking & Spooling Machine"
default = new/datum/cargoprofile/in_stacker()
profiles = list()
overrides = list()
emag_overrides = list()
typename = "Stacking and Spooling Machine"
/obj/machinery/programmable/unloader
name = "Cargo Unloader"
default = new/datum/cargoprofile/cargo/unload()
profiles = list()
overrides = list()
emag_overrides = list()
typename = "Cargo Unloader"
/obj/machinery/programmable/delivery
name = "Finished robot delivery"
default = new/datum/cargoprofile/finished()
profiles = list()
overrides = list()
emag_overrides = list()
typename = "Robot Delivery"
/obj/machinery/programmable/crate_handler
name = "Crate Handler"
default = null
profiles = list(new/datum/cargoprofile/cargo/unload(),new/datum/cargoprofile/cargo(),new/datum/cargoprofile/cargo/empty(),new/datum/cargoprofile/cargo/full())
overrides = list()
emag_overrides = list()
typename = "Crate Handler"
//----------------------------------------------------------------------------
// Unary machine: Input and output in the same location
// Be careful with this, it could easily be running the same
// computations every round needlessly
//----------------------------------------------------------------------------
/obj/machinery/programmable/unary
name = "Programmable Processor"
default = null
profiles = list()
overrides = list(new/datum/cargoprofile/unary/stacker(),new/datum/cargoprofile/unary/trainer())
emag_overrides = list(new/datum/cargoprofile/unary/shredder())
indir = 1
outdir = 1
typename = "Processor"
New()
..()
outdir = indir
output = input
buildMenu()
var/dat
dat += "<B>PROGRAMMABLE PROCESSOR</B><BR><TT>"
dat += "POWER: <A href='?src=\ref[src];operation=start'>[on ? "ON" : "OFF"]</A><BR>"
dat += "INLET: <A href='?src=\ref[src];operation=inlet'>[capitalize(dir2text(indir))]</A><BR>"
if(default)
dat += "MAIN PROGRAM: "
dat += "<TT>[default.name]: <A href='?src=\ref[src];operation=default'>[default.enabled ? "<B>YES</B>" : "NO"]</A><BR>"
if(profiles.len)
if(!default || !default.enabled)
dat += printlist(profiles)
dat += "</TT>"
if(overrides.len)
dat += "<HR>OVERRIDES:<BR><TT>"
dat += printlist(overrides)
dat += "</TT>"
return dat
Topic(href, href_list)
switch(href_list["operation"])
if("inlet")
indir *= 2 // N S E W
if(indir > 8)
indir = 1 // W N
outdir = indir
input = get_step(src,indir) // todo: check for glasswalls / no path to target?
output = input
updateUsrDialog()
return
return ..()
/obj/machinery/programmable/unary/stacker
name = "Stacking Machine"
default = new/datum/cargoprofile/unary/stacker()
profiles = list()
overrides = list()
emag_overrides = list()
typename = "Stacking Machine"
/obj/machinery/programmable/unary/shredder
name = "Paper Shredder"
default = new/datum/cargoprofile/unary/shredder()
profiles = list()
overrides = list()
emag_overrides = list(new/datum/cargoprofile/unary/gibber())
typename = "Paper Shredder"
/obj/machinery/programmable/unary/trainer
name = "\improper Boxing Trainer"
default = new/datum/cargoprofile/unary/trainer()
profiles = list()
overrides = list()
emag_overrides = list()
typename = "Boxing Trainer"
attack_hand(mob/user as mob) //How did I type this with boxing gloves on?
if(!istype(user,/mob/living/carbon/human))
return ..()
var/mob/living/carbon/human/H = user
if(H.gloves && istype(H.gloves, /obj/item/clothing/gloves/boxing))
var/newsleep = 0
if(H.loc != input)
H << "The boxing machine refuses to acknowledge you unless you face it head on!"
return
var/damage = 0
if(H.a_intent != "hurt")
damage += rand(0,5)
else
damage += rand(0,10)
if(!damage)
playsound(H.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("[H] tries to punch \the [src], but whiffs")
return
playsound(loc, "punch", 25, 1, -1)
if(HULK in H.mutations) damage += 5
if(damage < 5)
visible_message("[H] gives \the [src] a weak punch.")
if(prob(10))
visible_message("\blue \The [src] feints at [H], as though mocking \him.")
else if(damage < 10)
visible_message("[H] hits \the [src] with a solid [pick("punch","jab","smack")].")
else if(damage < 15)
visible_message("[pick("Whoa!","Nice!","Gasp!")] [H] hits [src] with a powerful [pick("punch","jab","uppercut","left hook", "right hook")].")
else if(damage < 20)
visible_message("[pick("WHOA!","ACK!","Jeez!")] [H] hits [src] so hard, the whole machine rocks band and forth for a moment.")
else
visible_message("Holy moly! [H] hits \the [src] so hard it stops working.")
stat |= BROKEN
return
while(damage >= 5)
if(prob(50))
newsleep++
damage -= 5
if(newsleep)
if(emagged)
visible_message("\red \The [src]'s lights glow a bloodthirsty red. It refuses to stop!")
sleep = 0
else
sleep += newsleep
visible_message("\blue \The [src]'s lights dim for a moment and it beeps, signifying a valid hit.")
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
return
else
return ..()
//----------------------------------------------------------------------------
// For construction
//----------------------------------------------------------------------------
/obj/item/weapon/circuitboard/programmable
name = "Circuit board (Programmable Unloader)"
build_path = "/obj/machinery/programmable"
board_type = "machine"
origin_tech = "engineering=3;programming=6"
frame_desc = "Requires 2 Manipulators, 1 Scanning Module, 1 Cable."
req_components = list(
"/obj/item/weapon/stock_parts/scanning_module" = 1,
"/obj/item/weapon/stock_parts/manipulator" = 2,
"/obj/item/weapon/cable_coil" = 1)
//Customization of the machine
var/datum/cargoprofile/default = new/datum/cargoprofile()
var/list/profiles = list()
var/list/overrides = list()
var/list/emag_overrides = list()
var/emagged = 0
var/hacking = 0
proc/resetlists()
profiles = list(new/datum/cargoprofile/cargo(),new/datum/cargoprofile/boxes(),new/datum/cargoprofile/supplies(),
new/datum/cargoprofile/exotics(),new/datum/cargoprofile/tools(),new/datum/cargoprofile/weapons(),new/datum/cargoprofile/finished(),
new/datum/cargoprofile/pressure(),new/datum/cargoprofile/pressure/full(),new/datum/cargoprofile/pressure/empty(),
new/datum/cargoprofile/chemical(),new/datum/cargoprofile/organics(),new/datum/cargoprofile/food(),
new/datum/cargoprofile/clothing(),new/datum/cargoprofile/trash())
overrides = list(new/datum/cargoprofile/cargo/unload(),new/datum/cargoprofile/in_stacker(),
new/datum/cargoprofile/unary/stacker(),new/datum/cargoprofile/unary/trainer())
emag_overrides = list(new/datum/cargoprofile/people(),new/datum/cargoprofile/unary/shredder())
New()
..()
resetlists()
attackby(obj/item/I as obj, mob/user as mob)
if(istype(I,/obj/item/device/multitool))
hacking = (hacking?0:1)
if(hacking)
user << "You unlock the data port on the board. You can now use a PDA to alter its data."
else
user << "You relock the data port."
if(istype(I,/obj/item/device/pda))
if(!hacking)
user << "It looks like you can't access the board's data port. You'll have to open it with a multitool."
else
user.set_machine(src)
interact(user)
if(istype(I,/obj/item/weapon/card/emag) && !emagged)
if(!hacking)
user << "There seems to be a data port on the card, but it's locked. A multitool could open it."
else
emagged = 1
overrides += emag_overrides
user << "You swipe the card in the card's data port. The lights flicker, then flash once."
proc/format(var/datum/cargoprofile/P,var/level)
// PROFILE=0 OVERRIDE=1 MAIN=2
if(P == null)
return "NONE<BR>"
var/dat = "[P.name]"
if(level == 0 || (level == 1 && !default))
dat += " <A href='?src=\ref[src];operation=promote;id=[P.id];level=[level]'>PROMOTE</A>"
if(level > 0)
dat += " <A href='?src=\ref[src];operation=demote;id=[P.id];level=[level]'>DEMOTE</A>"
dat += " <A href='?src=\ref[src];operation=delete;id=[P.id];level=[level]'>REMOVE</A>"
dat += "<BR>"
return dat
interact(mob/user as mob)
var/dat
dat = "MAIN FUNCTION<BR><TT>"
dat += format(default,2)
dat += "</TT>- CAUTION -<BR>\[<A href='?src=\ref[src];operation=deleteall'>DELETE NON-MAIN ALGORITHMS</A>\]<BR>"
dat += "\[<A href='?src=\ref[src];operation=reset'>MASTER RESET</A>\]<HR>"
dat += "OVERRIDES:<BR><TT>"
for(var/datum/cargoprofile/P in overrides)
dat += format(P,1)
dat += "</TT><BR>"
dat += "- CAUTION -<BR>\[<A href='?src=\ref[src];operation=deleteoverrides'>DELETE ALL OVERRIDES</A>\]<HR>"
dat += "</TT> TERTIARY PROFILES:<BR><TT>"
for(var/datum/cargoprofile/P in profiles)
dat += format(P,0)
dat += "</TT><BR>"
dat += "- CAUTION -<BR>\[<A href='?src=\ref[src];operation=deleteprofiles'>DELETE TERTIARY PROFILES</A>\]"
user << browse("<HEAD><TITLE>Circuit Reprogramming</TITLE></HEAD>[dat]", "window=progcircuit")
onclose(user, "progcircuit")
Topic(href, href_list)
if(..())
return
usr.set_machine(src)
var/id = href_list["id"]
var/level = text2num(href_list["level"])
switch(href_list["operation"])
if("promote")
if(level == 0)
for(var/datum/cargoprofile/T in profiles)
if(T.id == id)
overrides += T
profiles -= T
//updateUsrDialog()
interact(usr)
return
if(level == 1)
if(default) return
for(var/datum/cargoprofile/T in overrides)
if(T.id == id)
default = T
overrides -= T
if(default.dedicated_path)
build_path = "[default.dedicated_path]"
else
if(istype(default,/datum/cargoprofile/unary))
build_path = "/obj/machinery/programmable/unary"
else
build_path = "/obj/machinery/programmable"
//updateUsrDialog()
interact(usr)
return
if("demote")
if(level == 2)
overrides += default
default = null
//updateUsrDialog()
interact(usr)
return
if(level == 1)
for(var/datum/cargoprofile/T in overrides)
if(T.id == id)
profiles += T
overrides -= T
//updateUsrDialog()
interact(usr)
return
if("delete")
if(level == 2)
default = null
//updateUsrDialog()
interact(usr)
return
if(level == 1)
for(var/datum/cargoprofile/T in overrides)
if(T.id == id)
overrides -= T
//updateUsrDialog()
interact(usr)
return
if(level == 0)
for(var/datum/cargoprofile/T in profiles)
if(T.id == id)
profiles -= T
//updateUsrDialog()
interact(usr)
return
if("deleteall")
for(var/datum/cargoprofile/T in profiles)
profiles -= T
for(var/datum/cargoprofile/T in overrides)
overrides -= T
//updateUsrDialog()
interact(usr)
return
if("deleteoverrides")
for(var/datum/cargoprofile/T in overrides)
overrides -= T
interact(usr)
return
if("deleteprofiles")
for(var/datum/cargoprofile/T in profiles)
profiles -= T
interact(usr)
return
if("reset")
resetlists()
interact(usr)
return
//End switch
datum/design/programmable
name = "Circuit Design (Programmable Unloader)"
desc = "Allows for the construction of circuit boards used to build a Programmable Unloader."
id = "selunload"
req_tech = list("programming" = 5)
build_type = IMPRINTER
materials = list("$glass" = 2000, "sacid" = 20)
build_path = "/obj/item/weapon/circuitboard/programmable"