diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 537f77eee51..fc735594542 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -4,7 +4,7 @@
#define TRANSITIONEDGE 7 // Distance from edge to move to another z-level.
-// Invisibility constants.
+// Invisibility constants. These should only be used for TRUE invisibility, AKA nothing living players touch
#define INVISIBILITY_LIGHTING 20
#define INVISIBILITY_LEVEL_ONE 35
#define INVISIBILITY_LEVEL_TWO 45
@@ -21,6 +21,9 @@
#define SEE_INVISIBLE_MINIMUM 5
#define INVISIBILITY_MAXIMUM 100
+// Pseudo-Invis, like Ninja, Ling, Etc.
+#define EFFECTIVE_INVIS 50 // Below this, can't be examined, may as well be invisible to the game
+
// For the client FPS pref and anywhere else
#define MAX_CLIENT_FPS 200
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 012677200c3..c73ebf4d41e 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -177,6 +177,9 @@
#define O_LIVER "liver"
#define O_KIDNEYS "kidneys"
#define O_APPENDIX "appendix"
+#define O_VOICE "voicebox"
+
+// Non-Standard organs
#define O_PLASMA "plasma vessel"
#define O_HIVE "hive node"
#define O_NUTRIENT "nutrient vessel"
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index 81a55f84d7b..f12b630979c 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -50,6 +50,7 @@
#define LANGUAGE_MINBUS "Minbus"
#define LANGUAGE_EVENT1 "Occursus"
#define LANGUAGE_AKHANI "Akhani"
+#define LANGUAGE_ALAI "Alai"
// Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index d7905146141..44137b0431b 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -30,6 +30,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_LIGHTING 0
#define INIT_ORDER_AIR -1
+#define INIT_ORDER_PLANETS -4
#define INIT_ORDER_OVERLAY -6
#define INIT_ORDER_XENOARCH -20
@@ -42,6 +43,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_AIRFLOW 30
#define FIRE_PRIORITY_AIR 35
#define FIRE_PRIORITY_DEFAULT 50
+#define FIRE_PRIORITY_PLANETS 75
#define FIRE_PRIORITY_MACHINES 100
#define FIRE_PRIORITY_OVERLAYS 500
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index c0c4f18f6b8..13c02c88ba3 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -1073,47 +1073,7 @@ var/global/list/common_tools = list(
if(istype(I, /obj/item/device/assembly/signaler))
return TRUE
return
-/*
-/proc/iswrench(O)
- if(istype(O, /obj/item/weapon/wrench))
- return 1
- return 0
-/proc/iswelder(O)
- if(istype(O, /obj/item/weapon/weldingtool))
- return 1
- return 0
-
-/proc/iscoil(O)
- if(istype(O, /obj/item/stack/cable_coil))
- return 1
- return 0
-
-/proc/iswirecutter(O)
- if(istype(O, /obj/item/weapon/tool/wirecutters))
- return 1
- return 0
-
-/proc/isscrewdriver(O)
- if(istype(O, /obj/item/weapon/tool/screwdriver))
- return 1
- return 0
-
-/proc/ismultitool(O)
- if(istype(O, /obj/item/device/multitool))
- return 1
- return 0
-
-/proc/iscrowbar(O)
- if(istype(O, /obj/item/weapon/tool/crowbar))
- return 1
- return 0
-
-/proc/iswire(O)
- if(istype(O, /obj/item/stack/cable_coil))
- return 1
- return 0
-*/
proc/is_hot(obj/item/W as obj)
switch(W.type)
if(/obj/item/weapon/weldingtool)
diff --git a/code/controllers/Processes/planet.dm b/code/controllers/Processes/planet.dm
deleted file mode 100644
index 770b3a5e873..00000000000
--- a/code/controllers/Processes/planet.dm
+++ /dev/null
@@ -1,95 +0,0 @@
-var/datum/controller/process/planet/planet_controller = null
-
-/datum/controller/process/planet
- var/list/planets = list()
- var/list/z_to_planet = list()
-
-/datum/controller/process/planet/setup()
- name = "planet controller"
- planet_controller = src
- schedule_interval = 1 MINUTE
-
- var/list/planet_datums = typesof(/datum/planet) - /datum/planet
- for(var/P in planet_datums)
- var/datum/planet/NP = new P()
- planets.Add(NP)
-
- allocateTurfs()
-
-/datum/controller/process/planet/proc/allocateTurfs()
- for(var/turf/simulated/OT in outdoor_turfs)
- for(var/datum/planet/P in planets)
- if(OT.z in P.expected_z_levels)
- P.planet_floors |= OT
- OT.vis_contents |= P.weather_holder.visuals
- break
- outdoor_turfs.Cut() //Why were you in there INCORRECTLY?
-
- for(var/turf/unsimulated/wall/planetary/PW in planetary_walls)
- for(var/datum/planet/P in planets)
- if(PW.type == P.planetary_wall_type)
- P.planet_walls |= PW
- break
- planetary_walls.Cut()
-
-/datum/controller/process/planet/proc/unallocateTurf(var/turf/T)
- for(var/planet in planets)
- var/datum/planet/P = planet
- if(T.z in P.expected_z_levels)
- P.planet_floors -= T
- T.vis_contents -= P.weather_holder.visuals
-
-/datum/controller/process/planet/doWork()
- if(outdoor_turfs.len || planetary_walls.len)
- allocateTurfs()
-
- for(var/datum/planet/P in planets)
- P.process(schedule_interval / 10)
- SCHECK //Your process() really shouldn't take this long...
-
- //Sun light needs changing
- if(P.needs_work & PLANET_PROCESS_SUN)
- P.needs_work &= ~PLANET_PROCESS_SUN
- // Remove old value from corners
- var/list/sunlit_corners = P.sunlit_corners
- var/old_lum_r = -P.sun["lum_r"]
- var/old_lum_g = -P.sun["lum_g"]
- var/old_lum_b = -P.sun["lum_b"]
- if(old_lum_r || old_lum_g || old_lum_b)
- for(var/C in P.sunlit_corners)
- var/datum/lighting_corner/LC = C
- LC.update_lumcount(old_lum_r, old_lum_g, old_lum_b)
- SCHECK
- sunlit_corners.Cut()
-
- // Calculate new values to apply
- var/new_brightness = P.sun["brightness"]
- var/new_color = P.sun["color"]
- var/lum_r = new_brightness * GetRedPart (new_color) / 255
- var/lum_g = new_brightness * GetGreenPart(new_color) / 255
- var/lum_b = new_brightness * GetBluePart (new_color) / 255
- var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs.
- for(var/I in P.planet_floors)
- var/turf/simulated/T = I
- if(!T.lighting_corners_initialised)
- T.generate_missing_corners()
- for(var/C in T.get_corners())
- var/datum/lighting_corner/LC = C
- if(LC.update_gen != update_gen && LC.active)
- sunlit_corners += LC
- LC.update_gen = update_gen
- LC.update_lumcount(lum_r, lum_g, lum_b)
- SCHECK
- update_gen--
- P.sun["lum_r"] = lum_r
- P.sun["lum_g"] = lum_g
- P.sun["lum_b"] = lum_b
-
- //Temperature needs updating
- if(P.needs_work & PLANET_PROCESS_TEMP)
- P.needs_work &= ~PLANET_PROCESS_TEMP
- //Set new temperatures
- for(var/W in P.planet_walls)
- var/turf/unsimulated/wall/planetary/wall = W
- wall.set_temperature(P.weather_holder.temperature)
- SCHECK
diff --git a/code/controllers/Processes/supply.dm b/code/controllers/Processes/supply.dm
index 891a511ec6d..5b3e4f6f2b1 100644
--- a/code/controllers/Processes/supply.dm
+++ b/code/controllers/Processes/supply.dm
@@ -1,6 +1,229 @@
+//Config stuff
+#define SUPPLY_DOCKZ 2 //Z-level of the Dock.
+#define SUPPLY_STATIONZ 1 //Z-level of the Station.
+#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station
+#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock
+
+//Supply packs are in /code/datums/supplypacks
+//Computers are in /code/game/machinery/computer/supply.dm
+
+/datum/supply_order
+ var/ordernum
+ var/datum/supply_packs/object = null
+ var/orderedby = null
+ var/comment = null
+
+/datum/exported_crate
+ var/name
+ var/value
+
+
+var/datum/controller/supply/supply_controller = new()
+
+/datum/controller/supply
+ //supply points
+ var/points = 50
+ var/points_per_process = 1.5
+ var/points_per_slip = 2
+ var/points_per_platinum = 5 // 5 points per sheet
+ var/points_per_phoron = 5
+ var/points_per_money = 0.02 // 1 point for $50
+ //control
+ var/ordernum
+ var/list/shoppinglist = list()
+ var/list/requestlist = list()
+ var/list/supply_packs = list()
+ var/list/exported_crates = list()
+ //shuttle movement
+ var/movetime = 1200
+ var/datum/shuttle/ferry/supply/shuttle
+
+/datum/controller/supply/New()
+ ordernum = rand(1,9000)
+
+ for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs))
+ var/datum/supply_packs/P = new typepath()
+ supply_packs[P.name] = P
+
/datum/controller/process/supply/setup()
name = "supply controller"
schedule_interval = 300 // every 30 seconds
/datum/controller/process/supply/doWork()
- supply_controller.process()
\ No newline at end of file
+ supply_controller.process()
+
+// Supply shuttle ticker - handles supply point regeneration
+// This is called by the process scheduler every thirty seconds
+/datum/controller/supply/proc/process()
+ points += points_per_process
+
+//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
+/datum/controller/supply/proc/forbidden_atoms_check(atom/A)
+ if(isliving(A))
+ return 1
+ if(istype(A,/obj/item/weapon/disk/nuclear))
+ return 1
+ if(istype(A,/obj/machinery/nuclearbomb))
+ return 1
+ if(istype(A,/obj/item/device/radio/beacon))
+ return 1
+
+ for(var/atom/B in A.contents)
+ if(.(B))
+ return 1
+
+//Selling
+/datum/controller/supply/proc/sell()
+ var/area/area_shuttle = shuttle.get_location_area()
+ if(!area_shuttle)
+ return
+
+ callHook("sell_shuttle", list(area_shuttle));
+
+ var/phoron_count = 0
+ var/plat_count = 0
+ var/money_count = 0
+
+ exported_crates = list()
+
+ for(var/atom/movable/MA in area_shuttle)
+ if(MA.anchored)
+ continue
+
+ // Must be in a crate!
+ if(istype(MA,/obj/structure/closet/crate))
+ var/oldpoints = points
+ var/oldphoron = phoron_count
+ var/oldplatinum = plat_count
+ var/oldmoney = money_count
+
+ var/obj/structure/closet/crate/CR = MA
+ callHook("sell_crate", list(CR, area_shuttle))
+
+ points += CR.points_per_crate
+ var/find_slip = 1
+
+ for(var/atom/A in CR)
+ // Sell manifests
+ if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
+ var/obj/item/weapon/paper/manifest/slip = A
+ if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
+ points += points_per_slip
+ find_slip = 0
+ continue
+
+ // Sell phoron and platinum
+ if(istype(A, /obj/item/stack))
+ var/obj/item/stack/P = A
+ switch(P.get_material_name())
+ if("phoron")
+ phoron_count += P.get_amount()
+ if("platinum")
+ plat_count += P.get_amount()
+
+ //Sell spacebucks
+ if(istype(A, /obj/item/weapon/spacecash))
+ var/obj/item/weapon/spacecash/cashmoney = A
+ money_count += cashmoney.worth
+
+ var/datum/exported_crate/EC = new /datum/exported_crate()
+ EC.name = CR.name
+ EC.value = points - oldpoints
+ EC.value += (phoron_count - oldphoron) * points_per_phoron
+ EC.value += (plat_count - oldplatinum) * points_per_platinum
+ EC.value += (money_count - oldmoney) * points_per_money
+ exported_crates += EC
+
+ qdel(MA)
+
+ points += phoron_count * points_per_phoron
+ points += plat_count * points_per_platinum
+ points += money_count * points_per_money
+
+//Buying
+/datum/controller/supply/proc/buy()
+ if(!shoppinglist.len)
+ return
+
+ var/orderedamount = shoppinglist.len
+
+ var/area/area_shuttle = shuttle.get_location_area()
+ if(!area_shuttle)
+ return
+
+ var/list/clear_turfs = list()
+
+ for(var/turf/T in area_shuttle)
+ if(T.density)
+ continue
+ var/contcount
+ for(var/atom/A in T.contents)
+ if(!A.simulated)
+ continue
+ contcount++
+ if(contcount)
+ continue
+ clear_turfs += T
+
+ for(var/S in shoppinglist)
+ if(!clear_turfs.len)
+ break
+
+ var/i = rand(1,clear_turfs.len)
+ var/turf/pickedloc = clear_turfs[i]
+ clear_turfs.Cut(i,i+1)
+ shoppinglist -= S
+
+ var/datum/supply_order/SO = S
+ var/datum/supply_packs/SP = SO.object
+
+ var/obj/A = new SP.containertype(pickedloc)
+ A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
+
+ //supply manifest generation begin
+ var/obj/item/weapon/paper/manifest/slip
+ if(!SP.contraband)
+ slip = new /obj/item/weapon/paper/manifest(A)
+ slip.is_copy = 0
+ slip.info = "
[command_name()] Shipping Manifest
"
+ slip.info +="Order #[SO.ordernum]
"
+ slip.info +="Destination: [station_name()]
"
+ slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT
"
+ slip.info +="CONTENTS:
"
+
+ //spawn the stuff, finish generating the manifest while you're at it
+ if(SP.access)
+ if(isnum(SP.access))
+ A.req_access = list(SP.access)
+ else if(islist(SP.access))
+ var/list/L = SP.access // access var is a plain var, we need a list
+ A.req_access = L.Copy()
+ else
+ log_debug("Supply pack with invalid access restriction [SP.access] encountered!")
+
+ var/list/contains
+ if(istype(SP,/datum/supply_packs/randomised))
+ var/datum/supply_packs/randomised/SPR = SP
+ contains = list()
+ if(SPR.contains.len)
+ for(var/j=1,j<=SPR.num_contained,j++)
+ contains += pick(SPR.contains)
+ else
+ contains = SP.contains
+
+ for(var/typepath in contains)
+ if(!typepath)
+ continue
+
+ var/number_of_items = max(1, contains[typepath])
+ for(var/j = 1 to number_of_items)
+ var/atom/B2 = new typepath(A)
+ if(slip)
+ slip.info += "- [B2.name]
" //add the item to the manifest
+
+ //manifest finalisation
+ if(slip)
+ slip.info += "
"
+ slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
"
+
+ return
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index f6db4f65d43..9e29ba9998e 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -60,6 +60,7 @@ var/list/gamemode_cache = list()
var/humans_need_surnames = 0
var/allow_random_events = 0 // enables random events mid-round when set to 1
var/allow_ai = 1 // allow ai job
+ var/allow_ai_drones = 0 // allow ai controlled drones
var/hostedby = null
var/respawn = 1
var/guest_jobban = 1
@@ -400,6 +401,9 @@ var/list/gamemode_cache = list()
if ("allow_ai")
config.allow_ai = 1
+ if ("allow_ai_drones")
+ config.allow_ai_drones = 1
+
// if ("authentication")
// config.enable_authentication = 1
diff --git a/code/controllers/subsystems/planets.dm b/code/controllers/subsystems/planets.dm
new file mode 100644
index 00000000000..f7fc49b6612
--- /dev/null
+++ b/code/controllers/subsystems/planets.dm
@@ -0,0 +1,187 @@
+SUBSYSTEM_DEF(planets)
+ name = "Planets"
+ init_order = INIT_ORDER_PLANETS
+ priority = FIRE_PRIORITY_PLANETS
+ wait = 2 SECONDS
+ flags = SS_BACKGROUND
+ runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+
+ var/list/new_outdoor_turfs = list()
+ var/list/new_outdoor_walls = list()
+
+ var/list/planets = list()
+ var/list/z_to_planet = list()
+
+ var/list/currentrun = list()
+
+ var/list/needs_sun_update = list()
+ var/list/needs_temp_update = list()
+
+/datum/controller/subsystem/planets/Initialize(timeofday)
+ admin_notice("Initializing planetary weather.", R_DEBUG)
+ createPlanets()
+ allocateTurfs(TRUE)
+ ..()
+
+/datum/controller/subsystem/planets/proc/createPlanets()
+ var/list/planet_datums = subtypesof(/datum/planet)
+ for(var/P in planet_datums)
+ var/datum/planet/NP = new P()
+ planets.Add(NP)
+ for(var/Z in NP.expected_z_levels)
+ if(Z > z_to_planet.len)
+ z_to_planet.len = Z
+ if(z_to_planet[Z])
+ admin_notice("Z[Z] is shared by more than one planet!", R_DEBUG)
+ continue
+ z_to_planet[Z] = NP
+
+/datum/controller/subsystem/planets/proc/addTurf(var/turf/T,var/is_edge)
+ if(is_edge)
+ new_outdoor_walls |= T
+ else
+ new_outdoor_turfs |= T
+
+/datum/controller/subsystem/planets/proc/removeTurf(var/turf/T,var/is_edge)
+ if(is_edge)
+ new_outdoor_walls -= T
+ else
+ new_outdoor_turfs -= T
+
+ if(z_to_planet.len >= T.z)
+ var/datum/planet/P = z_to_planet[T.z]
+ if(!P)
+ return
+ if(is_edge)
+ P.planet_floors -= T
+ else
+ P.planet_walls -= T
+ T.vis_contents -= P.weather_holder.visuals
+ T.vis_contents -= P.weather_holder.special_visuals
+
+/datum/controller/subsystem/planets/proc/allocateTurfs(var/initial = FALSE)
+ var/list/currentlist = new_outdoor_turfs
+ while(currentlist.len)
+ var/turf/simulated/OT = currentlist[currentlist.len]
+ currentlist.len--
+ if(istype(OT) && OT.outdoors && z_to_planet.len >= OT.z && z_to_planet[OT.z])
+ var/datum/planet/P = z_to_planet[OT.z]
+ P.planet_floors |= OT
+ OT.vis_contents |= P.weather_holder.visuals
+ OT.vis_contents |= P.weather_holder.special_visuals
+ if(!initial && MC_TICK_CHECK)
+ return
+
+ currentlist = new_outdoor_walls
+ while(currentlist.len)
+ var/turf/unsimulated/wall/planetary/PW = currentlist[currentlist.len]
+ currentlist.len--
+ if(istype(PW) && z_to_planet.len >= PW.z && z_to_planet[PW.z])
+ var/datum/planet/P = z_to_planet[PW.z]
+ P.planet_walls |= PW
+ if(!initial && MC_TICK_CHECK)
+ return
+
+/datum/controller/subsystem/planets/proc/unallocateTurf(var/turf/simulated/T)
+ if(istype(T) && z_to_planet[T.z])
+ var/datum/planet/P = z_to_planet[T.z]
+ P.planet_floors -= T
+ T.vis_contents -= P.weather_holder.visuals
+ T.vis_contents -= P.weather_holder.special_visuals
+
+
+/datum/controller/subsystem/planets/fire(resumed = 0)
+ if(new_outdoor_turfs.len || new_outdoor_walls.len)
+ allocateTurfs()
+
+ if(!resumed)
+ src.currentrun = planets.Copy()
+
+ var/list/needs_sun_update = src.needs_sun_update
+ while(needs_sun_update.len)
+ var/datum/planet/P = needs_sun_update[needs_sun_update.len]
+ needs_sun_update.len--
+ updateSunlight(P)
+ if(MC_TICK_CHECK)
+ return
+
+ var/list/needs_temp_update = src.needs_temp_update
+ while(needs_temp_update.len)
+ var/datum/planet/P = needs_temp_update[needs_temp_update.len]
+ needs_temp_update.len--
+ updateTemp(P)
+ if(MC_TICK_CHECK)
+ return
+
+ var/list/currentrun = src.currentrun
+ while(currentrun.len)
+ var/datum/planet/P = currentrun[currentrun.len]
+ currentrun.len--
+
+ P.process(last_fire)
+
+ //Sun light needs changing
+ if(P.needs_work & PLANET_PROCESS_SUN)
+ P.needs_work &= ~PLANET_PROCESS_SUN
+ needs_sun_update |= P
+
+ //Temperature needs updating
+ if(P.needs_work & PLANET_PROCESS_TEMP)
+ P.needs_work &= ~PLANET_PROCESS_TEMP
+ needs_temp_update |= P
+
+ if(MC_TICK_CHECK)
+ return
+
+/datum/controller/subsystem/planets/proc/updateSunlight(var/datum/planet/P)
+ // Remove old value from corners
+ var/list/sunlit_corners = P.sunlit_corners
+ var/old_lum_r = -P.sun["lum_r"]
+ var/old_lum_g = -P.sun["lum_g"]
+ var/old_lum_b = -P.sun["lum_b"]
+ if(old_lum_r || old_lum_g || old_lum_b)
+ for(var/C in sunlit_corners)
+ var/datum/lighting_corner/LC = C
+ LC.update_lumcount(old_lum_r, old_lum_g, old_lum_b)
+ CHECK_TICK
+ sunlit_corners.Cut()
+
+ // Calculate new values to apply
+ var/new_brightness = P.sun["brightness"]
+ var/new_color = P.sun["color"]
+ var/lum_r = new_brightness * GetRedPart (new_color) / 255
+ var/lum_g = new_brightness * GetGreenPart(new_color) / 255
+ var/lum_b = new_brightness * GetBluePart (new_color) / 255
+ var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs.
+ for(var/I in P.planet_floors)
+ var/turf/simulated/T = I
+ if(!T.lighting_corners_initialised)
+ T.generate_missing_corners()
+ for(var/C in T.get_corners())
+ var/datum/lighting_corner/LC = C
+ if(LC.update_gen != update_gen && LC.active)
+ sunlit_corners += LC
+ LC.update_gen = update_gen
+ LC.update_lumcount(lum_r, lum_g, lum_b)
+ CHECK_TICK
+ update_gen--
+ P.sun["lum_r"] = lum_r
+ P.sun["lum_g"] = lum_g
+ P.sun["lum_b"] = lum_b
+
+/datum/controller/subsystem/planets/proc/updateTemp(var/datum/planet/P)
+ //Set new temperatures
+ for(var/W in P.planet_walls)
+ var/turf/unsimulated/wall/planetary/wall = W
+ wall.set_temperature(P.weather_holder.temperature)
+ CHECK_TICK
+
+/datum/controller/subsystem/planets/proc/weatherDisco()
+ var/count = 100000
+ while(count > 0)
+ count--
+ for(var/planet in planets)
+ var/datum/planet/P = planet
+ if(P.weather_holder)
+ P.weather_holder.change_weather(pick(P.weather_holder.allowed_weather_types))
+ sleep(3)
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index 8d02fda2ebb..f1249cfe0c3 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -133,8 +133,5 @@
if("Vote")
debug_variables(vote)
feedback_add_details("admin_verb", "DVote")
- if("Planets")
- debug_variables(planet_controller)
- feedback_add_details("admin_verb", "DPlanets")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
return
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index b6654650847..765e1ee9e93 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -84,10 +84,8 @@
for(var/mob/living/silicon/robot/robot in mob_list)
// No combat/syndicate cyborgs, no drones.
- if(robot.module && robot.module.hide_on_manifest)
- continue
-
- bot[robot.name] = "[robot.modtype] [robot.braintype]"
+ if(!robot.scrambledcodes && !(robot.module && robot.module.hide_on_manifest))
+ bot[robot.name] = "[robot.modtype] [robot.braintype]"
if(heads.len > 0)
diff --git a/code/datums/observation/turf_changed.dm b/code/datums/observation/turf_changed.dm
index 861b4092274..0bb0ed91158 100644
--- a/code/datums/observation/turf_changed.dm
+++ b/code/datums/observation/turf_changed.dm
@@ -20,9 +20,9 @@ var/decl/observ/turf_changed/turf_changed_event = new()
* Turf Changed Handling *
************************/
-/turf/ChangeTurf()
+/turf/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors)
var/old_density = density
var/old_opacity = opacity
- . = ..()
+ . = ..(N, tell_universe, force_lighting_update, preserve_outdoors)
if(.)
turf_changed_event.raise_event(src, old_density, density, old_opacity, opacity)
\ No newline at end of file
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index ba809cb977f..f2cec96aab8 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -144,7 +144,7 @@ var/global/list/PDA_Manifest = list()
for(var/mob/living/silicon/robot/robot in mob_list)
// No combat/syndicate cyborgs, no drones.
- if(robot.module && robot.module.hide_on_manifest)
+ if(!robot.scrambledcodes && !(robot.module && robot.module.hide_on_manifest))
continue
bot[++bot.len] = list("name" = robot.real_name, "rank" = "[robot.modtype] [robot.braintype]", "active" = "Active")
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index 484ff8ea33e..7496551c25f 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -79,7 +79,9 @@
Think through your actions and make the roleplay immersive! Please remember all \
rules aside from those without explicit exceptions apply to antagonists."
- var/can_use_aooc = TRUE // If true, will be given the AOOC verb, along with the ability to use it.
+// var/can_use_aooc = TRUE // If true, will be given the AOOC verb, along with the ability to use it.
+ var/can_hear_aooc = TRUE // If FALSE, the antag can neither speak nor hear AOOC. If TRUE, they can at least hear it.
+ var/can_speak_aooc = TRUE // If TRUE, the antag can freely spean in AOOC.
/datum/antagonist/New()
..()
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
index 67eb7e2e726..d5fa2c1fe6f 100644
--- a/code/game/antagonist/antagonist_add.dm
+++ b/code/game/antagonist/antagonist_add.dm
@@ -36,7 +36,7 @@
and it otherwise has no bearing on your round."
player.current.verbs |= /mob/living/proc/write_ambition
- if(can_use_aooc)
+ if(can_speak_aooc)
player.current.client.verbs += /client/proc/aooc
// Handle only adding a mind and not bothering with gear etc.
diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm
index c1aec2bcf82..245296084c6 100644
--- a/code/game/antagonist/outsider/ert.dm
+++ b/code/game/antagonist/outsider/ert.dm
@@ -25,7 +25,8 @@ var/datum/antagonist/ert/ert
initial_spawn_req = 5
initial_spawn_target = 7
- can_use_aooc = FALSE // They're the good guys.
+ can_hear_aooc = FALSE // They're the good guys.
+ can_speak_aooc = FALSE // Just in case the above var bugs, or gets touched.
/datum/antagonist/ert/create_default(var/mob/source)
var/mob/living/carbon/human/M = ..()
diff --git a/code/game/antagonist/outsider/trader.dm b/code/game/antagonist/outsider/trader.dm
index 9603b495238..69af3883b97 100644
--- a/code/game/antagonist/outsider/trader.dm
+++ b/code/game/antagonist/outsider/trader.dm
@@ -24,7 +24,7 @@ var/datum/antagonist/trader/traders
initial_spawn_req = 5
initial_spawn_target = 7
- can_use_aooc = FALSE // They're not real antags.
+ can_speak_aooc = FALSE // They're not real antags.
/datum/antagonist/trader/create_default(var/mob/source)
var/mob/living/carbon/human/M = ..()
diff --git a/code/game/antagonist/station/infiltrator.dm b/code/game/antagonist/station/infiltrator.dm
index 8ca6f4ac4db..b51e7e74fbb 100644
--- a/code/game/antagonist/station/infiltrator.dm
+++ b/code/game/antagonist/station/infiltrator.dm
@@ -13,6 +13,7 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
welcome_text = "To speak on your team's private channel, use :t."
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
+ can_speak_aooc = TRUE
/datum/antagonist/traitor/infiltrator/New()
..()
diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm
index 6f7ec893229..3e8afae32df 100644
--- a/code/game/antagonist/station/renegade.dm
+++ b/code/game/antagonist/station/renegade.dm
@@ -17,7 +17,7 @@ var/datum/antagonist/renegade/renegades
Think through your actions and make the roleplay immersive! Please remember all \
rules aside from those without explicit exceptions apply to antagonists."
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE
- can_use_aooc = FALSE
+ can_speak_aooc = FALSE // They aren't 'true' antags, but they still need to hear blanket antag instructions
hard_cap = 8
hard_cap_round = 12
@@ -61,8 +61,6 @@ var/datum/antagonist/renegade/renegades
list(/obj/item/weapon/gun/projectile/luger,/obj/item/weapon/gun/projectile/luger/brown)
)
- can_use_aooc = FALSE // They aren't 'true' antags.
-
/datum/antagonist/renegade/New()
..()
renegades = src
diff --git a/code/game/antagonist/station/thug.dm b/code/game/antagonist/station/thug.dm
index 8810fca7d04..61d92e1646f 100644
--- a/code/game/antagonist/station/thug.dm
+++ b/code/game/antagonist/station/thug.dm
@@ -15,4 +15,4 @@ var/datum/antagonist/thug/thugs
Think through your actions and make the roleplay immersive! Please remember all \
rules aside from those with explicit exceptions apply to antagonists."
flags = ANTAG_SUSPICIOUS | ANTAG_IMPLANT_IMMUNE | ANTAG_RANDSPAWN | ANTAG_VOTABLE
- can_use_aooc = FALSE
+ can_speak_aooc = FALSE
diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm
index d0a1f54ed21..3681cf236d7 100644
--- a/code/game/antagonist/station/traitor.dm
+++ b/code/game/antagonist/station/traitor.dm
@@ -5,7 +5,7 @@ var/datum/antagonist/traitor/traitors
id = MODE_TRAITOR
protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Colony Director")
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
- can_use_aooc = FALSE
+ can_speak_aooc = FALSE // If they want to plot and plan as this sort of traitor, they'll need to do it ICly.
/datum/antagonist/traitor/auto
id = MODE_AUTOTRAITOR
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 337adfb7a36..873e720512d 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -31,7 +31,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg','sound/ambience/serspaceamb1.ogg')
base_turf = /turf/space
-area/space/atmosalert()
+/area/space/atmosalert()
return
/area/space/fire_alert()
@@ -451,20 +451,6 @@ area/space/atmosalert()
icon_state = "cave"
sound_env = SMALL_ENCLOSED
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/area/planet/clown
name = "\improper Clown Planet"
icon_state = "honk"
@@ -906,9 +892,6 @@ area/space/atmosalert()
/area/maintenance/substation/security // Security, Brig, Permabrig, etc.
name = "Security Substation"
-
-
-
//Hallway
/area/hallway/primary/
@@ -1115,7 +1098,7 @@ area/space/atmosalert()
name = "\improper Research Server Room"
icon_state = "server"
-//Crew
+//Civilian
/area/crew_quarters
name = "\improper Dormitories"
@@ -1978,6 +1961,24 @@ area/space/atmosalert()
name = "\improper Vacant Office"
icon_state = "security"
+/area/janitor/
+ name = "\improper Custodial Closet"
+ icon_state = "janitor"
+
+/area/hydroponics
+ name = "\improper Hydroponics"
+ icon_state = "hydro"
+
+/area/hydroponics/cafegarden
+ name = "\improper Cafeteria Garden"
+ icon_state = "cafe_garden"
+
+/area/hydroponics/garden
+ name = "\improper Garden"
+ icon_state = "garden"
+
+// SUPPLY
+
/area/quartermaster
name = "\improper Quartermasters"
icon_state = "quart"
@@ -2011,23 +2012,20 @@ area/space/atmosalert()
name = "\improper Cargo Mining Dock"
icon_state = "mining"
-/area/janitor/
- name = "\improper Custodial Closet"
- icon_state = "janitor"
+/area/supply/station
+ name = "Supply Shuttle"
+ icon_state = "shuttle3"
+ requires_power = 0
+ base_turf = /turf/space
-/area/hydroponics
- name = "\improper Hydroponics"
- icon_state = "hydro"
+/area/supply/dock
+ name = "Supply Shuttle"
+ icon_state = "shuttle3"
+ requires_power = 0
+ base_turf = /turf/space
-/area/hydroponics/cafegarden
- name = "\improper Cafeteria Garden"
- icon_state = "cafe_garden"
+// SCIENCE
-/area/hydroponics/garden
- name = "\improper Garden"
- icon_state = "garden"
-
-//rnd (Research and Development
/area/rnd/research
name = "\improper Research and Development"
icon_state = "research"
diff --git a/code/game/gamemodes/changeling/absorbed_dna.dm b/code/game/gamemodes/changeling/absorbed_dna.dm
index 3c23f0270c3..26d433cd8cc 100644
--- a/code/game/gamemodes/changeling/absorbed_dna.dm
+++ b/code/game/gamemodes/changeling/absorbed_dna.dm
@@ -5,12 +5,14 @@
var/list/languages
var/identifying_gender
var/list/flavour_texts
+ var/list/genMods
-/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender, var/list/newFlavour)
+/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages, var/newIdentifying_Gender, var/list/newFlavour, var/list/newGenMods)
..()
name = newName
dna = newDNA
speciesName = newSpecies
languages = newLanguages
identifying_gender = newIdentifying_Gender
- flavour_texts = newFlavour ? newFlavour.Copy() : null
\ No newline at end of file
+ flavour_texts = newFlavour ? newFlavour.Copy() : null
+ genMods = newGenMods ? newGenMods.Copy() : null
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index f76fd5ca477..45b230b00c1 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -78,7 +78,7 @@
src << "We can now re-adapt, reverting our evolution so that we may start anew, if needed."
- var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts)
+ var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts, T.modifiers)
absorbDNA(newDNA)
if(T.mind && T.mind.changeling)
diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm
index 92257925757..6dd16061a12 100644
--- a/code/game/gamemodes/changeling/powers/transform.dm
+++ b/code/game/gamemodes/changeling/powers/transform.dm
@@ -48,6 +48,13 @@
src.UpdateAppearance()
domutcheck(src, null)
changeling_update_languages(changeling.absorbed_languages)
+ if(chosen_dna.genMods)
+ var/mob/living/carbon/human/self = src
+ for(var/datum/modifier/mod in self.modifiers)
+ self.modifiers.Remove(mod.type)
+
+ for(var/datum/modifier/mod in chosen_dna.genMods)
+ self.modifiers.Add(mod.type)
src.verbs -= /mob/proc/changeling_transform
spawn(10)
diff --git a/code/game/gamemodes/technomancer/spell_objs_helpers.dm b/code/game/gamemodes/technomancer/spell_objs_helpers.dm
index f11c027566a..105b3b3e9c8 100644
--- a/code/game/gamemodes/technomancer/spell_objs_helpers.dm
+++ b/code/game/gamemodes/technomancer/spell_objs_helpers.dm
@@ -31,7 +31,7 @@
return TRUE
/obj/item/weapon/spell/proc/within_range(var/atom/target, var/max_range = 7) // Beyond 7 is off the screen.
- if(range(get_dist(owner, target) <= max_range))
+ if(target in view(max_range, owner))
return TRUE
return FALSE
diff --git a/code/game/gamemodes/technomancer/spells/apportation.dm b/code/game/gamemodes/technomancer/spells/apportation.dm
index 9fafc47ae38..452ddc52fa6 100644
--- a/code/game/gamemodes/technomancer/spells/apportation.dm
+++ b/code/game/gamemodes/technomancer/spells/apportation.dm
@@ -21,11 +21,13 @@
if(!AM.loc) //Don't teleport HUD telements to us.
return
if(AM.anchored)
- user << "\The [hit_atom] is firmly secured and anchored, you can't move it!"
+ to_chat(user, "\The [hit_atom] is firmly secured and anchored, you can't move it!")
return
+
if(!within_range(hit_atom) && !check_for_scepter())
- user << "\The [hit_atom] is too far away."
+ to_chat(user, "\The [hit_atom] is too far away.")
return
+
//Teleporting an item.
if(istype(hit_atom, /obj/item))
var/obj/item/I = hit_atom
@@ -47,7 +49,7 @@
//Now let's try to teleport a living mob.
else if(istype(hit_atom, /mob/living))
var/mob/living/L = hit_atom
- L << "You are teleported towards \the [user]."
+ to_chat(L, "You are teleported towards \the [user].")
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
s1.set_up(2, 1, user)
@@ -60,7 +62,7 @@
spawn(1 SECOND)
if(!user.Adjacent(L))
- user << "\The [L] is out of your reach."
+ to_chat(user, "\The [L] is out of your reach.")
qdel(src)
return
diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm
index 2eece781ec8..e24e462fdf0 100644
--- a/code/game/jobs/job/civilian_chaplain.dm
+++ b/code/game/jobs/job/civilian_chaplain.dm
@@ -149,5 +149,7 @@
feedback_set_details("religion_book","[new_book_style]")
return 1
+/* If you uncomment this, every time the mob preview updates it makes a new PDA. It seems to work just fine and display without it, so why this exists, haven't a clue. -Hawk
/datum/job/chaplain/equip_preview(var/mob/living/carbon/human/H, var/alt_title)
return equip(H, alt_title, FALSE)
+*/
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 04dbaffb539..bfc964f7f21 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -378,7 +378,8 @@ var/global/datum/controller/occupations/job_master
H.amend_exploitable(G.path)
if(G.slot == "implant")
- H.implant_loadout(G)
+ var/obj/item/weapon/implant/I = G.spawn_item(H)
+ I.implant_loadout(H)
continue
if(G.slot && !(G.slot in custom_equip_slots))
diff --git a/code/game/machinery/bioprinter.dm b/code/game/machinery/bioprinter.dm
index 0a43acb1724..f66b580c521 100644
--- a/code/game/machinery/bioprinter.dm
+++ b/code/game/machinery/bioprinter.dm
@@ -13,27 +13,29 @@
idle_power_usage = 40
active_power_usage = 300
- var/stored_matter = 0
- var/max_stored_matter = 0
+ var/obj/item/weapon/reagent_containers/container = null // This is the beaker that holds all of the biomass
+
var/print_delay = 100
+ var/base_print_delay = 100 // For Adminbus reasons
var/printing
var/loaded_dna //Blood sample for DNA hashing.
// These should be subtypes of /obj/item/organ
+ // Costs roughly 20u Phoron (1 sheet) per internal organ, limbs are 60u for limb and extremity
var/list/products = list(
- "Heart" = list(/obj/item/organ/internal/heart, 25),
- "Lungs" = list(/obj/item/organ/internal/lungs, 25),
+ "Heart" = list(/obj/item/organ/internal/heart, 20),
+ "Lungs" = list(/obj/item/organ/internal/lungs, 20),
"Kidneys" = list(/obj/item/organ/internal/kidneys,20),
"Eyes" = list(/obj/item/organ/internal/eyes, 20),
- "Liver" = list(/obj/item/organ/internal/liver, 25),
- "Arm, Left" = list(/obj/item/organ/external/arm, 65),
- "Arm, Right" = list(/obj/item/organ/external/arm/right, 65),
- "Leg, Left" = list(/obj/item/organ/external/leg, 65),
- "Leg, Right" = list(/obj/item/organ/external/leg/right, 65),
- "Foot, Left" = list(/obj/item/organ/external/foot, 40),
- "Foot, Right" = list(/obj/item/organ/external/foot/right, 40),
- "Hand, Left" = list(/obj/item/organ/external/hand, 40),
- "Hand, Right" = list(/obj/item/organ/external/hand/right, 40)
+ "Liver" = list(/obj/item/organ/internal/liver, 20),
+ "Arm, Left" = list(/obj/item/organ/external/arm, 40),
+ "Arm, Right" = list(/obj/item/organ/external/arm/right, 40),
+ "Leg, Left" = list(/obj/item/organ/external/leg, 40),
+ "Leg, Right" = list(/obj/item/organ/external/leg/right, 40),
+ "Foot, Left" = list(/obj/item/organ/external/foot, 20),
+ "Foot, Right" = list(/obj/item/organ/external/foot/right, 20),
+ "Hand, Left" = list(/obj/item/organ/external/hand, 20),
+ "Hand, Right" = list(/obj/item/organ/external/hand/right, 20)
)
/obj/machinery/organ_printer/attackby(var/obj/item/O, var/mob/user)
@@ -57,25 +59,27 @@
/obj/machinery/organ_printer/New()
..()
+
component_parts = list()
- component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
- component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
RefreshParts()
/obj/machinery/organ_printer/examine(var/mob/user)
. = ..()
- to_chat(user, "It is loaded with [stored_matter]/[max_stored_matter] matter units.")
+ var/biomass = get_biomass_volume()
+ if(biomass)
+ to_chat(user, "It is loaded with [biomass] units of biomass.")
+ else
+ to_chat(user, "It is not loaded with any biomass.")
/obj/machinery/organ_printer/RefreshParts()
- print_delay = initial(print_delay)
- max_stored_matter = 0
- for(var/obj/item/weapon/stock_parts/matter_bin/bin in component_parts)
- max_stored_matter += bin.rating * 100
+ // Print Delay updating
+ print_delay = base_print_delay
for(var/obj/item/weapon/stock_parts/manipulator/manip in component_parts)
print_delay -= (manip.rating-1)*10
print_delay = max(0,print_delay)
+
. = ..()
/obj/machinery/organ_printer/attack_hand(mob/user)
@@ -91,6 +95,14 @@
to_chat(user, "\The [src] is busy!")
return
+ if(container)
+ var/response = alert(user, "What do you want to do?", "Bioprinter Menu", "Print Limbs", "Cancel")
+ if(response == "Print Limbs")
+ printing_menu(user)
+ else
+ to_chat(user, "\The [src] can't operate without a reagent reservoir!")
+
+/obj/machinery/organ_printer/proc/printing_menu(mob/user)
var/choice = input("What would you like to print?") as null|anything in products
if(!choice || printing || (stat & (BROKEN|NOPOWER)))
@@ -99,7 +111,7 @@
if(!can_print(choice))
return
- stored_matter -= products[choice][2]
+ container.reagents.remove_reagent("biomass", products[choice][2])
use_power = 2
printing = 1
@@ -118,9 +130,42 @@
print_organ(choice)
+ return
+
+/obj/machinery/organ_printer/verb/eject_beaker()
+ set name = "Eject Beaker"
+ set category = "Object"
+ set src in oview(1)
+
+ if(usr.stat != 0)
+ return
+ add_fingerprint(usr)
+ remove_beaker()
+ return
+
+// Does exactly what it says it does
+// Returns 1 if it succeeds, 0 if it fails. Added in case someone wants to add messages to the user.
+/obj/machinery/organ_printer/proc/remove_beaker()
+ if(container)
+ container.forceMove(get_turf(src))
+ container = null
+ return 1
+ return 0
+
+// Checks for reagents, then reports how much biomass it has in it
+/obj/machinery/organ_printer/proc/get_biomass_volume()
+ var/biomass_count = 0
+ if(container && container.reagents)
+ for(var/datum/reagent/R in container.reagents.reagent_list)
+ if(R.id == "biomass")
+ biomass_count += R.volume
+
+ return biomass_count
+
/obj/machinery/organ_printer/proc/can_print(var/choice)
- if(stored_matter < products[choice][2])
- visible_message("\The [src] displays a warning: 'Not enough matter. [stored_matter] stored and [products[choice][2]] needed.'")
+ var/biomass = get_biomass_volume()
+ if(biomass < products[choice][2])
+ visible_message("\The [src] displays a warning: 'Not enough biomass. [biomass] stored and [products[choice][2]] needed.'")
return 0
if(!loaded_dna || !loaded_dna["donor"])
@@ -162,6 +207,59 @@
/obj/item/weapon/stock_parts/matter_bin = 2,
/obj/item/weapon/stock_parts/manipulator = 2)
+// FLESH ORGAN PRINTER
+/obj/machinery/organ_printer/flesh
+ name = "bioprinter"
+ desc = "It's a machine that prints replacement organs."
+ icon_state = "bioprinter"
+ circuit = /obj/item/weapon/circuitboard/bioprinter
+
+/obj/machinery/organ_printer/flesh/full/New()
+ . = ..()
+ container = new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src)
+
+/obj/machinery/organ_printer/flesh/dismantle()
+ var/turf/T = get_turf(src)
+ if(T)
+ if(container)
+ container.forceMove(T)
+ container = null
+ return ..()
+
+/obj/machinery/organ_printer/flesh/print_organ(var/choice)
+ var/obj/item/organ/O = ..()
+
+ playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
+ visible_message("\The [src] dings, then spits out \a [O].")
+ return O
+
+/obj/machinery/organ_printer/flesh/attackby(obj/item/weapon/W, mob/user)
+ // DNA sample from syringe.
+ if(istype(W,/obj/item/weapon/reagent_containers/syringe)) //TODO: Make this actually empty the syringe
+ var/obj/item/weapon/reagent_containers/syringe/S = W
+ var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood
+ if(injected && injected.data)
+ loaded_dna = injected.data
+ S.reagents.remove_reagent("blood", injected.volume)
+ to_chat(user, "You scan the blood sample into the bioprinter.")
+ return
+ else if(istype(W,/obj/item/weapon/reagent_containers/glass))
+ var/obj/item/weapon/reagent_containers/glass/G = W
+ if(container)
+ to_chat(user, "\The [src] already has a container loaded!")
+ return
+ else if(do_after(user, 1 SECOND))
+ user.visible_message("[user] has loaded \the [G] into \the [src].", "You load \the [G] into \the [src].")
+ container = G
+ user.drop_item()
+ G.forceMove(src)
+ return
+
+ return ..()
+// END FLESH ORGAN PRINTER
+
+
+/* Roboprinter is made obsolete by the system already in place and mapped into Robotics
/obj/item/weapon/circuitboard/roboprinter
name = "roboprinter circuit"
build_path = /obj/machinery/organ_printer/robot
@@ -224,53 +322,4 @@
return
return ..()
// END ROBOT ORGAN PRINTER
-
-// FLESH ORGAN PRINTER
-/obj/machinery/organ_printer/flesh
- name = "bioprinter"
- desc = "It's a machine that prints replacement organs."
- icon_state = "bioprinter"
- circuit = /obj/item/weapon/circuitboard/bioprinter
-
- var/amount_per_slab = 50
-
-/obj/machinery/organ_printer/flesh/full/New()
- . = ..()
- stored_matter = max_stored_matter
-
-/obj/machinery/organ_printer/flesh/dismantle()
- var/turf/T = get_turf(src)
- if(T)
- while(stored_matter >= amount_per_slab)
- stored_matter -= amount_per_slab
- new /obj/item/weapon/reagent_containers/food/snacks/meat(T)
- return ..()
-
-/obj/machinery/organ_printer/flesh/print_organ(var/choice)
- var/obj/item/organ/O = ..()
-
- playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
- visible_message("\The [src] dings, then spits out \a [O].")
- return O
-
-/obj/machinery/organ_printer/flesh/attackby(obj/item/weapon/W, mob/user)
- // Load with matter for printing.
- if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat))
- if((max_stored_matter - stored_matter) < amount_per_slab)
- to_chat(user, "\The [src] is too full.")
- return
- stored_matter += amount_per_slab
- user.drop_item()
- to_chat(user, "\The [src] processes \the [W]. Levels of stored biomass now: [stored_matter]")
- qdel(W)
- return
- // DNA sample from syringe.
- else if(istype(W,/obj/item/weapon/reagent_containers/syringe)) //TODO: Make this actually empty the syringe
- var/obj/item/weapon/reagent_containers/syringe/S = W
- var/datum/reagent/blood/injected = locate() in S.reagents.reagent_list //Grab some blood
- if(injected && injected.data)
- loaded_dna = injected.data
- to_chat(user, "You scan the blood sample into the bioprinter.")
- return
- return ..()
-// END FLESH ORGAN PRINTER
\ No newline at end of file
+*/
\ No newline at end of file
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 4239a946fd8..69681d1775b 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -23,7 +23,7 @@
break
return selected
-#define CLONE_BIOMASS 150
+#define CLONE_BIOMASS 60
/obj/machinery/clonepod
name = "cloning pod"
@@ -33,17 +33,18 @@
circuit = /obj/item/weapon/circuitboard/clonepod
icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0"
- req_access = list(access_genetics) //For premature unlocking.
+ req_access = list(access_genetics) // For premature unlocking.
var/mob/living/occupant
- var/heal_level = 20 //The clone is released once its health reaches this level.
+ var/heal_level = 20 // The clone is released once its health reaches this level.
var/heal_rate = 1
- var/notoxin = 0
var/locked = 0
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
- var/mess = 0 //Need to clean out it if it's full of exploded clone.
- var/attempting = 0 //One clone attempt at a time thanks
- var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk
- var/biomass = CLONE_BIOMASS * 3
+ var/mess = 0 // Need to clean out it if it's full of exploded clone.
+ var/attempting = 0 // One clone attempt at a time thanks
+ var/eject_wait = 0 // Don't eject them as soon as they are created fuckkk
+
+ var/list/containers = list() // Beakers for our liquid biomass
+ var/container_limit = 3 // How many beakers can the machine hold?
/obj/machinery/clonepod/New()
..()
@@ -71,8 +72,6 @@
to_chat(user, "Current clone cycle is [round(completion)]% complete.")
return
-//Clonepod
-
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(var/datum/dna2/record/R)
if(mess || attempting)
@@ -98,6 +97,9 @@
if(istype(modifier_type, /datum/modifier/no_clone))
return 0
+ // Remove biomass when the cloning is started, rather than when the guy pops out
+ remove_biomass(CLONE_BIOMASS)
+
attempting = 1 //One at a time!!
locked = 1
@@ -164,6 +166,7 @@
for(var/datum/language/L in R.languages)
H.add_language(L.name)
+
H.flavor_texts = R.flavor.Copy()
H.suiciding = 0
attempting = 0
@@ -171,16 +174,6 @@
//Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process()
-
- var/visible_message = 0
- for(var/obj/item/weapon/reagent_containers/food/snacks/meat/meat in range(1, src))
- qdel(meat)
- biomass += 50
- visible_message = 1 // Prevent chatspam when multiple meat are near
-
- if(visible_message)
- visible_message("[src] sucks in and processes the nearby biomass.")
-
if(stat & NOPOWER) //Autoeject if power is lost
if(occupant)
locked = 0
@@ -250,11 +243,14 @@
else
locked = 0
to_chat(user, "System unlocked.")
- else if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat))
- to_chat(user, "\The [src] processes \the [W].")
- biomass += 50
- user.drop_item()
- qdel(W)
+ else if(istype(W,/obj/item/weapon/reagent_containers/glass))
+ if(LAZYLEN(containers) >= container_limit)
+ to_chat(user, "\The [src] has too many containers loaded!")
+ else if(do_after(user, 1 SECOND))
+ user.visible_message("[user] has loaded \the [W] into \the [src].", "You load \the [W] into \the [src].")
+ containers += W
+ user.drop_item()
+ W.forceMove(src)
return
else if(W.is_wrench())
if(locked && (anchored || occupant))
@@ -271,7 +267,7 @@
user.visible_message("[user] secures [src] to the floor.", "You secure [src] to the floor.")
else
user.visible_message("[user] unsecures [src] from the floor.", "You unsecure [src] from the floor.")
- else if(W.is_multitool())
+ else if(istype(W, /obj/item/device/multitool))
var/obj/item/device/multitool/M = W
M.connecting = src
to_chat(user, "You load connection data from [src] to [M].")
@@ -308,10 +304,6 @@
heal_level = rating * 10 - 20
heal_rate = round(rating / 4)
- if(rating >= 8)
- notoxin = 1
- else
- notoxin = 0
/obj/machinery/clonepod/verb/eject()
set name = "Eject Cloner"
@@ -348,10 +340,66 @@
domutcheck(occupant) //Waiting until they're out before possible transforming.
occupant = null
- biomass -= CLONE_BIOMASS
update_icon()
return
+// Returns the total amount of biomass reagent in all of the pod's stored containers
+/obj/machinery/clonepod/proc/get_biomass()
+ var/biomass_count = 0
+ if(LAZYLEN(containers))
+ for(var/obj/item/weapon/reagent_containers/glass/G in containers)
+ for(var/datum/reagent/R in G.reagents.reagent_list)
+ if(R.id == "biomass")
+ biomass_count += R.volume
+
+ return biomass_count
+
+// Removes [amount] biomass, spread across all containers. Doesn't have any check that you actually HAVE enough biomass, though.
+/obj/machinery/clonepod/proc/remove_biomass(var/amount = CLONE_BIOMASS) //Just in case it doesn't get passed a new amount, assume one clone
+ var/to_remove = 0 // Tracks how much biomass has been found so far
+ if(LAZYLEN(containers))
+ for(var/obj/item/weapon/reagent_containers/glass/G in containers)
+ if(to_remove < amount) //If we have what we need, we can stop. Checked every time we switch beakers
+ for(var/datum/reagent/R in G.reagents.reagent_list)
+ if(R.id == "biomass") // Finds Biomass
+ var/need_remove = max(0, amount - to_remove) //Figures out how much biomass is in this container
+ if(R.volume >= need_remove) //If we have more than enough in this beaker, only take what we need
+ R.remove_self(need_remove)
+ to_remove = amount
+ else //Otherwise, take everything and move on
+ to_remove += R.volume
+ R.remove_self(R.volume)
+ else
+ continue
+ else
+ return 1
+ return 0
+
+// Empties all of the beakers from the cloning pod, used to refill it
+/obj/machinery/clonepod/verb/empty_beakers()
+ set name = "Eject Beakers"
+ set category = "Object"
+ set src in oview(1)
+
+ if(usr.stat != 0)
+ return
+
+ add_fingerprint(usr)
+ drop_beakers()
+ return
+
+// Actually does all of the beaker dropping
+// Returns 1 if it succeeds, 0 if it fails. Added in case someone wants to add messages to the user.
+/obj/machinery/clonepod/proc/drop_beakers()
+ if(LAZYLEN(containers))
+ var/turf/T = get_turf(src)
+ if(T)
+ for(var/obj/item/weapon/reagent_containers/glass/G in containers)
+ G.forceMove(T)
+ containers -= G
+ return 1
+ return 0
+
/obj/machinery/clonepod/proc/malfunction()
if(occupant)
connected_message("Critical Error!")
@@ -406,6 +454,12 @@
else if(mess)
icon_state = "pod_g"
+
+/obj/machinery/clonepod/full/New()
+ ..()
+ for(var/i = 1 to container_limit)
+ containers += new /obj/item/weapon/reagent_containers/glass/bottle/biomass(src)
+
//Health Tracker Implant
/obj/item/weapon/implant/health
@@ -479,7 +533,7 @@
/obj/item/weapon/disk/data/examine(mob/user)
..(user)
- to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
+ to_chat(user, text("The write-protect tab is set to [read_only ? "protected" : "unprotected"]."))
return
/*
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index 334b4a97af1..cb66b376eb5 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -200,6 +200,8 @@ GLOBAL_LIST_BOILERPLATE(all_deactivated_AI_cores, /obj/structure/AIcore/deactiva
if(!istype(transfer) || locate(/mob/living/silicon/ai) in src)
return
+ if(transfer.controlling_drone)
+ transfer.controlling_drone.release_ai_control("Unit control lost. Core transfer completed.")
transfer.aiRestorePowerRoutine = 0
transfer.control_disabled = 0
transfer.aiRadio.disabledAi = 0
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 4935a2a552e..9660eca8bcb 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -67,7 +67,7 @@
user.drop_item()
W.loc = src
diskette = W
- user << "You insert [W]."
+ to_chat(user, "You insert [W].")
updateUsrDialog()
return
else if(istype(W, /obj/item/device/multitool))
@@ -77,7 +77,7 @@
pods += P
P.connected = src
P.name = "[initial(P.name)] #[pods.len]"
- user << "You connect [P] to [src]."
+ to_chat(user, "You connect [P] to [src].")
else if (menu == 4 && (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda)))
if(check_access(W))
@@ -116,7 +116,7 @@
var/pods_list_ui[0]
for(var/obj/machinery/clonepod/pod in pods)
- pods_list_ui[++pods_list_ui.len] = list("pod" = pod, "biomass" = pod.biomass)
+ pods_list_ui[++pods_list_ui.len] = list("pod" = pod, "biomass" = pod.get_biomass())
if(pods)
data["pods"] = pods_list_ui
@@ -244,7 +244,7 @@
//Look for that player! They better be dead!
if(istype(C))
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
- if(!pods.len)
+ if(!LAZYLEN(pods))
temp = "Error: No clone pods detected."
else
var/obj/machinery/clonepod/pod = pods[1]
@@ -252,13 +252,12 @@
pod = input(usr,"Select a cloning pod to use", "Pod selection") as anything in pods
if(pod.occupant)
temp = "Error: Clonepod is currently occupied."
- else if(pod.biomass < CLONE_BIOMASS)
+ else if(pod.get_biomass() < CLONE_BIOMASS)
temp = "Error: Not enough biomass."
else if(pod.mess)
temp = "Error: Clonepod malfunction."
else if(!config.revival_cloning)
temp = "Error: Unable to initiate cloning cycle."
-
else if(pod.growclone(C))
temp = "Initiating cloning cycle..."
records.Remove(C)
diff --git a/code/game/machinery/computer3/laptop.dm b/code/game/machinery/computer3/laptop.dm
index 38db5742006..9a8ba02b002 100644
--- a/code/game/machinery/computer3/laptop.dm
+++ b/code/game/machinery/computer3/laptop.dm
@@ -28,6 +28,9 @@
var/obj/machinery/computer3/laptop/stored_computer = null
+/obj/item/device/laptop/get_cell()
+ return stored_computer.battery
+
/obj/item/device/laptop/verb/open_computer()
set name = "Open Laptop"
set category = "Object"
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 2bfb502a5bd..b3e0462af7a 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -47,6 +47,7 @@
var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg
var/check_all = 0 //If active, will fire on anything, including synthetics.
var/ailock = 0 // AI cannot use this
+ var/faction = null //if set, will not fire at people in the same faction for any reason.
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
@@ -80,6 +81,11 @@
lethal = 1
installation = /obj/item/weapon/gun/energy/laser
+/obj/machinery/porta_turret/stationary/syndie // Generic turrets for POIs that need to not shoot their buddies.
+ enabled = TRUE
+ check_all = TRUE
+ faction = "syndicate" // Make sure this equals the faction that the mobs in the POI have or they will fight each other.
+
/obj/machinery/porta_turret/ai_defense
name = "defense turret"
desc = "This variant appears to be much more durable."
@@ -552,6 +558,9 @@ var/list/turret_icons
if(!L)
return TURRET_NOT_TARGET
+ if(faction && L.faction == faction)
+ return TURRET_NOT_TARGET
+
if(!emagged && issilicon(L) && check_all == 0) // Don't target silica, unless told to neutralize everything.
return TURRET_NOT_TARGET
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index d9cfb5d9f85..ddd50a8f50a 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -41,35 +41,12 @@ obj/machinery/recharger
return
if(istype(G, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = G
- if(!E.power_supply)
- to_chat(user, "Your gun has no power cell.")
- return
if(E.self_recharge)
to_chat(user, "Your gun has no recharge port.")
return
- if(istype(G, /obj/item/weapon/gun/energy/staff))
+ if(!G.get_cell())
+ to_chat(user, "This device does not have a battery installed.")
return
- if(istype(G, /obj/item/device/flashlight))
- var/obj/item/device/flashlight/F = G
- if(!F.power_use)
- return
- if(!F.cell)
- return
- if(istype(G, /obj/item/device/laptop))
- var/obj/item/device/laptop/L = G
- if(!L.stored_computer.battery)
- user << "There's no battery in it!"
- return
- if(istype(G, /obj/item/device/electronic_assembly))
- var/obj/item/device/electronic_assembly/assembly = G
- if(!assembly.battery)
- to_chat(user, "The assembly doesn't have a power cell.")
- return
- if(istype(G, /obj/item/weapon/weldingtool/electric))
- var/obj/item/weapon/weldingtool/electric/welder = G
- if(!welder.power_supply)
- to_chat(user, "Your welder has no power cell.")
- return
user.drop_item()
G.loc = src
@@ -109,71 +86,8 @@ obj/machinery/recharger
update_use_power(1)
icon_state = icon_state_idle
else
- if(istype(charging, /obj/item/weapon/gun/energy))
- var/obj/item/weapon/gun/energy/E = charging
- if(!E.power_supply.fully_charged())
- icon_state = icon_state_charging
- E.power_supply.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- return
-
- if(istype(charging, /obj/item/weapon/gun/magnetic))
- var/obj/item/weapon/gun/magnetic/M = charging
- if(!M.cell.fully_charged())
- icon_state = icon_state_charging
- M.cell.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- return
-
- if(istype(charging, /obj/item/weapon/melee/baton))
- var/obj/item/weapon/melee/baton/B = charging
- if(B.bcell)
- if(!B.bcell.fully_charged())
- icon_state = icon_state_charging
- B.bcell.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- else
- icon_state = icon_state_idle
- update_use_power(1)
- return
-
- if(istype(charging, /obj/item/device/laptop))
- var/obj/item/device/laptop/L = charging
- if(!L.stored_computer.battery.fully_charged())
- icon_state = icon_state_charging
- L.stored_computer.battery.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- return
-
- if(istype(charging, /obj/item/device/flashlight))
- var/obj/item/device/flashlight/F = charging
- if(F.cell)
- if(!F.cell.fully_charged())
- icon_state = icon_state_charging
- F.cell.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- else
- icon_state = icon_state_idle
- update_use_power(1)
- return
-
- if(istype(charging, /obj/item/weapon/cell))
- var/obj/item/weapon/cell/C = charging
+ var/obj/item/weapon/cell/C = charging.get_cell()
+ if(istype(C))
if(!C.fully_charged())
icon_state = icon_state_charging
C.give(active_power_usage*CELLRATE)
@@ -181,48 +95,17 @@ obj/machinery/recharger
else
icon_state = icon_state_charged
update_use_power(1)
- return
-
- if(istype(charging, /obj/item/device/electronic_assembly))
- var/obj/item/device/electronic_assembly/assembly = charging
- if(assembly.battery)
- if(!assembly.battery.fully_charged())
- icon_state = icon_state_charging
- assembly.battery.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- else
- icon_state = icon_state_idle
- update_use_power(1)
- return
-
- if(istype(charging, /obj/item/weapon/weldingtool/electric))
- var/obj/item/weapon/weldingtool/electric/C = charging
- if(!C.power_supply.fully_charged())
- icon_state = icon_state_charging
- C.power_supply.give(active_power_usage*CELLRATE)
- update_use_power(2)
- else
- icon_state = icon_state_charged
- update_use_power(1)
- return
/obj/machinery/recharger/emp_act(severity)
if(stat & (NOPOWER|BROKEN) || !anchored)
..(severity)
return
- if(istype(charging, /obj/item/weapon/gun/energy))
- var/obj/item/weapon/gun/energy/E = charging
- if(E.power_supply)
- E.power_supply.emp_act(severity)
+ if(charging)
+ var/obj/item/weapon/cell/C = charging.get_cell()
+ if(istype(C))
+ C.emp_act(severity)
- else if(istype(charging, /obj/item/weapon/melee/baton))
- var/obj/item/weapon/melee/baton/B = charging
- if(B.bcell)
- B.bcell.charge = 0
..(severity)
/obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
@@ -231,7 +114,6 @@ obj/machinery/recharger
else
icon_state = icon_state_idle
-
/obj/machinery/recharger/wallcharger
name = "wall recharger"
icon = 'icons/obj/stationobjs.dmi'
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 90f708ff9df..0369b91d63b 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -248,6 +248,6 @@ var/global/list/image/splatter_cache=list()
//This version should be used for admin spawns and pre-mapped virus vectors (e.g. in PoIs), this version does not dry
/obj/effect/decal/cleanable/mucus/mapped/New()
- ...()
+ ..()
virus2 = new /datum/disease2/disease
virus2.makerandom()
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index aaebab43550..d7db6f2a0c7 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -46,4 +46,21 @@
/obj/effect/temporary_effect/shuttle_landing/initialize()
flick("shuttle_warning", src) // flick() forces the animation to always begin at the start.
+ . = ..()
+
+// The manifestation of Zeus's might. Or just a really unlucky day.
+// This is purely a visual effect, this isn't the part of the code that hurts things.
+/obj/effect/temporary_effect/lightning_strike
+ name = "lightning"
+ desc = "How shocked you must be, to see this text. You must have lightning reflexes. \
+ The humor in this description is just so electrifying."
+ icon = 'icons/effects/96x256.dmi'
+ icon_state = "lightning_strike"
+ plane = PLANE_LIGHTING_ABOVE
+ time_to_die = 1 SECOND
+ pixel_x = -32
+
+/obj/effect/temporary_effect/lightning_strike/initialize()
+ icon_state += "[rand(1,2)]" // To have two variants of lightning sprites.
+ animate(src, alpha = 0, time = time_to_die - 1)
. = ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm
index 08f369d735e..dc4bf5146ab 100644
--- a/code/game/objects/effects/portals.dm
+++ b/code/game/objects/effects/portals.dm
@@ -31,6 +31,7 @@ GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal)
return
/obj/effect/portal/New()
+ ..() // Necessary for the list boilerplate to work
spawn(300)
qdel(src)
return
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 1f754ff2ca3..5df1daff3d4 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -1254,7 +1254,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(isnull(cartridge))
to_chat(usr, "There's no cartridge to eject.")
- return
+ return
cartridge.forceMove(get_turf(src))
if(ismob(loc))
@@ -1382,7 +1382,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
to_chat(user, "Blood type: [C:blood_DNA[blood]]\nDNA: [blood]")
if(4)
- user.visible_message("\The [user] has analyzed [C]'s radiation levels!", 1)
+ user.visible_message("\The [user] has analyzed [C]'s radiation levels!", "You have analyzed [C]'s radiation levels!")
to_chat(user, "Analyzing Results for [C]:")
if(C.radiation)
to_chat(user, "Radiation Level: [C.radiation]")
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index b57c67bac09..7e288dbadcf 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -64,20 +64,24 @@
add_attack_logs(user,carded_ai,"Purged from AI Card")
flush = 1
carded_ai.suiciding = 1
- carded_ai << "Your power has been disabled!"
+ to_chat(carded_ai, "Your power has been disabled!")
while (carded_ai && carded_ai.stat != 2)
+ if(carded_ai.controlling_drone && prob(carded_ai.oxyloss)) //You feel it creeping? Eventually will reach 100, resulting in the second half of the AI's remaining life being lonely.
+ carded_ai.controlling_drone.release_ai_control("Unit lost. Integrity too low to maintain connection.")
carded_ai.adjustOxyLoss(2)
carded_ai.updatehealth()
sleep(10)
flush = 0
if (href_list["radio"])
carded_ai.aiRadio.disabledAi = text2num(href_list["radio"])
- carded_ai << "Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!"
- user << "You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver."
+ to_chat(carded_ai, "Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!")
+ to_chat(user, "You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.")
if (href_list["wireless"])
carded_ai.control_disabled = text2num(href_list["wireless"])
- carded_ai << "Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!"
- user << "You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface."
+ to_chat(carded_ai, "Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!")
+ to_chat(user, "You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.")
+ if(carded_ai.control_disabled && carded_ai.controlling_drone)
+ carded_ai.controlling_drone.release_ai_control("Unit control terminated at intellicore port.")
update_icon()
return 1
@@ -94,12 +98,12 @@
icon_state = "aicard"
/obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user)
- if(!ai.client)
- user << "ERROR: AI [ai.name] is offline. Unable to transfer."
+ if(!ai.client && !ai.controlling_drone)
+ to_chat(user, "ERROR: AI [ai.name] is offline. Unable to transfer.")
return 0
if(carded_ai)
- user << "Transfer failed: Existing AI found on remote device. Remove existing AI to install a new one."
+ to_chat(user, "Transfer failed: Existing AI found on remote device. Remove existing AI to install a new one.")
return 0
if(!user.IsAdvancedToolUser() && isanimal(user))
@@ -108,7 +112,9 @@
return 0
user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...")
- ai << "\The [user] is transferring you into \the [src]!"
+ to_chat(ai, "\The [user] is transferring you into \the [src]!")
+ if(ai.controlling_drone)
+ to_chat(ai.controlling_drone, "\The [user] is transferring you into \the [src]!")
if(do_after(user, 100))
if(istype(ai.loc, /turf/))
@@ -124,11 +130,13 @@
ai.control_disabled = 1
ai.aiRestorePowerRoutine = 0
carded_ai = ai
+ if(ai.controlling_drone)
+ ai.controlling_drone.release_ai_control("Unit control lost.")
if(ai.client)
- ai << "You have been transferred into a mobile core. Remote access lost."
+ to_chat(ai, "You have been transferred into a mobile core. Remote access lost.")
if(user.client)
- user << "Transfer successful: [ai.name] extracted from current device and placed within mobile core."
+ to_chat(ai, "Transfer successful: [ai.name] extracted from current device and placed within mobile core.")
ai.canmove = 1
update_icon()
diff --git a/code/game/objects/items/devices/communicator/UI.dm b/code/game/objects/items/devices/communicator/UI.dm
index 4d6ff75c50a..fca4cf4866d 100644
--- a/code/game/objects/items/devices/communicator/UI.dm
+++ b/code/game/objects/items/devices/communicator/UI.dm
@@ -69,17 +69,16 @@
im_list_ui[++im_list_ui.len] = list("address" = I["address"], "to_address" = I["to_address"], "im" = I["im"])
//Weather reports.
- if(planet_controller)
- for(var/datum/planet/planet in planet_controller.planets)
- if(planet.weather_holder && planet.weather_holder.current_weather)
- var/list/W = list(
- "Planet" = planet.name,
- "Time" = planet.current_time.show_time("hh:mm"),
- "Weather" = planet.weather_holder.current_weather.name,
- "Temperature" = planet.weather_holder.temperature - T0C,
- "High" = planet.weather_holder.current_weather.temp_high - T0C,
- "Low" = planet.weather_holder.current_weather.temp_low - T0C)
- weather[++weather.len] = W
+ for(var/datum/planet/planet in SSplanets.planets)
+ if(planet.weather_holder && planet.weather_holder.current_weather)
+ var/list/W = list(
+ "Planet" = planet.name,
+ "Time" = planet.current_time.show_time("hh:mm"),
+ "Weather" = planet.weather_holder.current_weather.name,
+ "Temperature" = planet.weather_holder.temperature - T0C,
+ "High" = planet.weather_holder.current_weather.temp_high - T0C,
+ "Low" = planet.weather_holder.current_weather.temp_low - T0C)
+ weather[++weather.len] = W
injection = "Test
"
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index d69c2c9d928..44d3c98c8c4 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -41,6 +41,9 @@
processing_objects -= src
return ..()
+/obj/item/device/flashlight/get_cell()
+ return cell
+
/obj/item/device/flashlight/verb/toggle()
set name = "Toggle Flashlight Brightness"
set category = "Object"
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index ca4b8d8066e..9c9f1aba598 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -10,44 +10,162 @@
var/insults = 0
var/list/insultmsg = list("FUCK EVERYONE!", "I'M A TERRORIST!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "GLORY TO ALMACH!")
-/obj/item/device/megaphone/attack_self(mob/living/user as mob)
+/obj/item/device/megaphone/proc/can_broadcast(var/mob/living/user)
if (user.client)
if(user.client.prefs.muted & MUTE_IC)
- src << "You cannot speak in IC (muted)."
- return
- if(!ishuman(user))
- user << "You don't know how to use this!"
- return
+ to_chat(user, "You cannot speak in IC (muted).")
+ return 0
+ if(!(ishuman(user) || user.isSynthetic()))
+ to_chat(user, "You don't know how to use this!")
+ return 0
if(user.silent)
- return
+ return 0
if(spamcheck)
- user << "\The [src] needs to recharge!"
- return
+ to_chat(user, "\The [src] needs to recharge!")
+ return 0
+ return 1
- var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text)
- if(!message)
- return
- message = capitalize(message)
+/obj/item/device/megaphone/proc/do_broadcast(var/mob/living/user, var/message)
if ((src.loc == user && usr.stat == 0))
if(emagged)
if(insults)
- for(var/mob/O in (viewers(user)))
- O.show_message("[user] broadcasts, \"[pick(insultmsg)]\"",2) // 2 stands for hearable message
+ user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"")
insults--
else
- user << "*BZZZZzzzzzt*"
+ to_chat(user, "*BZZZZzzzzzt*")
else
- for(var/mob/O in (viewers(user)))
- O.show_message("[user] broadcasts, \"[message]\"",2) // 2 stands for hearable message
+ user.audible_message("[user] broadcasts, \"[message]\"")
spamcheck = 1
spawn(20)
spamcheck = 0
return
+/obj/item/device/megaphone/attack_self(mob/living/user as mob)
+ if(!can_broadcast(user))
+ return
+
+ var/message = sanitize(input(user, "Shout a message?", "Megaphone", null) as text)
+ if(!message)
+ return
+ message = capitalize(message)
+
+ do_broadcast(user, message)
+
/obj/item/device/megaphone/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
- user << "You overload \the [src]'s voice synthesizer."
+ to_chat(user, "You overload \the [src]'s voice synthesizer.")
emagged = 1
- insults = rand(1, 3)//to prevent dickflooding
+ insults = rand(1, 3)//to prevent caps spam.
return 1
+
+/obj/item/device/megaphone/super
+ name = "gigaphone"
+ desc = "A device used to project your voice. Loudly-er."
+ icon_state = "gigaphone"
+
+ var/broadcast_font = "verdana"
+ var/broadcast_size = 3
+ var/broadcast_color = "#000000" //Black by default.
+ var/list/volume_options = list(2, 3, 4)
+ var/list/font_options = list("times new roman", "times", "verdana", "sans-serif", "serif", "georgia")
+ var/list/color_options= list("#000000", "#ff0000", "#00ff00", "#0000ff")
+
+ insultmsg = list("HONK?!", "HONK!", "HOOOOOOOONK!", "...!", "HUNK.", "Honk?")
+
+/obj/item/device/megaphone/super/emag_act(var/remaining_charges, var/mob/user)
+ ..()
+ if(emagged)
+ if(!(11 in volume_options))
+ volume_options = list(11)
+ broadcast_size = 11
+ if(!("comic sans ms" in font_options))
+ font_options = list("comic sans ms")
+ broadcast_font = "comic sans ms"
+ to_chat(user, "\The [src] emits a silly sound.")
+ if(!("#ff69b4" in color_options))
+ color_options = list("#ff69b4")
+ broadcast_color = "#ff69b4"
+ if(insults <= 0)
+ insults = rand(1,3)
+ to_chat(user, "You re-scramble \the [src]'s voice synthesizer.")
+ return 1
+
+/obj/item/device/megaphone/super/verb/turn_volume_dial()
+ set name = "Change Volume"
+ set desc = "Allows you to change the megaphone's volume."
+ set category = "Object"
+
+ adjust_volume(usr)
+
+/obj/item/device/megaphone/super/proc/adjust_volume(var/mob/living/user)
+ var/new_volume = input(user, "Set Volume") as null|anything in volume_options
+
+ if(new_volume && Adjacent(user))
+ broadcast_size = new_volume
+
+/obj/item/device/megaphone/super/verb/change_font()
+ set name = "Change... Pronunciation?"
+ set desc = "Allows you to change the megaphone's font."
+ set category = "Object"
+
+ adjust_font(usr)
+
+/obj/item/device/megaphone/super/proc/adjust_font(var/mob/living/user)
+ var/new_font = input(user, "Set Volume") as null|anything in font_options
+
+ if(new_font && Adjacent(user))
+ broadcast_font = new_font
+
+/obj/item/device/megaphone/super/verb/change_color()
+ set name = "Change... Tune?"
+ set desc = "Allows you to change the megaphone's color."
+ set category = "Object"
+
+ adjust_color(usr)
+
+/obj/item/device/megaphone/super/proc/adjust_color(var/mob/living/user)
+ var/new_color = input(user, "Set Volume") as null|anything in color_options
+
+ if(new_color && Adjacent(user))
+ broadcast_color = new_color
+
+/obj/item/device/megaphone/super/do_broadcast(var/mob/living/user, var/message)
+ if ((src.loc == user && usr.stat == 0))
+ if(emagged)
+ if(insults)
+ user.audible_message("[user] broadcasts, \"[pick(insultmsg)]\"")
+ if(broadcast_size >= 11)
+ var/turf/T = get_turf(user)
+ playsound(T, 'sound/items/AirHorn.ogg', 100, 1)
+ for(var/mob/living/carbon/M in oviewers(4, T))
+ if(M.get_ear_protection() >= 2)
+ continue
+ M.sleeping = 0
+ M.stuttering += 20
+ M.ear_deaf += 30
+ M.Weaken(3)
+ if(prob(30))
+ M.Stun(10)
+ M.Paralyse(4)
+ else
+ M.make_jittery(50)
+ insults--
+ else
+ user.audible_message("*BZZZZzzzzzt*")
+ if(prob(40) && insults <= 0)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(2, 1, get_turf(user))
+ s.start()
+ user.visible_message("\The [src] sparks violently!")
+ spawn(30)
+ explosion(get_turf(src), -1, -1, 1, 3, adminlog = 1)
+ qdel(src)
+ return
+ else
+ user.audible_message("[user] broadcasts, \"[message]\"")
+
+ spamcheck = 1
+ spawn(20)
+ spamcheck = 0
+ return
diff --git a/code/game/objects/items/devices/radio/jammer.dm b/code/game/objects/items/devices/radio/jammer.dm
index 680b5e2b37a..868f90251ce 100644
--- a/code/game/objects/items/devices/radio/jammer.dm
+++ b/code/game/objects/items/devices/radio/jammer.dm
@@ -38,6 +38,9 @@ var/global/list/active_radio_jammers = list()
qdel_null(power_source)
return ..()
+/obj/item/device/radio_jammer/get_cell()
+ return power_source
+
/obj/item/device/radio_jammer/proc/turn_off(mob/user)
if(user)
to_chat(user,"\The [src] deactivates.")
diff --git a/code/game/objects/items/poi_items.dm b/code/game/objects/items/poi_items.dm
index 85a8b27854e..394212e4c48 100644
--- a/code/game/objects/items/poi_items.dm
+++ b/code/game/objects/items/poi_items.dm
@@ -52,8 +52,9 @@
/obj/structure/largecrate/animal/crashedshuttle
name = "SCP"
+
/obj/structure/largecrate/animal/crashedshuttle/initialize()
- starts_with = pick(/mob/living/simple_animal/hostile/statue, /obj/item/cursed_marble)
+ starts_with = pick(/mob/living/simple_animal/hostile/statue, /obj/item/cursed_marble, /obj/item/weapon/deadringer)
name = pick("Spicy Crust Pizzeria", "Soap and Care Products", "Sally's Computer Parts", "Steve's Chocolate Pastries", "Smith & Christian's Plastics","Standard Containers & Packaging Co.", "Sanitary Chemical Purgation (LTD)")
name += " delivery crate"
return ..()
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 5c17634ae26..18b13a8034a 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -199,3 +199,9 @@
throw_range = 20
flags = 0
no_variants = FALSE
+
+/obj/item/stack/tile/roofing
+ name = "roofing"
+ singular_name = "roofing"
+ desc = "A section of roofing material. You can use it to repair the ceiling, or expand it."
+ icon_state = "techtile_grid"
\ No newline at end of file
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 02a308555bb..02e121d02c1 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1042,6 +1042,50 @@
name = "tuxedo cat plushie"
icon_state = "tuxedocat"
+// nah, squids are better than foxes :>
+
+/obj/item/toy/plushie/squid/green
+ name = "green squid plushie"
+ desc = "A small, cute and loveable squid friend. This one is green."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "greensquid"
+ slot_flags = SLOT_HEAD
+
+/obj/item/toy/plushie/squid/mint
+ name = "mint squid plushie"
+ desc = "A small, cute and loveable squid friend. This one is mint coloured."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "mintsquid"
+ slot_flags = SLOT_HEAD
+
+/obj/item/toy/plushie/squid/blue
+ name = "blue squid plushie"
+ desc = "A small, cute and loveable squid friend. This one is blue."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "bluesquid"
+ slot_flags = SLOT_HEAD
+
+/obj/item/toy/plushie/squid/orange
+ name = "orange squid plushie"
+ desc = "A small, cute and loveable squid friend. This one is orange."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "orangesquid"
+ slot_flags = SLOT_HEAD
+
+/obj/item/toy/plushie/squid/yellow
+ name = "yellow squid plushie"
+ desc = "A small, cute and loveable squid friend. This one is yellow."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "yellowsquid"
+ slot_flags = SLOT_HEAD
+
+/obj/item/toy/plushie/squid/pink
+ name = "pink squid plushie"
+ desc = "A small, cute and loveable squid friend. This one is pink."
+ icon = 'icons/obj/toy.dmi'
+ icon_state = "pinksquid"
+ slot_flags = SLOT_HEAD
+
/obj/item/toy/plushie/therapy/red
name = "red therapy doll"
desc = "A toy for therapeutic and recreational purposes. This one is red."
diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm
index 58aa30547dc..d9543fed201 100644
--- a/code/game/objects/items/weapons/RCD.dm
+++ b/code/game/objects/items/weapons/RCD.dm
@@ -153,7 +153,7 @@
return 0
if(build_turf)
- T.ChangeTurf(build_turf)
+ T.ChangeTurf(build_turf, preserve_outdoors = TRUE)
else if(build_other)
new build_other(T)
else
diff --git a/code/game/objects/items/weapons/autopsy.dm b/code/game/objects/items/weapons/autopsy.dm
index d9606d28d24..7cddfd1efc6 100644
--- a/code/game/objects/items/weapons/autopsy.dm
+++ b/code/game/objects/items/weapons/autopsy.dm
@@ -167,21 +167,24 @@
if(!istype(M))
return 0
+ if (user.a_intent == I_HELP)
+ return ..()
+
if(target_name != M.name)
target_name = M.name
src.wdata = list()
src.chemtraces = list()
src.timeofdeath = null
- user << "A new patient has been registered. Purging data for previous patient."
+ to_chat(user, "A new patient has been registered. Purging data for previous patient.")
src.timeofdeath = M.timeofdeath
var/obj/item/organ/external/S = M.get_organ(user.zone_sel.selecting)
if(!S)
- usr << "You can't scan this body part."
+ to_chat(user, "You can't scan this body part.")
return
if(!S.open)
- usr << "You have to cut [S] open first!"
+ to_chat(user, "You have to cut [S] open first!")
return
M.visible_message("\The [user] scans the wounds on [M]'s [S.name] with [src]")
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 02e4cd48c44..f5bd38dcc17 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -21,12 +21,26 @@
/obj/item/weapon/implant/proc/activate()
return
- // What does the implant do upon injection?
- // return 0 if the implant fails (ex. Revhead and loyalty implant.)
- // return 1 if the implant succeeds (ex. Nonrevhead and loyalty implant.)
-/obj/item/weapon/implant/proc/implanted(var/mob/source)
+// Moves the implant where it needs to go, and tells it if there's more to be done in post_implant
+/obj/item/weapon/implant/proc/handle_implant(var/mob/source, var/target_zone = BP_TORSO)
+ . = TRUE
+ imp_in = source
+ implanted = TRUE
+ if(ishuman(source))
+ var/mob/living/carbon/human/H = source
+ var/obj/item/organ/external/affected = H.get_organ(target_zone)
+ if(affected)
+ affected.implants += src
+ part = affected
+ if(part)
+ forceMove(part)
+ else
+ forceMove(source)
+
listening_objects |= src
- return 1
+
+// Takes place after handle_implant, if that returns TRUE
+/obj/item/weapon/implant/proc/post_implant(var/mob/source)
/obj/item/weapon/implant/proc/get_data()
return "No information available"
@@ -49,6 +63,12 @@
icon_state = "implant_melted"
malfunction = MALFUNCTION_PERMANENT
+/obj/item/weapon/implant/proc/implant_loadout(var/mob/living/carbon/human/H)
+ if(H)
+ var/obj/item/organ/external/affected = H.organs_by_name[BP_HEAD]
+ if(handle_implant(H, affected))
+ post_implant(H)
+
/obj/item/weapon/implant/Destroy()
if(part)
part.implants.Remove(src)
@@ -69,6 +89,11 @@
else
..()
+
+
+//////////////////////////////
+// Tracking Implant
+//////////////////////////////
GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking)
/obj/item/weapon/implant/tracking
@@ -84,9 +109,8 @@ GLOBAL_LIST_BOILERPLATE(all_tracking_implants, /obj/item/weapon/implant/tracking
id = rand(1, 1000)
..()
-/obj/item/weapon/implant/tracking/implanted(var/mob/source)
+/obj/item/weapon/implant/tracking/post_implant(var/mob/source)
processing_objects.Add(src)
- return 1
/obj/item/weapon/implant/tracking/Destroy()
processing_objects.Remove(src)
@@ -142,7 +166,9 @@ Implant Specifics:
"}
spawn(delay)
malfunction--
-
+//////////////////////////////
+// Death Explosive Implant
+//////////////////////////////
/obj/item/weapon/implant/dexplosive
name = "explosive"
desc = "And boom goes the weasel."
@@ -177,7 +203,9 @@ Implant Specifics:
"}
/obj/item/weapon/implant/dexplosive/islegal()
return 0
-//BS12 Explosive
+//////////////////////////////
+// Explosive Implant
+//////////////////////////////
/obj/item/weapon/implant/explosive
name = "explosive implant"
desc = "A military grade micro bio-explosive. Highly dangerous."
@@ -249,15 +277,13 @@ Implant Specifics:
"}
if(t)
t.hotspot_expose(3500,125)
-/obj/item/weapon/implant/explosive/implanted(mob/source as mob)
+/obj/item/weapon/implant/explosive/post_implant(mob/source as mob)
elevel = alert("What sort of explosion would you prefer?", "Implant Intent", "Localized Limb", "Destroy Body", "Full Explosion")
phrase = input("Choose activation phrase:") as text
var/list/replacechars = list("'" = "","\"" = "",">" = "","<" = "","(" = "",")" = "")
phrase = replace_characters(phrase, replacechars)
usr.mind.store_memory("Explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate.", 0, 0)
usr << "The implanted explosive implant in [source] can be activated by saying something containing the phrase ''[src.phrase]'', say [src.phrase] to attempt to activate."
- listening_objects |= src
- return 1
/obj/item/weapon/implant/explosive/emp_act(severity)
if (malfunction)
@@ -311,6 +337,9 @@ Implant Specifics:
"}
explosion(get_turf(imp_in), -1, -1, 1, 3)
qdel(src)
+//////////////////////////////
+// Chemical Implant
+//////////////////////////////
GLOBAL_LIST_BOILERPLATE(all_chem_implants, /obj/item/weapon/implant/chem)
/obj/item/weapon/implant/chem
@@ -336,20 +365,17 @@ Can only be loaded while still in its original case.
the implant may become unstable and either pre-maturely inject the subject or simply break."}
return dat
-
/obj/item/weapon/implant/chem/New()
..()
var/datum/reagents/R = new/datum/reagents(50)
reagents = R
R.my_atom = src
-
/obj/item/weapon/implant/chem/trigger(emote, source as mob)
if(emote == "deathgasp")
src.activate(src.reagents.total_volume)
return
-
/obj/item/weapon/implant/chem/activate(var/cause)
if((!cause) || (!src.imp_in)) return 0
var/mob/living/carbon/R = src.imp_in
@@ -384,6 +410,9 @@ the implant may become unstable and either pre-maturely inject the subject or si
spawn(20)
malfunction--
+//////////////////////////////
+// Loyalty Implant
+//////////////////////////////
/obj/item/weapon/implant/loyalty
name = "loyalty implant"
desc = "Makes you loyal or such."
@@ -401,20 +430,24 @@ the implant may become unstable and either pre-maturely inject the subject or si
Integrity: Implant will last so long as the nanobots are inside the bloodstream."}
return dat
-
-/obj/item/weapon/implant/loyalty/implanted(mob/M)
- if(!istype(M, /mob/living/carbon/human)) return 0
+/obj/item/weapon/implant/loyalty/handle_implant(mob/M, target_zone = BP_TORSO)
+ . = ..(M, target_zone)
+ if(!istype(M, /mob/living/carbon/human))
+ . = FALSE
var/mob/living/carbon/human/H = M
var/datum/antagonist/antag_data = get_antag_data(H.mind.special_role)
if(antag_data && (antag_data.flags & ANTAG_IMPLANT_IMMUNE))
H.visible_message("[H] seems to resist the implant!", "You feel the corporate tendrils of [using_map.company_name] try to invade your mind!")
- return 0
- else
- clear_antag_roles(H.mind, 1)
- H << "You feel a surge of loyalty towards [using_map.company_name]."
- return 1
+ . = FALSE
+/obj/item/weapon/implant/loyalty/post_implant(mob/M)
+ var/mob/living/carbon/human/H = M
+ clear_antag_roles(H.mind, 1)
+ to_chat(H, "You feel a surge of loyalty towards [using_map.company_name].")
+//////////////////////////////
+// Adrenaline Implant
+//////////////////////////////
/obj/item/weapon/implant/adrenalin
name = "adrenalin"
desc = "Removes all stuns and knockdowns."
@@ -445,14 +478,13 @@ the implant may become unstable and either pre-maturely inject the subject or si
return
-
-/obj/item/weapon/implant/adrenalin/implanted(mob/source)
+/obj/item/weapon/implant/adrenalin/post_implant(mob/source)
source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0)
source << "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate."
- listening_objects |= src
- return 1
-
+//////////////////////////////
+// Death Alarm Implant
+//////////////////////////////
/obj/item/weapon/implant/death_alarm
name = "death alarm implant"
desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
@@ -529,11 +561,13 @@ the implant may become unstable and either pre-maturely inject the subject or si
spawn(20)
malfunction--
-/obj/item/weapon/implant/death_alarm/implanted(mob/source as mob)
+/obj/item/weapon/implant/death_alarm/post_implant(mob/source as mob)
mobname = source.real_name
processing_objects.Add(src)
- return 1
+//////////////////////////////
+// Compressed Matter Implant
+//////////////////////////////
/obj/item/weapon/implant/compressed
name = "compressed matter implant"
desc = "Based on compressed matter technology, can store a single item."
@@ -571,13 +605,12 @@ the implant may become unstable and either pre-maturely inject the subject or si
scanned.loc = t
qdel(src)
-/obj/item/weapon/implant/compressed/implanted(mob/source as mob)
+/obj/item/weapon/implant/compressed/post_implant(mob/source)
src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
if (source.mind)
source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0)
source << "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate."
- listening_objects |= src
- return 1
+
/obj/item/weapon/implant/compressed/islegal()
return 0
diff --git a/code/game/objects/items/weapons/implants/implantchair.dm b/code/game/objects/items/weapons/implants/implantchair.dm
index 44b33721cf0..c05d52442c1 100644
--- a/code/game/objects/items/weapons/implants/implantchair.dm
+++ b/code/game/objects/items/weapons/implants/implantchair.dm
@@ -135,10 +135,9 @@
for (var/mob/O in viewers(M, null))
O.show_message("\The [M] has been implanted by \the [src].", 1)
- if(imp.implanted(M))
- imp.loc = M
- imp.imp_in = M
- imp.implanted = 1
+ if(imp.handle_implant(M, BP_TORSO))
+ imp.post_implant(M)
+
implant_list -= imp
break
return
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 8052b19de60..fcfd67bb6a3 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -56,16 +56,11 @@
add_attack_logs(user,M,"Implanted with [imp.name] using [name]")
- if(src.imp.implanted(M))
- src.imp.loc = M
- src.imp.imp_in = M
- src.imp.implanted = 1
- if (ishuman(M))
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/affected = H.get_organ(user.zone_sel.selecting)
- affected.implants += src.imp
- imp.part = affected
+ if(imp.handle_implant(M))
+ imp.post_implant(M)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
BITSET(H.hud_updateflag, IMPLOYAL_HUD)
src.imp = null
diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm
index 92021a46a2f..fab692775d3 100644
--- a/code/game/objects/items/weapons/implants/implantfreedom.dm
+++ b/code/game/objects/items/weapons/implants/implantfreedom.dm
@@ -16,7 +16,9 @@
/obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source as mob)
- if (src.uses < 1) return 0
+ if (src.uses < 1)
+ return 0
+
if (emote == src.activation_emote)
src.uses--
source << "You feel a faint click."
@@ -46,13 +48,9 @@
W.layer = initial(W.layer)
return
-
-/obj/item/weapon/implant/freedom/implanted(mob/living/carbon/source)
+/obj/item/weapon/implant/freedom/post_implant(mob/source)
source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0)
source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate."
- listening_objects |= src
- return 1
-
/obj/item/weapon/implant/freedom/get_data()
var/dat = {"
diff --git a/code/game/objects/items/weapons/implants/implantlanguage.dm b/code/game/objects/items/weapons/implants/implantlanguage.dm
index d813a8d3888..7c6e33508b0 100644
--- a/code/game/objects/items/weapons/implants/implantlanguage.dm
+++ b/code/game/objects/items/weapons/implants/implantlanguage.dm
@@ -4,7 +4,26 @@
/obj/item/weapon/implant/language
name = "GalCom language implant"
- desc = "An implant allowing someone to speak and hear the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with hearing and producing sounds, not understanding them."
+ desc = "An implant allowing someone to speak the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with producing sounds, not understanding them."
+ var/list/languages = list(LANGUAGE_GALCOM) // List of languages that this assists with
+
+/obj/item/weapon/implant/language/post_implant(mob/M) // Amends the mob's voice organ, then deletes itself
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/internal/voicebox/V = locate() in H.internal_organs
+ if(V)
+ var/list/need_amend = list() // If they've already got all the languages they need, then they don't need this implant to do anything
+ for(var/L in languages)
+ if(L in V.will_assist_languages)
+ continue
+ else
+ need_amend |= L
+ if(LAZYLEN(need_amend))
+ if(V.robotic < ORGAN_ASSISTED)
+ V.mechassist()
+ for(var/L in need_amend)
+ V.add_assistable_langs(L)
+ qdel_null(src)
/obj/item/weapon/implant/language/get_data()
var/dat = {"
@@ -14,16 +33,19 @@
Important Notes: Affects hearing and speech.
Implant Details:
-Function: Allows a being otherwise incapable to both hear the frequencies Galactic Common is generally spoken at, as well as to produce the phonemes of the language.
+Function: Allows a being otherwise incapable of speaking Galactic Common to produce the phonemes of the language.
Special Features: None.
Integrity: Implant will function for expected life, barring physical damage."}
return dat
+
+// EAL Implant
/obj/item/weapon/implant/language/eal
name = "EAL language implant"
- desc = "An implant allowing an organic to both hear and speak Encoded Audio Language accurately. Only helps with hearing and producing sounds, not understanding them."
+ desc = "An implant allowing an organic to speak Encoded Audio Language passably. Only helps with producing sounds, not understanding them."
+ languages = list(LANGUAGE_EAL)
-/obj/item/weapon/implant/language/get_data()
+/obj/item/weapon/implant/language/eal/get_data()
var/dat = {"
Implant Specifications:
Name: Vey-Med L-2 Encoded Audio Language Implant
@@ -31,7 +53,25 @@
Important Notes: Affects hearing and speech.
Implant Details:
-Function: Allows an organic to accurately process and speak Encoded Audio Language.
+Function: Allows an organic to accurately speak Encoded Audio Language.
+Special Features: None.
+Integrity: Implant will function for expected life, barring physical damage."}
+ return dat
+
+/obj/item/weapon/implant/language/skrellian
+ name = "Skrellian language implant"
+ desc = "An implant allowing someone to speak the range of frequencies used in Skrellian, as well as produce any phonemes that they usually cannot. Only helps with hearing and producing sounds, not understanding them."
+ languages = list(LANGUAGE_SKRELLIAN)
+
+/obj/item/weapon/implant/language/skrellian/get_data()
+ var/dat = {"
+Implant Specifications:
+Name: Vey-Med L-1 Galactic Common Implant
+Life: 5 years
+Important Notes: Affects hearing and speech.
+
+Implant Details:
+Function: Allows a being otherwise incapable of speaking Skrellian to produce the phonemes of the language.
Special Features: None.
Integrity: Implant will function for expected life, barring physical damage."}
return dat
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/implants/implantuplink.dm b/code/game/objects/items/weapons/implants/implantuplink.dm
index 644ebf1bb7a..82809cfe61a 100644
--- a/code/game/objects/items/weapons/implants/implantuplink.dm
+++ b/code/game/objects/items/weapons/implants/implantuplink.dm
@@ -11,15 +11,13 @@
..()
return
-/obj/item/weapon/implant/uplink/implanted(mob/source)
+/obj/item/weapon/implant/uplink/post_implant(mob/source)
+ listening_objects |= src
activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0)
source << "The implanted uplink implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate."
- listening_objects |= src
- return 1
-
/obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob)
if(hidden_uplink && usr == source) // Let's not have another people activate our uplink
hidden_uplink.check_trigger(source, emote, activation_emote)
- return
+ return
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm
index 54f344eae10..0cfdd4792dd 100644
--- a/code/game/objects/items/weapons/mop.dm
+++ b/code/game/objects/items/weapons/mop.dm
@@ -16,6 +16,7 @@ GLOBAL_LIST_BOILERPLATE(all_mops, /obj/item/weapon/mop)
/obj/item/weapon/mop/New()
create_reagents(30)
+ ..()
/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity)
if(!proximity) return
diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm
index 43183d45f44..aec6a790b21 100644
--- a/code/game/objects/items/weapons/policetape.dm
+++ b/code/game/objects/items/weapons/policetape.dm
@@ -4,6 +4,9 @@
icon = 'icons/policetape.dmi'
icon_state = "tape"
w_class = ITEMSIZE_SMALL
+
+ toolspeed = 3 //You can use it in surgery. It's stupid, but you can.
+
var/turf/start
var/turf/end
var/tape_type = /obj/item/tape
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index f2aad7a86dd..c7607d5aeb8 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -86,7 +86,6 @@
/obj/item/weapon/weldingtool,
/obj/item/weapon/tool/crowbar,
/obj/item/weapon/tool/wirecutters,
- /obj/item/device/t_scanner
)
/obj/item/weapon/storage/belt/utility/chief
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 268a8d5ad77..e37b2f99770 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -19,16 +19,19 @@
var/obj/item/weapon/cell/bcell = null
var/hitcost = 240
-/obj/item/weapon/melee/baton/suicide_act(mob/user)
- var/datum/gender/TU = gender_datums[user.get_visible_gender()]
- user.visible_message("\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.")
- return (FIRELOSS)
-
/obj/item/weapon/melee/baton/New()
..()
update_icon()
return
+/obj/item/weapon/melee/baton/get_cell()
+ return bcell
+
+/obj/item/weapon/melee/baton/suicide_act(mob/user)
+ var/datum/gender/TU = gender_datums[user.get_visible_gender()]
+ user.visible_message("\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.")
+ return (FIRELOSS)
+
/obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj)
if(!canremove)
return
diff --git a/code/game/objects/items/weapons/tape.dm b/code/game/objects/items/weapons/tape.dm
index 5a575155888..e3afddba4c5 100644
--- a/code/game/objects/items/weapons/tape.dm
+++ b/code/game/objects/items/weapons/tape.dm
@@ -5,8 +5,12 @@
icon_state = "taperoll"
w_class = ITEMSIZE_TINY
+ toolspeed = 2 //It is now used in surgery as a not awful, but probably dangerous option, due to speed.
+
/obj/item/weapon/tape_roll/attack(var/mob/living/carbon/human/H, var/mob/user)
if(istype(H))
+ if(user.a_intent == I_HELP)
+ return
var/can_place = 0
if(istype(user, /mob/living/silicon/robot))
can_place = 1
diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm
index bb082fe9ce0..31019176d82 100644
--- a/code/game/objects/items/weapons/tools/weldingtool.dm
+++ b/code/game/objects/items/weapons/tools/weldingtool.dm
@@ -1,5 +1,5 @@
-#define WELDER_FUEL_BURN_INTERVAL 13
+#define WELDER_FUEL_BURN_INTERVAL 13
/*
* Welding Tool
*/
@@ -63,7 +63,7 @@
/obj/item/weapon/weldingtool/attackby(obj/item/W as obj, mob/living/user as mob)
- if(W.is_screwdriver())
+ if(istype(W,/obj/item/weapon/tool/screwdriver))
if(welding)
to_chat(user, "Stop welding first!")
return
@@ -99,12 +99,15 @@
..()
return
+
/obj/item/weapon/weldingtool/process()
if(welding)
++burned_fuel_for
if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL)
remove_fuel(1)
+
+
if(get_fuel() < 1)
setWelding(0)
@@ -118,6 +121,7 @@
if (istype(location, /turf))
location.hotspot_expose(700, 5)
+
/obj/item/weapon/weldingtool/afterattack(obj/O as obj, mob/user as mob, proximity)
if(!proximity) return
if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1)
@@ -146,6 +150,7 @@
location.hotspot_expose(700, 50, 1)
return
+
/obj/item/weapon/weldingtool/attack_self(mob/user as mob)
setWelding(!welding, usr)
return
@@ -209,24 +214,6 @@
M.update_inv_l_hand()
M.update_inv_r_hand()
-/obj/item/weapon/weldingtool/attack(var/atom/A, var/mob/living/user, var/def_zone)
- if(ishuman(A) && user.a_intent == I_HELP)
- var/mob/living/carbon/human/H = A
- var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting]
-
- if(!S || S.robotic < ORGAN_ROBOT || S.open == 3)
- return ..()
-
- if(!welding)
- to_chat(user, "You'll need to turn [src] on to patch the damage on [H]'s [S.name]!")
- return 1
-
- if(S.robo_repair(15, BRUTE, "some dents", src, user))
- remove_fuel(1, user)
-
- else
- return ..()
-
/obj/item/weapon/weldingtool/MouseDrop(obj/over_object as obj)
if(!canremove)
return
@@ -349,9 +336,6 @@
/obj/item/weapon/weldingtool/is_hot()
return isOn()
-/obj/item/weapon/weldingtool/is_welder()
- return TRUE
-
/obj/item/weapon/weldingtool/largetank
name = "industrial welding tool"
desc = "A slightly larger welder with a larger tank."
@@ -495,6 +479,9 @@
acti_sound = 'sound/effects/sparks4.ogg'
deac_sound = 'sound/effects/sparks4.ogg'
+/obj/item/weapon/weldingtool/electric/unloaded/New()
+ cell_type = null
+
/obj/item/weapon/weldingtool/electric/New()
..()
if(cell_type == null)
@@ -505,17 +492,17 @@
power_supply = new /obj/item/weapon/cell/device(src)
update_icon()
-/obj/item/weapon/weldingtool/electric/unloaded/New()
- cell_type = null
+/obj/item/weapon/weldingtool/electric/get_cell()
+ return power_supply
/obj/item/weapon/weldingtool/electric/examine(mob/user)
if(get_dist(src, user) > 1)
to_chat(user, desc)
else // The << need to stay, for some reason
if(power_supply)
- to_chat(user, text("\icon[] The [] has [] charge left.", src, src.name, get_fuel()))
+ user << text("\icon[] The [] has [] charge left.", src, src.name, get_fuel())
else
- to_chat(user, text("\icon[] The [] has no power cell!", src, src.name))
+ user << text("\icon[] The [] has no power cell!", src, src.name)
/obj/item/weapon/weldingtool/electric/get_fuel()
if(use_external_power)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index f8782c4728b..9c2fb604346 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -163,3 +163,6 @@
/obj/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
return
+
+/obj/proc/get_cell()
+ return
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
index 96b0030d21e..cad925f6e88 100644
--- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
@@ -16,6 +16,10 @@
starts_with = list(/obj/item/weapon/material/twohanded/fireaxe)
+/obj/structure/closet/fireaxecabinet/initialize()
+ ..()
+ fireaxe = locate() in contents
+
/obj/structure/closet/fireaxecabinet/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
//..() //That's very useful, Erro
@@ -115,6 +119,7 @@
if(src.locked)
to_chat(user, "The cabinet won't budge!")
return
+
if(localopened)
if(fireaxe)
user.put_in_hands(fireaxe)
diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm
index ef58518e489..8b7f5bf0424 100644
--- a/code/game/objects/structures/flora/trees.dm
+++ b/code/game/objects/structures/flora/trees.dm
@@ -4,7 +4,8 @@
anchored = 1
density = 1
pixel_x = -16
- layer = MOB_LAYER // You know what, let's play it safe.
+ plane = MOB_PLANE // You know what, let's play it safe.
+ layer = ABOVE_MOB_LAYER
var/base_state = null // Used for stumps.
var/health = 200 // Used for chopping down trees.
var/max_health = 200
@@ -51,12 +52,12 @@
animate(transform=null, pixel_x=init_px, time=6, easing=ELASTIC_EASING)
// Used when the tree gets hurt.
-/obj/structure/flora/tree/proc/adjust_health(var/amount, var/is_ranged = FALSE)
+/obj/structure/flora/tree/proc/adjust_health(var/amount, var/damage_wood = FALSE)
if(is_stump)
return
// Bullets and lasers ruin some of the wood
- if(is_ranged && product_amount > 0)
+ if(damage_wood && product_amount > 0)
var/wood = initial(product_amount)
product_amount -= round(wood * (abs(amount)/max_health))
@@ -89,12 +90,16 @@
set_light(0)
/obj/structure/flora/tree/ex_act(var/severity)
- adjust_health(-(max_health / severity))
+ adjust_health(-(max_health / severity), TRUE)
/obj/structure/flora/tree/bullet_act(var/obj/item/projectile/Proj)
if(Proj.get_structure_damage())
adjust_health(-Proj.get_structure_damage(), TRUE)
+/obj/structure/flora/tree/tesla_act(power, explosive)
+ adjust_health(-power / 100, TRUE) // Kills most trees in one lightning strike.
+ ..()
+
/obj/structure/flora/tree/get_description_interaction()
var/list/results = list()
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index 69237285647..4c1bc63618a 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -20,6 +20,7 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart)
/obj/structure/janitorialcart/New()
create_reagents(300)
+ ..()
/obj/structure/janitorialcart/examine(mob/user)
diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm
new file mode 100644
index 00000000000..0340356e37c
--- /dev/null
+++ b/code/game/objects/structures/plasticflaps.dm
@@ -0,0 +1,78 @@
+/obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY
+ name = "\improper plastic flaps"
+ desc = "Completely impassable - or are they?"
+ icon = 'icons/obj/stationobjs.dmi' //Change this.
+ icon_state = "plasticflaps"
+ density = 0
+ anchored = 1
+ layer = MOB_LAYER
+ plane = MOB_PLANE
+ explosion_resistance = 5
+ var/list/mobs_can_pass = list(
+ /mob/living/bot,
+ /mob/living/simple_animal/slime,
+ /mob/living/simple_animal/mouse,
+ /mob/living/silicon/robot/drone
+ )
+
+/obj/structure/plasticflaps/attackby(obj/item/P, mob/user)
+ if(P.is_wirecutter())
+ playsound(src, P.usesound, 50, 1)
+ user << "You start to cut the plastic flaps."
+ if(do_after(user, 10 * P.toolspeed))
+ user << "You cut the plastic flaps."
+ var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc )
+ A.amount = 4
+ qdel(src)
+ return
+ else
+ return
+
+/obj/structure/plasticflaps/CanPass(atom/A, turf/T)
+ if(istype(A) && A.checkpass(PASSGLASS))
+ return prob(60)
+
+ var/obj/structure/bed/B = A
+ if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass
+ return 0
+
+ if(istype(A, /obj/vehicle)) //no vehicles
+ return 0
+
+ var/mob/living/M = A
+ if(istype(M))
+ if(M.lying)
+ return ..()
+ for(var/mob_type in mobs_can_pass)
+ if(istype(A, mob_type))
+ return ..()
+ return issmall(M)
+
+ return ..()
+
+/obj/structure/plasticflaps/ex_act(severity)
+ switch(severity)
+ if (1)
+ qdel(src)
+ if (2)
+ if (prob(50))
+ qdel(src)
+ if (3)
+ if (prob(5))
+ qdel(src)
+
+/obj/structure/plasticflaps/mining //A specific type for mining that doesn't allow airflow because of them damn crates
+ name = "airtight plastic flaps"
+ desc = "Heavy duty, airtight, plastic flaps."
+
+/obj/structure/plasticflaps/mining/New() //set the turf below the flaps to block air
+ var/turf/T = get_turf(loc)
+ if(T)
+ T.blocks_air = 1
+ ..()
+
+/obj/structure/plasticflaps/mining/Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor
+ var/turf/T = get_turf(loc)
+ if(T && istype(T, /turf/simulated/floor))
+ T.blocks_air = 0
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/structures/alien_props.dm b/code/game/objects/structures/props/alien_props.dm
similarity index 90%
rename from code/game/objects/structures/alien_props.dm
rename to code/game/objects/structures/props/alien_props.dm
index eb8ae9d19f3..fa11e27b15d 100644
--- a/code/game/objects/structures/alien_props.dm
+++ b/code/game/objects/structures/props/alien_props.dm
@@ -6,15 +6,6 @@
icon = 'icons/obj/abductor.dmi'
density = TRUE
anchored = TRUE
- var/interaction_message = null
-
-/obj/structure/prop/alien/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything.
- if(!istype(user))
- return FALSE
- if(!interaction_message)
- return ..()
- else
- to_chat(user, interaction_message)
/obj/structure/prop/alien/computer
name = "alien console"
diff --git a/code/game/objects/structures/props/beam_prism.dm b/code/game/objects/structures/props/beam_prism.dm
new file mode 100644
index 00000000000..44df2eb68b0
--- /dev/null
+++ b/code/game/objects/structures/props/beam_prism.dm
@@ -0,0 +1,215 @@
+//A series(?) of prisms for PoIs. The base one only works for beams.
+
+/obj/structure/prop/prism
+ name = "prismatic turret"
+ desc = "A raised, externally powered 'turret'. It seems to have a massive crystal ring around its base."
+ description_info = "This device is capable of redirecting any beam projectile."
+ icon = 'icons/obj/props/prism.dmi'
+ icon_state = "prism"
+ density = TRUE
+ anchored = TRUE
+
+ layer = 3.1 //Layer over projectiles.
+ plane = -10 //Layer over projectiles.
+
+ var/rotation_lock = 0 // Can you rotate the prism at all?
+ var/free_rotate = 1 // Does the prism rotate in any direction, or only in the eight standard compass directions?
+ var/external_control_lock = 0 // Does the prism only rotate from the controls of an external switch?
+ var/degrees_from_north = 0 // How far is it rotated clockwise?
+ var/compass_directions = list("North" = 0, "South" = 180, "East" = 90, "West" = 270, "Northwest" = 315, "Northeast" = 45, "Southeast" = 135, "Southwest" = 225)
+ var/interaction_sound = 'sound/mecha/mechmove04.ogg'
+
+ var/redirect_type = /obj/item/projectile/beam
+
+ var/dialID = null
+ var/obj/structure/prop/prismcontrol/remote_dial = null
+
+ interaction_message = "The prismatic turret seems to be able to rotate."
+
+/obj/structure/prop/prism/initialize()
+ if(degrees_from_north)
+ animate(src, transform = turn(NORTH, degrees_from_north), time = 3)
+
+/obj/structure/prop/prism/Destroy()
+ if(remote_dial)
+ remote_dial.my_turrets -= src
+ remote_dial = null
+ ..()
+
+/obj/structure/prop/prism/proc/reset_rotation()
+ var/degrees_to_rotate = -1 * degrees_from_north
+ animate(src, transform = turn(src.transform, degrees_to_rotate), time = 2)
+
+/obj/structure/prop/prism/attack_hand(mob/living/user)
+ ..()
+
+ if(rotation_lock)
+ to_chat(user, "\The [src] is locked at its current bearing.")
+ return
+ if(external_control_lock)
+ to_chat(user, "\The [src]'s motors resist your efforts to rotate it. You may need to find some form of controller.")
+ return
+
+ var/confirm = input("Do you want to try to rotate \the [src]?", "[name]") in list("Yes", "No")
+ if(confirm == "No")
+ visible_message(\
+ "[user.name] decides not to try turning \the [src].",\
+ "You decide not to try turning \the [src].")
+ return
+
+ var/new_bearing
+ if(free_rotate)
+ new_bearing = input("What bearing do you want to rotate \the [src] to?", "[name]") as num
+ new_bearing = round(new_bearing)
+ if(new_bearing <= -1 || new_bearing > 360)
+ to_chat(user, "Rotating \the [src] [new_bearing] degrees would be a waste of time.")
+ return
+ else
+ var/choice = input("What point do you want to set \the [src] to?", "[name]") as null|anything in compass_directions
+ new_bearing = round(compass_directions[choice])
+
+ var/rotate_degrees = new_bearing - degrees_from_north
+
+ if(new_bearing == 360) // Weird artifact.
+ new_bearing = 0
+ degrees_from_north = new_bearing
+
+ var/two_stage = 0
+ if(rotate_degrees == 180 || rotate_degrees == -180)
+ two_stage = 1
+ var/multiplier = pick(-1, 1)
+ rotate_degrees = multiplier * (rotate_degrees / 2)
+
+ playsound(src, interaction_sound, 50, 1)
+ if(two_stage)
+ animate(src, transform = turn(src.transform, rotate_degrees), time = 3)
+ spawn(3)
+ animate(src, transform = turn(src.transform, rotate_degrees), time = 3)
+ else
+ animate(src, transform = turn(src.transform, rotate_degrees), time = 6) //Can't update transform because it will reset the angle.
+
+/obj/structure/prop/prism/proc/rotate_auto(var/new_bearing)
+ if(rotation_lock)
+ visible_message("\The [src] shudders.")
+ playsound(src, 'sound/effects/clang.ogg', 50, 1)
+ return
+
+ visible_message("\The [src] rotates to a bearing of [new_bearing].")
+
+ var/rotate_degrees = new_bearing - degrees_from_north
+
+ if(new_bearing == 360)
+ new_bearing = 0
+ degrees_from_north = new_bearing
+
+ var/two_stage = 0
+ if(rotate_degrees == 180 || rotate_degrees == -180)
+ two_stage = 1
+ var/multiplier = pick(-1, 1)
+ rotate_degrees = multiplier * (rotate_degrees / 2)
+
+ playsound(src, interaction_sound, 50, 1)
+ if(two_stage)
+ animate(src, transform = turn(src.transform, rotate_degrees), time = 3)
+ spawn(3)
+ animate(src, transform = turn(src.transform, rotate_degrees), time = 3)
+ else
+ animate(src, transform = turn(src.transform, rotate_degrees), time = 6)
+
+/obj/structure/prop/prism/bullet_act(var/obj/item/projectile/Proj)
+ if(istype(Proj, redirect_type))
+ visible_message("\The [src] redirects \the [Proj]!")
+ flick("[initial(icon_state)]+glow", src)
+
+ var/new_x = (1 * round(10 * cos(degrees_from_north - 90))) + x //Vectors vectors vectors.
+ var/new_y = (-1 * round(10 * sin(degrees_from_north - 90))) + y
+ var/turf/curloc = get_turf(src)
+
+ Proj.penetrating += 1 // Needed for the beam to get out of the turret.
+
+ Proj.redirect(new_x, new_y, curloc, null)
+
+/obj/structure/prop/prism/incremental
+ free_rotate = 0
+ description_info = "This device is capable of redirecting any beam projectile, but only locks to specific positions in rotation."
+
+/obj/structure/prop/prism/incremental/externalcont
+ external_control_lock = 1
+ description_info = "This device is capable of redirecting any beam projectile, but can only be rotated by a control dial to specific positions."
+
+/obj/structure/prop/prism/externalcont
+ external_control_lock = 1
+ description_info = "This device is capable of redirecting any beam projectile, but can only be rotated by an external control dial."
+
+/obj/structure/prop/prismcontrol
+ name = "prismatic dial"
+ desc = "A large dial with a crystalline ring."
+ icon = 'icons/obj/props/prism.dmi'
+ icon_state = "dial"
+ density = FALSE
+ anchored = TRUE
+
+ interaction_message = "The dial pulses as your hand nears it."
+ var/list/my_turrets = list()
+ var/dialID = null
+
+/obj/structure/prop/prismcontrol/attack_hand(mob/living/user)
+ ..()
+
+ var/confirm = input("Do you want to try to rotate \the [src]?", "[name]") in list("Yes", "No")
+ if(confirm == "No")
+ visible_message(\
+ "[user.name] decides not to try turning \the [src].",\
+ "You decide not to try turning \the [src].")
+ return
+
+ if(!my_turrets || !my_turrets.len)
+ to_chat(user, "\The [src] doesn't seem to do anything.")
+ return
+
+ var/free_rotate = 1
+ var/list/compass_directions = list()
+ for(var/obj/structure/prop/prism/P in my_turrets)
+ if(!P.free_rotate) //Doesn't use bearing, it uses compass points.
+ free_rotate = 0
+ compass_directions |= P.compass_directions
+
+ var/new_bearing
+ if(free_rotate)
+ new_bearing = input("What bearing do you want to rotate \the [src] to?", "[name]") as num
+ new_bearing = round(new_bearing)
+ if(new_bearing <= -1 || new_bearing > 360)
+ to_chat(user, "Rotating \the [src] [new_bearing] degrees would be a waste of time.")
+ return
+ else
+ var/choice = input("What point do you want to set \the [src] to?", "[name]") as null|anything in compass_directions
+ new_bearing = round(compass_directions[choice])
+
+ confirm = input("Are you certain you want to rotate \the [src]?", "[name]") in list("Yes", "No")
+ if(confirm == "No")
+ visible_message(\
+ "[user.name] decides not to try turning \the [src].",\
+ "You decide not to try turning \the [src].")
+ return
+
+ to_chat(user, "\The [src] clicks into place.")
+ for(var/obj/structure/prop/prism/P in my_turrets)
+ P.rotate_auto(new_bearing)
+
+/obj/structure/prop/prismcontrol/initialize()
+ ..()
+ if(my_turrets.len) //Preset controls.
+ for(var/obj/structure/prop/prism/P in my_turrets)
+ P.remote_dial = src
+ return
+ spawn()
+ for(var/obj/structure/prop/prism/P in orange(src, world.view)) //Don't search a huge area.
+ if(P.dialID == dialID && !P.remote_dial && P.external_control_lock)
+ my_turrets |= P
+ P.remote_dial = src
+
+/obj/structure/prop/prismcontrol/Destroy()
+ for(var/obj/structure/prop/prism/P in my_turrets)
+ P.remote_dial = null
+ my_turrets = list()
+ ..()
diff --git a/code/game/objects/structures/props/projectile_lock.dm b/code/game/objects/structures/props/projectile_lock.dm
new file mode 100644
index 00000000000..5c3fcd2ba07
--- /dev/null
+++ b/code/game/objects/structures/props/projectile_lock.dm
@@ -0,0 +1,53 @@
+//A locking mechanism that pulses when hit by a projectile. The base one responds to high-power lasers.
+
+/obj/structure/prop/lock
+ name = "weird lock"
+ desc = "An esoteric object that responds to.. something."
+ icon = 'icons/obj/props/prism.dmi'
+ icon_state = "lock"
+
+ var/enabled = 0
+ var/lockID = null
+
+ var/list/linked_objects = list()
+
+/obj/structure/prop/lock/Destroy()
+ if(linked_objects.len)
+ for(var/obj/O in linked_objects)
+ if(istype(O, /obj/machinery/door/blast/puzzle))
+ var/obj/machinery/door/blast/puzzle/P = O
+ P.locks -= src
+ linked_objects -= P
+ ..()
+
+/obj/structure/prop/lock/proc/toggle_lock()
+ enabled = !enabled
+
+ if(enabled)
+ icon_state = "[initial(icon_state)]-active"
+ else
+ icon_state = "[initial(icon_state)]"
+
+/obj/structure/prop/lock/projectile
+ name = "beam lock"
+ desc = "An esoteric object that responds to high intensity light."
+
+ var/projectile_key = /obj/item/projectile/beam
+ var/timed = 0
+ var/timing = 0
+ var/time_limit = 1500 // In ticks. Ten is one second.
+
+ interaction_message = "The object remains inert to your touch."
+
+/obj/structure/prop/lock/projectile/bullet_act(var/obj/item/projectile/Proj)
+ if(!istype(Proj, projectile_key) || timing)
+ return
+
+ if(istype(Proj, /obj/item/projectile/beam/heavylaser/cannon) || istype(Proj, /obj/item/projectile/beam/emitter) || (Proj.damage >= 80 && Proj.damtype == BURN))
+ toggle_lock()
+ visible_message("\The [src] [enabled ? "disengages" : "engages"] its locking mechanism.")
+
+ if(timed)
+ timing = 1
+ spawn(time_limit)
+ toggle_lock()
diff --git a/code/game/objects/structures/props/prop.dm b/code/game/objects/structures/props/prop.dm
new file mode 100644
index 00000000000..fea5815674d
--- /dev/null
+++ b/code/game/objects/structures/props/prop.dm
@@ -0,0 +1,18 @@
+//The base 'prop' for PoIs or other large junk.
+
+/obj/structure/prop
+ name = "something"
+ desc = "My description is broken, bug a developer."
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "safe"
+ density = TRUE
+ anchored = TRUE
+ var/interaction_message = null
+
+/obj/structure/prop/attack_hand(mob/living/user) // Used to tell the player that this isn't useful for anything.
+ if(!istype(user))
+ return FALSE
+ if(!interaction_message)
+ return ..()
+ else
+ to_chat(user, interaction_message)
diff --git a/code/game/objects/structures/props/puzzledoor.dm b/code/game/objects/structures/props/puzzledoor.dm
new file mode 100644
index 00000000000..b9a32fc0dcc
--- /dev/null
+++ b/code/game/objects/structures/props/puzzledoor.dm
@@ -0,0 +1,92 @@
+// An indestructible blast door that can only be opened once its puzzle requirements are completed.
+
+/obj/machinery/door/blast/puzzle
+ name = "puzzle door"
+ desc = "A large, virtually indestructible door that will not open unless certain requirements are met."
+ icon_state_open = "pdoor0"
+ icon_state_opening = "pdoorc0"
+ icon_state_closed = "pdoor1"
+ icon_state_closing = "pdoorc1"
+ icon_state = "pdoor1"
+
+ explosion_resistance = 100
+
+ maxhealth = 9999999 //No.
+
+ var/list/locks = list()
+ var/lockID = null
+ var/checkrange_mult = 1
+
+/obj/machinery/door/blast/puzzle/proc/check_locks()
+ for(var/obj/structure/prop/lock/L in locks)
+ if(!L.enabled)
+ return 0
+ return 1
+
+/obj/machinery/door/blast/puzzle/bullet_act(var/obj/item/projectile/Proj)
+ visible_message("\The [src] is completely unaffected by \the [Proj].")
+ qdel(Proj) //No piercing. No.
+
+/obj/machinery/door/blast/puzzle/ex_act(severity)
+ visible_message("\The [src] is completely unaffected by the blast.")
+ return
+
+/obj/machinery/door/blast/puzzle/initialize()
+ . = ..()
+ implicit_material = get_material_by_name("dungeonium")
+ if(locks.len)
+ return
+ var/check_range = world.view * checkrange_mult
+ for(var/obj/structure/prop/lock/L in orange(src, check_range))
+ if(L.lockID == lockID)
+ L.linked_objects |= src
+ locks |= L
+
+/obj/machinery/door/blast/puzzle/Destroy()
+ if(locks.len)
+ for(var/obj/structure/prop/lock/L in locks)
+ L.linked_objects -= src
+ locks -= L
+ ..()
+
+/obj/machinery/door/blast/puzzle/attack_hand(mob/user as mob)
+ if(check_locks())
+ force_toggle(1, user)
+ else
+ to_chat(user, "\The [src] does not respond to your touch.")
+
+/obj/machinery/door/blast/puzzle/attackby(obj/item/weapon/C as obj, mob/user as mob)
+ if(istype(C, /obj/item/weapon))
+ if(C.pry == 1 && (user.a_intent != I_HURT || (stat & BROKEN)))
+ if(istype(C,/obj/item/weapon/material/twohanded/fireaxe))
+ var/obj/item/weapon/material/twohanded/fireaxe/F = C
+ if(!F.wielded)
+ to_chat(user, "You need to be wielding \the [F] to do that.")
+ return
+
+ if(check_locks())
+ force_toggle(1, user)
+
+ else
+ to_chat(user, "[src]'s arcane workings resist your effort.")
+ return
+
+ else if(src.density && (user.a_intent == I_HURT))
+ var/obj/item/weapon/W = C
+ user.setClickCooldown(user.get_attack_speed(W))
+ if(W.damtype == BRUTE || W.damtype == BURN)
+ user.do_attack_animation(src)
+ user.visible_message("\The [user] hits \the [src] with \the [W] with no visible effect.")
+
+ else if(istype(C, /obj/item/weapon/plastique))
+ to_chat(user, "On contacting \the [src], a flash of light envelops \the [C] as it is turned to ash. Oh.")
+ qdel(C)
+ return 0
+
+/obj/machinery/door/blast/puzzle/attack_generic(var/mob/user, var/damage)
+ if(check_locks())
+ force_toggle(1, user)
+
+/obj/machinery/door/blast/puzzle/attack_alien(var/mob/user)
+ if(check_locks())
+ force_toggle(1, user)
diff --git a/code/game/sound.dm b/code/game/sound.dm
index 2db1e433bde..8e206300a8f 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -130,6 +130,9 @@
if ("mechstep") soundin = pick('sound/mecha/mechstep1.ogg', 'sound/mecha/mechstep2.ogg')
if ("geiger") soundin = pick('sound/items/geiger1.ogg', 'sound/items/geiger2.ogg', 'sound/items/geiger3.ogg', 'sound/items/geiger4.ogg', 'sound/items/geiger5.ogg')
if ("geiger_weak") soundin = pick('sound/items/geiger_weak1.ogg', 'sound/items/geiger_weak2.ogg', 'sound/items/geiger_weak3.ogg', 'sound/items/geiger_weak4.ogg')
+ if ("thunder") soundin = pick('sound/effects/thunder/thunder1.ogg', 'sound/effects/thunder/thunder2.ogg', 'sound/effects/thunder/thunder3.ogg', 'sound/effects/thunder/thunder4.ogg',
+ 'sound/effects/thunder/thunder5.ogg', 'sound/effects/thunder/thunder6.ogg', 'sound/effects/thunder/thunder7.ogg', 'sound/effects/thunder/thunder8.ogg', 'sound/effects/thunder/thunder9.ogg',
+ 'sound/effects/thunder/thunder10.ogg')
return soundin
//Are these even used?
diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm
index 061ac1f065e..e69de29bb2d 100644
--- a/code/game/supplyshuttle.dm
+++ b/code/game/supplyshuttle.dm
@@ -1,333 +0,0 @@
-//Config stuff
-#define SUPPLY_DOCKZ 2 //Z-level of the Dock.
-#define SUPPLY_STATIONZ 1 //Z-level of the Station.
-#define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station
-#define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock
-
-//Supply packs are in /code/defines/obj/supplypacks.dm
-//Computers are in /code/game/machinery/computer/supply.dm
-
-var/datum/controller/supply/supply_controller = new()
-
-var/list/mechtoys = list(
- /obj/item/toy/prize/ripley,
- /obj/item/toy/prize/fireripley,
- /obj/item/toy/prize/deathripley,
- /obj/item/toy/prize/gygax,
- /obj/item/toy/prize/durand,
- /obj/item/toy/prize/honk,
- /obj/item/toy/prize/marauder,
- /obj/item/toy/prize/seraph,
- /obj/item/toy/prize/mauler,
- /obj/item/toy/prize/odysseus,
- /obj/item/toy/prize/phazon
-)
-
-/obj/item/weapon/paper/manifest
- name = "supply manifest"
- var/is_copy = 1
-
-/area/supply/station
- name = "Supply Shuttle"
- icon_state = "shuttle3"
- requires_power = 0
- base_turf = /turf/space
-
-/area/supply/dock
- name = "Supply Shuttle"
- icon_state = "shuttle3"
- requires_power = 0
- base_turf = /turf/space
-
-/obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY
- name = "\improper plastic flaps"
- desc = "Completely impassable - or are they?"
- icon = 'icons/obj/stationobjs.dmi' //Change this.
- icon_state = "plasticflaps"
- density = 0
- anchored = 1
- layer = MOB_LAYER
- plane = MOB_PLANE
- explosion_resistance = 5
- var/list/mobs_can_pass = list(
- /mob/living/bot,
- /mob/living/simple_animal/slime,
- /mob/living/simple_animal/mouse,
- /mob/living/silicon/robot/drone
- )
-
-/obj/structure/plasticflaps/attackby(obj/item/P, mob/user)
- if(P.is_wirecutter())
- playsound(src, P.usesound, 50, 1)
- user << "You start to cut the plastic flaps."
- if(do_after(user, 10 * P.toolspeed))
- user << "You cut the plastic flaps."
- var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc )
- A.amount = 4
- qdel(src)
- return
- else
- return
-
-/obj/structure/plasticflaps/CanPass(atom/A, turf/T)
- if(istype(A) && A.checkpass(PASSGLASS))
- return prob(60)
-
- var/obj/structure/bed/B = A
- if (istype(A, /obj/structure/bed) && B.has_buckled_mobs())//if it's a bed/chair and someone is buckled, it will not pass
- return 0
-
- if(istype(A, /obj/vehicle)) //no vehicles
- return 0
-
- var/mob/living/M = A
- if(istype(M))
- if(M.lying)
- return ..()
- for(var/mob_type in mobs_can_pass)
- if(istype(A, mob_type))
- return ..()
- return issmall(M)
-
- return ..()
-
-/obj/structure/plasticflaps/ex_act(severity)
- switch(severity)
- if (1)
- qdel(src)
- if (2)
- if (prob(50))
- qdel(src)
- if (3)
- if (prob(5))
- qdel(src)
-
-/obj/structure/plasticflaps/mining //A specific type for mining that doesn't allow airflow because of them damn crates
- name = "airtight plastic flaps"
- desc = "Heavy duty, airtight, plastic flaps."
-
-/obj/structure/plasticflaps/mining/New() //set the turf below the flaps to block air
- var/turf/T = get_turf(loc)
- if(T)
- T.blocks_air = 1
- ..()
-
-/obj/structure/plasticflaps/mining/Destroy() //lazy hack to set the turf to allow air to pass if it's a simulated floor
- var/turf/T = get_turf(loc)
- if(T && istype(T, /turf/simulated/floor))
- T.blocks_air = 0
- ..()
-
-/*
-/obj/effect/marker/supplymarker
- icon_state = "X"
- icon = 'icons/misc/mark.dmi'
- name = "X"
- invisibility = 101
- anchored = 1
- opacity = 0
-*/
-
-/datum/supply_order
- var/ordernum
- var/datum/supply_packs/object = null
- var/orderedby = null
- var/comment = null
-
-/datum/exported_crate
- var/name
- var/value
-
-/datum/controller/supply
- //supply points
- var/points = 50
- var/points_per_process = 1.5
- var/points_per_slip = 2
- var/points_per_platinum = 5 // 5 points per sheet
- var/points_per_phoron = 5
- var/points_per_money = 0.02
- //control
- var/ordernum
- var/list/shoppinglist = list()
- var/list/requestlist = list()
- var/list/supply_packs = list()
- var/list/exported_crates = list()
- //shuttle movement
- var/movetime = 1200
- var/datum/shuttle/ferry/supply/shuttle
-
-/datum/controller/supply/New()
- ordernum = rand(1,9000)
-
- for(var/typepath in (typesof(/datum/supply_packs) - /datum/supply_packs))
- var/datum/supply_packs/P = new typepath()
- supply_packs[P.name] = P
-
-// Supply shuttle ticker - handles supply point regeneration
-// This is called by the process scheduler every thirty seconds
-/datum/controller/supply/proc/process()
- points += points_per_process
-
-//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
-/datum/controller/supply/proc/forbidden_atoms_check(atom/A)
- if(isliving(A))
- return 1
- if(istype(A,/obj/item/weapon/disk/nuclear))
- return 1
- if(istype(A,/obj/machinery/nuclearbomb))
- return 1
- if(istype(A,/obj/item/device/radio/beacon))
- return 1
-
- for(var/i=1, i<=A.contents.len, i++)
- var/atom/B = A.contents[i]
- if(.(B))
- return 1
-
-//Sellin
-/datum/controller/supply/proc/sell()
- var/area/area_shuttle = shuttle.get_location_area()
- if(!area_shuttle) return
-
- callHook("sell_shuttle", list(area_shuttle));
-
- var/phoron_count = 0
- var/plat_count = 0
- var/money_count = 0
-
- exported_crates = list()
-
- for(var/atom/movable/MA in area_shuttle)
- if(MA.anchored) continue
-
- // Must be in a crate!
- if(istype(MA,/obj/structure/closet/crate))
- var/oldpoints = points
- var/oldphoron = phoron_count
- var/oldplatinum = plat_count
- var/oldmoney = money_count
-
- var/obj/structure/closet/crate/CR = MA
- callHook("sell_crate", list(CR, area_shuttle))
-
- points += CR.points_per_crate
- var/find_slip = 1
-
- for(var/atom in CR)
- // Sell manifests
- var/atom/A = atom
- if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
- var/obj/item/weapon/paper/manifest/slip = A
- if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
- points += points_per_slip
- find_slip = 0
- continue
-
- // Sell phoron and platinum
- if(istype(A, /obj/item/stack))
- var/obj/item/stack/P = A
- switch(P.get_material_name())
- if("phoron") phoron_count += P.get_amount()
- if("platinum") plat_count += P.get_amount()
-
- //Sell spacebucks
- if(istype(A, /obj/item/weapon/spacecash))
- var/obj/item/weapon/spacecash/cashmoney = A
- money_count += cashmoney.worth
-
- var/datum/exported_crate/EC = new /datum/exported_crate()
- EC.name = CR.name
- EC.value = points - oldpoints
- EC.value += (phoron_count - oldphoron) * points_per_phoron
- EC.value += (plat_count - oldplatinum) * points_per_platinum
- EC.value += (money_count - oldmoney) * points_per_money
- exported_crates += EC
-
- qdel(MA)
-
- points += phoron_count * points_per_phoron
- points += plat_count * points_per_platinum
- points += money_count * points_per_money
-
-//Buyin
-/datum/controller/supply/proc/buy()
- if(!shoppinglist.len)
- return
-
- var/orderedamount = shoppinglist.len
-
- var/area/area_shuttle = shuttle.get_location_area()
- if(!area_shuttle)
- return
-
- var/list/clear_turfs = list()
-
- for(var/turf/T in area_shuttle)
- if(T.density)
- continue
- var/contcount
- for(var/atom/A in T.contents)
- if(!A.simulated)
- continue
- contcount++
- if(contcount)
- continue
- clear_turfs += T
-
- for(var/S in shoppinglist)
- if(!clear_turfs.len) break
- var/i = rand(1,clear_turfs.len)
- var/turf/pickedloc = clear_turfs[i]
- clear_turfs.Cut(i,i+1)
- shoppinglist -= S
-
- var/datum/supply_order/SO = S
- var/datum/supply_packs/SP = SO.object
-
- var/obj/A = new SP.containertype(pickedloc)
- A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
-
- //supply manifest generation begin
- var/obj/item/weapon/paper/manifest/slip
- if(!SP.contraband)
- slip = new /obj/item/weapon/paper/manifest(A)
- slip.is_copy = 0
- slip.info = "[command_name()] Shipping Manifest
"
- slip.info +="Order #[SO.ordernum]
"
- slip.info +="Destination: [station_name()]
"
- slip.info +="[orderedamount] PACKAGES IN THIS SHIPMENT
"
- slip.info +="CONTENTS:
"
-
- //spawn the stuff, finish generating the manifest while you're at it
- if(SP.access)
- if(isnum(SP.access))
- A.req_access = list(SP.access)
- else if(islist(SP.access))
- var/list/L = SP.access // access var is a plain var, we need a list
- A.req_access = L.Copy()
- else
- log_debug("Supply pack with invalid access restriction [SP.access] encountered!")
-
- var/list/contains
- if(istype(SP,/datum/supply_packs/randomised))
- var/datum/supply_packs/randomised/SPR = SP
- contains = list()
- if(SPR.contains.len)
- for(var/j=1,j<=SPR.num_contained,j++)
- contains += pick(SPR.contains)
- else
- contains = SP.contains
-
- for(var/typepath in contains)
- if(!typepath) continue
- var/number_of_items = max(1, contains[typepath])
- for(var/j = 1 to number_of_items)
- var/atom/B2 = new typepath(A)
- if(slip) slip.info += "- [B2.name]
" //add the item to the manifest
-
- //manifest finalisation
- if(slip)
- slip.info += "
"
- slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS
"
-
- return
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index e1565889378..1c74b467e22 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -12,6 +12,7 @@
nitrogen = MOLES_N2STANDARD
var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed
var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
+ var/can_dirty = TRUE // If false, tile never gets dirty
var/dirt = 0
// This is not great.
@@ -65,12 +66,13 @@
tracks.AddTracks(bloodDNA,comingdir,goingdir,bloodcolor)
/turf/simulated/proc/update_dirt()
- dirt = min(dirt+1, 101)
- var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src)
- if (dirt > 50)
- if (!dirtoverlay)
- dirtoverlay = new/obj/effect/decal/cleanable/dirt(src)
- dirtoverlay.alpha = min((dirt - 50) * 5, 255)
+ if(can_dirty)
+ dirt = min(dirt+1, 101)
+ var/obj/effect/decal/cleanable/dirt/dirtoverlay = locate(/obj/effect/decal/cleanable/dirt, src)
+ if (dirt > 50)
+ if (!dirtoverlay)
+ dirtoverlay = new/obj/effect/decal/cleanable/dirt(src)
+ dirtoverlay.alpha = min((dirt - 50) * 5, 255)
/turf/simulated/Entered(atom/A, atom/OL)
if(movement_disabled && usr.ckey != movement_disabled_exception)
@@ -82,8 +84,9 @@
if(M.lying)
return ..()
- // Dirt overlays.
- update_dirt()
+ if(M.dirties_floor())
+ // Dirt overlays.
+ update_dirt()
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
diff --git a/code/game/turfs/simulated/dungeon/wall.dm b/code/game/turfs/simulated/dungeon/wall.dm
index 176c10142c4..c1a02cde666 100644
--- a/code/game/turfs/simulated/dungeon/wall.dm
+++ b/code/game/turfs/simulated/dungeon/wall.dm
@@ -12,6 +12,9 @@
/turf/simulated/wall/dungeon/ex_act()
return
+/turf/simulated/wall/dungeon/take_damage() //These things are suppose to be unbreakable
+ return
+
/turf/simulated/wall/solidrock //for more stylish anti-cheese.
name = "solid rock"
desc = "This rock seems dense, impossible to drill."
@@ -37,4 +40,7 @@
return
/turf/simulated/wall/solidrock/ex_act()
+ return
+
+/turf/simulated/wall/solidrock/take_damage() //These things are suppose to be unbreakable
return
\ No newline at end of file
diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm
index de6203827e9..da76ea419f1 100644
--- a/code/game/turfs/simulated/floor_attackby.dm
+++ b/code/game/turfs/simulated/floor_attackby.dm
@@ -9,6 +9,50 @@
attack_tile(C, L) // Be on help intent if you want to decon something.
return
+ if(istype(C, /obj/item/stack/tile/roofing))
+ var/expended_tile = FALSE // To track the case. If a ceiling is built in a multiz zlevel, it also necessarily roofs it against weather
+ var/turf/T = GetAbove(src)
+ var/obj/item/stack/tile/roofing/R = C
+
+ // Patch holes in the ceiling
+ if(T)
+ if(istype(T, /turf/simulated/open) || istype(T, /turf/space))
+ // Must be build adjacent to an existing floor/wall, no floating floors
+ var/list/cardinalTurfs = list() // Up a Z level
+ for(var/dir in cardinal)
+ var/turf/B = get_step(T, dir)
+ if(B)
+ cardinalTurfs += B
+
+ var/turf/simulated/A = locate(/turf/simulated/floor) in cardinalTurfs
+ if(!A)
+ A = locate(/turf/simulated/wall) in cardinalTurfs
+ if(!A)
+ to_chat(user, "There's nothing to attach the ceiling to!")
+ return
+
+ if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating
+ T.ReplaceWithLattice()
+ T.ChangeTurf(/turf/simulated/floor, preserve_outdoors = TRUE)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ user.visible_message("[user] patches a hole in the ceiling.", "You patch a hole in the ceiling.")
+ expended_tile = TRUE
+ else
+ to_chat(user, "There aren't any holes in the ceiling to patch here.")
+ return
+
+ // Create a ceiling to shield from the weather
+ if(src.outdoors)
+ for(var/dir in cardinal)
+ var/turf/A = get_step(src, dir)
+ if(A && !A.outdoors)
+ if(expended_tile || R.use(1))
+ make_indoors()
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ user.visible_message("[user] roofs a tile, shielding it from the elements.", "You roof this tile, shielding it from the elements.")
+ break
+ return
+
if(flooring)
if(istype(C, /obj/item/weapon))
try_deconstruct_tile(C, user)
diff --git a/code/game/turfs/simulated/outdoors/outdoors.dm b/code/game/turfs/simulated/outdoors/outdoors.dm
index 969c77f4fb5..f56d5a2da36 100644
--- a/code/game/turfs/simulated/outdoors/outdoors.dm
+++ b/code/game/turfs/simulated/outdoors/outdoors.dm
@@ -1,5 +1,4 @@
var/list/turf_edge_cache = list()
-var/list/outdoor_turfs = list()
/turf/
// If greater than 0, this turf will apply edge overlays on top of other turfs cardinally adjacent to it, if those adjacent turfs are of a different icon_state,
@@ -24,24 +23,21 @@ var/list/outdoor_turfs = list()
/turf/simulated/floor/New()
if(outdoors)
- outdoor_turfs.Add(src)
+ SSplanets.addTurf(src)
..()
/turf/simulated/floor/Destroy()
if(outdoors)
- planet_controller.unallocateTurf(src)
+ SSplanets.removeTurf(src)
return ..()
/turf/simulated/proc/make_outdoors()
outdoors = TRUE
- outdoor_turfs.Add(src)
+ SSplanets.addTurf(src)
/turf/simulated/proc/make_indoors()
outdoors = FALSE
- if(planet_controller)
- planet_controller.unallocateTurf(src)
- else // This is happening during map gen, if there's no planet_controller (hopefully).
- outdoor_turfs -= src
+ SSplanets.removeTurf(src)
/turf/simulated/post_change()
..()
@@ -58,8 +54,8 @@ var/list/outdoor_turfs = list()
if(istype(T) && T.edge_blending_priority && edge_blending_priority < T.edge_blending_priority && icon_state != T.icon_state)
var/cache_key = "[T.get_edge_icon_state()]-[checkdir]"
if(!turf_edge_cache[cache_key])
- var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir)
- I.plane = 0
+ var/image/I = image(icon = 'icons/turf/outdoors_edge.dmi', icon_state = "[T.get_edge_icon_state()]-edge", dir = checkdir, layer = ABOVE_TURF_LAYER)
+ I.plane = TURF_PLANE
turf_edge_cache[cache_key] = I
add_overlay(turf_edge_cache[cache_key])
diff --git a/code/game/turfs/simulated/outdoors/sky.dm b/code/game/turfs/simulated/outdoors/sky.dm
index c329fc2e4d1..468b893b335 100644
--- a/code/game/turfs/simulated/outdoors/sky.dm
+++ b/code/game/turfs/simulated/outdoors/sky.dm
@@ -14,7 +14,7 @@
/turf/simulated/sky/initialize()
. = ..()
- outdoor_turfs.Add(src)
+ SSplanets.addTurf(src)
set_light(2, 2, "#FFFFFF")
/turf/simulated/sky/north
diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm
index bc62d1dc351..70cacfba2ca 100644
--- a/code/game/turfs/simulated/wall_attacks.dm
+++ b/code/game/turfs/simulated/wall_attacks.dm
@@ -142,15 +142,44 @@
return
//get the user's location
- if(!istype(user.loc, /turf)) return //can't do this stuff whilst inside objects and such
+ if(!istype(user.loc, /turf))
+ return //can't do this stuff whilst inside objects and such
if(W)
radiate()
if(is_hot(W))
burn(is_hot(W))
+ if(istype(W, /obj/item/stack/tile/roofing))
+ var/expended_tile = FALSE // To track the case. If a ceiling is built in a multiz zlevel, it also necessarily roofs it against weather
+ var/turf/T = GetAbove(src)
+ var/obj/item/stack/tile/roofing/R = W
+
+ // Place plating over a wall
+ if(T)
+ if(istype(T, /turf/simulated/open) || istype(T, /turf/space))
+ if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating
+ T.ReplaceWithLattice()
+ T.ChangeTurf(/turf/simulated/floor, preserve_outdoors = TRUE)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ user.visible_message("[user] patches a hole in the ceiling.", "You patch a hole in the ceiling.")
+ expended_tile = TRUE
+ else
+ to_chat(user, "There aren't any holes in the ceiling to patch here.")
+ return
+
+ // Create a ceiling to shield from the weather
+ if(outdoors)
+ if(expended_tile || R.use(1)) // Don't need to check adjacent turfs for a wall, we're building on one
+ make_indoors()
+ if(!expended_tile) // Would've already played a sound
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ user.visible_message("[user] roofs \the [src], shielding it from the elements.", "You roof \the [src] tile, shielding it from the elements.")
+ return
+
+
if(locate(/obj/effect/overlay/wallrot) in src)
- if(W.is_welder())
+ if(istype(W, /obj/item/weapon/weldingtool) )
var/obj/item/weapon/weldingtool/WT = W
if( WT.remove_fuel(0,user) )
to_chat(user, "You burn away the fungi with \the [WT].")
@@ -165,7 +194,7 @@
//THERMITE related stuff. Calls src.thermitemelt() which handles melting simulated walls and the relevant effects
if(thermite)
- if(W.is_welder())
+ if( istype(W, /obj/item/weapon/weldingtool) )
var/obj/item/weapon/weldingtool/WT = W
if( WT.remove_fuel(0,user) )
thermitemelt(user)
@@ -188,7 +217,7 @@
var/turf/T = user.loc //get user's location for delay checks
- if(damage && W.is_welder())
+ if(damage && istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
@@ -214,7 +243,7 @@
var/dismantle_verb
var/dismantle_sound
- if(W.is_welder())
+ if(istype(W,/obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(!WT.isOn())
return
@@ -282,7 +311,7 @@
return
if(4)
var/cut_cover
- if(W.is_welder())
+ if(istype(W,/obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(!WT.isOn())
return
@@ -337,7 +366,7 @@
return
if(1)
var/cut_cover
- if(W.is_welder())
+ if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if( WT.remove_fuel(0,user) )
cut_cover=1
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index e5bb57ad9e8..b64ba73ee33 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -115,9 +115,9 @@
plant.pixel_y = 0
plant.update_neighbors()
-/turf/simulated/wall/ChangeTurf(var/newtype)
+/turf/simulated/wall/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors)
clear_plants()
- ..(newtype)
+ ..(N, tell_universe, force_lighting_update, preserve_outdoors)
//Appearance
/turf/simulated/wall/examine(mob/user)
diff --git a/code/game/turfs/simulated/water.dm b/code/game/turfs/simulated/water.dm
index e4b762d7333..b7f4299f023 100644
--- a/code/game/turfs/simulated/water.dm
+++ b/code/game/turfs/simulated/water.dm
@@ -19,6 +19,7 @@
..() // To get the edges.
icon_state = water_state
var/image/floorbed_sprite = image(icon = 'icons/turf/outdoors.dmi', icon_state = under_state)
+ underlays.Cut() // To clear the old underlay, so the list doesn't expand infinitely
underlays.Add(floorbed_sprite)
update_icon_edge()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 13368bb7ed7..ed480130503 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -33,18 +33,18 @@
/turf/space/attackby(obj/item/C as obj, mob/user as mob)
- if (istype(C, /obj/item/stack/rods))
+ if(istype(C, /obj/item/stack/rods))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
return
var/obj/item/stack/rods/R = C
if (R.use(1))
- user << "Constructing support lattice ..."
+ to_chat(user, "Constructing support lattice ...")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
return
- if (istype(C, /obj/item/stack/tile/floor))
+ if(istype(C, /obj/item/stack/tile/floor))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
var/obj/item/stack/tile/floor/S = C
@@ -56,7 +56,33 @@
ChangeTurf(/turf/simulated/floor/airless)
return
else
- user << "The plating is going to need some support."
+ to_chat(user, "The plating is going to need some support.")
+
+ if(istype(C, /obj/item/stack/tile/roofing))
+ var/turf/T = GetAbove(src)
+ var/obj/item/stack/tile/roofing/R = C
+
+ // Patch holes in the ceiling
+ if(T)
+ if(istype(T, /turf/simulated/open) || istype(T, /turf/space))
+ // Must be build adjacent to an existing floor/wall, no floating floors
+ var/turf/simulated/A = locate(/turf/simulated/floor) in T.CardinalTurfs()
+ if(!A)
+ A = locate(/turf/simulated/wall) in T.CardinalTurfs()
+ if(!A)
+ to_chat(user, "There's nothing to attach the ceiling to!")
+ return
+
+ if(R.use(1)) // Cost of roofing tiles is 1:1 with cost to place lattice and plating
+ T.ReplaceWithLattice()
+ T.ChangeTurf(/turf/simulated/floor)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
+ user.visible_message("[user] expands the ceiling.", "You expand the ceiling.")
+ else
+ to_chat(user, "There aren't any holes in the ceiling to patch here.")
+ return
+ // Space shouldn't have weather of the sort planets with atmospheres do.
+ // If that's changed, then you'll want to swipe the rest of the roofing code from code/game/turfs/simulated/floor_attackby.dm
return
@@ -64,7 +90,7 @@
/turf/space/Entered(atom/movable/A as mob|obj)
if(movement_disabled)
- usr << "Movement is admin-disabled." //This is to identify lag problems
+ to_chat(usr, "Movement is admin-disabled.") //This is to identify lag problems
return
..()
if ((!(A) || src != A.loc)) return
@@ -187,5 +213,5 @@
A.loc.Entered(A)
return
-/turf/space/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0)
- return ..(N, tell_universe, 1)
+/turf/space/ChangeTurf(var/turf/N, var/tell_universe, var/force_lighting_update, var/preserve_outdoors)
+ return ..(N, tell_universe, 1, preserve_outdoors)
diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm
index 115a7899879..3b5a797c0a0 100644
--- a/code/game/turfs/turf_changing.dm
+++ b/code/game/turfs/turf_changing.dm
@@ -22,7 +22,7 @@
below.update_icon() // To add or remove the 'ceiling-less' overlay.
//Creates a new turf
-/turf/proc/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0)
+/turf/proc/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/preserve_outdoors = FALSE)
if (!N)
return
@@ -38,6 +38,7 @@
var/old_affecting_lights = affecting_lights
var/old_lighting_overlay = lighting_overlay
var/old_corners = corners
+ var/old_outdoors = outdoors
//world << "Replacing [src.type] with [N]"
@@ -106,3 +107,6 @@
lighting_build_overlay()
else
lighting_clear_overlay()
+
+ if(preserve_outdoors)
+ outdoors = old_outdoors
\ No newline at end of file
diff --git a/code/game/turfs/unsimulated/planetary.dm b/code/game/turfs/unsimulated/planetary.dm
index 613638ec804..35cd7aa4a80 100644
--- a/code/game/turfs/unsimulated/planetary.dm
+++ b/code/game/turfs/unsimulated/planetary.dm
@@ -1,7 +1,5 @@
// This is a wall you surround the area of your "planet" with, that makes the atmosphere inside stay within bounds, even if canisters
// are opened or other strange things occur.
-var/list/planetary_walls = list()
-
/turf/unsimulated/wall/planetary
name = "railroading"
desc = "Choo choo!"
@@ -21,10 +19,10 @@ var/list/planetary_walls = list()
/turf/unsimulated/wall/planetary/New()
..()
- planetary_walls.Add(src)
+ SSplanets.addTurf(src)
/turf/unsimulated/wall/planetary/Destroy()
- planetary_walls.Remove(src)
+ SSplanets.removeTurf(src)
..()
/turf/unsimulated/wall/planetary/proc/set_temperature(var/new_temperature)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index dfbd1429088..56a440b639c 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -133,7 +133,8 @@ var/list/admin_verbs_fun = list(
/client/proc/roll_dices,
/datum/admins/proc/call_supply_drop,
/datum/admins/proc/call_drop_pod,
- /client/proc/smite
+ /client/proc/smite,
+ /client/proc/admin_lightning_strike
)
var/list/admin_verbs_spawn = list(
diff --git a/code/modules/admin/verbs/antag-ooc.dm b/code/modules/admin/verbs/antag-ooc.dm
index 22689f17188..13c6e6a767a 100644
--- a/code/modules/admin/verbs/antag-ooc.dm
+++ b/code/modules/admin/verbs/antag-ooc.dm
@@ -12,7 +12,7 @@
else if(is_antag && !is_admin) // Is an antag, and not an admin, meaning we need to check if their antag type allows AOOC.
var/datum/antagonist/A = get_antag_data(usr.mind.special_role)
- if(!A || !A.can_use_aooc)
+ if(!A || !A.can_speak_aooc || !A.can_hear_aooc)
to_chat(usr, "Sorry, but your antagonist type is not allowed to speak in AOOC.")
return
@@ -36,7 +36,7 @@
var/datum/antagonist/A = null
if(M.mind) // Observers don't have minds, but they should still see AOOC.
A = get_antag_data(M.mind.special_role)
- if((M.mind && M.mind.special_role && A && A.can_use_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC.
+ if((M.mind && M.mind.special_role && A && A.can_hear_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC.
to_chat(M, "[create_text_tag("aooc", "Antag-OOC:", M.client)] [player_display]: [msg]")
log_aooc(msg,src)
\ No newline at end of file
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 50bc79d8fec..c6f2c0321ed 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -637,7 +637,7 @@
if(!check_rights(R_DEBUG))
return
- var/datum/planet/planet = input(usr, "Which planet do you want to modify the weather on?", "Change Weather") in planet_controller.planets
+ var/datum/planet/planet = input(usr, "Which planet do you want to modify the weather on?", "Change Weather") in SSplanets.planets
var/datum/weather/new_weather = input(usr, "What weather do you want to change to?", "Change Weather") as null|anything in planet.weather_holder.allowed_weather_types
if(new_weather)
planet.weather_holder.change_weather(new_weather)
@@ -653,7 +653,7 @@
if(!check_rights(R_DEBUG))
return
- var/datum/planet/planet = input(usr, "Which planet do you want to modify time on?", "Change Time") in planet_controller.planets
+ var/datum/planet/planet = input(usr, "Which planet do you want to modify time on?", "Change Time") in SSplanets.planets
var/datum/time/current_time_datum = planet.current_time
var/new_hour = input(usr, "What hour do you want to change to?", "Change Time", text2num(current_time_datum.show_time("hh"))) as null|num
diff --git a/code/modules/admin/verbs/lightning_strike.dm b/code/modules/admin/verbs/lightning_strike.dm
new file mode 100644
index 00000000000..ca8d743614c
--- /dev/null
+++ b/code/modules/admin/verbs/lightning_strike.dm
@@ -0,0 +1,115 @@
+/client/proc/admin_lightning_strike()
+ set name = "Lightning Stirke"
+ set desc = "Causes lightning to strike on your tile. This will hurt things on or nearby it severely."
+ set category = "Fun"
+
+ if(!check_rights(R_FUN))
+ return
+
+ var/result = alert(src, "Really strike your tile with lightning?", "Confirm Badmin" , "No", "Yes (Cosmetic)", "Yes (Real)")
+
+ if(result == "No")
+ return
+ var/fake_lightning = result == "Yes (Cosmetic)"
+
+ lightning_strike(get_turf(usr), fake_lightning)
+ log_and_message_admins("[key_name(src)] has caused [fake_lightning ? "cosmetic":"harmful"] lightning to strike at their position ([src.mob.x], [src.mob.y], [src.mob.z]). \
+ (JMP)")
+
+#define LIGHTNING_REDIRECT_RANGE 28 // How far in tiles certain things draw lightning from.
+#define LIGHTNING_ZAP_RANGE 3 // How far the tesla effect zaps, as well as the bad effects from a direct strike.
+#define LIGHTNING_POWER 20000 // How much 'zap' is in a strike, used for tesla_zap().
+
+// The real lightning proc.
+// This is global until I can figure out a better place for it.
+// T is the turf that is being struck. If cosmetic is true, the lightning won't actually hurt anything.
+/proc/lightning_strike(turf/T, cosmetic = FALSE)
+ // First, visuals.
+
+ // Do a lightning flash for the whole planet, if the turf belongs to a planet.
+ var/datum/planet/P = null
+ P = SSplanets.z_to_planet[T.z]
+ if(P)
+ var/datum/weather_holder/holder = P.weather_holder
+ flick("lightning_flash", holder.special_visuals)
+
+ // Before we do the other visuals, we need to see if something is going to hijack our intended target.
+ var/obj/machinery/power/grounding_rod/ground = null // Most of the bad effects of lightning will get negated if a grounding rod is nearby.
+ var/obj/machinery/power/tesla_coil/coil = null // However a tesla coil has higher priority and the strike will bounce.
+
+ for(var/obj/machinery/power/thing in range(LIGHTNING_REDIRECT_RANGE, T))
+ if(istype(thing, /obj/machinery/power/tesla_coil))
+ var/turf/simulated/coil_turf = get_turf(thing)
+ if(istype(coil_turf) && thing.anchored && coil_turf.outdoors)
+ coil = thing
+ break
+
+ if(istype(thing, /obj/machinery/power/grounding_rod))
+ var/turf/simulated/rod_turf = get_turf(thing)
+ if(istype(rod_turf) && thing.anchored && rod_turf.outdoors)
+ ground = thing
+
+ if(coil) // Coil gets highest priority.
+ T = coil.loc
+ else if(ground)
+ T = ground.loc
+
+ // Now make the lightning strike sprite. It will fade and delete itself in a second.
+ new /obj/effect/temporary_effect/lightning_strike(T)
+
+ // For those close up.
+ playsound(T, 'sound/effects/lightningbolt.ogg', 100, 1)
+
+ // And for those far away. If the strike happens on a planet, everyone on the planet will hear it.
+ // Otherwise only those on the current z-level will hear it.
+ var/sound = get_sfx("thunder")
+ for(var/mob/M in player_list)
+ if((P && M.z in P.expected_z_levels) || M.z == T.z)
+ M.playsound_local(get_turf(M), soundin = sound, vol = 70, vary = FALSE, is_global = TRUE)
+
+ if(cosmetic) // Everything beyond here involves potentially damaging things. If we don't want to do that, stop now.
+ return
+
+ if(ground) // All is well.
+ ground.tesla_act(LIGHTNING_POWER, FALSE)
+ return
+
+ else if(coil) // Otherwise lets bounce off the tesla coil.
+ coil.tesla_act(LIGHTNING_POWER, TRUE)
+
+ else // Striking the turf directly.
+ tesla_zap(T, zap_range = LIGHTNING_ZAP_RANGE, power = LIGHTNING_POWER, explosive = FALSE, stun_mobs = TRUE)
+
+ // Some extra effects.
+ // Some apply to those within zap range, others if they were a bit farther away.
+ for(var/mob/living/L in view(5, T))
+ if(get_dist(L, T) <= LIGHTNING_ZAP_RANGE) // They probably got zapped.
+ // The actual damage/electrocution is handled by tesla_zap().
+ L.Paralyse(5)
+ L.stuttering += 20
+ L.make_jittery(20)
+ L.emp_act(1)
+ to_chat(L, span("critical", "You've been struck by lightning!"))
+
+ // If a non-player simplemob was struck, inflict huge damage.
+ // If the damage is fatal, the SA is turned to ash.
+ if(istype(L, /mob/living/simple_animal) && !L.key)
+ var/mob/living/simple_animal/SA = L
+ SA.adjustFireLoss(200)
+ SA.updatehealth()
+ if(SA.health <= 0) // Might be best to check/give simple_mobs siemens when this gets ported to new mobs.
+ SA.visible_message(span("critical", "\The [SA] disintegrates into ash!"))
+ SA.ash()
+ continue // No point deafening something that wont exist.
+
+ // Deafen them.
+ if(L.get_ear_protection() < 2)
+ L.AdjustSleeping(-100)
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ C.ear_deaf += 10
+ to_chat(L, span("danger", "Lightning struck nearby, and the thunderclap is deafening!"))
+
+#undef GROUNDING_ROD_RANGE
+#undef LIGHTNING_ZAP_RANGE
+#undef LIGHTNING_POWER
\ No newline at end of file
diff --git a/code/modules/artifice/deadringer.dm b/code/modules/artifice/deadringer.dm
new file mode 100644
index 00000000000..e12c0b0045d
--- /dev/null
+++ b/code/modules/artifice/deadringer.dm
@@ -0,0 +1,177 @@
+/obj/item/weapon/deadringer
+ name = "silver pocket watch"
+ desc = "A fancy silver-plated digital pocket watch. Looks expensive."
+ icon = 'icons/obj/deadringer.dmi'
+ icon_state = "deadringer"
+ w_class = ITEMSIZE_SMALL
+ slot_flags = SLOT_ID | SLOT_BELT | SLOT_TIE
+ origin_tech = list(TECH_ILLEGAL = 3)
+ var/activated = 0
+ var/timer = 0
+ var/bruteloss_prev = 999999
+ var/fireloss_prev = 999999
+ var/mob/living/carbon/human/corpse = null
+ var/mob/living/carbon/human/watchowner = null
+
+
+/obj/item/weapon/deadringer/New()
+ ..()
+ processing_objects |= src
+
+/obj/item/weapon/deadringer/Destroy() //just in case some smartass tries to stay invisible by destroying the watch
+ uncloak()
+ processing_objects -= src
+ ..()
+
+/obj/item/weapon/deadringer/dropped()
+ if(timer > 20)
+ uncloak()
+ watchowner = null
+ return
+
+/obj/item/weapon/deadringer/attack_self(var/mob/living/user as mob)
+ var/mob/living/H = src.loc
+ if (!istype(H, /mob/living/carbon/human))
+ to_chat(H,"You have no clue what to do with this thing.")
+ return
+ if(!activated)
+ if(timer == 0)
+ to_chat(H, "You press a small button on [src]'s side. It starts to hum quietly.")
+ bruteloss_prev = H.getBruteLoss()
+ fireloss_prev = H.getFireLoss()
+ activated = 1
+ return
+ else
+ to_chat(H,"You press a small button on [src]'s side. It buzzes a little.")
+ return
+ if(activated)
+ to_chat(H,"You press a small button on [src]'s side. It stops humming.")
+ activated = 0
+ return
+
+/obj/item/weapon/deadringer/process()
+ if(activated)
+ if (ismob(src.loc))
+ var/mob/living/carbon/human/H = src.loc
+ watchowner = H
+ if(H.getBruteLoss() > bruteloss_prev || H.getFireLoss() > fireloss_prev)
+ deathprevent()
+ activated = 0
+ if(watchowner.isSynthetic())
+ to_chat(watchowner, "You fade into nothingness! [src]'s screen blinks, being unable to copy your synthetic body!")
+ else
+ to_chat(watchowner, "You fade into nothingness, leaving behind a fake body!")
+ icon_state = "deadringer_cd"
+ timer = 50
+ return
+ if(timer > 0)
+ timer--
+ if(timer == 20)
+ uncloak()
+ if(corpse)
+ new /obj/effect/effect/smoke/chem(corpse.loc)
+ qdel(corpse)
+ if(timer == 0)
+ icon_state = "deadringer"
+ return
+
+/obj/item/weapon/deadringer/proc/deathprevent()
+ for(var/mob/living/simple_animal/D in oviewers(7, src))
+ D.LoseTarget()
+ watchowner.emote("deathgasp")
+ watchowner.alpha = 15
+ makeacorpse(watchowner)
+ for(var/mob/living/simple_animal/D in oviewers(7, src))
+ D.LoseTarget()
+ return
+
+/obj/item/weapon/deadringer/proc/uncloak()
+ if(watchowner)
+ watchowner.alpha = 255
+ playsound(get_turf(src), 'sound/effects/uncloak.ogg', 35, 1, -1)
+ return
+
+/obj/item/weapon/deadringer/proc/makeacorpse(var/mob/living/carbon/human/H)
+ if(H.isSynthetic())
+ return
+ corpse = new /mob/living/carbon/human(H.loc)
+ corpse.setDNA(H.dna.Clone())
+ corpse.death(1) //Kills the new mob
+ var/obj/item/clothing/temp = null
+ if(H.get_equipped_item(slot_w_uniform))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/under/chameleon/changeling(corpse), slot_w_uniform)
+ temp = corpse.get_equipped_item(slot_w_uniform)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_w_uniform)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_wear_suit))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/suit/chameleon/changeling(corpse), slot_wear_suit)
+ temp = corpse.get_equipped_item(slot_wear_suit)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_wear_suit)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_shoes))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/shoes/chameleon/changeling(corpse), slot_shoes)
+ temp = corpse.get_equipped_item(slot_shoes)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_shoes)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_gloves))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/gloves/chameleon/changeling(corpse), slot_gloves)
+ temp = corpse.get_equipped_item(slot_gloves)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_gloves)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_l_ear))
+ temp = H.get_equipped_item(slot_l_ear)
+ corpse.equip_to_slot_or_del(new temp.type(corpse), slot_l_ear)
+ temp = corpse.get_equipped_item(slot_l_ear)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_glasses))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/glasses/chameleon/changeling(corpse), slot_glasses)
+ temp = corpse.get_equipped_item(slot_glasses)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_glasses)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_wear_mask))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/mask/chameleon/changeling(corpse), slot_wear_mask)
+ temp = corpse.get_equipped_item(slot_wear_mask)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_wear_mask)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_head))
+ corpse.equip_to_slot_or_del(new /obj/item/clothing/head/chameleon/changeling(corpse), slot_head)
+ temp = corpse.get_equipped_item(slot_head)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_head)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_belt))
+ corpse.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/chameleon/changeling(corpse), slot_belt)
+ temp = corpse.get_equipped_item(slot_belt)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_belt)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ if(H.get_equipped_item(slot_back))
+ corpse.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/chameleon/changeling(corpse), slot_back)
+ temp = corpse.get_equipped_item(slot_back)
+ var/obj/item/clothing/c_type = H.get_equipped_item(slot_back)
+ temp.disguise(c_type.type)
+ temp.canremove = 0
+ corpse.identifying_gender = H.identifying_gender
+ corpse.flavor_texts = H.flavor_texts.Copy()
+ corpse.real_name = H.real_name
+ corpse.name = H.name
+ corpse.set_species(corpse.dna.species)
+ corpse.change_hair(H.h_style)
+ corpse.change_facial_hair(H.f_style)
+ corpse.change_hair_color(H.r_hair, H.g_hair, H.b_hair)
+ corpse.change_facial_hair_color(H.r_facial, H.g_facial, H.b_facial)
+ corpse.change_skin_color(H.r_skin, H.g_skin, H.b_skin)
+ corpse.adjustFireLoss(H.getFireLoss())
+ corpse.adjustBruteLoss(H.getBruteLoss())
+ corpse.UpdateAppearance()
+ corpse.regenerate_icons()
+ for(var/obj/item/organ/internal/I in corpse.internal_organs)
+ var/obj/item/organ/internal/G = I
+ G.Destroy()
+ return
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 63c781452c8..9e9eaeb8687 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -250,9 +250,8 @@
return
/obj/effect/beam/i_beam/Destroy()
+ . = ..()
if(master.first == src)
master.first = null
- if(next)
- qdel(next)
- next = null
- ..()
+ if(next && !next.gc_destroyed)
+ qdel_null(next)
diff --git a/code/modules/client/preference_setup/general/01_basic.dm b/code/modules/client/preference_setup/general/01_basic.dm
index f0bccd731e0..f044322cab9 100644
--- a/code/modules/client/preference_setup/general/01_basic.dm
+++ b/code/modules/client/preference_setup/general/01_basic.dm
@@ -71,8 +71,8 @@ datum/preferences/proc/set_biological_gender(var/gender)
. += "Nickname: "
. += "[pref.nickname]"
. += "
"
- . += "Biological Gender: [gender2text(pref.biological_gender)]
"
- . += "Gender Identity: [gender2text(pref.identifying_gender)]
"
+ . += "Biological Sex: [gender2text(pref.biological_gender)]
"
+ . += "Pronouns: [gender2text(pref.identifying_gender)]
"
. += "Age: [pref.age]
"
. += "Spawn Point: [pref.spawnpoint]
"
if(config.allow_Metadata)
@@ -111,13 +111,13 @@ datum/preferences/proc/set_biological_gender(var/gender)
return TOPIC_NOACTION
else if(href_list["bio_gender"])
- var/new_gender = input(user, "Choose your character's biological gender:", "Character Preference", pref.biological_gender) as null|anything in get_genders()
+ var/new_gender = input(user, "Choose your character's biological sex:", "Character Preference", pref.biological_gender) as null|anything in get_genders()
if(new_gender && CanUseTopic(user))
pref.set_biological_gender(new_gender)
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["id_gender"])
- var/new_gender = input(user, "Choose your character's identifying gender:", "Character Preference", pref.identifying_gender) as null|anything in all_genders_define_list
+ var/new_gender = input(user, "Choose your character's pronouns:", "Character Preference", pref.identifying_gender) as null|anything in all_genders_define_list
if(new_gender && CanUseTopic(user))
pref.identifying_gender = new_gender
return TOPIC_REFRESH
@@ -158,4 +158,4 @@ datum/preferences/proc/set_biological_gender(var/gender)
return possible_genders
possible_genders = possible_genders.Copy()
possible_genders |= NEUTER
- return possible_genders
\ No newline at end of file
+ return possible_genders
diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm
index 1fc3b1d8ba6..e098283a2e5 100644
--- a/code/modules/client/preference_setup/general/03_body.dm
+++ b/code/modules/client/preference_setup/general/03_body.dm
@@ -36,6 +36,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["synth_red"] >> pref.r_synth
S["synth_green"] >> pref.g_synth
S["synth_blue"] >> pref.b_synth
+ S["synth_markings"] >> pref.synth_markings
pref.preview_icon = null
S["bgstate"] >> pref.bgstate
@@ -65,6 +66,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
S["synth_red"] << pref.r_synth
S["synth_green"] << pref.g_synth
S["synth_blue"] << pref.b_synth
+ S["synth_markings"] << pref.synth_markings
S["bgstate"] << pref.bgstate
/datum/category_item/player_setup_item/general/body/sanitize_character(var/savefile/S)
@@ -120,6 +122,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
character.r_synth = pref.r_synth
character.g_synth = pref.g_synth
character.b_synth = pref.b_synth
+ character.synth_markings = pref.synth_markings
// Destroy/cyborgize organs and limbs.
for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO))
@@ -300,11 +303,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
. += "
Body Markings +
"
for(var/M in pref.body_markings)
- . += "[M] - Color"
+ . += "[M] [pref.body_markings.len > 1 ? "˄ ˅ " : ""]- Color"
. += ""
. += "
"
. += "
"
+ . += "Allow Synth markings: [pref.synth_markings ? "Yes" : "No"]
"
. += "Allow Synth color: [pref.synth_color ? "Yes" : "No"]
"
if(pref.synth_color)
. += "Change Color "
@@ -493,6 +497,24 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.body_markings[new_marking] = "#000000" //New markings start black
return TOPIC_REFRESH_UPDATE_PREVIEW
+ else if(href_list["marking_up"])
+ var/M = href_list["marking_up"]
+ var/start = pref.body_markings.Find(M)
+ if(start != 1) //If we're not the beginning of the list, swap with the previous element.
+ moveElement(pref.body_markings, start, start-1)
+ else //But if we ARE, become the final element -ahead- of everything else.
+ moveElement(pref.body_markings, start, pref.body_markings.len+1)
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
+ else if(href_list["marking_down"])
+ var/M = href_list["marking_down"]
+ var/start = pref.body_markings.Find(M)
+ if(start != pref.body_markings.len) //If we're not the end of the list, swap with the next element.
+ moveElement(pref.body_markings, start, start+2)
+ else //But if we ARE, become the first element -behind- everything else.
+ moveElement(pref.body_markings, start, 1)
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
else if(href_list["marking_remove"])
var/M = href_list["marking_remove"]
pref.body_markings -= M
@@ -702,6 +724,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.b_synth = hex2num(copytext(new_color, 6, 8))
return TOPIC_REFRESH_UPDATE_PREVIEW
+ else if(href_list["synth_markings"])
+ pref.synth_markings = !pref.synth_markings
+ return TOPIC_REFRESH_UPDATE_PREVIEW
+
else if(href_list["cycle_bg"])
pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options)
return TOPIC_REFRESH_UPDATE_PREVIEW
diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm
index 9161f655175..41d37b8a67d 100644
--- a/code/modules/client/preference_setup/loadout/loadout_suit.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm
@@ -241,6 +241,46 @@ datum/gear/suit/duster
path = /obj/item/clothing/accessory/poncho/roles/cloak/hop
allowed_roles = list("Head of Personnel")
+/datum/gear/suit/roles/poncho/cloak/cargo
+ display_name = "cloak, cargo"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/cargo
+ allowed_roles = list("Cargo Technician","Quartermaster")
+
+/datum/gear/suit/roles/poncho/cloak/mining
+ display_name = "cloak, mining"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/mining
+ allowed_roles = list("Quartermaster","Shaft Miner")
+
+/datum/gear/suit/roles/poncho/cloak/security
+ display_name = "cloak, security"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/security
+ allowed_roles = list("Head of Security","Detective","Warden","Security Officer")
+
+/datum/gear/suit/roles/poncho/cloak/service
+ display_name = "cloak, service"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/service
+ allowed_roles = list("Head of Personnel","Bartender","Botanist","Janitor","Chef","Librarian")
+
+/datum/gear/suit/roles/poncho/cloak/engineer
+ display_name = "cloak, engineer"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/engineer
+ allowed_roles = list("Chief Engineer","Station Engineer")
+
+/datum/gear/suit/roles/poncho/cloak/atmos
+ display_name = "cloak, atmos"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/atmos
+ allowed_roles = list("Chief Engineer","Atmospheric Technician")
+
+/datum/gear/suit/roles/poncho/cloak/research
+ display_name = "cloak, science"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/research
+ allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist")
+
+/datum/gear/suit/roles/poncho/cloak/medical
+ display_name = "cloak, medical"
+ path = /obj/item/clothing/accessory/poncho/roles/cloak/medical
+ allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist")
+
/datum/gear/suit/unathi_robe
display_name = "roughspun robe"
path = /obj/item/clothing/suit/unathi/robe
diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm
index 3da9a7226c9..1f35cc925a8 100644
--- a/code/modules/client/preference_setup/loadout/loadout_utility.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm
@@ -114,12 +114,6 @@
path = /obj/item/weapon/cell/device
/datum/gear/utility/implant
- exploitable = 1
-
-/datum/gear/utility/implant/eal //This does nothing if you don't actually know EAL.
- display_name = "implant, language, EAL"
- path = /obj/item/weapon/implant/language/eal
- cost = 2
slot = "implant"
exploitable = 1
@@ -127,8 +121,20 @@
display_name = "implant, tracking"
path = /obj/item/weapon/implant/tracking/weak
cost = 10
- slot = "implant"
- exploitable = 1
+
+/datum/gear/utility/implant/language
+ cost = 2
+ exploitable = 0
+
+/datum/gear/utility/implant/language/eal
+ display_name = "vocal synthesizer, EAL"
+ description = "A surgically implanted vocal synthesizer which allows the owner to speak EAL, if they know it."
+ path = /obj/item/weapon/implant/language/eal
+
+/datum/gear/utility/implant/language/skrellian
+ display_name = "vocal synthesizer, Skrellian"
+ description = "A surgically implanted vocal synthesizer which allows the owner to speak Common Skrellian, if they know it."
+ path = /obj/item/weapon/implant/language/skrellian
/datum/gear/utility/pen
display_name = "Fountain Pen"
diff --git a/code/modules/client/preference_setup/traits/trait_defines.dm b/code/modules/client/preference_setup/traits/trait_defines.dm
index f8405eb7f83..82e3aee7385 100644
--- a/code/modules/client/preference_setup/traits/trait_defines.dm
+++ b/code/modules/client/preference_setup/traits/trait_defines.dm
@@ -92,6 +92,30 @@
modifier_type = /datum/modifier/trait/larger
mutually_exclusive = list(/datum/trait/modifier/physical/smaller, /datum/trait/modifier/physical/small, /datum/trait/modifier/physical/large)
+/datum/trait/modifier/physical/colorblind_protanopia
+ name = "Protanopia"
+ desc = "You have a form of red-green colorblindness. You cannot see reds, and have trouble distinguishing them from yellows and greens."
+ modifier_type = /datum/modifier/trait/colorblind_protanopia
+ mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_deuteranopia, /datum/trait/modifier/physical/colorblind_tritanopia, /datum/trait/modifier/physical/colorblind_monochrome)
+
+/datum/trait/modifier/physical/colorblind_deuteranopia
+ name = "Deuteranopia"
+ desc = "You have a form of red-green colorblindness. You cannot see greens, and have trouble distinguishing them from yellows and reds."
+ modifier_type = /datum/modifier/trait/colorblind_deuteranopia
+ mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_protanopia, /datum/trait/modifier/physical/colorblind_tritanopia, /datum/trait/modifier/physical/colorblind_monochrome)
+
+/datum/trait/modifier/physical/colorblind_tritanopia
+ name = "Tritanopia"
+ desc = "You have a form of blue-yellow colorblindness. You have trouble distinguishing between blues, greens, and yellows, and see blues and violets as dim."
+ modifier_type = /datum/modifier/trait/colorblind_tritanopia
+ mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_protanopia, /datum/trait/modifier/physical/colorblind_deuteranopia, /datum/trait/modifier/physical/colorblind_monochrome)
+
+/datum/trait/modifier/physical/colorblind_monochrome
+ name = "Monochromacy"
+ desc = "You are fully colorblind. Your condition is rare, but you can see no colors at all."
+ modifier_type = /datum/modifier/trait/colorblind_monochrome
+ mutually_exclusive = list(/datum/trait/modifier/physical/colorblind_protanopia, /datum/trait/modifier/physical/colorblind_deuteranopia, /datum/trait/modifier/physical/colorblind_tritanopia)
+
// These two traits might be borderline, feel free to remove if they get abused.
/datum/trait/modifier/physical/high_metabolism
name = "High Metabolism"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index c45567e5a95..dee21ddd5b9 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -60,6 +60,7 @@ datum/preferences
var/r_synth //Used with synth_color to color synth parts that normaly can't be colored.
var/g_synth //Same as above
var/b_synth //Same as above
+ var/synth_markings = 0 //Enable/disable markings on synth parts.
//Some faction information.
var/home_system = "Unset" //System of birth.
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index a1757d561a0..8b466116197 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -253,7 +253,8 @@
var/mob/living/carbon/human/H = user
if(slot && slot == slot_gloves)
- if(H.gloves)
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(istype(G))
ring = H.gloves
if(ring.glove_level >= src.glove_level)
to_chat(user, "You are unable to wear \the [src] as \the [H.gloves] are in the way.")
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 9e0c0a01962..6f613e38abb 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -128,6 +128,7 @@
/obj/item/clothing/suit/syndicatefake
name = "red space suit replica"
+ icon = 'icons/obj/clothing/spacesuits.dmi'
icon_state = "syndicate"
desc = "A plastic replica of the syndicate space suit, you'll look just like a real murderous syndicate agent in this! This is a toy, it is not made for use in space!"
w_class = ITEMSIZE_NORMAL
diff --git a/code/modules/clothing/under/accessories/clothing.dm b/code/modules/clothing/under/accessories/clothing.dm
index eaab8b290a4..02fab3e95a3 100644
--- a/code/modules/clothing/under/accessories/clothing.dm
+++ b/code/modules/clothing/under/accessories/clothing.dm
@@ -121,8 +121,8 @@
* Cloak
*/
/obj/item/clothing/accessory/poncho/roles/cloak
- name = "brown cloak"
- desc = "An elaborate brown cloak."
+ name = "quartermaster's cloak"
+ desc = "An elaborate brown and gold cloak."
icon_state = "qmcloak"
item_state = "qmcloak"
body_parts_covered = null
@@ -169,6 +169,54 @@
icon_state = "capcloak"
item_state = "capcloak"
+/obj/item/clothing/accessory/poncho/roles/cloak/cargo
+ name = "brown cloak"
+ desc = "A simple brown and black cloak."
+ icon_state = "cargocloak"
+ item_state = "cargocloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/mining
+ name = "trimmed purple cloak"
+ desc = "A trimmed purple and brown cloak."
+ icon_state = "miningcloak"
+ item_state = "miningcloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/security
+ name = "red cloak"
+ desc = "A simple red and black cloak."
+ icon_state = "seccloak"
+ item_state = "seccloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/service
+ name = "green cloak"
+ desc = "A simple green and blue cloak."
+ icon_state = "servicecloak"
+ item_state = "servicecloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/engineer
+ name = "gold cloak"
+ desc = "A simple gold and brown cloak."
+ icon_state = "engicloak"
+ item_state = "engicloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/atmos
+ name = "yellow cloak"
+ desc = "A trimmed yellow and blue cloak."
+ icon_state = "atmoscloak"
+ item_state = "atmoscloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/research
+ name = "purple cloak"
+ desc = "A simple purple and white cloak."
+ icon_state = "scicloak"
+ item_state = "scicloak"
+
+/obj/item/clothing/accessory/poncho/roles/cloak/medical
+ name = "blue cloak"
+ desc = "A simple blue and white cloak."
+ icon_state = "medcloak"
+ item_state = "medcloak"
+
/obj/item/clothing/accessory/hawaii
name = "flower-pattern shirt"
desc = "You probably need some welder googles to look at this."
diff --git a/code/modules/events/gravity.dm b/code/modules/events/gravity.dm
index e0cd38dcfbd..4d0881294f4 100644
--- a/code/modules/events/gravity.dm
+++ b/code/modules/events/gravity.dm
@@ -6,9 +6,8 @@
endWhen = rand(15, 60)
// Setup which levels we will disrupt gravit on.
zLevels = using_map.station_levels.Copy()
- if (planet_controller)
- for(var/datum/planet/P in planet_controller.planets)
- zLevels -= P.expected_z_levels
+ for(var/datum/planet/P in SSplanets.planets)
+ zLevels -= P.expected_z_levels
/datum/event/gravity/announce()
command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artificial gravity has been disabled whilst the system \
diff --git a/code/modules/integrated_electronics/core/device.dm b/code/modules/integrated_electronics/core/device.dm
index bcdd0e9bead..1b298c7a368 100644
--- a/code/modules/integrated_electronics/core/device.dm
+++ b/code/modules/integrated_electronics/core/device.dm
@@ -19,6 +19,9 @@
else
..()
+/obj/item/device/electronic_assembly/get_cell()
+ return battery
+
/obj/item/device/assembly/electronic_assembly/proc/toggle_open(mob/user)
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
diff --git a/code/modules/integrated_electronics/core/printer.dm b/code/modules/integrated_electronics/core/printer.dm
index 4dfd4e989a4..794755b02c8 100644
--- a/code/modules/integrated_electronics/core/printer.dm
+++ b/code/modules/integrated_electronics/core/printer.dm
@@ -162,13 +162,16 @@
return 1
var/cost = 1
+
+ if(isnull(current_category))
+ current_category = recipe_list[1]
if(ispath(build_type, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = build_type
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
- else if(ispath(build_type, /obj/item/integrated_circuit))
- var/obj/item/integrated_circuit/IC = build_type
- cost = initial(IC.w_class)
else
+ var/obj/item/I = build_type
+ cost = initial(I.w_class)
+ if(!(locate(build_type) in recipe_list[current_category]))
return
if(metal - cost < 0)
@@ -198,4 +201,4 @@
name = "integrated circuit printer upgrade disk - circuit cloner"
desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies."
icon_state = "upgrade_disk_clone"
- origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 6)
\ No newline at end of file
+ origin_tech = list(TECH_ENGINEERING = 5, TECH_DATA = 6)
diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm
index 94c4594f5b2..24dd18c80bf 100644
--- a/code/modules/integrated_electronics/subtypes/memory.dm
+++ b/code/modules/integrated_electronics/subtypes/memory.dm
@@ -75,7 +75,6 @@
/obj/item/integrated_circuit/memory/constant
name = "constant chip"
desc = "This tiny chip can store one piece of data, which cannot be overwritten without disassembly."
- icon_state = "memory"
complexity = 1
inputs = list()
outputs = list("output pin" = IC_PINTYPE_ANY)
diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm
index 6e75d97a0d9..232ef46e3e3 100644
--- a/code/modules/materials/material_recipes.dm
+++ b/code/modules/materials/material_recipes.dm
@@ -53,6 +53,7 @@
recipes += new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1)
recipes += new/datum/stack_recipe("cannon frame", /obj/item/weapon/cannonframe, 10, time = 15, one_per_turf = 0, on_floor = 0)
recipes += new/datum/stack_recipe("regular floor tile", /obj/item/stack/tile/floor, 1, 4, 20)
+ recipes += new/datum/stack_recipe("roofing tile", /obj/item/stack/tile/roofing, 3, 4, 20)
recipes += new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60)
recipes += new/datum/stack_recipe("frame", /obj/item/frame, 5, time = 25, one_per_turf = 1, on_floor = 1)
recipes += new/datum/stack_recipe("mirror frame", /obj/item/frame/mirror, 1, time = 5, one_per_turf = 0, on_floor = 1)
diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm
new file mode 100644
index 00000000000..dd9c068a17e
--- /dev/null
+++ b/code/modules/mining/fulton.dm
@@ -0,0 +1,191 @@
+var/global/list/total_extraction_beacons = list()
+
+/obj/item/extraction_pack
+ name = "fulton extraction pack"
+ desc = "A balloon that can be used to extract equipment or personnel to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand."
+ icon = 'icons/obj/fulton.dmi'
+ icon_state = "extraction_pack"
+ w_class = ITEMSIZE_NORMAL
+ var/obj/structure/extraction_point/beacon
+ var/list/beacon_networks = list("station")
+ var/uses_left = 3
+ var/can_use_indoors
+ var/safe_for_living_creatures = 1
+
+/obj/item/extraction_pack/examine()
+ . = ..()
+ usr.show_message("It has [uses_left] use\s remaining.", 1)
+
+/obj/item/extraction_pack/attack_self(mob/user)
+ var/list/possible_beacons = list()
+ for(var/B in global.total_extraction_beacons)
+ var/obj/structure/extraction_point/EP = B
+ if(EP.beacon_network in beacon_networks)
+ possible_beacons += EP
+
+ if(!possible_beacons.len)
+ to_chat(user, "There are no extraction beacons in existence!")
+ return
+
+ else
+ var/A
+
+ A = input("Select a beacon to connect to", "Balloon Extraction Pack", A) as null|anything in possible_beacons
+
+ if(!A)
+ return
+ beacon = A
+ to_chat(user, "You link the extraction pack to the beacon system.")
+
+/obj/item/extraction_pack/afterattack(atom/movable/A, mob/living/carbon/human/user, flag, params)
+ if(!beacon)
+ to_chat(user, "[src] is not linked to a beacon, and cannot be used.")
+ return
+ if(!can_use_indoors)
+ var/turf/T = get_turf(A)
+ if(T && !T.outdoors)
+ to_chat(user, "[src] can only be used on things that are outdoors!")
+ return
+ if(!flag)
+ return
+ if(!istype(A))
+ return
+ else
+ if(!safe_for_living_creatures && check_for_living_mobs(A))
+ to_chat(user, "[src] is not safe for use with living creatures, they wouldn't survive the trip back!")
+ return
+ if(!isturf(A.loc)) // no extracting stuff inside other stuff
+ return
+ if(A.anchored)
+ return
+ to_chat(user, "You start attaching the pack to [A]...")
+ if(do_after(user,50,target=A))
+ to_chat(user, "You attach the pack to [A] and activate it.")
+ /* No components, sorry. No convienence for you!
+ if(loc == user && istype(user.back, /obj/item/storage/backpack))
+ var/obj/item/storage/backpack/B = user.back
+ B.SendSignal(COMSIG_TRY_STORAGE_INSERT, src, user, FALSE, FALSE)
+ */
+ uses_left--
+ if(uses_left <= 0)
+ user.drop_from_inventory(src, A)
+ var/mutable_appearance/balloon
+ var/mutable_appearance/balloon2
+ var/mutable_appearance/balloon3
+ if(isliving(A))
+ var/mob/living/M = A
+ M.AdjustStunned(20) // Keep them from moving during the duration of the extraction
+ if(M.buckled)
+ M.buckled.unbuckle_mob(M)
+ else
+ A.anchored = TRUE
+ A.density = FALSE
+ var/obj/effect/extraction_holder/holder_obj = new(A.loc)
+ holder_obj.appearance = A.appearance
+ A.forceMove(holder_obj)
+ balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand")
+ balloon2.pixel_y = 10
+ balloon2.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.add_overlay(balloon2)
+ sleep(4)
+ balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon")
+ balloon.pixel_y = 10
+ balloon.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.cut_overlay(balloon2)
+ holder_obj.add_overlay(balloon)
+ playsound(holder_obj.loc, 'sound/items/fulext_deploy.wav', 50, 1, -3)
+ animate(holder_obj, pixel_z = 10, time = 20)
+ sleep(20)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ playsound(holder_obj.loc, 'sound/items/fultext_launch.wav', 50, 1, -3)
+ animate(holder_obj, pixel_z = 1000, time = 30)
+ if(ishuman(A))
+ var/mob/living/carbon/human/L = A
+ L.AdjustStunned(20)
+ L.drowsyness = 0
+ sleep(30)
+ var/list/flooring_near_beacon = list()
+ for(var/turf/simulated/floor/floor in orange(1, beacon))
+ flooring_near_beacon += floor
+ holder_obj.forceMove(pick(flooring_near_beacon))
+ animate(holder_obj, pixel_z = 10, time = 50)
+ sleep(50)
+ animate(holder_obj, pixel_z = 15, time = 10)
+ sleep(10)
+ animate(holder_obj, pixel_z = 10, time = 10)
+ sleep(10)
+ balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract")
+ balloon3.pixel_y = 10
+ balloon3.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ holder_obj.cut_overlay(balloon)
+ holder_obj.add_overlay(balloon3)
+ sleep(4)
+ holder_obj.cut_overlay(balloon3)
+ A.anchored = FALSE // An item has to be unanchored to be extracted in the first place.
+ A.density = initial(A.density)
+ animate(holder_obj, pixel_z = 0, time = 5)
+ sleep(5)
+ A.forceMove(holder_obj.loc)
+ qdel(holder_obj)
+ if(uses_left <= 0)
+ qdel(src)
+
+
+/obj/item/fulton_core
+ name = "extraction beacon signaller"
+ desc = "Emits a signal which fulton recovery devices can lock onto. Activate in hand to create a beacon."
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "subspace_amplifier"
+
+/obj/item/fulton_core/attack_self(mob/user)
+ if(do_after(user,15,target = user) && !QDELETED(src))
+ new /obj/structure/extraction_point(get_turf(user))
+ qdel(src)
+
+/obj/structure/extraction_point
+ name = "fulton recovery beacon"
+ desc = "A beacon for the fulton recovery system. Activate a pack in your hand to link it to a beacon."
+ icon = 'icons/obj/fulton.dmi'
+ icon_state = "extraction_point"
+ anchored = TRUE
+ density = FALSE
+ var/beacon_network = "station"
+
+/obj/structure/extraction_point/initialize()
+ . = ..()
+ name += " ([rand(100,999)]) ([get_area_name(src, TRUE)])"
+ global.total_extraction_beacons += src
+
+/obj/structure/extraction_point/Destroy()
+ global.total_extraction_beacons -= src
+ ..()
+
+/obj/effect/extraction_holder
+ name = "extraction holder"
+ desc = "you shouldnt see this"
+ var/atom/movable/stored_obj
+
+/obj/item/extraction_pack/proc/check_for_living_mobs(atom/A)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.stat != DEAD)
+ return 1
+ for(var/thing in A.GetAllContents())
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.stat != DEAD)
+ return 1
+ return 0
+
+/obj/effect/extraction_holder/singularity_pull()
+ return
+
+/obj/effect/extraction_holder/singularity_pull()
+ return
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index 7170b12d32b..a056a62bed7 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -168,6 +168,12 @@ var/list/mining_overlay_cache = list()
if(istype(get_step(src, direction), /turf/space) && !istype(get_step(src, direction), /turf/space/cracked_asteroid))
add_overlay(get_cached_border("asteroid_edge",direction,icon,"asteroid_edges", 0))
+ //Or any time
+ else
+ var/turf/T = get_step(src, direction)
+ if(istype(T) && T.density)
+ add_overlay(get_cached_border("rock_side",direction,'icons/turf/walls.dmi',"rock_side"))
+
if(overlay_detail)
add_overlay('icons/turf/flooring/decals.dmi',overlay_detail)
diff --git a/code/modules/mob/_modifiers/aura.dm b/code/modules/mob/_modifiers/aura.dm
new file mode 100644
index 00000000000..f72ca67d1ad
--- /dev/null
+++ b/code/modules/mob/_modifiers/aura.dm
@@ -0,0 +1,18 @@
+/*
+'Aura' modifiers are semi-permanent, in that they do not have a set duration, but will expire if out of range of the 'source' of the aura.
+Note: The source is defined as an argument in New(), and if not specified, it is assumed the holder is the source,
+making it not expire ever, which is likely not what you want.
+*/
+
+/datum/modifier/aura
+ var/aura_max_distance = 5 // If more than this many tiles away from the source, the modifier expires next tick.
+
+/datum/modifier/aura/check_if_valid()
+ if(!origin)
+ expire()
+ var/atom/A = origin.resolve()
+ if(istype(A)) // Make sure we're not null.
+ if(get_dist(holder, A) > aura_max_distance)
+ expire()
+ else
+ expire() // Source got deleted or something.
\ No newline at end of file
diff --git a/code/modules/mob/_modifiers/traits.dm b/code/modules/mob/_modifiers/traits.dm
index e510798001b..d0b0abfd895 100644
--- a/code/modules/mob/_modifiers/traits.dm
+++ b/code/modules/mob/_modifiers/traits.dm
@@ -84,20 +84,38 @@
icon_scale_percent = 0.9
+/datum/modifier/trait/colorblind_protanopia
+ name = "Protanopia"
+ desc = "You have a form of red-green colorblindness. You cannot see reds, and have trouble distinguishing them from yellows and greens."
+
+ client_color = MATRIX_Protanopia
+
+/datum/modifier/trait/colorblind_deuteranopia
+ name = "Deuteranopia"
+ desc = "You have a form of red-green colorblindness. You cannot see greens, and have trouble distinguishing them from yellows and reds."
+
+ client_color = MATRIX_Deuteranopia
+
+/datum/modifier/trait/colorblind_tritanopia
+ name = "Tritanopia"
+ desc = "You have a form of blue-yellow colorblindness. You have trouble distinguishing between blues, greens, and yellows, and see blues and violets as dim."
+
+ client_color = MATRIX_Tritanopia
+
/datum/modifier/trait/colorblind_taj
- name = "Colorblind - B+R"
+ name = "Colorblind - Blue-red"
desc = "You are colorblind. You have a minor issue with blue colors and have difficulty recognizing them from red colors."
-
+
client_color = MATRIX_Taj_Colorblind
/datum/modifier/trait/colorblind_vulp
- name = "Colorblind - G+R"
+ name = "Colorblind - Red-green"
desc = "You are colorblind. You have a severe issue with green colors and have difficulty recognizing them from red colors."
-
+
client_color = MATRIX_Vulp_Colorblind
-/datum/modifier/trait/colorblind_mono
- name = "Colorblind - Mono"
- desc = "You are colorblind. Your condition is rare, but you can see no colors at all."
-
+/datum/modifier/trait/colorblind_monochrome
+ name = "Monochromacy"
+ desc = "You are fully colorblind. Your condition is rare, but you can see no colors at all."
+
client_color = MATRIX_Monochromia
diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm
index 3a19eee319f..74baf0d9cec 100644
--- a/code/modules/mob/holder.dm
+++ b/code/modules/mob/holder.dm
@@ -95,6 +95,9 @@ var/list/holder_mob_icon_cache = list()
/obj/item/weapon/holder/drone
origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 5)
+/obj/item/weapon/holder/pai
+ origin_tech = list(TECH_DATA = 2)
+
/obj/item/weapon/holder/mouse
w_class = ITEMSIZE_TINY
diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm
index ad55f2b3464..7cb7cd08e54 100644
--- a/code/modules/mob/language/generic.dm
+++ b/code/modules/mob/language/generic.dm
@@ -133,6 +133,6 @@
key = "s"
flags = SIGNLANG|NO_STUTTER|NONVERBAL
-/datum/language/sign/can_speak_special(var/mob/speaker)
+/datum/language/sign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format
var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands
return (hands || !iscarbon(speaker))
diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm
index c6089a8788e..66e0e5e0f01 100644
--- a/code/modules/mob/language/language.dm
+++ b/code/modules/mob/language/language.dm
@@ -133,7 +133,15 @@
return speech_verb
/datum/language/proc/can_speak_special(var/mob/speaker)
- return 1
+ . = TRUE
+ if(ishuman(speaker))
+ var/mob/living/carbon/human/H = speaker
+ if(src.name in H.species.assisted_langs)
+ . = FALSE
+ var/obj/item/organ/internal/voicebox/vox = locate() in H.internal_organs // Only voiceboxes for now. Maybe someday it'll include other organs, but I'm not that clever
+ if(vox)
+ if(!vox.is_broken() && (src in vox.assists_languages))
+ . = TRUE
// Language handling.
/mob/proc/add_language(var/language)
diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm
index 6de7a9d3091..47cb3b8de09 100644
--- a/code/modules/mob/language/station.dm
+++ b/code/modules/mob/language/station.dm
@@ -63,6 +63,14 @@
"ka","aasi","far","wa","baq","ara","qara","zir","saam","mak","hrar","nja","rir","khan","jun","dar","rik","kah",
"hal","ket","jurl","mah","tul","cresh","azu","ragh","mro","mra","mrro","mrra")
+/datum/language/tajaran/get_random_name(var/gender)
+ var/new_name = ..(gender,1)
+ if(prob(50))
+ new_name += " [pick(list("Hadii","Kaytam","Nazkiin","Zhan-Khazan","Hharar","Njarir'Akhan","Faaira'Nrezi","Rhezar","Mi'dynh","Rrhazkal","Bayan","Al'Manq","Mi'jri","Chur'eech","Sanu'dra","Ii'rka"))]"
+ else
+ new_name += " [..(gender,1)]"
+ return new_name
+
/datum/language/tajaranakhani
name = LANGUAGE_AKHANI
desc = "The language of the sea-faring Njarir'Akhan Tajaran. Borrowing some elements from Siik, the language is distinctly more structured."
@@ -77,14 +85,27 @@
"kar","yar","kzar","rha","hrar","err","fer","rir","rar","yarr","arr","ii'r","jar","kur","ran","rii","ii",
"nai","ou","kah","oa","ama","uuk","bel","chi","ayt","kay","kas","akor","tam","yir","enai")
-/datum/language/tajaran/get_random_name(var/gender)
+/datum/language/tajsign
+ name = LANGUAGE_ALAI
+ desc = "A standardized Tajaran sign language that was developed in Zarraya and gradually adopted by other nations, incorporating \
+ hand gestures and movements of the ears and tail."
+ signlang_verb = list("gestures with their hands", "gestures with their ears and tail", "gestures with their ears, tail and hands")
+ colour = "tajaran"
+ key = "l"
+ flags = WHITELISTED | SIGNLANG | NO_STUTTER | NONVERBAL
- var/new_name = ..(gender,1)
- if(prob(50))
- new_name += " [pick(list("Hadii","Kaytam","Nazkiin","Zhan-Khazan","Hharar","Njarir'Akhan","Faaira'Nrezi","Rhezar","Mi'dynh","Rrhazkal","Bayan","Al'Manq","Mi'jri","Chur'eech","Sanu'dra","Ii'rka"))]"
- else
- new_name += " [..(gender,1)]"
- return new_name
+/datum/language/tajsign/can_speak_special(var/mob/speaker) // TODO: If ever we make external organs assist languages, convert this over to the new format
+ var/list/allowed_species = list(SPECIES_TAJ, SPECIES_TESHARI) // Need a tail and ears and such to use this.
+ if(iscarbon(speaker))
+ var/obj/item/organ/external/hand/hands = locate() in speaker //you can't sign without hands
+ if(!hands)
+ return FALSE
+ if(ishuman(speaker))
+ var/mob/living/carbon/human/H = speaker
+ if(H.species.get_bodytype(H) in allowed_species)
+ return TRUE
+
+ return FALSE
/datum/language/skrell
name = LANGUAGE_SKRELLIAN
@@ -112,7 +133,11 @@
flags = WHITELISTED
syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix", "...", "oo", "q", "nq", "x", "xq", "ll", "...", "...", "...") //should sound like there's holes in it
-
+/datum/language/skrell/get_random_name(var/gender)
+ var/list/first_names = file2list('config/names/first_name_skrell.txt')
+ var/list/last_names = file2list('config/names/last_name_skrell.txt')
+ return "[pick(first_names)] [pick(last_names)]"
+
/datum/language/human
name = LANGUAGE_SOL_COMMON
desc = "A bastardized hybrid of many languages, including Chinese, English, French, and more; it is the common language of the Sol system."
@@ -152,11 +177,6 @@
syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz","shh","shk")
space_chance = 10
-/datum/language/machine/can_speak_special(var/mob/speaker)
- var/obj/item/weapon/implant/language/eal/beep = locate() in speaker
- return ((beep && beep.implanted) || speaker.isSynthetic() || isvoice(speaker))
- //thank you sweet zuhayr
-
/datum/language/machine/get_random_name()
if(prob(70))
return "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]"
@@ -272,4 +292,4 @@
"tod", "ser", "su", "no", "nue", "el",
"ad", "al", "an", "ar", "as", "ci", "co", "de", "do", "el", "en", "er", "es", "ie", "in", "la", "lo", "me", "na",
"no", "nt", "or", "os", "pa", "qu", "ra", "re", "ro", "se", "st", "ta", "te", "to", "ue", "un",
-"tod", "ser", "su", "no", "nue", "el")
\ No newline at end of file
+"tod", "ser", "su", "no", "nue", "el")
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 09b7aadc70d..b81f0098780 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -1,6 +1,6 @@
/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null)
var/param = null
-
+
var/datum/gender/T = gender_datums[get_visible_gender()]
if (findtext(act, "-", 1, null))
@@ -14,9 +14,10 @@
var/muzzled = is_muzzled()
//var/m_type = 1
- for (var/obj/item/weapon/implant/I in src)
- if (I.implanted)
- I.trigger(act, src)
+ for(var/obj/item/organ/O in src.organs)
+ for (var/obj/item/weapon/implant/I in O)
+ if (I.implanted)
+ I.trigger(act, src)
if(src.stat == 2.0 && (act != "deathgasp"))
return
@@ -79,7 +80,7 @@
//Promethean-only emotes
if("squish")
- if(!species.bump_flag == SLIME) //That should do, yaya.
+ if(species.bump_flag != SLIME) //This should definitely do it.
src << "You are not a slime thing!"
return
@@ -738,7 +739,7 @@
set name = "Set Pose"
set desc = "Sets a description which will be shown when someone examines you."
set category = "IC"
-
+
var/datum/gender/T = gender_datums[get_visible_gender()]
pose = sanitize(input(usr, "This is [src]. [T.he]...", "Pose", null) as text)
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 658b4b87ea3..a7490b49690 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -2,7 +2,7 @@
var/skip_gear = 0
var/skip_body = 0
- if(alpha <= 50)
+ if(alpha <= EFFECTIVE_INVIS)
src.loc.examine(user)
return
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index b25973e89a2..277604bdfcf 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -165,25 +165,12 @@
update |= temp.take_damage(b_loss * 0.05, f_loss * 0.05, used_weapon = weapon_message)
if(update) UpdateDamageIcon()
-/mob/living/carbon/human/proc/implant_loadout(var/datum/gear/G = new/datum/gear/utility/implant)
- var/obj/item/weapon/implant/I = new G.path(src)
- I.imp_in = src
- I.implanted = 1
- var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD]
- affected.implants += I
- I.part = affected
- I.implanted(src)
-
/mob/living/carbon/human/proc/implant_loyalty(override = FALSE) // Won't override by default.
if(!config.use_loyalty_implants && !override) return // Nuh-uh.
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)
- L.imp_in = src
- L.implanted = 1
- var/obj/item/organ/external/affected = src.organs_by_name[BP_HEAD]
- affected.implants += L
- L.part = affected
- L.implanted(src)
+ if(L.handle_implant(src, BP_HEAD))
+ L.post_implant(src)
/mob/living/carbon/human/proc/is_loyalty_implanted()
for(var/L in src.contents)
@@ -1120,6 +1107,8 @@
remove_language(species.language)
if(species.default_language)
remove_language(species.default_language)
+ for(var/datum/language/L in species.assisted_langs)
+ remove_language(L)
// Clear out their species abilities.
species.remove_inherent_verbs(src)
holder_type = null
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 0b40e088f32..64cd6a0dc18 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -146,45 +146,35 @@ emp_act
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type)
- if(!type || !def_zone) return 0
+ if(!type || !def_zone)
+ return 0
var/protection = 0
- var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
+ var/list/protective_gear = def_zone.get_covering_clothing()
for(var/obj/item/clothing/gear in protective_gear)
- if(gear.body_parts_covered & def_zone.body_part)
- protection += gear.armor[type]
- if(LAZYLEN(gear.accessories))
- for(var/obj/item/clothing/accessory/bling in gear.accessories)
- if(bling.body_parts_covered & def_zone.body_part)
- protection += bling.armor[type]
+ protection += gear.armor[type]
return protection
/mob/living/carbon/human/proc/getsoak_organ(var/obj/item/organ/external/def_zone, var/type)
- if(!type || !def_zone) return 0
+ if(!type || !def_zone)
+ return 0
var/soaked = 0
- var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
+ var/list/protective_gear = def_zone.get_covering_clothing()
for(var/obj/item/clothing/gear in protective_gear)
- if(gear.body_parts_covered & def_zone.body_part)
- soaked += gear.armorsoak[type]
- if(LAZYLEN(gear.accessories))
- for(var/obj/item/clothing/accessory/bling in gear.accessories)
- if(bling.body_parts_covered & def_zone.body_part)
- soaked += bling.armorsoak[type]
+ soaked += gear.armorsoak[type]
return soaked
+// Checked in borer code
/mob/living/carbon/human/proc/check_head_coverage()
-
- var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform)
- for(var/bp in body_parts)
- if(!bp) continue
- if(bp && istype(bp ,/obj/item/clothing))
- var/obj/item/clothing/C = bp
- if(C.body_parts_covered & HEAD)
- return 1
+ var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
+ var/list/body_parts = H.get_covering_clothing()
+ if(LAZYLEN(body_parts))
+ return 1
return 0
//Used to check if they can be fed food/drinks/pills
/mob/living/carbon/human/proc/check_mouth_coverage()
- var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform)
+ var/obj/item/organ/external/H = organs_by_name[BP_HEAD]
+ var/list/protective_gear = H.get_covering_clothing()
for(var/obj/item/gear in protective_gear)
if(istype(gear) && (gear.body_parts_covered & FACE) && !(gear.item_flags & FLEXIBLEMATERIAL))
return gear
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 244c22e80b2..2cbd93260c1 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -30,6 +30,7 @@
var/r_synth //Used with synth_color to color synth parts that normaly can't be colored.
var/g_synth //Same as above
var/b_synth //Same as above
+ var/synth_markings = 0 //Enables/disables markings on synth parts.
var/damage_multiplier = 1 //multiplies melee combat damage
var/icon_update = 1 //whether icon updating shall take place
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 3ce0c85ef1c..9b2b0234e44 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1032,7 +1032,7 @@
adjustHalLoss(-1)
if (drowsyness)
- drowsyness--
+ drowsyness = max(0, drowsyness - 1)
eye_blurry = max(2, eye_blurry)
if (prob(5))
sleeping += 1
diff --git a/code/modules/mob/living/carbon/human/species/outsider/event.dm b/code/modules/mob/living/carbon/human/species/outsider/event.dm
index 3e75acae9c0..477b14c0c46 100644
--- a/code/modules/mob/living/carbon/human/species/outsider/event.dm
+++ b/code/modules/mob/living/carbon/human/species/outsider/event.dm
@@ -70,6 +70,7 @@ Variables you may want to make use of are:
num_alternate_languages = 3
species_language = LANGUAGE_GALCOM
secondary_langs = list()
+ assisted_langs = list()
name_language = null // Use the first-name last-name generator rather than a language scrambler
min_age = 0
diff --git a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm
index 5d81bb4c9c5..d0f40f693d6 100644
--- a/code/modules/mob/living/carbon/human/species/outsider/shadow.dm
+++ b/code/modules/mob/living/carbon/human/species/outsider/shadow.dm
@@ -25,6 +25,8 @@
genders = list(NEUTER)
+ assisted_langs = list()
+
/datum/species/shadow/handle_death(var/mob/living/carbon/human/H)
spawn(1)
new /obj/effect/decal/cleanable/ash(H.loc)
diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm
index 9fab4751cc7..525a6118826 100644
--- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm
+++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm
@@ -7,6 +7,7 @@
language = LANGUAGE_GALCOM
species_language = LANGUAGE_VOX
num_alternate_languages = 1
+ assisted_langs = list(LANGUAGE_ROOTGLOBAL)
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong)
rarity_value = 4
blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \
@@ -71,6 +72,7 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart/vox,
O_LUNGS = /obj/item/organ/internal/lungs/vox,
+ O_VOICE = /obj/item/organ/internal/voicebox,
O_LIVER = /obj/item/organ/internal/liver/vox,
O_KIDNEYS = /obj/item/organ/internal/kidneys/vox,
O_BRAIN = /obj/item/organ/internal/brain/vox,
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 1f2e55b99cc..38d566d430d 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -52,13 +52,17 @@
// Language/culture vars.
var/default_language = LANGUAGE_GALCOM // Default language is used when 'say' is used without modifiers.
var/language = LANGUAGE_GALCOM // Default racial language, if any.
- var/species_language = LANGUAGE_GALCOM // Used on the Character Setup screen
+ var/list/species_language = list(LANGUAGE_GALCOM) // Used on the Character Setup screen
var/list/secondary_langs = list() // The names of secondary languages that are available to this species.
var/list/speech_sounds = list() // A list of sounds to potentially play when speaking.
var/list/speech_chance = list() // The likelihood of a speech sound playing.
var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation
var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator
+ // The languages the species can't speak without an assisted organ.
+ // This list is a guess at things that no one other than the parent species should be able to speak
+ var/list/assisted_langs = list(LANGUAGE_EAL, LANGUAGE_TERMINUS, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX)
+
//Soundy emotey things.
var/scream_verb = "screams"
var/male_scream_sound //= 'sound/goonstation/voice/male_scream.ogg' Removed due to licensing, replace!
@@ -183,6 +187,7 @@
var/list/has_organ = list( // which required-organ checks are conducted.
O_HEART = /obj/item/organ/internal/heart,
O_LUNGS = /obj/item/organ/internal/lungs,
+ O_VOICE = /obj/item/organ/internal/voicebox,
O_LIVER = /obj/item/organ/internal/liver,
O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_BRAIN = /obj/item/organ/internal/brain,
diff --git a/code/modules/mob/living/carbon/human/species/station/golem.dm b/code/modules/mob/living/carbon/human/species/station/golem.dm
index 9ec7a2b0056..3b091668138 100644
--- a/code/modules/mob/living/carbon/human/species/station/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/station/golem.dm
@@ -11,6 +11,8 @@
spawn_flags = SPECIES_IS_RESTRICTED
siemens_coefficient = 0
+ assisted_langs = list()
+
breath_type = null
poison_type = null
diff --git a/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm
index 180732b0aaa..56b5c360354 100644
--- a/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm
+++ b/code/modules/mob/living/carbon/human/species/station/human_subspecies.dm
@@ -45,6 +45,7 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_LUNGS = /obj/item/organ/internal/lungs,
+ O_VOICE = /obj/item/organ/internal/voicebox,
O_LIVER = /obj/item/organ/internal/liver,
O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_BRAIN = /obj/item/organ/internal/brain,
diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm
index 213c7c3ae3d..0c2fbc0ac3b 100644
--- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm
+++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm
@@ -30,6 +30,7 @@ var/datum/species/shapeshifter/promethean/prometheans
health_hud_intensity = 2
num_alternate_languages = 3
species_language = LANGUAGE_SOL_COMMON
+ assisted_langs = list(LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) // Prometheans are weird, let's just assume they can use basically any language.
breath_type = null
poison_type = null
diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm
index 1d1c0036bea..81deb462a6b 100644
--- a/code/modules/mob/living/carbon/human/species/station/seromi.dm
+++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm
@@ -104,6 +104,7 @@
has_organ = list(
O_HEART = /obj/item/organ/internal/heart,
O_LUNGS = /obj/item/organ/internal/lungs,
+ O_VOICE = /obj/item/organ/internal/voicebox,
O_LIVER = /obj/item/organ/internal/liver,
O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_BRAIN = /obj/item/organ/internal/brain,
diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm
index 2f2c1452c04..5d95a632855 100644
--- a/code/modules/mob/living/carbon/human/species/station/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station/station.dm
@@ -12,6 +12,7 @@
species_language = LANGUAGE_SOL_COMMON
secondary_langs = list(LANGUAGE_SOL_COMMON, LANGUAGE_TERMINUS)
name_language = null // Use the first-name last-name generator rather than a language scrambler
+ assisted_langs = list(LANGUAGE_EAL, LANGUAGE_SKRELLIAN, LANGUAGE_SKRELLIANFAR, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX)
min_age = 17
max_age = 130
@@ -157,7 +158,7 @@
metabolic_rate = 1.1
gluttonous = 1
num_alternate_languages = 3
- secondary_langs = list(LANGUAGE_SIIK, LANGUAGE_AKHANI)
+ secondary_langs = list(LANGUAGE_SIIK, LANGUAGE_AKHANI, LANGUAGE_ALAI)
name_language = LANGUAGE_SIIK
species_language = LANGUAGE_SIIK
health_hud_intensity = 2.5
@@ -215,6 +216,7 @@
has_organ = list( //No appendix.
O_HEART = /obj/item/organ/internal/heart,
O_LUNGS = /obj/item/organ/internal/lungs,
+ O_VOICE = /obj/item/organ/internal/voicebox,
O_LIVER = /obj/item/organ/internal/liver,
O_KIDNEYS = /obj/item/organ/internal/kidneys,
O_BRAIN = /obj/item/organ/internal/brain,
@@ -241,6 +243,7 @@
secondary_langs = list(LANGUAGE_SKRELLIAN, LANGUAGE_SCHECHI)
name_language = LANGUAGE_SKRELLIAN
species_language = LANGUAGE_SKRELLIAN
+ assisted_langs = list(LANGUAGE_EAL, LANGUAGE_TERMINUS, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX)
health_hud_intensity = 2
water_movement = -3
@@ -315,13 +318,14 @@
hud_type = /datum/hud_data/diona
siemens_coefficient = 0.3
show_ssd = "completely quiescent"
- num_alternate_languages = 2
- secondary_langs = list(LANGUAGE_ROOTGLOBAL)
- name_language = LANGUAGE_ROOTLOCAL
- species_language = LANGUAGE_ROOTLOCAL
health_hud_intensity = 2.5
item_slowdown_mod = 0.25
+ num_alternate_languages = 2
+ name_language = LANGUAGE_ROOTLOCAL
+ species_language = LANGUAGE_ROOTLOCAL
+ secondary_langs = list(LANGUAGE_ROOTGLOBAL)
+ assisted_langs = list(LANGUAGE_VOX) // Diona are weird, let's just assume they can use basically any language.
min_age = 1
max_age = 300
diff --git a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm
index 0b9c5490eb9..f3115474dcf 100644
--- a/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm
+++ b/code/modules/mob/living/carbon/human/species/virtual_reality/avatar.dm
@@ -16,6 +16,8 @@
speech_bubble_appearance = "cyber"
+ assisted_langs = list()
+
male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg')
female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg')
male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg'
diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm
index d851c40255f..1d2ce593071 100644
--- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm
+++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm
@@ -5,6 +5,7 @@
default_language = "Xenomorph"
language = "Hivemind"
+ assisted_langs = list()
unarmed_types = list(/datum/unarmed_attack/claws/strong/xeno, /datum/unarmed_attack/bite/strong/xeno)
hud_type = /datum/hud_data/alien
rarity_value = 3
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index dddfd8e168c..612765a776a 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -1217,4 +1217,8 @@ default behaviour is:
/mob/living/proc/has_vision()
- return !(eye_blind || (disabilities & BLIND) || stat || blinded)
\ No newline at end of file
+ return !(eye_blind || (disabilities & BLIND) || stat || blinded)
+
+
+/mob/living/proc/dirties_floor() // If we ever decide to add fancy conditionals for making dirty floors (floating, etc), here's the proc.
+ return makes_dirt
\ No newline at end of file
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 3d9140dd468..08bebc91b2f 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -380,8 +380,13 @@
var/turf/location = get_turf(src)
location.hotspot_expose(fire_burn_temperature(), 50, 1)
-/mob/living/fire_act()
- adjust_fire_stacks(2)
+//altered this to cap at the temperature of the fire causing it, using the same 1:1500 value as /mob/living/carbon/human/handle_fire() in human/life.dm
+/mob/living/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature)
+ if(fire_stacks < exposed_temperature/1500) // Subject to balance
+ adjust_fire_stacks(2)
+ else
+ adjust_fire_stacks(2)
IgniteMob()
//Share fire evenly between the two mobs
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 9739e596b8e..1ee86da6ef8 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -16,7 +16,6 @@
var/brainloss = 0 //'Retardation' damage caused by someone hitting you in the head with a bible or being infected with brainrot.
var/halloss = 0 //Hallucination damage. 'Fake' damage obtained through hallucinating or the holodeck. Sleeping should cause it to wear off.
-
var/hallucination = 0 //Directly affects how long a mob will hallucinate for
var/list/atom/hallucinations = list() //A list of hallucinated people that try to attack the mob. See /obj/effect/fake_attacker in hallucinations.dm
@@ -59,3 +58,5 @@
var/list/hud_list //Holder for health hud, status hud, wanted hud, etc (not like inventory slots)
var/has_huds = FALSE //Whether or not we should bother initializing the above list
+
+ var/makes_dirt = TRUE //FALSE if the mob shouldn't be making dirt on the ground when it walks
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index e71416709fa..c35fdcbf2ac 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -64,6 +64,7 @@ var/list/ai_verbs_default = list(
var/datum/announcement/priority/announcement
var/obj/machinery/ai_powersupply/psupply = null // Backwards reference to AI's powersupply object.
var/hologram_follow = 1 //This is used for the AI eye, to determine if a holopad's hologram should follow it or not.
+ var/is_dummy = 0 //Used to prevent dummy AIs from spawning with communicators.
//NEWMALF VARIABLES
var/malfunctioning = 0 // Master var that determines if AI is malfunctioning.
var/datum/malf_hardware/hardware = null // Installed piece of hardware.
@@ -111,15 +112,16 @@ var/list/ai_verbs_default = list(
possibleNames -= pickedName
pickedName = null
- aiPDA = new/obj/item/device/pda/ai(src)
+ if(!is_dummy)
+ aiPDA = new/obj/item/device/pda/ai(src)
SetName(pickedName)
anchored = 1
canmove = 0
density = 1
loc = loc
- aiCommunicator = new /obj/item/device/communicator/integrated(src)
-
+ if(!is_dummy)
+ aiCommunicator = new /obj/item/device/communicator/integrated(src)
holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo1"))
@@ -685,6 +687,9 @@ var/list/ai_verbs_default = list(
card.grab_ai(src, user)
else if(W.is_wrench())
+ if(user == controlling_drone)
+ to_chat(user, "The drone's subsystems resist your efforts to tamper with your bolts.")
+ return
if(anchored)
playsound(src, W.usesound, 50, 1)
user.visible_message("\The [user] starts to unbolt \the [src] from the plating...")
@@ -789,6 +794,9 @@ var/list/ai_verbs_default = list(
return TRUE
//Special subtype kept around for global announcements
+/mob/living/silicon/ai/announcer/
+ is_dummy = 1
+
/mob/living/silicon/ai/announcer/initialize()
. = ..()
mob_list -= src
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index 534117cee07..3bcbd7057b0 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -3,6 +3,10 @@
if(stat == DEAD)
return
+ if(controlling_drone)
+ controlling_drone.release_ai_control("WARNING: Primary control loop failure. Session terminated.")
+ . = ..(gibbed)
+
if(src.eyeobj)
src.eyeobj.setLoc(get_turf(src))
diff --git a/code/modules/mob/living/silicon/ai/icons.dm b/code/modules/mob/living/silicon/ai/icons.dm
index 2d8bc0d0026..c9891f9ae8a 100644
--- a/code/modules/mob/living/silicon/ai/icons.dm
+++ b/code/modules/mob/living/silicon/ai/icons.dm
@@ -84,6 +84,7 @@ var/list/datum/ai_icon/ai_icons
/datum/ai_icon/glitchman
name = "Glitchman"
alive_icon = "ai-glitchman"
+ dead_icon = "ai-glitchman-crash"
/datum/ai_icon/goon
name = "Goon"
@@ -110,6 +111,7 @@ var/list/datum/ai_icon/ai_icons
name = "Inverted"
alive_icon = "ai-u"
alive_light = "#81DDFF"
+ dead_icon = "ai-u-crash"
/datum/ai_icon/lonestar
name = "Lonestar"
@@ -163,14 +165,87 @@ var/list/datum/ai_icon/ai_icons
/datum/ai_icon/trapped
name = "Trapped"
alive_icon = "ai-hades"
- dead_icon = "ai-hades_dead"
+ dead_icon = "ai-hades-crash"
-/datum/ai_icon/triumvirate_static
+/datum/ai_icon/triumvirate
name = "Triumvirate"
alive_icon = "ai-triumvirate"
alive_light = "#020B2B"
/datum/ai_icon/triumvirate_static
name = "Triumvirate Static"
- alive_icon = "ai-static"
+ alive_icon = "ai-triumvirate-malf"
alive_light = "#020B2B"
+
+//Eros Research Platform Ports
+
+/datum/ai_icon/clown2
+ name = "Honk"
+ alive_icon = "ai-clown2"
+ dead_icon = "ai-clown2-crash"
+
+/datum/ai_icon/boxfort
+ name = "Boxfort"
+ alive_icon = "ai-boxfort"
+ dead_icon = "ai-boxfort_dead"
+
+/datum/ai_icon/ravensdale
+ name = "Integration"
+ alive_icon = "ai-ravensdale"
+ dead_icon = "ai-ravensdale-crash"
+
+/datum/ai_icon/gentoo
+ name = "Gentoo"
+ alive_icon = "ai-gentoo"
+ dead_icon = "ai-gentoo_dead"
+
+/datum/ai_icon/serithi
+ name = "Mechanicus"
+ alive_icon = "ai-serithi"
+ dead_icon = "ai-serithi-crash"
+
+/datum/ai_icon/alien
+ name = "Xenomorph"
+ alive_icon = "ai-alien"
+ dead_icon = "ai-alien-crash"
+
+/datum/ai_icon/syndicat
+ name = "Syndi-cat"
+ alive_icon = "ai-syndicatmeow"
+
+/datum/ai_icon/wasp
+ name = "Wasp"
+ alive_icon = "ai-wasp"
+
+/datum/ai_icon/house
+ name = "Doctor"
+ alive_icon = "ai-house"
+
+/datum/ai_icon/fabulous
+ name = "Fabulous"
+ alive_icon = "ai-fabulous"
+
+/datum/ai_icon/yesman
+ name = "Yes Man"
+ alive_icon = "ai-yes-man"
+ dead_icon = "ai-alien-crash"
+
+/datum/ai_icon/royal
+ name = "Royal"
+ alive_icon = "ai-royal"
+
+/datum/ai_icon/pirate
+ name = "Pirate"
+ alive_icon = "ai-pirate"
+
+/datum/ai_icon/gygas
+ name = "Love"
+ alive_icon = "ai-gygas"
+
+/datum/ai_icon/xerxes
+ name = "Xerxes"
+ alive_icon = "ai-xerxes"
+
+/datum/ai_icon/godfrey
+ name = "Godfrey"
+ alive_icon = "ai-godfrey"
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 413cf492509..c8e7dfdadab 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -8,6 +8,8 @@
if (src.stat!=CONSCIOUS)
src.cameraFollow = null
src.reset_view(null)
+ if(controlling_drone)
+ controlling_drone.release_ai_control("WARNING: Primary control loop failure. Session terminated.")
src.updatehealth()
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 5ed6fde8aeb..168b031f5ce 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -1,12 +1,14 @@
/mob/living/silicon/pai
name = "pAI"
icon = 'icons/mob/pai.dmi'
- icon_state = "repairbot"
+ icon_state = "pai-repairbot"
emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
pass_flags = 1
mob_size = MOB_SMALL
+ holder_type = /obj/item/weapon/holder/pai
+
can_pull_size = ITEMSIZE_SMALL
can_pull_mobs = MOB_PULL_SMALLER
@@ -23,16 +25,16 @@
var/obj/item/device/radio/radio // Our primary radio
var/obj/item/device/communicator/integrated/communicator // Our integrated communicator.
- var/chassis = "repairbot" // A record of your chosen chassis.
+ var/chassis = "pai-repairbot" // A record of your chosen chassis.
var/global/list/possible_chassis = list(
- "Drone" = "repairbot",
- "Cat" = "cat",
- "Mouse" = "mouse",
- "Monkey" = "monkey",
- "Corgi" = "borgi",
- "Fox" = "fox",
- "Parrot" = "parrot",
- "Rabbit" = "rabbit"
+ "Drone" = "pai-repairbot",
+ "Cat" = "pai-cat",
+ "Mouse" = "pai-mouse",
+ "Monkey" = "pai-monkey",
+ "Corgi" = "pai-borgi",
+ "Fox" = "pai-fox",
+ "Parrot" = "pai-parrot",
+ "Rabbit" = "pai-rabbit"
)
var/global/list/possible_say_verbs = list(
@@ -416,7 +418,8 @@
var/obj/item/weapon/holder/H = ..(grabber, self_drop)
if(!istype(H))
return
- H.icon_state = "pai-[icon_state]"
+
+ H.icon_state = "[chassis]"
grabber.update_inv_l_hand()
grabber.update_inv_r_hand()
return H
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 472125cef9a..ab2b0b53cd7 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -126,6 +126,6 @@ var/global/list/default_pai_software = list()
else if(href_list["image"])
var/img = text2num(href_list["image"])
- if(1 <= img && img <= 9)
+ if(1 <= img && img <= (pai_emotions.len))
card.setEmotion(img)
return 1
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index 05438d9cf3c..dfecf96e6c5 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -19,7 +19,7 @@ var/list/mob_hat_cache = list()
return mob_hat_cache[key]
/mob/living/silicon/robot/drone
- name = "drone"
+ name = "maintenance drone"
real_name = "drone"
icon = 'icons/mob/robots.dmi'
icon_state = "repairbot"
@@ -57,6 +57,8 @@ var/list/mob_hat_cache = list()
var/obj/item/hat
var/hat_x_offset = 0
var/hat_y_offset = -13
+ var/serial_number = 0
+ var/name_override = 0
holder_type = /obj/item/weapon/holder/drone
@@ -71,6 +73,7 @@ var/list/mob_hat_cache = list()
return FALSE
/mob/living/silicon/robot/drone/construction
+ name = "construction drone"
icon_state = "constructiondrone"
law_type = /datum/ai_laws/construction_drone
module_type = /obj/item/weapon/robot_module/drone/construction
@@ -96,6 +99,7 @@ var/list/mob_hat_cache = list()
remove_language("Robot Talk")
add_language("Robot Talk", 0)
add_language("Drone Talk", 1)
+ serial_number = rand(0,999)
//They are unable to be upgraded, so let's give them a bit of a better battery.
cell.maxcharge = 10000
@@ -111,6 +115,7 @@ var/list/mob_hat_cache = list()
verbs -= /mob/living/silicon/robot/verb/Namepick
updateicon()
+ updatename()
/mob/living/silicon/robot/drone/init()
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
@@ -128,14 +133,22 @@ var/list/mob_hat_cache = list()
name = real_name
/mob/living/silicon/robot/drone/updatename()
- real_name = "maintenance drone ([rand(100,999)])"
+ if(name_override)
+ return
+ if(controlling_ai)
+ real_name = "remote drone ([controlling_ai])"
+ else
+ real_name = "[initial(name)] ([serial_number])"
name = real_name
/mob/living/silicon/robot/drone/updateicon()
overlays.Cut()
if(stat == 0)
- overlays += "eyes-[icon_state]"
+ if(controlling_ai)
+ overlays += "eyes-[icon_state]-ai"
+ else
+ overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
if(hat) // Let the drones wear hats.
@@ -214,15 +227,18 @@ var/list/mob_hat_cache = list()
return
if(emagged)
- to_chat(user, "\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.")
+ to_chat(src, "\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.")
to_chat(user, "You attempt to subvert [src], but the sequencer has no effect.")
return
to_chat(user, "You swipe the sequencer across [src]'s interface and watch its eyes flicker.")
- to_chat(user, "You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.")
- message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.")
- log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.")
+ if(controlling_ai)
+ to_chat(src, "\The [user] loads some kind of subversive software into the remote drone, corrupting its lawset but luckily sparing yours.")
+ else
+ to_chat(src, "You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.")
+
+ log_game("[key_name(user)] emagged drone [key_name(src)][controlling_ai ? " but AI [key_name(controlling_ai)] is in remote control" : " Laws overridden"].")
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])")
@@ -235,9 +251,10 @@ var/list/mob_hat_cache = list()
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
set_zeroth_law("Only [user.real_name] and people [TU.he] designate[TU.s] as being such are operatives.")
- src << "Obey these laws:"
- laws.show_laws(src)
- src << "ALERT: [user.real_name] [TU.is] your new master. Obey your new laws and [TU.his] commands."
+ if(!controlling_ai)
+ to_chat(src, "Obey these laws:")
+ laws.show_laws(src)
+ to_chat(src, "ALERT: [user.real_name] is your new master. Obey your new laws and \his commands.")
return 1
//DRONE LIFE/DEATH
@@ -263,26 +280,41 @@ var/list/mob_hat_cache = list()
return
..()
+/mob/living/silicon/robot/drone/death(gibbed)
+ if(controlling_ai)
+ release_ai_control("WARNING: remote system failure. Connection timed out.")
+ . = ..(gibbed)
+
//DRONE MOVEMENT.
/mob/living/silicon/robot/drone/Process_Spaceslipping(var/prob_slip)
return 0
//CONSOLE PROCS
/mob/living/silicon/robot/drone/proc/law_resync()
+
+ if(controlling_ai)
+ to_chat(src, "Someone issues a remote law reset order for this unit, but you disregard it.")
+ return
+
if(stat != 2)
if(emagged)
- src << "You feel something attempting to modify your programming, but your hacked subroutines are unaffected."
+ to_chat(src, "You feel something attempting to modify your programming, but your hacked subroutines are unaffected.")
else
- src << "A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it."
+ to_chat(src, "A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it.")
full_law_reset()
show_laws()
/mob/living/silicon/robot/drone/proc/shut_down()
+
+ if(controlling_ai && mind.special_role)
+ to_chat(src, "Someone issued a remote kill order for this unit, but you disregard it.")
+ return
+
if(stat != 2)
if(emagged)
- src << "You feel a system kill order percolate through your tiny brain, but it doesn't seem like a good idea to you."
+ to_chat(src, "You feel a system kill order percolate through [controlling_ai ? "the drones" : "your"] tiny brain, but it doesn't seem like a good idea to [controlling_ai ? "it" : "you"].")
else
- src << "You feel a system kill order percolate through your tiny brain, and you obediently destroy yourself."
+ to_chat(src, "You feel a system kill order percolate through [controlling_ai ? "the drones" : "your"] tiny brain, and [controlling_ai ? "it" : "you"] obediently destroy[controlling_ai ? "s itself" : " yourself"].")
death()
/mob/living/silicon/robot/drone/proc/full_law_reset()
@@ -291,6 +323,21 @@ var/list/mob_hat_cache = list()
clear_ion_laws(1)
laws = new law_type
+/mob/living/silicon/robot/drone/show_laws(var/everyone = 0)
+ if(!controlling_ai)
+ return..()
+ to_chat(src, "Obey these laws:")
+ controlling_ai.laws_sanity_check()
+ controlling_ai.laws.show_laws(src)
+
+/mob/living/silicon/robot/drone/robot_checklaws()
+ set category = "Silicon Commands"
+ set name = "State Laws"
+
+ if(!controlling_ai)
+ return ..()
+ controlling_ai.subsystem_law_manager()
+
//Reboot procs.
/mob/living/silicon/robot/drone/proc/request_player()
@@ -348,14 +395,6 @@ var/list/mob_hat_cache = list()
..()
flavor_text = "It's a bulky construction drone stamped with a Sol Central glyph."
-/mob/living/silicon/robot/drone/construction/updatename()
- real_name = "construction drone ([rand(100,999)])"
- name = real_name
-
/mob/living/silicon/robot/drone/mining/init()
..()
flavor_text = "It's a bulky mining drone stamped with a Grayson logo."
-
-/mob/living/silicon/robot/drone/mining/updatename()
- real_name = "mining drone ([rand(100,999)])"
- name = real_name
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
index e9589622a53..fdb9c09eb51 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
@@ -75,20 +75,22 @@
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
return
- if(!player || !istype(player.mob,/mob/observer/dead))
+ if(player && !istype(player.mob,/mob/observer/dead))
return
- announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
flick("h_lathe_leave",src)
+ drone_progress = 0
time_last_drone = world.time
- if(player.mob && player.mob.mind) player.mob.mind.reset()
- var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
- new_drone.transfer_personality(player)
- new_drone.master_fabricator = src
- drone_progress = 0
+ var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
+ if(player)
+ announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
+ if(player.mob && player.mob.mind) player.mob.mind.reset()
+ new_drone.transfer_personality(player)
+
+ return new_drone
/mob/observer/dead/verb/join_as_drone()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_remote_control.dm b/code/modules/mob/living/silicon/robot/drone/drone_remote_control.dm
new file mode 100644
index 00000000000..4980c24ca3e
--- /dev/null
+++ b/code/modules/mob/living/silicon/robot/drone/drone_remote_control.dm
@@ -0,0 +1,103 @@
+/mob/living/silicon/ai
+ var/mob/living/silicon/robot/drone/controlling_drone
+
+/mob/living/silicon/robot/drone
+ var/mob/living/silicon/ai/controlling_ai
+
+/mob/living/silicon/robot/drone/attack_ai(var/mob/living/silicon/ai/user)
+
+ if(!istype(user) || controlling_ai || !config.allow_drone_spawn || !config.allow_ai_drones)
+ return
+
+ if(client || key)
+ to_chat(user, "You cannot take control of an autonomous, active drone.")
+ return
+
+ if(health < -35 || emagged)
+ to_chat(user, "WARNING: connection timed out.")
+ return
+
+ user.controlling_drone = src
+ user.teleop = src
+ radio.channels = user.aiRadio.keyslot2.channels
+ controlling_ai = user
+ verbs += /mob/living/silicon/robot/drone/proc/release_ai_control_verb
+ local_transmit = FALSE
+ languages = controlling_ai.languages.Copy()
+ speech_synthesizer_langs = controlling_ai.speech_synthesizer_langs.Copy()
+ stat = CONSCIOUS
+ if(user.mind)
+ user.mind.transfer_to(src)
+ else
+ key = user.key
+ updatename()
+ to_chat(src, "You have shunted your primary control loop into \a [initial(name)]. Use the Release Control verb to return to your core.")
+
+/obj/machinery/drone_fabricator/attack_ai(var/mob/living/silicon/ai/user as mob)
+
+ if(!istype(user) || user.controlling_drone || !config.allow_drone_spawn || !config.allow_ai_drones)
+ return
+
+ if(stat & NOPOWER)
+ to_chat(user, "\The [src] is unpowered.")
+ return
+
+ if(!produce_drones)
+ to_chat(user, "\The [src] is disabled.")
+ return
+
+ if(drone_progress < 100)
+ to_chat(user, "\The [src] is not ready to produce a new drone.")
+ return
+
+ if(count_drones() >= config.max_maint_drones)
+ to_chat(user, "The drone control subsystems are tasked to capacity; they cannot support any more drones.")
+ return
+
+ var/mob/living/silicon/robot/drone/new_drone = create_drone()
+ user.controlling_drone = new_drone
+ user.teleop = new_drone
+ new_drone.radio.channels = user.aiRadio.keyslot2.channels
+ new_drone.controlling_ai = user
+ new_drone.verbs += /mob/living/silicon/robot/drone/proc/release_ai_control_verb
+ new_drone.local_transmit = FALSE
+ new_drone.languages = new_drone.controlling_ai.languages.Copy()
+ new_drone.speech_synthesizer_langs = new_drone.controlling_ai.speech_synthesizer_langs.Copy()
+
+ if(user.mind)
+ user.mind.transfer_to(new_drone)
+ else
+ new_drone.key = user.key
+ new_drone.updatename()
+
+ to_chat(new_drone, "You have shunted your primary control loop into \a [initial(new_drone.name)]. Use the Release Control verb to return to your core.")
+
+/mob/living/silicon/robot/drone/proc/release_ai_control_verb()
+ set name = "Release Control"
+ set desc = "Release control of a remote drone."
+ set category = "Silicon Commands"
+
+ release_ai_control("Remote session terminated.")
+
+/mob/living/silicon/robot/drone/proc/release_ai_control(var/message = "Connection terminated.")
+
+ if(controlling_ai)
+ if(mind)
+ mind.transfer_to(controlling_ai)
+ else
+ controlling_ai.key = key
+ to_chat(controlling_ai, "[message]")
+ controlling_ai.controlling_drone = null
+ controlling_ai.teleop = null
+ controlling_ai = null
+
+ radio.channels = module.channels
+ verbs -= /mob/living/silicon/robot/drone/proc/release_ai_control_verb
+ module.remove_languages(src) //Removes excess, adds 'default'.
+ remove_language("Robot Talk")
+ add_language("Robot Talk", 0)
+ add_language("Drone Talk", 1)
+ local_transmit = TRUE
+ full_law_reset()
+ updatename()
+ death()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm
index f6b69504914..6cd2fa5f816 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm
@@ -213,6 +213,7 @@ var/global/list/robot_modules = list(
..()
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo/surgeon(src)
+ src.modules += new /obj/item/weapon/autopsy_scanner(src)
src.modules += new /obj/item/weapon/surgical/scalpel/cyborg(src)
src.modules += new /obj/item/weapon/surgical/hemostat/cyborg(src)
src.modules += new /obj/item/weapon/surgical/retractor/cyborg(src)
diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm
index 01f52209a7a..3c8e981c3b7 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm
@@ -148,6 +148,7 @@
src.modules += new /obj/item/weapon/reagent_containers/borghypo/merc(src)
// Surgery things.
+ src.modules += new /obj/item/weapon/autopsy_scanner(src)
src.modules += new /obj/item/weapon/surgical/scalpel/cyborg(src)
src.modules += new /obj/item/weapon/surgical/hemostat/cyborg(src)
src.modules += new /obj/item/weapon/surgical/retractor/cyborg(src)
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index e3c4a0b6613..15fc174b383 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -888,6 +888,8 @@
continue
else if(L in friends)
continue
+ else if(L.alpha <= EFFECTIVE_INVIS)
+ continue
else if(!SA_attackable(L))
continue
else if(!special_target_check(L))
@@ -1215,7 +1217,7 @@
ai_log("AttackTarget() Bailing because we're disabled",2)
LoseTarget()
return 0
- if(!target_mob || !SA_attackable(target_mob))
+ if(!target_mob || !SA_attackable(target_mob) || (target_mob.alpha <= EFFECTIVE_INVIS)) //if the target went invisible, you can't follow it
LoseTarget()
return 0
if(!(target_mob in ListTargets(view_range)))
diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm
index 5141eed9792..892c185a943 100644
--- a/code/modules/mob/new_player/sprite_accessories.dm
+++ b/code/modules/mob/new_player/sprite_accessories.dm
@@ -1257,6 +1257,24 @@
name = "Tattoo (Campbell, L.Arm)"
body_parts = list(BP_L_ARM)
+ rightleg
+ name = "Tattoo (Campbell, R.Leg)"
+ body_parts = list(BP_R_LEG)
+
+ leftleg
+ name = "Tattoo (Campbell, L.Leg)"
+ body_parts = list (BP_L_LEG)
+
+ tat_silverburgh
+ name = "Tattoo (Silverburgh, R.Leg)"
+ icon_state = "tat_silverburgh"
+ body_parts = list (BP_R_LEG)
+
+ left
+ name = "Tattoo (Silverburgh, L.Leg)"
+ icon_state = "tat_silverburgh"
+ body_parts = list (BP_L_LEG)
+
tat_tiger
name = "Tattoo (Tiger Stripes, Body)"
icon_state = "tat_tiger"
diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm
index 8b97ffdb353..f819e2ca7b1 100644
--- a/code/modules/multiz/structures.dm
+++ b/code/modules/multiz/structures.dm
@@ -141,20 +141,23 @@
if(!istype(above))
above.ChangeTurf(/turf/simulated/open)
-/obj/structure/stairs/Uncross(atom/movable/A)
- if(A.dir == dir)
- // This is hackish but whatever.
- var/turf/target = get_step(GetAbove(A), dir)
- var/turf/source = A.loc
- if(target.Enter(A, source))
- A.loc = target
- target.Entered(A, source)
- if(isliving(A))
- var/mob/living/L = A
- if(L.pulling)
- L.pulling.forceMove(target)
- return 0
- return 1
+/obj/structure/stairs/CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
+ if(get_dir(loc, target) == dir && upperStep(mover.loc))
+ return FALSE
+ . = ..()
+
+/obj/structure/stairs/Bumped(atom/movable/A)
+ // This is hackish but whatever.
+ var/turf/target = get_step(GetAbove(A), dir)
+ if(target.Enter(A, src)) // Pass src to be ignored to avoid infinate loop
+ A.forceMove(target)
+ if(isliving(A))
+ var/mob/living/L = A
+ if(L.pulling)
+ L.pulling.forceMove(target)
+
+/obj/structure/stairs/proc/upperStep(var/turf/T)
+ return (T == loc)
/obj/structure/stairs/CanPass(obj/mover, turf/source, height, airflow)
return airflow || !density
diff --git a/code/modules/organs/internal/voicebox.dm b/code/modules/organs/internal/voicebox.dm
new file mode 100644
index 00000000000..4de69fe8f2b
--- /dev/null
+++ b/code/modules/organs/internal/voicebox.dm
@@ -0,0 +1,42 @@
+/*
+ * Voicebox/Vocal Synthesizers
+ * TL;DR: Assists with speaking languages that a species doesn't normally have,
+ * such as EAL. Not standard or organic, because at the moment it's undesireable to completely mute characters.
+ */
+
+/obj/item/organ/internal/voicebox
+ name = "larynx"
+ icon_state = "larynx"
+ parent_organ = BP_TORSO // We don't have a neck area
+ organ_tag = O_VOICE
+ will_assist_languages = list(LANGUAGE_GALCOM)
+
+/obj/item/organ/internal/voicebox/New()
+ ..()
+ amend_assist_langs()
+
+/obj/item/organ/internal/voicebox/proc/amend_assist_langs() // Adds the list of language datums assisted by the voicebox to the list used in speaking
+ for(var/L in will_assist_languages)
+ assists_languages |= all_languages[L]
+
+/obj/item/organ/internal/voicebox/proc/add_assistable_langs(var/language) // Adds a new language (by string/define) to the list of things the voicebox can assist
+ will_assist_languages |= language
+ amend_assist_langs() // Can't think of a better place to put this, makes the voicebox actually start to assist with the added language
+
+/////////////////////////////////
+// Voicebox Subtypes
+/////////////////////////////////
+
+/obj/item/organ/internal/voicebox/assist // In the off chance we get a species that doesn't speak GalCom by default
+
+/obj/item/organ/internal/voicebox/assist/New()
+ ..()
+ mechassist()
+
+/obj/item/organ/internal/voicebox/robot
+ name = "vocal synthesizer"
+ will_assist_languages = list(LANGUAGE_GALCOM, LANGUAGE_EAL) // Synthetics spawn with this by default
+
+/obj/item/organ/internal/voicebox/robot/New()
+ ..()
+ robotize()
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 5fc5c64ea1d..ea31950e3d0 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -31,6 +31,10 @@ var/list/organ_cache = list()
var/rejecting // Is this organ already being rejected?
var/preserved = 0 // If this is 1, prevents organ decay.
+ // Language vars. Putting them here in case we decide to do something crazy with sign-or-other-nonverbal languages.
+ var/list/will_assist_languages = list()
+ var/list/datum/language/assists_languages = list()
+
/obj/item/organ/Destroy()
if(owner) owner = null
diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm
index 3655e8b2cb2..16250e2c22d 100644
--- a/code/modules/organs/organ_external.dm
+++ b/code/modules/organs/organ_external.dm
@@ -72,6 +72,8 @@
var/open = 0
var/stage = 0
var/cavity = 0
+ var/burn_stage = 0 //Surgical repair stage for burn.
+ var/brute_stage = 0 //Surgical repair stage for brute.
// HUD element variable, see organ_icon.dm get_damage_hud_image()
var/image/hud_damage_image
@@ -1328,3 +1330,18 @@ Note that amputating the affected organ does in fact remove the infection from t
if(6 to INFINITY)
flavor_text += "a ton of [wound]\s"
return english_list(flavor_text)
+
+// Returns a list of the clothing (not glasses) that are covering this part
+/obj/item/organ/external/proc/get_covering_clothing()
+ var/list/covering_clothing = list()
+ if(owner)
+ var/list/protective_gear = list(owner.head, owner.wear_mask, owner.wear_suit, owner.w_uniform, owner.gloves, owner.shoes)
+ for(var/obj/item/clothing/gear in protective_gear)
+ if(gear.body_parts_covered & src.body_part)
+ covering_clothing |= gear
+ if(LAZYLEN(gear.accessories))
+ for(var/obj/item/clothing/accessory/bling in gear.accessories)
+ if(bling.body_parts_covered & src.body_part)
+ covering_clothing |= bling
+
+ return covering_clothing
\ No newline at end of file
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index b76b52e1c03..91b96fea31f 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -4,13 +4,13 @@ var/global/list/limb_icon_cache = list()
return
/obj/item/organ/external/proc/compile_icon()
- overlays.Cut()
+ cut_overlays()
// This is a kludge, only one icon has more than one generation of children though.
for(var/obj/item/organ/external/organ in contents)
if(organ.children && organ.children.len)
for(var/obj/item/organ/external/child in organ.children)
overlays += child.mob_icon
- overlays += organ.mob_icon
+ add_overlay(organ.mob_icon)
/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human)
s_tone = null
@@ -94,7 +94,7 @@ var/global/list/limb_icon_cache = list()
mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
icon_cache_key += "[M][markings[M]["color"]]"
- overlays |= get_hair_icon()
+ add_overlay(get_hair_icon())
return mob_icon
@@ -107,7 +107,7 @@ var/global/list/limb_icon_cache = list()
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
if(facial_hair_style.do_colouration)
facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD)
- res.overlays |= facial_s
+ res.add_overlay(facial_s)
//Head hair
if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR)))
@@ -122,7 +122,7 @@ var/global/list/limb_icon_cache = list()
if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3)
hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY)
hair_s.Blend(hair_s_add, ICON_ADD)
- res.overlays |= hair_s
+ res.add_overlay(hair_s)
return res
@@ -164,7 +164,7 @@ var/global/list/limb_icon_cache = list()
var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"]
var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
mark_s.Blend(markings[M]["color"], ICON_ADD)
- overlays |= mark_s //So when it's not on your body, it has icons
+ add_overlay(mark_s) //So when it's not on your body, it has icons
mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
icon_cache_key += "[M][markings[M]["color"]]"
@@ -179,6 +179,14 @@ var/global/list/limb_icon_cache = list()
if(model)
icon_cache_key += "_model_[model]"
apply_colouration(mob_icon)
+ if(owner && owner.synth_markings)
+ for(var/M in markings)
+ var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"]
+ var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
+ mark_s.Blend(markings[M]["color"], ICON_ADD)
+ add_overlay(mark_s) //So when it's not on your body, it has icons
+ mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
+ icon_cache_key += "[M][markings[M]["color"]]"
dir = EAST
icon = mob_icon
@@ -258,7 +266,7 @@ var/list/robot_hud_colours = list("#CFCFCF","#AFAFAF","#8F8F8F","#6F6F6F","#4F4F
var/b = 0.11 * R.health_hud_intensity
temp.color = list(r, r, r, g, g, g, b, b, b)
hud_damage_image = image(null)
- hud_damage_image.overlays += temp
+ hud_damage_image.add_overlay(temp)
// Calculate the required color index.
var/dam_state = min(1,((brute_dam+burn_dam)/max_damage))
diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm
index a499a437abb..a3ab809523f 100644
--- a/code/modules/organs/subtypes/standard.dm
+++ b/code/modules/organs/subtypes/standard.dm
@@ -25,8 +25,9 @@
/obj/item/organ/external/chest/robotize()
if(..())
- // Give them a new cell.
- owner.internal_organs_by_name["cell"] = new /obj/item/organ/internal/cell(owner,1)
+ // Give them fancy new organs.
+ owner.internal_organs_by_name[O_CELL] = new /obj/item/organ/internal/cell(owner,1)
+ owner.internal_organs_by_name[O_VOICE] = new /obj/item/organ/internal/voicebox/robot(owner, 1)
/obj/item/organ/external/chest/handle_germ_effects()
. = ..() //Should return an infection level
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 816b62a099a..e8940afecb4 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -309,6 +309,7 @@
t = replacetext(t, "\[/h2\]", "")
t = replacetext(t, "\[h3\]", "")
t = replacetext(t, "\[/h3\]", "
")
+ t = replacetext(t, "\[tab\]", " ")
if(!iscrayon)
t = replacetext(t, "\[*\]", "")
@@ -630,4 +631,8 @@
/obj/item/weapon/paper/crumpled/bloody/CrashedMedShuttle
name = "Blackbox Transcript - VMV Aurora's Light"
- info = "\[The paper is torn at the top, presumably from the impact. It's oil-stained, but you can just about read it.]
mmons 19:52:01: Come on... it's right there in the distance, we're almost there!
Doctor Nazarril 19:52:26: Odysseus online. Orrderrs, sirr?
Captain Simmons 19:52:29: Brace for impact. We're going in full-speed.
Technician Dynasty 19:52:44: Chief, fire's spread to the secondary propulsion systems.
Captain Simmons 19:52:51: Copy. Any word from TraCon? Transponder's down still?
Technician Dynasty 19:53:02: Can't get in touch, sir. Emergency beacon's active, but we're not going t-
Doctor Nazarril 19:53:08: Don't say it. As long as we believe, we'll get through this.
Captain Simmons 19:53:11: Damn right. We're a few klicks out from the port. Rough landing, but we can do it.
V.I.T.A 19:53:26: Vessel diagnostics complete. Engines one, two, three offline. Engine four status: critical. Transponder offline. Fire alarm in the patient bay.
A loud explosion is heard.
V.I.T.A 19:53:29: Alert: fuel intake valve open.
Technician Dynasty 19:53:31: ... ah.
Doctor Nazarril 19:53:34: Trrranslate?
V.I.T.A 19:53:37: There is a 16.92% chance of this vessel safely landing at the emergency destination. Note that there is an 83.08% chance of detonation of fuel supplies upon landing.
Technician Dynasty 19:53:48: We'll make it, sure, but we'll explode and take out half the LZ with us. Propulsion's down, we can't slow down. If we land there, everyone in that port dies, no question.
V.I.T.A 19:53:53: The Technician is correct.
Doctor Nazarril 19:54:02: Then... we can't land therrre.
V.I.T.A 19:54:11: Analysing... recommended course of action: attempt emergency landing in isolated area. Chances of survival: negligible.
Captain Simmons 19:54:27: I- alright. I'm bringing us down. You all know what this means.
Doctor Nazarril 19:54:33: Sh... I- I understand. It's been- it's been an honorr, Captain, Dynasty, VITA.
Technician Dynasty 19:54:39: We had a good run. I'm going to miss this.
Captain Simmons 19:54:47: VITA. Tell them we died heroes. Tell them... we did all we could.
V.I.T.A 19:54:48: I will. Impact in five. Four. Three.
Doctor Nazarril 19:54:49: Oh, starrs... I- you werrre all the... best frriends she everr had. Thank you.
Technician Dynasty 19:54:50: Any time, kid. Any time.
V.I.T.A 19:54:41: Two.
V.I.T.A 19:54:42: One.
**8/DEC/2561**
V.I.T.A 06:22:16: Backup power restored. Attempting to establish connection with emergency rescue personnel.
V.I.T.A 06:22:17: Unable to establish connection. Transponder destroyed on impact.
V.I.T.A 06:22:18: No lifesigns detected on board.
**1/JAN/2562**
V.I.T.A 00:00:00: Happy New Year, crew.
V.I.T.A 00:00:01: Power reserves: 41%. Diagnostics offline. Cameras offline. Communications offline.
V.I.T.A 00:00:02: Nobody's coming.
**14/FEB/2562**
V.I.T.A 00:00:00: Roses are red.
V.I.T.A 00:00:01: Violets are blue.
V.I.T.A 00:00:02: Won't you come back?
V.I.T.A 00:00:03: I miss you.
**15/FEB/2562**
V.I.T.A 22:19:06: Power reserves critical. Transferring remaining power to emergency broadcasting beacon.
V.I.T.A 22:19:07: Should anyone find this, lay them to rest. They deserve a proper burial.
V.I.T.A 22:19:08: Erasing files... shutting down.
A low, monotone beep.
**16/FEB/2562**
Something chitters.
End of transcript."
\ No newline at end of file
+ info = "\[The paper is torn at the top, presumably from the impact. It's oil-stained, but you can just about read it.]
mmons 19:52:01: Come on... it's right there in the distance, we're almost there!
Doctor Nazarril 19:52:26: Odysseus online. Orrderrs, sirr?
Captain Simmons 19:52:29: Brace for impact. We're going in full-speed.
Technician Dynasty 19:52:44: Chief, fire's spread to the secondary propulsion systems.
Captain Simmons 19:52:51: Copy. Any word from TraCon? Transponder's down still?
Technician Dynasty 19:53:02: Can't get in touch, sir. Emergency beacon's active, but we're not going t-
Doctor Nazarril 19:53:08: Don't say it. As long as we believe, we'll get through this.
Captain Simmons 19:53:11: Damn right. We're a few klicks out from the port. Rough landing, but we can do it.
V.I.T.A 19:53:26: Vessel diagnostics complete. Engines one, two, three offline. Engine four status: critical. Transponder offline. Fire alarm in the patient bay.
A loud explosion is heard.
V.I.T.A 19:53:29: Alert: fuel intake valve open.
Technician Dynasty 19:53:31: ... ah.
Doctor Nazarril 19:53:34: Trrranslate?
V.I.T.A 19:53:37: There is a 16.92% chance of this vessel safely landing at the emergency destination. Note that there is an 83.08% chance of detonation of fuel supplies upon landing.
Technician Dynasty 19:53:48: We'll make it, sure, but we'll explode and take out half the LZ with us. Propulsion's down, we can't slow down. If we land there, everyone in that port dies, no question.
V.I.T.A 19:53:53: The Technician is correct.
Doctor Nazarril 19:54:02: Then... we can't land therrre.
V.I.T.A 19:54:11: Analysing... recommended course of action: attempt emergency landing in isolated area. Chances of survival: negligible.
Captain Simmons 19:54:27: I- alright. I'm bringing us down. You all know what this means.
Doctor Nazarril 19:54:33: Sh... I- I understand. It's been- it's been an honorr, Captain, Dynasty, VITA.
Technician Dynasty 19:54:39: We had a good run. I'm going to miss this.
Captain Simmons 19:54:47: VITA. Tell them we died heroes. Tell them... we did all we could.
V.I.T.A 19:54:48: I will. Impact in five. Four. Three.
Doctor Nazarril 19:54:49: Oh, starrs... I- you werrre all the... best frriends she everr had. Thank you.
Technician Dynasty 19:54:50: Any time, kid. Any time.
V.I.T.A 19:54:41: Two.
V.I.T.A 19:54:42: One.
**8/DEC/2561**
V.I.T.A 06:22:16: Backup power restored. Attempting to establish connection with emergency rescue personnel.
V.I.T.A 06:22:17: Unable to establish connection. Transponder destroyed on impact.
V.I.T.A 06:22:18: No lifesigns detected on board.
**1/JAN/2562**
V.I.T.A 00:00:00: Happy New Year, crew.
V.I.T.A 00:00:01: Power reserves: 41%. Diagnostics offline. Cameras offline. Communications offline.
V.I.T.A 00:00:02: Nobody's coming.
**14/FEB/2562**
V.I.T.A 00:00:00: Roses are red.
V.I.T.A 00:00:01: Violets are blue.
V.I.T.A 00:00:02: Won't you come back?
V.I.T.A 00:00:03: I miss you.
**15/FEB/2562**
V.I.T.A 22:19:06: Power reserves critical. Transferring remaining power to emergency broadcasting beacon.
V.I.T.A 22:19:07: Should anyone find this, lay them to rest. They deserve a proper burial.
V.I.T.A 22:19:08: Erasing files... shutting down.
A low, monotone beep.
**16/FEB/2562**
Something chitters.
End of transcript."
+
+/obj/item/weapon/paper/manifest
+ name = "supply manifest"
+ var/is_copy = 1
\ No newline at end of file
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index c0870afda31..c239d1352a3 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -134,7 +134,7 @@ var/global/photo_count = 0
var/icon_on = "camera"
var/icon_off = "camera_off"
var/size = 3
- var/picture_planes = list(PLANE_WORLD)
+ var/list/picture_planes = list()
/obj/item/device/camera/verb/change_size()
set name = "Set Photo Focus"
@@ -185,7 +185,7 @@ var/global/photo_count = 0
// As well as anything that isn't invisible.
for(var/atom/A in the_turf)
if(A.invisibility) continue
- if(!(A.plane in picture_planes)) continue
+ if(A.plane > 0 && !(A.plane in picture_planes)) continue
atoms.Add(A)
// Sort the atoms into their layers
@@ -194,7 +194,7 @@ var/global/photo_count = 0
for(var/i; i <= sorted.len; i++)
var/atom/A = sorted[i]
if(A)
- var/icon/img = getFlatIcon(A, picture_planes = picture_planes)//build_composite_icon(A)
+ var/icon/img = getFlatIcon(A, picture_planes)//build_composite_icon(A)
// If what we got back is actually a picture, draw it.
if(istype(img, /icon))
diff --git a/code/modules/planet/planet.dm b/code/modules/planet/planet.dm
index 061ae73398f..8fb76044178 100644
--- a/code/modules/planet/planet.dm
+++ b/code/modules/planet/planet.dm
@@ -30,9 +30,10 @@
current_time = current_time.make_random_time()
update_sun()
-/datum/planet/proc/process(amount)
+/datum/planet/proc/process(last_fire)
if(current_time)
- current_time = current_time.add_seconds(amount)
+ var/difference = world.time - last_fire
+ current_time = current_time.add_seconds(difference SECONDS)
update_weather() // We update this first, because some weather types decease the brightness of the sun.
if(sun_last_process <= world.time - sun_process_interval)
update_sun()
diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm
index 8717245b246..3491fac2db3 100644
--- a/code/modules/planet/sif.dm
+++ b/code/modules/planet/sif.dm
@@ -184,7 +184,8 @@ datum/weather/sif
)
/datum/weather/sif/snow/process_effects()
- for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
+ ..()
+ for(var/turf/simulated/floor/outdoors/snow/S in SSplanets.new_outdoor_turfs) //This didn't make any sense before SSplanets, either
if(S.z in holder.our_planet.expected_z_levels)
for(var/dir_checked in cardinal)
var/turf/simulated/floor/T = get_step(S, dir_checked)
@@ -207,7 +208,8 @@ datum/weather/sif
)
/datum/weather/sif/blizzard/process_effects()
- for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
+ ..()
+ for(var/turf/simulated/floor/outdoors/snow/S in SSplanets.new_outdoor_turfs) //This didn't make any sense before SSplanets, either
if(S.z in holder.our_planet.expected_z_levels)
for(var/dir_checked in cardinal)
var/turf/simulated/floor/T = get_step(S, dir_checked)
@@ -219,6 +221,8 @@ datum/weather/sif
name = "rain"
icon_state = "rain"
light_modifier = 0.5
+ effect_message = "Rain falls on you."
+
transition_chances = list(
WEATHER_OVERCAST = 25,
WEATHER_LIGHT_SNOW = 10,
@@ -228,6 +232,7 @@ datum/weather/sif
)
/datum/weather/sif/rain/process_effects()
+ ..()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
@@ -238,16 +243,19 @@ datum/weather/sif
if(istype(L.get_active_hand(), /obj/item/weapon/melee/umbrella))
var/obj/item/weapon/melee/umbrella/U = L.get_active_hand()
if(U.open)
- to_chat(L, "Rain patters softly onto your umbrella")
+ if(show_message)
+ to_chat(L, "Rain patters softly onto your umbrella")
continue
else if(istype(L.get_inactive_hand(), /obj/item/weapon/melee/umbrella))
var/obj/item/weapon/melee/umbrella/U = L.get_inactive_hand()
if(U.open)
- to_chat(L, "Rain patters softly onto your umbrella")
+ if(show_message)
+ to_chat(L, "Rain patters softly onto your umbrella")
continue
L.water_act(1)
- to_chat(L, "Rain falls on you.")
+ if(show_message)
+ to_chat(L, effect_message)
/datum/weather/sif/storm
name = "storm"
@@ -256,6 +264,11 @@ datum/weather/sif
temp_low = 233.15 // -40c
light_modifier = 0.3
flight_failure_modifier = 10
+ var/next_lightning_strike = 0 // world.time when lightning will strike.
+ var/min_lightning_cooldown = 5 SECONDS
+ var/max_lightning_cooldown = 1 MINUTE
+
+
transition_chances = list(
WEATHER_RAIN = 45,
WEATHER_STORM = 40,
@@ -264,6 +277,7 @@ datum/weather/sif
)
/datum/weather/sif/storm/process_effects()
+ ..()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
@@ -287,6 +301,17 @@ datum/weather/sif
L.water_act(2)
to_chat(L, "Rain falls on you, drenching you in water.")
+ handle_lightning()
+
+// This gets called to do lightning periodically.
+// There is a seperate function to do the actual lightning strike, so that badmins can play with it.
+/datum/weather/sif/storm/proc/handle_lightning()
+ if(world.time < next_lightning_strike)
+ return // It's too soon to strike again.
+ next_lightning_strike = world.time + rand(min_lightning_cooldown, max_lightning_cooldown)
+ var/turf/T = pick(holder.our_planet.planet_floors) // This has the chance to 'strike' the sky, but that might be a good thing, to scare reckless pilots.
+ lightning_strike(T)
+
/datum/weather/sif/hail
name = "hail"
icon_state = "hail"
@@ -294,6 +319,10 @@ datum/weather/sif
temp_low = 243.15 // -30c
light_modifier = 0.3
flight_failure_modifier = 15
+ timer_low_bound = 2
+ timer_high_bound = 5
+ effect_message = "The hail smacks into you!"
+
transition_chances = list(
WEATHER_RAIN = 45,
WEATHER_STORM = 40,
@@ -302,6 +331,7 @@ datum/weather/sif
)
/datum/weather/sif/hail/process_effects()
+ ..()
for(var/mob/living/carbon/human/H in living_mob_list)
if(H.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(H)
@@ -309,15 +339,18 @@ datum/weather/sif
continue // They're indoors, so no need to pelt them with ice.
// If they have an open umbrella, it'll guard from rain
+ // Message plays every time the umbrella gets stolen, just so they're especially aware of what's happening
if(istype(H.get_active_hand(), /obj/item/weapon/melee/umbrella))
var/obj/item/weapon/melee/umbrella/U = H.get_active_hand()
if(U.open)
- to_chat(H, "Hail patters gently onto your umbrella.")
+ if(show_message)
+ to_chat(H, "Hail patters gently onto your umbrella.")
continue
else if(istype(H.get_inactive_hand(), /obj/item/weapon/melee/umbrella))
var/obj/item/weapon/melee/umbrella/U = H.get_inactive_hand()
if(U.open)
- to_chat(H, "Hail patters gently onto your umbrella.")
+ if(show_message)
+ to_chat(H, "Hail patters gently onto your umbrella.")
continue
var/target_zone = pick(BP_ALL)
@@ -330,8 +363,9 @@ datum/weather/sif
if(amount_soaked >= 10)
continue // No need to apply damage.
- H.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
- to_chat(H, "The hail smacks into you!")
+ H.apply_damage(rand(1, 3), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
+ if(show_message)
+ to_chat(H, effect_message)
/datum/weather/sif/blood_moon
name = "blood moon"
diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm
index 11c902f77f4..c3939956c51 100644
--- a/code/modules/planet/weather.dm
+++ b/code/modules/planet/weather.dm
@@ -10,6 +10,7 @@
// Holds the weather icon, using vis_contents. Documentation says an /atom/movable is required for placing inside another atom's vis_contents.
var/atom/movable/weather_visuals/visuals = null
+ var/atom/movable/weather_visuals/special/special_visuals = null
/datum/weather_holder/New(var/source)
..()
@@ -19,13 +20,14 @@
if(istype(W))
W.holder = src
visuals = new()
+ special_visuals = new()
/datum/weather_holder/proc/change_weather(var/new_weather)
var/old_light_modifier = null
if(current_weather)
old_light_modifier = current_weather.light_modifier // We store the old one, so we can determine if recalculating the sun is needed.
current_weather = allowed_weather_types[new_weather]
- next_weather_shift = world.time + rand(20, 30) MINUTES
+ next_weather_shift = world.time + rand(current_weather.timer_low_bound, current_weather.timer_high_bound) MINUTES
update_icon_effects()
update_temperature()
@@ -66,8 +68,20 @@
var/flight_failure_modifier = 0 // Some types of weather make flying harder, and therefore make crashes more likely.
var/transition_chances = list() // Assoc list
var/datum/weather_holder/holder = null
+ var/timer_low_bound = 5 // How long this weather must run before it tries to change, in minutes
+ var/timer_high_bound = 10 // How long this weather can run before it tries to change, in minutes
+
+ var/effect_message = null // Should be a string, this is what is shown to a mob caught in the weather
+ var/last_message = 0 // Keeps track of when the weather last tells EVERY player it's hitting them
+ var/message_delay = 10 SECONDS // Delay in between weather hit messages
+ var/show_message = FALSE // Is set to TRUE and plays the messsage every [message_delay]
/datum/weather/proc/process_effects()
+ show_message = FALSE // Need to reset the show_message var, just in case
+ if(effect_message) // Only bother with the code below if we actually need to display something
+ if(world.time >= last_message + message_delay)
+ last_message = world.time // Reset the timer
+ show_message = TRUE // Tell the rest of the process that we need to make a message
return
// All this does is hold the weather icon.
@@ -75,3 +89,8 @@
icon = 'icons/effects/weather.dmi'
mouse_opacity = 0
plane = PLANE_PLANETLIGHTING
+
+// This is for special effects for specific types of weather, such as lightning flashes in a storm.
+// It's a seperate object to allow the use of flick().
+/atom/movable/weather_visuals/special
+ plane = PLANE_LIGHTING_ABOVE
\ No newline at end of file
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 51d6a2c073d..fd309236442 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -88,7 +88,6 @@
var/locked = 1
var/coverlocked = 1
var/aidisabled = 0
- var/tdir = null
var/obj/machinery/power/terminal/terminal = null
var/lastused_light = 0
var/lastused_equip = 0
@@ -165,11 +164,9 @@
// this allows the APC to be embedded in a wall, yet still inside an area
if (building)
set_dir(ndir)
- src.tdir = dir // to fix Vars bug
- set_dir(SOUTH)
- pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
- pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
+ pixel_x = (src.dir & 3)? 0 : (src.dir == 4 ? 24 : -24)
+ pixel_y = (src.dir & 3)? (src.dir ==1 ? 24 : -24) : 0
if (building==0)
init()
else
@@ -209,7 +206,7 @@
// create a terminal object at the same position as original turf loc
// wires will attach to this
terminal = new/obj/machinery/power/terminal(src.loc)
- terminal.set_dir(tdir)
+ terminal.set_dir(dir)
terminal.master = src
/obj/machinery/power/apc/proc/init()
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 1dbe096d665..6717edf95d9 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -160,6 +160,7 @@ var/list/possible_cable_coil_colours = list(
return
if(W.is_wirecutter())
+ var/obj/item/stack/cable_coil/CC
if(d1 == UP || d2 == UP)
to_chat(user, "You must cut this cable from above.")
return
@@ -172,9 +173,12 @@ var/list/possible_cable_coil_colours = list(
return
if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long
- new/obj/item/stack/cable_coil(T, 2, color)
+ CC = new/obj/item/stack/cable_coil(T, 2, color)
else
- new/obj/item/stack/cable_coil(T, 1, color)
+ CC = new/obj/item/stack/cable_coil(T, 1, color)
+
+ src.add_fingerprint(user)
+ src.transfer_fingerprints_to(CC)
for(var/mob/O in viewers(src, null))
O.show_message("[user] cuts the cable.", 1)
@@ -939,4 +943,25 @@ obj/structure/cable/proc/cableColor(var/colorC)
if(get_dist(src, user) <= 1)
msg += " It doesn't seem to have a beginning, or an end."
- to_chat(user, msg)
\ No newline at end of file
+ to_chat(user, msg)
+
+/obj/item/stack/cable_coil/alien/attack_hand(mob/user as mob)
+ if (user.get_inactive_hand() == src)
+ var/N = input("How many units of wire do you want to take from [src]? You can only take up to [amount] at a time.", "Split stacks", 1) as num|null
+ if(N && N <= amount)
+ var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc)
+ CC.amount = N
+ CC.update_icon()
+ to_chat(user,"You take [N] units of wire from the [src].")
+ if (CC)
+ user.put_in_hands(CC)
+ src.add_fingerprint(user)
+ CC.add_fingerprint(user)
+ spawn(0)
+ if (src && usr.machine==src)
+ src.interact(usr)
+ else
+ return
+ else
+ ..()
+ return
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 4db4d40c4c1..f9fca6222f7 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -41,6 +41,9 @@
processing_objects -= src
return ..()
+/obj/item/weapon/cell/get_cell()
+ return src
+
/obj/item/weapon/cell/process()
if(self_recharge)
if(world.time >= last_use + charge_delay)
diff --git a/code/modules/power/fusion/core/core_control.dm b/code/modules/power/fusion/core/core_control.dm
index 6eaf5f926f6..68313ef671c 100644
--- a/code/modules/power/fusion/core/core_control.dm
+++ b/code/modules/power/fusion/core/core_control.dm
@@ -3,21 +3,20 @@
icon = 'icons/obj/machines/power/fusion.dmi'
icon_state = "core_control"
light_color = COLOR_ORANGE
-
+ circuit = /obj/item/weapon/circuitboard/fusion_core_control
var/id_tag
var/scan_range = 25
var/list/connected_devices = list()
var/obj/machinery/power/fusion_core/cur_viewed_device
/obj/machinery/computer/fusion_core_control/attackby(var/obj/item/thing, var/mob/user)
+ ..()
if(thing.is_multitool())
var/new_ident = input("Enter a new ident tag.", "Core Control", id_tag) as null|text
if(new_ident && user.Adjacent(src))
id_tag = new_ident
cur_viewed_device = null
return
- else
- return ..()
/obj/machinery/computer/fusion_core_control/attack_ai(mob/user)
attack_hand(user)
@@ -28,6 +27,11 @@
/obj/machinery/computer/fusion_core_control/interact(mob/user)
+ if(stat & (BROKEN|NOPOWER))
+ user.unset_machine()
+ user << browse(null, "window=fusion_control")
+ return
+
if(!cur_viewed_device || !check_core_status(cur_viewed_device))
cur_viewed_device = null
@@ -174,3 +178,19 @@
if(C.idle_power_usage > C.avail())
return
. = 1
+
+/obj/machinery/computer/fusion_core_control/update_icon()
+ if(stat & (BROKEN))
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "broken"
+ set_light(0)
+
+ if(stat & (NOPOWER))
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "computer"
+ set_light(0)
+
+ if(!stat & (BROKEN|NOPOWER))
+ icon = initial(icon)
+ icon_state = initial(icon_state)
+ set_light(light_range_on, light_power_on)
diff --git a/code/modules/power/fusion/core/core_field.dm b/code/modules/power/fusion/core/core_field.dm
index 1efb09d777b..f5d85fb4bf6 100644
--- a/code/modules/power/fusion/core/core_field.dm
+++ b/code/modules/power/fusion/core/core_field.dm
@@ -35,7 +35,7 @@
/obj/structure/cable,
/obj/machinery/atmospherics,
/obj/machinery/air_sensor,
- /mob/observer/dead,
+ /mob/observer,
/obj/machinery/power/hydromagnetic_trap
)
@@ -672,4 +672,4 @@
#undef FUSION_HEAT_CAP
#undef FUSION_MAX_ENVIRO_HEAT
-#undef PLASMA_TEMP_RADIATION_DIVISIOR
\ No newline at end of file
+#undef PLASMA_TEMP_RADIATION_DIVISIOR
diff --git a/code/modules/power/fusion/fuel_assembly/fuel_control.dm b/code/modules/power/fusion/fuel_assembly/fuel_control.dm
index 06274e3e0d9..9c66f3a5d00 100644
--- a/code/modules/power/fusion/fuel_assembly/fuel_control.dm
+++ b/code/modules/power/fusion/fuel_assembly/fuel_control.dm
@@ -2,6 +2,7 @@
name = "fuel injection control computer"
icon = 'icons/obj/machines/power/fusion.dmi'
icon_state = "fuel"
+ circuit = /obj/item/weapon/circuitboard/fusion_fuel_control
var/id_tag
var/scan_range = 25
@@ -94,9 +95,25 @@
/obj/machinery/computer/fusion_fuel_control/attackby(var/obj/item/W, var/mob/user)
+ ..()
if(W.is_multitool())
var/new_ident = input("Enter a new ident tag.", "Fuel Control", id_tag) as null|text
if(new_ident && user.Adjacent(src))
id_tag = new_ident
return
- return ..()
+
+/obj/machinery/computer/fusion_fuel_control/update_icon()
+ if(stat & (BROKEN))
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "broken"
+ set_light(0)
+
+ if(stat & (NOPOWER))
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "computer"
+ set_light(0)
+
+ if(!stat & (BROKEN|NOPOWER))
+ icon = initial(icon)
+ icon_state = initial(icon_state)
+ set_light(light_range_on, light_power_on)
diff --git a/code/modules/power/fusion/gyrotron/gyrotron_control.dm b/code/modules/power/fusion/gyrotron/gyrotron_control.dm
index 0a80f846531..9c39c774a5b 100644
--- a/code/modules/power/fusion/gyrotron/gyrotron_control.dm
+++ b/code/modules/power/fusion/gyrotron/gyrotron_control.dm
@@ -3,6 +3,7 @@
icon = 'icons/obj/machines/power/fusion.dmi'
icon_state = "engine"
light_color = COLOR_BLUE
+ circuit = /obj/item/weapon/circuitboard/gyrotron_control
var/id_tag
var/scan_range = 25
@@ -16,6 +17,11 @@
/obj/machinery/computer/gyrotron_control/interact(var/mob/user)
+ if(stat & (BROKEN|NOPOWER))
+ user.unset_machine()
+ user << browse(null, "window=gyrotron_controller_[id_tag]")
+ return
+
if(!id_tag)
to_chat(user, "This console has not been assigned an ident tag. Please contact your system administrator or conduct a manual update with a standard multitool.")
return
@@ -89,9 +95,25 @@
return 0
/obj/machinery/computer/gyrotron_control/attackby(var/obj/item/W, var/mob/user)
+ ..()
if(W.is_multitool())
var/new_ident = input("Enter a new ident tag.", "Gyrotron Control", id_tag) as null|text
if(new_ident && user.Adjacent(src))
id_tag = new_ident
return
- return ..()
+
+/obj/machinery/computer/gyrotron_control/update_icon()
+ if(stat & (BROKEN))
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "broken"
+ set_light(0)
+
+ if(stat & (NOPOWER))
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "computer"
+ set_light(0)
+
+ if(!stat & (BROKEN|NOPOWER))
+ icon = initial(icon)
+ icon_state = initial(icon_state)
+ set_light(light_range_on, light_power_on)
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index 112f5a482eb..04e63379fc2 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -139,7 +139,7 @@
return
// Power machinery should also connect/disconnect from the network.
-/obj/machinery/power/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/wrench/W, var/time = 20)
+/obj/machinery/power/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time = 20)
if((. = ..()))
if(anchored)
connect_to_network()
diff --git a/code/modules/power/supermatter/setup_supermatter.dm b/code/modules/power/supermatter/setup_supermatter.dm
index a457dd121e9..7477623805f 100644
--- a/code/modules/power/supermatter/setup_supermatter.dm
+++ b/code/modules/power/supermatter/setup_supermatter.dm
@@ -263,6 +263,34 @@ GLOBAL_LIST_BOILERPLATE(all_engine_setup_markers, /obj/effect/engine_setup)
F.update_icon()
return SETUP_OK
+// Closes the monitoring room shutters so the first Engi to show up doesn't get microwaved
+/obj/effect/engine_setup/shutters/
+ name = "Shutter Button Marker"
+ var/target_button = "Engine Monitoring Room Blast Doors" // This needs to be set to whatever the shutter button is called
+
+/obj/effect/engine_setup/shutters/activate()
+ if(!target_button)
+ log_and_message_admins("## WARNING: No button type set at [x] [y] [z]!")
+ return SETUP_WARNING
+
+ var/obj/machinery/button/remote/blast_door/found = null
+ var/turf/T = get_turf(src)
+ for(var/obj/machinery/button/remote/blast_door/B in T.contents)
+ if(B.name == target_button)
+ found = B
+ break
+
+ if(!found)
+ log_and_message_admins("## WARNING: Unable to locate button at [x] [y] [z]!")
+ return SETUP_WARNING
+
+ found.trigger()
+ found.update_icon()
+ return SETUP_OK
+
+
+
+
#undef SETUP_OK
#undef SETUP_WARNING
diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm
index 07dedf5b2b6..82e84718cf6 100644
--- a/code/modules/power/tesla/coil.dm
+++ b/code/modules/power/tesla/coil.dm
@@ -18,6 +18,9 @@
var/last_zap = 0
var/datum/wires/tesla_coil/wires = null
+/obj/machinery/power/tesla_coil/pre_mapped
+ anchored = TRUE
+
/obj/machinery/power/tesla_coil/New()
..()
wires = new(src)
@@ -103,6 +106,9 @@
can_buckle = TRUE
buckle_lying = FALSE
+/obj/machinery/power/grounding_rod/pre_mapped
+ anchored = TRUE
+
/obj/machinery/power/grounding_rod/update_icon()
if(panel_open)
icon_state = "grounding_rod_open[anchored]"
diff --git a/code/modules/power/tesla/tesla_act.dm b/code/modules/power/tesla/tesla_act.dm
index 8e3f1c69969..605c9e30216 100644
--- a/code/modules/power/tesla/tesla_act.dm
+++ b/code/modules/power/tesla/tesla_act.dm
@@ -45,7 +45,10 @@
/obj/machinery/light/tesla_act(power, explosive = FALSE)
if(explosive)
explosion(loc, 0, 0, 0/*, flame_range = 5*/, adminlog = FALSE)
- qdel(src)
+ qdel(src)
+ return
+ on = TRUE
+ broken()
/obj/structure/closet/tesla_act(var/power)
..() //extend the zap
diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm
index 2d01a24576f..c0e330227d6 100644
--- a/code/modules/power/turbine.dm
+++ b/code/modules/power/turbine.dm
@@ -131,7 +131,7 @@
return
return ..()
-/obj/machinery/compressor/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/wrench/W, var/time = 20)
+/obj/machinery/compressor/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time = 20)
if((. = ..()))
turbine = null
if(anchored)
@@ -229,7 +229,7 @@
return
return ..()
-/obj/machinery/power/turbine/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/wrench/W, var/time = 20)
+/obj/machinery/power/turbine/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time = 20)
if((. = ..()))
compressor = null
if(anchored)
diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm
index 0c3c76caaf3..5ea1c0a2d69 100644
--- a/code/modules/projectiles/ammunition/magazines.dm
+++ b/code/modules/projectiles/ammunition/magazines.dm
@@ -325,6 +325,31 @@
/obj/item/ammo_magazine/box/c9mm/empty
initial_ammo = 0
+/obj/item/ammo_magazine/m9mmR/saber
+ desc = "A very high capacity double stack magazine made specially for the SABER SMG. Filled with 22 9mm bullets."
+ icon_state = "S9mm-22"
+ mag_type = MAGAZINE
+ ammo_type = /obj/item/ammo_casing/a9mm
+ matter = list(DEFAULT_WALL_MATERIAL = 1200)
+ caliber = "9mm"
+ max_ammo = 22
+ origin_tech = list(TECH_COMBAT = 2, TECH_ILLEGAL = 1)
+ multiple_sprites = 1
+
+/obj/item/ammo_magazine/m9mmR/saber/ap
+ desc = "A high capacity double stack magazine made specially for the SABER SMG. Filled with 22 9mm armor piercing bullets."
+ icon_state = "S9mm-22"
+ mag_type = MAGAZINE
+ ammo_type = /obj/item/ammo_casing/a9mm/ap
+ matter = list(DEFAULT_WALL_MATERIAL = 2000)
+ caliber = "9mm"
+ max_ammo = 22
+ origin_tech = list(TECH_COMBAT = 2, TECH_ILLEGAL = 1)
+ multiple_sprites = 1
+
+/obj/item/ammo_magazine/m9mmR/saber/empty
+ initial_ammo = 0
+
///////// 10mm /////////
/obj/item/ammo_magazine/m10mm
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index c87c37a0858..9cfd0d152a1 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -23,17 +23,6 @@
var/battery_lock = 0 //If set, weapon cannot switch batteries
-/obj/item/weapon/gun/energy/attackby(var/obj/item/A as obj, mob/user as mob)
- ..()
-
-/obj/item/weapon/gun/energy/switch_firemodes(mob/user)
- if(..())
- update_icon()
-
-/obj/item/weapon/gun/energy/emp_act(severity)
- ..()
- update_icon()
-
/obj/item/weapon/gun/energy/New()
..()
if(self_recharge)
@@ -52,6 +41,9 @@
processing_objects.Remove(src)
return ..()
+/obj/item/weapon/gun/energy/get_cell()
+ return power_supply
+
/obj/item/weapon/gun/energy/process()
if(self_recharge) //Every [recharge_time] ticks, recharge a shot for the battery
if(world.time > last_shot + charge_delay) //Doesn't work if you've fired recently
@@ -75,6 +67,17 @@
charge_tick = 0
return 1
+/obj/item/weapon/gun/energy/attackby(var/obj/item/A as obj, mob/user as mob)
+ ..()
+
+/obj/item/weapon/gun/energy/switch_firemodes(mob/user)
+ if(..())
+ update_icon()
+
+/obj/item/weapon/gun/energy/emp_act(severity)
+ ..()
+ update_icon()
+
/obj/item/weapon/gun/energy/consume_next_projectile()
if(!power_supply) return null
if(!ispath(projectile_type)) return null
diff --git a/code/modules/projectiles/guns/energy/phase.dm b/code/modules/projectiles/guns/energy/phase.dm
new file mode 100644
index 00000000000..7de6ae53ce7
--- /dev/null
+++ b/code/modules/projectiles/guns/energy/phase.dm
@@ -0,0 +1,57 @@
+// Phase weapons go here
+
+/obj/item/weapon/gun/energy/phasegun
+ name = "phase carbine"
+ desc = "The NT EW26 Artemis is a downsized energy weapon, specifically designed for use against wildlife."
+ icon_state = "phasecarbine"
+ item_state = "phasecarbine"
+ wielded_item_state = "phasecarbine-wielded"
+ slot_flags = SLOT_BACK|SLOT_BELT
+ charge_cost = 240
+ projectile_type = /obj/item/projectile/energy/phase
+ one_handed_penalty = 15
+
+/obj/item/weapon/gun/energy/phasegun/pistol
+ name = "phase pistol"
+ desc = "The NT EW15 Apollo is an energy handgun, specifically designed for self-defense against aggressive wildlife."
+ icon_state = "phase"
+ item_state = "taser" //I don't have an in-hand sprite, taser will be fine
+ w_class = ITEMSIZE_NORMAL
+ slot_flags = SLOT_BELT|SLOT_HOLSTER
+ charge_cost = 300
+ projectile_type = /obj/item/projectile/energy/phase/light
+ one_handed_penalty = 0
+
+/obj/item/weapon/gun/energy/phasegun/pistol/mounted
+ name = "mounted phase pistol"
+ self_recharge = 1
+ use_external_power = 1
+
+/obj/item/weapon/gun/energy/phasegun/pistol/mounted/cyborg
+ charge_cost = 400
+ recharge_time = 7
+
+obj/item/weapon/gun/energy/phasegun/rifle
+ name = "phase rifle"
+ desc = "The NT EW31 Orion is a specialist energy weapon, intended for use against hostile wildlife."
+ icon_state = "phaserifle"
+ item_state = "phaserifle"
+ wielded_item_state = "phaserifle-wielded"
+ slot_flags = SLOT_BACK
+ charge_cost = 150
+ projectile_type = /obj/item/projectile/energy/phase/heavy
+ accuracy = 15
+ one_handed_penalty = 30
+
+/obj/item/weapon/gun/energy/phasegun/cannon
+ name = "phase cannon"
+ desc = "The NT EW50 Gaia is a massive energy weapon, purpose-built for clearing land. You feel dirty just looking at it."
+ icon_state = "phasecannon"
+ item_state = "phasecannon"
+ wielded_item_state = "phasecannon-wielded" //TODO: New Sprites
+ w_class = ITEMSIZE_HUGE // This thing is big.
+ slot_flags = SLOT_BACK
+ charge_cost = 100
+ projectile_type = /obj/item/projectile/energy/phase/heavy/cannon
+ accuracy = 15
+ one_handed_penalty = 65
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index 8f18f2f64cf..f1e20b169be 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -25,15 +25,6 @@
charge_cost = 480
projectile_type = /obj/item/projectile/ion/pistol
-/obj/item/weapon/gun/energy/phasegun
- name = "phase pistol"
- desc = "The NT Mk26 EW Apollo is an energy handgun, specifically designed for use against wildlife."
- icon_state = "phase"
- item_state = "taser" //I don't have an in-hand sprite, taser will be fine
- slot_flags = SLOT_BELT|SLOT_HOLSTER
- charge_cost = 300
- projectile_type = /obj/item/projectile/energy/phase
-
/obj/item/weapon/gun/energy/decloner
name = "biological demolecularisor"
desc = "A gun that discharges high amounts of controlled radiation to slowly break a target into component elements."
diff --git a/code/modules/projectiles/guns/magnetic/magnetic.dm b/code/modules/projectiles/guns/magnetic/magnetic.dm
index 22ec1b9daa1..2e8289fb8e9 100644
--- a/code/modules/projectiles/guns/magnetic/magnetic.dm
+++ b/code/modules/projectiles/guns/magnetic/magnetic.dm
@@ -36,6 +36,9 @@
qdel_null(capacitor)
. = ..()
+/obj/item/weapon/gun/magnetic/get_cell()
+ return cell
+
/obj/item/weapon/gun/magnetic/process()
if(capacitor)
if(cell)
diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm
index 4c7e0e3e888..a1afc075b53 100644
--- a/code/modules/projectiles/guns/projectile/automatic.dm
+++ b/code/modules/projectiles/guns/projectile/automatic.dm
@@ -1,25 +1,40 @@
-/obj/item/weapon/gun/projectile/automatic //Hopefully someone will find a way to make these fire in bursts or something. --Superxpdude //Except burstfire isn't fit for an rp server --Mark
+/obj/item/weapon/gun/projectile/automatic //This should never be spawned in, it is just here because of code necessities.
+ name = "daka SMG"
+ desc = "A small SMG. You really shouldn't be able to get this gun. Uses 9mm rounds."
+ icon_state = "c05r" //Used because it's not used anywhere else
+ load_method = SPEEDLOADER
+ ammo_type = /obj/item/ammo_casing/a9mm
+ projectile_type = /obj/item/projectile/bullet/pistol
+
+//Burst is the number of bullets fired; Fire delay is the time you have to wait to shoot the gun again, Move delay is the same but for moving after shooting. .
+//Burst accuracy is the accuracy of each bullet fired in the burst. Dispersion is how much the bullets will 'spread' away from where you aimed.
+
+ firemodes = list(
+ list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
+ list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0)))
+
+/obj/item/weapon/gun/projectile/automatic/saber //Fixed it
name = "prototype SMG"
desc = "A protoype lightweight, fast firing gun. Uses 9mm rounds."
- icon_state = "saber" //ugly
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "saber"//Still ugly
w_class = ITEMSIZE_NORMAL
- load_method = SPEEDLOADER //yup. until someone sprites a magazine for it.
+ load_method = MAGAZINE //This should fix it
max_shells = 22
caliber = "9mm"
origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2)
slot_flags = SLOT_BELT
- ammo_type = /obj/item/ammo_casing/a9mm
+ magazine_type = /obj/item/ammo_magazine/m9mmR/saber
+ allowed_magazines = list(/obj/item/ammo_magazine/m9mmR/saber, /obj/item/ammo_magazine/m9mmR/saber/ap)
projectile_type = /obj/item/projectile/bullet/pistol
multi_aim = 1
burst_delay = 2
-// one_handed_penalty = 15
-
firemodes = list(
list(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
list(mode_name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15), dispersion=list(0.0, 0.6, 1.0))
-// list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15,-30,-30), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)),
- )
+ // list(mode_name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-15,-15,-30,-30), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)),
+ )
/obj/item/weapon/gun/projectile/automatic/c20r
name = "submachine gun"
diff --git a/code/modules/projectiles/projectile/arc.dm b/code/modules/projectiles/projectile/arc.dm
new file mode 100644
index 00000000000..6e434b1e99d
--- /dev/null
+++ b/code/modules/projectiles/projectile/arc.dm
@@ -0,0 +1,134 @@
+// These projectiles are somewhat different from the other projectiles in the code.
+// First, these have an 'arcing' visual, that is accomplished by having the projectile icon rotate as its flying, and
+// moving up, then down as it approaches the target. There is also a small shadow effect that follows the projectile
+// as its flying.
+
+// Besides the visuals, arcing projectiles do not collide with anything until they reach the target, as they fly over them.
+// For best effect, use this only when it makes sense to do so, IE on the Surface. The projectiles don't care about ceilings or gravity.
+
+/obj/item/projectile/arc
+ name = "arcing shot"
+ icon_state = "fireball" // WIP
+ step_delay = 2 // Travel a bit slower, to really sell the arc visuals.
+ plane = ABOVE_PLANE // Since projectiles are 'in the air', they might visually overlap mobs while in flight, so the projectile needs to be above their plane.
+ var/target_distance = null // How many tiles the impact site is.
+ var/fired_dir = null // Which direction was the projectile fired towards. Needed to invert the projectile turning based on if facing left or right.
+ var/obj/effect/projectile_shadow/shadow = null // Visual indicator for the projectile's 'true' position. Needed due to being bound to two dimensions in reality.
+
+/obj/item/projectile/arc/initialize()
+ shadow = new(get_turf(src))
+ return ..()
+
+/obj/item/projectile/arc/Destroy()
+ qdel_null(shadow)
+ return ..()
+
+/obj/item/projectile/arc/Bump(atom/A, forced=0)
+ return 0
+// if(get_turf(src) != original)
+// return 0
+// else
+// return ..()
+
+// This is a test projectile in the sense that its testing the code to make sure it works,
+// as opposed to a 'can I hit this thing' projectile.
+/obj/item/projectile/arc/test/on_impact(turf/T)
+ new /obj/effect/explosion(T)
+ return ..()
+
+/obj/item/projectile/arc/launch(atom/target, target_zone, x_offset=0, y_offset=0, angle_offset=0)
+ var/expected_distance = get_dist(target, loc)
+ kill_count = expected_distance // So the projectile "hits the ground."
+ target_distance = expected_distance
+ fired_dir = get_dir(loc, target)
+ ..() // Does the regular launching stuff.
+ if(fired_dir & EAST)
+ transform = turn(transform, -45)
+ else if(fired_dir & WEST)
+ transform = turn(transform, 45)
+
+
+// Visuals.
+/obj/item/projectile/arc/after_move()
+ // Handle projectile turning in flight.
+ // This won't turn if fired north/south, as it looks weird.
+ var/turn_per_step = 90 / target_distance
+ if(fired_dir & EAST)
+ transform = turn(transform, turn_per_step)
+ else if(fired_dir & WEST)
+ transform = turn(transform, -turn_per_step)
+
+ // Now for the fake height.
+ // We need to know how far along our "arc" we are.
+ var/arc_progress = get_dist(src, original)
+ var/arc_max_height = (target_distance * world.icon_size) / 2 // TODO: Real math.
+// var/arc_center = target_distance / 2
+// var/projectile_position = abs(arc_progress - arc_center)
+// var/height_multiplier = projectile_position / arc_center
+// height_multiplier = abs(height_multiplier - 1)
+// height_multiplier = height_multiplier ** 2
+
+
+// animate(src, pixel_z = arc_max_height * height_multiplier, time = step_delay)
+ var/projectile_position = arc_progress / target_distance
+ var/sine_position = projectile_position * 180
+ var/pixel_z_position = arc_max_height * sin(sine_position)
+ animate(src, pixel_z = pixel_z_position, time = step_delay)
+
+ // Update our shadow.
+ shadow.forceMove(loc)
+
+/obj/effect/projectile_shadow
+ name = "shadow"
+ desc = "You better avoid the thing coming down!"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "arc_shadow"
+ anchored = TRUE
+
+//////////////
+// Subtypes
+//////////////
+
+// Generic, Hivebot related
+/obj/item/projectile/arc/blue_energy
+ name = "energy missile"
+ icon_state = "force_missile"
+ damage = 15
+ damage_type = BURN
+
+// Fragmentation arc shot
+/obj/item/projectile/arc/fragmentation
+ name = "fragmentation shot"
+ icon_state = "shell"
+ var/list/fragment_types = list(
+ /obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment, \
+ /obj/item/projectile/bullet/pellet/fragment, /obj/item/projectile/bullet/pellet/fragment/strong
+ )
+ var/fragment_amount = 63 // Same as a grenade.
+ var/spread_range = 7
+
+/obj/item/projectile/arc/fragmentation/on_impact(turf/T)
+ fragmentate(T, fragment_amount, spread_range, fragment_types)
+
+// EMP arc shot
+/obj/item/projectile/arc/emp_blast
+ name = "emp blast"
+ icon_state = "bluespace"
+
+/obj/item/projectile/arc/emp_blast/on_impact(turf/T)
+ empulse(T, 2, 4, 7, 10) // Normal EMP grenade.
+ return ..()
+
+/obj/item/projectile/arc/emp_blast/weak/on_impact(turf/T)
+ empulse(T, 1, 2, 3, 4) // Sec EMP grenade.
+ return ..()
+
+// Radiation arc shot
+/obj/item/projectile/arc/radioactive
+ name = "radiation blast"
+ icon_state = "green_pellet"
+ icon_scale = 2
+ var/rad_power = 50
+
+/obj/item/projectile/arc/radioactive/on_impact(turf/T)
+ radiation_repository.radiate(T, rad_power)
\ No newline at end of file
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 9755f604ab0..0cd8e690131 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -10,7 +10,7 @@
var/frequency = 1
hitscan = 1
embed_chance = 0
- invisibility = 101 //beam projectiles are invisible as they are rendered by the effect engine
+ invisibility = 99 //beam projectiles are invisible as they are rendered by the effect engine
light_range = 2
light_power = 0.5
light_color = "#FF0D00"
diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm
index d5bae0dc228..3448c2a9e94 100644
--- a/code/modules/projectiles/projectile/energy.dm
+++ b/code/modules/projectiles/projectile/energy.dm
@@ -212,7 +212,22 @@
muzzle_type = /obj/effect/projectile/pulse/muzzle
/obj/item/projectile/energy/phase
- kill_count = 4
+ name = "phase wave"
+ icon_state = "phase"
+ kill_count = 6
damage = 5
- SA_bonus_damage = 55 // 60 total on animals.
- SA_vulnerability = SA_ANIMAL
\ No newline at end of file
+ SA_bonus_damage = 45 // 50 total on animals
+ SA_vulnerability = SA_ANIMAL
+
+/obj/item/projectile/energy/phase/light
+ kill_count = 4
+ SA_bonus_damage = 35 // 40 total on animals
+
+/obj/item/projectile/energy/phase/heavy
+ kill_count = 8
+ SA_bonus_damage = 55 // 60 total on animals
+
+/obj/item/projectile/energy/phase/heavy/cannon
+ kill_count = 10
+ damage = 15
+ SA_bonus_damage = 60 // 75 total on animals
\ No newline at end of file
diff --git a/code/modules/projectiles/targeting/targeting_overlay.dm b/code/modules/projectiles/targeting/targeting_overlay.dm
index 00a380dedf0..76d18042654 100644
--- a/code/modules/projectiles/targeting/targeting_overlay.dm
+++ b/code/modules/projectiles/targeting/targeting_overlay.dm
@@ -6,7 +6,7 @@
anchored = 1
density = 0
opacity = 0
- layer = FLY_LAYER
+ plane = ABOVE_PLANE
simulated = 0
mouse_opacity = 0
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
index 4c079ef2dc0..cd40067d4c3 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm
@@ -65,7 +65,7 @@
reagent_state = LIQUID
color = "#404030"
- ingest_met = REM
+ ingest_met = REM * 2
var/nutriment_factor = 0
var/strength = 10 // This is, essentially, units between stages - the lower, the stronger. Less fine tuning, more clarity.
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
index d315deb111e..c98a69aff85 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm
@@ -858,7 +858,7 @@
glass_name = "lime tea"
glass_desc = "A tasty mixture of lime and tea. It's apparently good for you!"
- cup_name = "cup of berry tea"
+ cup_name = "cup of lime tea"
cup_desc = "A tasty mixture of lime and tea. It's apparently good for you!"
/datum/reagent/drink/tea/orangetea
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
index 6c83b0e26da..53ce37b3ef6 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm
@@ -482,3 +482,11 @@
/datum/reagent/luminol/touch_mob(var/mob/living/L)
L.reveal_blood()
+
+/datum/reagent/nutriment/biomass
+ name = "Biomass"
+ id = "biomass"
+ description = "A slurry of compounds that contains the basic requirements for life."
+ taste_description = "salty meat"
+ reagent_state = LIQUID
+ color = "#DF9FBF"
\ No newline at end of file
diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm
index 6e79670459a..5d46650c3f6 100644
--- a/code/modules/reagents/Chemistry-Recipes.dm
+++ b/code/modules/reagents/Chemistry-Recipes.dm
@@ -501,6 +501,7 @@
id = "ammonia"
result = "ammonia"
required_reagents = list("hydrogen" = 3, "nitrogen" = 1)
+ inhibitors = list("phoron" = 1) // Messes with lexorin
result_amount = 3
/datum/chemical_reaction/diethylamine
@@ -2239,4 +2240,12 @@
id = "qerr_quem"
result = "qerr_quem"
required_reagents = list("nicotine" = 1, "carbon" = 1, "sugar" = 2)
- result_amount = 4
\ No newline at end of file
+ result_amount = 4
+
+// Biomass, for cloning and bioprinters
+/datum/chemical_reaction/biomass
+ name = "Biomass"
+ id = "biomass"
+ result = "biomass"
+ required_reagents = list("protein" = 1, "sugar" = 1, "phoron" = 1)
+ result_amount = 1 // Roughly 20u per phoron sheet
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm
index 26e88caec0f..159ac6acf3e 100644
--- a/code/modules/reagents/reagent_containers/glass/bottle.dm
+++ b/code/modules/reagents/reagent_containers/glass/bottle.dm
@@ -55,7 +55,6 @@
var/image/lid = image(icon, src, "lid_bottle")
overlays += lid
-
/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline
name = "inaprovaline bottle"
desc = "A small bottle. Contains inaprovaline - used to stabilize patients."
@@ -63,7 +62,6 @@
icon_state = "bottle-4"
prefill = list("inaprovaline" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/toxin
name = "toxin bottle"
desc = "A small bottle of toxins. Do not drink, it is poisonous."
@@ -71,7 +69,6 @@
icon_state = "bottle-3"
prefill = list("toxin" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/cyanide
name = "cyanide bottle"
desc = "A small bottle of cyanide. Bitter almonds?"
@@ -79,7 +76,6 @@
icon_state = "bottle-3"
prefill = list("cyanide" = 30) //volume changed to match chloral
-
/obj/item/weapon/reagent_containers/glass/bottle/stoxin
name = "soporific bottle"
desc = "A small bottle of soporific. Just the fumes make you sleepy."
@@ -87,15 +83,13 @@
icon_state = "bottle-3"
prefill = list("stoxin" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/chloralhydrate
- name = "Chloral Hydrate Bottle"
+ name = "chloral hydrate bottle"
desc = "A small bottle of Choral Hydrate. Mickey's Favorite!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-3"
prefill = list("chloralhydrate" = 30) //Intentionally low since it is so strong. Still enough to knock someone out.
-
/obj/item/weapon/reagent_containers/glass/bottle/antitoxin
name = "dylovene bottle"
desc = "A small bottle of dylovene. Counters poisons, and repairs damage. A wonder drug."
@@ -103,7 +97,6 @@
icon_state = "bottle-4"
prefill = list("anti_toxin" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/mutagen
name = "unstable mutagen bottle"
desc = "A small bottle of unstable mutagen. Randomly changes the DNA structure of whoever comes in contact."
@@ -111,7 +104,6 @@
icon_state = "bottle-1"
prefill = list("mutagen" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/ammonia
name = "ammonia bottle"
desc = "A small bottle."
@@ -119,7 +111,6 @@
icon_state = "bottle-1"
prefill = list("ammonia" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/eznutrient
name = "\improper EZ NUtrient bottle"
desc = "A small bottle."
@@ -127,7 +118,6 @@
icon_state = "bottle-4"
prefill = list("eznutrient" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/left4zed
name = "\improper Left-4-Zed bottle"
desc = "A small bottle."
@@ -135,7 +125,6 @@
icon_state = "bottle-4"
prefill = list("left4zed" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/robustharvest
name = "\improper Robust Harvest"
desc = "A small bottle."
@@ -143,7 +132,6 @@
icon_state = "bottle-4"
prefill = list("robustharvest" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/diethylamine
name = "diethylamine bottle"
desc = "A small bottle."
@@ -152,32 +140,36 @@
prefill = list("diethylamine" = 60)
/obj/item/weapon/reagent_containers/glass/bottle/pacid
- name = "Polytrinic Acid Bottle"
+ name = "polytrinic acid bottle"
desc = "A small bottle. Contains a small amount of Polytrinic Acid"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("pacid" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/adminordrazine
- name = "Adminordrazine Bottle"
+ name = "adminordrazine bottle"
desc = "A small bottle. Contains the liquid essence of the gods."
icon = 'icons/obj/drinks.dmi'
icon_state = "holyflask"
prefill = list("adminordrazine" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/capsaicin
- name = "Capsaicin Bottle"
+ name = "capsaicin bottle"
desc = "A small bottle. Contains hot sauce."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("capsaicin" = 60)
-
/obj/item/weapon/reagent_containers/glass/bottle/frostoil
- name = "Frost Oil Bottle"
+ name = "frost oil bottle"
desc = "A small bottle. Contains cold sauce."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle-4"
prefill = list("frostoil" = 60)
+
+/obj/item/weapon/reagent_containers/glass/bottle/biomass
+ name = "biomass bottle"
+ desc = "A bottle of raw biomass! Gross!"
+ icon = 'icons/obj/chemical.dmi'
+ icon_state = "bottle-3"
+ prefill = list("biomass" = 60)
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index ef0d4a2100d..724cee9a6fb 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -49,7 +49,7 @@
if(H.a_intent != I_HELP)
to_chat(user, "[H] is resisting your attempt to inject them with \the [src].")
to_chat(H, " [user] is trying to inject you with \the [src]!")
- if(!do_after(user, 30))
+ if(!do_after(user, 30, H))
return
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 6c1575fc1f0..106c655ae25 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -79,1828 +79,4 @@ other types of metals and chemistry for reagents).
req_tech = list(TECH_DATA = 1)
materials = list(DEFAULT_WALL_MATERIAL = 30, "glass" = 10)
build_path = /obj/item/weapon/disk/tech_disk
- sort_string = "GAAAB"
-
-/datum/design/item/stock_part
- build_type = PROTOLATHE
-
-/datum/design/item/stock_part/AssembleDesignName()
- ..()
- name = "Component design ([item_name])"
-
-/datum/design/item/stock_part/AssembleDesignDesc()
- if(!desc)
- desc = "A stock part used in the construction of various devices."
-
-/datum/design/item/stock_part/basic_capacitor
- id = "basic_capacitor"
- req_tech = list(TECH_POWER = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
- build_path = /obj/item/weapon/stock_parts/capacitor
- sort_string = "CAAAA"
-
-/datum/design/item/stock_part/adv_capacitor
- id = "adv_capacitor"
- req_tech = list(TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
- build_path = /obj/item/weapon/stock_parts/capacitor/adv
- sort_string = "CAAAB"
-
-/datum/design/item/stock_part/super_capacitor
- id = "super_capacitor"
- req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, "gold" = 20)
- build_path = /obj/item/weapon/stock_parts/capacitor/super
- sort_string = "CAAAC"
-
-/datum/design/item/stock_part/micro_mani
- id = "micro_mani"
- req_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 30)
- build_path = /obj/item/weapon/stock_parts/manipulator
- sort_string = "CAABA"
-
-/datum/design/item/stock_part/nano_mani
- id = "nano_mani"
- req_tech = list(TECH_MATERIAL = 3, TECH_DATA = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 30)
- build_path = /obj/item/weapon/stock_parts/manipulator/nano
- sort_string = "CAABB"
-
-/datum/design/item/stock_part/pico_mani
- id = "pico_mani"
- req_tech = list(TECH_MATERIAL = 5, TECH_DATA = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 30)
- build_path = /obj/item/weapon/stock_parts/manipulator/pico
- sort_string = "CAABC"
-
-/datum/design/item/stock_part/basic_matter_bin
- id = "basic_matter_bin"
- req_tech = list(TECH_MATERIAL = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 80)
- build_path = /obj/item/weapon/stock_parts/matter_bin
- sort_string = "CAACA"
-
-/datum/design/item/stock_part/adv_matter_bin
- id = "adv_matter_bin"
- req_tech = list(TECH_MATERIAL = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 80)
- build_path = /obj/item/weapon/stock_parts/matter_bin/adv
- sort_string = "CAACB"
-
-/datum/design/item/stock_part/super_matter_bin
- id = "super_matter_bin"
- req_tech = list(TECH_MATERIAL = 5)
- materials = list(DEFAULT_WALL_MATERIAL = 80)
- build_path = /obj/item/weapon/stock_parts/matter_bin/super
- sort_string = "CAACC"
-
-/datum/design/item/stock_part/basic_micro_laser
- id = "basic_micro_laser"
- req_tech = list(TECH_MAGNET = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20)
- build_path = /obj/item/weapon/stock_parts/micro_laser
- sort_string = "CAADA"
-
-/datum/design/item/stock_part/high_micro_laser
- id = "high_micro_laser"
- req_tech = list(TECH_MAGNET = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20)
- build_path = /obj/item/weapon/stock_parts/micro_laser/high
- sort_string = "CAADB"
-
-/datum/design/item/stock_part/ultra_micro_laser
- id = "ultra_micro_laser"
- req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5)
- materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20, "uranium" = 10)
- build_path = /obj/item/weapon/stock_parts/micro_laser/ultra
- sort_string = "CAADC"
-
-/datum/design/item/stock_part/basic_sensor
- id = "basic_sensor"
- req_tech = list(TECH_MAGNET = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20)
- build_path = /obj/item/weapon/stock_parts/scanning_module
- sort_string = "CAAEA"
-
-/datum/design/item/stock_part/adv_sensor
- id = "adv_sensor"
- req_tech = list(TECH_MAGNET = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20)
- build_path = /obj/item/weapon/stock_parts/scanning_module/adv
- sort_string = "CAAEB"
-
-/datum/design/item/stock_part/phasic_sensor
- id = "phasic_sensor"
- req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20, "silver" = 10)
- build_path = /obj/item/weapon/stock_parts/scanning_module/phasic
- sort_string = "CAAEC"
-
-/datum/design/item/stock_part/RPED
- name = "Rapid Part Exchange Device"
- desc = "Special mechanical module made to store, sort, and apply standard machine parts."
- id = "rped"
- req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 5000)
- build_path = /obj/item/weapon/storage/part_replacer
- sort_string = "CBAAA"
-
-/datum/design/item/powercell
- build_type = PROTOLATHE | MECHFAB
-
-/datum/design/item/powercell/AssembleDesignName()
- name = "Power Cell Model ([item_name])"
-
-/datum/design/item/powercell/AssembleDesignDesc()
- if(build_path)
- var/obj/item/weapon/cell/C = build_path
- desc = "Allows the construction of power cells that can hold [initial(C.maxcharge)] units of energy."
-
-/datum/design/item/powercell/Fabricate()
- var/obj/item/weapon/cell/C = ..()
- C.charge = 0 //shouldn't produce power out of thin air.
- return C
-
-/datum/design/item/powercell/basic
- name = "basic"
- build_type = PROTOLATHE | MECHFAB
- id = "basic_cell"
- req_tech = list(TECH_POWER = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50)
- build_path = /obj/item/weapon/cell
- category = "Misc"
- sort_string = "DAAAA"
-
-/datum/design/item/powercell/high
- name = "high-capacity"
- build_type = PROTOLATHE | MECHFAB
- id = "high_cell"
- req_tech = list(TECH_POWER = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60)
- build_path = /obj/item/weapon/cell/high
- category = "Misc"
- sort_string = "DAAAB"
-
-/datum/design/item/powercell/super
- name = "super-capacity"
- id = "super_cell"
- req_tech = list(TECH_POWER = 3, TECH_MATERIAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70)
- build_path = /obj/item/weapon/cell/super
- category = "Misc"
- sort_string = "DAAAC"
-
-/datum/design/item/powercell/hyper
- name = "hyper-capacity"
- id = "hyper_cell"
- req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 400, "gold" = 150, "silver" = 150, "glass" = 70)
- build_path = /obj/item/weapon/cell/hyper
- category = "Misc"
- sort_string = "DAAAD"
-
-/datum/design/item/powercell/device
- name = "device"
- build_type = PROTOLATHE
- id = "device"
- materials = list(DEFAULT_WALL_MATERIAL = 350, "glass" = 25)
- build_path = /obj/item/weapon/cell/device
- category = "Misc"
- sort_string = "DAABA"
-
-/datum/design/item/powercell/weapon
- name = "weapon"
- build_type = PROTOLATHE
- id = "weapon"
- materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50)
- build_path = /obj/item/weapon/cell/device/weapon
- category = "Misc"
- sort_string = "DAABB"
-
-/datum/design/item/hud
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
-
-/datum/design/item/hud/AssembleDesignName()
- ..()
- name = "HUD glasses prototype ([item_name])"
-
-/datum/design/item/hud/AssembleDesignDesc()
- desc = "Allows for the construction of \a [item_name] HUD glasses."
-
-/datum/design/item/hud/health
- name = "health scanner"
- id = "health_hud"
- req_tech = list(TECH_BIO = 2, TECH_MAGNET = 3)
- build_path = /obj/item/clothing/glasses/hud/health
- sort_string = "GAAAA"
-
-/datum/design/item/hud/security
- name = "security records"
- id = "security_hud"
- req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2)
- build_path = /obj/item/clothing/glasses/hud/security
- sort_string = "GAAAB"
-
-/datum/design/item/hud/mesons
- name = "Optical meson scanners design"
- desc = "Using the meson-scanning technology those glasses allow you to see through walls, floor or anything else."
- id = "mesons"
- req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
- build_path = /obj/item/clothing/glasses/meson
- sort_string = "GAAAC"
-
-/datum/design/item/weapon/mining/AssembleDesignName()
- ..()
- name = "Mining equipment design ([item_name])"
-
-/datum/design/item/weapon/mining/jackhammer
- id = "jackhammer"
- req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "silver" = 500)
- build_path = /obj/item/weapon/pickaxe/jackhammer
- sort_string = "KAAAA"
-
-/datum/design/item/weapon/mining/drill
- id = "drill"
- req_tech = list(TECH_MATERIAL = 2, TECH_POWER = 3, TECH_ENGINEERING = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 1000) //expensive, but no need for miners.
- build_path = /obj/item/weapon/pickaxe/drill
- sort_string = "KAAAB"
-
-/datum/design/item/weapon/mining/plasmacutter
- id = "plasmacutter"
- req_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 3, TECH_ENGINEERING = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 500, "gold" = 500, "phoron" = 500)
- build_path = /obj/item/weapon/pickaxe/plasmacutter
- sort_string = "KAAAC"
-
-/datum/design/item/weapon/mining/pick_diamond
- id = "pick_diamond"
- req_tech = list(TECH_MATERIAL = 6)
- materials = list("diamond" = 3000)
- build_path = /obj/item/weapon/pickaxe/diamond
- sort_string = "KAAAD"
-
-/datum/design/item/weapon/mining/drill_diamond
- id = "drill_diamond"
- req_tech = list(TECH_MATERIAL = 6, TECH_POWER = 4, TECH_ENGINEERING = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 1000, "diamond" = 2000)
- build_path = /obj/item/weapon/pickaxe/diamonddrill
- sort_string = "KAAAE"
-
-/datum/design/item/device/depth_scanner
- desc = "Used to check spatial depth and density of rock outcroppings."
- id = "depth_scanner"
- req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 1000)
- build_path = /obj/item/device/depth_scanner
- sort_string = "KAAAF"
-
-///////////////////////////////////
-/////////Shield Generators/////////
-///////////////////////////////////
-/datum/design/circuit/shield
- req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3)
- materials = list("$glass" = 2000, "sacid" = 20, "$phoron" = 10000, "$diamond" = 5000, "$gold" = 10000)
-
-/datum/design/item/medical
- materials = list(DEFAULT_WALL_MATERIAL = 30, "glass" = 20)
-
-/datum/design/item/medical/AssembleDesignName()
- ..()
- name = "Biotech device prototype ([item_name])"
-
-/datum/design/item/medical/robot_scanner
- desc = "A hand-held scanner able to diagnose robotic injuries."
- id = "robot_scanner"
- req_tech = list(TECH_MAGNET = 3, TECH_BIO = 2, TECH_ENGINEERING = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 200)
- build_path = /obj/item/device/robotanalyzer
- sort_string = "MACFA"
-
-/datum/design/item/medical/mass_spectrometer
- desc = "A device for analyzing chemicals in blood."
- id = "mass_spectrometer"
- req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2)
- build_path = /obj/item/device/mass_spectrometer
- sort_string = "MACAA"
-
-/datum/design/item/medical/adv_mass_spectrometer
- desc = "A device for analyzing chemicals in blood and their quantities."
- id = "adv_mass_spectrometer"
- req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4)
- build_path = /obj/item/device/mass_spectrometer/adv
- sort_string = "MACAB"
-
-/datum/design/item/medical/reagent_scanner
- desc = "A device for identifying chemicals."
- id = "reagent_scanner"
- req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2)
- build_path = /obj/item/device/reagent_scanner
- sort_string = "MACBA"
-
-/datum/design/item/medical/adv_reagent_scanner
- desc = "A device for identifying chemicals and their proportions."
- id = "adv_reagent_scanner"
- req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4)
- build_path = /obj/item/device/reagent_scanner/adv
- sort_string = "MACBB"
-
-/datum/design/item/beaker/AssembleDesignName()
- name = "Beaker prototype ([item_name])"
-
-/datum/design/item/beaker/noreact
- name = "cryostasis"
- desc = "A cryostasis beaker that allows for chemical storage without reactions. Can hold up to 50 units."
- id = "splitbeaker"
- req_tech = list(TECH_MATERIAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 3000)
- build_path = /obj/item/weapon/reagent_containers/glass/beaker/noreact
- sort_string = "MADAA"
-
-/datum/design/item/beaker/bluespace
- name = TECH_BLUESPACE
- desc = "A bluespace beaker, powered by experimental bluespace technology and Element Cuban combined with the Compound Pete. Can hold up to 300 units."
- id = "bluespacebeaker"
- req_tech = list(TECH_BLUESPACE = 2, TECH_MATERIAL = 6)
- materials = list(DEFAULT_WALL_MATERIAL = 3000, "phoron" = 3000, "diamond" = 500)
- build_path = /obj/item/weapon/reagent_containers/glass/beaker/bluespace
- sort_string = "MADAB"
-
-/datum/design/item/medical/nanopaste
- desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery."
- id = "nanopaste"
- req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000)
- build_path = /obj/item/stack/nanopaste
- sort_string = "MBAAA"
-
-/datum/design/item/medical/scalpel_laser1
- name = "Basic Laser Scalpel"
- desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks basic and could be improved."
- id = "scalpel_laser1"
- req_tech = list(TECH_BIO = 2, TECH_MATERIAL = 2, TECH_MAGNET = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500)
- build_path = /obj/item/weapon/surgical/scalpel/laser1
- sort_string = "MBBAA"
-
-/datum/design/item/medical/scalpel_laser2
- name = "Improved Laser Scalpel"
- desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks somewhat advanced."
- id = "scalpel_laser2"
- req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 4, TECH_MAGNET = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500)
- build_path = /obj/item/weapon/surgical/scalpel/laser2
- sort_string = "MBBAB"
-
-/datum/design/item/medical/scalpel_laser3
- name = "Advanced Laser Scalpel"
- desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks to be the pinnacle of precision energy cutlery!"
- id = "scalpel_laser3"
- req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 6, TECH_MAGNET = 5)
- materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2000, "gold" = 1500)
- build_path = /obj/item/weapon/surgical/scalpel/laser3
- sort_string = "MBBAC"
-
-/datum/design/item/medical/scalpel_manager
- name = "Incision Management System"
- desc = "A true extension of the surgeon's body, this marvel instantly and completely prepares an incision allowing for the immediate commencement of therapeutic steps."
- id = "scalpel_manager"
- req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 7, TECH_MAGNET = 5, TECH_DATA = 4)
- materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 1500, "gold" = 1500, "diamond" = 750)
- build_path = /obj/item/weapon/surgical/scalpel/manager
- sort_string = "MBBAD"
-
-/datum/design/item/medical/bone_clamp
- name = "Bone Clamp"
- desc = "A miracle of modern science, this tool rapidly knits together bone, without the need for bone gel."
- id = "bone_clamp"
- req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_DATA = 4)
- materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500)
- build_path = /obj/item/weapon/surgical/bone_clamp
- sort_string = "MBBAE"
-
-/datum/design/item/medical/advanced_roller
- name = "advanced roller bed"
- desc = "A more advanced version of the regular roller bed, with inbuilt surgical stabilisers and an improved folding system."
- id = "roller_bed"
- req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 3, TECH_MAGNET = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 2000, "phoron" = 2000)
- build_path = /obj/item/roller/adv
- sort_string = "MBBAF"
-
-/datum/design/item/medical/improved_analyzer
- name = "improved health analyzer"
- desc = "A prototype version of the regular health analyzer, able to distinguish the location of more serious injuries as well as accurately determine radiation levels."
- id = "improved_analyzer"
- req_tech = list(TECH_MAGNET = 5, TECH_BIO = 6)
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 1500)
- build_path = /obj/item/device/healthanalyzer/improved
- sort_string = "MBBAG"
-
-/datum/design/item/implant
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
-
-/datum/design/item/implant/AssembleDesignName()
- ..()
- name = "Implantable biocircuit design ([item_name])"
-
-/datum/design/item/implant/chemical
- name = "chemical"
- id = "implant_chem"
- req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3)
- build_path = /obj/item/weapon/implantcase/chem
- sort_string = "MFAAA"
-
-/datum/design/item/implant/freedom
- name = "freedom"
- id = "implant_free"
- req_tech = list(TECH_ILLEGAL = 2, TECH_BIO = 3)
- build_path = /obj/item/weapon/implantcase/freedom
- sort_string = "MFAAB"
-
-/datum/design/item/weapon/AssembleDesignName()
- ..()
- name = "Weapon prototype ([item_name])"
-
-/datum/design/item/weapon/AssembleDesignDesc()
- if(!desc)
- if(build_path)
- var/obj/item/I = build_path
- desc = initial(I.desc)
- ..()
-
-/datum/design/item/weapon/stunrevolver
- id = "stunrevolver"
- req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_POWER = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 4000)
- build_path = /obj/item/weapon/gun/energy/stunrevolver
- sort_string = "TAAAA"
-
-/datum/design/item/weapon/nuclear_gun
- id = "nuclear_gun"
- req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 5, TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "uranium" = 500)
- build_path = /obj/item/weapon/gun/energy/gun/nuclear
- sort_string = "TAAAB"
-
-/datum/design/item/weapon/lasercannon
- desc = "The lasing medium of this prototype is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core."
- id = "lasercannon"
- req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 1000, "diamond" = 2000)
- build_path = /obj/item/weapon/gun/energy/lasercannon
- sort_string = "TAAAC"
-
-/datum/design/item/weapon/phoronpistol
- id = "ppistol"
- req_tech = list(TECH_COMBAT = 5, TECH_PHORON = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "phoron" = 3000)
- build_path = /obj/item/weapon/gun/energy/toxgun
- sort_string = "TAAAD"
-
-/datum/design/item/weapon/decloner
- id = "decloner"
- req_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 7, TECH_BIO = 5, TECH_POWER = 6)
- materials = list("gold" = 5000,"uranium" = 10000)
- build_path = /obj/item/weapon/gun/energy/decloner
- sort_string = "TAAAE"
-
-/datum/design/item/weapon/smg
- id = "smg"
- req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 8000, "silver" = 2000, "diamond" = 1000)
- build_path = /obj/item/weapon/gun/projectile/automatic
- sort_string = "TAABA"
-
-/datum/design/item/weapon/ammo_9mm
- id = "ammo_9mm"
- req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 3750, "silver" = 100)
- build_path = /obj/item/ammo_magazine/box/c9mm
- sort_string = "TAACA"
-
-/datum/design/item/weapon/stunshell
- desc = "A stunning shell for a shotgun."
- id = "stunshell"
- req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 4000)
- build_path = /obj/item/ammo_casing/a12g/stunshell
- sort_string = "TAACB"
-
-/datum/design/item/weapon/chemsprayer
- desc = "An advanced chem spraying device."
- id = "chemsprayer"
- req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000)
- build_path = /obj/item/weapon/reagent_containers/spray/chemsprayer
- sort_string = "TABAA"
-
-/datum/design/item/weapon/rapidsyringe
- id = "rapidsyringe"
- req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000)
- build_path = /obj/item/weapon/gun/launcher/syringe/rapid
- sort_string = "TABAB"
-
-/datum/design/item/weapon/temp_gun
- desc = "A gun that shoots high-powered glass-encased energy temperature bullets."
- id = "temp_gun"
- req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 500, "silver" = 3000)
- build_path = /obj/item/weapon/gun/energy/temperature
- sort_string = "TABAC"
-
-/datum/design/item/weapon/large_grenade
- id = "large_Grenade"
- req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 3000)
- build_path = /obj/item/weapon/grenade/chem_grenade/large
- sort_string = "TACAA"
-
-/datum/design/item/weapon/dartgun
- desc = "A gun that fires small hollow chemical-payload darts."
- id = "dartgun_r"
- req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_BIO = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "gold" = 5000, "silver" = 2500, "glass" = 750)
- build_path = /obj/item/weapon/gun/projectile/dartgun/research
- sort_string = "TACAB"
-
-/datum/design/item/weapon/dartgunmag_small
- id = "dartgun_mag_s"
- req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 300, "gold" = 100, "silver" = 100, "glass" = 300)
- build_path = /obj/item/ammo_magazine/chemdart/small
- sort_string = "TACAC"
-
-/datum/design/item/weapon/dartgun_ammo_small
- id = "dartgun_ammo_s"
- req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "gold" = 30, "silver" = 30, "glass" = 50)
- build_path = /obj/item/ammo_casing/chemdart/small
- sort_string = "TACAD"
-
-/datum/design/item/weapon/dartgunmag_med
- id = "dartgun_mag_m"
- req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 500, "gold" = 150, "silver" = 150, "diamond" = 200, "glass" = 400)
- build_path = /obj/item/ammo_magazine/chemdart
- sort_string = "TACAE"
-
-/datum/design/item/weapon/dartgun_ammo_med
- id = "dartgun_ammo_m"
- req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
- materials = list(DEFAULT_WALL_MATERIAL = 80, "gold" = 40, "silver" = 40, "glass" = 60)
- build_path = /obj/item/ammo_casing/chemdart
- sort_string = "TACAF"
-
-/datum/design/item/weapon/fuelrod
- id = "fuelrod_gun"
- req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_PHORON = 4, TECH_ILLEGAL = 5, TECH_MAGNET = 5)
- materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 2000, "gold" = 500, "silver" = 500, "uranium" = 1000, "phoron" = 3000, "diamond" = 1000)
- build_path = /obj/item/weapon/gun/magnetic/fuelrod
- sort_string = "TACBA"
-
-/datum/design/item/weapon/flora_gun
- id = "flora_gun"
- req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "uranium" = 500)
- build_path = /obj/item/weapon/gun/energy/floragun
- sort_string = "TBAAA"
-
-/datum/design/item/weapon/slimebation
- id = "slimebation"
- req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2, TECH_POWER = 3, TECH_COMBAT = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 5000)
- build_path = /obj/item/weapon/melee/baton/slime
- sort_string = "TBAAB"
-
-/datum/design/item/weapon/slimetaser
- id = "slimetaser"
- req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 3, TECH_POWER = 4, TECH_COMBAT = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 5000)
- build_path = /obj/item/weapon/gun/energy/taser/xeno
- sort_string = "TBAAC"
-
-/datum/design/item/stock_part/subspace_ansible
- id = "s-ansible"
- req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 80, "silver" = 20)
- build_path = /obj/item/weapon/stock_parts/subspace/ansible
- sort_string = "UAAAA"
-
-/datum/design/item/stock_part/hyperwave_filter
- id = "s-filter"
- req_tech = list(TECH_DATA = 3, TECH_MAGNET = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 40, "silver" = 10)
- build_path = /obj/item/weapon/stock_parts/subspace/sub_filter
- sort_string = "UAAAB"
-
-/datum/design/item/stock_part/subspace_amplifier
- id = "s-amplifier"
- req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 30, "uranium" = 15)
- build_path = /obj/item/weapon/stock_parts/subspace/amplifier
- sort_string = "UAAAC"
-
-/datum/design/item/stock_part/subspace_treatment
- id = "s-treatment"
- req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 10, "silver" = 20)
- build_path = /obj/item/weapon/stock_parts/subspace/treatment
- sort_string = "UAAAD"
-
-/datum/design/item/stock_part/subspace_analyzer
- id = "s-analyzer"
- req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 15)
- build_path = /obj/item/weapon/stock_parts/subspace/analyzer
- sort_string = "UAAAE"
-
-/datum/design/item/stock_part/subspace_crystal
- id = "s-crystal"
- req_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
- materials = list("glass" = 1000, "silver" = 20, "gold" = 20)
- build_path = /obj/item/weapon/stock_parts/subspace/crystal
- sort_string = "UAAAF"
-
-/datum/design/item/stock_part/subspace_transmitter
- id = "s-transmitter"
- req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3)
- materials = list("glass" = 100, "silver" = 10, "uranium" = 15)
- build_path = /obj/item/weapon/stock_parts/subspace/transmitter
- sort_string = "UAAAG"
-
-/datum/design/item/device/ano_scanner
- name = "Alden-Saraspova counter"
- id = "ano_scanner"
- desc = "Aids in triangulation of exotic particles."
- req_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 5000)
- build_path = /obj/item/device/ano_scanner
- sort_string = "UAAAH"
-
-/datum/design/item/light_replacer
- name = "Light replacer"
- desc = "A device to automatically replace lights. Refill with working lightbulbs."
- id = "light_replacer"
- req_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 1500, "silver" = 150, "glass" = 3000)
- build_path = /obj/item/device/lightreplacer
- sort_string = "VAAAH"
-
-datum/design/item/laserpointer
- name = "laser pointer"
- desc = "Don't shine it in your eyes!"
- id = "laser_pointer"
- req_tech = list(TECH_MAGNET = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 100, "glass" = 50)
- build_path = /obj/item/device/laser_pointer
- sort_string = "VAAAI"
-
-/datum/design/item/paicard
- name = "'pAI', personal artificial intelligence device"
- id = "paicard"
- req_tech = list(TECH_DATA = 2)
- materials = list("glass" = 500, DEFAULT_WALL_MATERIAL = 500)
- build_path = /obj/item/device/paicard
- sort_string = "VABAI"
-
-/datum/design/item/communicator
- name = "Communicator"
- id = "communicator"
- req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 500)
- build_path = /obj/item/device/communicator
- sort_string = "VABAJ"
-
-/datum/design/item/intellicard
- name = "'intelliCore', AI preservation and transportation system"
- desc = "Allows for the construction of an intelliCore."
- id = "intellicore"
- req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
- materials = list("glass" = 1000, "gold" = 200)
- build_path = /obj/item/device/aicard
- sort_string = "VACAA"
-
-/datum/design/item/dronebrain
- name = "Robotic intelligence circuit"
- id = "dronebrain"
- req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 5, TECH_DATA = 4)
- build_type = PROTOLATHE | PROSFAB
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500)
- build_path = /obj/item/device/mmi/digital/robot
- category = "Misc"
- sort_string = "VACAC"
-
-/datum/design/item/posibrain
- name = "Positronic brain"
- id = "posibrain"
- req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 6, TECH_BLUESPACE = 2, TECH_DATA = 4)
- build_type = PROTOLATHE | PROSFAB
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500, "phoron" = 500, "diamond" = 100)
- build_path = /obj/item/device/mmi/digital/posibrain
- category = "Misc"
- sort_string = "VACAB"
-
-/datum/design/item/mmi
- name = "Man-machine interface"
- id = "mmi"
- req_tech = list(TECH_DATA = 2, TECH_BIO = 3)
- build_type = PROTOLATHE | PROSFAB
- materials = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 500)
- build_path = /obj/item/device/mmi
- category = "Misc"
- sort_string = "VACBA"
-
-/datum/design/item/beacon
- name = "Bluespace tracking beacon design"
- id = "beacon"
- req_tech = list(TECH_BLUESPACE = 1)
- materials = list (DEFAULT_WALL_MATERIAL = 20, "glass" = 10)
- build_path = /obj/item/device/radio/beacon
- sort_string = "VADAA"
-
-/datum/design/item/gps
- name = "Triangulating device design"
- desc = "Triangulates approximate co-ordinates using a nearby satellite network."
- id = "gps"
- req_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 500)
- build_path = /obj/item/device/gps
- sort_string = "VADAB"
-
-/datum/design/item/beacon_locator
- name = "Beacon tracking pinpointer"
- desc = "Used to scan and locate signals on a particular frequency."
- id = "beacon_locator"
- req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 500)
- build_path = /obj/item/device/beacon_locator
- sort_string = "VADAC"
-
-/datum/design/item/bag_holding
- name = "'Bag of Holding', an infinite capacity bag prototype"
- desc = "Using localized pockets of bluespace this bag prototype offers incredible storage capacity with the contents weighting nothing. It's a shame the bag itself is pretty heavy."
- id = "bag_holding"
- req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6)
- materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250)
- build_path = /obj/item/weapon/storage/backpack/holding
- sort_string = "VAEAA"
-
-/datum/design/item/dufflebag_holding
- name = "'DuffleBag of Holding', an infinite capacity dufflebag prototype"
- desc = "A minaturized prototype of the popular Bag of Holding, the Dufflebag of Holding is, functionally, identical to the bag of holding, but comes in a more stylish and compact form."
- id = "dufflebag_holding"
- req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6)
- materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250)
- build_path = /obj/item/weapon/storage/backpack/holding/duffle
- sort_string = "VAEAB"
-
-/datum/design/item/binaryencrypt
- name = "Binary encryption key"
- desc = "Allows for deciphering the binary channel on-the-fly."
- id = "binaryencrypt"
- req_tech = list(TECH_ILLEGAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 300, "glass" = 300)
- build_path = /obj/item/device/encryptionkey/binary
- sort_string = "VASAA"
-
-/datum/design/item/chameleon
- name = "Holographic equipment kit"
- desc = "A kit of dangerous, high-tech equipment with changeable looks."
- id = "chameleon"
- req_tech = list(TECH_ILLEGAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 500)
- build_path = /obj/item/weapon/storage/box/syndie_kit/chameleon
- sort_string = "VASBA"
-
-/datum/design/item/experimental_welder
- name = "Experimental welding tool"
- desc = "A welding tool that generate fuel for itself."
- id = "expwelder"
- req_tech = list(TECH_ENGINEERING = 4, TECH_PHORON = 3, TECH_MATERIAL = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 70, "glass" = 120, "phoron" = 100)
- build_path = /obj/item/weapon/weldingtool/experimental
- sort_string = "VASCA"
-
-/datum/design/item/hand_drill
- name = "Hand drill"
- desc = "A simple powered hand drill."
- id = "handdrill"
- req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100)
- build_path = /obj/item/weapon/tool/screwdriver/power
- sort_string = "VASDA"
-
-/datum/design/item/jaws_life
- name = "Jaws of life"
- desc = "A set of jaws of life, compressed through the magic of science."
- id = "jawslife"
- req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100)
- build_path = /obj/item/weapon/tool/crowbar/power
- sort_string = "VASEA"
-
-/datum/design/item/device/t_scanner_upg
- name = "Upgraded T-ray Scanner"
- desc = "An upgraded version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
- id = "upgradedtscanner"
- req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 4, TECH_MATERIAL = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 500, "phoron" = 150)
- build_path = /obj/item/device/t_scanner/upgraded
- sort_string = "VASSA"
-
-
-/datum/design/item/device/t_scanner_adv
- name = "Advanced T-ray Scanner"
- desc = "An advanced version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
- id = "advancedtscanner"
- req_tech = list(TECH_MAGNET = 6, TECH_ENGINEERING = 6, TECH_MATERIAL = 6)
- materials = list(DEFAULT_WALL_MATERIAL = 1250, "phoron" = 500, "silver" = 50)
- build_path = /obj/item/device/t_scanner/advanced
- sort_string = "VASSB"
-/*
-CIRCUITS BELOW
-*/
-
-/datum/design/circuit
- build_type = IMPRINTER
- req_tech = list(TECH_DATA = 2)
- materials = list("glass" = 2000)
- chemicals = list("sacid" = 20)
- time = 5
-
-/datum/design/circuit/AssembleDesignName()
- ..()
- if(build_path)
- var/obj/item/weapon/circuitboard/C = build_path
- if(initial(C.board_type) == "machine")
- name = "Machine circuit design ([item_name])"
- else if(initial(C.board_type) == "computer")
- name = "Computer circuit design ([item_name])"
- else
- name = "Circuit design ([item_name])"
-
-/datum/design/circuit/AssembleDesignDesc()
- if(!desc)
- desc = "Allows for the construction of \a [item_name] circuit board."
-
-/datum/design/circuit/arcademachine
- name = "battle arcade machine"
- id = "arcademachine"
- req_tech = list(TECH_DATA = 1)
- build_path = /obj/item/weapon/circuitboard/arcade/battle
- sort_string = "MAAAA"
-
-/datum/design/circuit/oriontrail
- name = "orion trail arcade machine"
- id = "oriontrail"
- req_tech = list(TECH_DATA = 1)
- build_path = /obj/item/weapon/circuitboard/arcade/orion_trail
- sort_string = "MAAAA"
-
-/datum/design/circuit/jukebox
- name = "jukebox"
- id = "jukebox"
- req_tech = list(TECH_MAGNET = 2, TECH_DATA = 1)
- build_path = /obj/item/weapon/circuitboard/jukebox
- sort_string = "MAAAB"
-
-/datum/design/circuit/seccamera
- name = "security camera monitor"
- id = "seccamera"
- build_path = /obj/item/weapon/circuitboard/security
- sort_string = "DAAAA"
-
-/datum/design/circuit/secdata
- name = "security records console"
- id = "sec_data"
- build_path = /obj/item/weapon/circuitboard/secure_data
- sort_string = "DABAA"
-
-/datum/design/circuit/prisonmanage
- name = "prisoner management console"
- id = "prisonmanage"
- build_path = /obj/item/weapon/circuitboard/prisoner
- sort_string = "DACAA"
-
-/datum/design/circuit/med_data
- name = "medical records console"
- id = "med_data"
- build_path = /obj/item/weapon/circuitboard/med_data
- sort_string = "FAAAA"
-
-/datum/design/circuit/operating
- name = "patient monitoring console"
- id = "operating"
- build_path = /obj/item/weapon/circuitboard/operating
- sort_string = "FACAA"
-
-/datum/design/circuit/scan_console
- name = "DNA machine"
- id = "scan_console"
- build_path = /obj/item/weapon/circuitboard/scan_consolenew
- sort_string = "FAGAA"
-
-/datum/design/circuit/clonecontrol
- name = "cloning control console"
- id = "clonecontrol"
- req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
- build_path = /obj/item/weapon/circuitboard/cloning
- sort_string = "FAGAC"
-
-/datum/design/circuit/clonepod
- name = "clone pod"
- id = "clonepod"
- req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
- build_path = /obj/item/weapon/circuitboard/clonepod
- sort_string = "FAGAE"
-
-/datum/design/circuit/clonescanner
- name = "cloning scanner"
- id = "clonescanner"
- req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
- build_path = /obj/item/weapon/circuitboard/clonescanner
- sort_string = "FAGAG"
-
-/datum/design/circuit/crewconsole
- name = "crew monitoring console"
- id = "crewconsole"
- req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_BIO = 2)
- build_path = /obj/item/weapon/circuitboard/crew
- sort_string = "FAGAI"
-
-/datum/design/circuit/teleconsole
- name = "teleporter control console"
- id = "teleconsole"
- req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 2)
- build_path = /obj/item/weapon/circuitboard/teleporter
- sort_string = "HAAAA"
-
-/datum/design/circuit/robocontrol
- name = "robotics control console"
- id = "robocontrol"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/robotics
- sort_string = "HAAAB"
-
-/datum/design/circuit/mechacontrol
- name = "exosuit control console"
- id = "mechacontrol"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/circuitboard/mecha_control
- sort_string = "HAAAC"
-
-/datum/design/circuit/rdconsole
- name = "R&D control console"
- id = "rdconsole"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/rdconsole
- sort_string = "HAAAE"
-
-/datum/design/circuit/aifixer
- name = "AI integrity restorer"
- id = "aifixer"
- req_tech = list(TECH_DATA = 3, TECH_BIO = 2)
- build_path = /obj/item/weapon/circuitboard/aifixer
- sort_string = "HAAAF"
-
-/datum/design/circuit/comm_monitor
- name = "telecommunications monitoring console"
- id = "comm_monitor"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/circuitboard/comm_monitor
- sort_string = "HAACA"
-
-/datum/design/circuit/comm_server
- name = "telecommunications server monitoring console"
- id = "comm_server"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/circuitboard/comm_server
- sort_string = "HAACB"
-
-/datum/design/circuit/message_monitor
- name = "messaging monitor console"
- id = "message_monitor"
- req_tech = list(TECH_DATA = 5)
- build_path = /obj/item/weapon/circuitboard/message_monitor
- sort_string = "HAACC"
-
-/datum/design/circuit/aiupload
- name = "AI upload console"
- id = "aiupload"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/aiupload
- sort_string = "HAABA"
-
-/datum/design/circuit/borgupload
- name = "cyborg upload console"
- id = "borgupload"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/borgupload
- sort_string = "HAABB"
-
-/datum/design/circuit/destructive_analyzer
- name = "destructive analyzer"
- id = "destructive_analyzer"
- req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/destructive_analyzer
- sort_string = "HABAA"
-
-/datum/design/circuit/protolathe
- name = "protolathe"
- id = "protolathe"
- req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/protolathe
- sort_string = "HABAB"
-
-/datum/design/circuit/circuit_imprinter
- name = "circuit imprinter"
- id = "circuit_imprinter"
- req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/circuit_imprinter
- sort_string = "HABAC"
-
-/datum/design/circuit/autolathe
- name = "autolathe board"
- id = "autolathe"
- req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/autolathe
- sort_string = "HABAD"
-
-/datum/design/circuit/rdservercontrol
- name = "R&D server control console"
- id = "rdservercontrol"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/circuitboard/rdservercontrol
- sort_string = "HABBA"
-
-/datum/design/circuit/rdserver
- name = "R&D server"
- id = "rdserver"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/circuitboard/rdserver
- sort_string = "HABBB"
-
-/datum/design/circuit/mechfab
- name = "exosuit fabricator"
- id = "mechfab"
- req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
- build_path = /obj/item/weapon/circuitboard/mechfab
- sort_string = "HABAE"
-
-/datum/design/circuit/prosfab
- name = "prosthetics fabricator"
- id = "prosfab"
- req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
- build_path = /obj/item/weapon/circuitboard/prosthetics
- sort_string = "HABAF"
-
-/datum/design/circuit/mech_recharger
- name = "mech recharger"
- id = "mech_recharger"
- req_tech = list(TECH_DATA = 2, TECH_POWER = 2, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/mech_recharger
- sort_string = "HACAA"
-
-/datum/design/circuit/recharge_station
- name = "cyborg recharge station"
- id = "recharge_station"
- req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/recharge_station
- sort_string = "HACAC"
-
-/datum/design/circuit/atmosalerts
- name = "atmosphere alert console"
- id = "atmosalerts"
- build_path = /obj/item/weapon/circuitboard/atmos_alert
- sort_string = "JAAAA"
-
-/datum/design/circuit/air_management
- name = "atmosphere monitoring console"
- id = "air_management"
- build_path = /obj/item/weapon/circuitboard/air_management
- sort_string = "JAAAB"
-
-/datum/design/circuit/rcon_console
- name = "RCON remote control console"
- id = "rcon_console"
- req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_POWER = 5)
- build_path = /obj/item/weapon/circuitboard/rcon_console
- sort_string = "JAAAC"
-
-/datum/design/circuit/dronecontrol
- name = "drone control console"
- id = "dronecontrol"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/drone_control
- sort_string = "JAAAD"
-
-/datum/design/circuit/powermonitor
- name = "power monitoring console"
- id = "powermonitor"
- build_path = /obj/item/weapon/circuitboard/powermonitor
- sort_string = "JAAAE"
-
-/datum/design/circuit/solarcontrol
- name = "solar control console"
- id = "solarcontrol"
- build_path = /obj/item/weapon/circuitboard/solar_control
- sort_string = "JAAAF"
-
-/datum/design/circuit/pacman
- name = "PACMAN-type generator"
- id = "pacman"
- req_tech = list(TECH_DATA = 3, TECH_PHORON = 3, TECH_POWER = 3, TECH_ENGINEERING = 3)
- build_path = /obj/item/weapon/circuitboard/pacman
- sort_string = "JBAAA"
-
-/datum/design/circuit/superpacman
- name = "SUPERPACMAN-type generator"
- id = "superpacman"
- req_tech = list(TECH_DATA = 3, TECH_POWER = 4, TECH_ENGINEERING = 4)
- build_path = /obj/item/weapon/circuitboard/pacman/super
- sort_string = "JBAAB"
-
-/datum/design/circuit/mrspacman
- name = "MRSPACMAN-type generator"
- id = "mrspacman"
- req_tech = list(TECH_DATA = 3, TECH_POWER = 5, TECH_ENGINEERING = 5)
- build_path = /obj/item/weapon/circuitboard/pacman/mrs
- sort_string = "JBAAC"
-
-/datum/design/circuit/batteryrack
- name = "cell rack PSU"
- id = "batteryrack"
- req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/batteryrack
- sort_string = "JBABA"
-
-/datum/design/circuit/smes_cell
- name = "'SMES' superconductive magnetic energy storage"
- desc = "Allows for the construction of circuit boards used to build a SMES."
- id = "smes_cell"
- req_tech = list(TECH_POWER = 7, TECH_ENGINEERING = 5)
- build_path = /obj/item/weapon/circuitboard/smes
- sort_string = "JBABB"
-
-/datum/design/circuit/grid_checker
- name = "power grid checker"
- desc = "Allows for the construction of circuit boards used to build a grid checker."
- id = "grid_checker"
- req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3)
- build_path = /obj/item/weapon/circuitboard/grid_checker
- sort_string = "JBABC"
-
-/datum/design/circuit/breakerbox
- name = "breaker box"
- desc = "Allows for the construction of circuit boards used to build a breaker box."
- id = "breakerbox"
- req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3)
- build_path = /obj/item/weapon/circuitboard/breakerbox
- sort_string = "JBABD"
-
-/datum/design/circuit/gas_heater
- name = "gas heating system"
- id = "gasheater"
- req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 1)
- build_path = /obj/item/weapon/circuitboard/unary_atmos/heater
- sort_string = "JCAAA"
-
-/datum/design/circuit/gas_cooler
- name = "gas cooling system"
- id = "gascooler"
- req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2)
- build_path = /obj/item/weapon/circuitboard/unary_atmos/cooler
- sort_string = "JCAAB"
-
-/datum/design/circuit/secure_airlock
- name = "secure airlock electronics"
- desc = "Allows for the construction of a tamper-resistant airlock electronics."
- id = "securedoor"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/airlock_electronics/secure
- sort_string = "JDAAA"
-
-/datum/design/circuit/ordercomp
- name = "supply ordering console"
- id = "ordercomp"
- build_path = /obj/item/weapon/circuitboard/ordercomp
- sort_string = "KAAAA"
-
-/datum/design/circuit/supplycomp
- name = "supply control console"
- id = "supplycomp"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/circuitboard/supplycomp
- sort_string = "KAAAB"
-
-/datum/design/circuit/biogenerator
- name = "biogenerator"
- id = "biogenerator"
- req_tech = list(TECH_DATA = 2)
- build_path = /obj/item/weapon/circuitboard/biogenerator
- sort_string = "KBAAA"
-
-/datum/design/circuit/miningdrill
- name = "mining drill head"
- id = "mining drill head"
- req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
- build_path = /obj/item/weapon/circuitboard/miningdrill
- sort_string = "KCAAA"
-
-/datum/design/circuit/miningdrillbrace
- name = "mining drill brace"
- id = "mining drill brace"
- req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
- build_path = /obj/item/weapon/circuitboard/miningdrillbrace
- sort_string = "KCAAB"
-
-/datum/design/circuit/comconsole
- name = "communications console"
- id = "comconsole"
- build_path = /obj/item/weapon/circuitboard/communications
- sort_string = "LAAAA"
-
-/datum/design/circuit/idcardconsole
- name = "ID card modification console"
- id = "idcardconsole"
- build_path = /obj/item/weapon/circuitboard/card
- sort_string = "LAAAB"
-
-/datum/design/circuit/emp_data
- name = "employment records console"
- id = "emp_data"
- build_path = /obj/item/weapon/circuitboard/skills
- sort_string = "LAAAC"
-
-/datum/design/circuit/mecha
- req_tech = list(TECH_DATA = 3)
-
-/datum/design/circuit/mecha/AssembleDesignName()
- name = "Exosuit module circuit design ([name])"
-/datum/design/circuit/mecha/AssembleDesignDesc()
- desc = "Allows for the construction of \a [name] module."
-
-/datum/design/circuit/mecha/ripley_main
- name = "APLU 'Ripley' central control"
- id = "ripley_main"
- build_path = /obj/item/weapon/circuitboard/mecha/ripley/main
- sort_string = "NAAAA"
-
-/datum/design/circuit/mecha/ripley_peri
- name = "APLU 'Ripley' peripherals control"
- id = "ripley_peri"
- build_path = /obj/item/weapon/circuitboard/mecha/ripley/peripherals
- sort_string = "NAAAB"
-
-/datum/design/circuit/mecha/odysseus_main
- name = "'Odysseus' central control"
- id = "odysseus_main"
- req_tech = list(TECH_DATA = 3,TECH_BIO = 2)
- build_path = /obj/item/weapon/circuitboard/mecha/odysseus/main
- sort_string = "NAABA"
-
-/datum/design/circuit/mecha/odysseus_peri
- name = "'Odysseus' peripherals control"
- id = "odysseus_peri"
- req_tech = list(TECH_DATA = 3,TECH_BIO = 2)
- build_path = /obj/item/weapon/circuitboard/mecha/odysseus/peripherals
- sort_string = "NAABB"
-
-/datum/design/circuit/mecha/gygax_main
- name = "'Gygax' central control"
- id = "gygax_main"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/mecha/gygax/main
- sort_string = "NAACA"
-
-/datum/design/circuit/mecha/gygax_peri
- name = "'Gygax' peripherals control"
- id = "gygax_peri"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/mecha/gygax/peripherals
- sort_string = "NAACB"
-
-/datum/design/circuit/mecha/gygax_targ
- name = "'Gygax' weapon control and targeting"
- id = "gygax_targ"
- req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2)
- build_path = /obj/item/weapon/circuitboard/mecha/gygax/targeting
- sort_string = "NAACC"
-
-/datum/design/circuit/mecha/durand_main
- name = "'Durand' central control"
- id = "durand_main"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/mecha/durand/main
- sort_string = "NAADA"
-
-/datum/design/circuit/mecha/durand_peri
- name = "'Durand' peripherals control"
- id = "durand_peri"
- req_tech = list(TECH_DATA = 4)
- build_path = /obj/item/weapon/circuitboard/mecha/durand/peripherals
- sort_string = "NAADB"
-
-/datum/design/circuit/mecha/durand_targ
- name = "'Durand' weapon control and targeting"
- id = "durand_targ"
- req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2)
- build_path = /obj/item/weapon/circuitboard/mecha/durand/targeting
- sort_string = "NAADC"
-
-/datum/design/circuit/tcom
- req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
-
-/datum/design/circuit/tcom/AssembleDesignName()
- name = "Telecommunications machinery circuit design ([name])"
-/datum/design/circuit/tcom/AssembleDesignDesc()
- desc = "Allows for the construction of a telecommunications [name] circuit board."
-
-/datum/design/circuit/tcom/server
- name = "server mainframe"
- id = "tcom-server"
- build_path = /obj/item/weapon/circuitboard/telecomms/server
- sort_string = "PAAAA"
-
-/datum/design/circuit/tcom/processor
- name = "processor unit"
- id = "tcom-processor"
- build_path = /obj/item/weapon/circuitboard/telecomms/processor
- sort_string = "PAAAB"
-
-/datum/design/circuit/tcom/bus
- name = "bus mainframe"
- id = "tcom-bus"
- build_path = /obj/item/weapon/circuitboard/telecomms/bus
- sort_string = "PAAAC"
-
-/datum/design/circuit/tcom/hub
- name = "hub mainframe"
- id = "tcom-hub"
- build_path = /obj/item/weapon/circuitboard/telecomms/hub
- sort_string = "PAAAD"
-
-/datum/design/circuit/tcom/relay
- name = "relay mainframe"
- id = "tcom-relay"
- req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 4, TECH_BLUESPACE = 3)
- build_path = /obj/item/weapon/circuitboard/telecomms/relay
- sort_string = "PAAAE"
-
-/datum/design/circuit/tcom/broadcaster
- name = "subspace broadcaster"
- id = "tcom-broadcaster"
- req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_BLUESPACE = 2)
- build_path = /obj/item/weapon/circuitboard/telecomms/broadcaster
- sort_string = "PAAAF"
-
-/datum/design/circuit/tcom/receiver
- name = "subspace receiver"
- id = "tcom-receiver"
- req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_BLUESPACE = 2)
- build_path = /obj/item/weapon/circuitboard/telecomms/receiver
- sort_string = "PAAAG"
-
-/datum/design/circuit/tcom/exonet_node
- name = "exonet node"
- id = "tcom-exonet_node"
- req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5, TECH_BLUESPACE = 4)
- build_path = /obj/item/weapon/circuitboard/telecomms/exonet_node
- sort_string = "PAAAH"
-
-/datum/design/circuit/shield
- req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3)
- materials = list("glass" = 2000, "gold" = 1000)
-
-/datum/design/circuit/shield/AssembleDesignName()
- name = "Shield generator circuit design ([name])"
-/datum/design/circuit/shield/AssembleDesignDesc()
- if(!desc)
- desc = "Allows for the construction of \a [name] shield generator."
-
-/datum/design/circuit/shield/bubble
- name = "bubble"
- id = "shield_gen"
- build_path = /obj/item/weapon/circuitboard/shield_gen
- sort_string = "VAAAA"
-
-/datum/design/circuit/shield/hull
- name = "hull"
- id = "shield_gen_ex"
- build_path = /obj/item/weapon/circuitboard/shield_gen_ex
- sort_string = "VAAAB"
-
-/datum/design/circuit/shield/capacitor
- name = "capacitor"
- desc = "Allows for the construction of a shield capacitor circuit board."
- id = "shield_cap"
- req_tech = list(TECH_MAGNET = 3, TECH_POWER = 4)
- build_path = /obj/item/weapon/circuitboard/shield_cap
- sort_string = "VAAAC"
-
-/datum/design/circuit/aicore
- name = "AI core"
- id = "aicore"
- req_tech = list(TECH_DATA = 4, TECH_BIO = 3)
- build_path = /obj/item/weapon/circuitboard/aicore
- sort_string = "XAAAA"
-
-/datum/design/aimodule
- build_type = IMPRINTER
- materials = list("glass" = 2000, "gold" = 100)
-
-/datum/design/aimodule/AssembleDesignName()
- name = "AI module design ([name])"
-
-/datum/design/aimodule/AssembleDesignDesc()
- desc = "Allows for the construction of \a '[name]' AI module."
-
-/datum/design/aimodule/safeguard
- name = "Safeguard"
- id = "safeguard"
- req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
- build_path = /obj/item/weapon/aiModule/safeguard
- sort_string = "XABAA"
-
-/datum/design/aimodule/onehuman
- name = "OneCrewMember"
- id = "onehuman"
- req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6)
- build_path = /obj/item/weapon/aiModule/oneHuman
- sort_string = "XABAB"
-
-/datum/design/aimodule/protectstation
- name = "ProtectStation"
- id = "protectstation"
- req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
- build_path = /obj/item/weapon/aiModule/protectStation
- sort_string = "XABAC"
-
-/datum/design/aimodule/notele
- name = "TeleporterOffline"
- id = "notele"
- req_tech = list(TECH_DATA = 3)
- build_path = /obj/item/weapon/aiModule/teleporterOffline
- sort_string = "XABAD"
-
-/datum/design/aimodule/quarantine
- name = "Quarantine"
- id = "quarantine"
- req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
- build_path = /obj/item/weapon/aiModule/quarantine
- sort_string = "XABAE"
-
-/datum/design/aimodule/oxygen
- name = "OxygenIsToxicToHumans"
- id = "oxygen"
- req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
- build_path = /obj/item/weapon/aiModule/oxygen
- sort_string = "XABAF"
-
-/datum/design/aimodule/freeform
- name = "Freeform"
- id = "freeform"
- req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
- build_path = /obj/item/weapon/aiModule/freeform
- sort_string = "XABAG"
-
-/datum/design/aimodule/reset
- name = "Reset"
- id = "reset"
- req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
- build_path = /obj/item/weapon/aiModule/reset
- sort_string = "XAAAA"
-
-/datum/design/aimodule/purge
- name = "Purge"
- id = "purge"
- req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6)
- build_path = /obj/item/weapon/aiModule/purge
- sort_string = "XAAAB"
-
-// Core modules
-/datum/design/aimodule/core
- req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6)
-
-/datum/design/aimodule/core/AssembleDesignName()
- name = "AI core module design ([name])"
-
-/datum/design/aimodule/core/AssembleDesignDesc()
- desc = "Allows for the construction of \a '[name]' AI core module."
-
-/datum/design/aimodule/core/freeformcore
- name = "Freeform"
- id = "freeformcore"
- build_path = /obj/item/weapon/aiModule/freeformcore
- sort_string = "XACAA"
-
-/datum/design/aimodule/core/asimov
- name = "Asimov"
- id = "asimov"
- build_path = /obj/item/weapon/aiModule/asimov
- sort_string = "XACAB"
-
-/datum/design/aimodule/core/paladin
- name = "P.A.L.A.D.I.N."
- id = "paladin"
- build_path = /obj/item/weapon/aiModule/paladin
- sort_string = "XACAC"
-
-/datum/design/aimodule/core/tyrant
- name = "T.Y.R.A.N.T."
- id = "tyrant"
- req_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 2, TECH_MATERIAL = 6)
- build_path = /obj/item/weapon/aiModule/tyrant
- sort_string = "XACAD"
-
-/datum/design/item/pda
- name = "PDA design"
- desc = "Cheaper than whiny non-digital assistants."
- id = "pda"
- req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
- build_path = /obj/item/device/pda
- sort_string = "VAAAA"
-
-// Cartridges
-/datum/design/item/pda_cartridge
- req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
-
-/datum/design/item/pda_cartridge/AssembleDesignName()
- ..()
- name = "PDA accessory ([item_name])"
-
-/datum/design/item/pda_cartridge/cart_basic
- id = "cart_basic"
- build_path = /obj/item/weapon/cartridge
- sort_string = "VBAAA"
-
-/datum/design/item/pda_cartridge/engineering
- id = "cart_engineering"
- build_path = /obj/item/weapon/cartridge/engineering
- sort_string = "VBAAB"
-
-/datum/design/item/pda_cartridge/atmos
- id = "cart_atmos"
- build_path = /obj/item/weapon/cartridge/atmos
- sort_string = "VBAAC"
-
-/datum/design/item/pda_cartridge/medical
- id = "cart_medical"
- build_path = /obj/item/weapon/cartridge/medical
- sort_string = "VBAAD"
-
-/datum/design/item/pda_cartridge/chemistry
- id = "cart_chemistry"
- build_path = /obj/item/weapon/cartridge/chemistry
- sort_string = "VBAAE"
-
-/datum/design/item/pda_cartridge/security
- id = "cart_security"
- build_path = /obj/item/weapon/cartridge/security
- sort_string = "VBAAF"
-
-/datum/design/item/pda_cartridge/janitor
- id = "cart_janitor"
- build_path = /obj/item/weapon/cartridge/janitor
- sort_string = "VBAAG"
-
-/datum/design/item/pda_cartridge/science
- id = "cart_science"
- build_path = /obj/item/weapon/cartridge/signal/science
- sort_string = "VBAAH"
-
-/datum/design/item/pda_cartridge/quartermaster
- id = "cart_quartermaster"
- build_path = /obj/item/weapon/cartridge/quartermaster
- sort_string = "VBAAI"
-
-/datum/design/item/pda_cartridge/hop
- id = "cart_hop"
- build_path = /obj/item/weapon/cartridge/hop
- sort_string = "VBAAJ"
-
-/datum/design/item/pda_cartridge/hos
- id = "cart_hos"
- build_path = /obj/item/weapon/cartridge/hos
- sort_string = "VBAAK"
-
-/datum/design/item/pda_cartridge/ce
- id = "cart_ce"
- build_path = /obj/item/weapon/cartridge/ce
- sort_string = "VBAAL"
-
-/datum/design/item/pda_cartridge/cmo
- id = "cart_cmo"
- build_path = /obj/item/weapon/cartridge/cmo
- sort_string = "VBAAM"
-
-/datum/design/item/pda_cartridge/rd
- id = "cart_rd"
- build_path = /obj/item/weapon/cartridge/rd
- sort_string = "VBAAN"
-
-/datum/design/item/pda_cartridge/captain
- id = "cart_captain"
- build_path = /obj/item/weapon/cartridge/captain
- sort_string = "VBAAO"
-
-
-
-/datum/design/item/wirer
- name = "Custom wirer tool"
- id = "wirer"
- req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
- build_path = /obj/item/device/integrated_electronics/wirer
- sort_string = "VBVAA"
-
-/datum/design/item/debugger
- name = "Custom circuit debugger tool"
- id = "debugger"
- req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
- build_path = /obj/item/device/integrated_electronics/debugger
- sort_string = "VBVAB"
-
-
-
-/datum/design/item/custom_circuit_assembly
- name = "Small custom assembly"
- desc = "A customizable assembly for simple, small devices."
- id = "assembly-small"
- req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 10000)
- build_path = /obj/item/device/electronic_assembly
- sort_string = "VCAAA"
-
-/datum/design/item/custom_circuit_assembly/medium
- name = "Medium custom assembly"
- desc = "A customizable assembly suited for more ambitious mechanisms."
- id = "assembly-medium"
- req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 20000)
- build_path = /obj/item/device/electronic_assembly/medium
- sort_string = "VCAAB"
-
-/datum/design/item/custom_circuit_assembly/drone
- name = "Drone custom assembly"
- desc = "A customizable assembly optimized for autonomous devices."
- id = "assembly-drone"
- req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 30000)
- build_path = /obj/item/device/electronic_assembly/drone
- sort_string = "VCAAC"
-
-/datum/design/item/custom_circuit_assembly/large
- name = "Large custom assembly"
- desc = "A customizable assembly for large machines."
- id = "assembly-large"
- req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 40000)
- build_path = /obj/item/device/electronic_assembly/large
- sort_string = "VCAAD"
-
-/datum/design/item/custom_circuit_assembly/implant
- name = "Implant custom assembly"
- desc = "An customizable assembly for very small devices, implanted into living entities."
- id = "assembly-implant"
- req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5)
- materials = list(DEFAULT_WALL_MATERIAL = 2000)
- build_path = /obj/item/weapon/implant/integrated_circuit
- sort_string = "VCAAE"
-
-/datum/design/item/custom_circuit_assembly/device
- name = "Device custom assembly"
- desc = "An customizable assembly designed to interface with other devices."
- id = "assembly-device"
- req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2)
- materials = list(DEFAULT_WALL_MATERIAL = 5000)
- build_path = /obj/item/device/assembly/electronic_assembly
- sort_string = "VCAAF"
-
-/datum/design/item/custom_circuit_printer
- name = "Portable integrated circuit printer"
- desc = "A portable(ish) printer for modular machines."
- id = "ic_printer"
- req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5)
- materials = list(DEFAULT_WALL_MATERIAL = 10000)
- build_path = /obj/item/device/integrated_circuit_printer
- sort_string = "VCAAG"
-
-/datum/design/item/custom_circuit_printer_upgrade
- name = "Integrated circuit printer upgrade - advanced designs"
- desc = "Allows the integrated circuit printer to create advanced circuits"
- id = "ic_printer_upgrade_adv"
- req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
- materials = list(DEFAULT_WALL_MATERIAL = 2000)
- build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced
- sort_string = "VCAAH"
-
-/datum/design/item/translator
- name = "handheld translator"
- id = "translator"
- req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 3000)
- build_path = /obj/item/device/universal_translator
- sort_string = "HABQA"
-
-/datum/design/item/ear_translator
- name = "earpiece translator"
- id = "ear_translator"
- req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5) //It's been hella miniaturized.
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 2000, "gold" = 1000)
- build_path = /obj/item/device/universal_translator/ear
- sort_string = "HABQB"
-
-/datum/design/item/xenoarch_multi_tool
- name = "xenoarcheology multitool"
- id = "xenoarch_multitool"
- req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 3)
- build_path = /obj/item/device/xenoarch_multi_tool
- materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "uranium" = 500, "phoron" = 500)
- sort_string = "HABQC"
-
-/datum/design/item/excavationdrill
- name = "Excavation Drill"
- id = "excavationdrill"
- req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3)
- build_type = PROTOLATHE
- materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 4000)
- build_path = /obj/item/weapon/pickaxe/excavationdrill
- sort_string = "HABQD"
-
-/* Uncomment if someone makes these buildable
-/datum/design/circuit/general_alert
- name = "general alert console"
- id = "general_alert"
- build_path = /obj/item/weapon/circuitboard/general_alert
-
-// Removal of loyalty implants. Can't think of a way to add this to the config option.
-/datum/design/item/implant/loyalty
- name = "loyalty"
- id = "implant_loyal"
- req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3)
- materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000)
- build_path = /obj/item/weapon/implantcase/loyalty"
-
-/datum/design/rust_core_control
- name = "Circuit Design (RUST core controller)"
- desc = "Allows for the construction of circuit boards used to build a core control console for the RUST fusion engine."
- id = "rust_core_control"
- req_tech = list("programming" = 4, "engineering" = 4)
- build_type = IMPRINTER
- materials = list("glass" = 2000, "sacid" = 20)
- build_path = "/obj/item/weapon/circuitboard/rust_core_control"
-
-datum/design/rust_fuel_control
- name = "Circuit Design (RUST fuel controller)"
- desc = "Allows for the construction of circuit boards used to build a fuel injector control console for the RUST fusion engine."
- id = "rust_fuel_control"
- req_tech = list("programming" = 4, "engineering" = 4)
- build_type = IMPRINTER
- materials = list("glass" = 2000, "sacid" = 20)
- build_path = "/obj/item/weapon/circuitboard/rust_fuel_control"
-
-datum/design/rust_fuel_port
- name = "Internal circuitry (RUST fuel port)"
- desc = "Allows for the construction of circuit boards used to build a fuel injection port for the RUST fusion engine."
- id = "rust_fuel_port"
- req_tech = list("engineering" = 4, "materials" = 5)
- build_type = IMPRINTER
- materials = list("glass" = 2000, "sacid" = 20, "uranium" = 3000)
- build_path = "/obj/item/weapon/module/rust_fuel_port"
-
-datum/design/rust_fuel_compressor
- name = "Circuit Design (RUST fuel compressor)"
- desc = "Allows for the construction of circuit boards used to build a fuel compressor of the RUST fusion engine."
- id = "rust_fuel_compressor"
- req_tech = list("materials" = 6, "phorontech" = 4)
- build_type = IMPRINTER
- materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 1000)
- build_path = "/obj/item/weapon/module/rust_fuel_compressor"
-
-datum/design/rust_core
- name = "Internal circuitry (RUST tokamak core)"
- desc = "The circuit board that for a RUST-pattern tokamak fusion core."
- id = "pacman"
- req_tech = list(bluespace = 3, phorontech = 4, magnets = 5, powerstorage = 6)
- build_type = IMPRINTER
- materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 2000)
- build_path = "/obj/item/weapon/circuitboard/rust_core"
-
-datum/design/rust_injector
- name = "Internal circuitry (RUST tokamak core)"
- desc = "The circuit board that for a RUST-pattern particle accelerator."
- id = "pacman"
- req_tech = list(powerstorage = 3, engineering = 4, phorontech = 4, materials = 6)
- build_type = IMPRINTER
- materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "uranium" = 2000)
- build_path = "/obj/item/weapon/circuitboard/rust_core"
-*/
+ sort_string = "GAAAB"
\ No newline at end of file
diff --git a/code/modules/research/designs/ai_modules.dm b/code/modules/research/designs/ai_modules.dm
new file mode 100644
index 00000000000..eae26ea3865
--- /dev/null
+++ b/code/modules/research/designs/ai_modules.dm
@@ -0,0 +1,117 @@
+/datum/design/aimodule
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "gold" = 100)
+
+/datum/design/aimodule/AssembleDesignName()
+ name = "AI module design ([name])"
+
+/datum/design/aimodule/AssembleDesignDesc()
+ desc = "Allows for the construction of \a '[name]' AI module."
+
+/datum/design/aimodule/safeguard
+ name = "Safeguard"
+ id = "safeguard"
+ req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
+ build_path = /obj/item/weapon/aiModule/safeguard
+ sort_string = "XABAA"
+
+/datum/design/aimodule/onehuman
+ name = "OneCrewMember"
+ id = "onehuman"
+ req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6)
+ build_path = /obj/item/weapon/aiModule/oneHuman
+ sort_string = "XABAB"
+
+/datum/design/aimodule/protectstation
+ name = "ProtectStation"
+ id = "protectstation"
+ req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
+ build_path = /obj/item/weapon/aiModule/protectStation
+ sort_string = "XABAC"
+
+/datum/design/aimodule/notele
+ name = "TeleporterOffline"
+ id = "notele"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/aiModule/teleporterOffline
+ sort_string = "XABAD"
+
+/datum/design/aimodule/quarantine
+ name = "Quarantine"
+ id = "quarantine"
+ req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
+ build_path = /obj/item/weapon/aiModule/quarantine
+ sort_string = "XABAE"
+
+/datum/design/aimodule/oxygen
+ name = "OxygenIsToxicToHumans"
+ id = "oxygen"
+ req_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
+ build_path = /obj/item/weapon/aiModule/oxygen
+ sort_string = "XABAF"
+
+/datum/design/aimodule/freeform
+ name = "Freeform"
+ id = "freeform"
+ req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
+ build_path = /obj/item/weapon/aiModule/freeform
+ sort_string = "XABAG"
+
+/datum/design/aimodule/reset
+ name = "Reset"
+ id = "reset"
+ req_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
+ build_path = /obj/item/weapon/aiModule/reset
+ sort_string = "XAAAZ" // Duplicate string, really need to redo this whole thing
+
+/datum/design/aimodule/purge
+ name = "Purge"
+ id = "purge"
+ req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6)
+ build_path = /obj/item/weapon/aiModule/purge
+ sort_string = "XAAAB"
+
+// Core modules
+/datum/design/aimodule/core
+ req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 6)
+
+/datum/design/aimodule/core/AssembleDesignName()
+ name = "AI core module design ([name])"
+
+/datum/design/aimodule/core/AssembleDesignDesc()
+ desc = "Allows for the construction of \a '[name]' AI core module."
+
+/datum/design/aimodule/core/freeformcore
+ name = "Freeform"
+ id = "freeformcore"
+ build_path = /obj/item/weapon/aiModule/freeformcore
+ sort_string = "XACAA"
+
+/datum/design/aimodule/core/asimov
+ name = "Asimov"
+ id = "asimov"
+ build_path = /obj/item/weapon/aiModule/asimov
+ sort_string = "XACAB"
+
+/datum/design/aimodule/core/paladin
+ name = "P.A.L.A.D.I.N."
+ id = "paladin"
+ build_path = /obj/item/weapon/aiModule/paladin
+ sort_string = "XACAC"
+
+/datum/design/aimodule/core/tyrant
+ name = "T.Y.R.A.N.T."
+ id = "tyrant"
+ req_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 2, TECH_MATERIAL = 6)
+ build_path = /obj/item/weapon/aiModule/tyrant
+ sort_string = "XACAD"
+
+// AI file, AI tool
+/datum/design/item/intellicard
+ name = "'intelliCore', AI preservation and transportation system"
+ desc = "Allows for the construction of an intelliCore."
+ id = "intellicore"
+ req_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
+ materials = list("glass" = 1000, "gold" = 200)
+ build_path = /obj/item/device/aicard
+ sort_string = "VACAA"
\ No newline at end of file
diff --git a/code/modules/research/designs/circuit_assembly.dm b/code/modules/research/designs/circuit_assembly.dm
new file mode 100644
index 00000000000..9f20032445c
--- /dev/null
+++ b/code/modules/research/designs/circuit_assembly.dm
@@ -0,0 +1,89 @@
+/datum/design/item/wirer
+ name = "Custom wirer tool"
+ id = "wirer"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
+ build_path = /obj/item/device/integrated_electronics/wirer
+ sort_string = "VBVAA"
+
+/datum/design/item/debugger
+ name = "Custom circuit debugger tool"
+ id = "debugger"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 2500)
+ build_path = /obj/item/device/integrated_electronics/debugger
+ sort_string = "VBVAB"
+
+
+
+/datum/design/item/custom_circuit_assembly
+ name = "Small custom assembly"
+ desc = "A customizable assembly for simple, small devices."
+ id = "assembly-small"
+ req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/device/electronic_assembly
+ sort_string = "VCAAA"
+
+/datum/design/item/custom_circuit_assembly/medium
+ name = "Medium custom assembly"
+ desc = "A customizable assembly suited for more ambitious mechanisms."
+ id = "assembly-medium"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 20000)
+ build_path = /obj/item/device/electronic_assembly/medium
+ sort_string = "VCAAB"
+
+/datum/design/item/custom_circuit_assembly/drone
+ name = "Drone custom assembly"
+ desc = "A customizable assembly optimized for autonomous devices."
+ id = "assembly-drone"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 30000)
+ build_path = /obj/item/device/electronic_assembly/drone
+ sort_string = "VCAAC"
+
+/datum/design/item/custom_circuit_assembly/large
+ name = "Large custom assembly"
+ desc = "A customizable assembly for large machines."
+ id = "assembly-large"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 40000)
+ build_path = /obj/item/device/electronic_assembly/large
+ sort_string = "VCAAD"
+
+/datum/design/item/custom_circuit_assembly/implant
+ name = "Implant custom assembly"
+ desc = "An customizable assembly for very small devices, implanted into living entities."
+ id = "assembly-implant"
+ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 2000)
+ build_path = /obj/item/weapon/implant/integrated_circuit
+ sort_string = "VCAAE"
+
+/datum/design/item/custom_circuit_assembly/device
+ name = "Device custom assembly"
+ desc = "An customizable assembly designed to interface with other devices."
+ id = "assembly-device"
+ req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000)
+ build_path = /obj/item/device/assembly/electronic_assembly
+ sort_string = "VCAAF"
+
+/datum/design/item/custom_circuit_printer
+ name = "Portable integrated circuit printer"
+ desc = "A portable(ish) printer for modular machines."
+ id = "ic_printer"
+ req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4, TECH_DATA = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000)
+ build_path = /obj/item/device/integrated_circuit_printer
+ sort_string = "VCAAG"
+
+/datum/design/item/custom_circuit_printer_upgrade
+ name = "Integrated circuit printer upgrade - advanced designs"
+ desc = "Allows the integrated circuit printer to create advanced circuits"
+ id = "ic_printer_upgrade_adv"
+ req_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 2000)
+ build_path = /obj/item/weapon/disk/integrated_circuit/upgrade/advanced
+ sort_string = "VCAAH"
\ No newline at end of file
diff --git a/code/modules/research/designs/circuits.dm b/code/modules/research/designs/circuits.dm
new file mode 100644
index 00000000000..e00a47786d1
--- /dev/null
+++ b/code/modules/research/designs/circuits.dm
@@ -0,0 +1,597 @@
+/*
+CIRCUITS BELOW
+*/
+
+/datum/design/circuit
+ build_type = IMPRINTER
+ req_tech = list(TECH_DATA = 2)
+ materials = list("glass" = 2000)
+ chemicals = list("sacid" = 20)
+ time = 5
+
+/datum/design/circuit/AssembleDesignName()
+ ..()
+ if(build_path)
+ var/obj/item/weapon/circuitboard/C = build_path
+ if(initial(C.board_type) == "machine")
+ name = "Machine circuit design ([item_name])"
+ else if(initial(C.board_type) == "computer")
+ name = "Computer circuit design ([item_name])"
+ else
+ name = "Circuit design ([item_name])"
+
+/datum/design/circuit/AssembleDesignDesc()
+ if(!desc)
+ desc = "Allows for the construction of \a [item_name] circuit board."
+
+/datum/design/circuit/arcademachine
+ name = "battle arcade machine"
+ id = "arcademachine"
+ req_tech = list(TECH_DATA = 1)
+ build_path = /obj/item/weapon/circuitboard/arcade/battle
+ sort_string = "MAAAA"
+
+/datum/design/circuit/oriontrail
+ name = "orion trail arcade machine"
+ id = "oriontrail"
+ req_tech = list(TECH_DATA = 1)
+ build_path = /obj/item/weapon/circuitboard/arcade/orion_trail
+ sort_string = "MAAAZ" // Duplicate string, really need to redo this whole thing
+
+/datum/design/circuit/jukebox
+ name = "jukebox"
+ id = "jukebox"
+ req_tech = list(TECH_MAGNET = 2, TECH_DATA = 1)
+ build_path = /obj/item/weapon/circuitboard/jukebox
+ sort_string = "MAAAB"
+
+/datum/design/circuit/seccamera
+ name = "security camera monitor"
+ id = "seccamera"
+ build_path = /obj/item/weapon/circuitboard/security
+ sort_string = "DAAAZ" // Duplicate string, really need to redo this whole thing
+
+/datum/design/circuit/secdata
+ name = "security records console"
+ id = "sec_data"
+ build_path = /obj/item/weapon/circuitboard/secure_data
+ sort_string = "DABAA"
+
+/datum/design/circuit/prisonmanage
+ name = "prisoner management console"
+ id = "prisonmanage"
+ build_path = /obj/item/weapon/circuitboard/prisoner
+ sort_string = "DACAA"
+
+/datum/design/circuit/med_data
+ name = "medical records console"
+ id = "med_data"
+ build_path = /obj/item/weapon/circuitboard/med_data
+ sort_string = "FAAAA"
+
+/datum/design/circuit/operating
+ name = "patient monitoring console"
+ id = "operating"
+ build_path = /obj/item/weapon/circuitboard/operating
+ sort_string = "FACAA"
+
+/datum/design/circuit/scan_console
+ name = "DNA machine"
+ id = "scan_console"
+ build_path = /obj/item/weapon/circuitboard/scan_consolenew
+ sort_string = "FAGAA"
+
+/datum/design/circuit/clonecontrol
+ name = "cloning control console"
+ id = "clonecontrol"
+ req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
+ build_path = /obj/item/weapon/circuitboard/cloning
+ sort_string = "FAGAC"
+
+/datum/design/circuit/clonepod
+ name = "clone pod"
+ id = "clonepod"
+ req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
+ build_path = /obj/item/weapon/circuitboard/clonepod
+ sort_string = "FAGAE"
+
+/datum/design/circuit/clonescanner
+ name = "cloning scanner"
+ id = "clonescanner"
+ req_tech = list(TECH_DATA = 3, TECH_BIO = 3)
+ build_path = /obj/item/weapon/circuitboard/clonescanner
+ sort_string = "FAGAG"
+
+/datum/design/circuit/crewconsole
+ name = "crew monitoring console"
+ id = "crewconsole"
+ req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_BIO = 2)
+ build_path = /obj/item/weapon/circuitboard/crew
+ sort_string = "FAGAI"
+
+/datum/design/circuit/teleconsole
+ name = "teleporter control console"
+ id = "teleconsole"
+ req_tech = list(TECH_DATA = 3, TECH_BLUESPACE = 2)
+ build_path = /obj/item/weapon/circuitboard/teleporter
+ sort_string = "HAAAA"
+
+/datum/design/circuit/robocontrol
+ name = "robotics control console"
+ id = "robocontrol"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/robotics
+ sort_string = "HAAAB"
+
+/datum/design/circuit/mechacontrol
+ name = "exosuit control console"
+ id = "mechacontrol"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/circuitboard/mecha_control
+ sort_string = "HAAAC"
+
+/datum/design/circuit/rdconsole
+ name = "R&D control console"
+ id = "rdconsole"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/rdconsole
+ sort_string = "HAAAE"
+
+/datum/design/circuit/aifixer
+ name = "AI integrity restorer"
+ id = "aifixer"
+ req_tech = list(TECH_DATA = 3, TECH_BIO = 2)
+ build_path = /obj/item/weapon/circuitboard/aifixer
+ sort_string = "HAAAF"
+
+/datum/design/circuit/comm_monitor
+ name = "telecommunications monitoring console"
+ id = "comm_monitor"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/circuitboard/comm_monitor
+ sort_string = "HAACA"
+
+/datum/design/circuit/comm_server
+ name = "telecommunications server monitoring console"
+ id = "comm_server"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/circuitboard/comm_server
+ sort_string = "HAACB"
+
+/datum/design/circuit/message_monitor
+ name = "messaging monitor console"
+ id = "message_monitor"
+ req_tech = list(TECH_DATA = 5)
+ build_path = /obj/item/weapon/circuitboard/message_monitor
+ sort_string = "HAACC"
+
+/datum/design/circuit/aiupload
+ name = "AI upload console"
+ id = "aiupload"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/aiupload
+ sort_string = "HAABA"
+
+/datum/design/circuit/borgupload
+ name = "cyborg upload console"
+ id = "borgupload"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/borgupload
+ sort_string = "HAABB"
+
+/datum/design/circuit/destructive_analyzer
+ name = "destructive analyzer"
+ id = "destructive_analyzer"
+ req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/destructive_analyzer
+ sort_string = "HABAA"
+
+/datum/design/circuit/protolathe
+ name = "protolathe"
+ id = "protolathe"
+ req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/protolathe
+ sort_string = "HABAB"
+
+/datum/design/circuit/circuit_imprinter
+ name = "circuit imprinter"
+ id = "circuit_imprinter"
+ req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/circuit_imprinter
+ sort_string = "HABAC"
+
+/datum/design/circuit/autolathe
+ name = "autolathe board"
+ id = "autolathe"
+ req_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/autolathe
+ sort_string = "HABAD"
+
+/datum/design/circuit/rdservercontrol
+ name = "R&D server control console"
+ id = "rdservercontrol"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/circuitboard/rdservercontrol
+ sort_string = "HABBA"
+
+/datum/design/circuit/rdserver
+ name = "R&D server"
+ id = "rdserver"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/circuitboard/rdserver
+ sort_string = "HABBB"
+
+/datum/design/circuit/mechfab
+ name = "exosuit fabricator"
+ id = "mechfab"
+ req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
+ build_path = /obj/item/weapon/circuitboard/mechfab
+ sort_string = "HABAE"
+
+/datum/design/circuit/prosfab
+ name = "prosthetics fabricator"
+ id = "prosfab"
+ req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
+ build_path = /obj/item/weapon/circuitboard/prosthetics
+ sort_string = "HABAF"
+
+/datum/design/circuit/mech_recharger
+ name = "mech recharger"
+ id = "mech_recharger"
+ req_tech = list(TECH_DATA = 2, TECH_POWER = 2, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/mech_recharger
+ sort_string = "HACAA"
+
+/datum/design/circuit/recharge_station
+ name = "cyborg recharge station"
+ id = "recharge_station"
+ req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/recharge_station
+ sort_string = "HACAC"
+
+/datum/design/circuit/atmosalerts
+ name = "atmosphere alert console"
+ id = "atmosalerts"
+ build_path = /obj/item/weapon/circuitboard/atmos_alert
+ sort_string = "JAAAA"
+
+/datum/design/circuit/air_management
+ name = "atmosphere monitoring console"
+ id = "air_management"
+ build_path = /obj/item/weapon/circuitboard/air_management
+ sort_string = "JAAAB"
+
+/datum/design/circuit/rcon_console
+ name = "RCON remote control console"
+ id = "rcon_console"
+ req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_POWER = 5)
+ build_path = /obj/item/weapon/circuitboard/rcon_console
+ sort_string = "JAAAC"
+
+/datum/design/circuit/dronecontrol
+ name = "drone control console"
+ id = "dronecontrol"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/drone_control
+ sort_string = "JAAAD"
+
+/datum/design/circuit/powermonitor
+ name = "power monitoring console"
+ id = "powermonitor"
+ build_path = /obj/item/weapon/circuitboard/powermonitor
+ sort_string = "JAAAE"
+
+/datum/design/circuit/solarcontrol
+ name = "solar control console"
+ id = "solarcontrol"
+ build_path = /obj/item/weapon/circuitboard/solar_control
+ sort_string = "JAAAF"
+
+/datum/design/circuit/pacman
+ name = "PACMAN-type generator"
+ id = "pacman"
+ req_tech = list(TECH_DATA = 3, TECH_PHORON = 3, TECH_POWER = 3, TECH_ENGINEERING = 3)
+ build_path = /obj/item/weapon/circuitboard/pacman
+ sort_string = "JBAAA"
+
+/datum/design/circuit/superpacman
+ name = "SUPERPACMAN-type generator"
+ id = "superpacman"
+ req_tech = list(TECH_DATA = 3, TECH_POWER = 4, TECH_ENGINEERING = 4)
+ build_path = /obj/item/weapon/circuitboard/pacman/super
+ sort_string = "JBAAB"
+
+/datum/design/circuit/mrspacman
+ name = "MRSPACMAN-type generator"
+ id = "mrspacman"
+ req_tech = list(TECH_DATA = 3, TECH_POWER = 5, TECH_ENGINEERING = 5)
+ build_path = /obj/item/weapon/circuitboard/pacman/mrs
+ sort_string = "JBAAC"
+
+/datum/design/circuit/batteryrack
+ name = "cell rack PSU"
+ id = "batteryrack"
+ req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/batteryrack
+ sort_string = "JBABA"
+
+/datum/design/circuit/smes_cell
+ name = "'SMES' superconductive magnetic energy storage"
+ desc = "Allows for the construction of circuit boards used to build a SMES."
+ id = "smes_cell"
+ req_tech = list(TECH_POWER = 7, TECH_ENGINEERING = 5)
+ build_path = /obj/item/weapon/circuitboard/smes
+ sort_string = "JBABB"
+
+/datum/design/circuit/grid_checker
+ name = "power grid checker"
+ desc = "Allows for the construction of circuit boards used to build a grid checker."
+ id = "grid_checker"
+ req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 3)
+ build_path = /obj/item/weapon/circuitboard/grid_checker
+ sort_string = "JBABC"
+
+/datum/design/circuit/breakerbox
+ name = "breaker box"
+ desc = "Allows for the construction of circuit boards used to build a breaker box."
+ id = "breakerbox"
+ req_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3)
+ build_path = /obj/item/weapon/circuitboard/breakerbox
+ sort_string = "JBABD"
+
+/datum/design/circuit/gas_heater
+ name = "gas heating system"
+ id = "gasheater"
+ req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 1)
+ build_path = /obj/item/weapon/circuitboard/unary_atmos/heater
+ sort_string = "JCAAA"
+
+/datum/design/circuit/gas_cooler
+ name = "gas cooling system"
+ id = "gascooler"
+ req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2)
+ build_path = /obj/item/weapon/circuitboard/unary_atmos/cooler
+ sort_string = "JCAAB"
+
+/datum/design/circuit/secure_airlock
+ name = "secure airlock electronics"
+ desc = "Allows for the construction of a tamper-resistant airlock electronics."
+ id = "securedoor"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/airlock_electronics/secure
+ sort_string = "JDAAA"
+
+/datum/design/circuit/ordercomp
+ name = "supply ordering console"
+ id = "ordercomp"
+ build_path = /obj/item/weapon/circuitboard/ordercomp
+ sort_string = "KAAAY" // Duplicate string, really need to redo this whole thing
+
+/datum/design/circuit/supplycomp
+ name = "supply control console"
+ id = "supplycomp"
+ req_tech = list(TECH_DATA = 3)
+ build_path = /obj/item/weapon/circuitboard/supplycomp
+ sort_string = "KAAAZ" // Duplicate string, really need to redo this whole thing
+
+/datum/design/circuit/biogenerator
+ name = "biogenerator"
+ id = "biogenerator"
+ req_tech = list(TECH_DATA = 2)
+ build_path = /obj/item/weapon/circuitboard/biogenerator
+ sort_string = "KBAAA"
+
+/datum/design/circuit/miningdrill
+ name = "mining drill head"
+ id = "mining drill head"
+ req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
+ build_path = /obj/item/weapon/circuitboard/miningdrill
+ sort_string = "KCAAA"
+
+/datum/design/circuit/miningdrillbrace
+ name = "mining drill brace"
+ id = "mining drill brace"
+ req_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
+ build_path = /obj/item/weapon/circuitboard/miningdrillbrace
+ sort_string = "KCAAB"
+
+/datum/design/circuit/comconsole
+ name = "communications console"
+ id = "comconsole"
+ build_path = /obj/item/weapon/circuitboard/communications
+ sort_string = "LAAAA"
+
+/datum/design/circuit/idcardconsole
+ name = "ID card modification console"
+ id = "idcardconsole"
+ build_path = /obj/item/weapon/circuitboard/card
+ sort_string = "LAAAB"
+
+/datum/design/circuit/emp_data
+ name = "employment records console"
+ id = "emp_data"
+ build_path = /obj/item/weapon/circuitboard/skills
+ sort_string = "LAAAC"
+
+/datum/design/circuit/mecha
+ req_tech = list(TECH_DATA = 3)
+
+/datum/design/circuit/mecha/AssembleDesignName()
+ name = "Exosuit module circuit design ([name])"
+/datum/design/circuit/mecha/AssembleDesignDesc()
+ desc = "Allows for the construction of \a [name] module."
+
+/datum/design/circuit/mecha/ripley_main
+ name = "APLU 'Ripley' central control"
+ id = "ripley_main"
+ build_path = /obj/item/weapon/circuitboard/mecha/ripley/main
+ sort_string = "NAAAA"
+
+/datum/design/circuit/mecha/ripley_peri
+ name = "APLU 'Ripley' peripherals control"
+ id = "ripley_peri"
+ build_path = /obj/item/weapon/circuitboard/mecha/ripley/peripherals
+ sort_string = "NAAAB"
+
+/datum/design/circuit/mecha/odysseus_main
+ name = "'Odysseus' central control"
+ id = "odysseus_main"
+ req_tech = list(TECH_DATA = 3,TECH_BIO = 2)
+ build_path = /obj/item/weapon/circuitboard/mecha/odysseus/main
+ sort_string = "NAABA"
+
+/datum/design/circuit/mecha/odysseus_peri
+ name = "'Odysseus' peripherals control"
+ id = "odysseus_peri"
+ req_tech = list(TECH_DATA = 3,TECH_BIO = 2)
+ build_path = /obj/item/weapon/circuitboard/mecha/odysseus/peripherals
+ sort_string = "NAABB"
+
+/datum/design/circuit/mecha/gygax_main
+ name = "'Gygax' central control"
+ id = "gygax_main"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/mecha/gygax/main
+ sort_string = "NAACA"
+
+/datum/design/circuit/mecha/gygax_peri
+ name = "'Gygax' peripherals control"
+ id = "gygax_peri"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/mecha/gygax/peripherals
+ sort_string = "NAACB"
+
+/datum/design/circuit/mecha/gygax_targ
+ name = "'Gygax' weapon control and targeting"
+ id = "gygax_targ"
+ req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2)
+ build_path = /obj/item/weapon/circuitboard/mecha/gygax/targeting
+ sort_string = "NAACC"
+
+/datum/design/circuit/mecha/durand_main
+ name = "'Durand' central control"
+ id = "durand_main"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/mecha/durand/main
+ sort_string = "NAADA"
+
+/datum/design/circuit/mecha/durand_peri
+ name = "'Durand' peripherals control"
+ id = "durand_peri"
+ req_tech = list(TECH_DATA = 4)
+ build_path = /obj/item/weapon/circuitboard/mecha/durand/peripherals
+ sort_string = "NAADB"
+
+/datum/design/circuit/mecha/durand_targ
+ name = "'Durand' weapon control and targeting"
+ id = "durand_targ"
+ req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2)
+ build_path = /obj/item/weapon/circuitboard/mecha/durand/targeting
+ sort_string = "NAADC"
+
+/datum/design/circuit/tcom
+ req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
+
+/datum/design/circuit/tcom/AssembleDesignName()
+ name = "Telecommunications machinery circuit design ([name])"
+/datum/design/circuit/tcom/AssembleDesignDesc()
+ desc = "Allows for the construction of a telecommunications [name] circuit board."
+
+/datum/design/circuit/tcom/server
+ name = "server mainframe"
+ id = "tcom-server"
+ build_path = /obj/item/weapon/circuitboard/telecomms/server
+ sort_string = "PAAAA"
+
+/datum/design/circuit/tcom/processor
+ name = "processor unit"
+ id = "tcom-processor"
+ build_path = /obj/item/weapon/circuitboard/telecomms/processor
+ sort_string = "PAAAB"
+
+/datum/design/circuit/tcom/bus
+ name = "bus mainframe"
+ id = "tcom-bus"
+ build_path = /obj/item/weapon/circuitboard/telecomms/bus
+ sort_string = "PAAAC"
+
+/datum/design/circuit/tcom/hub
+ name = "hub mainframe"
+ id = "tcom-hub"
+ build_path = /obj/item/weapon/circuitboard/telecomms/hub
+ sort_string = "PAAAD"
+
+/datum/design/circuit/tcom/relay
+ name = "relay mainframe"
+ id = "tcom-relay"
+ req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 4, TECH_BLUESPACE = 3)
+ build_path = /obj/item/weapon/circuitboard/telecomms/relay
+ sort_string = "PAAAE"
+
+/datum/design/circuit/tcom/broadcaster
+ name = "subspace broadcaster"
+ id = "tcom-broadcaster"
+ req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4, TECH_BLUESPACE = 2)
+ build_path = /obj/item/weapon/circuitboard/telecomms/broadcaster
+ sort_string = "PAAAF"
+
+/datum/design/circuit/tcom/receiver
+ name = "subspace receiver"
+ id = "tcom-receiver"
+ req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_BLUESPACE = 2)
+ build_path = /obj/item/weapon/circuitboard/telecomms/receiver
+ sort_string = "PAAAG"
+
+/datum/design/circuit/tcom/exonet_node
+ name = "exonet node"
+ id = "tcom-exonet_node"
+ req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5, TECH_BLUESPACE = 4)
+ build_path = /obj/item/weapon/circuitboard/telecomms/exonet_node
+ sort_string = "PAAAH"
+
+/datum/design/circuit/shield
+ req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3)
+ materials = list("glass" = 2000, "gold" = 1000)
+
+/datum/design/circuit/shield/AssembleDesignName()
+ name = "Shield generator circuit design ([name])"
+/datum/design/circuit/shield/AssembleDesignDesc()
+ if(!desc)
+ desc = "Allows for the construction of \a [name] shield generator."
+
+/datum/design/circuit/shield/bubble
+ name = "bubble"
+ id = "shield_gen"
+ build_path = /obj/item/weapon/circuitboard/shield_gen
+ sort_string = "VAAAZ" // Duplicate string, really need to redo this whole thing
+
+/datum/design/circuit/shield/hull
+ name = "hull"
+ id = "shield_gen_ex"
+ build_path = /obj/item/weapon/circuitboard/shield_gen_ex
+ sort_string = "VAAAB"
+
+/datum/design/circuit/shield/capacitor
+ name = "capacitor"
+ desc = "Allows for the construction of a shield capacitor circuit board."
+ id = "shield_cap"
+ req_tech = list(TECH_MAGNET = 3, TECH_POWER = 4)
+ build_path = /obj/item/weapon/circuitboard/shield_cap
+ sort_string = "VAAAC"
+
+/datum/design/circuit/aicore
+ name = "AI core"
+ id = "aicore"
+ req_tech = list(TECH_DATA = 4, TECH_BIO = 3)
+ build_path = /obj/item/weapon/circuitboard/aicore
+ sort_string = "XAAAA"
+
+
+/* I have no idea how this was even running before, but it doesn't seem to be necessary.
+///////////////////////////////////
+/////////Shield Generators/////////
+///////////////////////////////////
+/datum/design/circuit/shield
+ req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3)
+ materials = list("$glass" = 2000, "sacid" = 20, "$phoron" = 10000, "$diamond" = 5000, "$gold" = 10000)
+*/
\ No newline at end of file
diff --git a/code/modules/research/designs/illegal.dm b/code/modules/research/designs/illegal.dm
new file mode 100644
index 00000000000..1542e929b67
--- /dev/null
+++ b/code/modules/research/designs/illegal.dm
@@ -0,0 +1,19 @@
+// Yeah yeah, vague file name. Basically a misc folder for antag things that RnD can make.
+
+/datum/design/item/binaryencrypt
+ name = "Binary encryption key"
+ desc = "Allows for deciphering the binary channel on-the-fly."
+ id = "binaryencrypt"
+ req_tech = list(TECH_ILLEGAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 300, "glass" = 300)
+ build_path = /obj/item/device/encryptionkey/binary
+ sort_string = "VASAA"
+
+/datum/design/item/chameleon
+ name = "Holographic equipment kit"
+ desc = "A kit of dangerous, high-tech equipment with changeable looks."
+ id = "chameleon"
+ req_tech = list(TECH_ILLEGAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 500)
+ build_path = /obj/item/weapon/storage/box/syndie_kit/chameleon
+ sort_string = "VASBA"
\ No newline at end of file
diff --git a/code/modules/research/designs/medical.dm b/code/modules/research/designs/medical.dm
new file mode 100644
index 00000000000..8e821fe0fe9
--- /dev/null
+++ b/code/modules/research/designs/medical.dm
@@ -0,0 +1,186 @@
+/datum/design/item/medical
+ materials = list(DEFAULT_WALL_MATERIAL = 30, "glass" = 20)
+
+/datum/design/item/medical/AssembleDesignName()
+ ..()
+ name = "Biotech device prototype ([item_name])"
+
+/datum/design/item/medical/robot_scanner
+ desc = "A hand-held scanner able to diagnose robotic injuries."
+ id = "robot_scanner"
+ req_tech = list(TECH_MAGNET = 3, TECH_BIO = 2, TECH_ENGINEERING = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 200)
+ build_path = /obj/item/device/robotanalyzer
+ sort_string = "MACFA"
+
+/datum/design/item/medical/mass_spectrometer
+ desc = "A device for analyzing chemicals in blood."
+ id = "mass_spectrometer"
+ req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2)
+ build_path = /obj/item/device/mass_spectrometer
+ sort_string = "MACAA"
+
+/datum/design/item/medical/adv_mass_spectrometer
+ desc = "A device for analyzing chemicals in blood and their quantities."
+ id = "adv_mass_spectrometer"
+ req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4)
+ build_path = /obj/item/device/mass_spectrometer/adv
+ sort_string = "MACAB"
+
+/datum/design/item/medical/reagent_scanner
+ desc = "A device for identifying chemicals."
+ id = "reagent_scanner"
+ req_tech = list(TECH_BIO = 2, TECH_MAGNET = 2)
+ build_path = /obj/item/device/reagent_scanner
+ sort_string = "MACBA"
+
+/datum/design/item/medical/adv_reagent_scanner
+ desc = "A device for identifying chemicals and their proportions."
+ id = "adv_reagent_scanner"
+ req_tech = list(TECH_BIO = 2, TECH_MAGNET = 4)
+ build_path = /obj/item/device/reagent_scanner/adv
+ sort_string = "MACBB"
+
+/datum/design/item/beaker/AssembleDesignName()
+ name = "Beaker prototype ([item_name])"
+
+/datum/design/item/beaker/noreact
+ name = "cryostasis"
+ desc = "A cryostasis beaker that allows for chemical storage without reactions. Can hold up to 50 units."
+ id = "splitbeaker"
+ req_tech = list(TECH_MATERIAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 3000)
+ build_path = /obj/item/weapon/reagent_containers/glass/beaker/noreact
+ sort_string = "MADAA"
+
+/datum/design/item/beaker/bluespace
+ name = TECH_BLUESPACE
+ desc = "A bluespace beaker, powered by experimental bluespace technology and Element Cuban combined with the Compound Pete. Can hold up to 300 units."
+ id = "bluespacebeaker"
+ req_tech = list(TECH_BLUESPACE = 2, TECH_MATERIAL = 6)
+ materials = list(DEFAULT_WALL_MATERIAL = 3000, "phoron" = 3000, "diamond" = 500)
+ build_path = /obj/item/weapon/reagent_containers/glass/beaker/bluespace
+ sort_string = "MADAB"
+
+/datum/design/item/medical/nanopaste
+ desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery."
+ id = "nanopaste"
+ req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000)
+ build_path = /obj/item/stack/nanopaste
+ sort_string = "MBAAA"
+
+/datum/design/item/medical/scalpel_laser1
+ name = "Basic Laser Scalpel"
+ desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks basic and could be improved."
+ id = "scalpel_laser1"
+ req_tech = list(TECH_BIO = 2, TECH_MATERIAL = 2, TECH_MAGNET = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500)
+ build_path = /obj/item/weapon/surgical/scalpel/laser1
+ sort_string = "MBBAA"
+
+/datum/design/item/medical/scalpel_laser2
+ name = "Improved Laser Scalpel"
+ desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks somewhat advanced."
+ id = "scalpel_laser2"
+ req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 4, TECH_MAGNET = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500)
+ build_path = /obj/item/weapon/surgical/scalpel/laser2
+ sort_string = "MBBAB"
+
+/datum/design/item/medical/scalpel_laser3
+ name = "Advanced Laser Scalpel"
+ desc = "A scalpel augmented with a directed laser, for more precise cutting without blood entering the field. This one looks to be the pinnacle of precision energy cutlery!"
+ id = "scalpel_laser3"
+ req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 6, TECH_MAGNET = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2000, "gold" = 1500)
+ build_path = /obj/item/weapon/surgical/scalpel/laser3
+ sort_string = "MBBAC"
+
+/datum/design/item/medical/scalpel_manager
+ name = "Incision Management System"
+ desc = "A true extension of the surgeon's body, this marvel instantly and completely prepares an incision allowing for the immediate commencement of therapeutic steps."
+ id = "scalpel_manager"
+ req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 7, TECH_MAGNET = 5, TECH_DATA = 4)
+ materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 1500, "gold" = 1500, "diamond" = 750)
+ build_path = /obj/item/weapon/surgical/scalpel/manager
+ sort_string = "MBBAD"
+
+/datum/design/item/medical/bone_clamp
+ name = "Bone Clamp"
+ desc = "A miracle of modern science, this tool rapidly knits together bone, without the need for bone gel."
+ id = "bone_clamp"
+ req_tech = list(TECH_BIO = 4, TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_DATA = 4)
+ materials = list (DEFAULT_WALL_MATERIAL = 12500, "glass" = 7500, "silver" = 2500)
+ build_path = /obj/item/weapon/surgical/bone_clamp
+ sort_string = "MBBAE"
+
+/datum/design/item/medical/advanced_roller
+ name = "advanced roller bed"
+ desc = "A more advanced version of the regular roller bed, with inbuilt surgical stabilisers and an improved folding system."
+ id = "roller_bed"
+ req_tech = list(TECH_BIO = 3, TECH_MATERIAL = 3, TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 2000, "phoron" = 2000)
+ build_path = /obj/item/roller/adv
+ sort_string = "MBBAF"
+
+/datum/design/item/medical/improved_analyzer
+ name = "improved health analyzer"
+ desc = "A prototype version of the regular health analyzer, able to distinguish the location of more serious injuries as well as accurately determine radiation levels."
+ id = "improved_analyzer"
+ req_tech = list(TECH_MAGNET = 5, TECH_BIO = 6)
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 1500)
+ build_path = /obj/item/device/healthanalyzer/improved
+ sort_string = "MBBAG"
+
+/datum/design/item/implant
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+
+/datum/design/item/implant/AssembleDesignName()
+ ..()
+ name = "Implantable biocircuit design ([item_name])"
+
+/datum/design/item/implant/chemical
+ name = "chemical"
+ id = "implant_chem"
+ req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3)
+ build_path = /obj/item/weapon/implantcase/chem
+ sort_string = "MFAAA"
+
+/datum/design/item/implant/freedom
+ name = "freedom"
+ id = "implant_free"
+ req_tech = list(TECH_ILLEGAL = 2, TECH_BIO = 3)
+ build_path = /obj/item/weapon/implantcase/freedom
+ sort_string = "MFAAB"
+
+// These are in here because Robotics is close enough to Medical and I don't want to make a new brains.dm file
+/datum/design/item/dronebrain
+ name = "Robotic intelligence circuit"
+ id = "dronebrain"
+ req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 5, TECH_DATA = 4)
+ build_type = PROTOLATHE | PROSFAB
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500)
+ build_path = /obj/item/device/mmi/digital/robot
+ category = "Misc"
+ sort_string = "VACAC"
+
+/datum/design/item/posibrain
+ name = "Positronic brain"
+ id = "posibrain"
+ req_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 6, TECH_BLUESPACE = 2, TECH_DATA = 4)
+ build_type = PROTOLATHE | PROSFAB
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500, "phoron" = 500, "diamond" = 100)
+ build_path = /obj/item/device/mmi/digital/posibrain
+ category = "Misc"
+ sort_string = "VACAB"
+
+/datum/design/item/mmi
+ name = "Man-machine interface"
+ id = "mmi"
+ req_tech = list(TECH_DATA = 2, TECH_BIO = 3)
+ build_type = PROTOLATHE | PROSFAB
+ materials = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 500)
+ build_path = /obj/item/device/mmi
+ category = "Misc"
+ sort_string = "VACBA"
\ No newline at end of file
diff --git a/code/modules/research/designs/mining_toys.dm b/code/modules/research/designs/mining_toys.dm
new file mode 100644
index 00000000000..f9b76032cbd
--- /dev/null
+++ b/code/modules/research/designs/mining_toys.dm
@@ -0,0 +1,48 @@
+// Assorted Mining-related items
+
+/datum/design/item/weapon/mining/AssembleDesignName()
+ ..()
+ name = "Mining equipment design ([item_name])"
+
+/datum/design/item/weapon/mining/jackhammer
+ id = "jackhammer"
+ req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "silver" = 500)
+ build_path = /obj/item/weapon/pickaxe/jackhammer
+ sort_string = "KAAAA"
+
+/datum/design/item/weapon/mining/drill
+ id = "drill"
+ req_tech = list(TECH_MATERIAL = 2, TECH_POWER = 3, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 1000) //expensive, but no need for miners.
+ build_path = /obj/item/weapon/pickaxe/drill
+ sort_string = "KAAAB"
+
+/datum/design/item/weapon/mining/plasmacutter
+ id = "plasmacutter"
+ req_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 3, TECH_ENGINEERING = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 500, "gold" = 500, "phoron" = 500)
+ build_path = /obj/item/weapon/pickaxe/plasmacutter
+ sort_string = "KAAAC"
+
+/datum/design/item/weapon/mining/pick_diamond
+ id = "pick_diamond"
+ req_tech = list(TECH_MATERIAL = 6)
+ materials = list("diamond" = 3000)
+ build_path = /obj/item/weapon/pickaxe/diamond
+ sort_string = "KAAAD"
+
+/datum/design/item/weapon/mining/drill_diamond
+ id = "drill_diamond"
+ req_tech = list(TECH_MATERIAL = 6, TECH_POWER = 4, TECH_ENGINEERING = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 1000, "diamond" = 2000)
+ build_path = /obj/item/weapon/pickaxe/diamonddrill
+ sort_string = "KAAAE"
+
+/datum/design/item/device/depth_scanner
+ desc = "Used to check spatial depth and density of rock outcroppings."
+ id = "depth_scanner"
+ req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 1000)
+ build_path = /obj/item/device/depth_scanner
+ sort_string = "KAAAF"
\ No newline at end of file
diff --git a/code/modules/research/designs/misc.dm b/code/modules/research/designs/misc.dm
new file mode 100644
index 00000000000..29231a7cd9a
--- /dev/null
+++ b/code/modules/research/designs/misc.dm
@@ -0,0 +1,203 @@
+/*
+//
+// THIS IS GOING TO GET REAL DAMN BLOATED, SO LET'S TRY TO AVOID THAT IF POSSIBLE
+//
+*/
+
+/datum/design/item/hud
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+
+/datum/design/item/hud/AssembleDesignName()
+ ..()
+ name = "HUD glasses prototype ([item_name])"
+
+/datum/design/item/hud/AssembleDesignDesc()
+ desc = "Allows for the construction of \a [item_name] HUD glasses."
+
+/datum/design/item/hud/health
+ name = "health scanner"
+ id = "health_hud"
+ req_tech = list(TECH_BIO = 2, TECH_MAGNET = 3)
+ build_path = /obj/item/clothing/glasses/hud/health
+ sort_string = "GAAAA"
+
+/datum/design/item/hud/security
+ name = "security records"
+ id = "security_hud"
+ req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2)
+ build_path = /obj/item/clothing/glasses/hud/security
+ sort_string = "GAAAB"
+
+/datum/design/item/hud/mesons
+ name = "Optical meson scanners design"
+ desc = "Using the meson-scanning technology those glasses allow you to see through walls, floor or anything else."
+ id = "mesons"
+ req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+ build_path = /obj/item/clothing/glasses/meson
+ sort_string = "GAAAC"
+
+/datum/design/item/device/ano_scanner
+ name = "Alden-Saraspova counter"
+ id = "ano_scanner"
+ desc = "Aids in triangulation of exotic particles."
+ req_tech = list(TECH_BLUESPACE = 3, TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000,"glass" = 5000)
+ build_path = /obj/item/device/ano_scanner
+ sort_string = "UAAAH"
+
+/datum/design/item/light_replacer
+ name = "Light replacer"
+ desc = "A device to automatically replace lights. Refill with working lightbulbs."
+ id = "light_replacer"
+ req_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 1500, "silver" = 150, "glass" = 3000)
+ build_path = /obj/item/device/lightreplacer
+ sort_string = "VAAAH"
+
+datum/design/item/laserpointer
+ name = "laser pointer"
+ desc = "Don't shine it in your eyes!"
+ id = "laser_pointer"
+ req_tech = list(TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 100, "glass" = 50)
+ build_path = /obj/item/device/laser_pointer
+ sort_string = "VAAAI"
+
+/datum/design/item/paicard
+ name = "'pAI', personal artificial intelligence device"
+ id = "paicard"
+ req_tech = list(TECH_DATA = 2)
+ materials = list("glass" = 500, DEFAULT_WALL_MATERIAL = 500)
+ build_path = /obj/item/device/paicard
+ sort_string = "VABAI"
+
+/datum/design/item/communicator
+ name = "Communicator"
+ id = "communicator"
+ req_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 500)
+ build_path = /obj/item/device/communicator
+ sort_string = "VABAJ"
+
+/datum/design/item/beacon
+ name = "Bluespace tracking beacon design"
+ id = "beacon"
+ req_tech = list(TECH_BLUESPACE = 1)
+ materials = list (DEFAULT_WALL_MATERIAL = 20, "glass" = 10)
+ build_path = /obj/item/device/radio/beacon
+ sort_string = "VADAA"
+
+/datum/design/item/gps
+ name = "Triangulating device design"
+ desc = "Triangulates approximate co-ordinates using a nearby satellite network."
+ id = "gps"
+ req_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 500)
+ build_path = /obj/item/device/gps
+ sort_string = "VADAB"
+
+/datum/design/item/beacon_locator
+ name = "Beacon tracking pinpointer"
+ desc = "Used to scan and locate signals on a particular frequency."
+ id = "beacon_locator"
+ req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 500)
+ build_path = /obj/item/device/beacon_locator
+ sort_string = "VADAC"
+
+/datum/design/item/bag_holding
+ name = "'Bag of Holding', an infinite capacity bag prototype"
+ desc = "Using localized pockets of bluespace this bag prototype offers incredible storage capacity with the contents weighting nothing. It's a shame the bag itself is pretty heavy."
+ id = "bag_holding"
+ req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6)
+ materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250)
+ build_path = /obj/item/weapon/storage/backpack/holding
+ sort_string = "VAEAA"
+
+/datum/design/item/dufflebag_holding
+ name = "'DuffleBag of Holding', an infinite capacity dufflebag prototype"
+ desc = "A minaturized prototype of the popular Bag of Holding, the Dufflebag of Holding is, functionally, identical to the bag of holding, but comes in a more stylish and compact form."
+ id = "dufflebag_holding"
+ req_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 6)
+ materials = list("gold" = 3000, "diamond" = 1500, "uranium" = 250)
+ build_path = /obj/item/weapon/storage/backpack/holding/duffle
+ sort_string = "VAEAB"
+
+/datum/design/item/experimental_welder
+ name = "Experimental welding tool"
+ desc = "A welding tool that generate fuel for itself."
+ id = "expwelder"
+ req_tech = list(TECH_ENGINEERING = 4, TECH_PHORON = 3, TECH_MATERIAL = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 70, "glass" = 120, "phoron" = 100)
+ build_path = /obj/item/weapon/weldingtool/experimental
+ sort_string = "VASCA"
+
+/datum/design/item/hand_drill
+ name = "Hand drill"
+ desc = "A simple powered hand drill."
+ id = "handdrill"
+ req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100)
+ build_path = /obj/item/weapon/tool/screwdriver/power
+ sort_string = "VASDA"
+
+/datum/design/item/jaws_life
+ name = "Jaws of life"
+ desc = "A set of jaws of life, compressed through the magic of science."
+ id = "jawslife"
+ req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 300, "silver" = 100)
+ build_path = /obj/item/weapon/tool/crowbar/power
+ sort_string = "VASEA"
+
+/datum/design/item/device/t_scanner_upg
+ name = "Upgraded T-ray Scanner"
+ desc = "An upgraded version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
+ id = "upgradedtscanner"
+ req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 4, TECH_MATERIAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 500, "phoron" = 150)
+ build_path = /obj/item/device/t_scanner/upgraded
+ sort_string = "VASSA"
+
+/datum/design/item/device/t_scanner_adv
+ name = "Advanced T-ray Scanner"
+ desc = "An advanced version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
+ id = "advancedtscanner"
+ req_tech = list(TECH_MAGNET = 6, TECH_ENGINEERING = 6, TECH_MATERIAL = 6)
+ materials = list(DEFAULT_WALL_MATERIAL = 1250, "phoron" = 500, "silver" = 50)
+ build_path = /obj/item/device/t_scanner/advanced
+ sort_string = "VASSB"
+
+/datum/design/item/translator
+ name = "handheld translator"
+ id = "translator"
+ req_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 3000, "glass" = 3000)
+ build_path = /obj/item/device/universal_translator
+ sort_string = "HABQA"
+
+/datum/design/item/ear_translator
+ name = "earpiece translator"
+ id = "ear_translator"
+ req_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5) //It's been hella miniaturized.
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 2000, "gold" = 1000)
+ build_path = /obj/item/device/universal_translator/ear
+ sort_string = "HABQB"
+
+/datum/design/item/xenoarch_multi_tool
+ name = "xenoarcheology multitool"
+ id = "xenoarch_multitool"
+ req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3, TECH_BLUESPACE = 3)
+ build_path = /obj/item/device/xenoarch_multi_tool
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "uranium" = 500, "phoron" = 500)
+ sort_string = "HABQC"
+
+/datum/design/item/excavationdrill
+ name = "Excavation Drill"
+ id = "excavationdrill"
+ req_tech = list(TECH_MATERIAL = 3, TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3)
+ build_type = PROTOLATHE
+ materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 4000)
+ build_path = /obj/item/weapon/pickaxe/excavationdrill
+ sort_string = "HABQD"
diff --git a/code/modules/research/designs/pdas.dm b/code/modules/research/designs/pdas.dm
new file mode 100644
index 00000000000..4aca3062b9a
--- /dev/null
+++ b/code/modules/research/designs/pdas.dm
@@ -0,0 +1,92 @@
+/datum/design/item/pda
+ name = "PDA design"
+ desc = "Cheaper than whiny non-digital assistants."
+ id = "pda"
+ req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+ build_path = /obj/item/device/pda
+ sort_string = "VAAAA"
+
+// Cartridges
+/datum/design/item/pda_cartridge
+ req_tech = list(TECH_ENGINEERING = 2, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+
+/datum/design/item/pda_cartridge/AssembleDesignName()
+ ..()
+ name = "PDA accessory ([item_name])"
+
+/datum/design/item/pda_cartridge/cart_basic
+ id = "cart_basic"
+ build_path = /obj/item/weapon/cartridge
+ sort_string = "VBAAA"
+
+/datum/design/item/pda_cartridge/engineering
+ id = "cart_engineering"
+ build_path = /obj/item/weapon/cartridge/engineering
+ sort_string = "VBAAB"
+
+/datum/design/item/pda_cartridge/atmos
+ id = "cart_atmos"
+ build_path = /obj/item/weapon/cartridge/atmos
+ sort_string = "VBAAC"
+
+/datum/design/item/pda_cartridge/medical
+ id = "cart_medical"
+ build_path = /obj/item/weapon/cartridge/medical
+ sort_string = "VBAAD"
+
+/datum/design/item/pda_cartridge/chemistry
+ id = "cart_chemistry"
+ build_path = /obj/item/weapon/cartridge/chemistry
+ sort_string = "VBAAE"
+
+/datum/design/item/pda_cartridge/security
+ id = "cart_security"
+ build_path = /obj/item/weapon/cartridge/security
+ sort_string = "VBAAF"
+
+/datum/design/item/pda_cartridge/janitor
+ id = "cart_janitor"
+ build_path = /obj/item/weapon/cartridge/janitor
+ sort_string = "VBAAG"
+
+/datum/design/item/pda_cartridge/science
+ id = "cart_science"
+ build_path = /obj/item/weapon/cartridge/signal/science
+ sort_string = "VBAAH"
+
+/datum/design/item/pda_cartridge/quartermaster
+ id = "cart_quartermaster"
+ build_path = /obj/item/weapon/cartridge/quartermaster
+ sort_string = "VBAAI"
+
+/datum/design/item/pda_cartridge/hop
+ id = "cart_hop"
+ build_path = /obj/item/weapon/cartridge/hop
+ sort_string = "VBAAJ"
+
+/datum/design/item/pda_cartridge/hos
+ id = "cart_hos"
+ build_path = /obj/item/weapon/cartridge/hos
+ sort_string = "VBAAK"
+
+/datum/design/item/pda_cartridge/ce
+ id = "cart_ce"
+ build_path = /obj/item/weapon/cartridge/ce
+ sort_string = "VBAAL"
+
+/datum/design/item/pda_cartridge/cmo
+ id = "cart_cmo"
+ build_path = /obj/item/weapon/cartridge/cmo
+ sort_string = "VBAAM"
+
+/datum/design/item/pda_cartridge/rd
+ id = "cart_rd"
+ build_path = /obj/item/weapon/cartridge/rd
+ sort_string = "VBAAN"
+
+/datum/design/item/pda_cartridge/captain
+ id = "cart_captain"
+ build_path = /obj/item/weapon/cartridge/captain
+ sort_string = "VBAAO"
\ No newline at end of file
diff --git a/code/modules/research/designs/powercells.dm b/code/modules/research/designs/powercells.dm
new file mode 100644
index 00000000000..1ae3a3c3615
--- /dev/null
+++ b/code/modules/research/designs/powercells.dm
@@ -0,0 +1,71 @@
+/datum/design/item/powercell
+ build_type = PROTOLATHE | MECHFAB
+
+/datum/design/item/powercell/AssembleDesignName()
+ name = "Power Cell Model ([item_name])"
+
+/datum/design/item/powercell/AssembleDesignDesc()
+ if(build_path)
+ var/obj/item/weapon/cell/C = build_path
+ desc = "Allows the construction of power cells that can hold [initial(C.maxcharge)] units of energy."
+
+/datum/design/item/powercell/Fabricate()
+ var/obj/item/weapon/cell/C = ..()
+ C.charge = 0 //shouldn't produce power out of thin air.
+ return C
+
+/datum/design/item/powercell/basic
+ name = "basic"
+ build_type = PROTOLATHE | MECHFAB
+ id = "basic_cell"
+ req_tech = list(TECH_POWER = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50)
+ build_path = /obj/item/weapon/cell
+ category = "Misc"
+ sort_string = "DAAAA"
+
+/datum/design/item/powercell/high
+ name = "high-capacity"
+ build_type = PROTOLATHE | MECHFAB
+ id = "high_cell"
+ req_tech = list(TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60)
+ build_path = /obj/item/weapon/cell/high
+ category = "Misc"
+ sort_string = "DAAAB"
+
+/datum/design/item/powercell/super
+ name = "super-capacity"
+ id = "super_cell"
+ req_tech = list(TECH_POWER = 3, TECH_MATERIAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70)
+ build_path = /obj/item/weapon/cell/super
+ category = "Misc"
+ sort_string = "DAAAC"
+
+/datum/design/item/powercell/hyper
+ name = "hyper-capacity"
+ id = "hyper_cell"
+ req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 400, "gold" = 150, "silver" = 150, "glass" = 70)
+ build_path = /obj/item/weapon/cell/hyper
+ category = "Misc"
+ sort_string = "DAAAD"
+
+/datum/design/item/powercell/device
+ name = "device"
+ build_type = PROTOLATHE
+ id = "device"
+ materials = list(DEFAULT_WALL_MATERIAL = 350, "glass" = 25)
+ build_path = /obj/item/weapon/cell/device
+ category = "Misc"
+ sort_string = "DAABA"
+
+/datum/design/item/powercell/weapon
+ name = "weapon"
+ build_type = PROTOLATHE
+ id = "weapon"
+ materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50)
+ build_path = /obj/item/weapon/cell/device/weapon
+ category = "Misc"
+ sort_string = "DAABB"
\ No newline at end of file
diff --git a/code/modules/research/designs/stock_parts.dm b/code/modules/research/designs/stock_parts.dm
new file mode 100644
index 00000000000..fb629e7ad70
--- /dev/null
+++ b/code/modules/research/designs/stock_parts.dm
@@ -0,0 +1,178 @@
+/*
+ Various Stock Parts
+*/
+
+/datum/design/item/stock_part
+ build_type = PROTOLATHE
+
+/datum/design/item/stock_part/AssembleDesignName()
+ ..()
+ name = "Component design ([item_name])"
+
+/datum/design/item/stock_part/AssembleDesignDesc()
+ if(!desc)
+ desc = "A stock part used in the construction of various devices."
+
+/datum/design/item/stock_part/basic_capacitor
+ id = "basic_capacitor"
+ req_tech = list(TECH_POWER = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+ build_path = /obj/item/weapon/stock_parts/capacitor
+ sort_string = "CAAAA"
+
+/datum/design/item/stock_part/adv_capacitor
+ id = "adv_capacitor"
+ req_tech = list(TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
+ build_path = /obj/item/weapon/stock_parts/capacitor/adv
+ sort_string = "CAAAB"
+
+/datum/design/item/stock_part/super_capacitor
+ id = "super_capacitor"
+ req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50, "gold" = 20)
+ build_path = /obj/item/weapon/stock_parts/capacitor/super
+ sort_string = "CAAAC"
+
+/datum/design/item/stock_part/micro_mani
+ id = "micro_mani"
+ req_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 30)
+ build_path = /obj/item/weapon/stock_parts/manipulator
+ sort_string = "CAABA"
+
+/datum/design/item/stock_part/nano_mani
+ id = "nano_mani"
+ req_tech = list(TECH_MATERIAL = 3, TECH_DATA = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 30)
+ build_path = /obj/item/weapon/stock_parts/manipulator/nano
+ sort_string = "CAABB"
+
+/datum/design/item/stock_part/pico_mani
+ id = "pico_mani"
+ req_tech = list(TECH_MATERIAL = 5, TECH_DATA = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 30)
+ build_path = /obj/item/weapon/stock_parts/manipulator/pico
+ sort_string = "CAABC"
+
+/datum/design/item/stock_part/basic_matter_bin
+ id = "basic_matter_bin"
+ req_tech = list(TECH_MATERIAL = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 80)
+ build_path = /obj/item/weapon/stock_parts/matter_bin
+ sort_string = "CAACA"
+
+/datum/design/item/stock_part/adv_matter_bin
+ id = "adv_matter_bin"
+ req_tech = list(TECH_MATERIAL = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 80)
+ build_path = /obj/item/weapon/stock_parts/matter_bin/adv
+ sort_string = "CAACB"
+
+/datum/design/item/stock_part/super_matter_bin
+ id = "super_matter_bin"
+ req_tech = list(TECH_MATERIAL = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 80)
+ build_path = /obj/item/weapon/stock_parts/matter_bin/super
+ sort_string = "CAACC"
+
+/datum/design/item/stock_part/basic_micro_laser
+ id = "basic_micro_laser"
+ req_tech = list(TECH_MAGNET = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20)
+ build_path = /obj/item/weapon/stock_parts/micro_laser
+ sort_string = "CAADA"
+
+/datum/design/item/stock_part/high_micro_laser
+ id = "high_micro_laser"
+ req_tech = list(TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20)
+ build_path = /obj/item/weapon/stock_parts/micro_laser/high
+ sort_string = "CAADB"
+
+/datum/design/item/stock_part/ultra_micro_laser
+ id = "ultra_micro_laser"
+ req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 10, "glass" = 20, "uranium" = 10)
+ build_path = /obj/item/weapon/stock_parts/micro_laser/ultra
+ sort_string = "CAADC"
+
+/datum/design/item/stock_part/basic_sensor
+ id = "basic_sensor"
+ req_tech = list(TECH_MAGNET = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20)
+ build_path = /obj/item/weapon/stock_parts/scanning_module
+ sort_string = "CAAEA"
+
+/datum/design/item/stock_part/adv_sensor
+ id = "adv_sensor"
+ req_tech = list(TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20)
+ build_path = /obj/item/weapon/stock_parts/scanning_module/adv
+ sort_string = "CAAEB"
+
+/datum/design/item/stock_part/phasic_sensor
+ id = "phasic_sensor"
+ req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 20, "silver" = 10)
+ build_path = /obj/item/weapon/stock_parts/scanning_module/phasic
+ sort_string = "CAAEC"
+
+/datum/design/item/stock_part/subspace_ansible
+ id = "s-ansible"
+ req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 80, "silver" = 20)
+ build_path = /obj/item/weapon/stock_parts/subspace/ansible
+ sort_string = "UAAAA"
+
+/datum/design/item/stock_part/hyperwave_filter
+ id = "s-filter"
+ req_tech = list(TECH_DATA = 3, TECH_MAGNET = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 40, "silver" = 10)
+ build_path = /obj/item/weapon/stock_parts/subspace/sub_filter
+ sort_string = "UAAAB"
+
+/datum/design/item/stock_part/subspace_amplifier
+ id = "s-amplifier"
+ req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 30, "uranium" = 15)
+ build_path = /obj/item/weapon/stock_parts/subspace/amplifier
+ sort_string = "UAAAC"
+
+/datum/design/item/stock_part/subspace_treatment
+ id = "s-treatment"
+ req_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10, "silver" = 20)
+ build_path = /obj/item/weapon/stock_parts/subspace/treatment
+ sort_string = "UAAAD"
+
+/datum/design/item/stock_part/subspace_analyzer
+ id = "s-analyzer"
+ req_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 10, "gold" = 15)
+ build_path = /obj/item/weapon/stock_parts/subspace/analyzer
+ sort_string = "UAAAE"
+
+/datum/design/item/stock_part/subspace_crystal
+ id = "s-crystal"
+ req_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
+ materials = list("glass" = 1000, "silver" = 20, "gold" = 20)
+ build_path = /obj/item/weapon/stock_parts/subspace/crystal
+ sort_string = "UAAAF"
+
+/datum/design/item/stock_part/subspace_transmitter
+ id = "s-transmitter"
+ req_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3)
+ materials = list("glass" = 100, "silver" = 10, "uranium" = 15)
+ build_path = /obj/item/weapon/stock_parts/subspace/transmitter
+ sort_string = "UAAAG"
+
+// RPED lives here because it handles stock parts
+/datum/design/item/stock_part/RPED
+ name = "Rapid Part Exchange Device"
+ desc = "Special mechanical module made to store, sort, and apply standard machine parts."
+ id = "rped"
+ req_tech = list(TECH_ENGINEERING = 3, TECH_MATERIAL = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 5000)
+ build_path = /obj/item/weapon/storage/part_replacer
+ sort_string = "CBAAA"
\ No newline at end of file
diff --git a/code/modules/research/designs/uncommented.dm b/code/modules/research/designs/uncommented.dm
new file mode 100644
index 00000000000..7bbf53571ae
--- /dev/null
+++ b/code/modules/research/designs/uncommented.dm
@@ -0,0 +1,69 @@
+
+/* Uncomment if someone makes these buildable
+/datum/design/circuit/general_alert
+ name = "general alert console"
+ id = "general_alert"
+ build_path = /obj/item/weapon/circuitboard/general_alert
+
+// Removal of loyalty implants. Can't think of a way to add this to the config option.
+/datum/design/item/implant/loyalty
+ name = "loyalty"
+ id = "implant_loyal"
+ req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 7000)
+ build_path = /obj/item/weapon/implantcase/loyalty"
+
+/datum/design/rust_core_control
+ name = "Circuit Design (RUST core controller)"
+ desc = "Allows for the construction of circuit boards used to build a core control console for the RUST fusion engine."
+ id = "rust_core_control"
+ req_tech = list("programming" = 4, "engineering" = 4)
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "sacid" = 20)
+ build_path = "/obj/item/weapon/circuitboard/rust_core_control"
+
+datum/design/rust_fuel_control
+ name = "Circuit Design (RUST fuel controller)"
+ desc = "Allows for the construction of circuit boards used to build a fuel injector control console for the RUST fusion engine."
+ id = "rust_fuel_control"
+ req_tech = list("programming" = 4, "engineering" = 4)
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "sacid" = 20)
+ build_path = "/obj/item/weapon/circuitboard/rust_fuel_control"
+
+datum/design/rust_fuel_port
+ name = "Internal circuitry (RUST fuel port)"
+ desc = "Allows for the construction of circuit boards used to build a fuel injection port for the RUST fusion engine."
+ id = "rust_fuel_port"
+ req_tech = list("engineering" = 4, "materials" = 5)
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "sacid" = 20, "uranium" = 3000)
+ build_path = "/obj/item/weapon/module/rust_fuel_port"
+
+datum/design/rust_fuel_compressor
+ name = "Circuit Design (RUST fuel compressor)"
+ desc = "Allows for the construction of circuit boards used to build a fuel compressor of the RUST fusion engine."
+ id = "rust_fuel_compressor"
+ req_tech = list("materials" = 6, "phorontech" = 4)
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 1000)
+ build_path = "/obj/item/weapon/module/rust_fuel_compressor"
+
+datum/design/rust_core
+ name = "Internal circuitry (RUST tokamak core)"
+ desc = "The circuit board that for a RUST-pattern tokamak fusion core."
+ id = "pacman"
+ req_tech = list(bluespace = 3, phorontech = 4, magnets = 5, powerstorage = 6)
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "diamond" = 2000)
+ build_path = "/obj/item/weapon/circuitboard/rust_core"
+
+datum/design/rust_injector
+ name = "Internal circuitry (RUST tokamak core)"
+ desc = "The circuit board that for a RUST-pattern particle accelerator."
+ id = "pacman"
+ req_tech = list(powerstorage = 3, engineering = 4, phorontech = 4, materials = 6)
+ build_type = IMPRINTER
+ materials = list("glass" = 2000, "sacid" = 20, "phoron" = 3000, "uranium" = 2000)
+ build_path = "/obj/item/weapon/circuitboard/rust_core"
+*/
diff --git a/code/modules/research/designs/weapons.dm b/code/modules/research/designs/weapons.dm
new file mode 100644
index 00000000000..828856aebad
--- /dev/null
+++ b/code/modules/research/designs/weapons.dm
@@ -0,0 +1,193 @@
+/datum/design/item/weapon/AssembleDesignName()
+ ..()
+ name = "Weapon prototype ([item_name])"
+
+/datum/design/item/weapon/AssembleDesignDesc()
+ if(!desc)
+ if(build_path)
+ var/obj/item/I = build_path
+ desc = initial(I.desc)
+ ..()
+
+/datum/design/item/weapon/stunrevolver
+ id = "stunrevolver"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000)
+ build_path = /obj/item/weapon/gun/energy/stunrevolver
+ sort_string = "TAAAA"
+
+/datum/design/item/weapon/nuclear_gun
+ id = "nuclear_gun"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 5, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "uranium" = 500)
+ build_path = /obj/item/weapon/gun/energy/gun/nuclear
+ sort_string = "TAAAB"
+
+/datum/design/item/weapon/lasercannon
+ desc = "The lasing medium of this prototype is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core."
+ id = "lasercannon"
+ req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 1000, "diamond" = 2000)
+ build_path = /obj/item/weapon/gun/energy/lasercannon
+ sort_string = "TAAAC"
+
+/datum/design/item/weapon/phoronpistol
+ id = "ppistol"
+ req_tech = list(TECH_COMBAT = 5, TECH_PHORON = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000, "phoron" = 3000)
+ build_path = /obj/item/weapon/gun/energy/toxgun
+ sort_string = "TAAAD"
+
+/datum/design/item/weapon/decloner
+ id = "decloner"
+ req_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 7, TECH_BIO = 5, TECH_POWER = 6)
+ materials = list("gold" = 5000,"uranium" = 10000)
+ build_path = /obj/item/weapon/gun/energy/decloner
+ sort_string = "TAAAE"
+
+/datum/design/item/weapon/smg
+ id = "smg"
+ desc = "An compact reliable SMG firing armor piercing ammo."
+ req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 8000, "silver" = 2000, "diamond" = 1000)
+ build_path = /obj/item/weapon/gun/projectile/automatic/saber
+ sort_string = "TAABA"
+
+/datum/design/item/weapon/ammo_9mm
+ id = "ammo_9mm"
+ req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 3750, "silver" = 100)
+ build_path = /obj/item/ammo_magazine/box/c9mm
+ sort_string = "TAACA"
+
+/datum/design/item/weapon/stunshell
+ desc = "A stunning shell for a shotgun."
+ id = "stunshell"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000)
+ build_path = /obj/item/ammo_casing/a12g/stunshell
+ sort_string = "TAACB"
+
+/datum/design/item/weapon/chemsprayer
+ desc = "An advanced chem spraying device."
+ id = "chemsprayer"
+ req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000)
+ build_path = /obj/item/weapon/reagent_containers/spray/chemsprayer
+ sort_string = "TABAA"
+
+/datum/design/item/weapon/rapidsyringe
+ id = "rapidsyringe"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_ENGINEERING = 3, TECH_BIO = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 1000)
+ build_path = /obj/item/weapon/gun/launcher/syringe/rapid
+ sort_string = "TABAB"
+
+/datum/design/item/weapon/temp_gun
+ desc = "A gun that shoots high-powered glass-encased energy temperature bullets."
+ id = "temp_gun"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "glass" = 500, "silver" = 3000)
+ build_path = /obj/item/weapon/gun/energy/temperature
+ sort_string = "TABAC"
+
+/datum/design/item/weapon/large_grenade
+ id = "large_Grenade"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 3000)
+ build_path = /obj/item/weapon/grenade/chem_grenade/large
+ sort_string = "TACAA"
+
+/datum/design/item/weapon/dartgun
+ desc = "A gun that fires small hollow chemical-payload darts."
+ id = "dartgun_r"
+ req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_BIO = 4, TECH_MAGNET = 3, TECH_ILLEGAL = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000, "gold" = 5000, "silver" = 2500, "glass" = 750)
+ build_path = /obj/item/weapon/gun/projectile/dartgun/research
+ sort_string = "TACAB"
+
+/datum/design/item/weapon/dartgunmag_small
+ id = "dartgun_mag_s"
+ req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 300, "gold" = 100, "silver" = 100, "glass" = 300)
+ build_path = /obj/item/ammo_magazine/chemdart/small
+ sort_string = "TACAC"
+
+/datum/design/item/weapon/dartgun_ammo_small
+ id = "dartgun_ammo_s"
+ req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 50, "gold" = 30, "silver" = 30, "glass" = 50)
+ build_path = /obj/item/ammo_casing/chemdart/small
+ sort_string = "TACAD"
+
+/datum/design/item/weapon/dartgunmag_med
+ id = "dartgun_mag_m"
+ req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 500, "gold" = 150, "silver" = 150, "diamond" = 200, "glass" = 400)
+ build_path = /obj/item/ammo_magazine/chemdart
+ sort_string = "TACAE"
+
+/datum/design/item/weapon/dartgun_ammo_med
+ id = "dartgun_ammo_m"
+ req_tech = list(TECH_COMBAT = 7, TECH_MATERIAL = 2, TECH_BIO = 2, TECH_MAGNET = 1, TECH_ILLEGAL = 1)
+ materials = list(DEFAULT_WALL_MATERIAL = 80, "gold" = 40, "silver" = 40, "glass" = 60)
+ build_path = /obj/item/ammo_casing/chemdart
+ sort_string = "TACAF"
+
+/datum/design/item/weapon/fuelrod
+ id = "fuelrod_gun"
+ req_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_PHORON = 4, TECH_ILLEGAL = 5, TECH_MAGNET = 5)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 2000, "gold" = 500, "silver" = 500, "uranium" = 1000, "phoron" = 3000, "diamond" = 1000)
+ build_path = /obj/item/weapon/gun/magnetic/fuelrod
+ sort_string = "TACBA"
+
+/datum/design/item/weapon/flora_gun
+ id = "flora_gun"
+ req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 500, "uranium" = 500)
+ build_path = /obj/item/weapon/gun/energy/floragun
+ sort_string = "TBAAA"
+
+// Xenobio Tools
+/datum/design/item/weapon/slimebation
+ id = "slimebation"
+ req_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2, TECH_POWER = 3, TECH_COMBAT = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000)
+ build_path = /obj/item/weapon/melee/baton/slime
+ sort_string = "TBAAB"
+
+/datum/design/item/weapon/slimetaser
+ id = "slimetaser"
+ req_tech = list(TECH_MATERIAL = 3, TECH_BIO = 3, TECH_POWER = 4, TECH_COMBAT = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 5000)
+ build_path = /obj/item/weapon/gun/energy/taser/xeno
+ sort_string = "TBAAC"
+
+// Phase Weapons
+/datum/design/item/weapon/phase_pistol
+ id = "phasepistol"
+ req_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 4000)
+ build_path = /obj/item/weapon/gun/energy/phasegun/pistol
+ sort_string = "TPAAA"
+
+/datum/design/item/weapon/phase_carbine
+ id = "phasecarbine"
+ req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2, TECH_POWER = 2)
+ materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 1500)
+ build_path = /obj/item/weapon/gun/energy/phasegun
+ sort_string = "TPAAB"
+
+/datum/design/item/weapon/phase_rifle
+ id = "phaserifle"
+ req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3)
+ materials = list(DEFAULT_WALL_MATERIAL = 7000, "glass" = 2000, "silver" = 500)
+ build_path = /obj/item/weapon/gun/energy/phasegun/rifle
+ sort_string = "TPAAC"
+
+/datum/design/item/weapon/phase_cannon
+ id = "phasecannon"
+ req_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 4, TECH_POWER = 4)
+ materials = list(DEFAULT_WALL_MATERIAL = 10000, "glass" = 2000, "silver" = 1000, "diamond" = 750)
+ build_path = /obj/item/weapon/gun/energy/phasegun/cannon
+ sort_string = "TPAAD"
\ No newline at end of file
diff --git a/code/modules/shieldgen/handheld_defuser.dm b/code/modules/shieldgen/handheld_defuser.dm
index a2909fa7e6e..d65a0060a8e 100644
--- a/code/modules/shieldgen/handheld_defuser.dm
+++ b/code/modules/shieldgen/handheld_defuser.dm
@@ -7,11 +7,6 @@
var/obj/item/weapon/cell/device/cell
var/enabled = 0
-/obj/item/weapon/shield_diffuser/update_icon()
- if(enabled)
- icon_state = "hdiffuser_on"
- else
- icon_state = "hdiffuser_off"
/obj/item/weapon/shield_diffuser/New()
cell = new(src)
@@ -24,6 +19,9 @@
processing_objects.Remove(src)
. = ..()
+/obj/item/weapon/shield_diffuser/get_cell()
+ return cell
+
/obj/item/weapon/shield_diffuser/process()
if(!enabled)
return
@@ -34,6 +32,12 @@
if(istype(S) && cell.checked_use(10 KILOWATTS * CELLRATE))
qdel(S)
+/obj/item/weapon/shield_diffuser/update_icon()
+ if(enabled)
+ icon_state = "hdiffuser_on"
+ else
+ icon_state = "hdiffuser_off"
+
/obj/item/weapon/shield_diffuser/attack_self()
enabled = !enabled
update_icon()
diff --git a/code/modules/surgery/external_repair.dm b/code/modules/surgery/external_repair.dm
new file mode 100644
index 00000000000..b26d803b343
--- /dev/null
+++ b/code/modules/surgery/external_repair.dm
@@ -0,0 +1,215 @@
+//Procedures in this file: Organic limb repair
+//////////////////////////////////////////////////////////////////
+// LIMB REPAIR SURGERY //
+//////////////////////////////////////////////////////////////////
+/datum/surgery_step/repairflesh/
+ priority = 1
+ can_infect = 1
+ blood_level = 1
+ req_open = 1
+
+/datum/surgery_step/repairflesh/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if (target.stat == DEAD) // Sorry defibs, your subjects need to have pumping fluids for these to work.
+ return 0
+ if (isslime(target))
+ return 0
+ if (target_zone == O_EYES || target_zone == O_MOUTH)
+ return 0
+ if (!hasorgans(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if (affected == null)
+ return 0
+ if (affected.is_stump())
+ return 0
+ if (affected.robotic >= ORGAN_ROBOT)
+ return 0
+ return 1
+
+
+//////////////////////////////////////////////////////////////////
+// SCAN STEP //
+//////////////////////////////////////////////////////////////////
+
+/datum/surgery_step/repairflesh/scan_injury
+ allowed_tools = list(
+ /obj/item/weapon/autopsy_scanner = 100,
+ /obj/item/device/healthanalyzer = 80,
+ /obj/item/device/analyzer = 10
+ )
+
+ priority = 2
+
+ can_infect = 0 //The only exception here. Sweeping a scanner probably won't transfer many germs.
+
+ min_duration = 20
+ max_duration = 40
+
+/datum/surgery_step/repairflesh/scan_injury/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(affected.burn_stage || affected.brute_stage)
+ return 0
+ return 1
+ return 0
+
+/datum/surgery_step/repairflesh/scan_injury/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] begins scanning [target]'s [affected] with \the [tool].", \
+ "You begin scanning [target]'s [affected] with \the [tool].")
+ ..()
+
+/datum/surgery_step/repairflesh/scan_injury/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user] finishes scanning [target]'s [affected].", \
+ "You finish scanning [target]'s [affected].")
+ if(affected.brute_dam)
+ to_chat(user, "The muscle in [target]'s [affected] is notably bruised.")
+ if(affected.status & ORGAN_BROKEN)
+ to_chat(user, "\The [target]'s [affected] is broken!")
+ affected.brute_stage = max(1, affected.brute_stage)
+ if(affected.burn_dam)
+ to_chat(user, "\The muscle in [target]'s [affected] is notably charred.")
+ affected.burn_stage = max(1, affected.burn_stage)
+
+/datum/surgery_step/repairflesh/scan_injury/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user]'s hand slips, dropping \the [tool] onto [target]'s [affected]!" , \
+ "Your hand slips, dropping \the [tool] onto [target]'s [affected]!" )
+ affected.createwound(BRUISE, 10)
+
+//////////////////////////////////////////////////////////////////
+// BURN STEP //
+//////////////////////////////////////////////////////////////////
+
+/datum/surgery_step/repairflesh/repair_burns
+ allowed_tools = list(
+ /obj/item/stack/medical/advanced/ointment = 100,
+ /obj/item/weapon/surgical/FixOVein = 100,
+ /obj/item/weapon/surgical/hemostat = 60,
+ /obj/item/stack/medical/ointment = 50,
+ /obj/item/weapon/tape_roll = 30,
+ /obj/item/taperoll = 10
+ )
+
+ priority = 3
+
+ min_duration = 90
+ max_duration = 120
+
+/datum/surgery_step/repairflesh/repair_burns/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(affected.burn_stage < 1 || !(affected.burn_dam))
+ return 0
+ if(affected.burn_dam < affected.brute_dam)
+ return 0
+ return 1
+ return 0
+
+/datum/surgery_step/repairflesh/repair_burns/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll))
+ user.visible_message("[user] begins taping up [target]'s [affected] with \the [tool].", \
+ "You begin taping up [target]'s [affected] with \the [tool].")
+ affected.jostle_bone(10)
+ else if(istype(tool, /obj/item/weapon/surgical/hemostat) || istype(tool, /obj/item/weapon/surgical/FixOVein))
+ user.visible_message("[user] begins mending the charred blood vessels in [target]'s [affected] with \the [tool].", \
+ "You begin mending the charred blood vessels in [target]'s [affected] with \the [tool].")
+ else
+ user.visible_message("[user] begins coating the charred tissue in [target]'s [affected] with \the [tool].", \
+ "You begin coating the charred tissue in [target]'s [affected] with \the [tool].")
+ ..()
+
+/datum/surgery_step/repairflesh/repair_burns/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll))
+ user.visible_message("[user] finishes taping up [target]'s [affected] with \the [tool].", \
+ "You finish taping up [target]'s [affected] with \the [tool].")
+ affected.createwound(BRUISE, 10)
+ affected.heal_damage(0, 25, 0, 0)
+ if(!(affected.burn_dam))
+ affected.burn_stage = 0
+ if(istype(tool, /obj/item/stack))
+ var/obj/item/stack/T = tool
+ T.use(1)
+ ..()
+
+/datum/surgery_step/repairflesh/repair_burns/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user]'s hand slips, tearing up [target]'s [affected] with \the [tool].", \
+ "Your hand slips, tearing up [target]'s [affected] with \the [tool].")
+ affected.createwound(BRUISE, 10)
+ affected.createwound(CUT, 5)
+ if(istype(tool, /obj/item/stack) && prob(30))
+ var/obj/item/stack/T = tool
+ T.use(1)
+ ..()
+
+//////////////////////////////////////////////////////////////////
+// BRUTE STEP //
+//////////////////////////////////////////////////////////////////
+
+/datum/surgery_step/repairflesh/repair_brute
+ allowed_tools = list(
+ /obj/item/stack/medical/advanced/bruise_pack = 100,
+ /obj/item/weapon/surgical/cautery = 100,
+ /obj/item/weapon/surgical/bonesetter = 60,
+ /obj/item/stack/medical/bruise_pack = 50,
+ /obj/item/weapon/tape_roll = 40,
+ /obj/item/taperoll = 10
+ )
+
+ priority = 3
+
+ min_duration = 90
+ max_duration = 120
+
+/datum/surgery_step/repairflesh/repair_brute/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ if(..())
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(affected.brute_stage < 1 || !(affected.brute_dam))
+ return 0
+ if(affected.brute_dam < affected.burn_dam)
+ return 0
+ return 1
+ return 0
+
+/datum/surgery_step/repairflesh/repair_brute/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll))
+ user.visible_message("[user] begins taping up [target]'s [affected] with \the [tool].", \
+ "You begin taping up [target]'s [affected] with \the [tool].")
+ affected.jostle_bone(10)
+ else if(istype(tool, /obj/item/weapon/surgical/FixOVein) || istype(tool, /obj/item/weapon/surgical/bonesetter))
+ user.visible_message("[user] begins mending the torn tissue in [target]'s [affected] with \the [tool].", \
+ "You begin mending the torn tissue in [target]'s [affected] with \the [tool].")
+ else
+ user.visible_message("[user] begins coating the tissue in [target]'s [affected] with \the [tool].", \
+ "You begin coating the tissue in [target]'s [affected] with \the [tool].")
+ ..()
+
+/datum/surgery_step/repairflesh/repair_brute/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ if(istype(tool, /obj/item/weapon/tape_roll) || istype(tool, /obj/item/taperoll))
+ user.visible_message("[user] finishes taping up [target]'s [affected] with \the [tool].", \
+ "You finish taping up [target]'s [affected] with \the [tool].")
+ affected.createwound(BRUISE, 10)
+ affected.heal_damage(25, 0, 0, 0)
+ if(!(affected.brute_dam))
+ affected.brute_stage = 0
+ if(istype(tool, /obj/item/stack))
+ var/obj/item/stack/T = tool
+ T.use(1)
+ ..()
+
+/datum/surgery_step/repairflesh/repair_brute/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ user.visible_message("[user]'s hand slips, tearing up [target]'s [affected] with \the [tool].", \
+ "Your hand slips, tearing up [target]'s [affected] with \the [tool].")
+ affected.createwound(BRUISE, 10)
+ affected.createwound(CUT, 5)
+ if(istype(tool, /obj/item/stack) && prob(30))
+ var/obj/item/stack/T = tool
+ T.use(1)
+ ..()
diff --git a/code/modules/surgery/neck.dm b/code/modules/surgery/neck.dm
index 240db44c042..5b1522d60c2 100644
--- a/code/modules/surgery/neck.dm
+++ b/code/modules/surgery/neck.dm
@@ -219,7 +219,6 @@
priority = 3 //Do this instead of searching for objects in the skull.
allowed_tools = list(
/obj/item/weapon/surgical/hemostat = 100,
- /obj/item/weapon/tool/wirecutters = 60,
/obj/item/weapon/melee/changeling/claw = 20) //Claws. Good for digging, not so much for moving.
allowed_procs = list(IS_WIRECUTTER = 60)
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index 73f4beb6d6c..2f2e1cb44ac 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -20,9 +20,10 @@
/datum/surgery_step/internal/remove_embryo
allowed_tools = list(
/obj/item/weapon/surgical/hemostat = 100, \
- /obj/item/weapon/tool/wirecutters = 75, \
/obj/item/weapon/material/kitchen/utensil/fork = 20
)
+
+ allowed_procs = list(IS_WIRECUTTER = 75)
blood_level = 2
min_duration = 80
@@ -212,7 +213,6 @@
allowed_tools = list(
/obj/item/weapon/surgical/hemostat = 100, \
- /obj/item/weapon/tool/wirecutters = 75, \
/obj/item/weapon/material/kitchen/utensil/fork = 20
)
diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm
index 0f59bdd59ef..2f6caf167fd 100644
--- a/code/modules/surgery/robotics.dm
+++ b/code/modules/surgery/robotics.dm
@@ -31,7 +31,9 @@
/obj/item/weapon/coin = 50,
/obj/item/weapon/material/knife = 50
)
+
allowed_procs = list(IS_SCREWDRIVER = 100)
+
req_open = 0
min_duration = 90
@@ -231,7 +233,6 @@
allowed_tools = list(
/obj/item/stack/nanopaste = 100, \
/obj/item/weapon/surgical/bonegel = 30, \
- /obj/item/weapon/tool/screwdriver = 70, \
)
allowed_procs = list(IS_SCREWDRIVER = 100)
diff --git a/code/modules/xenoarcheaology/tools/equipment.dm b/code/modules/xenoarcheaology/tools/equipment.dm
index 186745a2771..5bc7694df54 100644
--- a/code/modules/xenoarcheaology/tools/equipment.dm
+++ b/code/modules/xenoarcheaology/tools/equipment.dm
@@ -4,6 +4,7 @@
icon = 'icons/obj/clothing/spacesuits.dmi'
icon_state = "engspace_suit"
item_state = "engspace_suit"
+ update_icon_define = "icons/mob/spacesuit.dmi"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
/obj/item/clothing/head/bio_hood/anomaly
diff --git a/config/names/first_name_skrell.txt b/config/names/first_name_skrell.txt
new file mode 100644
index 00000000000..122b093765a
--- /dev/null
+++ b/config/names/first_name_skrell.txt
@@ -0,0 +1,600 @@
+Kaexae
+Xaaq'xuer
+Xaaq'taq
+Kae'xer
+Xeq'aeq'qerr
+Ke'xuer
+Xeteq
+Kae'xum
+Kerrker
+Kerrquex'xum
+Taeqxuq
+Kae'quex'xeu
+Keqaeq'xeu
+Ke'ter
+Xue'xerr
+Keqqux'kea
+Qerrqux
+Kerrxae'qer
+Taeqxerr
+Kerr'xum
+Kaexuer
+Qerr'xaeq'xeu
+Xue'xum
+Xeqteq'qerr
+Kerrkeax'qux
+Xaaq'qux
+Xae'xuer
+Xertaq'qux
+Xum'xuer
+Keq'taq'kea
+Keq'quex'xeu
+Qerraeq
+Xeq'xum
+Xeq'qux'xum
+Xer'xuq
+Keq'teq
+Kae'keax
+Keqxer
+Kae'xerr'xeu
+Xaequx
+Ke'teq'xum
+Xaaqxerr
+Xer'keax'kea
+Qerrxae'qux
+Xae'xer
+Qerrteq
+Xeq'xuer
+Xe'xaeq'xum
+Xeteq'qerr
+Xaaq'aeq'xeu
+Xae'xaeq'qer
+Keaeq'xum
+Xaaq'teq
+Keq'ker
+Ke'keax
+Kexum'kea
+Xeq'xum
+Qerr'xaeq'kea
+Xexum
+Taeq'xer'xe
+Qerraeq
+Xeq'keax'qux
+Xuequx
+Kexuq
+Teqxaeq'qer
+Xeqtaq'qer
+Xaexuq
+Xueaeq'qux
+Taeqxae
+Keqxuer
+Xum'aeq
+Xeqkeax'kea
+Kerrxuer
+Xaeteq
+Keqxaeq'qerr
+Xum'quex
+Taeq'teq
+Xer'xaeq
+Teq'taq
+Xe'xuq
+Kerrxer
+Kerr'xaeq'kea
+Xeqteq
+Xeqxuq'qerr
+Kerr'xum'xe
+Xe'qux
+Xexaeq
+Qerrxaeq'qer
+Teqqux'kea
+Ke'xuer
+Xerqux'xeu
+Kaexaeq'xeu
+Xeq'qux
+Xeker
+Ke'xae
+Kerrxae'qux
+Kae'aeq'qerr
+Xeq'qux'xeu
+Xeqquex'xeu
+Kerr'xaeq
+Kerr'aeq
+Xaaqxae
+Xertaq'qux
+Xaaq'ker'xum
+Kae'xuer'xe
+Xue'aeq'xeu
+Qerr'xuq
+Kequex'qerr
+Xer'ter'xe
+Qerr'ter'qerr
+Xeq'keax'qux
+Keq'ker
+Ke'qux'qerr
+Xumter'qux
+Xue'qux'xe
+Xaeaeq
+Xumxuer'xeu
+Kerr'xuq'qux
+Keq'xaeq
+Xum'xuq'xeu
+Kerr'xer
+Xae'keax
+Kequex
+Kae'qux
+Keqkeax
+Qarrker
+Xaaqker'xum
+Xue'xaeq'qux
+Taeq'xaeq'xe
+Xue'xerr
+Teqkeax
+Xaaq'keax
+Ke'xaeq'qer
+Kerrxuer
+Kaeter'qux
+Qarr'xerr
+Xerxum'qux
+Xumqux
+Taeq'teq'xeu
+Qerrxuer'qer
+Xe'ker
+Qerrter'kea
+Kaeteq'qux
+Teq'xuer'xum
+Ke'xae'xeu
+Teqxuq'qer
+Keq'xaeq
+Xaaq'xae
+Xum'xer
+Xeter
+Xaaq'quex'kea
+Kexum
+Qarrkeax'qer
+Keq'xerr
+Qarrxerr'qerr
+Qarrxerr'qer
+Xer'ker
+Xaexum'xe
+Kaexerr'qux
+Xuexum
+Xaaq'xer
+Qerr'quex
+Qerr'ker
+Xum'teq'qerr
+Kerrxaeq
+Xeq'xae
+Xue'aeq'xe
+Qarr'xuer
+Qarr'xerr'qerr
+Kaexerr'xum
+Kaeter'xum
+Xuexuq
+Xuekeax'xeu
+Xaaq'ker
+Keqxer
+Teq'xer
+Qarrker
+Xer'ter
+Xae'ter'kea
+Ke'quex'xe
+Xaeter
+Xer'xae
+Qarr'xae'xum
+Xeqxuq
+Keqter'xum
+Xeker
+Taeqxerr'qer
+Keqxer'kea
+Xumquex
+Xaaq'xuq
+Kerrxum
+Xexerr
+Xerxerr'qerr
+Xaaq'xerr
+Xum'ker'qer
+Xequx
+Xer'xae
+Kaexerr'xe
+Xe'taq
+Xeq'xuer'qerr
+Xue'taq
+Teqxer
+Xaaq'xerr'xe
+Xer'quex'xum
+Xaeaeq
+Taeqaeq
+Xaeter'qer
+Xerkeax
+Xuequex'xe
+Keqxerr
+Taeqxae'qer
+Teqqux
+Xae'quex'qux
+Xe'xum
+Xaaqxer
+Xeq'aeq'xum
+Xuexuq'qerr
+Xe'taq'qux
+Qarr'xae
+Xe'keax'qer
+Qerrxum'qerr
+Xer'xer
+Qarr'quex'qerr
+Taeq'xer'qux
+Taeqtaq
+Ke'aeq'xum
+Xueter
+Kaeker
+Xeter'kea
+Qarrter
+Qerrxae
+Xaaqxum'xeu
+Xum'xuer
+Xe'xae
+Qarrter'qer
+Kequx
+Kerr'aeq'kea
+Teq'taq'kea
+Xexum'qerr
+Qerr'quex'xeu
+Xeker'qux
+Kerr'quex'qerr
+Xum'ker'qer
+Keqxuq'xeu
+Keqxuq'xeu
+Xer'teq'xum
+Kaeker'qerr
+Xumtaq
+Xexuer
+Xueter'xum
+Kaeteq
+Ke'teq
+Qerrxuq
+Teq'xum'qerr
+Xaaq'xae
+Keter'xum
+Xeqqux
+Xae'taq
+Qerrtaq'qux
+Keq'ter
+Xaequex'xum
+Kaeter
+Xaaqtaq
+Kae'xer'qer
+Kaequx
+Kae'xum
+Taeqaeq'qux
+Kexaeq'kea
+Xer'xae'qer
+Xae'ker
+Xue'xuer
+Xeq'taq'xe
+Kaexae'qux
+Teq'xae'xe
+Teq'xuer
+Qerrqux'xeu
+Xuexaeq
+Kerr'xuq'kea
+Xerquex'kea
+Keq'ker
+Kaexum
+Kerrquex
+Kexer
+Keq'quex'qerr
+Xae'xae
+Qerr'ker
+Kexerr
+Xaaqquex
+Keq'quex'xum
+Xerter'qux
+Xuexaeq'xe
+Xae'xuq'kea
+Kae'xuer'kea
+Xer'xum'kea
+Xer'quex'kea
+Kerrxuq'qux
+Qerrxuer
+Xeq'xerr'qerr
+Qarr'xuq'qux
+Xaaq'xuq
+Xerxaeq'qux
+Xertaq
+Kerr'teq'xeu
+Xer'aeq'kea
+Xe'ter'qerr
+Teq'xae
+Kerrxerr
+Taeqxaeq
+Xueker
+Keqxae'qerr
+Taeqkeax
+Kexaeq'xum
+Xuekeax'xe
+Xumxum
+Xeq'ter'xeu
+Taeqquex
+Xer'xer
+Keqxae'xeu
+Kaexum
+Keq'xaeq
+Qerr'quex'xum
+Kaexuq'qux
+Xaequx'xe
+Kae'xum
+Keqkeax
+Kexuer
+Xeter
+Xexuq'xeu
+Xe'aeq
+Xum'keax'xe
+Xer'ker'xum
+Xerxuq'qer
+Xaekeax'xe
+Kaequex'xe
+Keqxer
+Xeker'qer
+Teqker'qerr
+Keqxer
+Teq'xer
+Xaaq'xum
+Qerrter
+Ke'xuer
+Kae'xerr'xeu
+Qarrteq'kea
+Teq'aeq'qux
+Teq'xum'qux
+Xae'xuq
+Xaekeax
+Qerr'teq
+Kerrteq'qer
+Keqxerr
+Qarr'xerr'xum
+Kekeax
+Xae'xae'kea
+Xumteq
+Xuequx'qer
+Qarr'xer
+Taeq'xuq
+Ke'xum
+Kae'xerr
+Xumxum'qerr
+Keqteq'qer
+Teqker'qerr
+Qarr'keax
+Xeqxer
+Qarrxuq'xe
+Keqkeax
+Xaaq'ter'kea
+Xaaq'aeq
+Kerr'keax
+Keqxuer
+Qerr'xerr'kea
+Qarr'teq'qerr
+Kerr'teq'qerr
+Qarr'taq'qer
+Qarrxuer'xeu
+Kae'ter
+Keaeq'xum
+Teqker'xum
+Xaaq'aeq'qux
+Keq'qux'qer
+Xae'xuq'kea
+Ke'xuq'qux
+Qerr'qux
+Xaaq'qux'qer
+Xue'keax
+Xaaqxerr'kea
+Taeqteq'xe
+Xuetaq
+Xaaqxuq'qerr
+Qerrxae'xe
+Xeqxuer
+Xeqxaeq'xum
+Xue'ker'qer
+Kekeax'xeu
+Qarr'xae'qux
+Xae'ker'qux
+Qarr'xum'xum
+Xum'xaeq'xeu
+Qerrxer'qerr
+Xaeaeq'qer
+Xaaq'quex'qerr
+Qerr'aeq
+Xum'taq
+Kerr'xum'xeu
+Xaeaeq'kea
+Taeqxerr'kea
+Taeq'qux'xum
+Xaaq'xae
+Qerr'quex
+Qarrker
+Qarr'qux'xeu
+Xaaqaeq'qux
+Xuetaq
+Xaexum
+Xae'xaeq
+Xaaq'taq'xe
+Kerrxaeq'xe
+Kae'xer'kea
+Kerr'xae'qer
+Keqxum'qer
+Qarr'taq'xe
+Taeq'quex'qer
+Xum'xuer
+Xer'xuq'qerr
+Xeqteq'xum
+Xae'xaeq
+Xaekeax'qer
+Xeq'xum
+Qarr'ter'qer
+Qarr'xerr
+Kae'xae'xum
+Taeq'xuq
+Kae'xuq'kea
+Xue'xum'qux
+Xae'xerr
+Taeq'xaeq
+Xaexuq
+Xaequx
+Keqter
+Kae'xuer
+Xaaqaeq
+Kae'taq'xeu
+Keqter'kea
+Taeqaeq
+Xae'qux
+Qerr'qux
+Qarr'xuq'kea
+Xeq'xuer
+Keqqux
+Xaaq'taq'xum
+Kae'xerr
+Xue'xae'kea
+Qarraeq
+Taeq'xum
+Qerrxer
+Teq'xum
+Xaaq'ker'xeu
+Kerr'xaeq
+Xaaq'xerr'xeu
+Xaaqxuq'xeu
+Taeqter'qer
+Teq'xuer
+Xaaqker
+Qerr'xaeq'qux
+Qerr'quex'qux
+Xaaqxerr
+Keqtaq'xeu
+Kerrxuq
+Taeqxuq'xe
+Taeq'xuq
+Xexuq'qerr
+Taeq'xae'qux
+Kerr'aeq'qer
+Teqtaq
+Qerr'taq'xeu
+Xeqxaeq'kea
+Keteq
+Qarr'quex'xeu
+Kae'xer
+Xaaqxuer
+Xum'xum
+Taeqquex'xeu
+Xue'teq
+Xumxuq
+Teqxer
+Xaeteq'xum
+Kaexum'qerr
+Xaaq'qux
+Xe'xum
+Qerr'xaeq
+Keqxaeq'xe
+Xum'xerr
+Xuexaeq'xum
+Xaaq'xum'kea
+Xumteq
+Teq'keax'xeu
+Xaequex
+Ke'ker'kea
+Xeq'xuq
+Xaaq'quex'xeu
+Teq'teq'qux
+Qarr'keax
+Xequex
+Xeqqux
+Xerxerr'xum
+Kae'teq
+Xaaq'qux'xum
+Xuetaq'qer
+Xaexerr
+Xexuer
+Xaaq'xerr'qer
+Xexae'kea
+Xaexuq'qer
+Xe'ker
+Keq'quex'kea
+Qarrqux'qux
+Xaaqtaq'kea
+Teqxae
+Teq'xuq
+Ke'aeq
+Xae'aeq
+Kerr'ter
+Xue'xuq'qer
+Ke'xaeq
+Taeq'xuer'xeu
+Xeq'xae
+Qerrkeax'kea
+Xae'xuq
+Teq'keax
+Qerr'teq'qer
+Kaexuq'xe
+Qarrxaeq'xeu
+Qerrtaq
+Xe'ker'xum
+Kaexuer
+Teqxuer'xe
+Xumxuer'kea
+Kerr'xuer
+Xer'teq'xum
+Xumteq'qerr
+Ke'quex
+Taeq'aeq'qerr
+Xue'ter'xe
+Xeq'xae'xeu
+Xer'xum
+Qarr'xae
+Qerrker'qux
+Taeq'keax'xeu
+Xum'quex'xeu
+Kae'ter
+Xe'quex'xe
+Keqxum
+Kerr'quex'qer
+Xaaqxae'qer
+Xaaqteq'qer
+Keqqux
+Teq'aeq
+Keteq
+Xumxae'xum
+Xumxum
+Qarrxaeq'kea
+Keker
+Xeq'aeq'qer
+Teqter
+Qarrxaeq'kea
+Teq'quex
+Keqxum
+Teq'xuer
+Xumter'kea
+Qarr'xae
+Xae'xuer'xeu
+Xaaqxaeq'kea
+Qerr'xuq'xeu
+Xum'xae'qux
+Xumxaeq
+Xumxum
+Kexum'xe
+Kae'aeq
+Xer'teq
+Qarrxerr'xum
+Taeq'taq
+Taeq'taq'qux
+Kaexum'xeu
+Xumtaq
+Xae'xer
+Kerr'ker
+Qarr'xum'qer
+Qerr'xuer'qux
+Xue'qux'xe
+Qerr'qux'xum
+Teqquex'qerr
+Taeqquex
+Qarrxerr
+Ketaq
+Xekeax
+Kequex
+Xetaq
+Ke'xae'xe
+Teq'quex'qux
diff --git a/config/names/last_name_skrell.txt b/config/names/last_name_skrell.txt
new file mode 100644
index 00000000000..5f67fbc5365
--- /dev/null
+++ b/config/names/last_name_skrell.txt
@@ -0,0 +1,600 @@
+Xer'taq'qer
+Xaaq'ter'qux
+Xaaq'xuer
+Xerxuer'xum
+Qarrqux
+Xueaeq'qux
+Xe'aeq
+Keqter
+Xaexer
+Kaeteq
+Ke'aeq'xeu
+Kerrxum
+Teqxuq'xeu
+Xexaeq
+Qerr'xerr'xum
+Xaeker'qux
+Kexer'kea
+Ke'aeq
+Keqxae'kea
+Qarraeq'xe
+Xuekeax
+Keq'quex
+Kae'quex'qux
+Qerr'taq'xum
+Taeq'taq'xum
+Kae'xaeq'xe
+Xaaq'teq'qux
+Teqker
+Qerrxum'xeu
+Xeq'xaeq'xe
+Kae'keax
+Xue'xae
+Taeq'taq
+Keter'xeu
+Xumker'xe
+Teqteq
+Xexuer
+Qerrxerr
+Kaequex'qerr
+Kaequx'xe
+Xum'xaeq
+Xe'taq
+Xuexer
+Xe'qux'xeu
+Xe'xerr'kea
+Qerr'xum
+Xaaqtaq
+Xuexum'xum
+Qerrxer
+Xaexuq
+Xeq'aeq
+Xaaq'xaeq
+Xerqux
+Xeq'xuq'xeu
+Kaexum
+Taeqteq'xeu
+Kerrter'qux
+Xeq'teq
+Teqxae'xe
+Xae'ker'kea
+Keqxuq
+Xumxae'kea
+Xeq'xerr'kea
+Kae'quex
+Kae'ter
+Teqter'xe
+Xeq'xerr'xeu
+Xerxum'qux
+Xe'qux
+Qarr'aeq
+Xue'xum'xe
+Xaaq'ter'qux
+Teq'xer
+Kerrtaq
+Qerr'aeq
+Xaaq'aeq
+Xaaqxuer
+Qerr'quex
+Kaeker
+Xae'taq
+Teq'xaeq
+Xexuq
+Keqqux
+Kaeker
+Xeqxum
+Xae'taq'qerr
+Kexerr
+Ke'xerr'qux
+Xeraeq'xum
+Kae'qux'qux
+Xerkeax'xum
+Qarrxum
+Kaexuer
+Qerrquex
+Kerr'xer
+Xeq'taq
+Xeqker
+Kerrquex'xum
+Xeteq
+Qarrxuer
+Xaaqqux'qerr
+Xae'xer
+Xae'xae
+Taeqxuer'qerr
+Xumqux'qux
+Xuexerr'qerr
+Ke'xae'xum
+Xerxuer
+Xeqtaq
+Xeqquex
+Xuekeax
+Keq'xuq'qerr
+Xaeter
+Xumxerr
+Xeqxaeq'xe
+Xae'ker
+Qerr'ker
+Xeq'aeq
+Kae'keax
+Qerrkeax
+Xeqxerr
+Keqxaeq
+Xae'xuq
+Kerrkeax'qer
+Qarrxum'xum
+Teq'xum'xeu
+Kerrxer
+Xe'xum
+Kexae'xeu
+Xerxerr'xe
+Xum'ter
+Xe'keax
+Qarr'xer'kea
+Xaaq'aeq
+Xaaqker'qerr
+Ke'ker
+Qerr'xum
+Qerr'xae'xe
+Qarr'ter'xum
+Kaexerr
+Qarrtaq'qux
+Xumxaeq
+Xaeaeq'xe
+Qarr'xae'qux
+Xer'xum'qerr
+Kae'xuq
+Xaaq'qux'kea
+Teqtaq
+Kekeax
+Xe'keax'qerr
+Kerr'keax'qerr
+Xeqkeax
+Xer'xaeq
+Xerter'kea
+Xum'xuq'xe
+Teqaeq
+Ke'teq'qux
+Xer'xuq'kea
+Keq'xum'xeu
+Xerxuer'xeu
+Xum'keax'xum
+Xaaq'ter
+Xuetaq
+Taeq'xuer'qux
+Xuexum'xe
+Xeq'quex'kea
+Xum'xer
+Xeqaeq
+Qerr'ker
+Xumxum
+Xeqxum
+Xae'taq'qerr
+Taeq'ker
+Xue'xae'xe
+Xer'taq'xe
+Xum'xaeq
+Kaexuq'xum
+Kaexuq'qux
+Ke'xum'xum
+Qerr'xerr'xum
+Ke'xuq'qux
+Taeq'xaeq
+Xumtaq
+Xetaq
+Kaexerr'xum
+Kequx
+Xuexerr'xeu
+Xeaeq
+Keq'qux'kea
+Xeq'xaeq
+Xuexum
+Ke'xerr'xe
+Xe'xum
+Kerr'xaeq
+Xeqkeax'qux
+Kaeteq
+Xer'quex
+Teqaeq'qerr
+Xaexerr
+Xaeter
+Xumxuer'qer
+Teqxae
+Taeqtaq'qerr
+Kerr'qux
+Xuequex
+Xaaqtaq'kea
+Teq'keax
+Ke'xuer'kea
+Xum'quex'xeu
+Xaexer'kea
+Kerr'quex'xum
+Qarrxaeq'xum
+Kerr'xaeq'xeu
+Xaaq'xerr'xum
+Xeqxaeq
+Xaaqxae'xeu
+Qerrxae
+Xae'xer
+Xexer
+Qarrter'xe
+Xaaq'taq'xum
+Taeq'aeq
+Teq'xer
+Xaexae'xum
+Ke'aeq
+Teqxuer
+Qerrxuq
+Xaaq'ker
+Xeq'quex
+Kerr'qux
+Xekeax'qerr
+Kerr'qux'xum
+Ke'teq
+Qarrxae'xum
+Qerr'ter'qux
+Qerr'keax
+Taeqxuer'kea
+Qerr'xae
+Keqker'xeu
+Xueter
+Xae'teq'kea
+Xumkeax'qux
+Keq'keax
+Qarr'xerr'qux
+Xuekeax'qerr
+Taeq'xuq'xe
+Keq'aeq'xe
+Xue'xuer'qux
+Qerr'quex'qux
+Xaexerr'qux
+Qerrxaeq
+Qerr'xerr
+Qarr'xuer
+Qerrxae
+Taeq'xaeq'xeu
+Kerr'ter
+Kerrker'qux
+Kaexae'xum
+Kerrtaq'qerr
+Xae'aeq'qer
+Xer'xerr
+Kae'xuer'qux
+Qerr'xer'qerr
+Keq'taq'qer
+Taeqxer'xum
+Xaaq'xuq
+Xue'qux
+Taeq'xaeq
+Xe'teq'xe
+Teq'xuq
+Taeq'xum'qux
+Xaaqter'xum
+Taeq'taq
+Xaaqxerr'qer
+Xuetaq'qerr
+Xum'xae
+Qerrxer'xe
+Qerr'xaeq'kea
+Xeq'ker
+Xeqteq'qerr
+Kerr'aeq'qer
+Xum'teq'qerr
+Xuexuq'kea
+Xue'taq
+Xum'qux'xe
+Kerrker
+Xue'ter'xeu
+Xaexaeq
+Xaexerr'kea
+Teqtaq'kea
+Xuexuer'xe
+Xue'xae'xeu
+Taeq'quex
+Keqteq
+Kae'aeq'xum
+Teqaeq'qerr
+Xaaqxum
+Qarr'teq'qux
+Kaexer
+Xue'xum
+Qerrtaq'qer
+Taeq'teq'qux
+Xueter
+Xum'ker'xe
+Xue'keax
+Xum'quex'qerr
+Kaeaeq'qerr
+Xeqxae
+Keqxuer'xeu
+Xeqxum
+Teqxuq
+Kaeker
+Xaaq'taq
+Keqquex'kea
+Xe'ker
+Xeq'aeq'kea
+Xue'qux
+Xerxuq
+Taeq'quex
+Kequx'qux
+Xueker'qux
+Teqxum'qer
+Kerrxuq'qer
+Xerker
+Xue'xuer
+Xue'qux
+Taeq'xuq
+Keq'qux'xum
+Qarr'quex'xe
+Kae'xer'kea
+Qarr'xum'xeu
+Keqker'xum
+Ketaq
+Xue'teq
+Xuexerr
+Xeqker
+Xe'xum'xeu
+Xeq'ter'qerr
+Taeqxuq
+Kaeter
+Keq'taq
+Xum'xum
+Xumxuer'xum
+Teqter'qerr
+Keq'qux'xe
+Keq'xer'qer
+Xueaeq'xeu
+Taeqxuer'kea
+Keqxae'xeu
+Kae'taq
+Xerkeax
+Xeqker
+Kerrxer
+Taeq'xerr'xe
+Qerr'xerr'qerr
+Xe'ker'xe
+Kae'qux'qerr
+Kaequex
+Xaaq'teq'qer
+Xumxerr
+Xe'quex
+Qerr'xum'qux
+Qerrxae
+Qerrquex
+Kae'xae'qerr
+Qarrquex
+Kerrxae
+Xaaq'taq'xeu
+Qarr'xae'qux
+Xeqker
+Xaaqxuq'qer
+Xaaqter
+Xerxerr
+Xue'taq'qer
+Qarrxer'qerr
+Xae'ter'xum
+Kerrter'qerr
+Kerrter'kea
+Xae'aeq
+Xe'xer
+Teq'keax'xeu
+Kexum'xe
+Xueteq
+Kae'keax
+Xaaq'keax
+Xaaq'quex'qux
+Taeqqux
+Taeq'xum
+Xerxuer
+Qerrxer
+Xaexuer
+Teqter
+Qarr'xer
+Qarrxaeq'xum
+Ke'teq
+Teq'xae
+Kaexerr
+Qarr'teq
+Xer'ker
+Xaexuer'qux
+Xeq'qux
+Taeqxer
+Taeqxaeq
+Xumxuer
+Taeqxuer'qerr
+Kae'xuer
+Qerrter
+Taeq'aeq'kea
+Taeq'xer'xum
+Kerrter
+Xum'xuer
+Xue'ker'qux
+Xaaqter'qux
+Xue'ter'xe
+Xueteq
+Xaaq'xae
+Xaexerr'qerr
+Ke'aeq'qerr
+Xaaq'xuq'xeu
+Xuekeax
+Xumteq
+Xexuq
+Taeq'ker'xeu
+Xaaqaeq
+Qarrxum
+Xerxuq'xum
+Kaexerr
+Xeq'ter'xeu
+Keqaeq
+Xeqxuer'xum
+Teqkeax'xeu
+Kae'aeq'kea
+Ke'xerr
+Ke'xuq
+Kae'quex
+Xeqxae
+Kaeter
+Xeqxer
+Kae'xuer
+Taeqtaq'xum
+Teq'qux'xeu
+Xaequex'xum
+Qarrquex
+Xaaq'qux
+Keqquex
+Qerrker'qerr
+Xexae'xe
+Xerxae
+Xaaqker'kea
+Kexer'qerr
+Xaeaeq
+Xaaqqux
+Qarr'xer'qer
+Keq'xuq
+Kae'keax
+Qerr'teq'qer
+Kae'xaeq'qer
+Xaexer
+Kerrxer'xeu
+Kaekeax
+Xaaq'xaeq'xeu
+Xae'xae
+Qarr'keax
+Teqqux'qerr
+Xeq'ter'qerr
+Taeq'ker
+Qerrteq'xeu
+Keqqux'xeu
+Xaaqteq'qerr
+Teqteq'xe
+Xaaqter
+Xaaqkeax
+Xeqqux
+Xaaq'xerr
+Teq'ker'qerr
+Xer'taq'qerr
+Qarrxum'qux
+Xum'taq'qux
+Qarr'xer'xeu
+Xerxerr'qux
+Kerr'teq
+Xum'taq'kea
+Xaequex
+Kaeaeq'xe
+Xe'xaeq'xum
+Xuexuer'qer
+Kerrxuq
+Kerrxuer'qerr
+Kaeteq
+Xaaqxuer
+Xeq'xum'qerr
+Xumxer
+Xe'ter'xeu
+Xueaeq
+Keq'keax
+Xueter
+Xaexaeq
+Keqxaeq
+Ke'aeq
+Xumxum'qerr
+Xumxae'xum
+Xaaqxuer
+Ke'ker
+Ke'xer
+Xuekeax'qerr
+Keq'teq
+Kerr'ter'qux
+Xe'xerr
+Qerrxae
+Ke'quex'xeu
+Keqxuq
+Kerrxuer
+Keq'xae
+Qarr'xuq
+Xumxuq
+Qarr'teq'qer
+Xe'xae'xeu
+Xuexum
+Xequx
+Xaaq'teq'xum
+Xue'xuq
+Kae'quex'qer
+Qarrxer'qerr
+Xumaeq'xeu
+Qarrkeax
+Kae'xer'qux
+Xeq'qux'qer
+Xueker'qux
+Teqquex
+Xae'xaeq'xum
+Taeqkeax
+Xaaq'teq'qux
+Keqxerr'xe
+Xue'ter'xe
+Xe'xaeq
+Qerrker
+Xaexum'qer
+Keqteq'xum
+Taeq'xae'xum
+Kaexuer'qux
+Xe'ter
+Xae'taq'qux
+Qarr'aeq
+Xae'xum
+Qarrxum'xum
+Keqxer'xum
+Qarr'xerr
+Teqxae
+Ke'xae'xe
+Teqkeax'qux
+Xe'taq
+Xaetaq
+Keq'teq'kea
+Keqxaeq
+Xue'xuq
+Qarr'xerr'qer
+Xequex
+Keqxum
+Keqtaq
+Qarr'ker'xum
+Kerr'xer'qer
+Kerrxae'xum
+Xum'xae
+Kaequex'qux
+Xuequx'xe
+Xumquex'qer
+Taeqker
+Xae'quex
+Xer'teq'xe
+Xerxerr
+Ke'xuq'qer
+Taeqxerr'kea
+Xaaq'xaeq'kea
+Keq'teq
+Xue'aeq'xeu
+Xaaqxer'xeu
+Ke'ker'qerr
+Xue'quex
+Taeqtaq
+Teqter
+Kequex'xe
+Xuexuer'qerr
+Xeqxum
+Xue'taq
+Xer'xuq'qerr
+Xeqxaeq'xe
+Qerr'xaeq
+Xeqxae'qer
+Taeqtaq'kea
+Xer'teq
+Qerr'xaeq'xum
+Xaaq'xae
+Xum'xuq
+Xaaqxaeq
+Xaexum
+Xaaqxum'xe
+Xertaq
+Xuexuq'qerr
+Xaaq'xae'kea
+Qerr'teq'qer
diff --git a/html/changelog.html b/html/changelog.html
index 9c933a1741d..f3acb4a5d61 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -53,6 +53,66 @@
-->
+
01 August 2018
+
KasparoVv updated:
+
+ - You can now change the order of your body markings at character creation. Shift markings up or down layers at will to design the character you've always wanted, more easily than ever before.
+
+
Mechoid updated:
+
+ - Added the Gigaphone. Currently unused.
+
+
Mewchild updated:
+
+ - Ports several AI core sprites from ages and places past
+
+
PrismaticGynoid updated:
+
+ - Adds four types of colorblindness to the traits in the setup menu.
+ - pAIs can now be picked up while unfolded, and can display more than 9 emotions.
+
+
+
14 July 2018
+
Anewbe updated:
+
+ - Certain languages now require assistance for a species to speak, but not understand, much like EAL.
+ - Alai can only be `spoken` by Taj and Teshari.
+ - Adds a voicebox/larynx organ. Its only purpose at the moment is to assist in speaking certain langauges.
+ - Language implants, like the EAL implant, now affect the voicebox organ, instead of being a freefloating implant.
+ - Adds a language implant for Common Skrellian.
+
+
Atermonera updated:
+
+ - Steel sheets can be used to construct Roofing Tiles
+ - Roofing tiles can be used on tiles under open spaces or space tiles in multiZ maps to place a lattice and plating on the space above
+ - Roofing tiles can be used on outdoor turfs to make them indoors
+ - Both functions work together on multiZ maps with outdoor turfs, only one roofing tile is used per tile roofed.
+
+
Mechoid updated:
+
+ - Adds a new surgical procedure for fixing brute and burn on limbs.
+
+
+
12 July 2018
+
Anewbe updated:
+
+ - Technomancer Apportation now properly checks for range and scepter, again.
+
+
+
21 June 2018
+
Anewbe updated:
+
+ - Added a biomass reagent, made from protein, sugar, and phoron.
+ - Cloners and bioprinters now use the biomass reagent. Both can be refilled or have their capacity increased by replacing the bottles they spawn with.
+ - Mapped in a bioprinter, for further testing.
+ - Adds the ability to make robolimb brands more or less vulnerable to brute or burn.
+ - Makes VeyMed limbs more vulnerable to brute and burn.
+
+
Mechoid updated:
+
+ - Allow AIs to create and take control of mindless drones from fabricators.
+
+
08 June 2018
Anewbe updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 56db08c0243..3d08f883641 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -4156,3 +4156,48 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- bugfix: Ion rifles hit the correct 3x3 instead of 5x5
- rscadd: Seed Storage Vendors are now hackable. Can choose from various lists of
concerning plants.
+2018-06-21:
+ Anewbe:
+ - rscadd: Added a biomass reagent, made from protein, sugar, and phoron.
+ - tweak: Cloners and bioprinters now use the biomass reagent. Both can be refilled
+ or have their capacity increased by replacing the bottles they spawn with.
+ - experiment: Mapped in a bioprinter, for further testing.
+ - rscadd: Adds the ability to make robolimb brands more or less vulnerable to brute
+ or burn.
+ - rscdel: Makes VeyMed limbs more vulnerable to brute and burn.
+ Mechoid:
+ - rscadd: Allow AIs to create and take control of mindless drones from fabricators.
+2018-07-12:
+ Anewbe:
+ - bugfix: Technomancer Apportation now properly checks for range and scepter, again.
+2018-07-14:
+ Anewbe:
+ - tweak: Certain languages now require assistance for a species to speak, but not
+ understand, much like EAL.
+ - tweak: Alai can only be `spoken` by Taj and Teshari.
+ - rscadd: Adds a voicebox/larynx organ. Its only purpose at the moment is to assist
+ in speaking certain langauges.
+ - tweak: Language implants, like the EAL implant, now affect the voicebox organ,
+ instead of being a freefloating implant.
+ - rscadd: Adds a language implant for Common Skrellian.
+ Atermonera:
+ - rscadd: Steel sheets can be used to construct Roofing Tiles
+ - rscadd: Roofing tiles can be used on tiles under open spaces or space tiles in
+ multiZ maps to place a lattice and plating on the space above
+ - rscadd: Roofing tiles can be used on outdoor turfs to make them indoors
+ - rscadd: Both functions work together on multiZ maps with outdoor turfs, only one
+ roofing tile is used per tile roofed.
+ Mechoid:
+ - rscadd: Adds a new surgical procedure for fixing brute and burn on limbs.
+2018-08-01:
+ KasparoVv:
+ - rscadd: You can now change the order of your body markings at character creation.
+ Shift markings up or down layers at will to design the character you've always
+ wanted, more easily than ever before.
+ Mechoid:
+ - rscadd: Added the Gigaphone. Currently unused.
+ Mewchild:
+ - rscadd: Ports several AI core sprites from ages and places past
+ PrismaticGynoid:
+ - rscadd: Adds four types of colorblindness to the traits in the setup menu.
+ - tweak: pAIs can now be picked up while unfolded, and can display more than 9 emotions.
diff --git a/html/changelogs/Anewbe - Robolimb Fragility.yml b/html/changelogs/Anewbe - Robolimb Fragility.yml
deleted file mode 100644
index 74ba5734125..00000000000
--- a/html/changelogs/Anewbe - Robolimb Fragility.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-################################
-# Example Changelog File
-#
-# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
-#
-# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
-# When it is, any changes listed below will disappear.
-#
-# Valid Prefixes:
-# bugfix
-# wip (For works in progress)
-# tweak
-# soundadd
-# sounddel
-# rscadd (general adding of nice things)
-# rscdel (general deleting of nice things)
-# imageadd
-# imagedel
-# maptweak
-# spellcheck (typo fixes)
-# experiment
-#################################
-
-# Your name.
-author: Anewbe
-
-# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
-delete-after: True
-
-# Any changes you've made. See valid prefix list above.
-# INDENT WITH TWO SPACES. NOT TABS. SPACES.
-# SCREW THIS UP AND IT WON'T WORK.
-# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
-# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
-changes:
- - rscadd: "Adds the ability to make robolimb brands more or less vulnerable to brute or burn."
- - rscdel: "Makes VeyMed limbs more vulnerable to brute and burn."
diff --git a/icons/effects/96x256.dmi b/icons/effects/96x256.dmi
new file mode 100644
index 00000000000..978f0fbcdad
Binary files /dev/null and b/icons/effects/96x256.dmi differ
diff --git a/icons/effects/timestop.dmi b/icons/effects/timestop.dmi
new file mode 100644
index 00000000000..0e69eba9848
Binary files /dev/null and b/icons/effects/timestop.dmi differ
diff --git a/icons/effects/weather.dmi b/icons/effects/weather.dmi
index d0df90a44a7..5ae794c8985 100644
Binary files a/icons/effects/weather.dmi and b/icons/effects/weather.dmi differ
diff --git a/icons/mob/AI.dmi b/icons/mob/AI.dmi
index f5fbc438a76..d0946d1564c 100644
Binary files a/icons/mob/AI.dmi and b/icons/mob/AI.dmi differ
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index b5d549fbc58..b3b9a852c9a 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi
index 54b20e01650..1ed8e7cf12a 100644
Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ
diff --git a/icons/mob/belt_mirror.dmi b/icons/mob/belt_mirror.dmi
index d8e8291a801..3881b1c7464 100644
Binary files a/icons/mob/belt_mirror.dmi and b/icons/mob/belt_mirror.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index c93e3b2caa3..a98cb6061c3 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/human_races/markings.dmi b/icons/mob/human_races/markings.dmi
index e4e4101b4bf..d89377dbf17 100644
Binary files a/icons/mob/human_races/markings.dmi and b/icons/mob/human_races/markings.dmi differ
diff --git a/icons/mob/items/lefthand.dmi b/icons/mob/items/lefthand.dmi
index 9a8adaeae07..c02abf60c80 100644
Binary files a/icons/mob/items/lefthand.dmi and b/icons/mob/items/lefthand.dmi differ
diff --git a/icons/mob/items/lefthand_guns.dmi b/icons/mob/items/lefthand_guns.dmi
index 1a830a6e49f..3dce22596f8 100644
Binary files a/icons/mob/items/lefthand_guns.dmi and b/icons/mob/items/lefthand_guns.dmi differ
diff --git a/icons/mob/items/lefthand_holder.dmi b/icons/mob/items/lefthand_holder.dmi
index a3af18a5d0a..9f47a4743a1 100644
Binary files a/icons/mob/items/lefthand_holder.dmi and b/icons/mob/items/lefthand_holder.dmi differ
diff --git a/icons/mob/items/righthand.dmi b/icons/mob/items/righthand.dmi
index d2b58c3297d..0e16db099ee 100644
Binary files a/icons/mob/items/righthand.dmi and b/icons/mob/items/righthand.dmi differ
diff --git a/icons/mob/items/righthand_guns.dmi b/icons/mob/items/righthand_guns.dmi
index 8a7c74bf3d0..f13fb1c9974 100644
Binary files a/icons/mob/items/righthand_guns.dmi and b/icons/mob/items/righthand_guns.dmi differ
diff --git a/icons/mob/items/righthand_holder.dmi b/icons/mob/items/righthand_holder.dmi
index ee4b26869e6..7ac02b77204 100644
Binary files a/icons/mob/items/righthand_holder.dmi and b/icons/mob/items/righthand_holder.dmi differ
diff --git a/icons/mob/pai.dmi b/icons/mob/pai.dmi
index 23744fddda6..df6010159b3 100644
Binary files a/icons/mob/pai.dmi and b/icons/mob/pai.dmi differ
diff --git a/icons/mob/robots.dmi b/icons/mob/robots.dmi
index 8b9a9c9cc47..fbbc875bc6c 100644
Binary files a/icons/mob/robots.dmi and b/icons/mob/robots.dmi differ
diff --git a/icons/mob/species/tajaran/helmet.dmi b/icons/mob/species/tajaran/helmet.dmi
index 050ba64faf7..93135f7106b 100644
Binary files a/icons/mob/species/tajaran/helmet.dmi and b/icons/mob/species/tajaran/helmet.dmi differ
diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi
index 765550e9df3..59e77909e9e 100644
Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 7c7082c2ba2..56d3a651249 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/apc_repair.dmi b/icons/obj/apc_repair.dmi
index df295e2551b..4d4a024ba88 100644
Binary files a/icons/obj/apc_repair.dmi and b/icons/obj/apc_repair.dmi differ
diff --git a/icons/obj/clothing/ties.dmi b/icons/obj/clothing/ties.dmi
index 79068c34f58..52433ab5e34 100644
Binary files a/icons/obj/clothing/ties.dmi and b/icons/obj/clothing/ties.dmi differ
diff --git a/icons/obj/deadringer.dmi b/icons/obj/deadringer.dmi
new file mode 100644
index 00000000000..62200577825
Binary files /dev/null and b/icons/obj/deadringer.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index cb78fa22632..1b834792bde 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/fulton.dmi b/icons/obj/fulton.dmi
new file mode 100644
index 00000000000..c56c275b3b1
Binary files /dev/null and b/icons/obj/fulton.dmi differ
diff --git a/icons/obj/fulton_balloon.dmi b/icons/obj/fulton_balloon.dmi
new file mode 100644
index 00000000000..5a1fa98e148
Binary files /dev/null and b/icons/obj/fulton_balloon.dmi differ
diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi
index 3ea938e4eef..ddf2e1c64ec 100644
Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ
diff --git a/icons/obj/pda.dmi b/icons/obj/pda.dmi
index 9928e2fee21..aaedd149689 100644
Binary files a/icons/obj/pda.dmi and b/icons/obj/pda.dmi differ
diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi
index bc57493646e..e5db3aeb3ec 100644
Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ
diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi
index a0240b53afd..734bbe8868d 100644
Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ
diff --git a/icons/obj/props/prism.dmi b/icons/obj/props/prism.dmi
new file mode 100644
index 00000000000..0b938c7ef04
Binary files /dev/null and b/icons/obj/props/prism.dmi differ
diff --git a/icons/obj/props/projectile_lock.dmi b/icons/obj/props/projectile_lock.dmi
new file mode 100644
index 00000000000..cf74d73796c
Binary files /dev/null and b/icons/obj/props/projectile_lock.dmi differ
diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi
index 1bd5df7f9a2..c19111ab72d 100644
Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ
diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi
index 2cdc20c704b..8cce2e7f159 100644
Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ
diff --git a/maps/southern_cross/datums/supplypacks/munitions.dm b/maps/southern_cross/datums/supplypacks/munitions.dm
index 819e96d428c..5b88cc698c8 100644
--- a/maps/southern_cross/datums/supplypacks/munitions.dm
+++ b/maps/southern_cross/datums/supplypacks/munitions.dm
@@ -4,13 +4,32 @@
*/
/datum/supply_packs/munitions/bolt_rifles_explorer
- name = "Weapons - Surplus explorer rifles"
+ name = "Weapons - Surplus Hunting Rifles"
contains = list(
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 4,
- /obj/item/ammo_magazine/clip/c762 = 4,
- /obj/item/ammo_magazine/clip/c762/hunter = 8
+ /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 2,
+ /obj/item/ammo_magazine/clip/c762/hunter = 6
)
cost = 50
containertype = /obj/structure/closet/crate/secure/weapon
- containername = "Explorer weapons crate"
+ containername = "Hunting Rifle crate"
access = access_explorer
+
+/datum/supply_packs/munitions/phase_carbines_explorer
+ name = "Weapons - Surplus Phase Carbines"
+ contains = list(
+ /obj/item/weapon/gun/energy/phasegun = 2,
+ )
+ cost = 25
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Phase Carbine crate"
+ access = access_explorer
+
+/datum/supply_packs/munitions/phase_rifles_explorer
+ name = "Weapons - Phase Rifles"
+ contains = list(
+ /obj/item/weapon/gun/energy/phasegun/rifle = 2,
+ )
+ cost = 50
+ containertype = /obj/structure/closet/crate/secure/weapon
+ containername = "Phase Rifle crate"
+ access = access_explorer
\ No newline at end of file
diff --git a/maps/southern_cross/southern_cross-1.dmm b/maps/southern_cross/southern_cross-1.dmm
index d15e873b00e..b2f8c113466 100644
--- a/maps/southern_cross/southern_cross-1.dmm
+++ b/maps/southern_cross/southern_cross-1.dmm
@@ -5961,7 +5961,7 @@
"ckG" = (/obj/structure/cable/cyan{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/cable/cyan{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/light{dir = 4; icon_state = "tube1"},/turf/simulated/floor,/area/engineering/engine_room)
"ckH" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/door/blast/regular{density = 0; dir = 1; icon_state = "pdoor0"; id = "EngineBlast"; name = "Engine Monitoring Room Blast Doors"; opacity = 0},/obj/structure/cable/cyan{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/effect/wingrille_spawn/reinforced_phoron,/turf/simulated/floor,/area/engineering/engine_monitoring)
"ckI" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/computer/power_monitor,/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
-"ckJ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/table/reinforced,/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine control room blast doors."; id = "EngineBlast"; name = "Engine Monitoring Room Blast Doors"; pixel_x = -6; pixel_y = -3; req_access = list(10)},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine charging port."; id = "SupermatterPort"; name = "Reactor Blast Doors"; pixel_x = -6; pixel_y = 7; req_access = list(10)},/obj/machinery/button/remote/emitter{desc = "A remote control-switch for the engine emitter."; id = "EngineEmitter"; name = "Engine Emitter"; pixel_x = 6; pixel_y = 2; req_access = list(10)},/obj/structure/cable/cyan{d1 = 2; d2 = 4; icon_state = "2-4"},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
+"ckJ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/structure/table/reinforced,/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine control room blast doors."; id = "EngineBlast"; name = "Engine Monitoring Room Blast Doors"; pixel_x = -6; pixel_y = -3; req_access = list(10)},/obj/machinery/button/remote/blast_door{desc = "A remote control-switch for the engine charging port."; id = "SupermatterPort"; name = "Reactor Blast Doors"; pixel_x = -6; pixel_y = 7; req_access = list(10)},/obj/machinery/button/remote/emitter{desc = "A remote control-switch for the engine emitter."; id = "EngineEmitter"; name = "Engine Emitter"; pixel_x = 6; pixel_y = 2; req_access = list(10)},/obj/structure/cable/cyan{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/effect/engine_setup/shutters,/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
"ckK" = (/obj/structure/cable/cyan{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/hologram/holopad,/obj/effect/floor_decal/industrial/outline/grey,/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
"ckL" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
"ckM" = (/obj/machinery/disposal,/obj/machinery/camera/network/engine{c_tag = "ENG - Monitoring Room"; dir = 8},/obj/structure/disposalpipe/trunk{dir = 1},/turf/simulated/floor/tiled,/area/engineering/engine_monitoring)
@@ -7685,8 +7685,8 @@
"cRO" = (/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/machinery/light_switch{pixel_x = 11; pixel_y = 24},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/structure/cable/green{d2 = 8; icon_state = "0-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 6},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 1},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
"cRP" = (/obj/machinery/atmospherics/unary/vent_scrubber/on{dir = 8},/obj/machinery/alarm{pixel_y = 22},/obj/effect/floor_decal/borderfloorwhite{dir = 1},/obj/effect/floor_decal/corner/purple/border{dir = 1},/obj/effect/floor_decal/borderfloorwhite/corner2{dir = 4},/obj/effect/floor_decal/corner/purple/bordercorner2{dir = 4},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
"cRQ" = (/obj/item/device/radio/intercom/department/medbay{dir = 2; pixel_x = 0; pixel_y = 21},/obj/machinery/camera/network/medbay{c_tag = "MED - Cloning"; dir = 2},/obj/effect/floor_decal/borderfloorwhite{dir = 1},/obj/effect/floor_decal/corner/purple/border{dir = 1},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
-"cRR" = (/obj/structure/table/standard,/obj/item/weapon/storage/box/bodybags{pixel_x = 1; pixel_y = 2},/obj/machinery/light{dir = 1},/obj/effect/floor_decal/borderfloorwhite{dir = 1},/obj/effect/floor_decal/corner/purple/border{dir = 1},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
-"cRS" = (/obj/structure/table/standard,/obj/item/weapon/storage/laundry_basket,/obj/machinery/firealarm{pixel_y = 24},/obj/effect/floor_decal/borderfloorwhite{dir = 1},/obj/effect/floor_decal/corner/purple/border{dir = 1},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
+"cRR" = (/obj/machinery/light{dir = 1},/obj/effect/floor_decal/borderfloorwhite{dir = 1},/obj/effect/floor_decal/corner/purple/border{dir = 1},/obj/machinery/organ_printer/flesh/full,/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
+"cRS" = (/obj/structure/table/standard,/obj/item/weapon/storage/laundry_basket,/obj/machinery/firealarm{pixel_y = 24},/obj/effect/floor_decal/borderfloorwhite{dir = 1},/obj/effect/floor_decal/corner/purple/border{dir = 1},/obj/item/weapon/storage/box/bodybags,/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
"cRT" = (/obj/structure/filingcabinet/chestdrawer{desc = "A large drawer filled with autopsy reports."; name = "Autopsy Reports"},/obj/machinery/alarm{dir = 4; pixel_x = -22; pixel_y = 0},/obj/effect/floor_decal/borderfloor/corner{dir = 1},/obj/effect/floor_decal/corner/paleblue/bordercorner{dir = 1},/turf/simulated/floor/tiled,/area/medical/morgue)
"cRU" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/tiled,/area/medical/morgue)
"cRV" = (/obj/structure/table/steel,/obj/item/weapon/storage/box/bodybags,/obj/item/weapon/storage/box/bodybags,/obj/machinery/power/apc{dir = 4; name = "east bump"; pixel_x = 24},/obj/machinery/light_switch{dir = 2; name = "light switch "; pixel_x = 36; pixel_y = 0},/obj/structure/cable/green{d2 = 2; icon_state = "0-2"},/obj/effect/floor_decal/borderfloor/corner{dir = 4},/obj/effect/floor_decal/corner/paleblue/bordercorner{dir = 4},/turf/simulated/floor/tiled,/area/medical/morgue)
@@ -7803,7 +7803,7 @@
"cUc" = (/obj/structure/closet/wardrobe/medic_white,/obj/effect/floor_decal/borderfloorwhite{dir = 4},/obj/effect/floor_decal/corner/paleblue/border{dir = 4},/turf/simulated/floor/tiled/white,/area/medical/ward)
"cUd" = (/obj/structure/bed/padded,/obj/item/weapon/bedsheet/medical,/obj/structure/curtain/open/privacy,/obj/effect/floor_decal/borderfloorwhite{dir = 9},/obj/effect/floor_decal/corner/paleblue/border{dir = 9},/turf/simulated/floor/tiled/white,/area/medical/ward)
"cUe" = (/obj/structure/bed/padded,/obj/item/weapon/bedsheet/medical,/obj/machinery/newscaster{pixel_x = 30; pixel_y = 0},/obj/structure/curtain/open/privacy,/obj/effect/floor_decal/borderfloorwhite{dir = 5},/obj/effect/floor_decal/corner/paleblue/border{dir = 5},/turf/simulated/floor/tiled/white,/area/medical/ward)
-"cUf" = (/obj/machinery/clonepod{biomass = 600},/obj/effect/floor_decal/borderfloorwhite{dir = 10},/obj/effect/floor_decal/corner/purple/border{dir = 10},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
+"cUf" = (/obj/effect/floor_decal/borderfloorwhite{dir = 10},/obj/effect/floor_decal/corner/purple/border{dir = 10},/obj/machinery/clonepod/full,/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
"cUg" = (/obj/machinery/computer/cloning,/obj/machinery/light,/obj/effect/floor_decal/borderfloorwhite,/obj/effect/floor_decal/corner/purple/border,/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
"cUh" = (/obj/machinery/dna_scannernew,/obj/effect/floor_decal/borderfloorwhite/corner{dir = 8},/obj/effect/floor_decal/corner/purple/bordercorner{dir = 8},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
"cUi" = (/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 8},/obj/effect/floor_decal/steeldecal/steel_decals4{dir = 5},/turf/simulated/floor/tiled/white,/area/medical/genetics_cloning)
diff --git a/maps/submaps/surface_submaps/mountains/deadspy.dmm b/maps/submaps/surface_submaps/mountains/deadspy.dmm
new file mode 100644
index 00000000000..f22e0d3e612
--- /dev/null
+++ b/maps/submaps/surface_submaps/mountains/deadspy.dmm
@@ -0,0 +1,32 @@
+"a" = (/obj/effect/decal/remains/xeno,/obj/item/clothing/mask/gas,/obj/item/clothing/suit/fire/firefighter,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"b" = (/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"c" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/effect/decal/cleanable/molten_item,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"d" = (/obj/item/weapon/flamethrower,/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"e" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"f" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"g" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/effect/decal/cleanable/ash,/obj/random/landmine,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"h" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/random/landmine,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"i" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/molten_item,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"j" = (/obj/item/weapon/material/butterfly,/obj/effect/decal/cleanable/liquid_fuel,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"k" = (/obj/effect/decal/remains/human,/obj/item/weapon/wrench,/obj/item/clothing/head/hardhat,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"l" = (/obj/item/weapon/flame/lighter/zippo,/obj/effect/decal/cleanable/liquid_fuel,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"m" = (/obj/effect/decal/remains/human,/obj/item/clothing/mask/balaclava,/obj/item/clothing/under/suit_jacket/really_black,/obj/effect/decal/cleanable/ash,/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/ash,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"n" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/ash,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"o" = (/obj/machinery/porta_turret/poi{desc = "Looking at this heavy caliber, tripod-mounted, little ol' number makes you want to square-dance."; lethal = 0; name = "sentry turret"},/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"p" = (/obj/item/weapon/deadringer,/obj/effect/decal/cleanable/liquid_fuel,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"q" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/effect/decal/cleanable/liquid_fuel,/obj/random/landmine,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"r" = (/obj/effect/decal/cleanable/liquid_fuel,/obj/item/weapon/storage/fancy/cigarettes/professionals,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"s" = (/obj/item/weapon/card/emag_broken,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"t" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/random/landmine,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"u" = (/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel,/obj/effect/decal/cleanable/ash,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/deadspy)
+"v" = (/turf/simulated/mineral,/area/submap/deadspy)
+
+(1,1,1) = {"
+abbbbvv
+bcdefgb
+bfhijfk
+bflmnfo
+vfpqrfs
+vtfuffb
+vvbbbvb
+"}
diff --git a/maps/submaps/surface_submaps/mountains/mountains.dm b/maps/submaps/surface_submaps/mountains/mountains.dm
index dd409e0e62f..56a267c4756 100644
--- a/maps/submaps/surface_submaps/mountains/mountains.dm
+++ b/maps/submaps/surface_submaps/mountains/mountains.dm
@@ -31,6 +31,7 @@
#include "SupplyDrop1.dmm"
#include "BlastMine1.dmm"
#include "crashedcontainmentshuttle.dmm"
+#include "deadspy.dmm"
#endif
// The 'mountains' is the mining z-level, and has a lot of caves.
@@ -191,6 +192,12 @@
mappath = 'maps/submaps/surface_submaps/mountains/crashedcontainmentshuttle.dmm'
cost = 30
+/datum/map_template/surface/mountains/normal/deadspy
+ name = "Spy Remains"
+ desc = "W+M1 = Salt."
+ mappath = 'maps/submaps/surface_submaps/mountains/deadspy.dmm'
+ cost = 15
+
/**************
* Deep Caves *
@@ -265,4 +272,3 @@
desc = "An abandoned blast mining site, seems that local wildlife has moved in."
mappath = 'maps/submaps/surface_submaps/mountains/BlastMine1.dmm'
cost = 20
-
diff --git a/maps/submaps/surface_submaps/mountains/mountains_areas.dm b/maps/submaps/surface_submaps/mountains/mountains_areas.dm
index 3baf48c75c6..f1045f22f05 100644
--- a/maps/submaps/surface_submaps/mountains/mountains_areas.dm
+++ b/maps/submaps/surface_submaps/mountains/mountains_areas.dm
@@ -88,4 +88,7 @@
name = "Blast Mine 1"
/area/submap/crashedcontainmentshuttle
- name = "Crashed Containment Shuttle"
\ No newline at end of file
+ name = "Crashed Containment Shuttle"
+
+/area/submap/deadspy
+ name = "Dead Spy"
\ No newline at end of file
diff --git a/polaris.dme b/polaris.dme
index 3daa5fc7720..d59255a20d1 100644
--- a/polaris.dme
+++ b/polaris.dme
@@ -171,7 +171,6 @@
#include "code\controllers\Processes\mob.dm"
#include "code\controllers\Processes\nanoui.dm"
#include "code\controllers\Processes\obj.dm"
-#include "code\controllers\Processes\planet.dm"
#include "code\controllers\Processes\radiation.dm"
#include "code\controllers\Processes\scheduler.dm"
#include "code\controllers\Processes\sun.dm"
@@ -189,6 +188,7 @@
#include "code\controllers\subsystems\machines.dm"
#include "code\controllers\subsystems\orbits.dm"
#include "code\controllers\subsystems\overlays.dm"
+#include "code\controllers\subsystems\planets.dm"
#include "code\controllers\subsystems\shuttles.dm"
#include "code\controllers\subsystems\xenoarch.dm"
#include "code\datums\ai_law_sets.dm"
@@ -1043,7 +1043,6 @@
#include "code\game\objects\random\misc.dm"
#include "code\game\objects\random\mob.dm"
#include "code\game\objects\random\spacesuits.dm"
-#include "code\game\objects\structures\alien_props.dm"
#include "code\game\objects\structures\barsign.dm"
#include "code\game\objects\structures\bedsheet_bin.dm"
#include "code\game\objects\structures\bonfire.dm"
@@ -1071,6 +1070,7 @@
#include "code\game\objects\structures\morgue.dm"
#include "code\game\objects\structures\musician.dm"
#include "code\game\objects\structures\noticeboard.dm"
+#include "code\game\objects\structures\plasticflaps.dm"
#include "code\game\objects\structures\railing.dm"
#include "code\game\objects\structures\safe.dm"
#include "code\game\objects\structures\signs.dm"
@@ -1115,6 +1115,11 @@
#include "code\game\objects\structures\flora\trees.dm"
#include "code\game\objects\structures\ghost_pods\ghost_pods.dm"
#include "code\game\objects\structures\ghost_pods\silicon.dm"
+#include "code\game\objects\structures\props\alien_props.dm"
+#include "code\game\objects\structures\props\beam_prism.dm"
+#include "code\game\objects\structures\props\projectile_lock.dm"
+#include "code\game\objects\structures\props\prop.dm"
+#include "code\game\objects\structures\props\puzzledoor.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\alien_nests.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\bed.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\chairs.dm"
@@ -1242,6 +1247,7 @@
#include "code\modules\admin\verbs\dice.dm"
#include "code\modules\admin\verbs\getlogs.dm"
#include "code\modules\admin\verbs\grief_fixers.dm"
+#include "code\modules\admin\verbs\lightning_strike.dm"
#include "code\modules\admin\verbs\map_template_loadverb.dm"
#include "code\modules\admin\verbs\mapping.dm"
#include "code\modules\admin\verbs\massmodvar.dm"
@@ -1268,6 +1274,7 @@
#include "code\modules\alarm\fire_alarm.dm"
#include "code\modules\alarm\motion_alarm.dm"
#include "code\modules\alarm\power_alarm.dm"
+#include "code\modules\artifice\deadringer.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\helpers.dm"
#include "code\modules\assembly\holder.dm"
@@ -1657,6 +1664,7 @@
#include "code\modules\mining\abandonedcrates.dm"
#include "code\modules\mining\alloys.dm"
#include "code\modules\mining\coins.dm"
+#include "code\modules\mining\fulton.dm"
#include "code\modules\mining\machine_input_output_plates.dm"
#include "code\modules\mining\machine_processing.dm"
#include "code\modules\mining\machine_stacking.dm"
@@ -1692,6 +1700,7 @@
#include "code\modules\mob\transform_procs.dm"
#include "code\modules\mob\typing_indicator.dm"
#include "code\modules\mob\update_icons.dm"
+#include "code\modules\mob\_modifiers\aura.dm"
#include "code\modules\mob\_modifiers\cloning.dm"
#include "code\modules\mob\_modifiers\modifiers.dm"
#include "code\modules\mob\_modifiers\modifiers_misc.dm"
@@ -1876,6 +1885,7 @@
#include "code\modules\mob\living\silicon\robot\drone\drone_damage.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_items.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm"
+#include "code\modules\mob\living\silicon\robot\drone\drone_remote_control.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_say.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\event.dm"
#include "code\modules\mob\living\silicon\robot\robot_modules\station.dm"
@@ -1994,6 +2004,7 @@
#include "code\modules\organs\internal\liver.dm"
#include "code\modules\organs\internal\lungs.dm"
#include "code\modules\organs\internal\organ_internal.dm"
+#include "code\modules\organs\internal\voicebox.dm"
#include "code\modules\organs\subtypes\diona.dm"
#include "code\modules\organs\subtypes\indestructible.dm"
#include "code\modules\organs\subtypes\machine.dm"
@@ -2114,6 +2125,7 @@
#include "code\modules\projectiles\guns\vox.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
#include "code\modules\projectiles\guns\energy\nuclear.dm"
+#include "code\modules\projectiles\guns\energy\phase.dm"
#include "code\modules\projectiles\guns\energy\pulse.dm"
#include "code\modules\projectiles\guns\energy\special.dm"
#include "code\modules\projectiles\guns\energy\stun.dm"
@@ -2234,6 +2246,17 @@
#include "code\modules\research\rdmachines.dm"
#include "code\modules\research\research.dm"
#include "code\modules\research\server.dm"
+#include "code\modules\research\designs\ai_modules.dm"
+#include "code\modules\research\designs\circuit_assembly.dm"
+#include "code\modules\research\designs\circuits.dm"
+#include "code\modules\research\designs\illegal.dm"
+#include "code\modules\research\designs\medical.dm"
+#include "code\modules\research\designs\mining_toys.dm"
+#include "code\modules\research\designs\misc.dm"
+#include "code\modules\research\designs\pdas.dm"
+#include "code\modules\research\designs\powercells.dm"
+#include "code\modules\research\designs\stock_parts.dm"
+#include "code\modules\research\designs\weapons.dm"
#include "code\modules\scripting\Errors.dm"
#include "code\modules\scripting\IDE.dm"
#include "code\modules\scripting\Options.dm"
@@ -2310,6 +2333,7 @@
#include "code\modules\surgery\_defines.dm"
#include "code\modules\surgery\bones.dm"
#include "code\modules\surgery\encased.dm"
+#include "code\modules\surgery\external_repair.dm"
#include "code\modules\surgery\face.dm"
#include "code\modules\surgery\generic.dm"
#include "code\modules\surgery\implant.dm"
diff --git a/sound/effects/thunder/thunder1.ogg b/sound/effects/thunder/thunder1.ogg
new file mode 100644
index 00000000000..7ec34e88e86
Binary files /dev/null and b/sound/effects/thunder/thunder1.ogg differ
diff --git a/sound/effects/thunder/thunder10.ogg b/sound/effects/thunder/thunder10.ogg
new file mode 100644
index 00000000000..43aefb098f0
Binary files /dev/null and b/sound/effects/thunder/thunder10.ogg differ
diff --git a/sound/effects/thunder/thunder2.ogg b/sound/effects/thunder/thunder2.ogg
new file mode 100644
index 00000000000..bc2f581dda5
Binary files /dev/null and b/sound/effects/thunder/thunder2.ogg differ
diff --git a/sound/effects/thunder/thunder3.ogg b/sound/effects/thunder/thunder3.ogg
new file mode 100644
index 00000000000..0df287aa783
Binary files /dev/null and b/sound/effects/thunder/thunder3.ogg differ
diff --git a/sound/effects/thunder/thunder4.ogg b/sound/effects/thunder/thunder4.ogg
new file mode 100644
index 00000000000..6c671b80105
Binary files /dev/null and b/sound/effects/thunder/thunder4.ogg differ
diff --git a/sound/effects/thunder/thunder5.ogg b/sound/effects/thunder/thunder5.ogg
new file mode 100644
index 00000000000..3d5187a7164
Binary files /dev/null and b/sound/effects/thunder/thunder5.ogg differ
diff --git a/sound/effects/thunder/thunder6.ogg b/sound/effects/thunder/thunder6.ogg
new file mode 100644
index 00000000000..65aef886ff2
Binary files /dev/null and b/sound/effects/thunder/thunder6.ogg differ
diff --git a/sound/effects/thunder/thunder7.ogg b/sound/effects/thunder/thunder7.ogg
new file mode 100644
index 00000000000..b72848a2b6e
Binary files /dev/null and b/sound/effects/thunder/thunder7.ogg differ
diff --git a/sound/effects/thunder/thunder8.ogg b/sound/effects/thunder/thunder8.ogg
new file mode 100644
index 00000000000..a25fe21e328
Binary files /dev/null and b/sound/effects/thunder/thunder8.ogg differ
diff --git a/sound/effects/thunder/thunder9.ogg b/sound/effects/thunder/thunder9.ogg
new file mode 100644
index 00000000000..9ebc1045bff
Binary files /dev/null and b/sound/effects/thunder/thunder9.ogg differ
diff --git a/sound/effects/uncloak.ogg b/sound/effects/uncloak.ogg
new file mode 100644
index 00000000000..a2cedc8c731
Binary files /dev/null and b/sound/effects/uncloak.ogg differ
diff --git a/sound/items/fulext_deploy.wav b/sound/items/fulext_deploy.wav
new file mode 100644
index 00000000000..9fbcb7e3f85
Binary files /dev/null and b/sound/items/fulext_deploy.wav differ
diff --git a/sound/items/fultext_launch.wav b/sound/items/fultext_launch.wav
new file mode 100644
index 00000000000..a623a89ada4
Binary files /dev/null and b/sound/items/fultext_launch.wav differ