From 1659e2804ea6b39bcfe23fa8b8058886699196e5 Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Tue, 21 Apr 2020 04:04:10 +0200
Subject: [PATCH 01/41] Deletes lots of autoylathe copypasta.
---
_maps/map_files/generic/CentCom.dmm | 2 +-
code/__DEFINES/machines.dm | 16 +-
code/datums/wires/autoylathe.dm | 48 --
code/game/machinery/autolathe.dm | 43 +-
code/game/machinery/toylathe.dm | 415 ------------------
.../circuitboards/machine_circuitboards.dm | 4 +-
.../research/designs/autoylathe_designs.dm | 40 +-
.../machine_designs_all_misc.dm | 2 +-
code/modules/research/rdconsole.dm | 2 +-
code/modules/research/techweb/_techweb.dm | 18 +-
tgstation.dme | 2 -
11 files changed, 81 insertions(+), 511 deletions(-)
delete mode 100644 code/datums/wires/autoylathe.dm
delete mode 100644 code/game/machinery/toylathe.dm
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index c9b81cefd9..eadf31ad46 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -16752,7 +16752,7 @@
},
/area/centcom/holding)
"Nf" = (
-/obj/machinery/autoylathe,
+/obj/machinery/autolathe/toy,
/turf/open/indestructible/hotelwood,
/area/centcom/holding)
"Ni" = (
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index eee0676dec..5a26feb624 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -22,14 +22,14 @@
//used in design to specify which machine can build it
#define IMPRINTER (1<<0) //For circuits. Uses glass/chemicals.
-#define PROTOLATHE (1<<1) //New stuff. Uses glass/metal/chemicals
-#define AUTOLATHE (1<<2) //Uses glass/metal only.
-#define CRAFTLATHE (1<<3) //Uses fuck if I know. For use eventually.
-#define MECHFAB (1<<4) //Remember, objects utilising this flag should have construction_time and construction_cost vars.
-#define BIOGENERATOR (1<<5) //Uses biomass
-#define LIMBGROWER (1<<6) //Uses synthetic flesh
-#define SMELTER (1<<7) //uses various minerals
-#define AUTOYLATHE (1<<8) // CITADEL ADD
+#define PROTOLATHE (1<<1) //New stuff. Uses materials/chemicals
+#define AUTOLATHE (1<<2) //Uses materials only.
+#define TOYLATHE (1<<3) //Glass/metal/plastic. Meant for toys.
+#define NO_PUBLIC_LATHE (1<<4) //prevents the design from being auto-unlocked by public auto(y)lathes.
+#define MECHFAB (1<<5) //Remember, objects utilising this flag should have construction_time and construction_cost vars.
+#define BIOGENERATOR (1<<6) //Uses biomass
+#define LIMBGROWER (1<<7) //Uses synthetic flesh
+#define SMELTER (1<<8) //uses various minerals
#define NANITE_COMPILER (1<<9) //Prints nanite disks
#define AUTOBOTTLER (1<<10) //Uses booze, for printing
//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
diff --git a/code/datums/wires/autoylathe.dm b/code/datums/wires/autoylathe.dm
deleted file mode 100644
index 736c9551ec..0000000000
--- a/code/datums/wires/autoylathe.dm
+++ /dev/null
@@ -1,48 +0,0 @@
-/datum/wires/autoylathe
- holder_type = /obj/machinery/autoylathe
- proper_name = "Autoylathe"
-
-/datum/wires/autoylathe/New(atom/holder)
- wires = list(
- WIRE_HACK, WIRE_DISABLE,
- WIRE_SHOCK, WIRE_ZAP
- )
- add_duds(6)
- ..()
-
-/datum/wires/autoylathe/interactable(mob/user)
- var/obj/machinery/autoylathe/A = holder
- if(A.panel_open)
- return TRUE
-
-/datum/wires/autoylathe/get_status()
- var/obj/machinery/autoylathe/A = holder
- var/list/status = list()
- status += "The red light is [A.disabled ? "on" : "off"]."
- status += "The blue light is [A.hacked ? "on" : "off"]."
- return status
-
-/datum/wires/autoylathe/on_pulse(wire)
- var/obj/machinery/autoylathe/A = holder
- switch(wire)
- if(WIRE_HACK)
- A.adjust_hacked(!A.hacked)
- addtimer(CALLBACK(A, /obj/machinery/autoylathe.proc/reset, wire), 60)
- if(WIRE_SHOCK)
- A.shocked = !A.shocked
- addtimer(CALLBACK(A, /obj/machinery/autoylathe.proc/reset, wire), 60)
- if(WIRE_DISABLE)
- A.disabled = !A.disabled
- addtimer(CALLBACK(A, /obj/machinery/autoylathe.proc/reset, wire), 60)
-
-/datum/wires/autoylathe/on_cut(wire, mend)
- var/obj/machinery/autoylathe/A = holder
- switch(wire)
- if(WIRE_HACK)
- A.adjust_hacked(!mend)
- if(WIRE_HACK)
- A.shocked = !mend
- if(WIRE_DISABLE)
- A.disabled = !mend
- if(WIRE_ZAP)
- A.shock(usr, 50)
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index 6fa7fa30c0..961c5e8331 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -28,11 +28,11 @@
var/prod_coeff = 1
var/datum/design/being_built
- var/datum/techweb/stored_research
var/list/datum/design/matching_designs
var/selected_category
var/screen = 1
+ var/datum/techweb/stored_research = /datum/techweb/specialized/autounlocking/autolathe
var/list/categories = list(
"Tools",
"Electronics",
@@ -45,9 +45,7 @@
"Dinnerware",
"Imported"
)
-
-/obj/machinery/autolathe/Initialize()
- var/static/list/allowed_types = list(
+ var/list/allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/gold,
@@ -63,10 +61,12 @@
/datum/material/adamantine,
/datum/material/mythril
)
- AddComponent(/datum/component/material_container, allowed_types, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
+
+/obj/machinery/autolathe/Initialize()
+ AddComponent(/datum/component/material_container, allowed_materials, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autolathe(src)
- stored_research = new /datum/techweb/specialized/autounlocking/autolathe
+ stored_research = new stored_research
matching_designs = list()
/obj/machinery/autolathe/Destroy()
@@ -91,7 +91,7 @@
if(AUTOLATHE_SEARCH_MENU)
dat = search_win(user)
- var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
+ var/datum/browser/popup = new(user, name, name, 400, 500)
popup.set_content(dat)
popup.open()
@@ -439,8 +439,37 @@
desc = "An autolathe reprogrammed with security protocols to prevent hacking."
hackable = FALSE
circuit = /obj/item/circuitboard/machine/autolathe/secure
+ stored_research = /datum/techweb/specialized/autounlocking/autolathe/public
//Called when the object is constructed by an autolathe
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
return
+
+/obj/machinery/autolathe/toy
+ name = "autoylathe"
+ desc = "It produces toys using plastic, metal and glass."
+ circuit = /obj/item/circuitboard/machine/autolathe/toy
+
+ stored_research = /datum/techweb/specialized/autounlocking/autolathe/toy
+ categories = list(
+ "Toys",
+ "Figurines",
+ "Pistols",
+ "Rifles",
+ "Heavy",
+ "Melee",
+ "Armor",
+ "Adult",
+ "Misc",
+ "Imported"
+ )
+ allowed_materials = list(
+ /datum/material/iron,
+ /datum/material/glass,
+ /datum/material/plastic
+ )
+
+/obj/machinery/autolathe/toy/hacked/Initialize()
+ . = ..()
+ adjust_hacked(TRUE)
diff --git a/code/game/machinery/toylathe.dm b/code/game/machinery/toylathe.dm
deleted file mode 100644
index c679f3f983..0000000000
--- a/code/game/machinery/toylathe.dm
+++ /dev/null
@@ -1,415 +0,0 @@
-#define AUTOYLATHE_MAIN_MENU 1
-#define AUTOYLATHE_CATEGORY_MENU 2
-#define AUTOYLATHE_SEARCH_MENU 3
-
-/obj/machinery/autoylathe
- name = "autoylathe"
- desc = "It produces toys using plastic, metal and glass."
- icon_state = "autolathe"
- density = TRUE
- use_power = IDLE_POWER_USE
- idle_power_usage = 10
- active_power_usage = 100
- circuit = /obj/item/circuitboard/machine/autoylathe
- layer = BELOW_OBJ_LAYER
-
- var/operating = FALSE
- var/list/L = list()
- var/list/LL = list()
- var/hacked = FALSE
- var/disabled = 0
- var/shocked = FALSE
- var/hack_wire
- var/disable_wire
- var/shock_wire
-
- var/busy = FALSE
- var/prod_coeff = 1
-
- var/datum/design/being_built
- var/datum/techweb/stored_research
- var/list/datum/design/matching_designs
- var/selected_category
- var/screen = 1
-
- var/list/categories = list(
- "Toys",
- "Figurines",
- "Pistols",
- "Rifles",
- "Heavy",
- "Melee",
- "Armor",
- "Adult",
- "Misc",
- "Imported"
- )
-
-/obj/machinery/autoylathe/Initialize()
- var/static/list/allowed_materials = list(
- /datum/material/iron,
- /datum/material/glass,
- /datum/material/plastic
- )
- AddComponent(/datum/component/material_container, allowed_materials, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
- . = ..()
-
- wires = new /datum/wires/autoylathe(src)
- stored_research = new /datum/techweb/specialized/autounlocking/autoylathe
- matching_designs = list()
-
-/obj/machinery/autoylathe/Destroy()
- QDEL_NULL(wires)
- return ..()
-
-/obj/machinery/autoylathe/ui_interact(mob/user)
- . = ..()
- if(!is_operational())
- return
-
- if(shocked && !(stat & NOPOWER))
- shock(user,50)
-
- var/dat
-
- switch(screen)
- if(AUTOYLATHE_MAIN_MENU)
- dat = main_win(user)
- if(AUTOYLATHE_CATEGORY_MENU)
- dat = category_win(user,selected_category)
- if(AUTOYLATHE_SEARCH_MENU)
- dat = search_win(user)
-
- var/datum/browser/popup = new(user, "Autoylathe", name, 400, 500)
- popup.set_content(dat)
- popup.open()
-
-/obj/machinery/autoylathe/on_deconstruction()
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- materials.retrieve_all()
-
-/obj/machinery/autoylathe/attackby(obj/item/O, mob/user, params)
- if (busy)
- to_chat(user, "The autoylathe is busy. Please wait for completion of previous operation.")
- return TRUE
-
- if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O))
- updateUsrDialog()
- return TRUE
-
- if(default_deconstruction_crowbar(O))
- return TRUE
-
- if(panel_open && is_wire_tool(O))
- wires.interact(user)
- return TRUE
-
- if(user.a_intent == INTENT_HARM) //so we can hit the machine
- return ..()
-
- if(stat)
- return TRUE
-
- if(istype(O, /obj/item/disk/design_disk))
- user.visible_message("[user] begins to load \the [O] in \the [src]...",
- "You begin to load a design from \the [O]...",
- "You hear the chatter of a floppy drive.")
- busy = TRUE
- var/obj/item/disk/design_disk/D = O
- if(do_after(user, 14.4, target = src))
- for(var/B in D.blueprints)
- if(B)
- stored_research.add_design(B)
- busy = FALSE
- return TRUE
-
- return ..()
-
-/obj/machinery/autoylathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
- if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
- flick("autolathe_r",src)//plays glass insertion animation by default otherwise
- else
- flick("autolathe_o",src)//plays metal insertion animation
-
- use_power(min(1000, amount_inserted / 100))
- updateUsrDialog()
-
-/obj/machinery/autoylathe/Topic(href, href_list)
- if(..())
- return
- if (!busy)
- if(href_list["menu"])
- screen = text2num(href_list["menu"])
- updateUsrDialog()
-
- if(href_list["category"])
- selected_category = href_list["category"]
- updateUsrDialog()
-
- if(href_list["make"])
-
- /////////////////
- //href protection
- being_built = stored_research.isDesignResearchedID(href_list["make"])
- if(!being_built)
- return
-
- var/multiplier = text2num(href_list["multiplier"])
- var/is_stack = ispath(being_built.build_path, /obj/item/stack)
- multiplier = CLAMP(multiplier,1,50)
-
- /////////////////
-
- var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient
- var/total_amount = 0
- for(var/MAT in being_built.materials)
- total_amount += being_built.materials[MAT]
- var/power = max(2000, (total_amount)*multiplier/5) //Change this to use all materials
-
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
-
- var/list/materials_used = list()
- var/list/custom_materials = list() //These will apply their material effect, This should usually only be one.
-
- for(var/MAT in being_built.materials)
- var/datum/material/used_material = MAT
- var/amount_needed = being_built.materials[MAT] * coeff * multiplier
- if(istext(used_material)) //This means its a category
- var/list/list_to_show = list()
- for(var/i in SSmaterials.materials_by_category[used_material])
- if(materials.materials[i] > 0)
- list_to_show += i
-
- used_material = input("Choose [used_material]", "Custom Material") as null|anything in list_to_show
- if(!used_material)
- return //Didn't pick any material, so you can't build shit either.
- custom_materials[used_material] += amount_needed
-
- materials_used[used_material] = amount_needed
-
- if(materials.has_materials(materials_used))
- busy = TRUE
- use_power(power)
- icon_state = "autolathe_n"
- var/time = is_stack ? 32 : 32*coeff*multiplier
- addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
- else
- to_chat(usr, "Not enough materials for this operation.")
-
- if(href_list["search"])
- matching_designs.Cut()
-
- for(var/v in stored_research.researched_designs)
- var/datum/design/D = SSresearch.techweb_design_by_id(v)
- if(findtext(D.name,href_list["to_search"]))
- matching_designs.Add(D)
- updateUsrDialog()
- else
- to_chat(usr, "The autoylathe is busy. Please wait for completion of previous operation.")
-
- updateUsrDialog()
-
- return
-
-/obj/machinery/autoylathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack)
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- var/atom/A = drop_location()
- use_power(power)
- materials.use_materials(materials_used)
-
- if(is_stack)
- var/obj/item/stack/N = new being_built.build_path(A, multiplier)
- N.update_icon()
- N.autoylathe_crafted(src)
- else
- for(var/i=1, i<=multiplier, i++)
- var/obj/item/new_item = new being_built.build_path(A)
- new_item.autoylathe_crafted(src)
- if(length(picked_materials))
- new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
- icon_state = "autolathe"
- busy = FALSE
- updateDialog()
-
-/obj/machinery/autoylathe/RefreshParts()
- var/T = 0
- for(var/obj/item/stock_parts/matter_bin/MB in component_parts)
- T += MB.rating*75000
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- materials.max_amount = T
- T=1.2
- for(var/obj/item/stock_parts/manipulator/M in component_parts)
- T -= M.rating*0.2
- prod_coeff = CLAMP(T,1,0) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
-
-/obj/machinery/autoylathe/proc/main_win(mob/user)
- var/dat = "
Autoylathe Menu:
"
- dat += materials_printout()
-
- dat += "
"
-
- var/line_length = 1
- dat += "
"
-
- for(var/C in categories)
- if(line_length > 2)
- dat += "
"
- line_length = 1
-
- dat += "| [C] | "
- line_length++
-
- dat += "
"
- return dat
-
-/obj/machinery/autoylathe/proc/category_win(mob/user,selected_category)
- var/dat = "Return to main menu"
- dat += "Browsing [selected_category]:
"
- dat += materials_printout()
-
- for(var/v in stored_research.researched_designs)
- var/datum/design/D = SSresearch.techweb_design_by_id(v)
- if(!(selected_category in D.category))
- continue
-
- if(disabled || !can_build(D))
- dat += "
[D.name]"
- else
- dat += "
[D.name]"
-
- if(ispath(D.build_path, /obj/item/stack))
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- var/max_multiplier
- for(var/datum/material/mat in D.materials)
- max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat]))
- if (max_multiplier>10 && !disabled)
- dat += "
x10"
- if (max_multiplier>25 && !disabled)
- dat += "
x25"
- if(max_multiplier > 0 && !disabled)
- dat += "
x[max_multiplier]"
- else
- if(!disabled && can_build(D, 5))
- dat += "
x5"
- if(!disabled && can_build(D, 10))
- dat += "
x10"
-
- dat += "[get_design_cost(D)]
"
-
- dat += "
"
- return dat
-
-/obj/machinery/autoylathe/proc/search_win(mob/user)
- var/dat = "Return to main menu"
- dat += "Search results:
"
- dat += materials_printout()
-
- for(var/v in matching_designs)
- var/datum/design/D = v
- if(disabled || !can_build(D))
- dat += "
[D.name]"
- else
- dat += "
[D.name]"
-
- if(ispath(D.build_path, /obj/item/stack))
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- var/max_multiplier
- for(var/datum/material/mat in D.materials)
- max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat]))
- if (max_multiplier>10 && !disabled)
- dat += "
x10"
- if (max_multiplier>25 && !disabled)
- dat += "
x25"
- if(max_multiplier > 0 && !disabled)
- dat += "
x[max_multiplier]"
-
- dat += "[get_design_cost(D)]
"
-
- dat += "
"
- return dat
-
-/obj/machinery/autoylathe/proc/materials_printout()
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
- var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
"
- for(var/mat_id in materials.materials)
- var/datum/material/M = mat_id
- var/mineral_amount = materials.materials[mat_id]
- if(mineral_amount > 0)
- dat += "[M.name] amount: [mineral_amount] cm3
"
- return dat
-
-/obj/machinery/autoylathe/proc/can_build(datum/design/D, amount = 1)
- if(D.make_reagents.len)
- return FALSE
-
- var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
-
- var/list/required_materials = list()
-
- for(var/i in D.materials)
- required_materials[i] = D.materials[i] * coeff * amount
-
- var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
-
- return materials.has_materials(required_materials)
-
-/obj/machinery/autoylathe/proc/get_design_cost(datum/design/D)
- var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
- var/dat
- for(var/i in D.materials)
- if(istext(i)) //Category handling
- dat += "[D.materials[i] * coeff] [i]"
- else
- var/datum/material/M = i
- dat += "[D.materials[i] * coeff] [M.name] "
- return dat
-
-/obj/machinery/autoylathe/proc/reset(wire)
- switch(wire)
- if(WIRE_HACK)
- if(!wires.is_cut(wire))
- adjust_hacked(FALSE)
- if(WIRE_SHOCK)
- if(!wires.is_cut(wire))
- shocked = FALSE
- if(WIRE_DISABLE)
- if(!wires.is_cut(wire))
- disabled = FALSE
-
-/obj/machinery/autoylathe/proc/shock(mob/user, prb)
- if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
- return FALSE
- if(!prob(prb))
- return FALSE
- var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
- return TRUE
- else
- return FALSE
-
-/obj/machinery/autoylathe/proc/adjust_hacked(state)
- hacked = state
- for(var/id in SSresearch.techweb_designs)
- var/datum/design/D = SSresearch.techweb_designs[id]
- if((D.build_type & AUTOYLATHE) && ("hacked" in D.category))
- if(hacked)
- stored_research.add_design(D)
- else
- stored_research.remove_design(D)
-
-/obj/machinery/autoylathe/hacked/Initialize()
- . = ..()
- adjust_hacked(TRUE)
-
-//Called when the object is constructed by an autoylathe
-//Has a reference to the autoylathe so you can do !!FUN!! things with hacked lathes
-/obj/item/proc/autoylathe_crafted(obj/machinery/autoylathe/A)
- return
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index aaa87bbf01..2d63a39323 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -1033,9 +1033,9 @@
build_path = /obj/machinery/vending/kink
req_components = list(/obj/item/vending_refill/kink = 1)
-/obj/item/circuitboard/machine/autoylathe
+/obj/item/circuitboard/machine/autolathe/toy
name = "Autoylathe (Machine Board)"
- build_path = /obj/machinery/autoylathe
+ build_path = /obj/machinery/autolathe/toy
req_components = list(
/obj/item/stock_parts/matter_bin = 3,
/obj/item/stock_parts/manipulator = 1,
diff --git a/code/modules/research/designs/autoylathe_designs.dm b/code/modules/research/designs/autoylathe_designs.dm
index 7811cfdaad..0e572fee7a 100644
--- a/code/modules/research/designs/autoylathe_designs.dm
+++ b/code/modules/research/designs/autoylathe_designs.dm
@@ -1,5 +1,5 @@
/datum/design/autoylathe
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
/datum/design/autoylathe/mech
category = list("initial", "Figurines")
@@ -558,7 +558,7 @@
/datum/design/foam_x9
name = "Foam Force X9 Rifle"
id = "foam_x9"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
build_path = /obj/item/gun/ballistic/automatic/x9/toy
category = list("initial", "Rifles")
@@ -566,7 +566,7 @@
/datum/design/foam_dart
name = "Box of Foam Darts"
id = "foam_dart"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 500, /datum/material/iron = 100)
build_path = /obj/item/ammo_box/foambox
category = list("initial", "Misc")
@@ -574,7 +574,7 @@
/datum/design/foam_magpistol
name = "Foam Force Magpistol"
id = "magfoam_launcher"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
build_path = /obj/item/gun/ballistic/shotgun/toy/mag
category = list("initial", "Pistols")
@@ -582,7 +582,7 @@
/datum/design/foam_magrifle
name = "Foam Force MagRifle"
id = "foam_magrifle"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
build_path = /obj/item/gun/ballistic/automatic/toy/magrifle
category = list("initial", "Rifles")
@@ -590,7 +590,7 @@
/datum/design/foam_hyperburst
name = "MagTag Hyper Rifle"
id = "foam_hyperburst"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 2000, /datum/material/glass = 1000)
build_path = /obj/item/gun/energy/laser/practice/hyperburst
category = list("initial", "Rifles")
@@ -598,7 +598,7 @@
/datum/design/foam_sp
name = "Foam Force Stealth Pistol"
id = "foam_sp"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 1000)
build_path = /obj/item/gun/ballistic/automatic/toy/pistol/stealth
category = list("initial", "Pistols")
@@ -606,7 +606,7 @@
/datum/design/toyray
name = "RayTag Gun"
id = "toyray"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 1000, /datum/material/glass = 1000)
build_path = /obj/item/gun/energy/laser/practice/raygun
category = list("initial", "Pistols")
@@ -614,7 +614,7 @@
/datum/design/am4c
name = "Foam Force AM4-C Rifle"
id = "foam_am4c"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
build_path = /obj/item/gun/ballistic/automatic/AM4C
category = list("initial", "Rifles")
@@ -622,7 +622,7 @@
/datum/design/foam_f3
name = "Replica F3 Justicar"
id = "foam_f3"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
build_path = /obj/item/toy/gun/justicar
category = list("initial", "Pistols")
@@ -630,7 +630,7 @@
/datum/design/toy_blaster
name = "pump-action plastic blaster"
id = "toy_blaster"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 750, /datum/material/glass = 1000)
build_path = /obj/item/gun/energy/pumpaction/toy
category = list("initial", "Rifles")
@@ -638,7 +638,7 @@
/datum/design/capammo
name = "Box of Caps"
id = "capammo"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/iron = 10, /datum/material/glass = 10)
build_path = /obj/item/toy/ammo/gun
category = list("initial", "Misc")
@@ -646,7 +646,7 @@
/datum/design/foam_smg
name = "Foam Force SMG"
id = "foam_smg"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
build_path = /obj/item/gun/ballistic/automatic/toy/unrestricted
category = list("initial", "Pistols")
@@ -654,7 +654,7 @@
/datum/design/foam_pistol
name = "Foam Force Pistol"
id = "foam_pistol"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
build_path = /obj/item/gun/ballistic/automatic/toy/pistol/unrestricted
category = list("initial", "Pistols")
@@ -662,7 +662,7 @@
/datum/design/foam_shotgun
name = "Foam Force Shotgun"
id = "foam_shotgun"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
build_path = /obj/item/gun/ballistic/shotgun/toy/unrestricted
category = list("initial", "Rifles")
@@ -670,7 +670,7 @@
/datum/design/foam_dartred
name = "Box of Lastag Red Foam Darts"
id = "redfoam_dart"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 500, /datum/material/iron = 100)
build_path = /obj/item/ammo_box/foambox/tag/red
category = list("initial", "Misc")
@@ -678,7 +678,7 @@
/datum/design/foam_dartblue
name = "Box of Lastag Blue Foam Darts"
id = "bluefoam_dart"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 500, /datum/material/iron = 100)
build_path = /obj/item/ammo_box/foambox/tag/blue
category = list("initial", "Misc")
@@ -686,7 +686,7 @@
/datum/design/foam_bow
name = "Foam Force Crossbow"
id = "foam_bow"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
build_path = /obj/item/gun/ballistic/shotgun/toy/crossbow
category = list("initial", "Pistols")
@@ -694,7 +694,7 @@
/datum/design/foam_c20
name = "Donksoft C20R"
id = "foam_c20"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
build_path = /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted
category = list("hacked", "Rifles")
@@ -702,7 +702,7 @@
/datum/design/foam_l6
name = "Donksoft LMG"
id = "foam_LMG"
- build_type = AUTOYLATHE
+ build_type = TOYLATHE
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
build_path = /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted
category = list("hacked", "Rifles")
diff --git a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
index 6d63df7d4b..06cdef5ecc 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
@@ -111,6 +111,6 @@
name = "Machine Design (Autoylathe)"
desc = "The circuit board for an autoylathe."
id = "autoylathe"
- build_path = /obj/item/circuitboard/machine/autoylathe
+ build_path = /obj/item/circuitboard/machine/autolathe/toy
departmental_flags = DEPARTMENTAL_FLAG_ALL
category = list("Misc. Machinery")
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index be1b9460b0..ddc732d132 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -1026,7 +1026,7 @@ Nothing else in the console has ID requirements.
autolathe_friendly = FALSE
D.category -= "Imported"
- if(D.build_type & (AUTOLATHE|PROTOLATHE|CRAFTLATHE)) // Specifically excludes circuit imprinter and mechfab
+ if(D.build_type & (AUTOLATHE|PROTOLATHE|TOYLATHE)) // Specifically excludes circuit imprinter and mechfab
D.build_type = autolathe_friendly ? (D.build_type | AUTOLATHE) : D.build_type
D.category |= "Imported"
d_disk.blueprints[slot] = D
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index 388fa3785c..ddf6edc9f9 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -344,6 +344,7 @@
/datum/techweb/specialized/autounlocking
var/design_autounlock_buildtypes = NONE
+ var/design_autounlock_skip_types = NONE
var/design_autounlock_categories = list("initial") //if a design has a buildtype that matches the abovea and either has a category in this or this is null, unlock it.
var/node_autounlock_ids = list() //autounlock nodes of this type.
@@ -356,7 +357,7 @@
research_node_id(id, TRUE, FALSE)
for(var/id in SSresearch.techweb_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(id)
- if(D.build_type & design_autounlock_buildtypes)
+ if(D.build_type & (design_autounlock_buildtypes & allowed_buildtypes) && !(D.build_type & design_autounlock_skip_types))
for(var/i in D.category)
if(i in design_autounlock_categories)
add_design_by_id(D.id)
@@ -364,7 +365,16 @@
/datum/techweb/specialized/autounlocking/autolathe
design_autounlock_buildtypes = AUTOLATHE
- allowed_buildtypes = AUTOLATHE
+ allowed_buildtypes = AUTOLATHE|TOYLATHE
+
+/datum/techweb/specialized/autounlocking/autolathe/public
+ design_autounlock_skip_types = NO_PUBLIC_LATHE
+
+/datum/techweb/specialized/autounlocking/autolathe/toy
+ design_autounlock_buildtypes = TOYLATHE
+
+/datum/techweb/specialized/autounlocking/autolathe/toy/public
+ design_autounlock_skip_types = NO_PUBLIC_LATHE
/datum/techweb/specialized/autounlocking/limbgrower
design_autounlock_buildtypes = LIMBGROWER
@@ -381,10 +391,6 @@
/datum/techweb/specialized/autounlocking/exofab
allowed_buildtypes = MECHFAB
-/datum/techweb/specialized/autounlocking/autoylathe
- design_autounlock_buildtypes = AUTOYLATHE
- allowed_buildtypes = AUTOYLATHE
-
/datum/techweb/specialized/autounlocking/autobottler
design_autounlock_buildtypes = AUTOBOTTLER
allowed_buildtypes = AUTOBOTTLER
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index 3b3bb74df1..ef267190fd 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -585,7 +585,6 @@
#include "code\datums\wires\airlock.dm"
#include "code\datums\wires\apc.dm"
#include "code\datums\wires\autolathe.dm"
-#include "code\datums\wires\autoylathe.dm"
#include "code\datums\wires\emitter.dm"
#include "code\datums\wires\explosive.dm"
#include "code\datums\wires\microwave.dm"
@@ -722,7 +721,6 @@
#include "code\game\machinery\syndicatebeacon.dm"
#include "code\game\machinery\syndicatebomb.dm"
#include "code\game\machinery\teleporter.dm"
-#include "code\game\machinery\toylathe.dm"
#include "code\game\machinery\transformer.dm"
#include "code\game\machinery\turnstile.dm"
#include "code\game\machinery\washing_machine.dm"
From e9bf432a0df148be149157b5af65f65becb92495 Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Wed, 22 Apr 2020 03:30:40 +0200
Subject: [PATCH 02/41] Scavenging element.
---
code/__DEFINES/dcs/signals.dm | 2 +-
code/__DEFINES/misc.dm | 7 +
code/__HELPERS/_lists.dm | 26 +--
code/__HELPERS/mobs.dm | 12 +-
code/controllers/subsystem/vote.dm | 2 +-
code/datums/ai_laws.dm | 2 +-
code/datums/components/archaeology.dm | 95 ----------
code/datums/elements/scavenging.dm | 164 ++++++++++++++++++
code/game/gamemodes/game_mode.dm | 2 +-
code/game/objects/effects/landmarks.dm | 2 +-
code/game/objects/structures/loot_pile.dm | 66 +++++++
.../antagonists/traitor/datum_traitor.dm | 2 +-
.../living/simple_animal/friendly/mouse.dm | 6 +
icons/obj/loot_piles.dmi | Bin 0 -> 12091 bytes
tgstation.dme | 2 +
15 files changed, 261 insertions(+), 129 deletions(-)
delete mode 100644 code/datums/components/archaeology.dm
create mode 100644 code/datums/elements/scavenging.dm
create mode 100644 code/game/objects/structures/loot_pile.dm
create mode 100644 icons/obj/loot_piles.dmi
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 53348b3467..a09c96ad30 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -30,7 +30,7 @@
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
#define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
-#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob)
+#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob, list/examine_list)
#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //from base of atom/get_examine_name(): (/mob, list/overrides)
//Positions for overrides list
#define EXAMINE_POSITION_ARTICLE 1
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 3fb149d071..9febca663d 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -523,3 +523,10 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define NIGHTSHIFT_AREA_NONE 4 //default/highest.
#define UNTIL(X) while(!(X)) stoplag()
+
+
+//Scavenging element defines for special loot "events".
+#define SCAVENGING_FOUND_NOTHING "found_nothing"
+#define SCAVENGING_SPAWN_MOUSE "spawn_mouse"
+#define SCAVENGING_SPAWN_MICE "spawn_mice"
+#define SCAVENGING_SPAWN_TOM "spawn_tom_the_mouse"
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index a34b3ce67c..754b56a202 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -234,38 +234,20 @@
//2. Gets a number between 1 and that total
//3. For each element in the list, subtracts its weighting from that number
//4. If that makes the number 0 or less, return that element.
-/proc/pickweight(list/L)
+/proc/pickweight(list/L, base_weight = 1)
var/total = 0
var/item
for (item in L)
if (!L[item])
- L[item] = 1
+ L[item] = base_weight
total += L[item]
- total = rand(1, total)
+ total = rand() * total
for (item in L)
- total -=L [item]
+ total -= L[item]
if (total <= 0)
return item
- return null
-
-/proc/pickweightAllowZero(list/L) //The original pickweight proc will sometimes pick entries with zero weight. I'm not sure if changing the original will break anything, so I left it be.
- var/total = 0
- var/item
- for (item in L)
- if (!L[item])
- L[item] = 0
- total += L[item]
-
- total = rand(0, total)
- for (item in L)
- total -=L [item]
- if (total <= 0 && L[item])
- return item
-
- return null
-
//Pick a random element from the list and remove it from the list.
/proc/pick_n_take(list/L)
RETURN_TYPE(L[_].type)
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 2827e40120..d3ad4dcaec 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -311,7 +311,7 @@ GLOBAL_LIST_EMPTY(species_list)
else
return "unknown"
-/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null, ignorehelditem = 0)
+/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null, ignorehelditem = FALSE, resume_time = 0 SECONDS)
if(!user || !target)
return 0
var/user_loc = user.loc
@@ -330,10 +330,10 @@ GLOBAL_LIST_EMPTY(species_list)
var/endtime = world.time+time
var/starttime = world.time
. = 1
- while (world.time < endtime)
+ while (world.time + resume_time < endtime)
stoplag(1)
if (progress)
- progbar.update(world.time - starttime)
+ progbar.update(world.time - starttime + resume_time)
if(QDELETED(user) || QDELETED(target))
. = 0
break
@@ -365,7 +365,7 @@ GLOBAL_LIST_EMPTY(species_list)
checked_health["health"] = health
return ..()
-/proc/do_after(mob/user, var/delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null, required_mobility_flags = (MOBILITY_USE|MOBILITY_MOVE))
+/proc/do_after(mob/user, var/delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null, required_mobility_flags = (MOBILITY_USE|MOBILITY_MOVE), resume_time = 0 SECONDS)
if(!user)
return 0
var/atom/Tloc = null
@@ -394,10 +394,10 @@ GLOBAL_LIST_EMPTY(species_list)
var/starttime = world.time
. = 1
var/mob/living/L = isliving(user) && user //evals to last thing eval'd
- while (world.time < endtime)
+ while (world.time + resume_time < endtime)
stoplag(1)
if (progress)
- progbar.update(world.time - starttime)
+ progbar.update(world.time - starttime + resume_time)
if(drifting && !user.inertia_dir)
drifting = 0
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index a202afd905..df3f24f0dc 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -361,7 +361,7 @@ SUBSYSTEM_DEF(vote)
picked = S
runnable_storytellers[S] *= round(stored_gamemode_votes[initial(S.name)]*100000,1)
if(!picked)
- picked = pickweightAllowZero(runnable_storytellers)
+ picked = pickweight(runnable_storytellers, 0)
GLOB.dynamic_storyteller_type = picked
if("map")
var/datum/map_config/VM = config.maplist[.]
diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm
index ebddc187ae..9c6bb2ebfd 100644
--- a/code/datums/ai_laws.dm
+++ b/code/datums/ai_laws.dm
@@ -253,7 +253,7 @@
var/datum/ai_laws/lawtype
var/list/law_weights = CONFIG_GET(keyed_list/law_weight)
while(!lawtype && law_weights.len)
- var/possible_id = pickweightAllowZero(law_weights)
+ var/possible_id = pickweight(law_weights, 0)
lawtype = lawid_to_type(possible_id)
if(!lawtype)
law_weights -= possible_id
diff --git a/code/datums/components/archaeology.dm b/code/datums/components/archaeology.dm
deleted file mode 100644
index b5740650e9..0000000000
--- a/code/datums/components/archaeology.dm
+++ /dev/null
@@ -1,95 +0,0 @@
-/datum/component/archaeology
- dupe_mode = COMPONENT_DUPE_UNIQUE
- var/list/archdrops = list(/obj/item/bikehorn = list(ARCH_PROB = 100, ARCH_MAXDROP = 1)) // honk~
- var/prob2drop
- var/dug
- var/datum/callback/callback
-
-/datum/component/archaeology/Initialize(list/_archdrops = list(), datum/callback/_callback)
- archdrops = _archdrops
- for(var/i in archdrops)
- if(isnull(archdrops[i][ARCH_MAXDROP]))
- archdrops[i][ARCH_MAXDROP] = 1
- stack_trace("ARCHAEOLOGY WARNING: [parent] contained a null max_drop value in [i].")
- if(isnull(archdrops[i][ARCH_PROB]))
- archdrops[i][ARCH_PROB] = 100
- stack_trace("ARCHAEOLOGY WARNING: [parent] contained a null probability value in [i].")
- callback = _callback
- RegisterSignal(parent, COMSIG_PARENT_ATTACKBY,.proc/Dig)
- RegisterSignal(parent, COMSIG_ATOM_EX_ACT, .proc/BombDig)
- RegisterSignal(parent, COMSIG_ATOM_SING_PULL, .proc/SingDig)
-
-/datum/component/archaeology/InheritComponent(datum/component/archaeology/A, i_am_original)
- var/list/other_archdrops = A.archdrops
- var/list/_archdrops = archdrops
- for(var/I in other_archdrops)
- _archdrops[I] += other_archdrops[I]
-
-/datum/component/archaeology/proc/Dig(datum/source, obj/item/I, mob/living/user)
- if(dug)
- to_chat(user, "Looks like someone has dug here already.")
- return
-
- if(!isturf(user.loc))
- return
-
- if(I.tool_behaviour == TOOL_SHOVEL || I.tool_behaviour == TOOL_MINING)
- to_chat(user, "You start digging...")
-
- if(I.use_tool(parent, user, 40, volume=50))
- to_chat(user, "You dig a hole.")
- gets_dug()
- dug = TRUE
- SSblackbox.record_feedback("tally", "pick_used_mining", 1, I.type)
- return COMPONENT_NO_AFTERATTACK
-
-/datum/component/archaeology/proc/gets_dug()
- if(dug)
- return
- else
- var/turf/open/OT = get_turf(parent)
- for(var/thing in archdrops)
- var/maxtodrop = archdrops[thing][ARCH_MAXDROP]
- for(var/i in 1 to maxtodrop)
- if(prob(archdrops[thing][ARCH_PROB])) // can't win them all!
- new thing(OT)
-
- if(isopenturf(OT))
- if(OT.postdig_icon_change)
- if(istype(OT, /turf/open/floor/plating/asteroid/) && !OT.postdig_icon)
- var/turf/open/floor/plating/asteroid/AOT = parent
- AOT.icon_plating = "[AOT.environment_type]_dug"
- AOT.icon_state = "[AOT.environment_type]_dug"
- else
- if(isplatingturf(OT))
- var/turf/open/floor/plating/POT = parent
- POT.icon_plating = "[POT.postdig_icon]"
- POT.icon_state = "[OT.postdig_icon]"
-
- if(OT.slowdown) //Things like snow slow you down until you dig them.
- OT.slowdown = 0
- dug = TRUE
- if(callback)
- callback.Invoke()
-
-/datum/component/archaeology/proc/SingDig(datum/source, S, current_size)
- switch(current_size)
- if(STAGE_THREE)
- if(prob(30))
- gets_dug()
- if(STAGE_FOUR)
- if(prob(50))
- gets_dug()
- else
- if(current_size >= STAGE_FIVE && prob(70))
- gets_dug()
-
-/datum/component/archaeology/proc/BombDig(datum/source, severity, target)
- switch(severity)
- if(3)
- return
- if(2)
- if(prob(20))
- gets_dug()
- if(1)
- gets_dug()
diff --git a/code/datums/elements/scavenging.dm b/code/datums/elements/scavenging.dm
new file mode 100644
index 0000000000..b2ca7adcc3
--- /dev/null
+++ b/code/datums/elements/scavenging.dm
@@ -0,0 +1,164 @@
+ /*
+ * Scavenging element. Its scope shouldn't elude your imagination.
+ * Basically loot piles that can be searched through for some items.
+ * In my opinion, these are more engaging than normal maintenance loot spawners.
+ * The loot doesn't have to be strictly made of items and objects, you could also use it to invoke some "events"
+ * such as mice, rats, an halloween spook, persistent relics, traps, etcetera, go wild.
+ */
+/datum/element/scavenging
+ element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
+ id_arg_index = 3
+
+ var/list/loot_left_per_atom = list() //loot left per attached atom.
+ var/list/loot_table //pickweight list of available loot.
+ var/list/unique_loot //limited loot, once the associated value reaches zero, its key is removed from loot_table
+ var/scavenge_time = 12 SECONDS //how much time it takes
+ var/can_use_hands = TRUE //bare handed scavenge time multiplier. If set to zero, only tools are usable.
+ var/list/tool_types //which tool types the player can use instead of scavenging by hand, associated value is their speed.
+ var/del_atom_on_depletion = FALSE //Will the atom be deleted when there is no loot left?
+ var/list/search_texts = list("searches through ", "search through ", "You hear rummaging...")
+
+ var/mean_loot_weight = 0
+ var/list/progress_per_atom = list() //seconds of ditched progress per atom, used to resume the work instead of starting over.
+ var/static/list/players_busy_scavenging = list() //players already busy scavenging.
+
+/datum/element/scavenging/Attach(atom/target, amount = 5, list/loot, list/unique, time = 10 SECONDS, hands = TRUE, list/tools, list/texts, del_deplete = FALSE)
+ . = ..()
+ if(. == ELEMENT_INCOMPATIBLE || !length(loot) || !amount || !istype(target) || isarea(target))
+ return ELEMENT_INCOMPATIBLE
+ loot_left_per_atom[target] = amount
+ if(!loot_table)
+ loot_table = loot
+ for(var/A in loot_table) //tally the list weights
+ mean_loot_weight += loot_table[A]
+ mean_loot_weight /= length(loot_table)
+ if(!unique_loot)
+ unique_loot = unique || list()
+ scavenge_time = time
+ can_use_hands = hands
+ tool_types = tools
+ if(texts)
+ search_texts = texts
+ del_atom_on_depletion = del_deplete
+ if(can_use_hands)
+ RegisterSignal(target, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW), .proc/scavenge_barehanded)
+ if(tool_types)
+ RegisterSignal(target, COMSIG_PARENT_ATTACKBY, .proc/scavenge_tool)
+ RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_examine)
+
+/datum/element/scavenging/Detach(atom/target)
+ . = ..()
+ loot_left_per_atom -= target
+ progress_per_atom -= target
+ UnregisterSignal(target, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE))
+
+/datum/element/scavenging/proc/on_examine(atom/source, mob/user, list/examine_list)
+ var/text
+ var/methods = tool_types
+ if(can_use_hands)
+ if(!length(methods))
+ methods = list("bare handed")
+ else
+ methods += "simply bare handed"
+ text = english_list(methods, "", " or ")
+ . += "Looks like [source.p_they()] can be scavenged[length(tool_types) ? " with either a" : ""] [text]"
+
+/datum/element/scavenging/proc/scavenge_barehanded(atom/source, mob/user)
+ scavenge(source, user, 1)
+ return COMPONENT_NO_ATTACK_HAND
+
+/datum/element/scavenging/proc/scavenge_tool(atom/source, obj/item/I, mob/living/user, params)
+ if(mob.a_intent == INTENT_HARM) //Robust trash disposal techniques!
+ return
+ var/speed_multi = tool_types[I.tool_behaviour]
+ if(!speed_multi)
+ return
+ scavenge(source, user, speed_multi)
+ return COMPONENT_NO_AFTERATTACK
+
+/datum/element/scavenging/proc/scavenge(atom/source, mob/user, speed_multi = 1)
+ if(players_busy_scavenging[user])
+ return
+ players_busy_scavenging[user] = TRUE
+ var/progress_done = progress_per_atom[source]
+ var/len_messages = length(search_texts)
+ var/msg_first_person
+ if(len_messages >= 2)
+ msg_first_person = "You [progress_done ? "resume a ditched task and " : ""][search_texts[2]] [src]."
+ var/msg_blind
+ if(len_messages >= 3)
+ msg_blind = "[search_texts[3]]"
+ user.visible_message("[user] [search_texts[1]] [src].", msg_first_person, msg_blind)
+ if(do_after(user, scavenge_time, TRUE, source, TRUE, CALLBACK(src, .proc/set_progress, source, world.time), resume_time = progress_done))
+ spawn_loot(source, user)
+ players_busy_scavenging -= user
+ progress_per_atom -= source
+
+/datum/element/scavenging/proc/set_progress(atom/source, start_time)
+ progress_per_atom[source] = world.time - start_time
+
+/datum/element/scavenging/proc/spawn_loot(atom/source, mob/user)
+ var/loot = pickweight(loot_table)
+ var/special = TRUE
+ var/free = FALSE
+ if(!loot_left_per_atom[source])
+ to_chat(user, "Looks likes there is nothing worth of interest left in [src] anymore, further attempts would be futile.")
+ return
+ switch(loot) // TODO: datumize these out.
+ if(SCAVENGING_FOUND_NOTHING)
+ to_chat(user, "You found nothing, better luck next time.")
+ free = TRUE //doesn't consume the loot pile.
+ if(SCAVENGING_SPAWN_MOUSE)
+ var/nasty_rodent = pick("mouse", "rodent", "squeaky critter", "stupid pest", "annoying cable chewer", "nasty, ugly, evil, disease-ridden rodent")
+ to_chat(user, "You found something in [src]... no wait, that's just another [nasty_rodent].")
+ new /mob/living/simple_animal/mouse(source.loc)
+ if(SCAVENGING_SPAWN_MICE)
+ user.visible_message("A small gang of mice emerges from [source].", \
+ "You found something in [src]... no wait, that's just another- no wait, that's a lot of damn mice.")
+ for(var/i in 1 to rand(4, 6))
+ new /mob/living/simple_animal/mouse(source.loc)
+ if(SCAVENGING_SPAWN_TOM)
+ if(GLOB.tom_existed) //There can only be one.
+ to_chat(user, "You found nothing, better luck next time.")
+ free = TRUE
+ else
+ to_chat(user, "You found something in [src]... no wait, that's Tom, the mouse! What is he doing here?")
+ new /mob/living/simple_animal/mouse/brown/Tom(source.loc)
+ else
+ special = FALSE
+
+ if(!special) //generic loot. Nothing too strange like more loot spawners anyway.
+ var/atom/A = new loot(source.loc)
+ if(isitem(A) && !user.get_active_held_item())
+ user.put_in_hands(A)
+ var/rarity_append = "."
+ switch(loot_table[loot]/mean_loot_weight*100)
+ if(0 to 1)
+ rarity_append = "! AMAZING!"
+ if(1 to 2)
+ rarity_append = "! Woah!"
+ if(2 to 5)
+ rarity_append = ". Rare!"
+ if(5 to 10)
+ rarity_append = ". Great."
+ if(10 to 25)
+ rarity_append = ". Nice."
+ if(20 to 50)
+ rarity_append = ". Not bad."
+ to_chat(user, "You found something in [src]... it's \a [A][rarity_append]")
+
+ if(unique_loot[loot])
+ var/loot_left = --unique_loot[loot]
+ if(!loot_left)
+ loot_table -= loot
+ unique_loot -= loot
+ mean_loot_weight = 0
+ for(var/A in loot_table) //re-tally the list weights
+ mean_loot_weight += loot_table[A]
+ mean_loot_weight /= length(loot_table)
+
+ if(!free)
+ --loot_left_per_atom[source]
+ if(del_atom_on_depletion && !loot_left_per_atom[source])
+ source.visible_message("[src] has been looted clean.")
+ qdel(source)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 5affeba6d6..57919863f2 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -272,7 +272,7 @@
reports += config.mode_reports[config_tag]
Count++
for(var/i in Count to rand(3,5)) //Between three and five wrong entries on the list.
- var/false_report_type = pickweightAllowZero(report_weights)
+ var/false_report_type = pickweight(report_weights, 0)
report_weights[false_report_type] = 0 //Make it so the same false report won't be selected twice
reports += config.mode_reports[false_report_type]
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 04f14692e3..851a041aab 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -483,7 +483,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
if(!SSmapping.station_room_templates[t])
log_world("Station room spawner placed at ([T.x], [T.y], [T.z]) has invalid ruin name of \"[t]\" in its list")
templates -= t
- template_name = pickweightAllowZero(templates)
+ template_name = pickweight(templates, 0)
if(!template_name)
GLOB.stationroom_landmarks -= src
qdel(src)
diff --git a/code/game/objects/structures/loot_pile.dm b/code/game/objects/structures/loot_pile.dm
new file mode 100644
index 0000000000..0886c1c8b7
--- /dev/null
+++ b/code/game/objects/structures/loot_pile.dm
@@ -0,0 +1,66 @@
+ /*
+ * Loot piles structures, somewhat inspired from Polaris 13 ones but without the one search per pile ckey/mind restriction
+ * because the actual code is located its own element and has enough variables already. the piles themselves merely cosmetical.
+ */
+/obj/structure/loot_pile
+ name = "pile of junk"
+ desc = "Lots of junk lying around. They say one man's trash is another man's treasure."
+ icon = 'icons/obj/loot_piles.dmi'
+ density = FALSE
+ anchored = TRUE
+ var/loot_amount = 5
+ var/delete_on_depletion = FALSE
+ var/can_use_hands = TRUE
+ var/scavenge_time = 12 SECONDS
+ var/allowed_tools = list(TOOL_SHOVEL = 0.6) //list of tool_behaviours with associated speed multipliers (lower is better)
+ var/icon_states_to_use = list("junk_pile1", "junk_pile2", "junk_pile3", "junk_pile4", "junk_pile5")
+ var/list/loot = list(
+ SCAVENGING_FOUND_NOTHING = 50,
+ SCAVENGING_SPAWN_MOUSE = 10,
+ SCAVENGING_SPAWN_MICE = 5,
+ SCAVENGING_SPAWN_TOM = 1,
+ /obj/item/flashlight/flare = 10,
+ /obj/item/flashlight/glowstick = 10,
+ /obj/item/flashlight/glowstick/blue = 10,
+ /obj/item/flashlight/glowstick/orange = 10,
+ /obj/item/flashlight/glowstick/red = 10,
+ /obj/item/flashlight/glowstick/yellow = 10,
+ /obj/item/clothing/mask/gas = 5,
+ /obj/item/clothing/mask/breath = 10,
+ /obj/item/storage/box = 10,
+ /obj/item/clothing/shoes/galoshes = 2,
+ /obj/item/clothing/shoes/sneakers/black = 10,
+ /obj/item/clothing/gloves/color/fyellow = 5,
+ /obj/item/clothing/gloves/color/yellow = 2,
+ /obj/item/clothing/glasses/sunglasses = 3,
+ /obj/item/clothing/glasses/meson = 3,
+ /obj/item/clothing/glasses/welding = 3,
+ /obj/item/clothing/head/hardhat = 10,
+ /obj/item/clothing/head/ushanka = 10,
+ /obj/item/clothing/head/welding = 5,
+ /obj/item/clothing/suit/hazardvest = 10,
+ /obj/item/clothing/under/syndicate/tacticool = 5,
+ /obj/item/clothing/under/pants/camo = 10,
+ /obj/item/stack/spacecash/c10 = 20,
+ /obj/item/stack/spacecash/c20 = 20,
+ /obj/item/stack/spacecash/c50 = 20,
+ /obj/item/radio/headset = 10)
+
+ /*
+ * Associated values in this list are not weights but numbers of times the kery can be rolled
+ * before being removed from ALL piles with same kind. This is why I wanted 'scavenging' to be an element and not a component.
+ */
+ var/list/unique_loot = list(/obj/item/clothing/gloves/color/yellow = 2, SCAVENGING_SPAWN_TOM = 1)
+
+/obj/structure/loot_pile/Initialize()
+ . = ..()
+ icon_state = pick(icon_states_to_use)
+
+/obj/structure/loot_pile/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/scavenging, loot_amount, loot, unique_loot, scavenge_time, can_use_hands, allowed_tools, null, delete_on_depletion)
+
+/obj/structure/loot_pile/infinite
+ name = "endless pile of junk."
+ desc = "Lots of awful code lying around. They don't say one coder's trash is another coder's treasure though..."
+ loot_amount = INFINITY
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index cf10f87bf8..df5e6004ba 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -48,7 +48,7 @@
var/datum/traitor_class/class = GLOB.traitor_classes[C]
var/weight = LOGISTIC_FUNCTION(1.5*class.weight,chaos_weight,class.chaos,0)
weights[C] = weight * 1000
- var/choice = pickweightAllowZero(weights)
+ var/choice = pickweight(weights, 0)
if(!choice)
choice = TRAITOR_HUMAN // it's an "easter egg"
var/datum/traitor_class/actual_class = GLOB.traitor_classes[choice]
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 370442d4c4..7f83bb9f9b 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -97,6 +97,8 @@
body_color = "brown"
icon_state = "mouse_brown"
+GLOBAL_VAR(tom_existed)
+
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
name = "Tom"
@@ -106,6 +108,10 @@
response_harm = "splats"
gold_core_spawnable = NO_SPAWN
+/mob/living/simple_animal/mouse/brown/Tom/Initialize()
+ . = ..()
+ GLOB.tom_existed = TRUE
+
/obj/item/reagent_containers/food/snacks/deadmouse
name = "dead mouse"
desc = "It looks like somebody dropped the bass on it. A lizard's favorite meal."
diff --git a/icons/obj/loot_piles.dmi b/icons/obj/loot_piles.dmi
new file mode 100644
index 0000000000000000000000000000000000000000..3d83d6612ec49b238a0934962192abac1d90d6f9
GIT binary patch
literal 12091
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
B=b!)p
literal 0
HcmV?d00001
diff --git a/tgstation.dme b/tgstation.dme
index 3b3bb74df1..147c91c92e 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -516,6 +516,7 @@
#include "code\datums\elements\ghost_role_eligibility.dm"
#include "code\datums\elements\mob_holder.dm"
#include "code\datums\elements\polychromic.dm"
+#include "code\datums\elements\scavenging.dm"
#include "code\datums\elements\spellcasting.dm"
#include "code\datums\elements\swimming.dm"
#include "code\datums\elements\sword_point.dm"
@@ -1119,6 +1120,7 @@
#include "code\game\objects\structures\lattice.dm"
#include "code\game\objects\structures\life_candle.dm"
#include "code\game\objects\structures\loom.dm"
+#include "code\game\objects\structures\loot_pile.dm"
#include "code\game\objects\structures\manned_turret.dm"
#include "code\game\objects\structures\memorial.dm"
#include "code\game\objects\structures\mineral_doors.dm"
From 122067c5f4e0fe81a722c68b961df7a0a3d1eac1 Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Wed, 22 Apr 2020 03:52:45 +0200
Subject: [PATCH 03/41] wip
---
code/datums/elements/scavenging.dm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/code/datums/elements/scavenging.dm b/code/datums/elements/scavenging.dm
index b2ca7adcc3..c34fd8f430 100644
--- a/code/datums/elements/scavenging.dm
+++ b/code/datums/elements/scavenging.dm
@@ -67,8 +67,8 @@
scavenge(source, user, 1)
return COMPONENT_NO_ATTACK_HAND
-/datum/element/scavenging/proc/scavenge_tool(atom/source, obj/item/I, mob/living/user, params)
- if(mob.a_intent == INTENT_HARM) //Robust trash disposal techniques!
+/datum/element/scavenging/proc/scavenge_tool(atom/source, obj/item/I, mob/user, params)
+ if(user.a_intent == INTENT_HARM) //Robust trash disposal techniques!
return
var/speed_multi = tool_types[I.tool_behaviour]
if(!speed_multi)
From af3651172c1c4c60e1f8033e35fcd19ad8c08536 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:29:31 -0700
Subject: [PATCH 04/41] wow lotsa effort huh
---
code/controllers/subsystem/mapping.dm | 24 +++
.../crafting/recipes/recipes_misc.dm | 9 ++
code/game/objects/items/crayons.dm | 9 +-
.../items/devices/electrochromatic_kit.dm | 15 ++
code/game/objects/structures/window.dm | 141 +++++++++++++++++-
code/modules/assembly/doorcontrol.dm | 47 +++++-
.../autolathe_designs_electronics.dm | 8 +
tgstation.dme | 1 +
8 files changed, 241 insertions(+), 13 deletions(-)
create mode 100644 code/game/objects/items/devices/electrochromatic_kit.dm
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index 89155cefb3..ffda2731b1 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -42,6 +42,13 @@ SUBSYSTEM_DEF(mapping)
var/stat_map_name = "Loading..."
+ /// Lookup list for random generated IDs.
+ var/list/random_generated_ids_by_original = list()
+ /// next id for separating obfuscated ids.
+ var/obfuscation_next_id = 1
+ /// "secret" key
+ var/obfuscation_secret
+
//dlete dis once #39770 is resolved
/datum/controller/subsystem/mapping/proc/HACK_LoadMapConfig()
if(!config)
@@ -52,6 +59,10 @@ SUBSYSTEM_DEF(mapping)
#endif
stat_map_name = config.map_name
+/datum/controller/subsystem/mapping/PreInit()
+ if(!obfuscation_secret)
+ obfuscation_secret = md5(GUID()) //HAH! Guess this!
+
/datum/controller/subsystem/mapping/Initialize(timeofday)
HACK_LoadMapConfig()
if(initialized)
@@ -568,3 +579,16 @@ GLOBAL_LIST_EMPTY(the_station_areas)
LM.load()
if(GLOB.stationroom_landmarks.len)
seedStation() //I'm sure we can trust everyone not to insert a 1x1 rooms which loads a landmark which loads a landmark which loads a la...
+
+/**
+ * Generates an obfuscated but constant id for an original id for cases where you don't want players codediving for an id.
+ * WARNING: MAKE SURE PLAYERS ARE NOT ABLE TO ACCESS THIS. To save performance, it's just secret + an incrementing number. Very guessable if you know what the secret is.
+ */
+/datum/controller/subsystem/mapping/proc/get_obfuscated_id(original, id_type = "GENERAL")
+ if(!original)
+ return //no.
+ var/key = "[original]%[id_type]"
+ if(random_generated_ids_by_original[key])
+ return random_generated_ids_by_original[key]
+ random_generated_ids_by_original[key] = "[obfuscation_secret]%[obfuscation_next++]"
+ return value
diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm
index cf0e1bdec9..b26755d4ac 100644
--- a/code/datums/components/crafting/recipes/recipes_misc.dm
+++ b/code/datums/components/crafting/recipes/recipes_misc.dm
@@ -233,6 +233,15 @@
subcategory = CAT_TOOL
category = CAT_MISC
+/datum/crafting_recipe/electrochromatic_kit
+ name = "Electrochromatic Kit"
+ result = /obj/item/electronics/electrochromatic_kit
+ reqs = list(/obj/item/stack/metal = 1,
+ /obj/item/stack/cable_coil = 1)
+ time = 5
+ subcategory = CAT_MISCELLANEOUS
+ category = CAT_MISC
+
////////////
//Vehicles//
////////////
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 3dad3877b7..f60edf2917 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -726,13 +726,12 @@
to_chat(usr, "A color that dark on an object like this? Surely not...")
return FALSE
- target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
if(istype(target, /obj/structure/window))
- if(color_hex2num(paint_color) < 255)
- target.set_opacity(255)
- else
- target.set_opacity(initial(target.opacity))
+ var/obj/structure/window/W = target
+ W.spraycan_paint(paint_color)
+ else
+ target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
. = use_charges(user, 2)
var/fraction = min(1, . / reagents.maximum_volume)
diff --git a/code/game/objects/items/devices/electrochromatic_kit.dm b/code/game/objects/items/devices/electrochromatic_kit.dm
new file mode 100644
index 0000000000..aae886d397
--- /dev/null
+++ b/code/game/objects/items/devices/electrochromatic_kit.dm
@@ -0,0 +1,15 @@
+/obj/item/electronics/electrochromatic_kit
+ name = "electrochromatic kit"
+ desc = "A kit for upgrading a window into an electrochromatic one."
+ icon = 'icons/obj/device.dmi'
+ /// Electrochromatic ID
+ var/id
+
+/obj/item/electronics/electrochromatic_kit/attack_self(mob/user)
+ . = ..()
+ if(.)
+ return
+ var/new_id = input(user, "Set this kit's electrochromatic ID", "Set ID", id) as text|null
+ if(isnull(new_id))
+ return
+ id = new_id
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 5dd4e7d987..07fd8142cb 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -1,3 +1,19 @@
+#define NOT_ELECTROCHROMATIC 0
+#define ELECTROCHROMATIC_OFF 1
+#define ELECTROCHROMATIC_DIMMED 2
+
+GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
+
+/proc/do_electrochromatic_toggle(new_status, id)
+ var/list/windows = GLOB.electrochromatic_window_lookup["[id]"]
+ if(!windows)
+ return
+ var/obj/structure/window/W = i
+ for(var/i in windows)
+ W = i
+ new_status? W.electrochromatic_dim() : W.electrochromatic_off()
+
+
/obj/structure/window
name = "window"
desc = "A window."
@@ -28,8 +44,15 @@
rad_insulation = RAD_VERY_LIGHT_INSULATION
rad_flags = RAD_PROTECT_CONTENTS
+ /// Electrochromatic status
+ var/electrochromatic_status = NOT_ELECTROCHROMATIC
+ /// Electrochromatic ID. Set the first character to ! to replace with a SSmapping generated pseudorandom obfuscated ID for mapping purposes.
+ var/electrochromatic_id
+
/obj/structure/window/examine(mob/user)
. = ..()
+ if(electrochromatic_status != NOT_ELECTROCHROMATIC)
+ . += "The window has electrochromatic circuitry on it.")
if(reinf)
if(anchored && state == WINDOW_SCREWED_TO_FRAME)
. += "The window is screwed to the frame."
@@ -52,6 +75,10 @@
if(reinf && anchored)
state = WINDOW_SCREWED_TO_FRAME
+ if(mapload && electrochromatic_id)
+ if(copytext(electrochromatic_id, 1, 2) == "!")
+ electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id)
+
ini_dir = dir
air_update_turf(1)
@@ -62,6 +89,12 @@
real_explosion_block = explosion_block
explosion_block = EXPLOSION_BLOCK_PROC
+ if(electrochromatic_status != NOT_ELECTROCHROMATIC)
+ var/old = electrochromatic_status
+ make_electrochromatic()
+ if(old == ELECTROCHROMATIC_DIMMED)
+ electrochromatic_dim()
+
/obj/structure/window/ComponentInitialize()
. = ..()
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS ,null,CALLBACK(src, .proc/can_be_rotated),CALLBACK(src,.proc/after_rotation))
@@ -177,6 +210,24 @@
to_chat(user, "[src] is already in good condition!")
return
+ if(!anchored && istype(I, /obj/item/electronics/electrochromatic_kit && user.a_intent == INTENT_HELP)
+ var/obj/item/electronics/electrochromatic_kit/K = I
+ if(!user.temporarilyRemoveItemFromInventory(K))
+ to_chat(user, "[K] is stuck to your hand!")
+ return
+ if(is_electrochromatic)
+ to_chat(user, "[src] is already electrochromatic!")
+ return
+ if(!anchored)
+ to_chat(user, "[src] must not be attached to the floor!")
+ return
+ if(!K.id)
+ to_chat(user, "[K] has no ID set!")
+ return
+ user.visible_message("[user] upgrades [src] with [I].", "You upgrade [src] with [I].")
+ make_electrochromatic(K.id)
+ qdel(K)
+
if(!(flags_1&NODECONSTRUCT_1))
if(istype(I, /obj/item/screwdriver))
I.play_tool_sound(src, 75)
@@ -224,6 +275,85 @@
air_update_turf(TRUE)
update_nearby_icons()
+/obj/structure/window/proc/spraycan_paint(paint_color)
+ if(color_hex2num(paint_color) < 255)
+ set_opacity(255)
+ else
+ set_opacity(initial(opacity))
+ add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY)
+
+/obj/structure/window/proc/electrochromatic_dim()
+ if(electrochromatic_status == ELECTROCHROMATIC_DIMMED)
+ return
+ electrochromatic_status = ELECTROCHROMATIC_DIMMED
+ animate(src, color = "#222222", time = 2)
+ set_opacity(TRUE)
+
+/obj/structure/window/proc/electrochromatic_off()
+ if(electrochromatic_status == ELECTROCHROMATIC_OFF)
+ return
+ electrochromatic_on = FALSE
+ var/current = color
+ update_atom_colour()
+ var/newcolor = color
+ color = current
+ animate(src, color = newcolor, time = 2)
+
+/obj/structure/window/proc/remove_electrochromatic()
+ electrochromatic_status = NOT_ELECTROCHROMATIC
+ if(!electrochromatic_id)
+ return
+ var/list/L = GLOB.electrochromatic_window_lookup["[electrochromatic_id]"]
+ if(L)
+ L -= src
+ electrochromatic_id = null
+
+/obj/structure/window/vv_edit_var(var_name, var_value)
+ var/old_id
+ var/check_status
+ if(var_name == NAMEOF(src, electrochromatic_id))
+ if((electrochromatic_status != NOT_ELECTROCHROMATIC) && electrochromatic_id)
+ old_id = electrochromatic_id
+ if(var_name == NAMEOF(src, electrochromatic_status))
+ check_status = TRUE
+ . = ..() //do this first incase it runtimes.
+ if(check_status)
+ if(electrochromatic_status == NOT_ELECTROCHROMATIC)
+ remove_electrochromatic()
+ return
+ else if(electrochromatic_status == ELECTROCHROMATIC_OFF)
+ if(!electrochromatic_id)
+ return
+ else
+ make_electrochromatic()
+ electrochromatic_off()
+ return
+ else if(electrochromatic_status == ELECTROCHROMATIC_DIMMED)
+ if(!electrochromatic_id)
+ return
+ else
+ make_electrochromatic()
+ electrochromatic_dim()
+ return
+ else
+ remove_electrochromatic()
+ if(old_id)
+ GLOB.electrochromatic_window_lookup[old_id] -= src
+ if(electrochromatic_id)
+ GLOB.electrochromatic_window_lookup[electrochromatic_id] += src
+
+/obj/structure/window/proc/make_electrochromatic(new_id)
+ remove_electrochromatic()
+ electrochromatic_id = new_id
+ electrochromatic_status = ELECTROCHROMATIC_OFF
+ LAZYINITLIST(GLOB.electrochromatic_window_lookup["[electrochromatic_id]")
+ GLOB.electrochromatic_window_lookup[electrochromatic_id] |= src
+
+/obj/structure/window/update_atom_colour()
+ if((electrochromatic_status != ELECTROCHROMATIC_OFF) && (electrochromatic_status != ELECTROCHROMATIC_DIMMED))
+ return FALSE
+ return ..()
+
/obj/structure/window/proc/check_state(checked_state)
if(state == checked_state)
return TRUE
@@ -263,7 +393,6 @@
if(BURN)
playsound(src, 'sound/items/Welder.ogg', 100, 1)
-
/obj/structure/window/deconstruct(disassembled = TRUE)
if(QDELETED(src))
return
@@ -272,6 +401,9 @@
if(!(flags_1 & NODECONSTRUCT_1))
for(var/obj/item/shard/debris in spawnDebris(drop_location()))
transfer_fingerprints_to(debris) // transfer fingerprints to shards only
+ if(electrochromatic_status != NOT_ELECTROCHROMATIC) //eh fine keep your kit.
+ new /obj/item/electrochromatic_kit/K(drop_location())
+ // Intentionally not setting the ID so you can't decon one to know all of the IDs.
qdel(src)
update_nearby_icons()
@@ -315,9 +447,9 @@
density = FALSE
air_update_turf(1)
update_nearby_icons()
+ remove_electrochromatic()
return ..()
-
/obj/structure/window/Move()
var/turf/T = loc
. = ..()
@@ -731,7 +863,6 @@
set_opacity(TRUE)
queue_smooth(src)
-
/obj/structure/window/paperframe/attackby(obj/item/W, mob/user)
if(W.get_temperature())
fire_act(W.get_temperature())
@@ -749,3 +880,7 @@
return
..()
update_icon()
+
+#undef NOT_ELECTROCHROMATIC
+#undef ELECTROCHROMATIC_OFF
+#undef ELECTROCHROMATIC_DIMMED
diff --git a/code/modules/assembly/doorcontrol.dm b/code/modules/assembly/doorcontrol.dm
index 1c9c1a0203..1b9e63abaa 100644
--- a/code/modules/assembly/doorcontrol.dm
+++ b/code/modules/assembly/doorcontrol.dm
@@ -3,14 +3,42 @@
desc = "A small electronic device able to control a blast door remotely."
icon_state = "control"
attachable = TRUE
- var/id = null
- var/can_change_id = 0
+ /// Our ID. Make the first character ! if you want to obfuscate it as a mapper via randomization.
+ var/id
+ /// Can the ID be changed if used in hand?
+ var/can_change_id = FALSE
+ /// Show ID?
+ var/show_id = TRUE
+ /// Numerical ID or text?
+ var/id_is_number = FALSE
var/cooldown = FALSE //Door cooldowns
+/obj/item/assembly/Initialize(mapload)
+ if(mapload && id)
+ if(copytext(id, 1, 2) == "!")
+ id = SSmapping.get_obfuscated_id(id)
+ return ..()
+
/obj/item/assembly/control/examine(mob/user)
. = ..()
- if(id)
+ if(id && show_id)
. += "Its channel ID is '[id]'."
+ if(can_change_id)
+ . += "Use in hand to change ID."
+
+/obj/item/assembly/control/attack_self(mob/living/user)
+ . = ..()
+ if(.)
+ return
+ if(!can_change_id)
+ return
+ var/new_id
+ if(id_is_number)
+ new_id = input(user, "Set ID (number)", "Set ID", show_id? id : null) as number|null
+ else
+ new_id = input(user, "Set ID", "Set ID", show_id? id : null) as text|null
+ if(!isnull(new_id)) //0/"" is considered !, so check null instead of just !.
+ id = new_id
/obj/item/assembly/control/activate()
cooldown = TRUE
@@ -22,7 +50,6 @@
INVOKE_ASYNC(M, openclose ? /obj/machinery/door/poddoor.proc/open : /obj/machinery/door/poddoor.proc/close)
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
-
/obj/item/assembly/control/airlock
name = "airlock controller"
desc = "A small electronic device able to control an airlock remotely."
@@ -123,7 +150,6 @@
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
-
/obj/item/assembly/control/crematorium
name = "crematorium controller"
desc = "An evil-looking remote controller for a crematorium."
@@ -135,3 +161,14 @@
C.cremate(usr)
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
+
+/obj/item/assembly/control/electrochromatic
+ name = "electrochromatic window controller"
+ desc = "Toggles linked electrochromatic windows."
+ can_change_id = TRUE
+ /// Stores our status to prevent windows from desyncing.
+ var/on = FALSE
+
+/obj/item/assembly/control/electrochromatic/activate()
+ on = !on
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ELECTROCHROMATIC_WINDOW_TOGGLE, on, id)
diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm
index 86e11010bc..5d80b91087 100644
--- a/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm
+++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_electronics.dm
@@ -74,3 +74,11 @@
materials = list(/datum/material/glass = 20)
build_path = /obj/item/stock_parts/cell/emergency_light
category = list("initial", "Electronics")
+
+/datum/design/electrochromatic_control
+ name = "Electrochromatic Control Circuit"
+ id = "electrochromatic_control_circuit"
+ build_type = AUTOLATHE
+ materials = list(/datum/material/iron = 100, /datum/material/glass = 100)
+ build_path = /obj/item/assembly/control/electrochromatic
+ category = list("initial", "Electronics")
diff --git a/tgstation.dme b/tgstation.dme
index 848d149ae0..ceed653acc 100755
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -980,6 +980,7 @@
#include "code\game\objects\items\devices\dogborg_sleeper.dm"
#include "code\game\objects\items\devices\doorCharge.dm"
#include "code\game\objects\items\devices\electroadaptive_pseudocircuit.dm"
+#include "code\game\objects\items\devices\electrochromatic_kit.dm"
#include "code\game\objects\items\devices\flashlight.dm"
#include "code\game\objects\items\devices\forcefieldprojector.dm"
#include "code\game\objects\items\devices\geiger_counter.dm"
From a9d0ce45b9eb6188856492798015ca85af93e005 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:29:43 -0700
Subject: [PATCH 05/41] wow lotsa effort huh
---
code/game/objects/structures/window.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 07fd8142cb..6bc2ada140 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -52,7 +52,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
/obj/structure/window/examine(mob/user)
. = ..()
if(electrochromatic_status != NOT_ELECTROCHROMATIC)
- . += "The window has electrochromatic circuitry on it.")
+ . += "The window has electrochromatic circuitry on it."
if(reinf)
if(anchored && state == WINDOW_SCREWED_TO_FRAME)
. += "The window is screwed to the frame."
From e3b987879e3b9a2461e54b7bfcceda5eebaac8f7 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:30:18 -0700
Subject: [PATCH 06/41] wow lotsa effort huh
---
code/game/objects/structures/window.dm | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 6bc2ada140..54590134d2 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -210,7 +210,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
to_chat(user, "[src] is already in good condition!")
return
- if(!anchored && istype(I, /obj/item/electronics/electrochromatic_kit && user.a_intent == INTENT_HELP)
+ if(istype(I, /obj/item/electronics/electrochromatic_kit) && user.a_intent == INTENT_HELP)
var/obj/item/electronics/electrochromatic_kit/K = I
if(!user.temporarilyRemoveItemFromInventory(K))
to_chat(user, "[K] is stuck to your hand!")
@@ -218,7 +218,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
if(is_electrochromatic)
to_chat(user, "[src] is already electrochromatic!")
return
- if(!anchored)
+ if(anchored)
to_chat(user, "[src] must not be attached to the floor!")
return
if(!K.id)
@@ -346,7 +346,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
remove_electrochromatic()
electrochromatic_id = new_id
electrochromatic_status = ELECTROCHROMATIC_OFF
- LAZYINITLIST(GLOB.electrochromatic_window_lookup["[electrochromatic_id]")
+ LAZYINITLIST(GLOB.electrochromatic_window_lookup["[electrochromatic_id]"])
GLOB.electrochromatic_window_lookup[electrochromatic_id] |= src
/obj/structure/window/update_atom_colour()
From aeaf6ea102cd024fa2bfd08fa9c6152f618708c9 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:33:08 -0700
Subject: [PATCH 07/41] wow lotsa effort huh
---
code/game/objects/structures/window.dm | 6 +++++-
code/modules/assembly/doorcontrol.dm | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 54590134d2..1a5ebf17e0 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -352,7 +352,11 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
/obj/structure/window/update_atom_colour()
if((electrochromatic_status != ELECTROCHROMATIC_OFF) && (electrochromatic_status != ELECTROCHROMATIC_DIMMED))
return FALSE
- return ..()
+ . = ..()
+ if(color_hex2num(color) < 255)
+ set_opacity(255)
+ else
+ set_opacity(FALSE)
/obj/structure/window/proc/check_state(checked_state)
if(state == checked_state)
diff --git a/code/modules/assembly/doorcontrol.dm b/code/modules/assembly/doorcontrol.dm
index 1b9e63abaa..6016fd6453 100644
--- a/code/modules/assembly/doorcontrol.dm
+++ b/code/modules/assembly/doorcontrol.dm
@@ -34,7 +34,7 @@
return
var/new_id
if(id_is_number)
- new_id = input(user, "Set ID (number)", "Set ID", show_id? id : null) as number|null
+ new_id = input(user, "Set ID (number)", "Set ID", show_id? id : null) as num|null
else
new_id = input(user, "Set ID", "Set ID", show_id? id : null) as text|null
if(!isnull(new_id)) //0/"" is considered !, so check null instead of just !.
From 1b5e4b32cb8886facf8a342ad83406fa6e03719a Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:33:26 -0700
Subject: [PATCH 08/41] wow lotsa effort huh
---
code/modules/assembly/doorcontrol.dm | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/code/modules/assembly/doorcontrol.dm b/code/modules/assembly/doorcontrol.dm
index 6016fd6453..3c2d9fbce3 100644
--- a/code/modules/assembly/doorcontrol.dm
+++ b/code/modules/assembly/doorcontrol.dm
@@ -9,8 +9,6 @@
var/can_change_id = FALSE
/// Show ID?
var/show_id = TRUE
- /// Numerical ID or text?
- var/id_is_number = FALSE
var/cooldown = FALSE //Door cooldowns
/obj/item/assembly/Initialize(mapload)
@@ -33,10 +31,7 @@
if(!can_change_id)
return
var/new_id
- if(id_is_number)
- new_id = input(user, "Set ID (number)", "Set ID", show_id? id : null) as num|null
- else
- new_id = input(user, "Set ID", "Set ID", show_id? id : null) as text|null
+ new_id = input(user, "Set ID", "Set ID", show_id? id : null) as text|null
if(!isnull(new_id)) //0/"" is considered !, so check null instead of just !.
id = new_id
From bf7962d8f989ba0e1c5168a0b3f5c6bd2f6b7798 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:36:09 -0700
Subject: [PATCH 09/41] wow lotsa effort huh
---
code/controllers/subsystem/mapping.dm | 3 +--
code/datums/components/crafting/recipes/recipes_misc.dm | 2 +-
code/game/objects/structures/window.dm | 9 ++++-----
code/modules/assembly/doorcontrol.dm | 4 ++--
4 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index ffda2731b1..526e4b98e3 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -590,5 +590,4 @@ GLOBAL_LIST_EMPTY(the_station_areas)
var/key = "[original]%[id_type]"
if(random_generated_ids_by_original[key])
return random_generated_ids_by_original[key]
- random_generated_ids_by_original[key] = "[obfuscation_secret]%[obfuscation_next++]"
- return value
+ . = random_generated_ids_by_original[key] = "[obfuscation_secret]%[obfuscation_next_id++]"
diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm
index b26755d4ac..940e6c134f 100644
--- a/code/datums/components/crafting/recipes/recipes_misc.dm
+++ b/code/datums/components/crafting/recipes/recipes_misc.dm
@@ -236,7 +236,7 @@
/datum/crafting_recipe/electrochromatic_kit
name = "Electrochromatic Kit"
result = /obj/item/electronics/electrochromatic_kit
- reqs = list(/obj/item/stack/metal = 1,
+ reqs = list(/obj/item/stack/sheet/metal = 1,
/obj/item/stack/cable_coil = 1)
time = 5
subcategory = CAT_MISCELLANEOUS
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 1a5ebf17e0..143024bf97 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -8,12 +8,11 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
var/list/windows = GLOB.electrochromatic_window_lookup["[id]"]
if(!windows)
return
- var/obj/structure/window/W = i
+ var/obj/structure/window/W //define outside for performance because obviously this matters.
for(var/i in windows)
W = i
new_status? W.electrochromatic_dim() : W.electrochromatic_off()
-
/obj/structure/window
name = "window"
desc = "A window."
@@ -215,7 +214,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
if(!user.temporarilyRemoveItemFromInventory(K))
to_chat(user, "[K] is stuck to your hand!")
return
- if(is_electrochromatic)
+ if(electrochromatic_status != NOT_ELECTROCHROMATIC)
to_chat(user, "[src] is already electrochromatic!")
return
if(anchored)
@@ -292,7 +291,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
/obj/structure/window/proc/electrochromatic_off()
if(electrochromatic_status == ELECTROCHROMATIC_OFF)
return
- electrochromatic_on = FALSE
+ electrochromatic_status = ELECTROCHROMATIC_OFF
var/current = color
update_atom_colour()
var/newcolor = color
@@ -406,7 +405,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
for(var/obj/item/shard/debris in spawnDebris(drop_location()))
transfer_fingerprints_to(debris) // transfer fingerprints to shards only
if(electrochromatic_status != NOT_ELECTROCHROMATIC) //eh fine keep your kit.
- new /obj/item/electrochromatic_kit/K(drop_location())
+ new /obj/item/electronics/electrochromatic_kit/K(drop_location())
// Intentionally not setting the ID so you can't decon one to know all of the IDs.
qdel(src)
update_nearby_icons()
diff --git a/code/modules/assembly/doorcontrol.dm b/code/modules/assembly/doorcontrol.dm
index 3c2d9fbce3..41b063f43e 100644
--- a/code/modules/assembly/doorcontrol.dm
+++ b/code/modules/assembly/doorcontrol.dm
@@ -11,7 +11,7 @@
var/show_id = TRUE
var/cooldown = FALSE //Door cooldowns
-/obj/item/assembly/Initialize(mapload)
+/obj/item/assembly/control/Initialize(mapload)
if(mapload && id)
if(copytext(id, 1, 2) == "!")
id = SSmapping.get_obfuscated_id(id)
@@ -166,4 +166,4 @@
/obj/item/assembly/control/electrochromatic/activate()
on = !on
- SEND_GLOBAL_SIGNAL(COMSIG_GLOB_ELECTROCHROMATIC_WINDOW_TOGGLE, on, id)
+ do_electrochromatic_toggle(on, id)
From ff9f18bdbdbb0fb1bfb67a308cf2485f4447d2a4 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 03:38:41 -0700
Subject: [PATCH 10/41] wow lotsa effort huh
---
code/game/objects/structures/window.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 143024bf97..796db7a9c6 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -405,7 +405,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
for(var/obj/item/shard/debris in spawnDebris(drop_location()))
transfer_fingerprints_to(debris) // transfer fingerprints to shards only
if(electrochromatic_status != NOT_ELECTROCHROMATIC) //eh fine keep your kit.
- new /obj/item/electronics/electrochromatic_kit/K(drop_location())
+ new /obj/item/electronics/electrochromatic_kit(drop_location())
// Intentionally not setting the ID so you can't decon one to know all of the IDs.
qdel(src)
update_nearby_icons()
From 2e35a42f4356cc9795fe3925a25d97ec154b196a Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 04:10:38 -0700
Subject: [PATCH 11/41] wow lotsa effort huh
---
.../objects/items/devices/electrochromatic_kit.dm | 1 -
code/game/objects/structures/window.dm | 12 +++++++-----
code/modules/assembly/doorcontrol.dm | 2 --
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/code/game/objects/items/devices/electrochromatic_kit.dm b/code/game/objects/items/devices/electrochromatic_kit.dm
index aae886d397..d582eab00e 100644
--- a/code/game/objects/items/devices/electrochromatic_kit.dm
+++ b/code/game/objects/items/devices/electrochromatic_kit.dm
@@ -1,7 +1,6 @@
/obj/item/electronics/electrochromatic_kit
name = "electrochromatic kit"
desc = "A kit for upgrading a window into an electrochromatic one."
- icon = 'icons/obj/device.dmi'
/// Electrochromatic ID
var/id
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 796db7a9c6..a8c6dfb898 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -211,9 +211,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
if(istype(I, /obj/item/electronics/electrochromatic_kit) && user.a_intent == INTENT_HELP)
var/obj/item/electronics/electrochromatic_kit/K = I
- if(!user.temporarilyRemoveItemFromInventory(K))
- to_chat(user, "[K] is stuck to your hand!")
- return
if(electrochromatic_status != NOT_ELECTROCHROMATIC)
to_chat(user, "[src] is already electrochromatic!")
return
@@ -223,6 +220,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
if(!K.id)
to_chat(user, "[K] has no ID set!")
return
+ if(!user.temporarilyRemoveItemFromInventory(K))
+ to_chat(user, "[K] is stuck to your hand!")
+ return
user.visible_message("[user] upgrades [src] with [I].", "You upgrade [src] with [I].")
make_electrochromatic(K.id)
qdel(K)
@@ -341,8 +341,10 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
if(electrochromatic_id)
GLOB.electrochromatic_window_lookup[electrochromatic_id] += src
-/obj/structure/window/proc/make_electrochromatic(new_id)
+/obj/structure/window/proc/make_electrochromatic(new_id = electrochromatic_id)
remove_electrochromatic()
+ if(!new_id)
+ CRASH("Attempted to make electrochromatic with null ID.")
electrochromatic_id = new_id
electrochromatic_status = ELECTROCHROMATIC_OFF
LAZYINITLIST(GLOB.electrochromatic_window_lookup["[electrochromatic_id]"])
@@ -352,7 +354,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
if((electrochromatic_status != ELECTROCHROMATIC_OFF) && (electrochromatic_status != ELECTROCHROMATIC_DIMMED))
return FALSE
. = ..()
- if(color_hex2num(color) < 255)
+ if(color && (color_hex2num(color) < 255))
set_opacity(255)
else
set_opacity(FALSE)
diff --git a/code/modules/assembly/doorcontrol.dm b/code/modules/assembly/doorcontrol.dm
index 41b063f43e..32e262ce65 100644
--- a/code/modules/assembly/doorcontrol.dm
+++ b/code/modules/assembly/doorcontrol.dm
@@ -26,8 +26,6 @@
/obj/item/assembly/control/attack_self(mob/living/user)
. = ..()
- if(.)
- return
if(!can_change_id)
return
var/new_id
From f70490c61dce9205ae46979d0661191c3608e801 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 04:40:18 -0700
Subject: [PATCH 12/41] fixes
---
code/game/machinery/buttons.dm | 8 ++++++++
code/game/objects/structures/window.dm | 14 +++++++-------
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index ad3dd5d720..3a90707bbe 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -16,6 +16,9 @@
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0)
+ if(istext(id) && mapload)
+ if(copytext(id, 1, 2) == "!")
+ id = SSmapping.get_obfuscated_id(id)
. = ..()
if(built)
setDir(ndir)
@@ -260,6 +263,11 @@
req_access = list()
id = 1
+/obj/machinery/button/electrochromatic
+ name = "window dim control"
+ desc = "Controls linked electrochromatic windows"
+ device_type = /obj/item/assembly/control/electrochromatic
+
/obj/item/wallframe/button
name = "button frame"
desc = "Used for building buttons."
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index a8c6dfb898..e4d93ea8de 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -299,6 +299,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
animate(src, color = newcolor, time = 2)
/obj/structure/window/proc/remove_electrochromatic()
+ electrochromatic_off()
electrochromatic_status = NOT_ELECTROCHROMATIC
if(!electrochromatic_id)
return
@@ -308,14 +309,17 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
electrochromatic_id = null
/obj/structure/window/vv_edit_var(var_name, var_value)
- var/old_id
var/check_status
if(var_name == NAMEOF(src, electrochromatic_id))
- if((electrochromatic_status != NOT_ELECTROCHROMATIC) && electrochromatic_id)
- old_id = electrochromatic_id
+ if(electrochromatic_id && GLOB.electrochromatic_window_lookup["[electrochromatic_id]"])
+ GLOB.electrochromatic_window_lookup[electrochromatic_id] -= src
if(var_name == NAMEOF(src, electrochromatic_status))
check_status = TRUE
. = ..() //do this first incase it runtimes.
+ if(var_name == NAMEOF(src, electrochromatic_id))
+ if((electrochromatic_status != NOT_ELECTROCHROMATIC) && electrochromatic_id)
+ LAZYINITLIST(GLOB.electrochromatic_window_lookup[electrochromatic_id])
+ GLOB.electrochromatic_window_lookup[electrochromatic_id] += src
if(check_status)
if(electrochromatic_status == NOT_ELECTROCHROMATIC)
remove_electrochromatic()
@@ -336,10 +340,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
return
else
remove_electrochromatic()
- if(old_id)
- GLOB.electrochromatic_window_lookup[old_id] -= src
- if(electrochromatic_id)
- GLOB.electrochromatic_window_lookup[electrochromatic_id] += src
/obj/structure/window/proc/make_electrochromatic(new_id = electrochromatic_id)
remove_electrochromatic()
From 28da033111afe9857394579220c2f102462da8c0 Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Sun, 26 Apr 2020 17:37:27 -0700
Subject: [PATCH 13/41] fine
---
code/datums/components/crafting/recipes/recipes_misc.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm
index 940e6c134f..cd254943ea 100644
--- a/code/datums/components/crafting/recipes/recipes_misc.dm
+++ b/code/datums/components/crafting/recipes/recipes_misc.dm
@@ -239,7 +239,7 @@
reqs = list(/obj/item/stack/sheet/metal = 1,
/obj/item/stack/cable_coil = 1)
time = 5
- subcategory = CAT_MISCELLANEOUS
+ subcategory = CAT_TOOL
category = CAT_MISC
////////////
From 438a83b5c03a7e57c5d0e41d292738a495747049 Mon Sep 17 00:00:00 2001
From: ZeroMan
Date: Thu, 30 Apr 2020 17:56:07 -0400
Subject: [PATCH 14/41] a
---
code/modules/projectiles/ammunition/energy/special.dm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm
index 15e9b68912..994b0f7f01 100644
--- a/code/modules/projectiles/ammunition/energy/special.dm
+++ b/code/modules/projectiles/ammunition/energy/special.dm
@@ -4,8 +4,8 @@
fire_sound = 'sound/weapons/ionrifle.ogg'
/obj/item/ammo_casing/energy/ion/hos
- projectile_type = /obj/item/projectile/ion/weak
- e_cost = 300
+ projectile_type = /obj/item/projectile/ion
+ e_cost = 200
/obj/item/ammo_casing/energy/declone
projectile_type = /obj/item/projectile/energy/declone
From 42762c459e0891073672f70bc114ecf4b46fd78a Mon Sep 17 00:00:00 2001
From: Psody
Date: Fri, 1 May 2020 04:14:34 -0400
Subject: [PATCH 15/41] Lets actually use all the positions
---
code/modules/jobs/job_types/atmospheric_technician.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm
index 019e50799e..66861033fd 100644
--- a/code/modules/jobs/job_types/atmospheric_technician.dm
+++ b/code/modules/jobs/job_types/atmospheric_technician.dm
@@ -5,7 +5,7 @@
department_flag = ENGSEC
faction = "Station"
total_positions = 3
- spawn_positions = 2
+ spawn_positions = 3
supervisors = "the chief engineer"
selection_color = "#ff9b3d"
exp_requirements = 60
From 37d1c469eac2ab0a040e995f498cf2c769915c86 Mon Sep 17 00:00:00 2001
From: Sishen
Date: Fri, 1 May 2020 06:59:54 -0600
Subject: [PATCH 16/41] hnmhm cultplain??
---
code/modules/uplink/uplink_items/uplink_roles.dm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/code/modules/uplink/uplink_items/uplink_roles.dm b/code/modules/uplink/uplink_items/uplink_roles.dm
index 28479f8da7..da25cf5298 100644
--- a/code/modules/uplink/uplink_items/uplink_roles.dm
+++ b/code/modules/uplink/uplink_items/uplink_roles.dm
@@ -89,6 +89,7 @@
desc = "A reverse engineered clockwork slab. Is this really a good idea?."
item = /obj/item/clockwork/slab/traitor
cost = 20
+ player_minimum = 20
refundable = TRUE
restricted_roles = list("Chaplain")
@@ -97,6 +98,7 @@
desc = "A replica of a Nar'sian tome. This is probably a bad idea.."
item = /obj/item/tome/traitor
cost = 20
+ player_minimum = 20
refundable = TRUE
restricted_roles = list("Chaplain")
From a1f252d5588e255d12ff3224e7cad4a2f00c19ca Mon Sep 17 00:00:00 2001
From: Ghommie <42542238+Ghommie@users.noreply.github.com>
Date: Fri, 1 May 2020 19:48:27 +0200
Subject: [PATCH 17/41] Fixing several reported issues.
---
code/datums/elements/mob_holder.dm | 2 +-
code/game/objects/items/devices/multitool.dm | 5 ++---
.../sprite_accessories/_sprite_accessories.dm | 1 -
.../new_player/sprite_accessories/ears.dm | 17 +++++++++++------
.../mob/living/carbon/human/species.dm | 16 ----------------
.../mob/living/carbon/monkey/combat.dm | 8 +++-----
.../surgery/bodyparts/dismemberment.dm | 2 +-
icons/mob/blob.dmi | Bin 1294948 -> 1294952 bytes
icons/mob/mutant_bodyparts.dmi | Bin 33996 -> 33997 bytes
icons/obj/advancedtools.dmi | Bin 2446 -> 2474 bytes
icons/obj/items_cyborg.dmi | Bin 2344 -> 2461 bytes
modular_citadel/icons/mob/mam_ears.dmi | Bin 10613 -> 10605 bytes
12 files changed, 18 insertions(+), 33 deletions(-)
diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm
index a5c6e2725d..d770e0f30d 100644
--- a/code/datums/elements/mob_holder.dm
+++ b/code/datums/elements/mob_holder.dm
@@ -164,7 +164,7 @@
release()
/obj/item/clothing/head/mob_holder/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE)
- if(!ishuman(M)) //monkeys holding monkeys holding monkeys...
+ if(M == held_mob || !ishuman(M)) //monkeys holding monkeys holding monkeys...
return FALSE
return ..()
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 63092b5a13..4d0ed362fc 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -68,10 +68,9 @@
update_icon()
/obj/item/multitool/update_icon_state()
+ icon_state = initial(icon_state)
if(selected_io)
- icon_state = "multitool_red"
- else
- icon_state = "multitool"
+ icon_state += "_red"
/obj/item/multitool/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
index ab278b2e82..0b25132e00 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm
@@ -55,7 +55,6 @@
var/gender = NEUTER //Determines if the accessory will be skipped or included in random hair generations
var/gender_specific //Something that can be worn by either gender, but looks different on each
var/color_src = MUTCOLORS //Currently only used by mutantparts so don't worry about hair and stuff. This is the source that this accessory will get its color from. Default is MUTCOLOR, but can also be HAIR, FACEHAIR, EYECOLOR and 0 if none.
- var/hasinner //Decides if this sprite has an "inner" part, such as the fleshy parts on ears.
var/locked = FALSE //Is this part locked from roundstart selection? Used for parts that apply effects
var/dimension_x = 32
var/dimension_y = 32
diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
index c91bd633a5..3ba1e8b3b4 100644
--- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
+++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm
@@ -29,9 +29,10 @@
/datum/sprite_accessory/ears/human/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
- hasinner = 1
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
+ extra = TRUE
+ extra_color_src = NONE
/datum/sprite_accessory/ears/human/bigwolfdark
name = "Dark Big Wolf"
@@ -42,15 +43,17 @@
/datum/sprite_accessory/ears/human/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
- hasinner = 1
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
color_src = MATRIXED
+ extra = TRUE
+ extra_color_src = NONE
/datum/sprite_accessory/ears/cat
name = "Cat"
icon_state = "cat"
- hasinner = 1
color_src = HAIR
+ extra = TRUE
+ extra_color_src = NONE
/datum/sprite_accessory/ears/human/cow
name = "Cow"
@@ -196,7 +199,8 @@
/datum/sprite_accessory/mam_ears/bigwolfinner
name = "Big Wolf (ALT)"
icon_state = "bigwolfinner"
- hasinner = 1
+ extra = TRUE
+ extra_color_src = NONE
/datum/sprite_accessory/mam_ears/bigwolfdark
name = "Dark Big Wolf"
@@ -205,12 +209,13 @@
/datum/sprite_accessory/mam_ears/bigwolfinnerdark
name = "Dark Big Wolf (ALT)"
icon_state = "bigwolfinnerdark"
- hasinner = 1
+ extra = TRUE
+ extra_color_src = NONE
/datum/sprite_accessory/mam_ears/cat
name = "Cat"
icon_state = "cat"
- hasinner = 1
+ icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HAIR
/datum/sprite_accessory/mam_ears/catbig
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 683c3e18fd..e3a7b72f8b 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -909,22 +909,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
standing += accessory_overlay
- if(S.hasinner)
- var/mutable_appearance/inner_accessory_overlay = mutable_appearance(S.icon, layer = -layer)
- if(S.gender_specific)
- inner_accessory_overlay.icon_state = "[g]_[bodypart]inner_[S.icon_state]_[layertext]"
- else
- inner_accessory_overlay.icon_state = "m_[bodypart]inner_[S.icon_state]_[layertext]"
-
- if(S.center)
- inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y)
-
- if(OFFSET_MUTPARTS in H.dna.species.offset_features)
- inner_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1]
- inner_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2]
-
- standing += inner_accessory_overlay
-
if(S.extra) //apply the extra overlay, if there is one
var/mutable_appearance/extra_accessory_overlay = mutable_appearance(S.icon, layer = -layer)
if(S.gender_specific)
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
index a06d65ad4b..1b0856bfcd 100644
--- a/code/modules/mob/living/carbon/monkey/combat.dm
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -111,7 +111,7 @@
if(pickupTarget)
if(restrained() || blacklistItems[pickupTarget] || HAS_TRAIT(pickupTarget, TRAIT_NODROP))
pickupTarget = null
- else
+ else if(!isobj(loc) || istype(loc, /obj/item/clothing/head/mob_holder))
pickupTimer++
if(pickupTimer >= 4)
blacklistItems[pickupTarget] ++
@@ -126,10 +126,8 @@
pickupTarget = null
pickupTimer = 0
else if(ismob(pickupTarget.loc)) // in someones hand
- if(istype(pickupTarget, /obj/item/clothing/head/mob_holder/))
- var/obj/item/clothing/head/mob_holder/h = pickupTarget
- if(h && h.held_mob==src)
- return//dont let them pickpocket themselves
+ if(istype(pickupTarget, /obj/item/clothing/head/mob_holder))
+ return//dont let them pickpocket themselves or hold other monkys.
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE
diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm
index 66bca919c4..59cfcccde1 100644
--- a/code/modules/surgery/bodyparts/dismemberment.dm
+++ b/code/modules/surgery/bodyparts/dismemberment.dm
@@ -295,6 +295,7 @@
O.Insert(C)
update_bodypart_damage_state()
+ update_disabled()
C.updatehealth()
C.update_body()
@@ -302,7 +303,6 @@
C.update_damage_overlays()
C.update_mobility()
-
/obj/item/bodypart/head/attach_limb(mob/living/carbon/C, special)
//Transfer some head appearance vars over
if(brain)
diff --git a/icons/mob/blob.dmi b/icons/mob/blob.dmi
index 6964160c042f7f5d258de17430c8614deb9f38d5..a197581533c055a36e286bd090c1f9b6eca3f4f8 100644
GIT binary patch
delta 536
zcmaFT;{T$>e}YQ=rmB#L5|`BC)N?^esUFcL`~J#Z>6n^T-khn>So7yu_Dp-{A5nGd%{D}=Kg6sR8^o&V
z^EgmK#ygK?iGk-KhlEIu;<^iMk}V=^(Vn+`t}ih#-m#uN@qqWzdd1dEi9Z_K+<7&7
z-hVayI6LpoCEvphi&NA+5^cKFF6zvRn8;#ue0vyA`@|<=i9)4%+6w8_VG8fLm%Dau
zN{_lPR~+=h;<1=^r`7bMt2(MT{Hgi7;m!oBuUmavXGu*>j^E>S>Er)sUX{SVGmb?n
zzWni{`S+sfF^^{VJYQ0Caa~A#(L(J~7_r8g~D?ex%^ydd=^0f5bwMN=?4nRWaH6
z)Vsx3lNO)uN`L#B_1@~k@oNiG+)AWp-v0mp+_BZRMe{8KHXfVfz5Mo<=VuRT%sa32
zdfE+rw~u!!t)AB`XVyAt6E&s&`Q|
z+Fc6&ZXk5$(($tQ*Pbzb|8-)|w)abKdz~t;TXjS|Bi+_+B~zo%F0PHLXFVSlzZ94@
zn^ou9>JQ?I!6)RFOZctg2mcM7az0ZdKI}_3L
z$(NLJ>xP{1lmv^%V%lG-rXSOq7`fq1&EE??3-|PG_2o1*Giu&g;odm?fBsd$j;q;H
z_W$0xe3`>JgJbT(Ev~bJPPXXPPxO8IYhJR{-}Rk|i|m8)q-wY}E$Q{r>RfY@C-wWq
ztc~|-f3E)al`a43L-{a?fTO>A*L?kdf8)oz{xfNOQ?>+d|Mk-R@6Rm)KVDB=e%I-*
z>x1>Z%ZpE!+cb+@S>$@N+`oF6>+D5OHDCIdB`!u%&L`{**Tc6r@8M^*mol<
zp);4Rm*rnelj-{9w02wmQg7BYb?eX!;Vs+c*jF_$i!O7@@id-dpfh*!+eBxx-*bO+
zE7+cp`(XS(y7@k1`+Y_bW&&bnAZ7t#Rv=~rVs;?r0Afxc<^p1FAm#yLULfWJVtybN
Q0AfKP7TSKFQMmH}0024sN&o-=
diff --git a/icons/mob/mutant_bodyparts.dmi b/icons/mob/mutant_bodyparts.dmi
index 2f7f9b5be91f464a907cc24e72581d74d4359190..9c531a3df26d0fa797558d558da4e76f2a41ce68 100644
GIT binary patch
delta 507
zcmVne!p0X
z@?nwxMjy1Zq7b+5Kjhg?*HMW=e7wmsg<7iEe+dyHib7m9RRnFS&^Q-WbvOUESe93L
zR%;(bA#U?*|k9NtDwNQ)tB-+A)B6m@UF8piwFvQYqV66+^rLko#7bY5lHdTd##+ep$f`*
zY9$9kH?2VyvhKV=>U?^{L&JI=tTgBow`k+FG0cje7)DxPZ`Vi@aoxkp>&2
z|1q49ETM5$vR%em$=8f3>ltL};IRX?YJwla%GLX-0l(E&hNpc*QEbM4qc5#yyp@5T
zSXXGwew>w#(kBr?n;l5XiRE*i)o5TZ3Nd^4;*)0{ciPqi;Vlfdi}|t?<-;QX3+Fa-JeviJgtI;Zj)J-p{VxCj
delta 506
zcmVn{;*hz
z@^O*>kr<43q7XM9KjqoZ)KQBD8%d>bpPw;@;8;Kqfru>q65Sd*)bwJLKIrFm4Vy39-@g>C}At{
z-*dBbv4itntbzt?tK0GiA)B6mK;OBVMFb7lTBCF%ck2XXXE?@p1X6tTUTcpoR6%>B
zR&pRr(^|rDJwB?i#BMiWmf#mF#38x;HiVe1%%c($xG%KX=Eem
ze+(xiOK81QY?t*;@in8$dI4EFcq=U?A7`bb^hrc8b_a@bV)>S5wY0Dog_wPK^~p1oJLBqs@E3N?d!iFgK?%Z7lsw^N
zl_2~?$rDa%3Bo5$p8js^Kq=!CZEKAw^9{k^GDzu}u$aO9nMg5l3IAan!<+p5j={a3
zNRhAv`fDlyL$wC_P38qm;9WAu5uBuqa}rt9VFsl9zP>SoOR+BGa5)rxbZck>>$cqA
wuCzxtBloChYDqq^9RWOt>Wpo?JNNvxm@i9FJ}&aVKeuw#pe3hivp)ikf+Upsf&c&j
diff --git a/icons/obj/advancedtools.dmi b/icons/obj/advancedtools.dmi
index 974202dd58fd66882c1e24c2fbd2c0fc85419d44..19240a60eb4e8464588331abef7ee46309dd2264 100644
GIT binary patch
delta 2464
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
Bh|~Z8
diff --git a/icons/obj/items_cyborg.dmi b/icons/obj/items_cyborg.dmi
index a4bd75f7e51517d6e97e634cf7ee61b32a3eb9f7..769d5492c64ad8a7027401a2cef929e02d8f77e4 100644
GIT binary patch
delta 2239
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
Date: Fri, 1 May 2020 19:50:53 +0200
Subject: [PATCH 18/41] leftovers.
---
modular_citadel/icons/mob/mam_ears.dmi | Bin 10605 -> 10453 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/modular_citadel/icons/mob/mam_ears.dmi b/modular_citadel/icons/mob/mam_ears.dmi
index 55d41e33f59f31d80b345892e629602bf6668fe2..a3f09819f25890acbcc3d9dc2bff60b154efed80 100644
GIT binary patch
literal 10453
zcmch72UJsQw{0j=4j@F&QHoR*6s1WMDWO`ZN7RFq5ESW6gwR7!RHD+(FM@!8iiija
zCG-FRMG+Aq1`wQm
z%j6=%2^-O({989MOY+^b38=VweawTzA9$RL*?D-d5lj
z)s9C+VcR^>P8&6v6YixF*X^S=rUPnai=5hz_s>*cAH>qx1_;!HeTCniNf|!=*cv%5
zo8(EeFvpY-9^Qk?I|X4L+Ep6dG$?D?(ujtRr=s>>`*5Sp!JhUVpB?uhH(K8z@PcvF
z{&!`_as%ATVX4bm#^6z_u#p$Aw4bX(D)hwQnhn@7LyXO@CBip?-0#AkKUWv5lXNe#
zJF*{SGUXZbb`jiv`?jO1$=Q>tCL-mJX>zWPAQJ4_-GUS8BkbH-Ch^ow*G;RVBxp>s
z*sZr#6+vFs!R#Y7m;MyT89(h*&~z<5gtb(>b=QAvKQsij<@A*NrZisU^~a&P&nNXnD<3c+P%i^L~n{>
z#pO@~adr3-q5+
zdMZidc5Y=uY2a1e@Bz!EC`Gw-eDd~Agrpx{!CvvEr$T>9k^&f#wawj`yEsjSUKW-}
zI>q&<&kRQ>JkqI6at*2F(-255o8BVS`EsV_%UOXRM}lp4;=4v6E@WER;Q;y6qj#g}
zaUT#Ol_c7p&3HbaPKJ?75G=|V9Ku=DSG}8oRx5pZdk&!5IFpoE451rPa9U9-VjQYZoZE43W-;W<^7m5
z@4r1)--GRV&9IQZLrG4T))4|ua=W%XVW}|kIDCQ!=?IwIv{>RJxl1^dhRZCTrs47#
zhUaKk>|1(R*IPY#YS8gLD}E(N!NdG!o>UkT*w$zZ2!qbgEvJA$3&JuWl_HQJ=+%Bp
zP)f9*7%1BrBmnv*t^%?=v%5;;U$Lk)L-12p*^shBMIpx5_-xtG;2lC7r4<)=Y&rHA
z{Ki*4dxnYE%h@!|Im3D)2b|IPsK6_8oSrGMHdGNe=uE*rNZeh1*&Z>HFczQ)21_Sm
z{+S9=9R7IipyVeFVznK8o&>jj_F*SE`G6rNs&8TZ{cvG)xR~LMmdp>!o0HMz<1Lve
zqDNmFyu2Zo!`haP3yv7oE{fb_sIX5`?j8`3_BZQFrg^qkgs#PFMC{=sJk_|W`mGk^|
z|7HH8cRj82w7_Y(Y~{mKkMmz~FQ8|7ik@_z!e^{?y~}9oc`Tbpz-6vyFiKq%Q<*&f@TQvtg?D@%Hj&@8dP{a)-m)8?pB2&9}5$
zq6VVW7mg;>vi*3pV)QjJZkU)MsOfM@
z=Y4$jJo^~RHrd2O7Ro=jxd!C@H7&7
z0(F1^xs?WvJix`zVBf6jE)nMVRXOZne@dl{^{Hn`hRE!Q+@hr6Fpg+#8#gt)aQQB%
z?i}Xu)Z`twbUA%tVzJZo?rqumiC(+zIsHD1676Nz{o0x3Fefp&Jl8@$27`4E*de)n
zCLv~qaH5z7T_zYvP9kVSH(~x(^JIcf9%T7lA?kFnIppcK5^*D |