Fixes conflict with explosives PR

This commit is contained in:
Kyep
2016-07-16 02:59:19 -07:00
240 changed files with 6053 additions and 1556 deletions
+19 -14
View File
@@ -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))
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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)
+10
View File
@@ -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
+22 -9
View File
@@ -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)
+245 -125
View File
@@ -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
+166 -29
View File
@@ -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
+7 -2
View File
@@ -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)
+15
View File
@@ -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
+16 -1
View File
@@ -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
+6 -1
View File
@@ -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"
+16 -1
View File
@@ -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"
+14 -1
View File
@@ -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."
+68
View File
@@ -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()
+4 -2
View File
@@ -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(
+6
View File
@@ -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
+6 -4
View File
@@ -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()
..()
+2 -1
View File
@@ -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)
+1 -1
View File
@@ -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,\
+414
View File
@@ -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
+2
View File
@@ -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()
+39
View File
@@ -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
+1
View File
@@ -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)
+2 -1
View File
@@ -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))
+47 -1
View File
@@ -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())
+5 -2
View File
@@ -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)
+2 -7
View File
@@ -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)
+10
View File
@@ -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
+22 -7
View File
@@ -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
+4 -3
View File
@@ -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>"
+2 -1
View File
@@ -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
+25 -12
View File
@@ -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)
+49
View File
@@ -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"
+2 -2
View File
@@ -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
+73
View File
@@ -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)