diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 1b1913ef26..0e2ebb0c62 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -37410,18 +37410,12 @@ /obj/machinery/light{ dir = 1 }, -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/pen, +/obj/machinery/computer/atmos_alert, /turf/open/floor/plasteel/caution{ dir = 1 }, /area/engine/atmos) "byT" = ( -/obj/machinery/computer/atmos_alert, /obj/structure/sign/map/left{ desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; icon_state = "map-left-MS"; @@ -37431,6 +37425,7 @@ c_tag = "Atmospherics - Control Room"; network = list("SS13") }, +/obj/machinery/computer/station_alert, /turf/open/floor/plasteel/caution{ dir = 1 }, @@ -37441,7 +37436,6 @@ icon_state = "map-right-MS"; pixel_y = 32 }, -/obj/machinery/computer/station_alert, /turf/open/floor/plasteel/caution{ dir = 1 }, @@ -38222,13 +38216,12 @@ /turf/open/floor/plating, /area/engine/atmos) "bAB" = ( -/obj/item/clothing/mask/breath{ - pixel_x = 4 - }, -/obj/item/tank/internals/emergency_oxygen{ - pixel_x = -8 - }, /obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -3; + pixel_y = 7 + }, +/obj/item/pen, /turf/open/floor/plasteel/caution{ dir = 8 }, diff --git a/code/citadel/cit_guns.dm b/code/citadel/cit_guns.dm index bf8d034148..8a90e75a6b 100644 --- a/code/citadel/cit_guns.dm +++ b/code/citadel/cit_guns.dm @@ -111,7 +111,7 @@ w_class = WEIGHT_CLASS_BULKY can_suppress = 0 burst_size = 1 - fire_delay = 20 + fire_delay = 40 select = 0 actions_types = list() casing_ejector = 0 @@ -140,14 +140,14 @@ /datum/supply_pack/security/armory/spinfusor name = "Stormhammer Spinfusor Crate" - cost = 7000 + cost = 14000 contains = list(/obj/item/gun/ballistic/automatic/spinfusor, /obj/item/gun/ballistic/automatic/spinfusor) crate_name = "spinfusor crate" /datum/supply_pack/security/armory/spinfusorammo name = "Spinfusor Disk Crate" - cost = 4000 + cost = 7000 contains = list(/obj/item/ammo_box/aspinfusor, /obj/item/ammo_box/aspinfusor, /obj/item/ammo_box/aspinfusor, @@ -210,7 +210,7 @@ /obj/item/projectile/bullet/mags icon = 'icons/obj/guns/cit_guns.dmi' icon_state = "magjectile" - damage = 25 + damage = 15 armour_penetration = 10 light_range = 2 light_color = LIGHT_COLOR_RED @@ -218,9 +218,9 @@ /obj/item/projectile/bullet/nlmags //non-lethal boolets icon = 'icons/obj/guns/cit_guns.dmi' icon_state = "magjectile-nl" - damage = 2 - knockdown = 15 - stamina = 50 + damage = 1 + knockdown = 0 + stamina = 25 armour_penetration = -10 light_range = 2 light_color = LIGHT_COLOR_BLUE @@ -378,7 +378,7 @@ /obj/item/projectile/bullet/magrifle icon = 'icons/obj/guns/cit_guns.dmi' icon_state = "magjectile-large" - damage = 30 + damage = 25 armour_penetration = 25 light_range = 3 light_color = LIGHT_COLOR_RED @@ -386,10 +386,10 @@ /obj/item/projectile/bullet/nlmagrifle //non-lethal boolets icon = 'icons/obj/guns/cit_guns.dmi' icon_state = "magjectile-large-nl" - damage = 5 - knockdown = 30 - stamina = 75 - armour_penetration = 0 + damage = 2 + knockdown = 0 + stamina = 30 + armour_penetration = -10 light_range = 3 light_color = LIGHT_COLOR_BLUE @@ -443,7 +443,7 @@ can_suppress = 0 burst_size = 3 fire_delay = 2 - spread = 15 + spread = 30 recoil = 1 casing_ejector = 0 @@ -719,8 +719,8 @@ obj/item/projectile/bullet/c10mm/soporific if((blocked != 100) && isliving(target)) var/mob/living/L = target L.blur_eyes(6) - if(L.staminaloss >= 60) - L.Sleeping(250) + if(L.getStaminaLoss() >= 60) + L.Sleeping(300) else L.adjustStaminaLoss(25) return 1 @@ -753,7 +753,7 @@ obj/item/projectile/bullet/c10mm/soporific /obj/item/projectile/bullet/cflechettes //shreds flesh and forces bleeding name = "flechette (serrated)" - damage = 8 + damage = 15 dismemberment = 10 armour_penetration = -80 @@ -921,3 +921,294 @@ obj/item/projectile/bullet/c10mm/soporific materials = list(MAT_METAL = 7500, MAT_GLASS = 1000) build_path = /obj/item/gun/energy/laser/practice/raygun category = list("hacked", "Misc") + +/*///////////////////////////////////////////////////////////////////////////////////////////// + The Recolourable Gun +*////////////////////////////////////////////////////////////////////////////////////////////// + +/obj/item/gun/ballistic/automatic/pistol/p37 + name = "\improper CX Mk.37P" + desc = "A modern reimagining of an old legendary gun, the Mk.37 is a handgun with a toggle-locking mechanism manufactured by CX Armories. \ + This model is coated with a special polychromic material. \ + Has a small warning on the receiver that boldly states 'WARNING: WILL DETONATE UPON UNAUTHORIZED USE'. \ + Uses 9mm bullets loaded into proprietary magazines." + icon = 'icons/obj/guns/cit_guns.dmi' + icon_state = "p37" + w_class = WEIGHT_CLASS_NORMAL + spawnwithmagazine = FALSE + mag_type = /obj/item/ammo_box/magazine/m9mm/p37 + can_suppress = FALSE + pin = /obj/item/device/firing_pin/dna/dredd //goes boom if whoever isn't DNA locked to it tries to use it + actions_types = list(/datum/action/item_action/pick_color) + + var/frame_color = "#808080" //RGB + var/receiver_color = "#808080" + var/body_color = "#0098FF" + var/barrel_color = "#808080" + var/tip_color = "#808080" + var/arm_color = "#808080" + var/grip_color = "#00FFCB" //Does not actually colour the grip, just the lights surrounding it + var/energy_color = "#00FFCB" + +///Defining all the colourable bits and displaying them/// + +/obj/item/gun/ballistic/automatic/pistol/p37/update_icon() + var/mutable_appearance/frame_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_frame") + var/mutable_appearance/receiver_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_receiver") + var/mutable_appearance/body_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_body") + var/mutable_appearance/barrel_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_barrel") + var/mutable_appearance/tip_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_tip") + var/mutable_appearance/grip_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_grip") + var/mutable_appearance/energy_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_light") + var/mutable_appearance/arm_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_arm") + var/mutable_appearance/arm_overlay_e = mutable_appearance('icons/obj/guns/cit_guns.dmi', "p37_arm-e") + + if(frame_color) + frame_overlay.color = frame_color + if(receiver_color) + receiver_overlay.color = receiver_color + if(body_color) + body_overlay.color = body_color + if(barrel_color) + barrel_overlay.color = barrel_color + if(tip_color) + tip_overlay.color = tip_color + if(grip_color) + grip_overlay.color = grip_color + if(energy_color) + energy_overlay.color = energy_color + if(arm_color) + arm_overlay.color = arm_color + if(arm_color) + arm_overlay_e.color = arm_color + + cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other + + add_overlay(frame_overlay) + add_overlay(receiver_overlay) + add_overlay(body_overlay) + add_overlay(barrel_overlay) + add_overlay(tip_overlay) + add_overlay(grip_overlay) + add_overlay(energy_overlay) + + if(magazine) //does not need a cut_overlays proc call here because it's already called further up + add_overlay("p37_mag") + + if(chambered) + cut_overlay(arm_overlay_e) + add_overlay(arm_overlay) + else + cut_overlay(arm_overlay) + add_overlay(arm_overlay_e) + +///letting you actually recolor things/// + +/obj/item/gun/ballistic/automatic/pistol/p37/ui_action_click(mob/user, var/datum/action/A) + if(istype(A, /datum/action/item_action/pick_color)) + + var/choice = input(user,"Mk.37P polychrome options", "Gun Recolor") in list("Frame Color","Receiver Color","Body Color", + "Barrel Color", "Barrel Tip Color", "Grip Light Color", + "Light Color", "Arm Color", "*CANCEL*") + + switch(choice) + + if("Frame Color") + var/frame_color_input = input(usr,"Choose Frame Color") as color|null + if(frame_color_input) + frame_color = sanitize_hexcolor(frame_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Receiver Color") + var/receiver_color_input = input(usr,"Choose Receiver Color") as color|null + if(receiver_color_input) + receiver_color = sanitize_hexcolor(receiver_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Body Color") + var/body_color_input = input(usr,"Choose Body Color") as color|null + if(body_color_input) + body_color = sanitize_hexcolor(body_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Barrel Color") + var/barrel_color_input = input(usr,"Choose Barrel Color") as color|null + if(barrel_color_input) + barrel_color = sanitize_hexcolor(barrel_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Barrel Tip Color") + var/tip_color_input = input(usr,"Choose Barrel Tip Color") as color|null + if(tip_color_input) + tip_color = sanitize_hexcolor(tip_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Grip Light Color") + var/grip_color_input = input(usr,"Choose Grip Light Color") as color|null + if(grip_color_input) + grip_color = sanitize_hexcolor(grip_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Light Color") + var/energy_color_input = input(usr,"Choose Light Color") as color|null + if(energy_color_input) + energy_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + + if("Arm Color") + var/arm_color_input = input(usr,"Choose Arm Color") as color|null + if(arm_color_input) + arm_color = sanitize_hexcolor(arm_color_input, desired_format=6, include_crunch=1) + update_icon() + + else + ..() + +///boolets/// + +/obj/item/projectile/bullet/c9mm/frangible + name = "9mm frangible bullet" + damage = 15 + stamina = 0 + armour_penetration = -25 + +/obj/item/projectile/bullet/c9mm/rubber + name = "9mm rubber bullet" + damage = 2 + stamina = 25 + knockdown = 0 + +/obj/item/ammo_casing/c9mm/frangible + name = "9mm frangible bullet casing" + desc = "A 9mm frangible bullet casing." + projectile_type = /obj/item/projectile/bullet/c9mm/frangible + +/obj/item/ammo_casing/c9mm/rubber + name = "9mm rubber bullet casing" + desc = "A 9mm rubber bullet casing." + projectile_type = /obj/item/projectile/bullet/c9mm/rubber + +/obj/item/ammo_box/magazine/m9mm/p37 + name = "\improper P37 magazine (9mm frangible)" + desc = "A gun magazine. Loaded with plastic composite rounds which fragment upon impact to minimize collateral damage." + icon = 'icons/obj/guns/cit_guns.dmi' + icon_state = "11mm" //topkek + ammo_type = /obj/item/ammo_casing/c9mm/frangible + caliber = "9mm" + max_ammo = 11 + multiple_sprites = 1 + +/obj/item/ammo_box/magazine/m9mm/p37/fmj + name = "\improper P37 magazine (9mm)" + ammo_type = /obj/item/ammo_casing/c9mm + desc = "A gun magazine. Loaded with conventional full metal jacket rounds." + +/obj/item/ammo_box/magazine/m9mm/p37/rubber + name = "\improper P37 magazine (9mm Non-Lethal Rubbershot)" + ammo_type = /obj/item/ammo_casing/c9mm/rubber + desc = "A gun magazine. Loaded with less-than-lethal rubber bullets." + +/obj/item/ammo_box/c9mm/frangible + name = "ammo box (9mm frangible)" + ammo_type = /obj/item/ammo_casing/c9mm/frangible + +/obj/item/ammo_box/c9mm/rubber + name = "ammo box (9mm non-lethal rubbershot)" + ammo_type = /obj/item/ammo_casing/c9mm/rubber + +/datum/design/c9mmfrag + name = "Box of 9mm Frangible Bullets" + id = "9mm_frag" + build_type = AUTOLATHE + materials = list(MAT_METAL = 30000) + build_path = /obj/item/ammo_box/c9mm/frangible + category = list("initial", "Security") + +/datum/design/c9mmrubber + name = "Box of 9mm Rubber Bullets" + id = "9mm_rubber" + build_type = AUTOLATHE + materials = list(MAT_METAL = 30000) + build_path = /obj/item/ammo_box/c9mm/rubber + category = list("initial", "Security") + + +///Security Variant/// + +/obj/item/gun/ballistic/automatic/pistol/p37/sec + name = "\improper CX Mk.37S" + desc = "A modern reimagining of an old legendary gun, the Mk.37 is a handgun with a toggle-locking mechanism manufactured by CX Armories. Uses 9mm bullets loaded into proprietary magazines." + spawnwithmagazine = FALSE + pin = /obj/item/device/firing_pin/implant/mindshield + actions_types = list() //so you can't recolor it + + frame_color = "#808080" //RGB + receiver_color = "#808080" + body_color = "#282828" + barrel_color = "#808080" + tip_color = "#808080" + arm_color = "#800000" + grip_color = "#FFFF00" //Does not actually colour the grip, just the lights surrounding it + energy_color = "#FFFF00" + +///Foam Variant because WE NEED MEMES/// + +/obj/item/gun/ballistic/automatic/pistol/p37/foam + name = "\improper Foam Force Mk.37F" + desc = "A licensed foam-firing reproduction of a handgun with a toggle-locking mechanism manufactured by CX Armories. This model is coated with a special polychromic material. Uses standard foam pistol magazines." + icon_state = "p37_foam" + spawnwithmagazine = TRUE + mag_type = /obj/item/ammo_box/magazine/toy/pistol + can_suppress = FALSE + actions_types = list(/datum/action/item_action/pick_color) + +/datum/design/foam_p37 + name = "Foam Force Mk.37F" + id = "foam_p37" + build_type = AUTOLATHE + materials = list(MAT_METAL = 15000, MAT_GLASS = 10000) + build_path = /obj/item/gun/ballistic/automatic/pistol/p37/foam + category = list("hacked", "Misc") + + +/*///////////////////////////////////////////////////////////////////////////////////////////// + The Recolourable Energy Gun +*////////////////////////////////////////////////////////////////////////////////////////////// + +obj/item/gun/energy/e_gun/cx + name = "\improper CX Model D Energy Gun" + desc = "An overpriced hybrid energy gun with two settings: disable, and kill. Manufactured by CX Armories. Has a polychromic coating." + icon = 'icons/obj/guns/cit_guns.dmi' + icon_state = "cxe" + lefthand_file = 'icons/mob/citadel/guns_lefthand.dmi' + righthand_file = 'icons/mob/citadel/guns_righthand.dmi' + ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser) + origin_tech = "combat=4;magnets=3" + flight_x_offset = 15 + flight_y_offset = 10 + actions_types = list(/datum/action/item_action/pick_color) + var/body_color = "#252528" + +obj/item/gun/energy/e_gun/cx/update_icon() + ..() + var/mutable_appearance/body_overlay = mutable_appearance('icons/obj/guns/cit_guns.dmi', "cxegun_body") + if(body_color) + body_overlay.color = body_color + add_overlay(body_overlay) + +obj/item/gun/energy/e_gun/cx/ui_action_click(mob/user, var/datum/action/A) + if(istype(A, /datum/action/item_action/pick_color)) + if(alert("Are you sure you want to repaint your gun?", "Confirm Repaint", "Yes", "No") == "Yes") + var/body_color_input = input(usr,"Choose Body Color") as color|null + if(body_color_input) + body_color = sanitize_hexcolor(body_color_input, desired_format=6, include_crunch=1) + update_icon() + else + ..() + +obj/item/gun/energy/e_gun/cx/worn_overlays(isinhands, icon_file) + . = ..() + if(isinhands) + var/mutable_appearance/body_inhand = mutable_appearance(icon_file, "cxe_body") + body_inhand.color = body_color + . += body_inhand \ No newline at end of file diff --git a/code/datums/components/README.md b/code/datums/components/README.md index 8d37e15de3..eeb6615a63 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -26,7 +26,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo ### Defines -1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. +1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. ### Vars @@ -42,12 +42,13 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo * `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it 1. `/datum/component/var/dupe_type` (protected, type) * Definition of a duplicate component type - * `null` means exact match on `type` + * `null` means exact match on `type` (default) * Any other type means that and all subtypes 1. `/datum/component/var/list/signal_procs` (private) * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum recieves that signal 1. `/datum/component/var/datum/parent` (protected, read-only) * The datum this component belongs to + * Never `null` in child procs ### Procs @@ -72,7 +73,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo * Will only be called if a component's callback returns `TRUE` 1. `/datum/proc/TakeComponent(datum/component/C)` (public, final) * Properly transfers ownership of a component from one datum to another - * Singals `COMSIG_COMPONENT_REMOVING` on the parent + * Signals `COMSIG_COMPONENT_REMOVING` on the parent * Called on the datum you want to own the component with another datum's component 1. `/datum/proc/SendSignal(signal, ...)` (public, final) * Call to send a signal to the components of the target datum @@ -96,10 +97,13 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo 1. `/datum/component/proc/AfterComponentActivated()` (abstract, async) * Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called 1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep) - * Called before the new `parent` is assigned in `TakeComponent()`, after the remove signal, before the added signal + * Called before `new_parent` is assigned to `parent` in `TakeComponent()` * Allows the component to react to ownership transfers -1. `/datum/component/proc/_RemoveNoSignal()` (private, final) - * Internal, clears the parent var and removes the component from the parents component list +1. `/datum/component/proc/_RemoveFromParent()` (private, final) + * Clears `parent` and removes the component from it's component list +1. `/datum/component/proc/_CheckDupesAndJoinParent` (private, final) + * Tries to add the component to it's `parent`s `datum_components` list + * Properly handles duplicate situations based on the `dupe_mode` var 1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz) * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments * Makes a component listen for the specified `signal` on it's `parent` datum. diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 9978b01955..4e187a6a08 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -13,28 +13,37 @@ parent = null qdel(src) return + + _CheckDupesAndJoinParent(P) +/datum/component/proc/_CheckDupesAndJoinParent() + var/datum/P = parent var/dm = dupe_mode + + var/datum/component/old if(dm != COMPONENT_DUPE_ALLOWED) var/dt = dupe_type - var/datum/component/old if(!dt) old = P.GetExactComponent(type) else old = P.GetComponent(dt) if(old) + //One or the other has to die switch(dm) if(COMPONENT_DUPE_UNIQUE) old.InheritComponent(src, TRUE) - parent = null //prevent COMPONENT_REMOVING signal + parent = null //prevent COMPONENT_REMOVING signal, no _RemoveFromParent because we aren't in their list yet qdel(src) return if(COMPONENT_DUPE_HIGHLANDER) InheritComponent(old, FALSE) + old._RemoveFromParent() qdel(old) - - //let the others know - P.SendSignal(COMSIG_COMPONENT_ADDED, src) + + //provided we didn't eat someone + if(!old) + //let the others know + P.SendSignal(COMSIG_COMPONENT_ADDED, src) //lazy init the parent's dc list var/list/dc = P.datum_components @@ -74,29 +83,28 @@ enabled = FALSE var/datum/P = parent if(P) - _RemoveNoSignal() + _RemoveFromParent() P.SendSignal(COMSIG_COMPONENT_REMOVING, src) LAZYCLEARLIST(signal_procs) return ..() -/datum/component/proc/_RemoveNoSignal() +/datum/component/proc/_RemoveFromParent() var/datum/P = parent - if(P) - var/list/dc = P.datum_components - var/our_type = type - for(var/I in _GetInverseTypeList(our_type)) - var/list/components_of_type = dc[I] - if(islist(components_of_type)) // - var/list/subtracted = components_of_type - src - if(subtracted.len == 1) //only 1 guy left - dc[I] = subtracted[1] //make him special - else - dc[I] = subtracted - else //just us - dc -= I - if(!dc.len) - P.datum_components = null - parent = null + var/list/dc = P.datum_components + var/our_type = type + for(var/I in _GetInverseTypeList(our_type)) + var/list/components_of_type = dc[I] + if(islist(components_of_type)) // + var/list/subtracted = components_of_type - src + if(subtracted.len == 1) //only 1 guy left + dc[I] = subtracted[1] //make him special + else + dc[I] = subtracted + else //just us + dc -= I + if(!dc.len) + P.datum_components = null + parent = null /datum/component/proc/RegisterSignal(sig_type_or_types, proc_on_self, override = FALSE) if(QDELETED(src)) @@ -201,7 +209,7 @@ var/nt = new_type args[1] = src var/datum/component/C = new nt(arglist(args)) - return QDELING(C) ? GetComponent(new_type) : C + return QDELING(C) ? GetExactComponent(new_type) : C /datum/proc/LoadComponent(component_type, ...) . = GetComponent(component_type) @@ -213,13 +221,15 @@ return var/datum/helicopter = C.parent if(helicopter == src) - //wat + //if we're taking to the same thing no need for anything return - C._RemoveNoSignal() + if(C.OnTransfer(src) == COMPONENT_INCOMPATIBLE) + qdel(C) + return + C._RemoveFromParent() helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C) - C.OnTransfer(src) C.parent = src - SendSignal(COMSIG_COMPONENT_ADDED, C) + C._CheckDupesAndJoinParent() /datum/proc/TransferComponents(datum/target) var/list/dc = datum_components diff --git a/code/datums/datum.dm b/code/datums/datum.dm index cd589fd8c3..f7b15035d1 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -27,11 +27,11 @@ if(islist(all_components)) for(var/I in all_components) var/datum/component/C = I - C._RemoveNoSignal() + C._RemoveFromParent() qdel(C) else var/datum/component/C = all_components - C._RemoveNoSignal() + C._RemoveFromParent() qdel(C) dc.Cut() return QDEL_HINT_QUEUE diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm index d8b5210bc5..885407ef90 100644 --- a/code/datums/map_config.dm +++ b/code/datums/map_config.dm @@ -13,7 +13,6 @@ //Order matters here. var/list/transition_config = list(CENTCOM = SELFLOOPING, - CITY_OF_COGS = SELFLOOPING, MAIN_STATION = CROSSLINKED, EMPTY_AREA_1 = CROSSLINKED, EMPTY_AREA_2 = CROSSLINKED, @@ -93,7 +92,7 @@ return var/tc = json["transition_config"] - if(tc != "default") + if(tc != null && tc != "default") if(!islist(tc)) log_world("transition_config is not a list!") return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 3690de2c04..7d70940512 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1039,7 +1039,7 @@ remove_wizard() log_admin("[key_name(usr)] has de-wizard'ed [current].") if("wizard") - if(has_antag_datum(/datum/antagonist/wizard)) + if(!has_antag_datum(/datum/antagonist/wizard)) special_role = "Wizard" add_antag_datum(/datum/antagonist/wizard) message_admins("[key_name_admin(usr)] has wizard'ed [current].") diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 30fd178f12..86d6b62198 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -28,7 +28,7 @@ new /obj/item/clothing/gloves/color/captain(src) new /obj/item/restraints/handcuffs/cable/zipties(src) new /obj/item/storage/belt/sabre(src) - new /obj/item/gun/energy/e_gun(src) + new /obj/item/gun/energy/e_gun/cx(src) new /obj/item/door_remote/captain(src) /obj/structure/closet/secure_closet/hop @@ -51,7 +51,7 @@ new /obj/item/device/assembly/flash/handheld(src) new /obj/item/clothing/glasses/sunglasses(src) new /obj/item/restraints/handcuffs/cable/zipties(src) - new /obj/item/gun/energy/e_gun(src) + new /obj/item/gun/energy/e_gun/cx(src) new /obj/item/clothing/neck/petcollar(src) new /obj/item/door_remote/civillian(src) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index aa4a1b19ca..771ebe4155 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -228,7 +228,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
" switch(current_tab) - if (0) // Character Settings# + if (0) // Character Settings if(path) var/savefile/S = new /savefile(path) if(S) @@ -279,14 +279,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) // dat += "Size: [character_size]
" dat += "
" - dat += "

Body

" - dat += "Random Body " - dat += "Always Random Body: [be_random_body ? "Yes" : "No"]
" - - dat += "
" - - dat += "Species:
[pref_species.name]
" - dat += "Underwear:
[underwear]
" dat += "Undershirt:
[undershirt]
" dat += "Socks:
[socks]
" diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm index 160c42a9a5..2c698cb7dc 100644 --- a/code/modules/events/holiday/vday.dm +++ b/code/modules/events/holiday/vday.dm @@ -124,7 +124,14 @@ "You're the vomit to my flyperson.", "You must be liquid dark matter, because you're pulling me closer.", "Not even sorium can drive me away from you.", - "Wanna make like a borg and do some heavy petting?" ) + "Wanna make like a borg and do some heavy petting?", + "Are you powering the station? Because you super matter to me.", + "I wish science could make me a bag of holding you.", + "Let's call the emergency CUDDLE.", + "I must be tripping on BZ, because I saw an angel walk by.", + "Wanna empty out my tool storage?", + "Did you visit the medbay after you fell from heaven?", + "Are you wearing space pants? Wanna not be?" ) /obj/item/valentine/attackby(obj/item/W, mob/user, params) ..() @@ -174,8 +181,9 @@ "A heart-shaped candy that reads: WAG MY TAIL", "A heart-shaped candy that reads: VALIDTINES", "A heart-shaped candy that reads: FACEHUGGER", - "A heart-shaped candy that reads: DOMINATOR", - "A heart-shaped candy that reads: GET TESLA'D", - "A heart-shaped candy that reads: COCK CULT", - "A heart-shaped candy that reads: PET ME") + "A heart-shaped candy that reads: BOX OF HUGS", + "A heart-shaped candy that reads: REEBE MINE", + "A heart-shaped candy that reads: PET ME", + "A heart-shaped candy that reads: TO THE DORMS", + "A heart-shaped candy that reads: DIS MEMBER") icon_state = pick("candyheart", "candyheart2", "candyheart3", "candyheart4") diff --git a/code/modules/jobs/job_types/security.dm b/code/modules/jobs/job_types/security.dm index 442b75c972..a1b95065c6 100644 --- a/code/modules/jobs/job_types/security.dm +++ b/code/modules/jobs/job_types/security.dm @@ -48,7 +48,7 @@ Head of Security gloves = /obj/item/clothing/gloves/color/black/hos head = /obj/item/clothing/head/HoS/beret glasses = /obj/item/clothing/glasses/hud/security/sunglasses - suit_store = /obj/item/gun/energy/e_gun + suit_store = /obj/item/gun/energy/e_gun/cx r_pocket = /obj/item/device/assembly/flash/handheld l_pocket = /obj/item/restraints/handcuffs backpack_contents = list(/obj/item/melee/baton/loaded=1) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 10e2dedfd6..b21f0e2bba 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -22,6 +22,7 @@ limbs_id = "golem" fixed_mut_color = "aaa" var/info_text = "As an Iron Golem, you don't have any special traits." + var/random_eligible = TRUE //If false, the golem subtype can't be made through golem mutation toxin var/prefix = "Iron" var/list/special_names @@ -44,11 +45,20 @@ name = "Random Golem" blacklisted = FALSE dangerous_existence = FALSE + var/static/list/random_golem_types /datum/species/golem/random/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() - var/list/golem_types = typesof(/datum/species/golem) - src.type - var/datum/species/golem/golem_type = pick(golem_types) + if(!random_golem_types) + random_golem_types = subtypesof(/datum/species/golem) - type + for(var/V in random_golem_types) + var/datum/species/golem/G = V + if(!initial(G.random_eligible)) + random_golem_types -= G + to_chat(world, "Excluding golem type [initial(G.id)]") + else + to_chat(world, "Allowing golem type [initial(G.id)]") + var/datum/species/golem/golem_type = pick(random_golem_types) var/mob/living/carbon/human/H = C H.set_species(golem_type) to_chat(H, "[initial(golem_type.info_text)]") @@ -596,7 +606,7 @@ info_text = "As a clockwork golem, you are faster than \ other types of golem (being a machine), and are immune to electric shocks." species_traits = list(NO_UNDERWEAR, NOTRANSSTING, NOBREATH, NOZOMBIE, VIRUSIMMUNE, RADIMMUNE, NOBLOOD, RESISTCOLD, RESISTPRESSURE, PIERCEIMMUNE) - armor = 40 //Reinforced, but also slim to allow for fast movement + armor = 20 //Reinforced, but much less so to allow for fast movement attack_verb = "smash" attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg' sexes = FALSE @@ -638,7 +648,8 @@ has_corpse = TRUE blacklisted = TRUE dangerous_existence = TRUE - + random_eligible = FALSE + /datum/species/golem/cloth name = "Cloth Golem" id = "cloth golem" diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index aa288e52d7..3ea1be6f03 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -206,6 +206,7 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = 1500 + poison_type = "frost_oil" color = rgb(114,228,250) gold_core_spawnable = 0 @@ -214,6 +215,7 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = 1500 + poison_type = "frost_oil" color = rgb(114,228,250) gold_core_spawnable = 0 @@ -222,6 +224,7 @@ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 maxbodytemp = 1500 + poison_type = "frost_oil" color = rgb(114,228,250) gold_core_spawnable = 0 diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm index 63f7e48281..2365bb03ed 100644 --- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm +++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm @@ -66,7 +66,7 @@ /obj/machinery/smoke_machine/attackby(obj/item/I, mob/user, params) add_fingerprint(user) - if(istype(I, /obj/item/reagent_containers)) + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) var/obj/item/reagent_containers/RC = I var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this) if(units) diff --git a/code/modules/server_tools/nudge.py b/code/modules/server_tools/nudge.py deleted file mode 100644 index 3d94ccdad7..0000000000 --- a/code/modules/server_tools/nudge.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 -import sys -import pickle -import socket - - -def pack(): - data = sys.argv[1] - - nudge(str.encode(data)) - - -def nudge(data): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - with open('config/server_to_tool_bridge_port.txt', 'r') as myfile: - portstr=myfile.read().replace('\n', '').strip() - s.connect(("localhost", int(portstr))) - s.send(data) - s.close() - -if __name__ == "__main__" and len(sys.argv) > 1: - pack() diff --git a/code/modules/server_tools/server_tools.dm b/code/modules/server_tools/server_tools.dm deleted file mode 100644 index 9cacb4542f..0000000000 --- a/code/modules/server_tools/server_tools.dm +++ /dev/null @@ -1,93 +0,0 @@ -GLOBAL_VAR_INIT(reboot_mode, REBOOT_MODE_NORMAL) //if the world should request the service to kill it at reboot -GLOBAL_PROTECT(reboot_mode) - -/world/proc/RunningService() - return params[SERVICE_WORLD_PARAM] - -/proc/ServiceVersion() - if(world.RunningService()) - return world.params[SERVICE_VERSION_PARAM] - -/world/proc/ExportService(command) - return RunningService() && shell("python code/modules/server_tools/nudge.py \"[command]\"") == 0 - -/world/proc/IRCBroadcast(msg) - ExportService("[SERVICE_REQUEST_IRC_BROADCAST] [msg]") - -/world/proc/ServiceEndProcess() - log_world("Sending shutdown request!"); - sleep(1) //flush the buffers - ExportService(SERVICE_REQUEST_KILL_PROCESS) - -//called at the exact moment the world is supposed to reboot -/world/proc/ServiceReboot() - switch(GLOB.reboot_mode) - if(REBOOT_MODE_HARD) - to_chat(src, "Hard reboot triggered, you will automatically reconnect...") - ServiceEndProcess() - if(REBOOT_MODE_SHUTDOWN) - to_chat(src, "The server is shutting down...") - ServiceEndProcess() - else - ExportService(SERVICE_REQUEST_WORLD_REBOOT) //just let em know - -/world/proc/ServiceCommand(list/params) - var/sCK = RunningService() - var/their_sCK = params[SERVICE_CMD_PARAM_KEY] - - if(!their_sCK || their_sCK != sCK) - return "Invalid comms key!"; - - var/command = params[SERVICE_CMD_PARAM_COMMAND] - if(!command) - return "No command!" - - var/static/last_irc_status = 0 - switch(command) - if(SERVICE_CMD_HARD_REBOOT) - if(GLOB.reboot_mode != REBOOT_MODE_HARD) - GLOB.reboot_mode = REBOOT_MODE_HARD - log_world("Hard reboot requested by service") - message_admins("The world will hard reboot at the end of the game. Requested by service.") - SSblackbox.set_val("service_hard_restart", TRUE) - if(SERVICE_CMD_GRACEFUL_SHUTDOWN) - if(GLOB.reboot_mode != REBOOT_MODE_SHUTDOWN) - GLOB.reboot_mode = REBOOT_MODE_SHUTDOWN - log_world("Shutdown requested by service") - message_admins("The world will shutdown at the end of the game. Requested by service.") - SSblackbox.set_val("service_shutdown", TRUE) - if(SERVICE_CMD_WORLD_ANNOUNCE) - var/msg = params["message"] - if(!istext(msg) || !msg) - return "No message set!" - to_chat(src, "[html_encode(msg)]") - return "SUCCESS" - if(SERVICE_CMD_IRC_STATUS) - var/rtod = REALTIMEOFDAY - if(rtod - last_irc_status < IRC_STATUS_THROTTLE) - return - last_irc_status = rtod - var/list/adm = get_admin_counts() - var/list/allmins = adm["total"] - var/status = "Admins: [allmins.len] (Active: [english_list(adm["present"])] AFK: [english_list(adm["afk"])] Stealth: [english_list(adm["stealth"])] Skipped: [english_list(adm["noflags"])]). " - status += "Players: [GLOB.clients.len] (Active: [get_active_player_count(0,1,0)]). Mode: [SSticker.mode ? SSticker.mode.name : "Not started"]." - return status - if(SERVICE_CMD_IRC_CHECK) - var/rtod = REALTIMEOFDAY - if(rtod - last_irc_status < IRC_STATUS_THROTTLE) - return - last_irc_status = rtod - var/config_server = CONFIG_GET(string/server) - return "[GLOB.round_id ? "Round #[GLOB.round_id]: " : ""][GLOB.clients.len] players on [SSmapping.config.map_name], Mode: [GLOB.master_mode]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [config_server ? config_server : "[world.internet_address]:[world.port]"]" - if(SERVICE_CMD_ADMIN_MSG) - return IrcPm(params[SERVICE_CMD_PARAM_TARGET], params[SERVICE_CMD_PARAM_MESSAGE], params[SERVICE_CMD_PARAM_SENDER]) - - if(SERVICE_CMD_NAME_CHECK) - log_admin("IRC Name Check: [params[SERVICE_CMD_PARAM_SENDER]] on [params[SERVICE_CMD_PARAM_TARGET]]") - message_admins("IRC name checking on [params[SERVICE_CMD_PARAM_TARGET]] from [params[SERVICE_CMD_PARAM_SENDER]]") - return keywords_lookup(params[SERVICE_CMD_PARAM_TARGET], 1) - if(SERVICE_CMD_ADMIN_WHO) - return ircadminwho() - else - return "Unknown command: [command]" - diff --git a/icons/mob/citadel/guns_lefthand.dmi b/icons/mob/citadel/guns_lefthand.dmi index 9323726d77..808b4aadf0 100644 Binary files a/icons/mob/citadel/guns_lefthand.dmi and b/icons/mob/citadel/guns_lefthand.dmi differ diff --git a/icons/mob/citadel/guns_righthand.dmi b/icons/mob/citadel/guns_righthand.dmi index 6f22a499c7..ba4c495318 100644 Binary files a/icons/mob/citadel/guns_righthand.dmi and b/icons/mob/citadel/guns_righthand.dmi differ diff --git a/icons/obj/guns/cit_guns.dmi b/icons/obj/guns/cit_guns.dmi index 99fe102ffe..69d8f37810 100644 Binary files a/icons/obj/guns/cit_guns.dmi and b/icons/obj/guns/cit_guns.dmi differ