mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-17 18:13:34 +01:00
Fixes conflict with explosives PR
This commit is contained in:
@@ -92,7 +92,7 @@
|
||||
qdel(I)
|
||||
|
||||
/obj/effect/buildmode_line
|
||||
var/image/I
|
||||
var/image/I
|
||||
var/client/cl
|
||||
|
||||
/obj/effect/buildmode_line/New(var/client/c, var/atom/atom_a, var/atom/atom_b, var/linename)
|
||||
@@ -101,13 +101,13 @@
|
||||
I = image('icons/misc/mark.dmi', src, "line", 19.0)
|
||||
var/x_offset = ((atom_b.x * 32) + atom_b.pixel_x) - ((atom_a.x * 32) + atom_a.pixel_x)
|
||||
var/y_offset = ((atom_b.y * 32) + atom_b.pixel_y) - ((atom_a.y * 32) + atom_a.pixel_y)
|
||||
|
||||
|
||||
var/matrix/M = matrix()
|
||||
M.Translate(0, 16)
|
||||
M.Scale(1, sqrt((x_offset * x_offset) + (y_offset * y_offset)) / 32)
|
||||
M.Turn(90 - Atan2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
|
||||
M.Translate(atom_a.pixel_x, atom_a.pixel_y)
|
||||
|
||||
|
||||
transform = M
|
||||
cl = c
|
||||
cl.images += I
|
||||
@@ -242,6 +242,7 @@
|
||||
if(FILL_BUILDMODE)
|
||||
to_chat(user, "<span class='notice'>***********************************************************</span>")
|
||||
to_chat(user, "<span class='notice'>Left Mouse Button on turf/obj/mob = Select corner</span>")
|
||||
to_chat(user, "<span class='notice'>Left Mouse Button + Alt on turf/obj/mob = Delete region</span>")
|
||||
to_chat(user, "<span class='notice'>Right Mouse Button on buildmode button = Select object type</span>")
|
||||
to_chat(user, "<span class='notice'>***********************************************************</span>")
|
||||
if(LINK_BUILDMODE)
|
||||
@@ -509,16 +510,20 @@
|
||||
cornerB = select_tile(get_turf(object))
|
||||
if(left_click) //rectangular
|
||||
if(cornerA && cornerB)
|
||||
if(!objholder)
|
||||
to_chat(user, "<span class='warning'>Select object type first.</span>")
|
||||
if(alt_click)
|
||||
empty_region(block(get_turf(cornerA),get_turf(cornerB)))
|
||||
deselect_region()
|
||||
else
|
||||
for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
|
||||
if(ispath(objholder,/turf))
|
||||
T.ChangeTurf(objholder)
|
||||
else
|
||||
var/obj/A = new objholder(T)
|
||||
A.dir = build_dir
|
||||
deselect_region()
|
||||
if(!objholder)
|
||||
to_chat(user, "<span class='warning'>Select object type first.</span>")
|
||||
else
|
||||
for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
|
||||
if(ispath(objholder,/turf))
|
||||
T.ChangeTurf(objholder)
|
||||
else
|
||||
var/obj/A = new objholder(T)
|
||||
A.dir = build_dir
|
||||
deselect_region()
|
||||
return
|
||||
|
||||
//Something wrong - Reset
|
||||
@@ -567,13 +572,13 @@
|
||||
if(P.id_tag && P.id_tag != 1 && alert(holder, "Warning: This will unlink something else from the door. Continue?", "Buildmode", "Yes", "No") == "No")
|
||||
goto(line_jump)
|
||||
P.id_tag = M.id
|
||||
|
||||
|
||||
line_jump // For the goto
|
||||
valid_links = 0
|
||||
for(var/obj/effect/buildmode_line/L in link_lines)
|
||||
qdel(L)
|
||||
link_lines -= L
|
||||
|
||||
|
||||
if(istype(link_obj, /obj/machinery/door_control))
|
||||
var/obj/machinery/door_control/M = link_obj
|
||||
for(var/obj/machinery/door/airlock/P in range(M.range,M))
|
||||
|
||||
@@ -847,7 +847,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
sec_briefcase.contents += new /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow
|
||||
sec_briefcase.contents += new /obj/item/weapon/gun/projectile/revolver/mateba
|
||||
sec_briefcase.contents += new /obj/item/ammo_box/a357
|
||||
sec_briefcase.contents += new /obj/item/weapon/c4
|
||||
sec_briefcase.contents += new /obj/item/weapon/grenade/plastic/c4
|
||||
// briefcase must be unlocked by setting the code.
|
||||
M.equip_to_slot_or_del(sec_briefcase, slot_l_hand)
|
||||
var/obj/item/weapon/implant/dust/DUST = new /obj/item/weapon/implant/dust(M)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/client/proc/map_template_load()
|
||||
set category = "Debug"
|
||||
set name = "Map Template - Place"
|
||||
set name = "Map template - Place"
|
||||
|
||||
if(!holder)
|
||||
return
|
||||
|
||||
var/datum/map_template/template
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in map_templates
|
||||
@@ -16,22 +15,27 @@
|
||||
if(!T)
|
||||
return
|
||||
|
||||
if(!template.fits_in_map_bounds(T, centered = TRUE))
|
||||
to_chat(usr, "Map is too large to fit in bounds. Map's dimensions: ([template.width], [template.height])")
|
||||
return
|
||||
|
||||
var/list/preview = list()
|
||||
for(var/S in template.get_affected_turfs(T,centered = TRUE))
|
||||
preview += image('icons/turf/overlays.dmi',S,"greenOverlay")
|
||||
usr.client.images += preview
|
||||
if(alert(usr,"Confirm location.","Template Confirm","Yes","No") == "Yes")
|
||||
template.load(T, centered = TRUE)
|
||||
message_admins("[key_name_admin(usr)] has placed a map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</A>")
|
||||
var/timer = start_watch()
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has started to place the map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a></span>")
|
||||
if(template.load(T, centered = TRUE))
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a>. Took [stop_watch(timer)]s.</span>")
|
||||
else
|
||||
to_chat(usr, "Failed to place map")
|
||||
usr.client.images -= preview
|
||||
|
||||
/client/proc/map_template_upload()
|
||||
set category = "Debug"
|
||||
set name = "Map Template - Upload"
|
||||
|
||||
if(!holder)
|
||||
return
|
||||
|
||||
var/map = input(usr, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file
|
||||
if(!map)
|
||||
return
|
||||
@@ -39,7 +43,12 @@
|
||||
to_chat(usr, "Bad map file: [map]")
|
||||
return
|
||||
|
||||
var/timer = start_watch()
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has begun uploading a map template ([map])</span>")
|
||||
var/datum/map_template/M = new(map=map, rename="[map]")
|
||||
M.preload_size(map)
|
||||
map_templates[M.name] = M
|
||||
message_admins("[key_name_admin(usr)] has uploaded a map template ([map])")
|
||||
if(M.preload_size(map))
|
||||
to_chat(usr, "Map template '[map]' ready to place ([M.width]x[M.height])")
|
||||
map_templates[M.name] = M
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has uploaded a map template ([map]). Took [stop_watch(timer)]s.</span>")
|
||||
else
|
||||
to_chat(usr, "Map template '[map]' failed to load properly")
|
||||
|
||||
@@ -144,7 +144,7 @@ var/global/sent_strike_team = 0
|
||||
equip_to_slot_or_del(new /obj/item/weapon/storage/box/flashbangs(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack)
|
||||
if(!leader_selected)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/c4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(src), slot_in_backpack)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(src), slot_in_backpack)
|
||||
|
||||
@@ -148,10 +148,10 @@ var/global/sent_syndicate_strike_team = 0
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/ammo_box/magazine/m45(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/hypospray/combat/nanites(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/c4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_in_backpack)
|
||||
if(!syndicate_leader_selected)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/c4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(src), slot_in_backpack)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/card/emag(src), slot_in_backpack)
|
||||
else
|
||||
equip_to_slot_or_del(new /obj/item/weapon/pinpointer(src), slot_in_backpack)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
/obj/effect/landmark/corpse
|
||||
name = "Unknown"
|
||||
var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now
|
||||
var/mob_species = null //Set to make a mob of another race, currently used only in ruins
|
||||
var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse.
|
||||
var/corpsesuit = null
|
||||
var/corpseshoes = null
|
||||
@@ -37,6 +38,8 @@
|
||||
M.real_name = src.name
|
||||
M.death(1) //Kills the new mob
|
||||
M.timeofdeath = timeofdeath
|
||||
if(src.mob_species)
|
||||
M.set_species(src.mob_species)
|
||||
if(src.corpseuniform)
|
||||
M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform)
|
||||
if(src.corpsesuit)
|
||||
@@ -285,3 +288,10 @@
|
||||
corpseid = 1
|
||||
corpseidjob = "Commander"
|
||||
corpseidaccess = "Captain"
|
||||
|
||||
/obj/effect/landmark/corpse/abductor //Connected to ruins, for some reason?
|
||||
name = "abductor"
|
||||
mobname = "???"
|
||||
mob_species = "abductor"
|
||||
corpseuniform = /obj/item/clothing/under/color/grey
|
||||
corpseshoes = /obj/item/clothing/shoes/combat
|
||||
|
||||
@@ -9,30 +9,43 @@
|
||||
var/template_name = null
|
||||
var/datum/map_template/template = null
|
||||
var/centered = 1
|
||||
var/loaded = 0
|
||||
|
||||
/obj/effect/landmark/map_loader/New(loc, tname)
|
||||
/obj/effect/landmark/map_loader/New(turf/loc, tname)
|
||||
..()
|
||||
|
||||
if(tname)
|
||||
template_name = tname
|
||||
if(template_name)
|
||||
template = map_templates[template_name]
|
||||
|
||||
/obj/effect/landmark/map_loader/initialize()
|
||||
..()
|
||||
if(template)
|
||||
load(template)
|
||||
|
||||
/obj/effect/landmark/map_loader/set_tag()
|
||||
return
|
||||
|
||||
/obj/effect/landmark/map_loader/proc/load(datum/map_template/t)
|
||||
spawn(1)
|
||||
if(!t)
|
||||
return
|
||||
t.load(get_turf(src), centered = centered)
|
||||
t.loaded++
|
||||
qdel(src)
|
||||
if(!t)
|
||||
return
|
||||
if(loaded) // I wanna be super sure this loads only once
|
||||
return
|
||||
loaded = 1
|
||||
var/turf/pos = get_turf(src)
|
||||
// Hop to nullspace so we don't get re-initialized by the map we're loading
|
||||
loc = null
|
||||
t.load(pos, centered = centered)
|
||||
t.loaded++
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/landmark/map_loader/random
|
||||
var/template_list = ""
|
||||
|
||||
/obj/effect/landmark/map_loader/random/New()
|
||||
/obj/effect/landmark/map_loader/random/initialize()
|
||||
..()
|
||||
if(template_list)
|
||||
template_name = safepick(splittext(template_list, ";"))
|
||||
template = map_templates[template_name]
|
||||
load(template)
|
||||
load(template)
|
||||
|
||||
@@ -2,10 +2,22 @@
|
||||
//SS13 Optimized Map loader
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
//As of 3.6.2016
|
||||
//global datum that will preload variables on atoms instanciation
|
||||
var/global/use_preloader = FALSE
|
||||
var/global/dmm_suite/preloader/_preloader = new
|
||||
|
||||
/dmm_suite
|
||||
// These regexes are global - meaning that starting the maploader again mid-load will
|
||||
// reset progress - which means we need to track our index per-map, or we'll
|
||||
// eternally recurse
|
||||
// /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
|
||||
var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
|
||||
// /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
|
||||
var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
|
||||
// /^[\s\n]+|[\s\n]+$/
|
||||
var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
|
||||
var/static/list/modelCache = list()
|
||||
|
||||
/**
|
||||
* Construct the model map and control the loading process
|
||||
@@ -16,87 +28,156 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
* e.g aa = /turf/unsimulated/wall{icon_state = "rock"}
|
||||
* 2) Read the map line by line, parsing the result (using parse_grid)
|
||||
*
|
||||
* If `measureOnly` is set, then no atoms will be created, and all this will do
|
||||
* is return the bounds after parsing the file
|
||||
*
|
||||
* If you need to freeze init while you're working, you can use the spacial allocator's
|
||||
* "add_dirt" and "remove_dirt" which will put initializations on hold until you say
|
||||
* the word. This is important for loading large maps such as the cyberiad, where
|
||||
* atmos will attempt to start before it's ready, causing runtimes galore if init is
|
||||
* allowed to romp unchecked.
|
||||
*/
|
||||
/dmm_suite/load_map(dmm_file as file, x_offset = 0 as num, y_offset = 0 as num, z_offset as num, do_sleep = 1 as num)
|
||||
if(!z_offset)//what z_level we are creating the map on
|
||||
/dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num)
|
||||
var/tfile = dmm_file//the map file we're creating
|
||||
var/fname = "Lambda"
|
||||
if(isfile(tfile))
|
||||
fname = "[tfile]"
|
||||
tfile = file2text(tfile)
|
||||
|
||||
if(!x_offset)
|
||||
x_offset = 1
|
||||
if(!y_offset)
|
||||
y_offset = 1
|
||||
if(!z_offset)
|
||||
z_offset = world.maxz + 1
|
||||
|
||||
var/quote = ascii2text(34)
|
||||
var/tfile = file2text(dmm_file)//the map file we're creating
|
||||
var/tfile_len = length(tfile)
|
||||
var/lpos = 1 // the models definition index
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//first let's map model keys (e.g "aa") to their contents (e.g /turf/space{variables})
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF)
|
||||
var/list/grid_models = list()
|
||||
var/key_len = length(copytext(tfile,2,findtext(tfile,quote,2,0)))//the length of the model key (e.g "aa" or "aba")
|
||||
var/key_len = 0
|
||||
|
||||
//proceed line by line
|
||||
for(lpos=1; lpos<tfile_len; lpos=findtext(tfile,"\n",lpos,0)+1)
|
||||
var/tline = copytext(tfile,lpos,findtext(tfile,"\n",lpos,0))
|
||||
if(copytext(tline,1,2) != quote)//we reached the map "layout"
|
||||
break
|
||||
var/model_key = copytext(tline,2,2+key_len)
|
||||
var/model_contents = copytext(tline,findtext(tfile,"=")+3,length(tline))
|
||||
grid_models[model_key] = model_contents
|
||||
if(do_sleep)
|
||||
sleep(-1)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
//now let's fill the map with turf and objects using the constructed model map
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//position of the currently processed square
|
||||
var/zcrd=-1
|
||||
var/ycrd=y_offset
|
||||
var/xcrd=x_offset
|
||||
var/dmm_suite/loaded_map/LM = new
|
||||
// This try-catch is used as a budget "Finally" clause, as the dirt count
|
||||
// needs to be reset
|
||||
var/watch = start_watch()
|
||||
log_debug("[measureOnly ? "Measuring" : "Loading"] map: [fname]")
|
||||
try
|
||||
LM.index = 1
|
||||
while(dmmRegex.Find(tfile, LM.index))
|
||||
LM.index = dmmRegex.next
|
||||
|
||||
for(var/zpos=findtext(tfile,"\n(1,1,",lpos,0);zpos!=0;zpos=findtext(tfile,"\n(1,1,",zpos+1,0)) //in case there's several maps to load
|
||||
// "aa" = (/type{vars=blah})
|
||||
if(dmmRegex.group[1]) // Model
|
||||
var/key = dmmRegex.group[1]
|
||||
if(grid_models[key]) // Duplicate model keys are ignored in DMMs
|
||||
continue
|
||||
if(key_len != length(key))
|
||||
if(!key_len)
|
||||
key_len = length(key)
|
||||
else
|
||||
throw EXCEPTION("Inconsistant key length in DMM")
|
||||
if(!measureOnly)
|
||||
grid_models[key] = dmmRegex.group[2]
|
||||
|
||||
zcrd++
|
||||
world.maxz = max(world.maxz, zcrd+z_offset)//create a new z_level if needed
|
||||
// (1,1,1) = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
|
||||
else if(dmmRegex.group[3]) // Coords
|
||||
if(!key_len)
|
||||
throw EXCEPTION("Coords before model definition in DMM")
|
||||
|
||||
var/zgrid = copytext(tfile,findtext(tfile,quote+"\n",zpos,0)+2,findtext(tfile,"\n"+quote,zpos,0)+1) //copy the whole map grid
|
||||
var/z_depth = length(zgrid)
|
||||
var/xcrdStart = text2num(dmmRegex.group[3]) + x_offset - 1
|
||||
//position of the currently processed square
|
||||
var/xcrd
|
||||
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
|
||||
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
|
||||
|
||||
//if exceeding the world max x or y, increase it
|
||||
var/x_depth = length(copytext(zgrid,1,findtext(zgrid,"\n",2,0)))
|
||||
var/x_tilecount = x_depth/key_len
|
||||
if(world.maxx<x_tilecount)
|
||||
world.maxx=x_tilecount
|
||||
if(!measureOnly)
|
||||
if(zcrd > world.maxz)
|
||||
if(cropMap)
|
||||
continue
|
||||
else
|
||||
zlevels.increase_max_zlevel_to(zcrd) //create a new z_level if needed
|
||||
|
||||
var/y_depth = z_depth / (x_depth+1)//x_depth + 1 because we're counting the '\n' characters in z_depth
|
||||
if(world.maxy<y_depth)
|
||||
world.maxy=y_depth
|
||||
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
|
||||
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
|
||||
bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], zcrd)
|
||||
|
||||
//then proceed it line by line, starting from top
|
||||
ycrd = y_depth
|
||||
var/list/gridLines = splittext(dmmRegex.group[6], "\n")
|
||||
|
||||
for(var/gpos=1;gpos!=0;gpos=findtext(zgrid,"\n",gpos,0)+1)
|
||||
var/grid_line = copytext(zgrid,gpos,findtext(zgrid,"\n",gpos,0))
|
||||
var/leadingBlanks = 0
|
||||
while(leadingBlanks < gridLines.len && gridLines[++leadingBlanks] == "")
|
||||
if(leadingBlanks > 1)
|
||||
gridLines.Cut(1, leadingBlanks) // Remove all leading blank lines.
|
||||
|
||||
//fill the current square using the model map
|
||||
xcrd=0
|
||||
if(!gridLines.len) // Skip it if only blank lines exist.
|
||||
continue
|
||||
|
||||
for(var/mpos in 1 to x_depth step key_len)
|
||||
xcrd++
|
||||
var/model_key = copytext(grid_line,mpos,mpos+key_len)
|
||||
parse_grid(grid_models[model_key], xcrd + x_offset, ycrd + y_offset, zcrd + z_offset, do_sleep)
|
||||
if(gridLines.len && gridLines[gridLines.len] == "")
|
||||
gridLines.Cut(gridLines.len) // Remove only one blank line at the end.
|
||||
|
||||
//reached end of current map
|
||||
if(gpos+x_depth+1>z_depth)
|
||||
break
|
||||
bounds[MAP_MINY] = min(bounds[MAP_MINY], ycrd)
|
||||
ycrd += gridLines.len - 1 // Start at the top and work down
|
||||
|
||||
ycrd--
|
||||
if(do_sleep)
|
||||
sleep(-1)
|
||||
if(!cropMap && ycrd > world.maxy)
|
||||
if(!measureOnly)
|
||||
world.maxy = ycrd // Expand Y here. X is expanded in the loop below
|
||||
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], ycrd)
|
||||
else
|
||||
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], min(ycrd, world.maxy))
|
||||
|
||||
//reached End Of File
|
||||
if(findtext(tfile,quote+"}",zpos,0)+2==tfile_len)
|
||||
break
|
||||
if(do_sleep)
|
||||
sleep(-1)
|
||||
var/maxx = xcrdStart
|
||||
if(measureOnly)
|
||||
for(var/line in gridLines)
|
||||
maxx = max(maxx, xcrdStart + length(line) / key_len - 1)
|
||||
else
|
||||
for(var/line in gridLines)
|
||||
if(ycrd <= world.maxy && ycrd >= 1)
|
||||
xcrd = xcrdStart
|
||||
for(var/tpos = 1 to length(line) - key_len + 1 step key_len)
|
||||
if(xcrd > world.maxx)
|
||||
if(cropMap)
|
||||
break
|
||||
else
|
||||
world.maxx = xcrd
|
||||
|
||||
if(xcrd >= 1)
|
||||
var/model_key = copytext(line, tpos, tpos + key_len)
|
||||
if(!grid_models[model_key])
|
||||
throw EXCEPTION("Undefined model key in DMM: [model_key]. Map file: [fname].")
|
||||
parse_grid(grid_models[model_key], xcrd, ycrd, zcrd, LM)
|
||||
// After this call, it is NOT safe to reference `dmmRegex` without another call to
|
||||
// "Find" - we might've hit a map loader here and changed its state
|
||||
CHECK_TICK
|
||||
|
||||
maxx = max(maxx, xcrd)
|
||||
++xcrd
|
||||
--ycrd
|
||||
|
||||
bounds[MAP_MAXX] = max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx)
|
||||
|
||||
CHECK_TICK
|
||||
catch(var/exception/e)
|
||||
_preloader.reset()
|
||||
throw e
|
||||
|
||||
_preloader.reset()
|
||||
log_debug("Loaded map in [stop_watch(watch)]s.")
|
||||
qdel(LM)
|
||||
if(bounds[MAP_MINX] == 1.#INF) // Shouldn't need to check every item
|
||||
log_debug("Min x: bounds[MAP_MINX]")
|
||||
log_debug("Min y: bounds[MAP_MINY]")
|
||||
log_debug("Min z: bounds[MAP_MINZ]")
|
||||
log_debug("Max x: bounds[MAP_MAXX]")
|
||||
log_debug("Max y: bounds[MAP_MAXY]")
|
||||
log_debug("Max z: bounds[MAP_MAXZ]")
|
||||
return null
|
||||
else
|
||||
if(!measureOnly)
|
||||
for(var/t in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
|
||||
var/turf/T = t
|
||||
//we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
|
||||
T.AfterChange(1,keep_cabling = TRUE)
|
||||
return bounds
|
||||
|
||||
/**
|
||||
* Fill a given tile with its area/turf/objects/mobs
|
||||
@@ -115,48 +196,60 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
* 4) Instanciates the atom with its variables
|
||||
*
|
||||
*/
|
||||
/dmm_suite/proc/parse_grid(model as text, xcrd as num, ycrd as num, zcrd as num, do_sleep = 1)
|
||||
/dmm_suite/proc/parse_grid(model as text,xcrd as num,ycrd as num,zcrd as num, dmm_suite/loaded_map/LM)
|
||||
/*Method parse_grid()
|
||||
- Accepts a text string containing a comma separated list of type paths of the
|
||||
same construction as those contained in a .dmm file, and instantiates them.
|
||||
*/
|
||||
|
||||
var/list/members = list()//will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/explored)
|
||||
var/list/members_attributes = list()//will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
var/list/members //will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/explored)
|
||||
var/list/members_attributes //will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
|
||||
var/list/cached = modelCache[model]
|
||||
var/index
|
||||
|
||||
if(cached)
|
||||
members = cached[1]
|
||||
members_attributes = cached[2]
|
||||
else
|
||||
/////////////////////////////////////////////////////////
|
||||
//Constructing members and corresponding variables lists
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//Constructing members and corresponding variables lists
|
||||
////////////////////////////////////////////////////////
|
||||
members = list()
|
||||
members_attributes = list()
|
||||
index = 1
|
||||
|
||||
var/index=1
|
||||
var/old_position = 1
|
||||
var/dpos
|
||||
var/old_position = 1
|
||||
var/dpos
|
||||
|
||||
do
|
||||
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/explored)
|
||||
dpos= find_next_delimiter_position(model,old_position,",","{","}")//find next delimiter (comma here) that's not within {...}
|
||||
do
|
||||
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/explored)
|
||||
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") //find next delimiter (comma here) that's not within {...}
|
||||
|
||||
var/full_def = copytext(model,old_position,dpos)//full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/atom_def = text2path(copytext(full_def,1,findtext(full_def,"{")))//path definition, e.g /obj/foo/bar
|
||||
members.Add(atom_def)
|
||||
old_position = dpos + 1
|
||||
var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
|
||||
var/variables_start = findtext(full_def, "{")
|
||||
var/atom_def = text2path(trim_text(copytext(full_def, 1, variables_start))) //path definition, e.g /obj/foo/bar
|
||||
old_position = dpos + 1
|
||||
|
||||
//transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
var/list/fields = list()
|
||||
if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers!
|
||||
continue
|
||||
members.Add(atom_def)
|
||||
|
||||
var/variables_start = findtext(full_def,"{")
|
||||
if(variables_start)//if there's any variable
|
||||
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
|
||||
fields = readlist(full_def, ";")
|
||||
//transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
|
||||
var/list/fields = list()
|
||||
|
||||
//then fill the members_attributes list with the corresponding variables
|
||||
members_attributes.len++
|
||||
members_attributes[index++] = fields
|
||||
if(variables_start)//if there's any variable
|
||||
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
|
||||
fields = readlist(full_def, ";")
|
||||
|
||||
if(do_sleep)
|
||||
sleep(-1)
|
||||
while(dpos != 0)
|
||||
//then fill the members_attributes list with the corresponding variables
|
||||
members_attributes.len++
|
||||
members_attributes[index++] = fields
|
||||
|
||||
CHECK_TICK
|
||||
while(dpos != 0)
|
||||
|
||||
modelCache[model] = list(members, members_attributes)
|
||||
|
||||
|
||||
////////////////
|
||||
@@ -165,24 +258,25 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
|
||||
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
|
||||
|
||||
//in case of multiples turfs on one tile,
|
||||
//will contains the images of all underlying turfs, to simulate the DMM multiple tiles piling
|
||||
var/list/turfs_underlays = list()
|
||||
|
||||
//first instance the /area and remove it from the members list
|
||||
index = members.len
|
||||
|
||||
var/turf/crds = locate(xcrd,ycrd,zcrd)
|
||||
if(members[index] != /area/template_noop)
|
||||
// We assume `members[index]` is an area path, as above, yes? I will operate
|
||||
// on that assumption.
|
||||
if(!ispath(members[index], /area))
|
||||
throw EXCEPTION("Oh no, I thought this was an area!")
|
||||
|
||||
var/atom/instance
|
||||
_preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
|
||||
instance = LM.area_path_to_real_area(members[index])
|
||||
|
||||
instance = locate(members[index])
|
||||
var/turf/crds = locate(xcrd,ycrd,zcrd)
|
||||
if(crds)
|
||||
instance.contents.Add(crds)
|
||||
|
||||
if(use_preloader && instance)
|
||||
_preloader.load(instance)
|
||||
members.Remove(members[index])
|
||||
|
||||
//then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect
|
||||
|
||||
@@ -198,18 +292,20 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
if(T)
|
||||
//if others /turf are presents, simulates the underlays piling effect
|
||||
index = first_turf_index + 1
|
||||
while(index <= members.len)
|
||||
turfs_underlays.Insert(1,image(T.icon,null,T.icon_state,T.layer,T.dir))//add the current turf image to the underlays list
|
||||
var/turf/UT = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf
|
||||
add_underlying_turf(UT,T,turfs_underlays)//simulates the DMM piling effect
|
||||
T = UT
|
||||
while(index <= members.len - 1) // Last item is an /area
|
||||
var/underlay
|
||||
if(istype(T, /turf)) // I blame this on the stupid clown who coded the BYOND map editor
|
||||
underlay = T.appearance
|
||||
T = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf
|
||||
if(ispath(members[index],/turf))
|
||||
T.underlays += underlay
|
||||
|
||||
index++
|
||||
|
||||
//finally instance all remainings objects/mobs
|
||||
for(index in 1 to first_turf_index - 1)
|
||||
for(index in 1 to first_turf_index-1)
|
||||
instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)
|
||||
if(do_sleep)
|
||||
sleep(-1)
|
||||
CHECK_TICK
|
||||
|
||||
////////////////
|
||||
//Helpers procs
|
||||
@@ -222,7 +318,13 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
|
||||
var/turf/T = locate(x,y,z)
|
||||
if(T)
|
||||
instance = new path (T)//first preloader pass
|
||||
if(ispath(path, /turf))
|
||||
T.ChangeTurf(path, 1, 0)
|
||||
instance = T
|
||||
else if(ispath(path, /area))
|
||||
|
||||
else
|
||||
instance = new path (T)//first preloader pass
|
||||
|
||||
if(use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New()
|
||||
_preloader.load(instance)
|
||||
@@ -232,16 +334,11 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
//text trimming (both directions) helper proc
|
||||
//optionally removes quotes before and after the text (for variable name)
|
||||
/dmm_suite/proc/trim_text(what as text,trim_quotes=0)
|
||||
while(length(what) && (findtext(what," ",1,2)))
|
||||
what=copytext(what,2,0)
|
||||
while(length(what) && (findtext(what," ",length(what),0)))
|
||||
what=copytext(what,1,length(what))
|
||||
if(trim_quotes)
|
||||
while(length(what) && (findtext(what,quote,1,2)))
|
||||
what=copytext(what,2,0)
|
||||
while(length(what) && (findtext(what,quote,length(what),0)))
|
||||
what=copytext(what,1,length(what))
|
||||
return what
|
||||
return trimQuotesRegex.Replace(what, "")
|
||||
else
|
||||
return trimRegex.Replace(what, "")
|
||||
|
||||
|
||||
//find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape
|
||||
//returns 0 if reached the last delimiter
|
||||
@@ -313,14 +410,6 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
|
||||
return to_return
|
||||
|
||||
//simulates the DM multiple turfs on one tile underlaying
|
||||
/dmm_suite/proc/add_underlying_turf(turf/placed,turf/underturf, list/turfs_underlays)
|
||||
if(underturf.density)
|
||||
placed.density = 1
|
||||
if(underturf.opacity)
|
||||
placed.opacity = 1
|
||||
placed.underlays += turfs_underlays
|
||||
|
||||
//atom creation method that preloads variables at creation
|
||||
/atom/New()
|
||||
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
|
||||
@@ -336,6 +425,7 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
//Preloader datum
|
||||
//////////////////
|
||||
|
||||
// This ain't re-entrant, but we had this before the maploader update
|
||||
/dmm_suite/preloader
|
||||
parent_type = /datum
|
||||
var/list/attributes
|
||||
@@ -349,11 +439,41 @@ var/global/dmm_suite/preloader/_preloader = new
|
||||
|
||||
/dmm_suite/preloader/proc/load(atom/what)
|
||||
for(var/attribute in attributes)
|
||||
what.vars[attribute] = attributes[attribute]
|
||||
var/value = attributes[attribute]
|
||||
if(islist(value))
|
||||
value = deepCopyList(value)
|
||||
what.vars[attribute] = value
|
||||
use_preloader = FALSE
|
||||
|
||||
// If the map loader fails, make this safe
|
||||
/dmm_suite/preloader/proc/reset()
|
||||
use_preloader = FALSE
|
||||
attributes = list()
|
||||
target_path = null
|
||||
|
||||
// A datum for use within the context of loading a single map,
|
||||
// so that one can have separate "unpowered" areas for ruins or whatever,
|
||||
// yet have a single area type for use of mapping, instead of creating
|
||||
// a new area type for each new ruin
|
||||
/dmm_suite/loaded_map
|
||||
parent_type = /datum
|
||||
var/list/area_list = list()
|
||||
var/index = 1 // To store the state of the regex
|
||||
|
||||
/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
|
||||
if(!ispath(A, /area))
|
||||
throw EXCEPTION("Wrong argument to `area_path_to_real_area`")
|
||||
|
||||
if(!(A in area_list))
|
||||
if(initial(A.there_can_be_many))
|
||||
area_list[A] = new A
|
||||
else
|
||||
area_list[A] = locate(A)
|
||||
|
||||
return area_list[A]
|
||||
|
||||
/area/template_noop
|
||||
name = "Area Passthrough"
|
||||
|
||||
/turf/template_noop
|
||||
name = "Turf Passthrough"
|
||||
name = "Turf Passthrough"
|
||||
|
||||
@@ -326,7 +326,7 @@ swapmap
|
||||
x2+=x1-1
|
||||
y2+=y1-1
|
||||
z2+=z1-1
|
||||
world.maxz=max(z2,world.maxz) // stretch z if necessary
|
||||
zlevels.increase_max_zlevel_to(z2) // stretch z if necessary
|
||||
if(!ischunk)
|
||||
swapmaps_loaded[src]=null
|
||||
swapmaps_byname[id]=src
|
||||
@@ -373,7 +373,7 @@ swapmap
|
||||
mz=max(mz,M.z2)
|
||||
world.maxx=mx
|
||||
world.maxy=my
|
||||
world.maxz=mz
|
||||
zlevels.cut_levels_downto(mz)
|
||||
|
||||
// save and delete
|
||||
proc/Unload()
|
||||
|
||||
@@ -54,9 +54,8 @@
|
||||
name = "space hotel pamphlet"
|
||||
info = "<h3>Welcome to Deep Space Hotel 419!</h3>Thank you for choosing our hotel. Simply hand your credit or debit card to the concierge and get your room key! To check out, hand your credit card back.<small><h4>Conditions:</h4><ul><li>The hotel is not responsible for any losses due to time or space anomalies.<li>The hotel is not responsible for events that occur outside of the hotel station, including, but not limited to, events that occur inside of dimensional pockets.<li>The hotel is not responsible for overcharging your account.<li>The hotel is not responsible for missing persons.<li>The hotel is not responsible for mind-altering effects due to drugs, magic, demons, or space worms.</ul></small>"
|
||||
|
||||
/obj/effect/landmark/map_loader/hotel_room/New()
|
||||
/obj/effect/landmark/map_loader/hotel_room/initialize()
|
||||
..()
|
||||
|
||||
// load and randomly assign rooms
|
||||
var/global/list/south_room_templates = list()
|
||||
var/global/list/north_room_templates = list()
|
||||
@@ -65,26 +64,27 @@
|
||||
if(!loaded)
|
||||
loaded = 1
|
||||
for(var/map in flist(path))
|
||||
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
|
||||
if(copytext(map, 1, 3) == "n_")
|
||||
north_room_templates += T
|
||||
else if(copytext(map, 1, 3) == "s_")
|
||||
south_room_templates += T
|
||||
else
|
||||
// omnidirectional rooms are randomly assigned
|
||||
if(prob(50))
|
||||
if(cmptext(copytext(map, length(map) - 3), ".dmm"))
|
||||
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
|
||||
if(copytext(map, 1, 3) == "n_")
|
||||
north_room_templates += T
|
||||
else
|
||||
else if(copytext(map, 1, 3) == "s_")
|
||||
south_room_templates += T
|
||||
else
|
||||
// omnidirectional rooms are randomly assigned
|
||||
if(prob(50))
|
||||
north_room_templates += T
|
||||
else
|
||||
south_room_templates += T
|
||||
|
||||
var/datum/map_template/M = safepick(dir == NORTH ? north_room_templates : south_room_templates)
|
||||
if(M)
|
||||
template = M
|
||||
load(M)
|
||||
if(dir == NORTH)
|
||||
north_room_templates -= M
|
||||
else
|
||||
south_room_templates -= M
|
||||
load(M)
|
||||
|
||||
// The door to a hotel room, but also metadata for the room itself
|
||||
/obj/machinery/door/unpowered/hotel_door
|
||||
@@ -305,4 +305,4 @@
|
||||
S.retal_target = target
|
||||
S.retal = 1
|
||||
|
||||
#undef CHECKOUT_TIME
|
||||
#undef CHECKOUT_TIME
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away_mission_config.txt")
|
||||
|
||||
// Call this before you remove the last dirt on a z level - that way, all objects
|
||||
// will have proper atmos and other important enviro things
|
||||
/proc/late_setup_level(turfs, smoothTurfs)
|
||||
var/total_timer = start_watch()
|
||||
var/subtimer = start_watch()
|
||||
if(!smoothTurfs)
|
||||
smoothTurfs = turfs
|
||||
|
||||
log_debug("Setting up atmos")
|
||||
if(air_master)
|
||||
air_master.setup_allturfs(turfs)
|
||||
log_debug("\tTook [stop_watch(subtimer)]s")
|
||||
|
||||
subtimer = start_watch()
|
||||
log_debug("Initializing lighting")
|
||||
for(var/turf/T in turfs)
|
||||
if(T.dynamic_lighting)
|
||||
T.lighting_build_overlays()
|
||||
for(var/obj/structure/cable/PC in T)
|
||||
makepowernet_for(PC)
|
||||
log_debug("\tTook [stop_watch(subtimer)]s")
|
||||
|
||||
subtimer = start_watch()
|
||||
log_debug("Smoothing tiles")
|
||||
for(var/turf/T in smoothTurfs)
|
||||
if(T.smooth)
|
||||
smooth_icon(T)
|
||||
@@ -16,20 +29,95 @@
|
||||
var/atom/A = R
|
||||
if(A.smooth)
|
||||
smooth_icon(A)
|
||||
if(istype(T, /turf/simulated/mineral)) // For the listening post, among other maps
|
||||
var/turf/simulated/mineral/MT = T
|
||||
MT.add_edges()
|
||||
log_debug("\tTook [stop_watch(subtimer)]s")
|
||||
log_debug("Late setup finished - took [stop_watch(total_timer)]s")
|
||||
|
||||
/proc/empty_rect(low_x,low_y, hi_x,hi_y, z)
|
||||
var/timer = start_watch()
|
||||
log_debug("Emptying region: ([low_x], [low_y]) to ([hi_x], [hi_y]) on z '[z]'")
|
||||
empty_region(block(locate(low_x, low_y, z), locate(hi_x, hi_y, z)))
|
||||
log_debug("Took [stop_watch(timer)]s")
|
||||
|
||||
/proc/empty_region(list/turfs)
|
||||
for(var/thing in turfs)
|
||||
var/turf/T = thing
|
||||
for(var/otherthing in T)
|
||||
qdel(otherthing)
|
||||
T.ChangeTurf(/turf/space)
|
||||
|
||||
/proc/createRandomZlevel()
|
||||
if(awaydestinations.len) //crude, but it saves another var!
|
||||
return
|
||||
|
||||
var/list/potentialRandomZlevels = list()
|
||||
log_startup_progress("Searching for away missions...")
|
||||
var/list/Lines
|
||||
if(fexists("config/away_mission_config.txt"))
|
||||
Lines = file2list("config/away_mission_config.txt")
|
||||
else
|
||||
Lines = file2list("config/example/away_mission_config.txt")
|
||||
if(potentialRandomZlevels && potentialRandomZlevels.len)
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Loading away mission...")
|
||||
|
||||
if(!Lines.len) return
|
||||
var/map = pick(potentialRandomZlevels)
|
||||
var/file = file(map)
|
||||
if(isfile(file))
|
||||
var/zlev = zlevels.add_new_zlevel()
|
||||
zlevels.add_dirt(zlev)
|
||||
maploader.load_map(file, z_offset = zlev)
|
||||
late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev)))
|
||||
zlevels.remove_dirt(zlev)
|
||||
log_to_dd(" Away mission loaded: [map]")
|
||||
|
||||
//map_transition_config.Add(AWAY_MISSION_LIST)
|
||||
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name != "awaystart")
|
||||
continue
|
||||
awaydestinations.Add(L)
|
||||
|
||||
log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.")
|
||||
|
||||
else
|
||||
log_startup_progress(" No away missions found.")
|
||||
return
|
||||
|
||||
/proc/createALLZlevels()
|
||||
if(awaydestinations.len) //crude, but it saves another var!
|
||||
return
|
||||
|
||||
if(potentialRandomZlevels && potentialRandomZlevels.len)
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Loading away missions...")
|
||||
|
||||
for(var/map in potentialRandomZlevels)
|
||||
var/file = file(map)
|
||||
if(isfile(file))
|
||||
log_startup_progress("Loading away mission: [map]")
|
||||
var/zlev = zlevels.add_new_zlevel()
|
||||
zlevels.add_dirt(zlev)
|
||||
maploader.load_map(file, z_offset = zlev)
|
||||
late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev)))
|
||||
zlevels.remove_dirt(zlev)
|
||||
log_to_dd(" Away mission loaded: [map]")
|
||||
|
||||
//map_transition_config.Add(AWAY_MISSION_LIST)
|
||||
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name != "awaystart")
|
||||
continue
|
||||
awaydestinations.Add(L)
|
||||
|
||||
log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.")
|
||||
watch = start_watch()
|
||||
|
||||
else
|
||||
log_startup_progress(" No away missions found.")
|
||||
return
|
||||
|
||||
/proc/generateMapList(filename)
|
||||
var/list/potentialMaps = list()
|
||||
var/list/Lines = file2list(filename)
|
||||
|
||||
if(!Lines.len)
|
||||
return
|
||||
for(var/t in Lines)
|
||||
if(!t)
|
||||
continue
|
||||
@@ -42,38 +130,87 @@
|
||||
|
||||
var/pos = findtext(t, " ")
|
||||
var/name = null
|
||||
// var/value = null
|
||||
|
||||
if(pos)
|
||||
name = lowertext(copytext(t, 1, pos))
|
||||
// value = copytext(t, pos + 1)
|
||||
|
||||
else
|
||||
name = lowertext(t)
|
||||
|
||||
if(!name)
|
||||
continue
|
||||
|
||||
potentialRandomZlevels.Add(t)
|
||||
potentialMaps.Add(t)
|
||||
|
||||
return potentialMaps
|
||||
|
||||
|
||||
if(potentialRandomZlevels.len)
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Loading away mission...")
|
||||
/proc/seedRuins(z_level = 1, budget = 0, whitelist = /area/space, list/potentialRuins = space_ruins_templates)
|
||||
var/overall_sanity = 100
|
||||
var/ruins = potentialRuins.Copy()
|
||||
var/initialbudget = budget
|
||||
var/watch = start_watch()
|
||||
|
||||
var/map = pick(potentialRandomZlevels)
|
||||
var/file = file(map)
|
||||
if(isfile(file))
|
||||
maploader.load_map(file, do_sleep = 0)
|
||||
late_setup_level(block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz)))
|
||||
log_to_dd(" Away mission loaded: [map]")
|
||||
log_startup_progress("Loading ruins...")
|
||||
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name != "awaystart")
|
||||
while(budget > 0 && overall_sanity > 0)
|
||||
// Pick a ruin
|
||||
var/datum/map_template/ruin/ruin = ruins[pick(ruins)]
|
||||
// Can we afford it
|
||||
if(ruin.cost > budget)
|
||||
overall_sanity--
|
||||
continue
|
||||
// If so, try to place it
|
||||
var/sanity = 100
|
||||
// And if we can't fit it anywhere, give up, try again
|
||||
|
||||
while(sanity > 0)
|
||||
sanity--
|
||||
var/turf/T = locate(rand(25, world.maxx - 25), rand(25, world.maxy - 25), z_level)
|
||||
var/valid = 1
|
||||
|
||||
for(var/turf/check in ruin.get_affected_turfs(T,1))
|
||||
var/area/new_area = get_area(check)
|
||||
if(!(istype(new_area, whitelist)))
|
||||
valid = 0
|
||||
break
|
||||
|
||||
if(!valid)
|
||||
continue
|
||||
awaydestinations.Add(L)
|
||||
|
||||
log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.")
|
||||
log_to_dd(" Ruin \"[ruin.name]\" loaded in [stop_watch(watch)]s at ([T.x], [T.y], [T.z]).")
|
||||
|
||||
else
|
||||
log_startup_progress(" No away missions found.")
|
||||
return
|
||||
var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T)
|
||||
R.Load(ruins,ruin)
|
||||
budget -= ruin.cost
|
||||
if(!ruin.allow_duplicates)
|
||||
ruins -= ruin.name
|
||||
break
|
||||
|
||||
to_chat(world, "<span class='danger'> Loaded ruins. Or not.</span>") //So the players don't know if we loaded ruins, but we do have a message
|
||||
|
||||
if(initialbudget == budget) //Kill me
|
||||
log_to_dd(" No ruins loaded.")
|
||||
|
||||
|
||||
/obj/effect/ruin_loader
|
||||
name = "random ruin"
|
||||
desc = "If you got lucky enough to see this..."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "syndballoon"
|
||||
invisibility = 0
|
||||
|
||||
/obj/effect/ruin_loader/proc/Load(list/potentialRuins = space_ruins_templates, datum/map_template/template = null)
|
||||
var/list/possible_ruins = list()
|
||||
for(var/A in potentialRuins)
|
||||
var/datum/map_template/T = potentialRuins[A]
|
||||
if(!T.loaded)
|
||||
possible_ruins += T
|
||||
if(!template && possible_ruins.len)
|
||||
template = safepick(possible_ruins)
|
||||
if(!template)
|
||||
return 0
|
||||
template.load(get_turf(src),centered = 1)
|
||||
template.loaded++
|
||||
qdel(src)
|
||||
return 1
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
/obj/effect/levelref/New()
|
||||
..()
|
||||
levels += src
|
||||
|
||||
/obj/effect/levelref/initialize()
|
||||
..()
|
||||
for(var/obj/effect/levelref/O in levels)
|
||||
if(id == O.id && O != src)
|
||||
other = O
|
||||
@@ -104,7 +107,7 @@
|
||||
/turf/unsimulated/floor/upperlevel/New()
|
||||
..()
|
||||
var/obj/effect/levelref/R = locate() in get_area(src)
|
||||
if(R)
|
||||
if(R && R.other)
|
||||
init(R)
|
||||
|
||||
/turf/unsimulated/floor/upperlevel/Destroy()
|
||||
@@ -159,6 +162,8 @@
|
||||
..()
|
||||
portals += src
|
||||
|
||||
/obj/effect/view_portal/initialize()
|
||||
..()
|
||||
if(id)
|
||||
for(var/obj/effect/view_portal/O in portals)
|
||||
if(id == O.id && O != src && can_link(O))
|
||||
@@ -361,4 +366,4 @@
|
||||
screen_loc = "CENTER[ox >= 0 ? "+" : ""][ox],CENTER[oy >= 0 ? "+" : ""][oy]"
|
||||
|
||||
/obj/effect/view_portal_dummy/attack_ghost(mob/user)
|
||||
owner.attack_ghost(user)
|
||||
owner.attack_ghost(user)
|
||||
|
||||
@@ -260,3 +260,18 @@ proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
|
||||
|
||||
send_asset_list(client, uncommon)
|
||||
send_asset_list(client, common)
|
||||
|
||||
/datum/asset/chem_master
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/chem_master/register()
|
||||
for(var/i = 1 to 20)
|
||||
assets["pill[i].png"] = icon('icons/obj/chemical.dmi', "pill[i]")
|
||||
for(var/i = 1 to 20)
|
||||
assets["bottle[i].png"] = icon('icons/obj/chemical.dmi', "bottle[i]")
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
|
||||
/datum/asset/chem_master/send(client)
|
||||
send_asset_list(client,assets,verify)
|
||||
@@ -61,4 +61,35 @@
|
||||
|
||||
/datum/gear/accessory/scarf/stripedblue
|
||||
display_name = "scarf, striped blue"
|
||||
path = /obj/item/clothing/accessory/stripedbluescarf
|
||||
path = /obj/item/clothing/accessory/stripedbluescarf
|
||||
|
||||
/datum/gear/accessory/holobadge
|
||||
display_name = "holobadge, pin"
|
||||
path = /obj/item/clothing/accessory/holobadge
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/accessory/holobadge_n
|
||||
display_name = "holobadge, cord"
|
||||
path = /obj/item/clothing/accessory/holobadge/cord
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/accessory/tieblue
|
||||
display_name = "tie, blue"
|
||||
path = /obj/item/clothing/accessory/blue
|
||||
|
||||
/datum/gear/accessory/tiered
|
||||
display_name = "tie, red"
|
||||
path = /obj/item/clothing/accessory/red
|
||||
|
||||
/datum/gear/accessory/tieblack
|
||||
display_name = "tie, black"
|
||||
path = /obj/item/clothing/accessory/black
|
||||
|
||||
/datum/gear/accessory/tiehorrible
|
||||
display_name = "tie, vomit green"
|
||||
path = /obj/item/clothing/accessory/horrible
|
||||
|
||||
/datum/gear/accessory/stethoscope
|
||||
display_name = "stethoscope"
|
||||
path = /obj/item/clothing/accessory/stethoscope
|
||||
allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Paramedic", "Brig Physician")
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
/datum/gear/dice
|
||||
display_name = "d20"
|
||||
path = /obj/item/weapon/dice/d20
|
||||
display_name = "a d20"
|
||||
path = /obj/item/weapon/dice/d20
|
||||
|
||||
/datum/gear/uplift
|
||||
display_name = "a pack of Uplifts"
|
||||
path = /obj/item/weapon/storage/fancy/cigarettes/cigpack_uplift
|
||||
|
||||
/datum/gear/robust
|
||||
display_name = "a pack of Robusts"
|
||||
path = /obj/item/weapon/storage/fancy/cigarettes/cigpack_robust
|
||||
|
||||
/datum/gear/carp
|
||||
display_name = "a pack of Carps"
|
||||
path = /obj/item/weapon/storage/fancy/cigarettes/cigpack_carp
|
||||
|
||||
/datum/gear/midori
|
||||
display_name = "a pack of Midoris"
|
||||
path = /obj/item/weapon/storage/fancy/cigarettes/cigpack_midori
|
||||
|
||||
/datum/gear/lighter
|
||||
display_name = "a cheap lighter"
|
||||
path = /obj/item/weapon/lighter
|
||||
|
||||
/datum/gear/rock
|
||||
display_name = "a pet rock"
|
||||
path = /obj/item/toy/pet_rock
|
||||
|
||||
/datum/gear/sechud
|
||||
display_name = "a classic security HUD"
|
||||
path = /obj/item/clothing/glasses/hud/security
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/matches
|
||||
display_name = "a box of matches"
|
||||
path = /obj/item/weapon/storage/box/matches
|
||||
|
||||
/datum/gear/cards
|
||||
display_name = "a deck of cards"
|
||||
path = /obj/item/toy/cards/deck
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/datum/gear/hat
|
||||
subtype_path = /datum/gear/hat
|
||||
slot = slot_head
|
||||
sort_category = "Headwear"
|
||||
|
||||
/datum/gear/hat/hhat_yellow
|
||||
display_name = "hardhat, yellow"
|
||||
path = /obj/item/clothing/head/hardhat
|
||||
allowed_roles = list("Chief Engineer", "Engineer", "Mechanic", "Life Support Specialist")
|
||||
|
||||
/datum/gear/hat/hhat_orange
|
||||
display_name = "hardhat, orange"
|
||||
path = /obj/item/clothing/head/hardhat/orange
|
||||
allowed_roles = list("Chief Engineer", "Engineer", "Mechanic", "Life Support Specialist")
|
||||
|
||||
/datum/gear/hat/hhat_blue
|
||||
display_name = "hardhat, blue"
|
||||
path = /obj/item/clothing/head/hardhat/dblue
|
||||
allowed_roles = list("Chief Engineer", "Engineer", "Mechanic", "Life Support Specialist")
|
||||
|
||||
/datum/gear/hat/that
|
||||
display_name = "top hat"
|
||||
path = /obj/item/clothing/head/that
|
||||
|
||||
/datum/gear/hat/flatcap
|
||||
display_name = "flat cap"
|
||||
path = /obj/item/clothing/head/flatcap
|
||||
|
||||
/datum/gear/hat/fez
|
||||
display_name = "fez"
|
||||
path = /obj/item/clothing/head/fez
|
||||
|
||||
/datum/gear/hat/bfedora
|
||||
display_name = "fedora, black"
|
||||
path = /obj/item/clothing/head/fedora
|
||||
|
||||
/datum/gear/hat/wfedora
|
||||
display_name = "fedora, white"
|
||||
path = /obj/item/clothing/head/fedora/whitefedora
|
||||
|
||||
/datum/gear/hat/brfedora
|
||||
display_name = "fedora, brown"
|
||||
path = /obj/item/clothing/head/fedora/brownfedora
|
||||
|
||||
/datum/gear/hat/beretsec
|
||||
display_name = "security beret"
|
||||
path = /obj/item/clothing/head/beret/sec
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/hat/capcsec
|
||||
display_name = "security corporate cap"
|
||||
path = /obj/item/clothing/head/soft/sec/corp
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/hat/capsec
|
||||
display_name = "security cap"
|
||||
path = /obj/item/clothing/head/soft/sec
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/hat/capred
|
||||
display_name = "cap, red"
|
||||
path = /obj/item/clothing/head/soft/red
|
||||
|
||||
/datum/gear/hat/capblue
|
||||
display_name = "cap, blue"
|
||||
path = /obj/item/clothing/head/soft/blue
|
||||
|
||||
/datum/gear/hat/capgreen
|
||||
display_name = "cap, green"
|
||||
path = /obj/item/clothing/head/soft/green
|
||||
|
||||
/datum/gear/hat/capblack
|
||||
display_name = "cap, black"
|
||||
path = /obj/item/clothing/head/soft/black
|
||||
|
||||
/datum/gear/hat/cappurple
|
||||
display_name = "cap, purple"
|
||||
path = /obj/item/clothing/head/soft/purple
|
||||
|
||||
/datum/gear/hat/capwhite
|
||||
display_name = "cap, white"
|
||||
path = /obj/item/clothing/head/soft/mime
|
||||
|
||||
/datum/gear/hat/caporange
|
||||
display_name = "cap, orange"
|
||||
path = /obj/item/clothing/head/soft/orange
|
||||
|
||||
/datum/gear/hat/capgrey
|
||||
display_name = "cap, grey"
|
||||
path = /obj/item/clothing/head/soft/grey
|
||||
|
||||
/datum/gear/hat/capyellow
|
||||
display_name = "cap, yellow"
|
||||
path = /obj/item/clothing/head/soft/yellow
|
||||
|
||||
/datum/gear/hat/cowboyhat
|
||||
display_name = "cowboy hat"
|
||||
path = /obj/item/clothing/head/cowboyhat
|
||||
|
||||
/datum/gear/hat/beret/purple
|
||||
display_name = "beret, purple"
|
||||
path = /obj/item/clothing/head/beret/purple_normal
|
||||
|
||||
/datum/gear/hat/beret/black
|
||||
display_name = "beret, black"
|
||||
path = /obj/item/clothing/head/beret/black
|
||||
|
||||
/datum/gear/hat/beret/blue
|
||||
display_name = "beret, blue"
|
||||
path = /obj/item/clothing/head/beret/blue
|
||||
|
||||
/datum/gear/hat/beret/red
|
||||
display_name = "beret, red"
|
||||
path = /obj/item/clothing/head/beret
|
||||
@@ -0,0 +1,146 @@
|
||||
/datum/gear/suit
|
||||
subtype_path = /datum/gear/suit
|
||||
slot = slot_wear_suit
|
||||
sort_category = "External Wear"
|
||||
|
||||
//WINTER COATS
|
||||
/datum/gear/suit/coat
|
||||
subtype_path = /datum/gear/suit/coat
|
||||
cost = 2
|
||||
|
||||
/datum/gear/suit/coat/grey
|
||||
display_name = "winter coat"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat
|
||||
|
||||
/datum/gear/suit/coat/job
|
||||
subtype_path = /datum/gear/suit/coat
|
||||
subtype_cost_overlap = FALSE
|
||||
|
||||
/datum/gear/suit/coat/job/sec
|
||||
display_name = "winter coat, security"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/security
|
||||
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/suit/coat/job/captain
|
||||
display_name = "winter coat, captain"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/captain
|
||||
allowed_roles = list("Captain")
|
||||
|
||||
/datum/gear/suit/coat/job/med
|
||||
display_name = "winter coat, medical"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/medical
|
||||
allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Psychiatrist", "Paramedic", "Virologist", "Brig Physician")
|
||||
|
||||
/datum/gear/suit/coat/job/sci
|
||||
display_name = "winter coat, science"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/science
|
||||
allowed_roles = list("Scientist", "Research Director")
|
||||
|
||||
/datum/gear/suit/coat/job/engi
|
||||
display_name = "winter coat, engineering"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/engineering
|
||||
allowed_roles = list("Chief Engineer", "Engineer", "Mechanic")
|
||||
|
||||
/datum/gear/suit/coat/job/atmos
|
||||
display_name = "winter coat, atmospherics"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
|
||||
allowed_roles = list("Chief Engineer", "Life Support Specialist")
|
||||
|
||||
/datum/gear/suit/coat/job/hydro
|
||||
display_name = "winter coat, hydroponics"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/hydro
|
||||
allowed_roles = list("Botanist")
|
||||
|
||||
/datum/gear/suit/coat/job/cargo
|
||||
display_name = "winter coat, cargo"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/cargo
|
||||
allowed_roles = list("Quartermaster", "Cargo Technician")
|
||||
|
||||
/datum/gear/suit/coat/job/miner
|
||||
display_name = "winter coat, miner"
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/miner
|
||||
allowed_roles = list("Miner")
|
||||
|
||||
//LABCOATS
|
||||
/datum/gear/suit/labcoat_emt
|
||||
display_name = "labcoat, paramedic"
|
||||
path = /obj/item/clothing/suit/storage/labcoat/emt
|
||||
allowed_roles = list("Chief Medical Officer", "Paramedic")
|
||||
|
||||
//JACKETS
|
||||
/datum/gear/suit/leather_jacket
|
||||
display_name = "leather jacket"
|
||||
path = /obj/item/clothing/suit/jacket/leather
|
||||
|
||||
/datum/gear/suit/br_tcoat
|
||||
display_name = "trenchcoat, brown"
|
||||
path = /obj/item/clothing/suit/browntrenchcoat
|
||||
|
||||
/datum/gear/suit/bl_tcoat
|
||||
display_name = "trenchcoat, black"
|
||||
path = /obj/item/clothing/suit/blacktrenchcoat
|
||||
|
||||
/datum/gear/suit/bomber_jacket
|
||||
display_name = "bomber jacket"
|
||||
path = /obj/item/clothing/suit/jacket
|
||||
|
||||
/datum/gear/suit/ol_miljacket
|
||||
display_name = "military jacket, olive"
|
||||
path = /obj/item/clothing/suit/jacket/miljacket
|
||||
|
||||
/datum/gear/suit/nv_miljacket
|
||||
display_name = "military jacket, navy"
|
||||
path = /obj/item/clothing/suit/jacket/miljacket/navy
|
||||
|
||||
/datum/gear/suit/ds_miljacket
|
||||
display_name = "military jacket, desert"
|
||||
path = /obj/item/clothing/suit/jacket/miljacket/desert
|
||||
|
||||
/datum/gear/suit/wh_miljacket
|
||||
display_name = "military jacket, white"
|
||||
path = /obj/item/clothing/suit/jacket/miljacket/white
|
||||
|
||||
/datum/gear/suit/secjacket
|
||||
display_name = "security jacket"
|
||||
path = /obj/item/clothing/suit/armor/secjacket
|
||||
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/suit/poncho
|
||||
display_name = "poncho, classic"
|
||||
path = /obj/item/clothing/suit/poncho
|
||||
|
||||
/datum/gear/suit/grponcho
|
||||
display_name = "poncho, green"
|
||||
path = /obj/item/clothing/suit/poncho/green
|
||||
|
||||
/datum/gear/suit/rdponcho
|
||||
display_name = "poncho, red"
|
||||
path = /obj/item/clothing/suit/poncho/red
|
||||
|
||||
/datum/gear/suit/tphoodie
|
||||
display_name = "hoodie, Tharsis Polytech"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie/tp
|
||||
|
||||
/datum/gear/suit/nthoodie
|
||||
display_name = "hoodie, Nanotrasen"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie/nt
|
||||
|
||||
/datum/gear/suit/lamhoodie
|
||||
display_name = "hoodie, Lunar Academy of Medicine"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie/lam
|
||||
|
||||
/datum/gear/suit/cuthoodie
|
||||
display_name = "hoodie, Canaan University of Technology"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie/cut
|
||||
|
||||
/datum/gear/suit/mithoodie
|
||||
display_name = "hoodie, Martian Institute of Technology"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie/mit
|
||||
|
||||
/datum/gear/suit/bluehoodie
|
||||
display_name = "hoodie, blue"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie/blue
|
||||
|
||||
/datum/gear/suit/blackhoodie
|
||||
display_name = "hoodie, black"
|
||||
path = /obj/item/clothing/suit/hooded/hoodie
|
||||
@@ -24,7 +24,7 @@
|
||||
path = /obj/item/clothing/under/blackskirt
|
||||
|
||||
/datum/gear/uniform/skirt/job
|
||||
cost = 3
|
||||
cost = 2
|
||||
subtype_path = /datum/gear/uniform/skirt/job
|
||||
subtype_cost_overlap = FALSE
|
||||
|
||||
@@ -96,4 +96,96 @@
|
||||
/datum/gear/uniform/skirt/job/head_of_security
|
||||
display_name = "skirt, hos"
|
||||
path = /obj/item/clothing/under/rank/head_of_security/skirt
|
||||
allowed_roles = list("Head of Security")
|
||||
allowed_roles = list("Head of Security")
|
||||
|
||||
/datum/gear/uniform/sec
|
||||
subtype_path = /datum/gear/uniform/sec
|
||||
cost = 2
|
||||
|
||||
/datum/gear/uniform/sec/formal
|
||||
display_name = "security uniform, formal"
|
||||
path = /obj/item/clothing/under/rank/security/formal
|
||||
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
datum/gear/uniform/secorporate
|
||||
display_name = "security uniform, corporate "
|
||||
path = /obj/item/clothing/under/rank/security/corp
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/uniform/sec/dispatch
|
||||
display_name = "security uniform, dispatch"
|
||||
path = /obj/item/clothing/under/rank/dispatch
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/uniform/sec/casual
|
||||
display_name = "security uniform, casual"
|
||||
path = /obj/item/clothing/under/rank/security2
|
||||
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Detective", "Security Pod Pilot")
|
||||
|
||||
/datum/gear/uniform/shorts/red
|
||||
display_name = "shorts, red"
|
||||
path = /obj/item/clothing/under/shorts/red
|
||||
|
||||
/datum/gear/uniform/shorts/green
|
||||
display_name = "shorts, green"
|
||||
path = /obj/item/clothing/under/shorts/green
|
||||
|
||||
/datum/gear/uniform/shorts/blue
|
||||
display_name = "shorts, blue"
|
||||
path = /obj/item/clothing/under/shorts/blue
|
||||
|
||||
/datum/gear/uniform/shorts/black
|
||||
display_name = "shorts, black"
|
||||
path = /obj/item/clothing/under/shorts/black
|
||||
|
||||
/datum/gear/uniform/shorts/grey
|
||||
display_name = "shorts, grey"
|
||||
path = /obj/item/clothing/under/shorts/grey
|
||||
|
||||
/datum/gear/uniform/pants/jeans
|
||||
display_name = "jeans, classic"
|
||||
path = /obj/item/clothing/under/pants/classicjeans
|
||||
|
||||
/datum/gear/uniform/pants/mjeans
|
||||
display_name = "jeans, mustang"
|
||||
path = /obj/item/clothing/under/pants/mustangjeans
|
||||
|
||||
/datum/gear/uniform/pants/bljeans
|
||||
display_name = "jeans, black"
|
||||
path = /obj/item/clothing/under/pants/blackjeans
|
||||
|
||||
/datum/gear/uniform/pants/yfjeans
|
||||
display_name = "jeans, Young Folks"
|
||||
path = /obj/item/clothing/under/pants/youngfolksjeans
|
||||
|
||||
/datum/gear/uniform/pants/whitepants
|
||||
display_name = "pants, white"
|
||||
path = /obj/item/clothing/under/pants/white
|
||||
|
||||
/datum/gear/uniform/pants/redpants
|
||||
display_name = "pants, red"
|
||||
path = /obj/item/clothing/under/pants/red
|
||||
|
||||
/datum/gear/uniform/pants/blackpants
|
||||
display_name = "pants, black"
|
||||
path = /obj/item/clothing/under/pants/black
|
||||
|
||||
/datum/gear/uniform/pants/tanpants
|
||||
display_name = "pants, tan"
|
||||
path = /obj/item/clothing/under/pants/tan
|
||||
|
||||
/datum/gear/uniform/pants/bluepants
|
||||
display_name = "pants, blue"
|
||||
path = /obj/item/clothing/under/pants/blue
|
||||
|
||||
/datum/gear/uniform/pants/trackpants
|
||||
display_name = "trackpants"
|
||||
path = /obj/item/clothing/under/pants/track
|
||||
|
||||
/datum/gear/uniform/pants/khakipants
|
||||
display_name = "pants, khaki"
|
||||
path = /obj/item/clothing/under/pants/khaki
|
||||
|
||||
/datum/gear/uniform/pants/caopants
|
||||
display_name = "pants, camo"
|
||||
path = /obj/item/clothing/under/pants/camo
|
||||
|
||||
@@ -1844,10 +1844,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
character.name = character.real_name
|
||||
|
||||
character.flavor_text = flavor_text
|
||||
if(character.ckey && !jobban_isbanned(character, "Records"))
|
||||
character.med_record = med_record
|
||||
character.sec_record = sec_record
|
||||
character.gen_record = gen_record
|
||||
character.med_record = med_record
|
||||
character.sec_record = sec_record
|
||||
character.gen_record = gen_record
|
||||
|
||||
character.change_gender(gender)
|
||||
character.age = age
|
||||
|
||||
@@ -114,4 +114,19 @@
|
||||
prescription_upgradable = 1
|
||||
|
||||
/obj/item/clothing/glasses/hud/security/sunglasses/prescription
|
||||
prescription = 1
|
||||
prescription = 1
|
||||
|
||||
/obj/item/clothing/glasses/hud/hydroponic
|
||||
name = "Hydroponic HUD"
|
||||
desc = "A heads-up display capable of analyzing the health and status of plants growing in hydro trays and soil."
|
||||
icon_state = "hydroponichud"
|
||||
HUDType = DATA_HUD_HYDROPONIC
|
||||
|
||||
/obj/item/clothing/glasses/hud/hydroponic/night
|
||||
name = "Night Vision Hydroponic HUD"
|
||||
desc = "A hydroponic HUD fitted with a light amplifier."
|
||||
icon_state = "hydroponichudnight"
|
||||
item_state = "glasses"
|
||||
darkness_view = 8
|
||||
see_darkness = 0
|
||||
prescription_upgradable = 0
|
||||
@@ -116,6 +116,11 @@
|
||||
desc = "A beret for those who have shown immaculate proficienty in piping. Or plumbing."
|
||||
icon_state = "beret_atmospherics"
|
||||
|
||||
/obj/item/clothing/head/beret/ce
|
||||
name = "chief engineer beret"
|
||||
desc = "A white beret with the engineering insignia emblazoned on it. Its owner knows what they're doing. Probably."
|
||||
icon_state = "beret_ce"
|
||||
|
||||
//Medical
|
||||
/obj/item/clothing/head/surgery
|
||||
name = "surgical cap"
|
||||
@@ -137,4 +142,4 @@
|
||||
|
||||
/obj/item/clothing/head/surgery/black
|
||||
desc = "A cap coroners wear during autopsies. Keeps their hair from falling into the cadavers. It is as dark than the coroner's humor."
|
||||
icon_state = "surgcap_black"
|
||||
icon_state = "surgcap_black"
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
icon_state = "pwig"
|
||||
item_state = "pwig"
|
||||
|
||||
/obj/item/clothing/head/beret/blue
|
||||
icon_state = "beret_blue"
|
||||
|
||||
/obj/item/clothing/head/beret/black
|
||||
icon_state = "beret_black"
|
||||
|
||||
/obj/item/clothing/head/beret/purple_normal
|
||||
icon_state = "beret_purple_normal"
|
||||
|
||||
/obj/item/clothing/head/that
|
||||
name = "top-hat"
|
||||
desc = "It's an amish looking hat."
|
||||
@@ -161,6 +170,12 @@
|
||||
item_state = "boater_hat"
|
||||
desc = "Goes well with celery."
|
||||
|
||||
/obj/item/clothing/head/cowboyhat
|
||||
name = "cowboy hat"
|
||||
icon_state = "cowboyhat"
|
||||
item_state = "fedora"
|
||||
desc = "There's a new sheriff in town. Pass the whiskey."
|
||||
|
||||
/obj/item/clothing/head/fedora
|
||||
name = "\improper fedora"
|
||||
icon_state = "fedora"
|
||||
@@ -363,4 +378,4 @@
|
||||
name = "bloated human head"
|
||||
desc = "A horribly bloated and mismatched human head."
|
||||
icon_state = "lingspacehelmet"
|
||||
item_state = "lingspacehelmet"
|
||||
item_state = "lingspacehelmet"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/obj/item/clothing/suit/armor
|
||||
allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite,/obj/item/weapon/melee/classic_baton/telescopic,/obj/item/weapon/kitchen/knife/combat)
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO
|
||||
@@ -91,6 +90,20 @@
|
||||
species_fit = null
|
||||
sprite_sheets = null
|
||||
|
||||
/obj/item/clothing/suit/armor/secjacket
|
||||
name = "security jacket"
|
||||
desc = "A sturdy black jacket with reinforced fabric. Bears insignia of NT corporate security."
|
||||
icon_state = "secjacket_open"
|
||||
item_state = "hos"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
armor = list(melee = 15, bullet = 10, laser = 15, energy = 5, bomb = 15, bio = 0, rad = 0)
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
heat_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
ignore_suitadjust = 0
|
||||
suit_adjusted = 1
|
||||
action_button_name = "Open/Close Jacket"
|
||||
adjust_flavour = "unzip"
|
||||
|
||||
/obj/item/clothing/suit/armor/hos
|
||||
name = "armored coat"
|
||||
desc = "A trench coat enhanced with a special alloy for some protection and style."
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
//Hoods for winter coats and chaplain hoodie etc
|
||||
|
||||
/obj/item/clothing/suit/hooded
|
||||
action_button_name = "Adjust hood"
|
||||
var/obj/item/clothing/head/hood
|
||||
var/hoodtype = /obj/item/clothing/head/winterhood //so the chaplain hoodie or other hoodies can override this
|
||||
|
||||
/obj/item/clothing/suit/hooded/New()
|
||||
MakeHood()
|
||||
verbs -= /obj/item/clothing/suit/verb/openjacket //you can't unbutton those, deal with it
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/hooded/Destroy()
|
||||
qdel(hood)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/hooded/proc/MakeHood()
|
||||
if(!hood)
|
||||
var/obj/item/clothing/head/W = new hoodtype(src)
|
||||
hood = W
|
||||
|
||||
/obj/item/clothing/suit/hooded/ui_action_click()
|
||||
ToggleHood()
|
||||
|
||||
/obj/item/clothing/suit/hooded/equipped(mob/user, slot)
|
||||
if(slot != slot_wear_suit)
|
||||
RemoveHood()
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/hooded/proc/RemoveHood()
|
||||
icon_state = "[initial(icon_state)]"
|
||||
suit_adjusted = 0
|
||||
if(ishuman(hood.loc))
|
||||
var/mob/living/carbon/H = hood.loc
|
||||
H.unEquip(hood, 1)
|
||||
H.update_inv_wear_suit()
|
||||
hood.loc = src
|
||||
|
||||
/obj/item/clothing/suit/hooded/dropped()
|
||||
..()
|
||||
RemoveHood()
|
||||
|
||||
/obj/item/clothing/suit/hooded/verb/Hooderize(var/mob/user)
|
||||
set name = "Adjust the hood"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
if(!isliving(usr))
|
||||
return
|
||||
if(usr.stat)
|
||||
return
|
||||
ToggleHood()
|
||||
|
||||
/obj/item/clothing/suit/hooded/proc/ToggleHood()
|
||||
if(!suit_adjusted)
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
if(H.wear_suit != src)
|
||||
to_chat(H,"<span class='warning'>You must be wearing [src] to put up the hood!</span>")
|
||||
return
|
||||
if(H.head)
|
||||
to_chat(H,"<span class='warning'>You're already wearing something on your head!</span>")
|
||||
return
|
||||
else if(H.equip_to_slot_if_possible(hood,slot_head,0,0,1))
|
||||
suit_adjusted = 1
|
||||
icon_state = "[initial(icon_state)]_hood"
|
||||
H.update_inv_wear_suit()
|
||||
else
|
||||
RemoveHood()
|
||||
@@ -73,12 +73,13 @@
|
||||
)
|
||||
|
||||
//Chaplain
|
||||
/obj/item/clothing/suit/chaplain_hoodie
|
||||
/obj/item/clothing/suit/hooded/chaplain_hoodie
|
||||
name = "chaplain hoodie"
|
||||
desc = "This suit says to you 'hush'!"
|
||||
icon_state = "chaplain_hoodie"
|
||||
item_state = "chaplain_hoodie"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
hoodtype = /obj/item/clothing/head/chaplain_hood
|
||||
allowed = list(/obj/item/weapon/storage/bible, /obj/item/weapon/nullrod, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater, /obj/item/weapon/storage/fancy/candle_box, /obj/item/candle, /obj/item/weapon/tank/emergency_oxygen)
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
@@ -86,13 +87,14 @@
|
||||
)
|
||||
|
||||
//Chaplain
|
||||
/obj/item/clothing/suit/nun
|
||||
/obj/item/clothing/suit/hooded/nun
|
||||
name = "nun robe"
|
||||
desc = "Maximum piety in this star system."
|
||||
icon_state = "nun"
|
||||
item_state = "nun"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
|
||||
flags_inv = HIDESHOES|HIDEJUMPSUIT
|
||||
hoodtype = /obj/item/clothing/head/nun_hood
|
||||
allowed = list(/obj/item/weapon/storage/bible, /obj/item/weapon/nullrod, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater, /obj/item/weapon/storage/fancy/candle_box, /obj/item/candle, /obj/item/weapon/tank/emergency_oxygen)
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
|
||||
@@ -56,3 +56,9 @@
|
||||
desc = "A suit that protects against minor chemical spills. Has a black stripe on the shoulder."
|
||||
icon_state = "labcoat_mort_open"
|
||||
item_state = "labcoat_mort_open"
|
||||
|
||||
/obj/item/clothing/suit/storage/labcoat/emt
|
||||
name = "EMT labcoat"
|
||||
desc = "A comfortable suit for paramedics. Has dark colours."
|
||||
icon_state = "labcoat_emt_open"
|
||||
item_state = "labcoat_emt_open"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Contains:
|
||||
* Lasertag
|
||||
* Costume
|
||||
* Winter Coats
|
||||
* Misc
|
||||
*/
|
||||
|
||||
@@ -282,11 +283,194 @@
|
||||
item_state = "lingspacesuit"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
|
||||
/*
|
||||
* Winter Coats
|
||||
*/
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat
|
||||
name = "winter coat"
|
||||
desc = "A heavy jacket made from 'synthetic' animal furs."
|
||||
icon_state = "wintercoat"
|
||||
item_state = "labcoat"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0)
|
||||
allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/toy, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/lighter)
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/winterhood
|
||||
name = "winter hood"
|
||||
desc = "A hood attached to a heavy winter jacket."
|
||||
icon_state = "winterhood"
|
||||
body_parts_covered = HEAD
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
|
||||
flags = NODROP|BLOCKHAIR
|
||||
flags_inv = HIDEEARS
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list("Vox" = 'icons/mob/species/vox/head.dmi')
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/captain
|
||||
name = "captain's winter coat"
|
||||
icon_state = "wintercoat_captain"
|
||||
armor = list(melee = 25, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
|
||||
allowed = list(/obj/item/weapon/gun/energy, /obj/item/weapon/reagent_containers/spray/pepper, /obj/item/weapon/gun/projectile, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/weapon/melee/baton, /obj/item/weapon/restraints/handcuffs, /obj/item/device/flashlight/seclite, /obj/item/weapon/melee/classic_baton/telescopic)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/captain
|
||||
|
||||
/obj/item/clothing/head/winterhood/captain
|
||||
icon_state = "winterhood_captain"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/security
|
||||
name = "security winter coat"
|
||||
icon_state = "wintercoat_sec"
|
||||
armor = list(melee = 15, bullet = 10, laser = 20, energy = 5, bomb = 15, bio = 0, rad = 0) //worse stats than normal armor, but this one protects arms and makes space hurt less, CHOICES!
|
||||
allowed = list(/obj/item/weapon/gun/energy, /obj/item/weapon/reagent_containers/spray/pepper, /obj/item/weapon/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/weapon/melee/baton, /obj/item/weapon/restraints/handcuffs, /obj/item/device/flashlight/seclite, /obj/item/weapon/melee/classic_baton/telescopic)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/security
|
||||
|
||||
/obj/item/clothing/head/winterhood/security
|
||||
icon_state = "winterhood_sec"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/medical
|
||||
name = "medical winter coat"
|
||||
icon_state = "wintercoat_med"
|
||||
allowed = list(/obj/item/device/analyzer, /obj/item/weapon/dnainjector, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/syringe, /obj/item/weapon/reagent_containers/hypospray, /obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen, /obj/item/weapon/reagent_containers/glass/bottle, /obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/storage/pill_bottle, /obj/item/weapon/paper, /obj/item/weapon/melee/classic_baton/telescopic)
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/medical
|
||||
|
||||
/obj/item/clothing/head/winterhood/medical
|
||||
icon_state = "winterhood_med"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/science
|
||||
name = "science winter coat"
|
||||
icon_state = "wintercoat_sci"
|
||||
allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/weapon/dnainjector, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/syringe, /obj/item/weapon/reagent_containers/hypospray, /obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen, /obj/item/weapon/reagent_containers/glass/bottle, /obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/storage/pill_bottle, /obj/item/weapon/paper, /obj/item/weapon/melee/classic_baton/telescopic)
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/science
|
||||
|
||||
/obj/item/clothing/head/winterhood/science
|
||||
icon_state = "winterhood_sci"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/engineering
|
||||
name = "engineering winter coat"
|
||||
icon_state = "wintercoat_engi"
|
||||
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 20)
|
||||
allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/device/t_scanner, /obj/item/weapon/rcd)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/engineering
|
||||
|
||||
/obj/item/clothing/head/winterhood/engineering
|
||||
icon_state = "winterhood_engi"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
|
||||
name = "atmospherics winter coat"
|
||||
icon_state = "wintercoat_atmos"
|
||||
hoodtype = /obj/item/clothing/head/winterhood/engineering/atmos
|
||||
|
||||
/obj/item/clothing/head/winterhood/engineering/atmos
|
||||
icon_state = "winterhood_atmos"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/hydro
|
||||
name = "hydroponics winter coat"
|
||||
icon_state = "wintercoat_hydro"
|
||||
allowed = list(/obj/item/weapon/reagent_containers/spray, /obj/item/device/analyzer/plant_analyzer, /obj/item/seeds, /obj/item/weapon/reagent_containers/glass/bottle, /obj/item/weapon/hatchet, /obj/item/weapon/storage/bag/plants)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/hydro
|
||||
|
||||
/obj/item/clothing/head/winterhood/hydro
|
||||
icon_state = "winterhood_hydro"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/cargo
|
||||
name = "cargo winter coat"
|
||||
icon_state = "wintercoat_cargo"
|
||||
hoodtype = /obj/item/clothing/head/winterhood/cargo
|
||||
|
||||
/obj/item/clothing/head/winterhood/cargo
|
||||
icon_state = "winterhood_cargo"
|
||||
|
||||
/obj/item/clothing/suit/hooded/wintercoat/miner
|
||||
name = "mining winter coat"
|
||||
icon_state = "wintercoat_miner"
|
||||
allowed = list(/obj/item/weapon/pickaxe, /obj/item/device/flashlight, /obj/item/weapon/tank/emergency_oxygen, /obj/item/toy, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/lighter)
|
||||
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
hoodtype = /obj/item/clothing/head/winterhood/miner
|
||||
|
||||
/obj/item/clothing/head/winterhood/miner
|
||||
icon_state = "winterhood_miner"
|
||||
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
|
||||
//hoodies
|
||||
/obj/item/clothing/suit/hooded/hoodie
|
||||
name = "hoodie"
|
||||
desc = "It's a hoodie. It has a hood. Most hoodies do."
|
||||
icon_state = "black_hoodie"
|
||||
item_state = "labcoat"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
hoodtype = /obj/item/clothing/head/hood
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/hood
|
||||
name = "hood"
|
||||
desc = "A hood attached to a hoodie."
|
||||
icon_state = "blackhood"
|
||||
body_parts_covered = HEAD
|
||||
cold_protection = HEAD
|
||||
flags = NODROP|BLOCKHAIR
|
||||
flags_inv = HIDEEARS
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/hood/blue
|
||||
icon_state = "bluehood"
|
||||
|
||||
/obj/item/clothing/head/hood/white
|
||||
icon_state = "whitehood"
|
||||
|
||||
/obj/item/clothing/suit/hooded/hoodie/blue
|
||||
name = "blue hoodie"
|
||||
icon_state = "blue_hoodie"
|
||||
hoodtype = /obj/item/clothing/head/hood/blue
|
||||
|
||||
/obj/item/clothing/suit/hooded/hoodie/mit
|
||||
name = "Martian Institute of Technology hoodie"
|
||||
desc = "A hoodie proudly worn by students and graduates alike, has the letters 'MIT' on the back."
|
||||
icon_state = "mit_hoodie"
|
||||
hoodtype = /obj/item/clothing/head/hood
|
||||
|
||||
/obj/item/clothing/suit/hooded/hoodie/cut
|
||||
name = "Canaan University of Technology hoodie"
|
||||
desc = "A bright hoodie with the Canaan University of Technology logo on the front."
|
||||
icon_state = "cut_hoodie"
|
||||
hoodtype = /obj/item/clothing/head/hood/white
|
||||
|
||||
/obj/item/clothing/suit/hooded/hoodie/lam
|
||||
name = "Lunar Academy of Medicine hoodie"
|
||||
desc = "A bright hoodie with the Lunar Academy of Medicine logo on the back."
|
||||
icon_state = "lam_hoodie"
|
||||
hoodtype = /obj/item/clothing/head/hood/white
|
||||
|
||||
/obj/item/clothing/suit/hooded/hoodie/nt
|
||||
name = "Nanotrasen hoodie"
|
||||
desc = "A blue hoodie with the Nanotrasen logo on the back."
|
||||
icon_state = "nt_hoodie"
|
||||
hoodtype = /obj/item/clothing/head/hood/blue
|
||||
|
||||
/obj/item/clothing/suit/hooded/hoodie/tp
|
||||
name = "Tharsis Polytech hoodie"
|
||||
desc = "A dark hoodie with the Tharsis Polytech logo on the back."
|
||||
icon_state = "tp_hoodie"
|
||||
hoodtype = /obj/item/clothing/head/hood
|
||||
|
||||
/obj/item/clothing/suit/straight_jacket
|
||||
name = "straight jacket"
|
||||
desc = "A suit that completely restrains the wearer."
|
||||
@@ -307,6 +491,8 @@
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
|
||||
|
||||
//pyjamas
|
||||
//originally intended to be pinstripes >.>
|
||||
|
||||
@@ -364,6 +550,34 @@
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
//trackjackets
|
||||
|
||||
/obj/item/clothing/suit/tracksuit
|
||||
name = "black tracksuit"
|
||||
desc = "Lightweight and stylish. What else could a man ask of his tracksuit?"
|
||||
icon_state = "trackjacket_open"
|
||||
item_state = "bltrenchcoat"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
|
||||
ignore_suitadjust = 0
|
||||
suit_adjusted = 1
|
||||
action_button_name = "Open/Close Jacket"
|
||||
adjust_flavour = "unzip"
|
||||
species_fit = list("Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/suit/tracksuit/green
|
||||
name = "green tracksuit"
|
||||
icon_state = "trackjacketgreen_open"
|
||||
|
||||
/obj/item/clothing/suit/tracksuit/red
|
||||
name = "red tracksuit"
|
||||
icon_state = "trackjacketred_open"
|
||||
|
||||
/obj/item/clothing/suit/tracksuit/white
|
||||
name = "white tracksuit"
|
||||
icon_state = "trackjacketwhite_open"
|
||||
|
||||
//actual suits
|
||||
|
||||
|
||||
@@ -39,11 +39,13 @@
|
||||
desc = "Groovy!"
|
||||
icon_state = "psyche"
|
||||
item_color = "psyche"
|
||||
usr.update_inv_w_uniform()
|
||||
spawn(200)
|
||||
name = "Black Jumpsuit"
|
||||
icon_state = "bl_suit"
|
||||
item_color = "black"
|
||||
desc = null
|
||||
name = initial(name)
|
||||
icon_state = initial(icon_state)
|
||||
item_color = initial(item_color)
|
||||
desc = initial(desc)
|
||||
usr.update_inv_w_uniform()
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -178,7 +178,8 @@
|
||||
desc = "A blue comb, it looks like it was made to groom a Tajaran's fur."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
icon_state = "wingler_comb"
|
||||
attack_verb = "combed"
|
||||
attack_verb = list("combed")
|
||||
hitsound = 'sound/weapons/tap.ogg'
|
||||
force = 0
|
||||
throwforce = 0
|
||||
w_class = 2
|
||||
|
||||
@@ -102,3 +102,17 @@ var/total_runtimes_skipped = 0
|
||||
error_cache.logError(e, desclines, e_src = e_src)
|
||||
|
||||
#endif
|
||||
|
||||
/proc/log_runtime(exception/e, datum/e_src, extra_info)
|
||||
if(!istype(e))
|
||||
world.Error(e, e_src)
|
||||
return
|
||||
|
||||
if(extra_info)
|
||||
// Adding extra info adds two newlines, because parsing runtimes is funky
|
||||
if(islist(extra_info))
|
||||
e.desc = " [jointext(extra_info, "\n ")]\n\n" + e.desc
|
||||
else
|
||||
e.desc = " [extra_info]\n\n" + e.desc
|
||||
|
||||
world.Error(e, e_src)
|
||||
|
||||
@@ -516,7 +516,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
|
||||
/obj/item/clothing/mask/gas/voice, /obj/item/clothing/glasses/thermal,\
|
||||
/obj/item/device/chameleon, /obj/item/weapon/card/emag,\
|
||||
/obj/item/weapon/storage/toolbox/syndicate, /obj/item/weapon/aiModule,\
|
||||
/obj/item/device/radio/headset/syndicate, /obj/item/weapon/c4,\
|
||||
/obj/item/device/radio/headset/syndicate, /obj/item/weapon/grenade/plastic/c4,\
|
||||
/obj/item/device/powersink, /obj/item/weapon/storage/box/syndie_kit,\
|
||||
/obj/item/toy/syndicateballoon, /obj/item/weapon/gun/energy/laser/captain,\
|
||||
/obj/item/weapon/hand_tele, /obj/item/weapon/rcd, /obj/item/weapon/tank/jetpack,\
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
|
||||
//adjust these to change the maximum capacity of the bottler for each container type
|
||||
#define MAX_GLASS 10
|
||||
#define MAX_PLAST 20
|
||||
#define MAX_METAL 25
|
||||
|
||||
//adjust these to change the number of containers the bottler will make per sheet
|
||||
#define RATIO_GLASS 1
|
||||
#define RATIO_PLAST 2
|
||||
#define RATIO_METAL 5
|
||||
|
||||
/obj/machinery/bottler
|
||||
name = "bottler unit"
|
||||
desc = "A machine that combines ingredients and bottles the resulting beverages."
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "bottler_off"
|
||||
density = 1
|
||||
anchored = 1
|
||||
var/list/slots[3]
|
||||
var/list/datum/bottler_recipe/available_recipes
|
||||
var/list/acceptable_items
|
||||
var/list/containers = list("glass bottle" = 10, "plastic bottle" = 20, "metal can" = 25)
|
||||
var/bottling = 0
|
||||
|
||||
/obj/machinery/bottler/New()
|
||||
if(!available_recipes)
|
||||
available_recipes = list()
|
||||
acceptable_items = list()
|
||||
//These are going to be acceptable even if they aren't in a recipe
|
||||
acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks
|
||||
acceptable_items |= /obj/item/weapon/reagent_containers/food/drinks/cans
|
||||
//the rest is based on what is used in recipes so we don't have people destroying the nuke disc
|
||||
for(var/type in subtypesof(/datum/bottler_recipe))
|
||||
var/datum/bottler_recipe/recipe = new type
|
||||
if(recipe.result) // Ignore recipe subtypes that lack a result
|
||||
available_recipes += recipe
|
||||
for(var/i = 1, i <= recipe.ingredients.len, i++)
|
||||
acceptable_items |= recipe.ingredients[i]
|
||||
else
|
||||
qdel(recipe)
|
||||
|
||||
/obj/machinery/bottler/attackby(obj/item/O, mob/user, params)
|
||||
if(iswrench(O)) //This being before the canUnequip check allows borgs to (un)wrench bottlers in case they need move them to fix stuff
|
||||
playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
if(anchored)
|
||||
anchored = 0
|
||||
to_chat(user, "<span class='alert'>[src] can now be moved.</span>")
|
||||
else
|
||||
anchored = 1
|
||||
to_chat(user, "<span class='alert'>[src] is now secured.</span>")
|
||||
return 1
|
||||
if(!user.canUnEquip(O, 0))
|
||||
to_chat(user, "<span class='warning'>[O] is stuck to your hand, you can't seem to put it down!</span>")
|
||||
return 0
|
||||
if(is_type_in_list(O,acceptable_items))
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks))
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/S = O
|
||||
user.unEquip(S)
|
||||
if(S.reagents && !S.reagents.total_volume) //This prevents us from using empty foods, should one occur due to some sort of error
|
||||
to_chat(user, "<span class='warning'>[S] is gone, oh no!</span>")
|
||||
qdel(S) //Delete the food object because it is useless even as food due to the lack of reagents
|
||||
else
|
||||
insert_item(S, user)
|
||||
return 1
|
||||
else if(istype(O, /obj/item/weapon/reagent_containers/food/drinks/cans))
|
||||
var/obj/item/weapon/reagent_containers/food/drinks/cans/C = O
|
||||
if(C.reagents)
|
||||
if(C.canopened && C.reagents.total_volume) //This prevents us from using opened cans that still have something in them
|
||||
to_chat(user, "<span class='warning'>Only unopened cans and bottles can be processed to ensure product integrity.</span>")
|
||||
return 0
|
||||
user.unEquip(C)
|
||||
if(!C.reagents.total_volume) //Empty cans get recycled, even if they have somehow remained unopened due to some sort of error
|
||||
recycle_container(C)
|
||||
else //Full cans that are unopened get inserted for processing as ingredients
|
||||
insert_item(C, user)
|
||||
return 1
|
||||
else
|
||||
user.unEquip(O)
|
||||
insert_item(O, user)
|
||||
return 1
|
||||
else if(istype(O, /obj/item/trash/can)) //Crushed cans (and bottles) are returnable still
|
||||
var/obj/item/trash/can/C = O
|
||||
user.unEquip(C)
|
||||
recycle_container(C)
|
||||
return 1
|
||||
else if(istype(O, /obj/item/stack/sheet)) //Sheets of materials can replenish the machine's supply of drink containers (when people inevitably don't return them)
|
||||
var/obj/item/stack/sheet/S = O
|
||||
user.unEquip(S)
|
||||
process_sheets(S)
|
||||
return 1
|
||||
else //If it doesn't qualify in the above checks, we don't want it. Inform the person so they (ideally) stop trying to put the nuke disc in.
|
||||
to_chat(user, "<span class='warning'>You aren't sure this is able to be processed by the machine.</span>")
|
||||
return 0
|
||||
//..()
|
||||
|
||||
/obj/machinery/bottler/proc/insert_item(obj/item/O, mob/user)
|
||||
if(!O || !user)
|
||||
return
|
||||
if(slots[1] && slots[2] && slots[3])
|
||||
to_chat(user, "<span class='warning'>[src] is full, please remove or process the contents first.</span>")
|
||||
return
|
||||
var/slot_inserted = 0
|
||||
for(var/i = 1, i <= slots.len, i++)
|
||||
if(!slots[i])
|
||||
slots[i] = O
|
||||
slot_inserted = i
|
||||
break
|
||||
if(!slot_inserted)
|
||||
to_chat(user, "<span class='warning'>Something went wrong and the machine spits out [O].</span>")
|
||||
O.forceMove(loc)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You load [O] into the [slot_inserted]\th ingredient tray.</span>")
|
||||
O.forceMove(src)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/bottler/proc/eject_items(var/slot)
|
||||
var/obj/item/O = null
|
||||
if(!slot)
|
||||
for(var/i = 1, i <= slots.len, i++)
|
||||
if(slots[i])
|
||||
O = slots[i]
|
||||
O.forceMove(loc)
|
||||
slots[i] = null
|
||||
visible_message("<span class='notice'>[src] beeps as it ejects the contents of all the ingredient trays.</span>")
|
||||
else
|
||||
if(slots[slot]) //ensures the tray actually has something to eject so we don't runtime on trying to reference null
|
||||
O = slots[slot]
|
||||
O.forceMove(loc)
|
||||
slots[slot] = null
|
||||
visible_message("<span class='notice'>[src] beeps as it ejects [O.name] from the [slot]\th ingredient tray.</span>")
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/bottler/proc/recycle_container(obj/item/O)
|
||||
if(!O)
|
||||
return
|
||||
var/con_type
|
||||
var/max_define
|
||||
if(istype(O, /obj/item/trash/can))
|
||||
var/obj/item/trash/can/C = O
|
||||
if(C.is_glass)
|
||||
con_type = "glass bottle"
|
||||
max_define = MAX_GLASS
|
||||
else if(C.is_plastic)
|
||||
con_type = "plastic bottle"
|
||||
max_define = MAX_PLAST
|
||||
else
|
||||
con_type = "metal can"
|
||||
max_define = MAX_METAL
|
||||
else if(istype(O, /obj/item/weapon/reagent_containers/food/drinks/cans))
|
||||
var/obj/item/weapon/reagent_containers/food/drinks/cans/C = O
|
||||
if(C.is_glass)
|
||||
con_type = "glass bottle"
|
||||
max_define = MAX_GLASS
|
||||
else if(C.is_plastic)
|
||||
con_type = "plastic bottle"
|
||||
max_define = MAX_PLAST
|
||||
else
|
||||
con_type = "metal can"
|
||||
max_define = MAX_METAL
|
||||
if(con_type)
|
||||
if(containers[con_type] < max_define)
|
||||
containers[con_type]++
|
||||
visible_message("<span class='notice'>[src] whirs briefly as it prepares the container for reuse.</span>")
|
||||
qdel(O)
|
||||
updateUsrDialog()
|
||||
else
|
||||
visible_message("<span class='warning'>[src] cannot store any more cans at this time. Please fill some before recycling more.</span>")
|
||||
O.forceMove(loc)
|
||||
|
||||
/obj/machinery/bottler/proc/process_sheets(obj/item/stack/sheet/S)
|
||||
if(!S)
|
||||
return
|
||||
S.forceMove(loc)
|
||||
var/con_type
|
||||
var/max_define
|
||||
var/mat_ratio
|
||||
//Glass sheets for glass bottles (1 bottle per sheet)
|
||||
if(istype(S, /obj/item/stack/sheet/glass))
|
||||
con_type = "glass bottle"
|
||||
max_define = MAX_GLASS
|
||||
mat_ratio = RATIO_GLASS
|
||||
else if(istype(S, /obj/item/stack/sheet/mineral/plastic))
|
||||
con_type = "plastic bottle"
|
||||
max_define = MAX_PLAST
|
||||
mat_ratio = RATIO_PLAST
|
||||
else if(istype(S, /obj/item/stack/sheet/metal))
|
||||
con_type = "metal can"
|
||||
max_define = MAX_METAL
|
||||
mat_ratio = RATIO_METAL
|
||||
else
|
||||
visible_message("<span class='warning'>[src] rejects the unusable materials.</span>")
|
||||
return
|
||||
var/missing
|
||||
var/sheets_needed
|
||||
var/sheets_to_use
|
||||
if(con_type)
|
||||
missing = max_define - containers[con_type]
|
||||
sheets_needed = round(missing / mat_ratio, 1)
|
||||
if(missing % mat_ratio)
|
||||
sheets_needed += 1
|
||||
sheets_to_use = min(sheets_needed, S.amount)
|
||||
if(missing)
|
||||
visible_message("<span class='notice'>[src] shudders as it converts [sheets_to_use] [S.singular_name]\s into new [con_type]s.</span>")
|
||||
containers[con_type] += sheets_to_use * mat_ratio
|
||||
containers[con_type] = min(containers[con_type], max_define)
|
||||
S.use(sheets_to_use)
|
||||
else
|
||||
visible_message("<span class='warning'>[src] rejects the [S] because it already is fully stocked with [con_type]s.</span>")
|
||||
|
||||
/obj/machinery/bottler/proc/select_recipe()
|
||||
for(var/datum/bottler_recipe/recipe in available_recipes)
|
||||
var/number_matches = 0
|
||||
for(var/i = 1, i <= slots.len, i++)
|
||||
var/obj/item/O = slots[i]
|
||||
if(istype(O, recipe.ingredients[i]))
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O
|
||||
if(G.seed && G.seed.kitchen_tag == recipe.tags[i])
|
||||
number_matches++
|
||||
else
|
||||
number_matches++
|
||||
if(number_matches == 3)
|
||||
return recipe
|
||||
return null
|
||||
|
||||
/obj/machinery/bottler/proc/dispense_empty_container(container)
|
||||
var/con_type
|
||||
var/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/drink_container
|
||||
switch(container)
|
||||
if(1) //glass bottle
|
||||
con_type = "glass bottle"
|
||||
drink_container = /obj/item/weapon/reagent_containers/food/drinks/cans/bottler/glass_bottle
|
||||
if(2) //plastic bottle
|
||||
con_type = "plastic bottle"
|
||||
drink_container = /obj/item/weapon/reagent_containers/food/drinks/cans/bottler/plastic_bottle
|
||||
if(3) //metal can
|
||||
con_type = "metal can"
|
||||
drink_container = /obj/item/weapon/reagent_containers/food/drinks/cans/bottler/metal_can
|
||||
if(containers[con_type])
|
||||
//empties aren't sealed, so let's open it quietly
|
||||
drink_container = new drink_container()
|
||||
drink_container.canopened = 1
|
||||
drink_container.flags |= OPENCONTAINER
|
||||
drink_container.forceMove(loc)
|
||||
containers[con_type]--
|
||||
|
||||
/obj/machinery/bottler/proc/process_ingredients(container)
|
||||
//stop if we have ZERO ingredients (what would you process?)
|
||||
if(!slots[1] && !slots[2] && !slots[3])
|
||||
visible_message("<span class='warning'>There are no ingredients to process! Please insert some first.</span>")
|
||||
return
|
||||
//prep a container
|
||||
var/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/drink_container
|
||||
var/con_type
|
||||
switch(container)
|
||||
if(1) //glass bottle
|
||||
con_type = "glass bottle"
|
||||
drink_container = /obj/item/weapon/reagent_containers/food/drinks/cans/bottler/glass_bottle
|
||||
if(2) //plastic bottle
|
||||
con_type = "plastic bottle"
|
||||
drink_container = /obj/item/weapon/reagent_containers/food/drinks/cans/bottler/plastic_bottle
|
||||
if(3) //metal can
|
||||
con_type = "metal can"
|
||||
drink_container = /obj/item/weapon/reagent_containers/food/drinks/cans/bottler/metal_can
|
||||
|
||||
if(!con_type)
|
||||
visible_message("<span class='warning'>Error 404: Drink Container Not Found.</span>")
|
||||
return
|
||||
if(!containers[con_type])
|
||||
visible_message("<span class='warning'>Error 503: Out of [con_type]s.</span>")
|
||||
return
|
||||
else
|
||||
drink_container = new drink_container()
|
||||
containers[con_type]--
|
||||
//select and process a recipe based on inserted ingredients
|
||||
visible_message("<span class='notice'>[src] hums as it processes the ingredients...</span>")
|
||||
bottling = 1
|
||||
var/datum/bottler_recipe/recipe_to_use = select_recipe()
|
||||
if(!recipe_to_use)
|
||||
//bad recipe, ruins the drink
|
||||
var/contents = pick("thick goop", "pungent sludge", "unspeakable slurry", "gross-looking concoction", "eldritch abomination of liquids")
|
||||
visible_message("<span class='warning'>The [con_type] fills with \an [contents]...</span>")
|
||||
drink_container.reagents.add_reagent(pick("????", "toxic_slurry", "meatslurry", "glowing_slury", "fishwater"), pick(30, 50))
|
||||
drink_container.name = "Liquid Mistakes"
|
||||
drink_container.desc = "WARNING: CONTENTS MAY BE AWFUL, DRINK AT OWN RISK."
|
||||
else
|
||||
//good recipe, make it
|
||||
visible_message("<span class='notice'>The [con_type] fills with a delicious-looking beverage!</span>")
|
||||
drink_container.reagents.add_reagent(recipe_to_use.result, 50)
|
||||
drink_container.name = "[recipe_to_use.name]"
|
||||
drink_container.desc = "[recipe_to_use.description]"
|
||||
flick("bottler_on", src)
|
||||
spawn(45)
|
||||
for(var/i = 1, i <= slots.len, i++)
|
||||
qdel(slots[i])
|
||||
slots[i] = null
|
||||
bottling = 0
|
||||
drink_container.forceMove(loc)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/bottler/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/bottler/attack_ghost(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/bottler/attack_hand(mob/user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/bottler/interact(mob/user)
|
||||
user.set_machine(src)
|
||||
//html ahoy
|
||||
var/dat = ""
|
||||
if(bottling)
|
||||
dat = "<h2>Bottling in process, please wait...</h2>"
|
||||
else
|
||||
dat += "<table border='1' style='width:75%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<th colspan='3'>Containers:</th>"
|
||||
dat += "</tr>"
|
||||
dat += "<tr>"
|
||||
dat += "<td>Glass Bottles: [containers["glass bottle"]]</td>"
|
||||
dat += "<td>Plastic Bottles: [containers["plastic bottle"]]</td>"
|
||||
dat += "<td>Metal Cans: [containers["metal can"]]</td>"
|
||||
dat += "</tr>"
|
||||
dat += "<tr>"
|
||||
if(containers["glass bottle"])
|
||||
dat += "<td><A href='?src=\ref[src];dispense=1'>Dispense</a></td>"
|
||||
else
|
||||
dat += "<td>Out of stock</td>"
|
||||
if(containers["plastic bottle"])
|
||||
dat += "<td><A href='?src=\ref[src];dispense=2'>Dispense</a></td>"
|
||||
else
|
||||
dat += "<td>Out of stock</td>"
|
||||
if(containers["metal can"])
|
||||
dat += "<td><A href='?src=\ref[src];dispense=3'>Dispense</a></td>"
|
||||
else
|
||||
dat += "<td>Out of stock</td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<hr>"
|
||||
dat += "<table border='1' style='width:75%'>"
|
||||
dat += "<tr>"
|
||||
dat += "<th colspan='4'>Ingredient Tray Contents:</th>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "<tr>"
|
||||
for(var/i = 1, i <= slots.len, i++)
|
||||
var/obj/O = slots[i]
|
||||
if(O)
|
||||
dat += "<td>[bicon(O)]<br>[O.name]</td>"
|
||||
else
|
||||
dat += "<td>Tray Empty</td>"
|
||||
|
||||
if(slots[1] && slots[2] && slots[3])
|
||||
dat += "<td><A href='?src=\ref[src];process=1'>Process Ingredients</a></td>"
|
||||
else
|
||||
dat += "<td>Insufficient Ingredients</td>"
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "<tr>"
|
||||
for(var/i = 1, i <= slots.len, i++)
|
||||
if(slots[i])
|
||||
dat += "<td><A href='?src=\ref[src];eject=[i]'>Eject</a></td>"
|
||||
else
|
||||
dat += "<td>N/A</td>"
|
||||
dat += "<td><A href='?src=\ref[src];eject=0'>Eject All</a></td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
dat += "<hr>"
|
||||
dat += "<p>Insert three ingredients and press process to create a beverage. You will be able to select a container for the beverage before processing begins.</p>"
|
||||
dat += "<p>Inserting empty bottles and cans, as well as sheets of glass, plastic, or metal will restock the appropriate container supply.</p>"
|
||||
var/datum/browser/popup = new(user, "bottler", "Bottler Menu", 575, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/bottler/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(bottling)
|
||||
return
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["process"])
|
||||
var/list/choices = list("Glass Bottle" = 1, "Plastic Bottle" = 2, "Metal Can" = 3)
|
||||
var/selection = input("Select a container for your beverage.", "Container") as null|anything in choices
|
||||
if(!selection)
|
||||
return
|
||||
else
|
||||
selection = choices[selection]
|
||||
process_ingredients(selection)
|
||||
|
||||
if(href_list["eject"])
|
||||
var/slot = text2num(href_list["eject"])
|
||||
eject_items(slot)
|
||||
|
||||
if(href_list["dispense"])
|
||||
var/container = text2num(href_list["dispense"])
|
||||
dispense_empty_container(container)
|
||||
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/bottler/update_icon()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "bottler_broken"
|
||||
else if(bottling)
|
||||
icon_state = "bottler_on"
|
||||
else
|
||||
icon_state = "bottler_off"
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
/datum/bottler_recipe
|
||||
var/name = ""
|
||||
var/description = ""
|
||||
var/list/ingredients[3]
|
||||
var/list/tags[3]
|
||||
var/datum/reagent/result = null
|
||||
|
||||
|
||||
/* Example of how a bottler_recipe should look:
|
||||
/datum/bottler_recipe/example
|
||||
name = "Example"
|
||||
description = "This is an example."
|
||||
ingredients = list(thing_1, thing_2, thing_3)
|
||||
tags = list(null, "tag_2", null)
|
||||
result = "water"
|
||||
|
||||
The ingredients list must have 3 non-null entries.
|
||||
The tags list must have 3 entries, using null where a tag is unused.
|
||||
Failing to ensure both lists have EXACTLY 3 entries (unless the system is updated in the future to use a different number) will result in runtimes.
|
||||
There is no excuse to do this wrong now that there is an example for you. --FalseIncarnate
|
||||
*/
|
||||
|
||||
|
||||
/datum/bottler_recipe/Paradise_Punch
|
||||
name = "Paradise Punch"
|
||||
description = "Tastes just how you'd think Paradise would if you could bottle it."
|
||||
ingredients = list(/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown)
|
||||
tags = list("grapes", "banana", "cherries")
|
||||
result = "paradise_punch"
|
||||
|
||||
/datum/bottler_recipe/Applepocalypse
|
||||
name = "Apple-pocalypse"
|
||||
description = "If doomsday came in fruit form, it'd probably be apples."
|
||||
ingredients = list(/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown)
|
||||
tags = list("apple", "apple", "apple")
|
||||
result = "apple-pocalypse"
|
||||
|
||||
/datum/bottler_recipe/Berry_Banned
|
||||
name = "Berry Banned"
|
||||
description = "Reason for ban: Excessive Flavor."
|
||||
ingredients = list(/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown)
|
||||
tags = list("berries", "berries", "berries")
|
||||
result = "berry_banned"
|
||||
|
||||
/datum/bottler_recipe/Berry_Banned2
|
||||
name = "Berry Banned"
|
||||
description = "Reason for ban: Excessive Flavor."
|
||||
ingredients = list(/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown)
|
||||
tags = list("poisonberries", "poisonberries", "poisonberries")
|
||||
result = "berry_banned2"
|
||||
|
||||
/datum/bottler_recipe/Blackeye_Brew
|
||||
name = "Blackeye Brew"
|
||||
description = "Creamy, smooth flavor, just like the bald heads of the masses. Supposedly aged for 30 years."
|
||||
ingredients = list(/obj/item/weapon/reagent_containers/food/drinks/cans/cola,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/icecream)
|
||||
tags = list(null, "sugarcane", null)
|
||||
result = "blackeye_brew"
|
||||
|
||||
/datum/bottler_recipe/Grape_Granade
|
||||
name = "Grape Granade"
|
||||
description = "Exploding with grape flavor and a favorite among ERT members system-wide."
|
||||
ingredients = list(/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/device/flash)
|
||||
tags = list(null, "grapes", null)
|
||||
result = "grape_granade"
|
||||
|
||||
/datum/bottler_recipe/Meteor_Malt
|
||||
name = "Meteor Malt"
|
||||
description = "Soft drinks have been detected on collision course with your tastebuds."
|
||||
ingredients = list(/obj/item/weapon/ore,
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown,
|
||||
/obj/item/weapon/ore)
|
||||
tags = list(null, "wheat", null)
|
||||
result = "meteor_malt"
|
||||
@@ -109,7 +109,7 @@ var/global/datum/controller/process/garbage_collector/garbageCollector
|
||||
hint = D.Destroy()
|
||||
catch(var/exception/e)
|
||||
if(istype(e))
|
||||
gcwarning("qdel() caught runtime destroying [D.type]: [e] in [e.file], line [e.line]")
|
||||
log_runtime(e, D, "Caught by qdel() destroying [D.type]")
|
||||
else
|
||||
gcwarning("qdel() caught runtime destroying [D.type]: [e]")
|
||||
// Destroy runtimed? Panic! Hard delete!
|
||||
@@ -169,7 +169,7 @@ var/global/datum/controller/process/garbage_collector/garbageCollector
|
||||
Destroy()
|
||||
catch(var/exception/e)
|
||||
if(istype(e))
|
||||
gcwarning("Del() caught runtime destroying [type]: [e] in [e.file], line [e.line]")
|
||||
log_runtime(e, src, "Caught by Del() destroying [type]")
|
||||
else
|
||||
gcwarning("Del() caught runtime destroying [type]: [e]")
|
||||
if(del_profiling)
|
||||
|
||||
@@ -251,4 +251,4 @@
|
||||
if(!user.put_in_active_hand(QB))
|
||||
QB.forceMove(get_turf(src))
|
||||
visible_message("<span class='notice'>[user] removes the queen from the apiary.</span>")
|
||||
queen_bee = null
|
||||
queen_bee = null
|
||||
@@ -825,6 +825,7 @@
|
||||
display_name = "grapevines"
|
||||
mutants = list("greengrapes")
|
||||
chems = list("plantmatter" = list(1,10), "sugar" = list(1,5))
|
||||
kitchen_tag = "grapes"
|
||||
preset_icon = "grapes"
|
||||
|
||||
/datum/seed/grapes/New()
|
||||
@@ -1089,6 +1090,7 @@
|
||||
seed_name = "sugarcane"
|
||||
display_name = "sugarcanes"
|
||||
chems = list("sugar" = list(4,5))
|
||||
kitchen_tag = "sugarcane"
|
||||
preset_icon = "sugarcane"
|
||||
|
||||
/datum/seed/sugarcane/New()
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
flags = OPENCONTAINER
|
||||
volume = 100
|
||||
|
||||
hud_possible = list (PLANT_NUTRIENT_HUD, PLANT_WATER_HUD, PLANT_STATUS_HUD, PLANT_HEALTH_HUD, PLANT_TOXIN_HUD, PLANT_PEST_HUD, PLANT_WEED_HUD)
|
||||
|
||||
var/mechanical = 1 // Set to 0 to stop it from drawing the alert lights.
|
||||
var/base_name = "tray"
|
||||
|
||||
@@ -73,10 +75,12 @@
|
||||
if(weedlevel > 0)
|
||||
nymph.reagents.add_reagent("nutriment", weedlevel)
|
||||
weedlevel = 0
|
||||
plant_hud_set_weed()
|
||||
nymph.visible_message("<font color='blue'><b>[nymph]</b> begins rooting through [src], ripping out weeds and eating them noisily.</font>","<font color='blue'>You begin rooting through [src], ripping out weeds and eating them noisily.</font>")
|
||||
else if(nymph.nutrition > 100 && nutrilevel < 10)
|
||||
nymph.nutrition -= ((10-nutrilevel)*5)
|
||||
nutrilevel = 10
|
||||
plant_hud_set_nutrient()
|
||||
nymph.visible_message("<font color='blue'><b>[nymph]</b> secretes a trickle of green liquid, refilling [src].</font>","<font color='blue'>You secrete a trickle of green liquid, refilling [src].</font>")
|
||||
else
|
||||
nymph.visible_message("<font color='blue'><b>[nymph]</b> rolls around in [src] for a bit.</font>","<font color='blue'>You roll around in [src] for a bit.</font>")
|
||||
@@ -85,6 +89,17 @@
|
||||
/obj/machinery/portable_atmospherics/hydroponics/New()
|
||||
..()
|
||||
|
||||
var/datum/atom_hud/data/hydroponic/hydro_hud = huds[DATA_HUD_HYDROPONIC]
|
||||
prepare_huds()
|
||||
hydro_hud.add_to_hud(src)
|
||||
plant_hud_set_nutrient()
|
||||
plant_hud_set_water()
|
||||
plant_hud_set_status()
|
||||
plant_hud_set_health()
|
||||
plant_hud_set_toxin()
|
||||
plant_hud_set_pest()
|
||||
plant_hud_set_weed()
|
||||
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/hydroponics(null)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
|
||||
@@ -101,6 +116,7 @@
|
||||
if(closed_system)
|
||||
flags &= ~OPENCONTAINER
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/upgraded/New()
|
||||
..()
|
||||
component_parts = list()
|
||||
@@ -118,6 +134,8 @@
|
||||
maxnutri = tmp_capacity * 5 // Up to 30
|
||||
//waterlevel = maxwater
|
||||
//nutrilevel = 3
|
||||
plant_hud_set_nutrient()
|
||||
plant_hud_set_water()
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/bullet_act(var/obj/item/projectile/Proj)
|
||||
|
||||
@@ -150,12 +168,18 @@
|
||||
die()
|
||||
check_level_sanity()
|
||||
update_icon()
|
||||
plant_hud_set_status()
|
||||
plant_hud_set_health()
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/proc/die()
|
||||
dead = 1
|
||||
harvest = 0
|
||||
weedlevel += 1 * HYDRO_SPEED_MULTIPLIER
|
||||
pestlevel = 0
|
||||
plant_hud_set_status()
|
||||
plant_hud_set_health()
|
||||
plant_hud_set_weed()
|
||||
plant_hud_set_pest()
|
||||
|
||||
//Harvests the product of a plant.
|
||||
/obj/machinery/portable_atmospherics/hydroponics/proc/harvest(var/mob/user)
|
||||
@@ -233,6 +257,9 @@
|
||||
pestlevel = 0
|
||||
sampled = 0
|
||||
update_icon()
|
||||
plant_hud_set_weed()
|
||||
plant_hud_set_status()
|
||||
plant_hud_set_health()
|
||||
visible_message("<span class='notice'>[src] has been overtaken by [seed.display_name].</span>")
|
||||
|
||||
return
|
||||
@@ -391,6 +418,14 @@
|
||||
toxins = max(0,min(toxins,10))
|
||||
yield_mod = min(100, yield_mod)
|
||||
|
||||
plant_hud_set_nutrient()
|
||||
plant_hud_set_water()
|
||||
plant_hud_set_status()
|
||||
plant_hud_set_health()
|
||||
plant_hud_set_toxin()
|
||||
plant_hud_set_pest()
|
||||
plant_hud_set_weed()
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/proc/mutate_species()
|
||||
|
||||
var/previous_plant = seed.display_name
|
||||
@@ -409,6 +444,9 @@
|
||||
harvest = 0
|
||||
weedlevel = 0
|
||||
|
||||
plant_hud_set_health()
|
||||
plant_hud_set_weed()
|
||||
|
||||
update_icon()
|
||||
visible_message("\red The \blue [previous_plant] \red has suddenly mutated into \blue [seed.display_name]!")
|
||||
|
||||
@@ -585,6 +623,7 @@
|
||||
user.visible_message("<span class='danger'>[user] starts uprooting the weeds.</span>", "<span class='danger'>You remove the weeds from the [src].</span>")
|
||||
weedlevel = 0
|
||||
update_icon()
|
||||
plant_hud_set_weed()
|
||||
else
|
||||
to_chat(user, "<span class='danger'>This plot is completely devoid of weeds. It doesn't need uprooting.</span>")
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
// Bonus chance if the tray is unoccupied.
|
||||
if(waterlevel > 10 && nutrilevel > 2 && prob(isnull(seed) ? 6 : 3))
|
||||
weedlevel += 1 * HYDRO_SPEED_MULTIPLIER
|
||||
plant_hud_set_weed()
|
||||
|
||||
// There's a chance for a weed explosion to happen if the weeds take over.
|
||||
// Plants that are themselves weeds (weed_tolerance > 10) are unaffected.
|
||||
@@ -48,8 +49,10 @@
|
||||
// Maintain tray nutrient and water levels.
|
||||
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0 && nutrilevel > 0 && prob(25))
|
||||
nutrilevel -= max(0,seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) * HYDRO_SPEED_MULTIPLIER)
|
||||
plant_hud_set_nutrient()
|
||||
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 0 && waterlevel > 0 && prob(25))
|
||||
waterlevel -= max(0,seed.get_trait(TRAIT_WATER_CONSUMPTION) * HYDRO_SPEED_MULTIPLIER)
|
||||
plant_hud_set_water()
|
||||
|
||||
// Make sure the plant is not starving or thirsty. Adequate
|
||||
// water and nutrients will cause a plant to become healthier.
|
||||
@@ -91,6 +94,7 @@
|
||||
if(toxins > seed.get_trait(TRAIT_TOXINS_TOLERANCE))
|
||||
health -= toxin_uptake
|
||||
toxins -= toxin_uptake
|
||||
plant_hud_set_toxin()
|
||||
|
||||
// Check for pests and weeds.
|
||||
// Some carnivorous plants happily eat pests.
|
||||
@@ -100,6 +104,7 @@
|
||||
pestlevel -= HYDRO_SPEED_MULTIPLIER
|
||||
else if(pestlevel >= seed.get_trait(TRAIT_PEST_TOLERANCE))
|
||||
health -= HYDRO_SPEED_MULTIPLIER
|
||||
plant_hud_set_pest()
|
||||
|
||||
// Some plants thrive and live off of weeds.
|
||||
if(weedlevel > 0)
|
||||
@@ -108,6 +113,7 @@
|
||||
weedlevel -= HYDRO_SPEED_MULTIPLIER
|
||||
else if(weedlevel >= seed.get_trait(TRAIT_WEED_TOLERANCE))
|
||||
health -= HYDRO_SPEED_MULTIPLIER
|
||||
plant_hud_set_weed()
|
||||
|
||||
// Handle life and death.
|
||||
// If the plant gets too old, begin killing it each cycle
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/obj/item/weapon/storage/bible)
|
||||
|
||||
/obj/structure/bookcase/initialize()
|
||||
..()
|
||||
for(var/obj/item/I in loc)
|
||||
if(is_type_in_list(I, valid_types))
|
||||
I.forceMove(src)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
color = "#000000"
|
||||
icon_state = "light1"
|
||||
auto_init = 0 // doesn't need special init
|
||||
|
||||
var/lum_r
|
||||
var/lum_g
|
||||
@@ -104,4 +105,4 @@
|
||||
if(istype(T))
|
||||
T.lighting_overlay = null
|
||||
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var/on=0
|
||||
|
||||
/obj/machinery/media/receiver/boombox/initialize()
|
||||
..()
|
||||
if(on)
|
||||
update_on()
|
||||
update_icon()
|
||||
@@ -80,4 +81,4 @@
|
||||
if(on)
|
||||
icon_state="wallradio-p"
|
||||
else
|
||||
icon_state="wallradio"
|
||||
icon_state="wallradio"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
var/const/MAX_TEMP=70 // Celsius
|
||||
|
||||
/obj/machinery/media/transmitter/broadcast/initialize()
|
||||
..()
|
||||
testing("[type]/initialize() called!")
|
||||
if(autolink && autolink.len)
|
||||
for(var/obj/machinery/media/source in orange(20, src))
|
||||
|
||||
@@ -249,4 +249,50 @@
|
||||
if(colorindex >= 6)
|
||||
colorindex = 0
|
||||
icon_state = "mobcap[colorindex]"
|
||||
update_icon()
|
||||
update_icon()
|
||||
|
||||
//Fans
|
||||
/obj/structure/fans
|
||||
icon = 'icons/obj/lavaland/survival_pod.dmi'
|
||||
icon_state = "fans"
|
||||
name = "environmental regulation system"
|
||||
desc = "A large machine releasing a constant gust of air."
|
||||
anchored = 1
|
||||
density = 1
|
||||
var/arbitraryatmosblockingvar = 1
|
||||
var/buildstacktype = /obj/item/stack/sheet/metal
|
||||
var/buildstackamount = 5
|
||||
|
||||
/obj/structure/fans/proc/deconstruct()
|
||||
if(buildstacktype)
|
||||
new buildstacktype(loc, buildstackamount)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/fans/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user.visible_message("<span class='warning'>[user] disassembles the fan.</span>", \
|
||||
"<span class='notice'>You start to disassemble the fan...</span>", "You hear clanking and banging noises.")
|
||||
if(do_after(user, 20, target = src))
|
||||
deconstruct()
|
||||
return ..()
|
||||
|
||||
/obj/structure/fans/tiny
|
||||
name = "tiny fan"
|
||||
desc = "A tiny fan, releasing a thin gust of air."
|
||||
layer = TURF_LAYER+0.1
|
||||
density = 0
|
||||
icon_state = "fan_tiny"
|
||||
buildstackamount = 2
|
||||
|
||||
/obj/structure/fans/New(loc)
|
||||
..()
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/structure/fans/Destroy()
|
||||
arbitraryatmosblockingvar = 0
|
||||
air_update_turf(1)
|
||||
return ..()
|
||||
|
||||
/obj/structure/fans/CanAtmosPass(turf/T)
|
||||
return !arbitraryatmosblockingvar
|
||||
@@ -648,7 +648,7 @@
|
||||
newSnack.name = "Synthetic [newSnack.name]"
|
||||
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they vomit [newSnack] from their mouth!")
|
||||
catch(var/exception/e)
|
||||
log_to_dd("Cooking error: [e] in [e.file]:[e.line]")
|
||||
log_runtime(e, src, "Caught in SNPC cooking module")
|
||||
doing &= ~SNPC_SPECIAL
|
||||
// END COOKING MODULE
|
||||
|
||||
|
||||
@@ -1269,13 +1269,17 @@ var/global/list/damage_icon_parts = list()
|
||||
if(wear_suit)
|
||||
if(wear_suit.icon_override)
|
||||
var/icon_path = "[wear_suit.icon_override]"
|
||||
icon_path = "[copytext(icon_path, 1, findtext(icon_path, "/suit.dmi"))]/collar.dmi" //If this file doesn't exist, the end result is that COLLAR_LAYER will be unchanged (empty) so there won't be an issue.
|
||||
var/icon/icon_file = new(icon_path)
|
||||
icon_path = "[copytext(icon_path, 1, findtext(icon_path, "/suit.dmi"))]/collar.dmi" //If this file doesn't exist, the end result is that COLLAR_LAYER will be unchanged (empty).
|
||||
var/icon/icon_file
|
||||
if(fexists(icon_path)) //Just ensuring the nonexistance of a file with the above path won't cause a runtime.
|
||||
icon_file = new(icon_path)
|
||||
standing = image("icon" = icon_file, "icon_state" = "[wear_suit.icon_state]")
|
||||
else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[species.name])
|
||||
var/icon_path = "[wear_suit.sprite_sheets[species.name]]"
|
||||
icon_path = "[copytext(icon_path, 1, findtext(icon_path, "/suit.dmi"))]/collar.dmi" //If this file doesn't exist, the end result is that COLLAR_LAYER will be unchanged (empty) so there won't be an issue.
|
||||
var/icon/icon_file = new(icon_path)
|
||||
icon_path = "[copytext(icon_path, 1, findtext(icon_path, "/suit.dmi"))]/collar.dmi" //If this file doesn't exist, the end result is that COLLAR_LAYER will be unchanged (empty).
|
||||
var/icon/icon_file
|
||||
if(fexists(icon_path)) //Just ensuring the nonexistance of a file with the above path won't cause a runtime.
|
||||
icon_file = new(icon_path)
|
||||
standing = image("icon" = icon_file, "icon_state" = "[wear_suit.icon_state]")
|
||||
else
|
||||
if(wear_suit.icon_state in C.IconStates())
|
||||
|
||||
@@ -815,7 +815,8 @@ var/list/ai_verbs_default = list(
|
||||
"default",
|
||||
"floating face",
|
||||
"xeno queen",
|
||||
"eldritch"
|
||||
"eldritch",
|
||||
"ancient machine"
|
||||
)
|
||||
input = input("Please select a hologram:") as null|anything in icon_list
|
||||
if(input)
|
||||
@@ -829,6 +830,8 @@ var/list/ai_verbs_default = list(
|
||||
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3"))
|
||||
if("eldritch")
|
||||
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo4"))
|
||||
if("ancient machine")
|
||||
holo_icon = getHologramIcon(icon('icons/mob/ancient_machine.dmi', "ancient_machine"))
|
||||
return
|
||||
|
||||
/mob/living/silicon/ai/proc/corereturn()
|
||||
@@ -1040,4 +1043,4 @@ var/list/ai_verbs_default = list(
|
||||
|
||||
eyeobj.setLoc(get_turf(C))
|
||||
client.eye = eyeobj
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
|
||||
|
||||
/mob/living/silicon/robot/drone/Bump(atom/movable/AM as mob|obj, yes)
|
||||
if (!yes || ( \
|
||||
if(!yes || ( \
|
||||
!istype(AM,/obj/machinery/door) && \
|
||||
!istype(AM,/obj/machinery/recharge_station) && \
|
||||
!istype(AM,/obj/machinery/disposal/deliveryChute) && \
|
||||
|
||||
@@ -315,7 +315,7 @@ var/list/robot_verbs_default = list(
|
||||
if(camera && "Robots" in camera.network)
|
||||
camera.network.Add("Medical")
|
||||
module_sprites["Basic"] = "Medbot"
|
||||
module_sprites["Standard"] = "surgeon"
|
||||
module_sprites["Surgeon"] = "surgeon"
|
||||
module_sprites["Advanced Droid"] = "droid-medical"
|
||||
module_sprites["Needles"] = "medicalrobot"
|
||||
module_sprites["Standard"] = "robotMedi"
|
||||
@@ -1486,4 +1486,4 @@ var/list/robot_verbs_default = list(
|
||||
if(1)
|
||||
disable_component("comms", 160)
|
||||
if(2)
|
||||
disable_component("comms", 60)
|
||||
disable_component("comms", 60)
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
if(!item_to_add)
|
||||
usr.visible_message("[usr] pets [src].","<span class='notice'>You rest your hand on [src]'s back for a moment.</span>")
|
||||
return
|
||||
if(istype(item_to_add,/obj/item/weapon/c4)) // last thing he ever wears, I guess
|
||||
if(istype(item_to_add,/obj/item/weapon/grenade/plastic/c4)) // last thing he ever wears, I guess
|
||||
item_to_add.afterattack(src,usr,1)
|
||||
return
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
//Many hats added, Some will probably be removed, just want to see which ones are popular.
|
||||
/mob/living/simple_animal/pet/corgi/proc/place_on_head(obj/item/item_to_add, var/mob/user as mob)
|
||||
|
||||
if(istype(item_to_add,/obj/item/weapon/c4)) // last thing he ever wears, I guess
|
||||
if(istype(item_to_add,/obj/item/weapon/grenade/plastic/c4)) // last thing he ever wears, I guess
|
||||
item_to_add.afterattack(src,user,1)
|
||||
return
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
var/alerted = 0
|
||||
var/ore_eaten = 1
|
||||
var/chase_time = 100
|
||||
var/will_burrow = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/goldgrub/New()
|
||||
..()
|
||||
@@ -170,7 +171,7 @@
|
||||
visible_message("<span class='notice'>The ore was swallowed whole!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time
|
||||
if(!alerted)
|
||||
if(!alerted && will_burrow)
|
||||
alerted = 1
|
||||
spawn(chase_time)
|
||||
if(alerted)
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
explosive.forceMove(user.loc)
|
||||
explosive = null
|
||||
qdel(src)
|
||||
if(istype(I, /obj/item/weapon/grenade) || istype(I, /obj/item/weapon/c4))
|
||||
if(istype(I, /obj/item/weapon/grenade) || istype(I, /obj/item/weapon/grenade/plastic/c4))
|
||||
if(explosive)
|
||||
to_chat(user, "<span class='warning'>There is already a device attached behind \the [src], remove it first.</span>")
|
||||
return 1
|
||||
@@ -268,11 +268,6 @@
|
||||
var/obj/item/weapon/grenade/G = explosive
|
||||
explosive = null
|
||||
G.prime()
|
||||
else if(istype(explosive, /obj/item/weapon/c4))
|
||||
var/obj/item/weapon/c4/C = explosive
|
||||
explosive = null
|
||||
C.target = get_step(get_turf(src), dir)
|
||||
C.explode(get_turf(loc))
|
||||
|
||||
/obj/structure/sign/picture_frame/proc/toggle_tilt(mob/user)
|
||||
if(!isliving(usr) || usr.stat)
|
||||
@@ -312,4 +307,4 @@
|
||||
/obj/structure/sign/picture_frame/hear_message(mob/living/M as mob, msg)
|
||||
..()
|
||||
for(var/obj/O in contents)
|
||||
O.hear_message(M, msg)
|
||||
O.hear_message(M, msg)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define EMAG_DELAY 50
|
||||
|
||||
/obj/machinery/photocopier
|
||||
name = "photocopier"
|
||||
icon = 'icons/obj/library.dmi'
|
||||
@@ -9,6 +11,7 @@
|
||||
idle_power_usage = 30
|
||||
active_power_usage = 200
|
||||
power_channel = EQUIP
|
||||
var/emag_cooldown
|
||||
atom_say_verb = "bleeps"
|
||||
var/obj/item/copyitem = null //what's in the copier!
|
||||
var/copies = 1 //how many copies to print!
|
||||
@@ -51,6 +54,9 @@
|
||||
if(toner <= 0)
|
||||
break
|
||||
|
||||
if(emag_cooldown > world.time)
|
||||
return
|
||||
|
||||
if(istype(copyitem, /obj/item/weapon/paper))
|
||||
copy(copyitem)
|
||||
sleep(15)
|
||||
@@ -237,9 +243,11 @@
|
||||
G.take_damage(0, 30)
|
||||
spawn(20)
|
||||
H.emote("scream")
|
||||
emag_cooldown = world.time + EMAG_DELAY
|
||||
else
|
||||
to_chat(ass, "<span class='notice'>Something smells toasty...</span>")
|
||||
ass.apply_damage(30, BURN)
|
||||
emag_cooldown = world.time + EMAG_DELAY
|
||||
if(ishuman(ass)) //Suit checks are in check_ass
|
||||
var/mob/living/carbon/human/H = ass
|
||||
temp_img = icon('icons/obj/butts.dmi', H.species.butt_sprite)
|
||||
@@ -334,3 +342,5 @@
|
||||
name = "toner cartridge"
|
||||
icon_state = "tonercartridge"
|
||||
var/toner_amount = 30
|
||||
|
||||
#undef EMAG_DELAY
|
||||
|
||||
@@ -99,11 +99,22 @@
|
||||
var/global/list/status_overlays_lighting
|
||||
var/global/list/status_overlays_environ
|
||||
var/indestructible = 0 // If set, prevents aliens from destroying it
|
||||
var/keep_preset_name = 0
|
||||
|
||||
var/report_power_alarm = 1
|
||||
|
||||
var/shock_proof = 0 //if set to 1, this APC will not arc bolts of electricity if it's overloaded.
|
||||
|
||||
/obj/machinery/power/apc/worn_out
|
||||
name = "\improper Worn out APC"
|
||||
keep_preset_name = 1
|
||||
locked = 0
|
||||
environ = 0
|
||||
equipment = 0
|
||||
lighting = 0
|
||||
operating = 0
|
||||
|
||||
|
||||
/obj/machinery/power/apc/noalarm
|
||||
report_power_alarm = 0
|
||||
|
||||
@@ -192,15 +203,19 @@
|
||||
cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
|
||||
cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
|
||||
|
||||
var/area/A = src.loc.loc
|
||||
var/area/A = get_area(src)
|
||||
|
||||
|
||||
//if area isn't specified use current
|
||||
if(isarea(A) && src.areastring == null)
|
||||
src.area = A
|
||||
if(keep_preset_name)
|
||||
if(isarea(A))
|
||||
area = A
|
||||
// no-op, keep the name
|
||||
else if(isarea(A) && src.areastring == null)
|
||||
area = A
|
||||
name = "\improper [area.name] APC"
|
||||
else
|
||||
src.area = get_area_name(areastring)
|
||||
area = get_area_name(areastring)
|
||||
name = "\improper [area.name] APC"
|
||||
area.apc |= src
|
||||
update_icon()
|
||||
@@ -623,7 +638,7 @@
|
||||
else
|
||||
if(istype(user, /mob/living/silicon))
|
||||
return src.attack_hand(user)
|
||||
if (!opened && wiresexposed && \
|
||||
if(!opened && wiresexposed && \
|
||||
(istype(W, /obj/item/device/multitool) || \
|
||||
istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler)))
|
||||
return src.attack_hand(user)
|
||||
@@ -853,7 +868,7 @@
|
||||
if(istype(user, /mob/living/silicon))
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
var/mob/living/silicon/robot/robot = user
|
||||
if ( \
|
||||
if( \
|
||||
src.aidisabled || \
|
||||
malfhack && istype(malfai) && \
|
||||
( \
|
||||
@@ -1382,4 +1397,4 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
#undef APC_UPDATE_ICON_COOLDOWN
|
||||
#undef APC_UPDATE_ICON_COOLDOWN
|
||||
|
||||
@@ -82,6 +82,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
|
||||
//
|
||||
|
||||
/obj/machinery/gravity_generator/main/station/initialize()
|
||||
..()
|
||||
setup_parts()
|
||||
middle.overlays += "activated"
|
||||
update_list()
|
||||
@@ -215,17 +216,17 @@ var/const/GRAV_NEEDS_WRENCH = 3
|
||||
/obj/machinery/gravity_generator/main/attack_hand(mob/user as mob)
|
||||
if(!..())
|
||||
return interact(user)
|
||||
|
||||
|
||||
/obj/machinery/gravity_generator/main/attack_ai(mob/user as mob)
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/gravity_generator/main/attack_ghost(mob/user as mob)
|
||||
return interact(user)
|
||||
|
||||
/obj/machinery/gravity_generator/main/interact(mob/user as mob)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
|
||||
var/dat = "Gravity Generator Breaker: "
|
||||
if(breaker)
|
||||
dat += "<span class='linkOn'>ON</span> <A href='?src=\ref[src];gentoggle=1'>OFF</A>"
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
var/redeem_immediately = 0 // redeem immediately for holding cell
|
||||
|
||||
/obj/machinery/treadmill_monitor/initialize()
|
||||
..()
|
||||
if(id)
|
||||
for(var/obj/machinery/power/treadmill/T in machines)
|
||||
if(T.id == id)
|
||||
@@ -222,4 +223,4 @@
|
||||
#undef FONT_SIZE
|
||||
#undef FONT_COLOR
|
||||
#undef FONT_STYLE
|
||||
#undef CHARS_PER_LINE
|
||||
#undef CHARS_PER_LINE
|
||||
|
||||
@@ -655,25 +655,41 @@
|
||||
else if(href_list["change_pill"])
|
||||
#define MAX_PILL_SPRITE 20 //max icon state of the pill sprites
|
||||
var/dat = "<table>"
|
||||
var/j = 0
|
||||
for(var/i = 1 to MAX_PILL_SPRITE)
|
||||
dat += "<tr><td><a href=\"?src=\ref[src]&pill_sprite=[i]\"><img src=\"pill[i].png\" /></a></td></tr>"
|
||||
j++
|
||||
if(j == 1)
|
||||
dat += "<tr>"
|
||||
dat += "<td><a href=\"?src=\ref[src]&pill_sprite=[i]\"><img src=\"pill[i].png\" /></a></td>"
|
||||
if(j == 5)
|
||||
dat += "</tr>"
|
||||
j = 0
|
||||
dat += "</table>"
|
||||
usr << browse(dat, "window=chem_master")
|
||||
usr << browse(dat, "window=chem_master_iconsel;size=225x193")
|
||||
return
|
||||
else if(href_list["change_bottle"])
|
||||
#define MAX_BOTTLE_SPRITE 20 //max icon state of the bottle sprites
|
||||
var/dat = "<table>"
|
||||
var/j = 0
|
||||
for(var/i = 1 to MAX_BOTTLE_SPRITE)
|
||||
dat += "<tr><td><a href=\"?src=\ref[src]&bottle_sprite=[i]\"><img src=\"bottle[i].png\" /></a></td></tr>"
|
||||
j++
|
||||
if(j == 1)
|
||||
dat += "<tr>"
|
||||
dat += "<td><a href=\"?src=\ref[src]&bottle_sprite=[i]\"><img src=\"bottle[i].png\" /></a></td>"
|
||||
if(j == 5)
|
||||
dat += "</tr>"
|
||||
j = 0
|
||||
dat += "</table>"
|
||||
usr << browse(dat, "window=chem_master")
|
||||
usr << browse(dat, "window=chem_master_iconsel;size=225x193")
|
||||
return
|
||||
else if(href_list["pill_sprite"])
|
||||
pillsprite = href_list["pill_sprite"]
|
||||
usr << browse(null, "window=chem_master_iconsel")
|
||||
else if(href_list["bottle_sprite"])
|
||||
bottlesprite = href_list["bottle_sprite"]
|
||||
usr << browse(null, "window=chem_master_iconsel")
|
||||
|
||||
. = 1
|
||||
nanomanager.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/chem_master/attack_ai(mob/user as mob)
|
||||
@@ -689,13 +705,10 @@
|
||||
return
|
||||
|
||||
/obj/machinery/chem_master/ui_interact(mob/user, ui_key="main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(!(user.client in has_sprites))
|
||||
spawn()
|
||||
has_sprites += user.client
|
||||
for(var/i = 1 to MAX_PILL_SPRITE)
|
||||
usr << browse_rsc(icon('icons/obj/chemical.dmi', "pill" + num2text(i)), "pill[i].png")
|
||||
for(var/i = 1 to MAX_BOTTLE_SPRITE)
|
||||
usr << browse_rsc(icon('icons/obj/chemical.dmi', "bottle" + num2text(i)), "bottle[i].png")
|
||||
|
||||
var/datum/asset/chem_master/assets = get_asset_datum(/datum/asset/chem_master)
|
||||
assets.send(user)
|
||||
|
||||
var/data = list()
|
||||
|
||||
data["condi"] = condi
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
/*
|
||||
Paradise Pop reagents
|
||||
Created through the bottler machine via bottler_recipes, not through standard reactions
|
||||
Eventually will have special effects (minor mostly) tied to their reagents, but for now are purely for flavor
|
||||
|
||||
Make sure to yell at me to finish giving them effects later
|
||||
-FalseIncarnate
|
||||
*/
|
||||
|
||||
|
||||
//Paradise Punch: No effect, aside from maybe messages about how tasty it is or something
|
||||
/datum/reagent/paradise_punch
|
||||
name = "Paradise Punch"
|
||||
id = "paradise_punch"
|
||||
description = "Tastes just how you'd think Paradise would if you could bottle it."
|
||||
reagent_state = LIQUID
|
||||
color = "#cc0044"
|
||||
|
||||
//Apple-pocalypse: Low chance to cause a goonchem vortex that pulls things within a very small radius (2 tiles?) towards the drinker
|
||||
/datum/reagent/apple_pocalypse
|
||||
name = "Apple-pocalypse"
|
||||
id = "apple-pocalypse"
|
||||
description = "If doomsday came in fruit form, it'd probably be apples."
|
||||
reagent_state = LIQUID
|
||||
color = "#44FF44"
|
||||
|
||||
//Berry Banned: This one is tasty and safe to drink, might have a low chance of healing a random damage type?
|
||||
/datum/reagent/berry_banned
|
||||
name = "Berry Banned"
|
||||
id = "berry_banned"
|
||||
description = "Reason for ban: Excessive Flavor."
|
||||
reagent_state = LIQUID
|
||||
color = "#FF44FF"
|
||||
|
||||
//Berry Banned 2: This one is tasty and toxic. Deals toxin damage and MAYBE plays the "BWOINK!" sound if it kills someone?
|
||||
/datum/reagent/berry_banned2
|
||||
name = "Berry Banned"
|
||||
id = "berry_banned2"
|
||||
description = "Reason for ban: Excessive Flavor."
|
||||
reagent_state = LIQUID
|
||||
color = "#FF44FF"
|
||||
|
||||
//Blackeye Brew: Chance to make the drinker say greytider-themed things like "I thought clown was valid!"
|
||||
/datum/reagent/blackeye_brew
|
||||
name = "Blackeye Brew"
|
||||
id = "blackeye_brew"
|
||||
description = "Creamy, smooth flavor, just like the bald heads of the masses. Supposedly aged for 30 years."
|
||||
reagent_state = LIQUID
|
||||
color = "#4d2600"
|
||||
|
||||
//Grape Granade: causes the drinker to sometimes burp, has a low chance to cause a goonchem vortex that pushes things within a very small radius (1-2 tiles) away from the drinker
|
||||
/datum/reagent/grape_granade
|
||||
name = "Grape Granade"
|
||||
id = "grape_granade"
|
||||
description = "Exploding with grape flavor and a favorite among ERT members system-wide."
|
||||
reagent_state = LIQUID
|
||||
color = "#9933ff"
|
||||
|
||||
//Meteor Malt: Sometimes causes screen shakes for the drinker like a meteor impact, low chance to add 1-5 units of a random mineral reagent to the drinker's blood (iron, copper, silver, gold, uranium, carbon, etc)
|
||||
/datum/reagent/meteor_malt
|
||||
name = "Meteor Malt"
|
||||
id = "meteor_malt"
|
||||
description = "Soft drinks have been detected on collision course with your tastebuds."
|
||||
reagent_state = LIQUID
|
||||
color = "#cc9900"
|
||||
@@ -1,6 +1,7 @@
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans
|
||||
var canopened = 0
|
||||
var is_glass = 0
|
||||
var/canopened = 0
|
||||
var/is_glass = 0
|
||||
var/is_plastic = 0
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/New()
|
||||
..()
|
||||
@@ -16,6 +17,9 @@
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/proc/crush(mob/user)
|
||||
var/obj/item/trash/can/crushed_can = new /obj/item/trash/can(user.loc)
|
||||
crushed_can.icon_state = icon_state
|
||||
//inherit material vars for recycling purposes
|
||||
crushed_can.is_glass = is_glass
|
||||
crushed_can.is_plastic = is_plastic
|
||||
if(is_glass)
|
||||
playsound(user.loc, 'sound/effects/Glassbr3.ogg', rand(10, 50), 1)
|
||||
crushed_can.name = "broken bottle"
|
||||
@@ -85,6 +89,7 @@
|
||||
name = "Bottled Water"
|
||||
desc = "Introduced to the vending machines by Skrellian request, this water comes straight from the Martian poles."
|
||||
icon_state = "waterbottle"
|
||||
is_plastic = 1
|
||||
New()
|
||||
..()
|
||||
reagents.add_reagent("water", 30)
|
||||
@@ -259,3 +264,62 @@
|
||||
New()
|
||||
..()
|
||||
reagents.add_reagent("synthanol", 50)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler
|
||||
name = "generic beverage container"
|
||||
desc = "this shouldn't ever be spawned. shame on you"
|
||||
icon_state = "glass_bottle"
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/on_reagent_change()
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/pickup(mob/user)
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/dropped(mob/user)
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/attack_hand()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/update_icon()
|
||||
overlays.Cut()
|
||||
|
||||
if(reagents.total_volume)
|
||||
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10")
|
||||
|
||||
switch(round(reagents.total_volume))
|
||||
if(0 to 9)
|
||||
filling.icon_state = "[icon_state]-10"
|
||||
if(10 to 19)
|
||||
filling.icon_state = "[icon_state]10"
|
||||
if(20 to 29)
|
||||
filling.icon_state = "[icon_state]20"
|
||||
if(30 to 39)
|
||||
filling.icon_state = "[icon_state]30"
|
||||
if(40 to 49)
|
||||
filling.icon_state = "[icon_state]40"
|
||||
if(50 to INFINITY)
|
||||
filling.icon_state = "[icon_state]50"
|
||||
|
||||
filling.icon += mix_color_from_reagents(reagents.reagent_list)
|
||||
overlays += filling
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/glass_bottle
|
||||
name = "glass bottle"
|
||||
desc = "A glass bottle suitable for beverages."
|
||||
icon_state = "glass_bottle"
|
||||
is_glass = 1
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/plastic_bottle
|
||||
name = "plastic bottle"
|
||||
desc = "A plastic bottle suitable for beverages."
|
||||
icon_state = "plastic_bottle"
|
||||
is_plastic = 1
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/cans/bottler/metal_can
|
||||
name = "metal can"
|
||||
desc = "A metal can suitable for beverages."
|
||||
icon_state = "metal_can"
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
return
|
||||
else
|
||||
return 1
|
||||
if ( \
|
||||
if( \
|
||||
!isturf(src.loc) || \
|
||||
!(locate(/obj/structure/table) in src.loc) && \
|
||||
!(locate(/obj/machinery/optable) in src.loc) && \
|
||||
@@ -712,6 +712,18 @@
|
||||
reagents.add_reagent("toxin", 3)
|
||||
bitesize = 3
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/lizardmeat
|
||||
name = "mutant lizard meat"
|
||||
desc = "Seems to be a slab of meat from some mutant lizard thing?"
|
||||
icon_state = "xenomeat"
|
||||
filling_color = "#43DE18"
|
||||
|
||||
New()
|
||||
..()
|
||||
reagents.add_reagent("protein", 3)
|
||||
reagents.add_reagent("toxin", 3)
|
||||
bitesize = 3
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/spiderleg
|
||||
name = "spider leg"
|
||||
desc = "A still twitching leg of a giant spider... you don't really want to eat this, do you?"
|
||||
|
||||
@@ -205,13 +205,20 @@
|
||||
|
||||
var/percent = round((reagents.total_volume / volume) * 100)
|
||||
switch(percent)
|
||||
if(0 to 9) filling.icon_state = "[icon_state]-10"
|
||||
if(10 to 24) filling.icon_state = "[icon_state]10"
|
||||
if(25 to 49) filling.icon_state = "[icon_state]25"
|
||||
if(50 to 74) filling.icon_state = "[icon_state]50"
|
||||
if(75 to 79) filling.icon_state = "[icon_state]75"
|
||||
if(80 to 90) filling.icon_state = "[icon_state]80"
|
||||
if(91 to INFINITY) filling.icon_state = "[icon_state]100"
|
||||
if(0 to 9)
|
||||
filling.icon_state = "[icon_state]-10"
|
||||
if(10 to 24)
|
||||
filling.icon_state = "[icon_state]10"
|
||||
if(25 to 49)
|
||||
filling.icon_state = "[icon_state]25"
|
||||
if(50 to 74)
|
||||
filling.icon_state = "[icon_state]50"
|
||||
if(75 to 79)
|
||||
filling.icon_state = "[icon_state]75"
|
||||
if(80 to 90)
|
||||
filling.icon_state = "[icon_state]80"
|
||||
if(91 to INFINITY)
|
||||
filling.icon_state = "[icon_state]100"
|
||||
|
||||
filling.icon += mix_color_from_reagents(reagents.reagent_list)
|
||||
overlays += filling
|
||||
|
||||
@@ -21,6 +21,16 @@
|
||||
build_path = /obj/item/clothing/glasses/hud/health
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/health_hud_night
|
||||
name = "Night Vision Health Scanner HUD"
|
||||
desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness."
|
||||
id = "health_hud_night"
|
||||
req_tech = list("biotech" = 4, "magnets" = 5)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_URANIUM = 1000, MAT_SILVER = 250)
|
||||
build_path = /obj/item/clothing/glasses/hud/health/night
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/magboots
|
||||
name = "Magnetic Boots"
|
||||
desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle."
|
||||
@@ -41,14 +51,14 @@
|
||||
build_path = /obj/item/clothing/glasses/night
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/health_hud_night
|
||||
name = "Night Vision Health Scanner HUD"
|
||||
desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness."
|
||||
id = "health_hud_night"
|
||||
req_tech = list("biotech" = 4, "magnets" = 5)
|
||||
/datum/design/security_hud
|
||||
name = "Security HUD"
|
||||
desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status."
|
||||
id = "security_hud"
|
||||
req_tech = list("magnets" = 3, "combat" = 2)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 200, MAT_GLASS = 200, MAT_URANIUM = 1000, MAT_SILVER = 250)
|
||||
build_path = /obj/item/clothing/glasses/hud/health/night
|
||||
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
|
||||
build_path = /obj/item/clothing/glasses/hud/security
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/security_hud_night
|
||||
@@ -61,16 +71,6 @@
|
||||
build_path = /obj/item/clothing/glasses/hud/security/night
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/nvgmesons
|
||||
name = "Night Vision Optical Meson Scanners"
|
||||
desc = "Prototype meson scanners fitted with an extra sensor which amplifies the visible light spectrum and overlays it to the UHD display."
|
||||
id = "nvgmesons"
|
||||
req_tech = list("materials" = 5, "magnets" = 5, "engineering" = 4)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 300, MAT_GLASS = 400, MAT_PLASMA = 250, MAT_URANIUM = 1000)
|
||||
build_path = /obj/item/clothing/glasses/meson/night
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/mesons
|
||||
name = "Optical Meson Scanners"
|
||||
desc = "Used for seeing walls, floors, and stuff through anything."
|
||||
@@ -81,14 +81,14 @@
|
||||
build_path = /obj/item/clothing/glasses/meson
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/security_hud
|
||||
name = "Security HUD"
|
||||
desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status."
|
||||
id = "security_hud"
|
||||
req_tech = list("magnets" = 3, "combat" = 2)
|
||||
/datum/design/nvgmesons
|
||||
name = "Night Vision Optical Meson Scanners"
|
||||
desc = "Prototype meson scanners fitted with an extra sensor which amplifies the visible light spectrum and overlays it to the UHD display."
|
||||
id = "nvgmesons"
|
||||
req_tech = list("materials" = 5, "magnets" = 5, "engineering" = 4)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 50, MAT_GLASS = 50)
|
||||
build_path = /obj/item/clothing/glasses/hud/security
|
||||
materials = list(MAT_METAL = 300, MAT_GLASS = 400, MAT_PLASMA = 250, MAT_URANIUM = 1000)
|
||||
build_path = /obj/item/clothing/glasses/meson/night
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/air_horn
|
||||
@@ -170,3 +170,23 @@
|
||||
materials = list("$metal" = 200, "$glass" = 200, "$uranium" = 1000, "$plasma" = 300)
|
||||
build_path = /obj/item/clothing/glasses/hud/diagnostic/night
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/hydroponic_hud
|
||||
name = "Hydroponic HUD"
|
||||
desc = "A HUD used to analyze the health and status of plants growing in hydro trays and soil."
|
||||
id = "hydroponic_hud"
|
||||
req_tech = list("magnets" = 3, "biotech" = 3)
|
||||
build_type = PROTOLATHE
|
||||
materials = list("$metal" = 50, "$glass" = 50)
|
||||
build_path = /obj/item/clothing/glasses/hud/hydroponic
|
||||
category = list("Equipment")
|
||||
|
||||
/datum/design/hydroponic_hud_night
|
||||
name = "Night Vision Hydroponic HUD"
|
||||
desc = "A HUD used to analyze the health and status of plants growing in low-light environments."
|
||||
id = "hydroponic_hud_night"
|
||||
req_tech = list("magnets" = 5, "biotech" = 4)
|
||||
build_type = PROTOLATHE
|
||||
materials = list("$metal" = 200, "$glass" = 200, "$uranium" = 1000, "$plasma" = 200)
|
||||
build_path = /obj/item/clothing/glasses/hud/hydroponic/night
|
||||
category = list("Equipment")
|
||||
@@ -296,9 +296,7 @@
|
||||
if(20)
|
||||
//arcane clothing
|
||||
apply_prefix = 0
|
||||
var/list/possible_spawns = list(/obj/item/clothing/head/culthood,
|
||||
/obj/item/clothing/head/magus,
|
||||
/obj/item/clothing/head/culthood/alt,
|
||||
var/list/possible_spawns = list(/obj/item/clothing/head/magus,
|
||||
/obj/item/clothing/head/helmet/space/cult)
|
||||
|
||||
var/new_type = pick(possible_spawns)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//Parent types
|
||||
|
||||
/area/ruin/
|
||||
name = "\improper Unexplored Location"
|
||||
icon_state = "away"
|
||||
has_gravity = 1
|
||||
there_can_be_many = 1
|
||||
|
||||
|
||||
/area/ruin/unpowered
|
||||
always_unpowered = 0
|
||||
|
||||
/area/ruin/unpowered/no_grav
|
||||
has_gravity = 0
|
||||
|
||||
/area/ruin/powered
|
||||
requires_power = 0
|
||||
|
||||
|
||||
|
||||
|
||||
//Areas
|
||||
|
||||
/area/ruin/unpowered/no_grav/way_home
|
||||
name = "\improper Salvation"
|
||||
icon_state = "away"
|
||||
|
||||
/area/ruin/powered/snow_biodome
|
||||
|
||||
/area/ruin/powered/golem_ship
|
||||
name = "Free Golem Ship"
|
||||
|
||||
// Ruins of "onehalf" ship
|
||||
/area/ruin/onehalf/hallway
|
||||
name = "Hallway"
|
||||
icon_state = "hallC"
|
||||
|
||||
|
||||
/area/ruin/onehalf/drone_bay
|
||||
name = "Mining Drone Bay"
|
||||
icon_state = "engine"
|
||||
|
||||
/area/ruin/onehalf/dorms_med
|
||||
name = "Crew Quarters"
|
||||
icon_state = "Sleep"
|
||||
|
||||
/area/ruin/onehalf/bridge
|
||||
name = "Bridge"
|
||||
icon_state = "bridge"
|
||||
@@ -843,7 +843,7 @@
|
||||
name = "\improper Airtight plastic flaps"
|
||||
desc = "Heavy duty, airtight, plastic flaps."
|
||||
|
||||
/obj/structure/plasticflaps/mining/New()
|
||||
/obj/structure/plasticflaps/mining/initialize()
|
||||
air_update_turf(1)
|
||||
..()
|
||||
|
||||
@@ -857,4 +857,4 @@
|
||||
#undef ORDER_SCREEN_WIDTH
|
||||
#undef ORDER_SCREEN_HEIGHT
|
||||
#undef SUPPLY_SCREEN_WIDTH
|
||||
#undef SUPPLY_SCREEN_HEIGHT
|
||||
#undef SUPPLY_SCREEN_HEIGHT
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/datum/zlevel
|
||||
var/flags = 0
|
||||
var/dirt_count = 0
|
||||
var/zpos
|
||||
var/list/init_list = list()
|
||||
|
||||
/datum/zlevel/New(z)
|
||||
zpos = z
|
||||
|
||||
/datum/zlevel/proc/resume_init()
|
||||
if(dirt_count > 0)
|
||||
throw EXCEPTION("Init told to resume when z-level still dirty. Z level: '[zpos]'")
|
||||
log_debug("Releasing freeze on z-level '[zpos]'!")
|
||||
log_debug("Beginning initialization!")
|
||||
var/list/our_atoms = init_list // OURS NOW!!! (Keeping this list to ourselves will prevent hijack)
|
||||
init_list = list()
|
||||
var/list/late_maps = list()
|
||||
var/list/pipes = list()
|
||||
var/list/cables = list()
|
||||
var/watch = start_watch()
|
||||
for(var/schmoo in our_atoms)
|
||||
var/atom/movable/AM = schmoo
|
||||
if(AM) // to catch stuff like the nuke disk that no longer exists
|
||||
|
||||
// This can mess with our state - we leave these for last
|
||||
if(istype(AM, /obj/effect/landmark/map_loader))
|
||||
late_maps.Add(AM)
|
||||
continue
|
||||
AM.initialize()
|
||||
if(istype(AM, /obj/machinery/atmospherics))
|
||||
pipes.Add(AM)
|
||||
else if(istype(AM, /obj/structure/cable))
|
||||
cables.Add(AM)
|
||||
log_debug("Primary initialization finished in [stop_watch(watch)]s.")
|
||||
our_atoms.Cut()
|
||||
if(pipes.len)
|
||||
do_pipes(pipes)
|
||||
if(cables.len)
|
||||
do_cables(cables)
|
||||
if(late_maps.len)
|
||||
do_late_maps(late_maps)
|
||||
|
||||
/datum/zlevel/proc/do_pipes(list/pipes)
|
||||
var/watch = start_watch()
|
||||
log_debug("Building pipenets on z-level '[zpos]'!")
|
||||
for(var/schmoo in pipes)
|
||||
var/obj/machinery/atmospherics/machine = schmoo
|
||||
if(machine)
|
||||
machine.build_network()
|
||||
pipes.Cut()
|
||||
log_debug("Took [stop_watch(watch)]s")
|
||||
|
||||
/datum/zlevel/proc/do_cables(list/cables)
|
||||
var/watch = start_watch()
|
||||
log_debug("Building powernets on z-level '[zpos]'!")
|
||||
for(var/schmoo in cables)
|
||||
var/obj/structure/cable/C = schmoo
|
||||
if(C)
|
||||
makepowernet_for(C)
|
||||
cables.Cut()
|
||||
log_debug("Took [stop_watch(watch)]s")
|
||||
|
||||
/datum/zlevel/proc/do_late_maps(list/late_maps)
|
||||
var/watch = start_watch()
|
||||
log_debug("Loading map templates on z-level '[zpos]'!")
|
||||
zlevels.add_dirt(zpos) // Let's not repeatedly resume init for each template
|
||||
for(var/schmoo in late_maps)
|
||||
var/obj/effect/landmark/map_loader/ML = schmoo
|
||||
if(ML)
|
||||
ML.initialize()
|
||||
late_maps.Cut()
|
||||
zlevels.remove_dirt(zpos)
|
||||
log_debug("Took [stop_watch(watch)]s")
|
||||
@@ -0,0 +1,89 @@
|
||||
var/global/datum/zlev_manager/zlevels = new
|
||||
|
||||
/datum/zlev_manager
|
||||
// A list of z-levels
|
||||
var/list/z_list = list()
|
||||
|
||||
|
||||
// Populate our z level list
|
||||
/datum/zlev_manager/proc/initialize()
|
||||
z_list.len = world.maxz
|
||||
for(var/i = 1, i <= world.maxz, i++)
|
||||
z_list[i] = new /datum/zlevel(i)
|
||||
|
||||
|
||||
|
||||
/datum/zlev_manager/proc/get_zlev(z)
|
||||
if(z < 1)
|
||||
throw EXCEPTION("Non-positive z level given!")
|
||||
else if(z > z_list.len)
|
||||
throw EXCEPTION("Untracked z level: '[z]'")
|
||||
else
|
||||
return z_list[z]
|
||||
|
||||
// For when you need the z-level to be at a certain point
|
||||
/datum/zlev_manager/proc/increase_max_zlevel_to(new_maxz)
|
||||
if(world.maxz>=new_maxz)
|
||||
return
|
||||
while(world.maxz<new_maxz)
|
||||
add_new_zlevel()
|
||||
|
||||
// Increments the max z-level by one
|
||||
// For convenience's sake returns the z-level added
|
||||
/datum/zlev_manager/proc/add_new_zlevel()
|
||||
world.maxz++
|
||||
var/our_z = world.maxz
|
||||
z_list.len++
|
||||
z_list[our_z] = new /datum/zlevel(our_z)
|
||||
return our_z
|
||||
|
||||
/datum/zlev_manager/proc/cut_levels_downto(new_maxz)
|
||||
if(world.maxz <= new_maxz)
|
||||
return
|
||||
while(world.maxz>new_maxz)
|
||||
kill_topmost_zlevel()
|
||||
|
||||
// Decrements the max z-level by one
|
||||
// not normally used, but hey the swapmap loader wanted it
|
||||
/datum/zlev_manager/proc/kill_topmost_zlevel()
|
||||
var/our_z = world.maxz
|
||||
qdel(z_list[our_z])
|
||||
z_list.len--
|
||||
world.maxz--
|
||||
|
||||
/*
|
||||
* "Dirt" management
|
||||
* "Dirt" is used to keep track of whether a z level should automatically have
|
||||
* stuff on it initialize or not - the map loaders, when set to defer init, place
|
||||
* a freeze on the z levels they touch so as to prevent atmos from exploding,
|
||||
* among other things
|
||||
*/
|
||||
|
||||
|
||||
// Returns whether the given z level has a freeze on initialization
|
||||
/datum/zlev_manager/proc/is_zlevel_dirty(z)
|
||||
var/datum/zlevel/our_z = get_zlev(z)
|
||||
return (our_z.dirt_count > 0)
|
||||
|
||||
|
||||
// Increases the dirt count on a z level
|
||||
/datum/zlev_manager/proc/add_dirt(z)
|
||||
var/datum/zlevel/our_z = get_zlev(z)
|
||||
if(our_z.dirt_count == 0)
|
||||
log_debug("Placing an init freeze on z-level '[our_z.zpos]'!")
|
||||
our_z.dirt_count++
|
||||
|
||||
|
||||
// Decreases the dirt count on a z level
|
||||
/datum/zlev_manager/proc/remove_dirt(z)
|
||||
var/datum/zlevel/our_z = get_zlev(z)
|
||||
our_z.dirt_count--
|
||||
if(our_z.dirt_count == 0)
|
||||
our_z.resume_init()
|
||||
if(our_z.dirt_count < 0)
|
||||
log_debug("WARNING: Imbalanced dirt removal")
|
||||
our_z.dirt_count = 0
|
||||
|
||||
/datum/zlev_manager/proc/postpone_init(z, thing)
|
||||
var/datum/zlevel/our_z = get_zlev(z)
|
||||
our_z.init_list.Add(thing)
|
||||
Reference in New Issue
Block a user