From e76ce78a7bba629baeeb4a1fae18b0110b3e7c33 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 00:25:01 +0000 Subject: [PATCH 01/23] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-87610.yml | 6 ---- html/changelogs/AutoChangeLog-pr-87676.yml | 5 --- html/changelogs/AutoChangeLog-pr-87689.yml | 4 --- html/changelogs/AutoChangeLog-pr-87697.yml | 4 --- html/changelogs/AutoChangeLog-pr-87702.yml | 5 --- html/changelogs/AutoChangeLog-pr-87712.yml | 4 --- html/changelogs/AutoChangeLog-pr-87714.yml | 4 --- html/changelogs/AutoChangeLog-pr-87721.yml | 6 ---- html/changelogs/AutoChangeLog-pr-87730.yml | 4 --- html/changelogs/AutoChangeLog-pr-87736.yml | 5 --- html/changelogs/AutoChangeLog-pr-87737.yml | 4 --- html/changelogs/archive/2024-11.yml | 38 ++++++++++++++++++++++ 12 files changed, 38 insertions(+), 51 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-87610.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87676.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87689.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87697.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87702.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87712.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87714.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87721.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87730.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87736.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-87737.yml diff --git a/html/changelogs/AutoChangeLog-pr-87610.yml b/html/changelogs/AutoChangeLog-pr-87610.yml deleted file mode 100644 index 487644fc3a29a..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87610.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "00-Steven" -delete-after: True -changes: - - bugfix: "NTNRC no longer endlessly duplicates messages with duplicate contents upon switching channels." - - bugfix: "The new message header you get when NTNRC runs in the background actually works." - - bugfix: "NtOS header actually updates if there are no program headers." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87676.yml b/html/changelogs/AutoChangeLog-pr-87676.yml deleted file mode 100644 index df20f96c5612d..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87676.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "SyncIt21" -delete-after: True -changes: - - bugfix: "MK honk shoes now consume bananium & can clown again" - - code_imp: "material container objects end their attack chain early" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87689.yml b/html/changelogs/AutoChangeLog-pr-87689.yml deleted file mode 100644 index 40fbd2fab95fb..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87689.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SyncIt21" -delete-after: True -changes: - - bugfix: "status & newscaster frame won't drop extra glass sheets upon deconstruction" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87697.yml b/html/changelogs/AutoChangeLog-pr-87697.yml deleted file mode 100644 index 17d5b2b999d92..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87697.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Rhials" -delete-after: True -changes: - - bugfix: "Goliath Tendril Hammer arm (from the gene brain) is now resistant to being burned off by acid/fire." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87702.yml b/html/changelogs/AutoChangeLog-pr-87702.yml deleted file mode 100644 index 21da306548273..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87702.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "necromanceranne" -delete-after: True -changes: - - balance: "Some mind altering effects of heretics (predominantly Path of the Moon heretic abilities) are nullified using...a tinfoil hat. But awareness of the mind altering psychotropic eldritch brain wizards has spread amongst the conspiracy theorists. They could be anyone! Even YOU." - - balance: "Some additional spells (mindswap, nightmare's terrorize) are also blocked." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87712.yml b/html/changelogs/AutoChangeLog-pr-87712.yml deleted file mode 100644 index 310b552be4722..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87712.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "NoselessCanine" -delete-after: True -changes: - - balance: "Gas mask filters are now more effective, and their degradation is more heavily influenced by what gasses they are filtering." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87714.yml b/html/changelogs/AutoChangeLog-pr-87714.yml deleted file mode 100644 index 0f37160fbee8e..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87714.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "unit0016" -delete-after: True -changes: - - code_imp: "Mappers can now opt out of automatically linking their up/down station traits." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87721.yml b/html/changelogs/AutoChangeLog-pr-87721.yml deleted file mode 100644 index 82b007fdcb614..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87721.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Ghommie" -delete-after: True -changes: - - bugfix: "You can perform fish scanning experiments again." - - bugfix: "You can actually release fish on water turfs after catching them." - - spellcheck: "Fixed a typo in the name of material fishing rods." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87730.yml b/html/changelogs/AutoChangeLog-pr-87730.yml deleted file mode 100644 index 2450028e1e18d..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87730.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "thegrb93" -delete-after: True -changes: - - bugfix: "Fixes oil slimes making vegetable oil instead of corn oil" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87736.yml b/html/changelogs/AutoChangeLog-pr-87736.yml deleted file mode 100644 index f5aa63c75db72..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87736.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Jacquerel" -delete-after: True -changes: - - bugfix: "Living Limbs no longer try to grab things that are under the floor." - - spellcheck: "Living Limb feedback messages now don't redundantly specify that they are flesh arms." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-87737.yml b/html/changelogs/AutoChangeLog-pr-87737.yml deleted file mode 100644 index 63f172548d766..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-87737.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Fikou" -delete-after: True -changes: - - bugfix: "fixes borgs linking to ais in mechs cards and modsuits" \ No newline at end of file diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml index efaf9114db7e3..d5e17a66462b0 100644 --- a/html/changelogs/archive/2024-11.yml +++ b/html/changelogs/archive/2024-11.yml @@ -273,3 +273,41 @@ - spellcheck: the text for failing to succumb is now spanned zoomachina: - bugfix: e-cigarettes can't be emptied if the cap isn't open +2024-11-09: + 00-Steven: + - bugfix: NTNRC no longer endlessly duplicates messages with duplicate contents + upon switching channels. + - bugfix: The new message header you get when NTNRC runs in the background actually + works. + - bugfix: NtOS header actually updates if there are no program headers. + Fikou: + - bugfix: fixes borgs linking to ais in mechs cards and modsuits + Ghommie: + - bugfix: You can perform fish scanning experiments again. + - bugfix: You can actually release fish on water turfs after catching them. + - spellcheck: Fixed a typo in the name of material fishing rods. + Jacquerel: + - bugfix: Living Limbs no longer try to grab things that are under the floor. + - spellcheck: Living Limb feedback messages now don't redundantly specify that they + are flesh arms. + NoselessCanine: + - balance: Gas mask filters are now more effective, and their degradation is more + heavily influenced by what gasses they are filtering. + Rhials: + - bugfix: Goliath Tendril Hammer arm (from the gene brain) is now resistant to being + burned off by acid/fire. + SyncIt21: + - bugfix: MK honk shoes now consume bananium & can clown again + - code_imp: material container objects end their attack chain early + - bugfix: status & newscaster frame won't drop extra glass sheets upon deconstruction + necromanceranne: + - balance: Some mind altering effects of heretics (predominantly Path of the Moon + heretic abilities) are nullified using...a tinfoil hat. But awareness of the + mind altering psychotropic eldritch brain wizards has spread amongst the conspiracy + theorists. They could be anyone! Even YOU. + - balance: Some additional spells (mindswap, nightmare's terrorize) are also blocked. + thegrb93: + - bugfix: Fixes oil slimes making vegetable oil instead of corn oil + unit0016: + - code_imp: Mappers can now opt out of automatically linking their up/down station + traits. From 89ac80e7734b4b53e2babd32156616fef6d158d3 Mon Sep 17 00:00:00 2001 From: Xander3359 <66163761+Xander3359@users.noreply.github.com> Date: Fri, 8 Nov 2024 21:17:45 -0500 Subject: [PATCH 02/23] fix blade ascension not giving you the ring of blades (#87744) ## About The Pull Request fix blade ascension not giving you the ring of blades ## Why It's Good For The Game Bugfix Closes https://github.com/tgstation/tgstation/issues/87344 Closes https://github.com/tgstation/tgstation/issues/85635 ## Changelog :cl: fix: fix blade ascension not giving you the ring of blades /:cl: --- code/modules/antagonists/heretic/knowledge/blade_lore.dm | 2 +- code/modules/antagonists/heretic/magic/furious_steel.dm | 2 +- code/modules/antagonists/heretic/status_effects/buffs.dm | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index c24ed2c273f3c..6cde82e85166c 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -444,7 +444,7 @@ ) ADD_TRAIT(user, TRAIT_NEVER_WOUNDED, name) RegisterSignal(user, COMSIG_HERETIC_BLADE_ATTACK, PROC_REF(on_eldritch_blade)) - user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, 1 MINUTES) + user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, /obj/effect/floating_blade, 1 MINUTES) user.add_stun_absorption( source = name, message = span_warning("%EFFECT_OWNER throws off the stun!"), diff --git a/code/modules/antagonists/heretic/magic/furious_steel.dm b/code/modules/antagonists/heretic/magic/furious_steel.dm index d61ce5d1a3920..9414ca9d7116d 100644 --- a/code/modules/antagonists/heretic/magic/furious_steel.dm +++ b/code/modules/antagonists/heretic/magic/furious_steel.dm @@ -19,7 +19,7 @@ active_msg = "You summon forth three blades of furious silver." deactive_msg = "You conceal the blades of furious silver." cast_range = 20 - projectile_type = /obj/projectile/floating_blade + projectile_type = /obj/effect/floating_blade projectile_amount = 3 /// A ref to the status effect surrounding our heretic on activation. diff --git a/code/modules/antagonists/heretic/status_effects/buffs.dm b/code/modules/antagonists/heretic/status_effects/buffs.dm index d82d145b3ef65..4a4083e0ac4c9 100644 --- a/code/modules/antagonists/heretic/status_effects/buffs.dm +++ b/code/modules/antagonists/heretic/status_effects/buffs.dm @@ -148,7 +148,7 @@ /// If TRUE, we self-delete our status effect after all the blades are deleted. var/delete_on_blades_gone = TRUE /// What blade type to create - var/blade_type = /obj/effect/floating_blade + var/obj/effect/floating_blade/blade_type /// A list of blade effects orbiting / protecting our owner var/list/obj/effect/floating_blade/blades = list() @@ -190,8 +190,7 @@ if(QDELETED(src) || QDELETED(owner)) return - var/obj/effect/floating_blade/blade - blade = new blade_type(get_turf(owner)) + var/obj/effect/floating_blade/blade = new blade_type(get_turf(owner)) blades += blade blade.orbit(owner, blade_orbit_radius) RegisterSignal(blade, COMSIG_QDELETING, PROC_REF(remove_blade)) @@ -261,8 +260,8 @@ max_num_blades = 4, blade_orbit_radius = 20, time_between_initial_blades = 0.25 SECONDS, - blade_recharge_time = 1 MINUTES, blade_type = /obj/effect/floating_blade, + blade_recharge_time = 1 MINUTES, ) src.blade_recharge_time = blade_recharge_time From 9d46482f2f115d92595c0a432a8171d93b99aff3 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 02:18:06 +0000 Subject: [PATCH 03/23] Automatic changelog for PR #87744 [ci skip] --- html/changelogs/AutoChangeLog-pr-87744.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87744.yml diff --git a/html/changelogs/AutoChangeLog-pr-87744.yml b/html/changelogs/AutoChangeLog-pr-87744.yml new file mode 100644 index 0000000000000..c3ac14a47e82b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87744.yml @@ -0,0 +1,4 @@ +author: "Xander3359" +delete-after: True +changes: + - bugfix: "fix blade ascension not giving you the ring of blades" \ No newline at end of file From dfb5d07b88a093e794898ba4b7a90099eeb7859a Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Sat, 9 Nov 2024 04:07:55 +0100 Subject: [PATCH 04/23] Fixed fishing rod duping with poly belts and shapeshift spells. (#87706) ## About The Pull Request It turns out the "shapeshifted from spell" status ejects everything inside the shapeshifted mob when removed. That's been causing a little issue with the fishing rod from the profound_fisher component, which a few mobs have. This PR fixes just that. ## Why It's Good For The Game ![immagine](https://github.com/user-attachments/assets/b664ffa6-567f-4332-b7dc-a5d2badb43d3) ![immagine](https://github.com/user-attachments/assets/4c453f91-2852-40c0-8f54-c5d66f28fdb1) ## Changelog :cl: fix: Fixed fishing rod duping with poly belts and shapeshift spells. spellcheck: Fixed a small typo when examining fishing rods. /:cl: --- code/datums/components/profound_fisher.dm | 29 ++++++++++++++----- code/modules/fishing/fishing_rod.dm | 2 +- code/modules/mod/modules/modules_general.dm | 2 +- .../spell_types/shapeshift/_shape_status.dm | 2 +- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/code/datums/components/profound_fisher.dm b/code/datums/components/profound_fisher.dm index 9638af4a8f2c2..cc7e87aeb40af 100644 --- a/code/datums/components/profound_fisher.dm +++ b/code/datums/components/profound_fisher.dm @@ -2,15 +2,18 @@ /datum/component/profound_fisher ///the fishing rod this mob will use var/obj/item/fishing_rod/mob_fisher/our_rod + ///Wether we should delete the fishing rod along with the component or replace it if it's somehow removed from the parent + var/delete_rod_when_deleted = TRUE -/datum/component/profound_fisher/Initialize(our_rod) +/datum/component/profound_fisher/Initialize(our_rod, delete_rod_when_deleted = TRUE) var/isgloves = istype(parent, /obj/item/clothing/gloves) if(!isliving(parent) && !isgloves) return COMPONENT_INCOMPATIBLE src.our_rod = our_rod || new(parent) src.our_rod.internal = TRUE + src.delete_rod_when_deleted = delete_rod_when_deleted ADD_TRAIT(src.our_rod, TRAIT_NOT_BARFABLE, REF(src)) - RegisterSignal(src.our_rod, COMSIG_QDELETING, PROC_REF(on_rod_qdel)) + RegisterSignal(src.our_rod, COMSIG_MOVABLE_MOVED, PROC_REF(on_rod_moved)) if(!isgloves) RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack)) @@ -37,14 +40,26 @@ examine_list += span_info("When [EXAMINE_HINT("held")] or [EXAMINE_HINT("equipped")], [EXAMINE_HINT("right-click")] with a empty hand to open the integrated fishing rod interface.") examine_list += span_tinynoticeital("To fish, you need to turn combat mode off.") -/datum/component/profound_fisher/proc/on_rod_qdel(datum/source) +///Handles replacing the fishing rod if somehow removed from the parent movable if delete_rod_when_deleted is TRUE, otherwise delete the component. +/datum/component/profound_fisher/proc/on_rod_moved(datum/source) SIGNAL_HANDLER - qdel(src) + if(QDELETED(src) || our_rod.loc == parent) + return + if(delete_rod_when_deleted) + UnregisterSignal(our_rod, COMSIG_MOVABLE_MOVED) + if(!QDELETED(our_rod)) + qdel(our_rod) + our_rod = new our_rod.type(parent) + else + qdel(src) /datum/component/profound_fisher/Destroy() - our_rod.internal = FALSE - UnregisterSignal(our_rod, COMSIG_QDELETING) - REMOVE_TRAIT(our_rod, TRAIT_NOT_BARFABLE, REF(src)) + UnregisterSignal(our_rod, COMSIG_MOVABLE_MOVED) + if(!delete_rod_when_deleted) + our_rod.internal = FALSE + REMOVE_TRAIT(our_rod, TRAIT_NOT_BARFABLE, REF(src)) + else if(!QDELETED(our_rod)) + QDEL_NULL(our_rod) our_rod = null return ..() diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 8b24e34b9e541..4bd045616b3e8 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -122,7 +122,7 @@ if(hook) equipped_stuff += "[icon2html(hook, user)] [hook.name]" if(bait) - equipped_stuff += "[icon2html(bait, user)] [bait] as bait." + equipped_stuff += "[icon2html(bait, user)] [bait]" if(length(equipped_stuff)) . += span_notice("It has \a [english_list(equipped_stuff)] equipped.") if(!bait) diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 14fc328aed7f0..42e4c56f55ec1 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -985,7 +985,7 @@ return gloves.AddComponent(/datum/component/adjust_fishing_difficulty, 5) if(equipped) - gloves.AddComponent(/datum/component/profound_fisher, equipped) + gloves.AddComponent(/datum/component/profound_fisher, equipped, delete_rod_when_deleted = FALSE) /obj/item/mod/module/fishing_glove/on_part_deactivation(deleting = FALSE) var/obj/item/gloves = mod.get_part_from_slot(ITEM_SLOT_GLOVES) diff --git a/code/modules/spells/spell_types/shapeshift/_shape_status.dm b/code/modules/spells/spell_types/shapeshift/_shape_status.dm index 2f8d53eeac203..f8f44817a5932 100644 --- a/code/modules/spells/spell_types/shapeshift/_shape_status.dm +++ b/code/modules/spells/spell_types/shapeshift/_shape_status.dm @@ -194,7 +194,7 @@ if(owner?.contents) // Prevent round removal and consuming stuff when losing shapeshift for(var/atom/movable/thing as anything in owner.contents) - if(thing == caster_mob) + if(thing == caster_mob || HAS_TRAIT(thing, TRAIT_NOT_BARFABLE)) continue thing.forceMove(get_turf(owner)) From c4276cf81d55ce2fc4d06ccbcc823207a048bd30 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 03:08:16 +0000 Subject: [PATCH 05/23] Automatic changelog for PR #87706 [ci skip] --- html/changelogs/AutoChangeLog-pr-87706.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87706.yml diff --git a/html/changelogs/AutoChangeLog-pr-87706.yml b/html/changelogs/AutoChangeLog-pr-87706.yml new file mode 100644 index 0000000000000..0265c8918a5c8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87706.yml @@ -0,0 +1,5 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed fishing rod duping with poly belts and shapeshift spells." + - spellcheck: "Fixed a small typo when examining fishing rods." \ No newline at end of file From f8ef0319d3940a6db6ca99723f2e302e8887dc53 Mon Sep 17 00:00:00 2001 From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Date: Sat, 9 Nov 2024 14:17:07 +0530 Subject: [PATCH 06/23] Chem master validates selected container in UI (#87780) --- .../reagents/chemistry/machinery/chem_master.dm | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 87ba535a149c6..2aac6a457abfd 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -393,7 +393,6 @@ . = TRUE if(. && !QDELETED(src)) //transferring volatile reagents can cause a explosion & destory us update_appearance(UPDATE_OVERLAYS) - return . /obj/machinery/chem_master/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() @@ -447,9 +446,22 @@ if("selectContainer") var/obj/item/reagent_containers/target = locate(params["ref"]) + + //is this even a valid type path if(!ispath(target)) return FALSE + //are we printing a valid container + var/container_found = FALSE + for(var/category in printable_containers) + for(var/obj/item/reagent_containers/container as anything in printable_containers[category]) + if(target == container) + container_found = TRUE + break + if(!container_found) + return FALSE + + //set the container selected_container = target return TRUE From 18a1148db5a32620f27c0bc0d46034a0c083b535 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 08:47:27 +0000 Subject: [PATCH 07/23] Automatic changelog for PR #87780 [ci skip] --- html/changelogs/AutoChangeLog-pr-87780.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87780.yml diff --git a/html/changelogs/AutoChangeLog-pr-87780.yml b/html/changelogs/AutoChangeLog-pr-87780.yml new file mode 100644 index 0000000000000..159c49658736a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87780.yml @@ -0,0 +1,4 @@ +author: "SyncIt21" +delete-after: True +changes: + - bugfix: "chem master validates selected container in UI so no more href exploits" \ No newline at end of file From 263a6937ed50451842d8a831a599f29e01bdc710 Mon Sep 17 00:00:00 2001 From: harryob Date: Sat, 9 Nov 2024 10:06:30 +0000 Subject: [PATCH 08/23] fixes missing icons in abductor console (#87759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## About The Pull Request grabs the icon for the item correctly. also typescripts the interface because blessed type safety would've prevented it being missing in the first place. and clears some random deprecations ## Why It's Good For The Game pretty icons 👍 loading icons 👎 ![image](https://github.com/user-attachments/assets/ec524a52-fff5-4c67-b3fb-88fbfd5988af) ## Changelog :cl: fix: the abductor console now correctly loads images of equipment /:cl: closes #87565 --- .../antagonists/abductor/machinery/console.dm | 9 +++ ...bductorConsole.jsx => AbductorConsole.tsx} | 62 +++++++++++++------ 2 files changed, 53 insertions(+), 18 deletions(-) rename tgui/packages/tgui/interfaces/{AbductorConsole.jsx => AbductorConsole.tsx} (74%) diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm index 3dcdaf5a5b07e..4c5a30c0d9e27 100644 --- a/code/modules/antagonists/abductor/machinery/console.dm +++ b/code/modules/antagonists/abductor/machinery/console.dm @@ -94,10 +94,19 @@ "items" = (category == selected_cat ? list() : null)) for(var/gear in possible_gear[category]) var/datum/abductor_gear/AG = possible_gear[category][gear] + + var/atom/gear_path + if(!length(AG.build_path)) + continue + + gear_path = AG.build_path[1] + cat["items"] += list(list( "name" = AG.name, "cost" = AG.cost, "desc" = AG.description, + "icon" = gear_path::icon, + "icon_state" = gear_path::icon_state, )) data["categories"] += list(cat) return data diff --git a/tgui/packages/tgui/interfaces/AbductorConsole.jsx b/tgui/packages/tgui/interfaces/AbductorConsole.tsx similarity index 74% rename from tgui/packages/tgui/interfaces/AbductorConsole.jsx rename to tgui/packages/tgui/interfaces/AbductorConsole.tsx index bb2f1dffccfe3..d8d3305362725 100644 --- a/tgui/packages/tgui/interfaces/AbductorConsole.jsx +++ b/tgui/packages/tgui/interfaces/AbductorConsole.tsx @@ -5,10 +5,33 @@ import { Section, Tabs, } from 'tgui-core/components'; +import { BooleanLike } from 'tgui-core/react'; import { useBackend, useSharedState } from '../backend'; import { Window } from '../layouts'; -import { GenericUplink } from './Uplink/GenericUplink'; +import { GenericUplink, Item } from './Uplink/GenericUplink'; + +type AbductorConsoleData = { + categories: { name: string; items: ConsoleItem[] }[]; + + compactMode: BooleanLike; + experiment: BooleanLike; + points?: number; + credits?: number; + pad: BooleanLike; + gizmo: BooleanLike; + vest: BooleanLike; + vest_mode?: number; + vest_lock?: BooleanLike; +}; + +type ConsoleItem = { + name: string; + cost: number; + desc: string; + icon: string; + icon_state: string; +}; export const AbductorConsole = (props) => { const [tab, setTab] = useSharedState('tab', 1); @@ -47,15 +70,15 @@ export const AbductorConsole = (props) => { }; const Abductsoft = (props) => { - const { act, data } = useBackend(); + const { act, data } = useBackend(); const { experiment, points, credits, categories } = data; if (!experiment) { return No Experiment Machine Detected; } - const categoriesList = []; - const items = []; + const categoriesList: string[] = []; + const items: Item[] = []; for (let i = 0; i < categories.length; i++) { const category = categories[i]; categoriesList.push(category.name); @@ -67,7 +90,9 @@ const Abductsoft = (props) => { category: category.name, cost: `${item.cost} Credits`, desc: item.desc, - disabled: credits < item.cost, + disabled: (credits || 0) < item.cost, + icon: item.icon, + icon_state: item.icon_state, }); } } @@ -92,7 +117,7 @@ const Abductsoft = (props) => { }; const EmergencyTeleporter = (props) => { - const { act, data } = useBackend(); + const { act, data } = useBackend(); const { pad, gizmo } = data; if (!pad) { @@ -115,10 +140,11 @@ const EmergencyTeleporter = (props) => { @@ -126,7 +152,7 @@ const EmergencyTeleporter = (props) => { }; const VestSettings = (props) => { - const { act, data } = useBackend(); + const { act, data } = useBackend(); const { vest, vest_mode, vest_lock } = data; if (!vest) { @@ -139,25 +165,25 @@ const VestSettings = (props) => { buttons={ } > - From a85b48fdd4934650ff55fbe16f94598425279ca8 Mon Sep 17 00:00:00 2001 From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Date: Sat, 9 Nov 2024 15:37:20 +0530 Subject: [PATCH 09/23] Add unit test tag to your PR title (#87757) ## About The Pull Request You can now add `unit test` anywhere in your PR title to specify if you are adding/modifying unit tests for your code. It's worth 6 GBP (It Always has and wasn't changed here) For when you want some extra GBP for your unit tests that sometimes go un-noticed by maintainer's when reviewing large changes. It will encourage people to write unit tests so they can get the extra points ## Changelog N/A /:cl: --- tools/WebhookProcessor/github_webhook_processor.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index c3eb190aeaab0..24e9f502167d8 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -260,6 +260,8 @@ function tag_pr($payload, $opened) { $tags[] = 'Revert'; if(strpos(strtolower($title), 'removes') !== FALSE) $tags[] = 'Removal'; + if(strpos(strtolower($title), 'unit test') !== FALSE) + $tags[] = 'Unit Tests'; } $remove = array('Test Merge Candidate'); From 138c7b378c96d4ed2772df0e61553f3e1166a0ee Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 9 Nov 2024 04:07:36 -0600 Subject: [PATCH 10/23] Add `TRAIT_EVIL` to admin tooling (#87749) ## About The Pull Request Let's admins add/remove `TRAIT_EVIL` from mobs. ## Why It's Good For The Game Useful for debugging. ## Changelog :cl: admin: Admins can now add/remove TRAIT_EVIL from mobs. /:cl: --- code/_globalvars/traits/admin_tooling.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 9d1b47800b85c..7b7ca780a5409 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -100,6 +100,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_EXPANDED_FOV" = TRAIT_EXPANDED_FOV, "TRAIT_EXPERT_FISHER" = TRAIT_EXPERT_FISHER, "TRAIT_EXTROVERT" = TRAIT_EXTROVERT, + "TRAIT_EVIL" = TRAIT_EVIL, "TRAIT_FAKEDEATH" = TRAIT_FAKEDEATH, "TRAIT_FASTMED" = TRAIT_FASTMED, "TRAIT_FAST_CUFFING" = TRAIT_FAST_CUFFING, From 8621c7a9c24b3682bab9c569f588244f86e836ca Mon Sep 17 00:00:00 2001 From: Lucy Date: Sat, 9 Nov 2024 05:07:58 -0500 Subject: [PATCH 11/23] Use native BYOND `isnan` and `isinf` for math defines (#87748) ## About The Pull Request `// Remove these once we have Byond implementation.` Well guess what we have now? Altho sadly we still lack a native `isfinite`, so we still use a define for that. ## Why It's Good For The Game Native BYOND impls have better performance usually, due to them compiling down to instructions, avoiding proc overhead. ## Changelog No user-facing changes. --- code/__DEFINES/maths.dm | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index a7a95817b4405..aa13298e339a3 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -1,14 +1,5 @@ -// Remove these once we have Byond implementation. -// ------------------------------------ -#define IS_NAN(a) (a != a) - -#define IS_INF__UNSAFE(a) (a == a && a-a != a-a) -#define IS_INF(a) (isnum(a) && IS_INF__UNSAFE(a)) - -#define IS_FINITE__UNSAFE(a) (a-a == a-a) +#define IS_FINITE__UNSAFE(a) (!isinf(a) && !isnan(a)) #define IS_FINITE(a) (isnum(a) && IS_FINITE__UNSAFE(a)) -// ------------------------------------ -// Aight dont remove the rest // Credits to Nickr5 for the useful procs I've taken from his library resource. // This file is quadruple wrapped for your pleasure From 4cede34a4911096aa57f88473a5e23b0ec9b8cb6 Mon Sep 17 00:00:00 2001 From: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Date: Sat, 9 Nov 2024 11:08:51 +0100 Subject: [PATCH 12/23] [NO GBP] Fixes wings and jetpacks sometimes preventing you from opening doors (#87741) ## About The Pull Request I hate this timeline. What title says, makes jetpacks and wings allow you to bump into things you're moving into. ## Why It's Good For The Game This feels awful and requires you to stop pressing movement keys for a moment before resuming movement to get out of the "stuck" state ## Changelog :cl: fix: Fixed wings and jetpacks sometimes preventing you from opening doors /:cl: --- code/datums/components/jetpack.dm | 6 ++++++ .../surgery/organs/external/wings/functional_wings.dm | 2 +- code/modules/surgery/organs/external/wings/moth_wings.dm | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/code/datums/components/jetpack.dm b/code/datums/components/jetpack.dm index ccbe2b3fd4dac..fd49aa2b67b6a 100644 --- a/code/datums/components/jetpack.dm +++ b/code/datums/components/jetpack.dm @@ -164,6 +164,12 @@ /datum/component/jetpack/proc/on_pushoff(mob/source, movement_dir, continuous_move, atom/backup) SIGNAL_HANDLER + if (get_dir(source, backup) == movement_dir || source.loc == backup.loc) + return + + if (!source.client.intended_direction || (source.client.intended_direction & get_dir(source, backup))) + return + if (!should_trigger(source) || !check_on_move.Invoke(FALSE)) return diff --git a/code/modules/surgery/organs/external/wings/functional_wings.dm b/code/modules/surgery/organs/external/wings/functional_wings.dm index 63759761548d9..f773630f8bf1d 100644 --- a/code/modules/surgery/organs/external/wings/functional_wings.dm +++ b/code/modules/surgery/organs/external/wings/functional_wings.dm @@ -145,7 +145,7 @@ if (get_dir(source, backup) == movement_dir || source.loc == backup.loc) return - if (!can_fly(source) || !source.client.intended_direction) + if (!can_fly(source) || !source.client.intended_direction || (source.client.intended_direction & get_dir(source, backup))) return return COMPONENT_PREVENT_SPACEMOVE_HALT diff --git a/code/modules/surgery/organs/external/wings/moth_wings.dm b/code/modules/surgery/organs/external/wings/moth_wings.dm index 2753c88f2c478..265a9ee751226 100644 --- a/code/modules/surgery/organs/external/wings/moth_wings.dm +++ b/code/modules/surgery/organs/external/wings/moth_wings.dm @@ -82,7 +82,7 @@ if (get_dir(source, backup) == movement_dir || source.loc == backup.loc) return - if (!allow_flight() || !source.client.intended_direction) + if (!allow_flight() || !source.client.intended_direction || (source.client.intended_direction & get_dir(source, backup))) return return COMPONENT_PREVENT_SPACEMOVE_HALT From d990e4244e75b066a6404074ea32b7b2a31ca69b Mon Sep 17 00:00:00 2001 From: OrionTheFox <76465278+OrionTheFox@users.noreply.github.com> Date: Sat, 9 Nov 2024 03:10:28 -0700 Subject: [PATCH 13/23] Drinking Glass sprite updates (#87756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## About The Pull Request This was meant to be just fixing the missing pixel... then it turned to redoing all the glasses in all the basic sprites so they'd match... then redoing sprites that were outdated... And THEN I realized that drinking glasses can be using the same auto-sprite system beakers have and oh man it's spiraling. As for the (hopefully) full list of changes: - Removes all `glass_[color]` icons. Any drink that fell under these will now use the fill_icon and their reagent color. As such, a lot of reagent colors have been tweaked for readability/realism/lemons don't have red juice what the hell man (Some colors shown are outdated. It is very annoying to tweak these. I don't know how to in-game, if I even can. Relaunching several times is painful.) ![image](https://github.com/user-attachments/assets/7edae6b4-13ec-4d1e-827c-fb7da1b2013a) - Resprites the base `glass_empty`; now it is very visibly empty. The overlay being slightly transparent actually works pretty well with this. (Old / New) ![image](https://github.com/user-attachments/assets/e262c510-93d7-44b0-b4cc-cf498362b05b) - Full resprite of Curaçao (now it's actually its beautiful blue instead of gray) ![image](https://github.com/user-attachments/assets/3447c226-8f78-4fa3-bb55-4cb223a7e991) - Minor resprites Beer/Green Beer/Iced Beer/Ale (Yes, Beer/Green Beer have little animated bubbles) ![dreamseeker_Z1U2qBxRlx](https://github.com/user-attachments/assets/43903b24-2053-4571-b17b-f3ad80fa4150) ![image](https://github.com/user-attachments/assets/25327706-3207-4d3f-9ea8-ead29d3a0db0) - Minor resprite of Monkey Energy (It's animated now too but otherwise about the same sprite) ![dreammaker_lSqopANAXX](https://github.com/user-attachments/assets/7f797080-ae16-42c3-a1f1-e769506e31fd) - Minor resprites to Pina Olivida, Banana Juice, Lemon Juice, Carrot Juice - mostly just color tweaks so that they look more believable and the banana juice is less green - Fixes small nits in the sodas so that they are all consistent ## Why It's Good For The Game Sprite maintenance and (hopefully) improvements - we've got a lot of drinks in the Bars and the base foundation of that whole system deserves a bit of love as well ## Changelog :cl: image: redid most basic drinking glass sprites, and moved several drinks to use the same color system as beakers. Please bug report any incorrect colored drinks or juices! /:cl: --- .../reagents/drinks/alcohol_reagents.dm | 10 +++--- .../reagents/drinks/drink_reagents.dm | 32 +++++++++--------- .../reagents/drinks/glass_styles/alcohol.dm | 4 +-- .../drinks/glass_styles/coffee_tea.dm | 2 -- .../reagents/drinks/glass_styles/dairy.dm | 4 --- .../reagents/drinks/glass_styles/juices.dm | 14 -------- .../drinks/glass_styles/mixed_alcohol.dm | 8 ----- .../chemistry/reagents/other_reagents.dm | 1 - icons/obj/drinks/drinks.dmi | Bin 25921 -> 24901 bytes icons/obj/medical/reagent_fillings.dmi | Bin 7795 -> 9258 bytes 10 files changed, 22 insertions(+), 53 deletions(-) diff --git a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm index 58bacc57bcfd3..7866b2eb37f14 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm @@ -109,7 +109,7 @@ /datum/reagent/consumable/ethanol/beer name = "Beer" description = "An alcoholic beverage brewed since ancient times on Old Earth. Still popular today." - color = "#664300" // rgb: 102, 67, 0 + color = "#D7BC31" // rgb: 215, 188, 49 nutriment_factor = 1 boozepwr = 25 taste_description = "mild carbonated malt" @@ -1531,7 +1531,7 @@ /datum/reagent/consumable/ethanol/eggnog name = "Eggnog" description = "For enjoying the most wonderful time of the year." - color = "#fcfdc6" // rgb: 252, 253, 198 + color = "#ffe2ad" // rgb: 255, 226, 173 nutriment_factor = 2 boozepwr = 1 quality = DRINK_VERYGOOD @@ -1541,7 +1541,7 @@ /datum/reagent/consumable/ethanol/dreadnog name = "Dreadnog" description = "For suffering during a period of joy." - color = "#abb862" // rgb: 252, 253, 198 + color = "#f7ffad" // rgb: 247, 255, 173 nutriment_factor = 3 * REAGENTS_METABOLISM boozepwr = 1 quality = DRINK_REVOLTING @@ -1573,7 +1573,7 @@ /datum/reagent/consumable/ethanol/creme_de_menthe name = "Creme de Menthe" description = "A minty liqueur excellent for refreshing, cool drinks." - color = "#00cc00" + color = "#467446" //rgb: 70, 116, 70 boozepwr = 20 taste_description = "a minty, cool, and invigorating splash of cold streamwater" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1581,7 +1581,7 @@ /datum/reagent/consumable/ethanol/creme_de_cacao name = "Creme de Cacao" description = "A chocolatey liqueur excellent for adding dessert notes to beverages and bribing sororities." - color = "#996633" + color = "#350900" // rgb: 53, 9, 0 boozepwr = 20 taste_description = "a slick and aromatic hint of chocolates swirling in a bite of alcohol" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm index 09da70baa16e7..05a2c984287b3 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm @@ -30,7 +30,7 @@ /datum/reagent/consumable/limejuice name = "Lime Juice" description = "The sweet-sour juice of limes." - color = "#365E30" // rgb: 54, 94, 48 + color = "#a6f19a" // rgb: 166, 241, 154 taste_description = "unbearable sourness" ph = 2.2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -73,14 +73,14 @@ /datum/reagent/consumable/applejuice name = "Apple Juice" description = "The sweet juice of an apple, fit for all ages." - color = "#ECFF56" // rgb: 236, 255, 86 + color = "#fff06b" // rgb: 255, 240, 107 taste_description = "apples" ph = 3.2 // ~ 2.7 -> 3.7 /datum/reagent/consumable/poisonberryjuice name = "Poison Berry Juice" description = "A tasty juice blended from various kinds of very deadly and toxic berries." - color = "#863353" // rgb: 134, 51, 83 + color = "#792b49" // rgb: 121, 43, 73 taste_description = "berries" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -92,14 +92,14 @@ /datum/reagent/consumable/watermelonjuice name = "Watermelon Juice" description = "Delicious juice made from watermelon." - color = "#863333" // rgb: 134, 51, 51 + color = "#af5e5e" // rgb: 175, 94, 94 taste_description = "juicy watermelon" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/lemonjuice name = "Lemon Juice" description = "This juice is VERY sour." - color = "#863333" // rgb: 175, 175, 0 + color = "#ebeb9e" // rgb: 235, 235, 158 taste_description = "sourness" ph = 2 chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -107,7 +107,7 @@ /datum/reagent/consumable/banana name = "Banana Juice" description = "The raw essence of a banana. HONK" - color = "#863333" // rgb: 175, 175, 0 + color = "#FFFCB9" // rgb: 255, 252, 185 taste_description = "banana" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -167,7 +167,7 @@ name = "Potato Juice" description = "Juice of the potato. Bleh." nutriment_factor = 2 - color = "#302000" // rgb: 48, 32, 0 + color = "#E8A856" // rgb: 234, 157, 58 taste_description = "irish sadness" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -175,7 +175,7 @@ name = "Pickle Juice" description = "More accurately, this is the brine the pickle was floating in" nutriment_factor = 2 - color = "#302000" // rgb: 48, 32, 0 + color = "#cde65e" // rgb: 205, 230, 94 taste_description = "vinegar brine" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -362,7 +362,7 @@ /datum/reagent/consumable/icecoffee name = "Iced Coffee" description = "Coffee and ice, refreshing and cool." - color = "#102838" // rgb: 16, 40, 56 + color = "#462b15" // rgb: 70, 43, 21 nutriment_factor = 0 overdose_threshold = 80 taste_description = "bitter coldness" @@ -383,7 +383,7 @@ /datum/reagent/consumable/hot_ice_coffee name = "Hot Ice Coffee" description = "Coffee with pulsing ice shards" - color = "#102838" // rgb: 16, 40, 56 + color = "#462b15" // rgb: 70, 43, 21 nutriment_factor = 0 overdose_threshold = 80 taste_description = "bitter coldness and a hint of smoke" @@ -950,7 +950,7 @@ name = "Hot Coco" description = "Made with love! And coco beans." nutriment_factor = 4 - color = "#403010" // rgb: 64, 48, 16 + color = "#3b240e" // rgb: 59, 36, 14 taste_description = "creamy chocolate" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1095,7 +1095,7 @@ /datum/reagent/consumable/aloejuice name = "Aloe Juice" - color = "#A3C48B" + color = "#b3c5a7" // rgb: 179, 197, 167 description = "A healthy and refreshing juice." taste_description = "vegetable" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1139,7 +1139,7 @@ /datum/reagent/consumable/toechtauese_juice name = "Töchtaüse Juice" description = "An unpleasant juice made from töchtaüse berries. Best made into a syrup, unless you enjoy pain." - color = "#554862" + color = "#554862" // rgb: 85, 72, 98 nutriment_factor = 0 taste_description = "fiery itchy pain" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1147,7 +1147,7 @@ /datum/reagent/consumable/toechtauese_syrup name = "Töchtaüse Syrup" description = "A harsh spicy and bitter syrup, made from töchtaüse berries. Useful as an ingredient, both for food and cocktails." - color = "#554862" + color = "#554862" // rgb: 85, 72, 98 nutriment_factor = 0 taste_description = "sugar, spice, and nothing nice" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED @@ -1203,14 +1203,14 @@ /datum/reagent/consumable/cucumberjuice name = "Cucumber Juice" description = "Ordinary cucumber juice, nothing from the fantasy world." - color = "#6cd87a" + color = "#B1D861" // rgb: 177, 216, 97 taste_description = "light cucumber" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED /datum/reagent/consumable/cucumberlemonade name = "Cucumber Lemonade" description = "Cucumber juice, sugar, and soda; what else do I need?" - color = "#6cd87a" + color = "#cbe248" // rgb: 203, 226, 72 quality = DRINK_GOOD taste_description = "citrus soda with cucumber" chemical_flags = REAGENT_CAN_BE_SYNTHESIZED diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm index 5811f49da8f21..564f081601dc3 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/alcohol.dm @@ -95,6 +95,7 @@ name = "glass of amaretto" desc = "A sweet and syrupy looking drink." icon_state = "amarettoglass" + /datum/glass_style/drinking_glass/cognac required_drink_type = /datum/reagent/consumable/ethanol/cognac name = "glass of cognac" @@ -155,7 +156,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/pruno name = "glass of pruno" desc = "Fermented prison wine made from fruit, sugar, and despair. Security loves to confiscate this, which is the only kind thing Security has ever done." - icon_state = "glass_orange" /datum/glass_style/drinking_glass/navy_rum required_drink_type = /datum/reagent/consumable/ethanol/navy_rum @@ -187,7 +187,6 @@ name = "glass of yūyake" desc = "It's the saccharine essence of the 70s in a glass... the 1970s, that is!" icon = 'icons/obj/drinks/drinks.dmi' - icon_state = "glass_red" /datum/glass_style/drinking_glass/shochu required_drink_type = /datum/reagent/consumable/ethanol/shochu @@ -255,7 +254,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/hooch name = "Hooch" desc = "You've really hit rock bottom now... your liver packed its bags and left last night." - icon_state = "glass_brown2" /datum/glass_style/shot_glass/goldschlager required_drink_type = /datum/reagent/consumable/ethanol/goldschlager diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm index 36a8877b82018..938a3753dd3b4 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/coffee_tea.dm @@ -4,7 +4,6 @@ required_drink_type = /datum/reagent/consumable/coffee name = "glass of coffee" desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/tea required_drink_type = /datum/reagent/consumable/tea @@ -58,7 +57,6 @@ required_drink_type = /datum/reagent/consumable/hot_coco name = "glass of hot coco" desc = "A favorite winter drink to warm you up." - icon_state = "chocolateglass" drink_type = SUGAR | DAIRY /datum/glass_style/drinking_glass/italian_coco diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm index e788a589ad125..139f8a85929da 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/dairy.dm @@ -4,7 +4,6 @@ required_drink_type = /datum/reagent/consumable/milk name = "glass of milk" desc = "White and nutritious goodness!" - icon_state = "glass_white" drink_type = DAIRY | BREAKFAST /datum/glass_style/has_foodtype/juicebox/milk @@ -25,17 +24,14 @@ required_drink_type = /datum/reagent/consumable/soymilk name = "glass of soy milk" desc = "White and nutritious soy goodness!" - icon_state = "glass_white" /datum/glass_style/drinking_glass/cream required_drink_type = /datum/reagent/consumable/cream name = "glass of cream" desc = "Ewwww..." - icon_state = "glass_white" /datum/glass_style/drinking_glass/coconut_milk required_drink_type = /datum/reagent/consumable/coconut_milk name = "glass of coconut milk" desc = "The essence of the tropics, contained safely within a glass." icon = 'icons/obj/drinks/drinks.dmi' - icon_state = "glass_white" diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm index 6f837d8f51587..e7ecfa331faba 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/juices.dm @@ -4,7 +4,6 @@ required_drink_type = /datum/reagent/consumable/orangejuice name = "glass of orange juice" desc = "Vitamins! Yay!" - icon_state = "glass_orange" drink_type = FRUIT | BREAKFAST /datum/glass_style/has_foodtype/juicebox/orangejuice @@ -62,13 +61,11 @@ required_drink_type = /datum/reagent/consumable/tomatojuice name = "glass of tomato juice" desc = "Are you sure this is tomato juice?" - icon_state = "glass_red" /datum/glass_style/drinking_glass/limejuice required_drink_type = /datum/reagent/consumable/limejuice name = "glass of lime juice" desc = "A glass of sweet-sour lime juice." - icon_state = "glass_green" /datum/glass_style/drinking_glass/carrotjuice required_drink_type = /datum/reagent/consumable/carrotjuice @@ -80,19 +77,16 @@ required_drink_type = /datum/reagent/consumable/berryjuice name = "glass of berry juice" desc = "Berry juice. Or maybe it's jam. Who cares?" - icon_state = "berryjuice" /datum/glass_style/drinking_glass/poisonberryjuice required_drink_type = /datum/reagent/consumable/poisonberryjuice name = "glass of berry juice" desc = "Berry juice. Or maybe it's poison. Who cares?" - icon_state = "poisonberryjuice" /datum/glass_style/drinking_glass/watermelonjuice required_drink_type = /datum/reagent/consumable/watermelonjuice name = "glass of watermelon juice" desc = "A glass of watermelon juice." - icon_state = "glass_red" /datum/glass_style/drinking_glass/lemonjuice required_drink_type = /datum/reagent/consumable/lemonjuice @@ -116,43 +110,36 @@ required_drink_type = /datum/reagent/consumable/potato_juice name = "glass of potato juice" desc = "Bleh..." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/bungojuice required_drink_type = /datum/reagent/consumable/bungojuice name = "glass of bungo juice" desc = "Exotic! You feel like you are on vacation already." - icon_state = "glass_yellow" /datum/glass_style/drinking_glass/prunomix required_drink_type = /datum/reagent/consumable/prunomix name = "glass of pruno mixture" desc = "Fruit, sugar, yeast, and water pulped together into a pungent slurry." - icon_state = "glass_orange" /datum/glass_style/drinking_glass/aloejuice required_drink_type = /datum/reagent/consumable/aloejuice name = "glass of aloe juice" desc = "A healthy and refreshing juice." - icon_state = "glass_yellow" /datum/glass_style/drinking_glass/toechtauese_juice required_drink_type = /datum/reagent/consumable/toechtauese_juice name = "glass of töchtaüse juice" desc = "Raw, unadulterated töchtaüse juice. One swig will fill you with regrets." - icon_state = "toechtauese_syrup" /datum/glass_style/drinking_glass/toechtauese_syrup required_drink_type = /datum/reagent/consumable/toechtauese_syrup name = "glass of töchtaüse syrup" desc = "Not for drinking on its own." - icon_state = "toechtauese_syrup" /datum/glass_style/drinking_glass/cucumberjuice required_drink_type = /datum/reagent/consumable/cucumberjuice name = "glass of cucumber juice" desc = "A glass of cucumber juice." - icon_state = "glass_cucumber" // Effectively misc @@ -161,7 +148,6 @@ required_drink_type = /datum/reagent/consumable/menthol name = "glass of menthol" desc = "Tastes naturally minty, and imparts a very mild numbing sensation." - icon_state = "glass_green" /datum/glass_style/drinking_glass/grenadine required_drink_type = /datum/reagent/consumable/grenadine diff --git a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm index 67802b9af20c4..ee741191771d7 100644 --- a/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/drinks/glass_styles/mixed_alcohol.dm @@ -2,7 +2,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/bilk name = "glass of bilk" desc = "A brew of milk and beer. For those alcoholics who fear osteoporosis." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/threemileisland required_drink_type = /datum/reagent/consumable/ethanol/threemileisland @@ -400,7 +399,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/bacchus_blessing name = "Bacchus' Blessing" desc = "You didn't think it was possible for a liquid to be so utterly revolting. Are you sure about this...?" - icon_state = "glass_brown2" /datum/glass_style/drinking_glass/atomicbomb required_drink_type = /datum/reagent/consumable/ethanol/atomicbomb @@ -434,7 +432,6 @@ required_drink_type = /datum/reagent/consumable/ethanol/eggnog name = "eggnog" desc = "For enjoying the most wonderful time of the year." - icon_state = "glass_yellow" drink_type = FRUIT /datum/glass_style/has_foodtype/juicebox/eggnog @@ -461,25 +458,21 @@ required_drink_type = /datum/reagent/consumable/ethanol/triple_sec name = "Triple Sec" desc = "A glass of straight Triple Sec." - icon_state = "glass_orange" /datum/glass_style/drinking_glass/creme_de_menthe required_drink_type = /datum/reagent/consumable/ethanol/creme_de_menthe name = "Creme de Menthe" desc = "You can almost feel the first breath of spring just looking at it." - icon_state = "glass_green" /datum/glass_style/drinking_glass/creme_de_cacao required_drink_type = /datum/reagent/consumable/ethanol/creme_de_cacao name = "Creme de Cacao" desc = "A million hazing lawsuits and alcohol poisonings have started with this humble ingredient." - icon_state = "glass_brown" /datum/glass_style/drinking_glass/creme_de_coconut required_drink_type = /datum/reagent/consumable/ethanol/creme_de_coconut name = "Creme de Coconut" desc = "An unintimidating glass of coconut liqueur." - icon_state = "glass_white" /datum/glass_style/drinking_glass/quadruple_sec required_drink_type = /datum/reagent/consumable/ethanol/quadruple_sec @@ -787,7 +780,6 @@ /datum/glass_style/drinking_glass/mushi_kombucha required_drink_type = /datum/reagent/consumable/ethanol/mushi_kombucha name = "glass of mushi kombucha" - icon_state = "glass_orange" /datum/glass_style/drinking_glass/triumphal_arch required_drink_type = /datum/reagent/consumable/ethanol/triumphal_arch diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index e434161b03d70..2941e5ecd7d08 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -17,7 +17,6 @@ required_drink_type = /datum/reagent/blood name = "glass of tomato juice" desc = "Are you sure this is tomato juice?" - icon_state = "glass_red" // FEED ME /datum/reagent/blood/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user) diff --git a/icons/obj/drinks/drinks.dmi b/icons/obj/drinks/drinks.dmi index 4b966cb2db27568b97488286f19a2149b9ca09c7..5566cb09b2fb9a4f7fc72f8880945a84f62f8e94 100644 GIT binary patch literal 24901 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 U#(NQvZvfoCXP{B4_9*P%00@q>EC2ui diff --git a/icons/obj/medical/reagent_fillings.dmi b/icons/obj/medical/reagent_fillings.dmi index 0da57e714a52801d219f8f38d8c17e38f75ea202..163f41641ddc04396eee85a3b3ebe1b764f3bb5d 100644 GIT binary patch literal 9258 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 From c6d794180cb1e808f7b05ec09413192e9ae12ec2 Mon Sep 17 00:00:00 2001 From: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Date: Sat, 9 Nov 2024 15:41:57 +0530 Subject: [PATCH 14/23] Update README.md of unit tests folder for VS code support (#87758) ## About The Pull Request Turns out using dream daemon isn't the only way to run unit tests. You can do it from VS code itself & can see the output of each test in the fancy chat window. ![Screenshot (448)](https://github.com/user-attachments/assets/33aca6b5-3414-4560-9cc4-dd90fe80e2d1) With the added advantage of using your debugger to step through each line of code this should be the preferred way so I've updated the read me file of the unit tests folder to specify that You can also check the runtimes log in your game to see the output of each unit test ## Changelog :cl: N/A /:cl: --- code/modules/unit_tests/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/modules/unit_tests/README.md b/code/modules/unit_tests/README.md index 9fe97b8b16dd8..d53a6eb958694 100644 --- a/code/modules/unit_tests/README.md +++ b/code/modules/unit_tests/README.md @@ -39,7 +39,14 @@ Open `code/_compile_options.dm` and uncomment the following line. //#define UNIT_TESTS //If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between ``` -Then, run tgstation.dmb in Dream Daemon. Don't bother trying to connect, you won't need to. You'll be able to see the outputs of all the tests. You'll get to see which tests failed and for what reason. If they all pass, you're set! +There are 3 ways to run unit tests + +- Run tgstation.dmb in Dream Daemon. Don't bother trying to connect, you won't need to. You'll be able to see the outputs of all the tests. You'll get to see which tests failed and for what reason. If they all pass, you're set! + +- Launch game from VS Code. Launch the game as normal & you will see the output of your unit tests in your fancy chat window. This is preferred as you can use the debugger to step through each line of your unit test & can use the games inbuilt debugging tools to further aid in testing + +- Use VS Code Tgstation Test Explorer Extension. This allows you to run tests without launching the game & can also run focused tests(either a single or a selected group) + ## How to think about tests From 6f88740cc1b34208f55ec8fc3feca4c4bbff9d8c Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:14:23 +0000 Subject: [PATCH 15/23] Automatic changelog for PR #87759 [ci skip] --- html/changelogs/AutoChangeLog-pr-87759.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87759.yml diff --git a/html/changelogs/AutoChangeLog-pr-87759.yml b/html/changelogs/AutoChangeLog-pr-87759.yml new file mode 100644 index 0000000000000..612020fc7e78c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87759.yml @@ -0,0 +1,4 @@ +author: "harryob" +delete-after: True +changes: + - bugfix: "the abductor console now correctly loads images of equipment" \ No newline at end of file From 1b21f7afbc2ba8579f6b5eb17b0637ee6e1348c5 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:15:18 +0000 Subject: [PATCH 16/23] Automatic changelog for PR #87749 [ci skip] --- html/changelogs/AutoChangeLog-pr-87749.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87749.yml diff --git a/html/changelogs/AutoChangeLog-pr-87749.yml b/html/changelogs/AutoChangeLog-pr-87749.yml new file mode 100644 index 0000000000000..bf27ebeb9319e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87749.yml @@ -0,0 +1,4 @@ +author: "timothymtorres" +delete-after: True +changes: + - admin: "Admins can now add/remove TRAIT_EVIL from mobs." \ No newline at end of file From b8b495db710f8d838bbb2a6ee0e383ad4938f0d5 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:16:01 +0000 Subject: [PATCH 17/23] Automatic changelog for PR #87741 [ci skip] --- html/changelogs/AutoChangeLog-pr-87741.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87741.yml diff --git a/html/changelogs/AutoChangeLog-pr-87741.yml b/html/changelogs/AutoChangeLog-pr-87741.yml new file mode 100644 index 0000000000000..e27aee03b3bf4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87741.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Fixed wings and jetpacks sometimes preventing you from opening doors" \ No newline at end of file From 8df7f4ec2f7a8a389ad266e0d4c783601cbd0c40 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:16:05 +0000 Subject: [PATCH 18/23] Automatic changelog for PR #87756 [ci skip] --- html/changelogs/AutoChangeLog-pr-87756.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87756.yml diff --git a/html/changelogs/AutoChangeLog-pr-87756.yml b/html/changelogs/AutoChangeLog-pr-87756.yml new file mode 100644 index 0000000000000..a5c9f801d186e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87756.yml @@ -0,0 +1,4 @@ +author: "OrionTheFox" +delete-after: True +changes: + - image: "redid most basic drinking glass sprites, and moved several drinks to use the same color system as beakers. Please bug report any incorrect colored drinks or juices!" \ No newline at end of file From a32c6f7e3228755fa1790eef89766095f6a0a115 Mon Sep 17 00:00:00 2001 From: grungussuss <96586172+Sadboysuss@users.noreply.github.com> Date: Sat, 9 Nov 2024 13:16:12 +0300 Subject: [PATCH 19/23] the glove sounds are now only on some gloves [no gbp] (#87489) ## About The Pull Request mistakes were made ## Why It's Good For The Game god it's horrible, not only is it happening way too often because it's every glove, but also it doesn't fit any other glove other than insuls really, maybe nitriles but gosh just get rid of it for now, maybe later I will make a better sound for other gloves. ## Changelog :cl: grungussuss sound: only insulated,nitrile, enhanced retrieval, latex, boxing, improvised gripper gloves have an equip sound /:cl: --- code/modules/clothing/gloves/_gloves.dm | 1 - code/modules/clothing/gloves/boxing.dm | 1 + code/modules/clothing/gloves/insulated.dm | 1 + code/modules/clothing/gloves/plasmaman.dm | 1 + code/modules/clothing/gloves/special.dm | 1 + code/modules/clothing/gloves/tacklers.dm | 1 + 6 files changed, 5 insertions(+), 1 deletion(-) diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index 418f8358f4d2a..7d990e1ace50a 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -12,7 +12,6 @@ siemens_coefficient = 0.5 body_parts_covered = HANDS slot_flags = ITEM_SLOT_GLOVES - equip_sound = 'sound/items/equip/glove_equip.ogg' drop_sound = 'sound/items/handling/glove_drop.ogg' pickup_sound = 'sound/items/handling/glove_pick_up.ogg' attack_verb_continuous = list("challenges") diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm index ab6e03ae493d2..3c8edb4de730f 100644 --- a/code/modules/clothing/gloves/boxing.dm +++ b/code/modules/clothing/gloves/boxing.dm @@ -6,6 +6,7 @@ equip_delay_other = 60 species_exception = list(/datum/species/golem) // now you too can be a golem boxing champion clothing_traits = list(TRAIT_CHUNKYFINGERS) + equip_sound = 'sound/items/equip/glove_equip.ogg' /// Determines the version of boxing (or any martial art for that matter) that the boxing gloves gives var/style_to_give = /datum/martial_art/boxing diff --git a/code/modules/clothing/gloves/insulated.dm b/code/modules/clothing/gloves/insulated.dm index c7acc7f87e287..10791ad09f762 100644 --- a/code/modules/clothing/gloves/insulated.dm +++ b/code/modules/clothing/gloves/insulated.dm @@ -13,6 +13,7 @@ custom_price = PAYCHECK_CREW * 10 custom_premium_price = PAYCHECK_COMMAND * 6 cut_type = /obj/item/clothing/gloves/cut + equip_sound = 'sound/items/equip/glove_equip.ogg' /obj/item/clothing/gloves/color/yellow/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/gloves/plasmaman.dm b/code/modules/clothing/gloves/plasmaman.dm index d429ab10fd841..36fd467282b6b 100644 --- a/code/modules/clothing/gloves/plasmaman.dm +++ b/code/modules/clothing/gloves/plasmaman.dm @@ -9,6 +9,7 @@ max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT resistance_flags = NONE armor_type = /datum/armor/color_plasmaman + equip_sound = 'sound/items/equip/glove_equip.ogg' /datum/armor/color_plasmaman bio = 100 diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm index 7a005fe7fc313..09df92bb8c4f2 100644 --- a/code/modules/clothing/gloves/special.dm +++ b/code/modules/clothing/gloves/special.dm @@ -115,6 +115,7 @@ armor_type = /datum/armor/latex_gloves clothing_traits = list(TRAIT_QUICK_CARRY) resistance_flags = NONE + equip_sound = 'sound/items/equip/glove_equip.ogg' /datum/armor/latex_gloves bio = 100 diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm index ce3db5ab6547b..9564c20bfde78 100644 --- a/code/modules/clothing/gloves/tacklers.dm +++ b/code/modules/clothing/gloves/tacklers.dm @@ -8,6 +8,7 @@ resistance_flags = NONE custom_premium_price = PAYCHECK_COMMAND * 3.5 clothing_traits = list(TRAIT_FINGERPRINT_PASSTHROUGH,TRAIT_FAST_CUFFING) + equip_sound = 'sound/items/equip/glove_equip.ogg' /// For storing our tackler datum so we can remove it after var/datum/component/tackler /// See: [/datum/component/tackler/var/stamina_cost] From 27d9f99901279f2e0b02d33b2d745a1b62015524 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:17:02 +0000 Subject: [PATCH 20/23] Automatic changelog for PR #87489 [ci skip] --- html/changelogs/AutoChangeLog-pr-87489.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87489.yml diff --git a/html/changelogs/AutoChangeLog-pr-87489.yml b/html/changelogs/AutoChangeLog-pr-87489.yml new file mode 100644 index 0000000000000..8ad3a9a7489c0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87489.yml @@ -0,0 +1,4 @@ +author: "grungussuss" +delete-after: True +changes: + - sound: "only insulated,nitrile, enhanced retrieval, latex, boxing, improvised gripper gloves have an equip sound" \ No newline at end of file From bf2a1b788747c20d81741f3ceb0b6011eb6fcb48 Mon Sep 17 00:00:00 2001 From: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Date: Sat, 9 Nov 2024 12:43:25 +0200 Subject: [PATCH 21/23] hunting behaviors no longer share a cooldown (#87670) ## About The Pull Request all hunting subtrees were sharing a singular cooldown. this makes it so each subtree has its own cooldown ## Why It's Good For The Game fixes hunting subtree cooldowns affecting other subtrees. ## Changelog :cl: /:cl: --- code/__DEFINES/ai/ai_blackboard.dm | 8 +++++--- .../ai/hunting_behavior/hunting_behaviors.dm | 15 +++++---------- .../mob/living/basic/slime/ai/pet_command.dm | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 24461464c3e03..b5a7ad1ddfaac 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -49,11 +49,13 @@ #define BB_BANE_BATMAN "BB_bane_batman" //yep that's it -///Hunting BB keys +//Hunting BB keys +///key that holds our current hunting target #define BB_CURRENT_HUNTING_TARGET "BB_current_hunting_target" +///key that holds our less priority hunting target #define BB_LOW_PRIORITY_HUNTING_TARGET "BB_low_priority_hunting_target" -#define BB_HUNTING_COOLDOWN "BB_HUNTING_COOLDOWN" - +///key that holds the cooldown for our hunting subtree +#define BB_HUNTING_COOLDOWN(type) "BB_HUNTING_COOLDOWN_[type]" ///Basic Mob Keys ///Targeting subtrees diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index 0ab14ff0d3209..db684921281a7 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -26,16 +26,11 @@ /datum/ai_planning_subtree/find_and_hunt_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) if(!SPT_PROB(hunt_chance, seconds_per_tick)) return - if(controller.blackboard[BB_HUNTING_COOLDOWN] >= world.time) - return - var/mob/living/living_pawn = controller.pawn - // We can't hunt if we're indisposed - if(HAS_TRAIT(controller.pawn, TRAIT_HANDS_BLOCKED) || living_pawn.stat != CONSCIOUS) + + if(controller.blackboard[BB_HUNTING_COOLDOWN(type)] >= world.time) return - var/atom/hunted = controller.blackboard[target_key] - // We're not hunting anything, look around for something - if(isnull(hunted)) + if(!controller.blackboard_key_exists(target_key)) controller.queue_behavior(finding_behavior, target_key, hunt_targets, hunt_range) return @@ -44,7 +39,7 @@ // we may accidentally be executing another tree's hunt - not ideal, // try to set a unique target key if you have multiple - controller.queue_behavior(hunting_behavior, target_key, BB_HUNTING_COOLDOWN) + controller.queue_behavior(hunting_behavior, target_key, BB_HUNTING_COOLDOWN(type)) if(finish_planning) return SUBTREE_RETURN_FINISH_PLANNING //If we're hunting we're too busy for anything else @@ -115,7 +110,7 @@ /datum/ai_behavior/hunt_target/finish_action(datum/ai_controller/controller, succeeded, hunting_target_key, hunting_cooldown_key) . = ..() - if(succeeded) + if(succeeded && hunting_cooldown_key) controller.set_blackboard_key(hunting_cooldown_key, world.time + hunt_cooldown) else if(hunting_target_key) controller.clear_blackboard_key(hunting_target_key) diff --git a/code/modules/mob/living/basic/slime/ai/pet_command.dm b/code/modules/mob/living/basic/slime/ai/pet_command.dm index 33484e360fbed..211d7aa552cd8 100644 --- a/code/modules/mob/living/basic/slime/ai/pet_command.dm +++ b/code/modules/mob/living/basic/slime/ai/pet_command.dm @@ -10,7 +10,7 @@ var/mob/living/basic/slime/slime_pawn = controller.pawn if(isslime(slime_pawn) && slime_pawn.can_feed_on(controller.blackboard[BB_CURRENT_PET_TARGET], check_friendship = TRUE)) - controller.queue_behavior(hunting_behavior, BB_CURRENT_PET_TARGET, BB_HUNTING_COOLDOWN) + controller.queue_behavior(hunting_behavior, BB_CURRENT_PET_TARGET) return SUBTREE_RETURN_FINISH_PLANNING return ..() From d5daa9c9b80d94fda30dea054f36fcc9789bfc96 Mon Sep 17 00:00:00 2001 From: tonty <39193182+tontyGH@users.noreply.github.com> Date: Sat, 9 Nov 2024 05:57:45 -0500 Subject: [PATCH 22/23] [NO GBP] Renames mob/camera to mob/eye and makes everything follow suit (#87684) ## Why It's Good For The Game Clarity and consistency regarding DM's systems. Internally, `eye` is used for anything that controls the client's view. ![image](https://github.com/user-attachments/assets/7d1291e1-7a6a-4736-a14b-97834e89846f) How `eye` is used in DM is consistent with how we use the term, so I figured this would add clarity. Being named mob/camera also makes it unclear exactly what it's doing. The name implies that it would function similar to how mob/camera/ai_eye does, but most of the time it's only used as... an eye. My ulterior reason for this PR is that I want to clean up mob/camera/ai_eye and it's subtypes after this. ## Changelog :cl: server: mob/camera has been renamed to mob/eye, which may break downstreams /:cl: --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- .github/guides/ISSUE_MANAGER.md | 8 +- code/__DEFINES/dcs/signals/signals_blob.dm | 2 +- code/__DEFINES/dcs/signals/signals_reagent.dm | 2 +- code/__DEFINES/is_helpers.dm | 8 +- code/__HELPERS/mobs.dm | 2 +- code/__HELPERS/paths/path.dm | 2 +- code/__HELPERS/roundend.dm | 4 +- code/_onclick/hud/blob_overmind.dm | 20 ++--- code/_onclick/overmind.dm | 8 +- .../subsystem/points_of_interest.dm | 2 +- code/controllers/subsystem/ticker.dm | 2 +- code/datums/brain_damage/imaginary_friend.dm | 74 +++++++++--------- code/datums/components/blob_minion.dm | 10 +-- code/datums/components/lock_on_cursor.dm | 2 +- code/datums/holocall.dm | 4 +- code/game/atoms_movable.dm | 2 +- code/game/data_huds.dm | 2 +- .../machinery/computer/camera_advanced.dm | 22 +++--- code/game/machinery/launch_pad.dm | 2 +- .../effects/anomalies/anomalies_bluespace.dm | 2 +- .../effects/temporary_visuals/effect_trail.dm | 2 +- code/game/objects/items/devices/multitool.dm | 4 +- .../construction_actions.dm | 2 +- .../construction_console.dm | 12 +-- .../structures/crates_lockers/closets.dm | 2 +- .../admin/smites/imaginary_friend_special.dm | 4 +- .../antagonists/abductor/machinery/camera.dm | 8 +- code/modules/antagonists/blob/blob_antag.dm | 8 +- code/modules/antagonists/blob/blob_minion.dm | 4 +- .../blob/blobstrains/_blobstrain.dm | 6 +- .../antagonists/blob/blobstrains/_reagent.dm | 6 +- .../blob/blobstrains/blazing_oil.dm | 2 +- .../blob/blobstrains/cryogenic_poison.dm | 2 +- .../blob/blobstrains/debris_devourer.dm | 2 +- .../blob/blobstrains/distributed_neurons.dm | 2 +- .../blob/blobstrains/electromagnetic_web.dm | 2 +- .../blob/blobstrains/energized_jelly.dm | 2 +- .../blob/blobstrains/explosive_lattice.dm | 6 +- .../antagonists/blob/blobstrains/multiplex.dm | 4 +- .../blob/blobstrains/networked_fibers.dm | 4 +- .../blob/blobstrains/pressurized_slime.dm | 2 +- .../blob/blobstrains/reactive_spines.dm | 4 +- .../blob/blobstrains/regenerative_materia.dm | 2 +- .../blob/blobstrains/replicating_foam.dm | 4 +- .../blob/blobstrains/shifting_fragments.dm | 4 +- .../blob/blobstrains/synchronous_mesh.dm | 2 +- code/modules/antagonists/blob/overmind.dm | 48 ++++++------ code/modules/antagonists/blob/powers.dm | 40 +++++----- .../antagonists/blob/structures/_blob.dm | 6 +- code/modules/cargo/supplypod.dm | 2 +- code/modules/events/ghost_role/blob.dm | 2 +- code/modules/forensics/_forensics.dm | 8 +- code/modules/mob/dead/observer/observer.dm | 4 +- code/modules/mob/dead/observer/orbit.dm | 4 +- code/modules/mob/emote.dm | 10 +-- .../mob/{camera/camera.dm => eye/eye.dm} | 22 +++--- .../mob/living/basic/blob_minions/blob_mob.dm | 2 +- .../living/basic/blob_minions/blob_spore.dm | 2 +- .../living/basic/blob_minions/blobbernaut.dm | 2 +- code/modules/mob/living/silicon/ai/ai.dm | 4 +- .../living/silicon/ai/freelook/cameranet.dm | 2 +- .../mob/living/silicon/ai/freelook/chunk.dm | 10 +-- .../mob/living/silicon/ai/freelook/eye.dm | 30 +++---- .../modules/mob/living/silicon/ai/multicam.dm | 18 ++--- .../mob/living/simple_animal/bot/mulebot.dm | 4 +- code/modules/mob/transform_procs.dm | 2 +- code/modules/reagents/chemistry/recipes.dm | 4 +- .../research/xenobiology/xenobio_camera.dm | 40 +++++----- code/modules/shuttle/navigation_computer.dm | 28 +++---- code/modules/shuttle/supply.dm | 2 +- code/modules/transport/transport_module.dm | 2 +- code/modules/unit_tests/mob_faction.dm | 6 +- code/modules/unit_tests/unit_test.dm | 6 +- .../vehicles/mecha/mecha_ai_interaction.dm | 2 +- .../mob/{silicon/cameramob.dmi => eyemob.dmi} | Bin tgstation.dme | 2 +- 76 files changed, 298 insertions(+), 298 deletions(-) rename code/modules/mob/{camera/camera.dm => eye/eye.dm} (71%) rename icons/mob/{silicon/cameramob.dmi => eyemob.dmi} (100%) diff --git a/.github/guides/ISSUE_MANAGER.md b/.github/guides/ISSUE_MANAGER.md index c0ef14ae0cc7b..3ecab32a7f523 100644 --- a/.github/guides/ISSUE_MANAGER.md +++ b/.github/guides/ISSUE_MANAGER.md @@ -15,10 +15,10 @@ When examining new issues you should immediately notify a maintainer if you see - **Server Lagging** [[1]](https://github.com/tgstation/tgstation/issues/60193) [[2]](https://github.com/tgstation/tgstation/issues/51927) [[3]](https://github.com/tgstation/tgstation/issues/32762) - Something that is causing a _severe_ amount of lag during the game #### Runtime Issue Reports -If an issue reports a runtime, it must have the actual runtime call stack provided by round logging or in-game debug menu (https://github.com/tgstation/tgstation/issues/70329#issuecomment-1279853883). +If an issue reports a runtime, it must have the actual runtime call stack provided by round logging or in-game debug menu (https://github.com/tgstation/tgstation/issues/70329#issuecomment-1279853883).
Example runtime call stack - + ``` [2022-10-15 16:12:38.902] runtime error: Cannot execute null.add(). - proc name: visibility (/datum/cameranet/proc/visibility) @@ -28,8 +28,8 @@ If an issue reports a runtime, it must have the actual runtime call stack provid - usr.loc: the floor (150,25,4) (/turf/open/floor/circuit) - call stack: - Camera Net (/datum/cameranet): visibility(/list (/list), null, /list (/list), 1) - - AI (/mob/living/silicon/ai): camera visibility(Inactive AI Eye (/mob/camera/ai_eye)) - - Inactive AI Eye (/mob/camera/ai_eye): setLoc(the floor (150,25,4) (/turf/open/floor/circuit), 0) + - AI (/mob/living/silicon/ai): camera visibility(Inactive AI Eye (/mob/eye/ai_eye)) + - Inactive AI Eye (/mob/eye/ai_eye): setLoc(the floor (150,25,4) (/turf/open/floor/circuit), 0) - AI (/mob/living/silicon/ai): create eye() - AI (/mob/living/silicon/ai): Initialize(0, null, TagGamerGame2 (/mob/dead/new_player)) - Atoms (/datum/controller/subsystem/atoms): InitAtom(AI (/mob/living/silicon/ai), 0, /list (/list)) diff --git a/code/__DEFINES/dcs/signals/signals_blob.dm b/code/__DEFINES/dcs/signals/signals_blob.dm index afd4737bdd968..dac33906a3f6d 100644 --- a/code/__DEFINES/dcs/signals/signals_blob.dm +++ b/code/__DEFINES/dcs/signals/signals_blob.dm @@ -1,4 +1,4 @@ -/// Signal sent when a blob overmind picked a new strain (/mob/camera/blob/overmind, /datum/blobstrain/new_strain) +/// Signal sent when a blob overmind picked a new strain (/mob/eye/blob/overmind, /datum/blobstrain/new_strain) #define COMSIG_BLOB_SELECTED_STRAIN "blob_selected_strain" /// Signal sent by a blob spore when it creates a zombie (/mob/living/basic/blob_minion/spore/spore, //mob/living/basic/blob_minion/zombie/zombie) #define COMSIG_BLOB_ZOMBIFIED "blob_zombified" diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 367ec946361d0..78b4cec5ca075 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -14,7 +14,7 @@ #define COMSIG_REAGENT_EXPOSE_ATOM "reagent_expose_atom" ///from base of [/datum/reagent/proc/expose_atom]: (/obj, reac_volume) #define COMSIG_REAGENT_EXPOSE_OBJ "reagent_expose_obj" -///from base of [/datum/reagent/proc/expose_atom]: (/mob/living, reac_volume, methods, show_message, touch_protection, /mob/camera/blob) // ovemind arg is only used by blob reagents. +///from base of [/datum/reagent/proc/expose_atom]: (/mob/living, reac_volume, methods, show_message, touch_protection, /mob/eye/blob) // ovemind arg is only used by blob reagents. #define COMSIG_REAGENT_EXPOSE_MOB "reagent_expose_mob" ///from base of [/datum/reagent/proc/expose_atom]: (/turf, reac_volume) #define COMSIG_REAGENT_EXPOSE_TURF "reagent_expose_turf" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index dc51fdd68dd4d..5b3d50cdadd17 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -210,13 +210,13 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list( #define isnewplayer(A) (istype(A, /mob/dead/new_player)) -#define isovermind(A) (istype(A, /mob/camera/blob)) +#define isovermind(A) (istype(A, /mob/eye/blob)) -#define issentientdisease(A) (istype(A, /mob/camera/disease)) +#define issentientdisease(A) (istype(A, /mob/eye/disease)) -#define iscameramob(A) (istype(A, /mob/camera)) +#define iseyemob(A) (istype(A, /mob/eye)) -#define isaicamera(A) (istype(A, /mob/camera/ai_eye)) +#define isaicamera(A) (istype(A, /mob/eye/ai_eye)) //Objects #define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 92ebff1cc4e29..f3a2e4bd375b9 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -561,7 +561,7 @@ GLOBAL_LIST_INIT(skin_tone_names, list( var/list/sortmob = sort_names(GLOB.mob_list) for(var/mob/living/silicon/ai/mob_to_sort in sortmob) moblist += mob_to_sort - for(var/mob/camera/mob_to_sort in sortmob) + for(var/mob/eye/mob_to_sort in sortmob) moblist += mob_to_sort for(var/mob/living/silicon/pai/mob_to_sort in sortmob) moblist += mob_to_sort diff --git a/code/__HELPERS/paths/path.dm b/code/__HELPERS/paths/path.dm index 9530a5452351a..950cd1906846c 100644 --- a/code/__HELPERS/paths/path.dm +++ b/code/__HELPERS/paths/path.dm @@ -346,7 +346,7 @@ src.can_ventcrawl = HAS_TRAIT(living_construct, TRAIT_VENTCRAWLER_ALWAYS) || HAS_TRAIT(living_construct, TRAIT_VENTCRAWLER_NUDE) src.mob_size = living_construct.mob_size src.incorporeal_move = living_construct.incorporeal_move - if(iscameramob(construct_from)) + if(iseyemob(construct_from)) src.camera_type = construct_from.type src.is_bot = isbot(construct_from) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 72af6cf3ac181..292639f387682 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -12,7 +12,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list()) var/json_file = file("[GLOB.log_directory]/round_end_data.json") // All but npcs sublists and ghost category contain only mobs with minds var/list/file_data = list("escapees" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "abandoned" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "ghosts" = list(), "additional data" = list()) - var/num_survivors = 0 //Count of non-brain non-camera mobs with mind that are alive + var/num_survivors = 0 //Count of non-brain non-eye mobs with mind that are alive var/num_escapees = 0 //Above and on centcom z var/num_shuttle_escapees = 0 //Above and on escape shuttle var/list/area/shuttle_areas @@ -32,7 +32,7 @@ GLOBAL_LIST_INIT(achievements_unlocked, list()) if(M.mind) count_only = FALSE mob_data["ckey"] = M.mind.key - if(M.stat != DEAD && !isbrain(M) && !iscameramob(M)) + if(M.stat != DEAD && !isbrain(M) && !iseyemob(M)) num_survivors++ if(EMERGENCY_ESCAPED_OR_ENDGAMED && (M.onCentCom() || M.onSyndieBase())) num_escapees++ diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index be860caa1f024..8f8193a50451e 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -17,7 +17,7 @@ /atom/movable/screen/blob/jump_to_node/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.jump_to_node() /atom/movable/screen/blob/jump_to_core @@ -27,7 +27,7 @@ /atom/movable/screen/blob/jump_to_core/MouseEntered(location,control,params) if(hud?.mymob && isovermind(hud.mymob)) - var/mob/camera/blob/B = hud.mymob + var/mob/eye/blob/B = hud.mymob if(!B.placed) name = "Place Blob Core" desc = "Attempt to place your blob core at this location." @@ -39,7 +39,7 @@ /atom/movable/screen/blob/jump_to_core/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr if(!blob.placed) blob.place_blob_core(BLOB_NORMAL_PLACEMENT) blob.transport_core() @@ -58,7 +58,7 @@ /atom/movable/screen/blob/blobbernaut/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_blobbernaut() /atom/movable/screen/blob/resource_blob @@ -75,7 +75,7 @@ /atom/movable/screen/blob/resource_blob/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_special(BLOB_STRUCTURE_RESOURCE_COST, /obj/structure/blob/special/resource, BLOB_RESOURCE_MIN_DISTANCE, TRUE) /atom/movable/screen/blob/node_blob @@ -92,7 +92,7 @@ /atom/movable/screen/blob/node_blob/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_special(BLOB_STRUCTURE_NODE_COST, /obj/structure/blob/special/node, BLOB_NODE_MIN_DISTANCE, FALSE) /atom/movable/screen/blob/factory_blob @@ -109,7 +109,7 @@ /atom/movable/screen/blob/factory_blob/Click() if(!isovermind(usr)) return FALSE - var/mob/camera/blob/blob = usr + var/mob/eye/blob/blob = usr blob.create_special(BLOB_STRUCTURE_FACTORY_COST, /obj/structure/blob/special/factory, BLOB_FACTORY_MIN_DISTANCE, TRUE) /atom/movable/screen/blob/readapt_strain @@ -120,7 +120,7 @@ /atom/movable/screen/blob/readapt_strain/MouseEntered(location,control,params) if(hud?.mymob && isovermind(hud.mymob)) - var/mob/camera/blob/B = hud.mymob + var/mob/eye/blob/B = hud.mymob if(B.free_strain_rerolls) name = "[initial(name)] (FREE)" desc = "Randomly rerolls your strain for free." @@ -131,7 +131,7 @@ /atom/movable/screen/blob/readapt_strain/Click() if(isovermind(usr)) - var/mob/camera/blob/B = usr + var/mob/eye/blob/B = usr B.strain_reroll() /atom/movable/screen/blob/relocate_core @@ -147,7 +147,7 @@ /atom/movable/screen/blob/relocate_core/Click() if(isovermind(usr)) - var/mob/camera/blob/B = usr + var/mob/eye/blob/B = usr B.relocate_core() /datum/hud/blob_overmind/New(mob/owner) diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm index 900ad59bde2e4..a9d8dba6e13ff 100644 --- a/code/_onclick/overmind.dm +++ b/code/_onclick/overmind.dm @@ -1,7 +1,7 @@ // Blob Overmind Controls -/mob/camera/blob/ClickOn(atom/A, params) //Expand blob +/mob/eye/blob/ClickOn(atom/A, params) //Expand blob var/list/modifiers = params2list(params) if(LAZYACCESS(modifiers, MIDDLE_CLICK)) MiddleClickOn(A, params) @@ -19,18 +19,18 @@ if(T) expand_blob(T) -/mob/camera/blob/MiddleClickOn(atom/A) //Rally spores +/mob/eye/blob/MiddleClickOn(atom/A) //Rally spores . = ..() var/turf/T = get_turf(A) if(T) rally_spores(T) -/mob/camera/blob/CtrlClickOn(atom/A) //Create a shield +/mob/eye/blob/CtrlClickOn(atom/A) //Create a shield var/turf/T = get_turf(A) if(T) create_shield(T) -/mob/camera/blob/proc/blob_click_alt(atom/A) //Remove a blob +/mob/eye/blob/proc/blob_click_alt(atom/A) //Remove a blob var/turf/T = get_turf(A) if(T) remove_blob(T) diff --git a/code/controllers/subsystem/points_of_interest.dm b/code/controllers/subsystem/points_of_interest.dm index 4280d747b6106..7bec303d66a61 100644 --- a/code/controllers/subsystem/points_of_interest.dm +++ b/code/controllers/subsystem/points_of_interest.dm @@ -225,7 +225,7 @@ SUBSYSTEM_DEF(points_of_interest) /datum/point_of_interest/mob_poi/proc/get_type_sort_priority() if(isAI(target)) return 0 - if(iscameramob(target)) + if(iseyemob(target)) return 1 if(ispAI(target)) return 2 diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index aaca3ef1d574c..bb18a45b72d9a 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -628,7 +628,7 @@ SUBSYSTEM_DEF(ticker) if(STATION_NUKED) // There was a blob on board, guess it was nuked to stop it if(length(GLOB.overminds)) - for(var/mob/camera/blob/overmind as anything in GLOB.overminds) + for(var/mob/eye/blob/overmind as anything in GLOB.overminds) if(overmind.max_count < overmind.announcement_size) continue diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index ad60f6cd9a6a5..6945648a73467 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -9,7 +9,7 @@ scan_desc = "partial schizophrenia" gain_text = span_notice("You feel in good company, for some reason.") lose_text = span_warning("You feel lonely again.") - var/mob/camera/imaginary_friend/friend + var/mob/eye/imaginary_friend/friend var/friend_initialized = FALSE /datum/brain_trauma/special/imaginary_friend/on_gain() @@ -76,7 +76,7 @@ friend.log_message("became [key_name(owner)]'s split personality.", LOG_GAME) message_admins("[ADMIN_LOOKUPFLW(friend)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.") -/mob/camera/imaginary_friend +/mob/eye/imaginary_friend name = "imaginary friend" real_name = "imaginary friend" move_on_shuttle = TRUE @@ -96,7 +96,7 @@ /// Whether our host and other imaginary friends can hear us only when nearby or practically anywhere. var/extended_message_range = TRUE -/mob/camera/imaginary_friend/Login() +/mob/eye/imaginary_friend/Login() . = ..() if(!. || !client) return FALSE @@ -104,7 +104,7 @@ greet() Show() -/mob/camera/imaginary_friend/proc/greet() +/mob/eye/imaginary_friend/proc/greet() to_chat(src, span_notice("You are the imaginary friend of [owner]!")) to_chat(src, span_notice("You are absolutely loyal to your friend, no matter what.")) to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what [owner] cannot.")) @@ -114,7 +114,7 @@ * * imaginary_friend_owner - The living mob that owns the imaginary friend. * * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on these prefs. */ -/mob/camera/imaginary_friend/Initialize(mapload) +/mob/eye/imaginary_friend/Initialize(mapload) . = ..() var/static/list/grantable_actions = list( /datum/action/innate/imaginary_join, @@ -123,7 +123,7 @@ grant_actions_by_list(grantable_actions) /// Links this imaginary friend to the provided mob -/mob/camera/imaginary_friend/proc/attach_to_owner(mob/living/imaginary_friend_owner) +/mob/eye/imaginary_friend/proc/attach_to_owner(mob/living/imaginary_friend_owner) owner = imaginary_friend_owner if(!owner.imaginary_group) owner.imaginary_group = list(owner) @@ -131,14 +131,14 @@ greet() /// Copies appearance from passed player prefs, or randomises them if none are provided -/mob/camera/imaginary_friend/proc/setup_appearance(datum/preferences/appearance_from_prefs = null) +/mob/eye/imaginary_friend/proc/setup_appearance(datum/preferences/appearance_from_prefs = null) if(appearance_from_prefs) INVOKE_ASYNC(src, PROC_REF(setup_friend_from_prefs), appearance_from_prefs) else INVOKE_ASYNC(src, PROC_REF(setup_friend)) /// Randomise friend name and appearance -/mob/camera/imaginary_friend/proc/setup_friend() +/mob/eye/imaginary_friend/proc/setup_friend() gender = pick(MALE, FEMALE) real_name = generate_random_name_species_based(gender, FALSE, /datum/species/human) name = real_name @@ -151,7 +151,7 @@ * Arguments: * * appearance_from_prefs - If this is a valid set of prefs, the appearance of the imaginary friend is based on the currently selected character in them. Otherwise, it's random. */ -/mob/camera/imaginary_friend/proc/setup_friend_from_prefs(datum/preferences/appearance_from_prefs) +/mob/eye/imaginary_friend/proc/setup_friend_from_prefs(datum/preferences/appearance_from_prefs) if(!istype(appearance_from_prefs)) stack_trace("Attempted to create imaginary friend appearance from null prefs. Using random appearance.") setup_friend() @@ -181,14 +181,14 @@ Show() /// Returns all member clients of the imaginary_group -/mob/camera/imaginary_friend/proc/group_clients() +/mob/eye/imaginary_friend/proc/group_clients() var/group_clients = list() for(var/mob/person as anything in owner.imaginary_group) if(person.client) group_clients += person.client return group_clients -/mob/camera/imaginary_friend/proc/Show() +/mob/eye/imaginary_friend/proc/Show() if(!client || !owner) //nobody home return @@ -209,7 +209,7 @@ src.client.images |= current_image -/mob/camera/imaginary_friend/Destroy() +/mob/eye/imaginary_friend/Destroy() if(owner?.client) owner.client.images.Remove(human_image) if(client) @@ -217,12 +217,12 @@ owner.imaginary_group -= src return ..() -/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) +/mob/eye/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) if (safe_read_pref(client, /datum/preference/toggle/enable_runechat) && (safe_read_pref(client, /datum/preference/toggle/enable_runechat_non_mobs) || ismob(speaker))) create_chat_message(speaker, message_language, raw_message, spans) to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mods)) -/mob/camera/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null) +/mob/eye/imaginary_friend/send_speech(message, range = IMAGINARY_FRIEND_SPEECH_RANGE, obj/source = src, bubble_type = bubble_icon, list/spans = list(), datum/language/message_language = null, list/message_mods = list(), forced = null) message = get_message_mods(message, message_mods) message = capitalize(message) @@ -296,16 +296,16 @@ var/link = FOLLOW_LINK(dead_player, owner) to_chat(dead_player, "[link] [dead_rendered]") -/mob/camera/imaginary_friend/proc/clear_saypopup(image/say_popup) +/mob/eye/imaginary_friend/proc/clear_saypopup(image/say_popup) LAZYREMOVE(update_on_z, say_popup) -/mob/camera/imaginary_friend/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced, filterproof) +/mob/eye/imaginary_friend/whisper(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language, ignore_spam = FALSE, forced, filterproof) if(!message) return say("#[message]", bubble_type, spans, sanitize, language, ignore_spam, forced, filterproof) /datum/emote/imaginary_friend - mob_type_allowed_typecache = /mob/camera/imaginary_friend + mob_type_allowed_typecache = /mob/eye/imaginary_friend // We have to create our own since we can only show emotes to ourselves and our owner /datum/emote/imaginary_friend/run_emote(mob/user, params, type_override, intentional = FALSE) @@ -322,7 +322,7 @@ if(!msg) return TRUE - var/mob/camera/imaginary_friend/friend = user + var/mob/eye/imaginary_friend/friend = user var/dchatmsg = "[span_bold("[friend] (Imaginary friend of [friend.owner])")] [msg]" message = "[span_name("[user]")] [msg]" @@ -346,7 +346,7 @@ message = "points." message_param = "points at %t." -/datum/emote/imaginary_friend/point/run_emote(mob/camera/imaginary_friend/friend, params, type_override, intentional) +/datum/emote/imaginary_friend/point/run_emote(mob/eye/imaginary_friend/friend, params, type_override, intentional) message_param = initial(message_param) // reset return ..() @@ -380,7 +380,7 @@ return message // Another snowflake proc, when will they end... should have refactored it differently -/mob/camera/imaginary_friend/point_at(atom/pointed_atom) +/mob/eye/imaginary_friend/point_at(atom/pointed_atom) if(!isturf(loc)) return @@ -398,36 +398,36 @@ INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(flick_overlay_global), visual, group_clients(), 2.5 SECONDS) animate(visual, pixel_x = (tile.x - our_tile.x) * ICON_SIZE_X + pointed_atom.pixel_x, pixel_y = (tile.y - our_tile.y) * ICON_SIZE_Y + pointed_atom.pixel_y, time = 1.7, easing = EASE_OUT) -/mob/camera/imaginary_friend/create_thinking_indicator() +/mob/eye/imaginary_friend/create_thinking_indicator() if(active_thinking_indicator || active_typing_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER)) return FALSE active_thinking_indicator = image('icons/mob/effects/talk.dmi', src, "[bubble_icon]3", TYPING_LAYER) add_image_to_clients(active_thinking_indicator, group_clients()) -/mob/camera/imaginary_friend/remove_thinking_indicator() +/mob/eye/imaginary_friend/remove_thinking_indicator() if(!active_thinking_indicator) return FALSE remove_image_from_clients(active_thinking_indicator, group_clients()) active_thinking_indicator = null -/mob/camera/imaginary_friend/create_typing_indicator() +/mob/eye/imaginary_friend/create_typing_indicator() if(active_typing_indicator || active_thinking_indicator || !HAS_TRAIT(src, TRAIT_THINKING_IN_CHARACTER)) return FALSE active_typing_indicator = image('icons/mob/effects/talk.dmi', src, "[bubble_icon]0", TYPING_LAYER) add_image_to_clients(active_typing_indicator, group_clients()) -/mob/camera/imaginary_friend/remove_typing_indicator() +/mob/eye/imaginary_friend/remove_typing_indicator() if(!active_typing_indicator) return FALSE remove_image_from_clients(active_typing_indicator, group_clients()) active_typing_indicator = null -/mob/camera/imaginary_friend/remove_all_indicators() +/mob/eye/imaginary_friend/remove_all_indicators() REMOVE_TRAIT(src, TRAIT_THINKING_IN_CHARACTER, CURRENTLY_TYPING_TRAIT) remove_thinking_indicator() remove_typing_indicator() -/mob/camera/imaginary_friend/Move(NewLoc, Dir = 0) +/mob/eye/imaginary_friend/Move(NewLoc, Dir = 0) if(world.time < move_delay) return FALSE setDir(Dir) @@ -438,11 +438,11 @@ abstract_move(NewLoc) move_delay = world.time + 1 -/mob/camera/imaginary_friend/setDir(newdir) +/mob/eye/imaginary_friend/setDir(newdir) . = ..() Show() // The image does not actually update until Show() gets called -/mob/camera/imaginary_friend/proc/recall() +/mob/eye/imaginary_friend/proc/recall() if(!owner || loc == owner) return FALSE abstract_move(owner) @@ -456,7 +456,7 @@ button_icon_state = "join" /datum/action/innate/imaginary_join/Activate() - var/mob/camera/imaginary_friend/I = owner + var/mob/eye/imaginary_friend/I = owner I.recall() /datum/action/innate/imaginary_hide @@ -468,7 +468,7 @@ button_icon_state = "hide" /datum/action/innate/imaginary_hide/proc/update_status() - var/mob/camera/imaginary_friend/I = owner + var/mob/eye/imaginary_friend/I = owner if(I.hidden) name = "Show" desc = "Become visible to your owner." @@ -480,13 +480,13 @@ build_all_button_icons() /datum/action/innate/imaginary_hide/Activate() - var/mob/camera/imaginary_friend/fake_friend = owner + var/mob/eye/imaginary_friend/fake_friend = owner fake_friend.hidden = !fake_friend.hidden fake_friend.Show() build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON) /datum/action/innate/imaginary_hide/update_button_name(atom/movable/screen/movable/action_button/button, force) - var/mob/camera/imaginary_friend/fake_friend = owner + var/mob/eye/imaginary_friend/fake_friend = owner if(fake_friend.hidden) name = "Show" desc = "Become visible to your owner." @@ -496,7 +496,7 @@ return ..() /datum/action/innate/imaginary_hide/apply_button_icon(atom/movable/screen/movable/action_button/current_button, force = FALSE) - var/mob/camera/imaginary_friend/fake_friend = owner + var/mob/eye/imaginary_friend/fake_friend = owner if(fake_friend.hidden) button_icon_state = "unhide" else @@ -515,7 +515,7 @@ random_gain = FALSE /datum/brain_trauma/special/imaginary_friend/trapped_owner/make_friend() - friend = new /mob/camera/imaginary_friend/trapped(get_turf(owner), src) + friend = new /mob/eye/imaginary_friend/trapped(get_turf(owner), src) /datum/brain_trauma/special/imaginary_friend/trapped_owner/reroll_friend() //no rerolling- it's just the last owner's hell if(friend.client) //reconnected @@ -527,17 +527,17 @@ /datum/brain_trauma/special/imaginary_friend/trapped_owner/get_ghost() //no randoms return -/mob/camera/imaginary_friend/trapped +/mob/eye/imaginary_friend/trapped name = "figment of imagination?" real_name = "figment of imagination?" desc = "The previous host of this body." -/mob/camera/imaginary_friend/trapped/greet() +/mob/eye/imaginary_friend/trapped/greet() to_chat(src, span_notice(span_bold("You have managed to hold on as a figment of the new host's imagination!"))) to_chat(src, span_notice("All hope is lost for you, but at least you may interact with your host. You do not have to be loyal to them.")) to_chat(src, span_notice("You cannot directly influence the world around you, but you can see what the host cannot.")) -/mob/camera/imaginary_friend/trapped/setup_friend() +/mob/eye/imaginary_friend/trapped/setup_friend() real_name = "[owner.real_name]?" name = real_name human_image = icon('icons/mob/simple/lavaland/lavaland_monsters.dmi', icon_state = "curseblob") diff --git a/code/datums/components/blob_minion.dm b/code/datums/components/blob_minion.dm index fb92e1139ccfd..b74f813894db5 100644 --- a/code/datums/components/blob_minion.dm +++ b/code/datums/components/blob_minion.dm @@ -4,23 +4,23 @@ /datum/component/blob_minion dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS /// Overmind who is our boss - var/mob/camera/blob/overmind + var/mob/eye/blob/overmind /// Callback to run if overmind strain changes var/datum/callback/on_strain_changed -/datum/component/blob_minion/Initialize(mob/camera/blob/overmind, datum/callback/on_strain_changed) +/datum/component/blob_minion/Initialize(mob/eye/blob/overmind, datum/callback/on_strain_changed) . = ..() if (!isliving(parent)) return COMPONENT_INCOMPATIBLE src.on_strain_changed = on_strain_changed register_overlord(overmind) -/datum/component/blob_minion/InheritComponent(datum/component/new_comp, i_am_original, mob/camera/blob/overmind, datum/callback/on_strain_changed) +/datum/component/blob_minion/InheritComponent(datum/component/new_comp, i_am_original, mob/eye/blob/overmind, datum/callback/on_strain_changed) if (!isnull(on_strain_changed)) src.on_strain_changed = on_strain_changed register_overlord(overmind) -/datum/component/blob_minion/proc/register_overlord(mob/camera/blob/overmind) +/datum/component/blob_minion/proc/register_overlord(mob/eye/blob/overmind) if (isnull(overmind)) return src.overmind = overmind @@ -36,7 +36,7 @@ overmind_properties_changed() /// Our overmind has changed colour and properties -/datum/component/blob_minion/proc/overmind_properties_changed(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/datum/component/blob_minion/proc/overmind_properties_changed(mob/eye/blob/overmind, datum/blobstrain/new_strain) SIGNAL_HANDLER var/mob/living/living_parent = parent living_parent.update_appearance(UPDATE_ICON) diff --git a/code/datums/components/lock_on_cursor.dm b/code/datums/components/lock_on_cursor.dm index 84e315dc6ce29..1d8adedcb3c5b 100644 --- a/code/datums/components/lock_on_cursor.dm +++ b/code/datums/components/lock_on_cursor.dm @@ -36,7 +36,7 @@ lock_amount = 1, list/target_typecache = list(), list/immune = list(), - icon = 'icons/mob/silicon/cameramob.dmi', + icon = 'icons/mob/eyemob.dmi', icon_state = "marker", datum/callback/on_lock, datum/callback/can_target_callback, diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index fead0417db9b2..84889ad6bd931 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -1,4 +1,4 @@ -/mob/camera/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/holo/setLoc(turf/destination, force_update = FALSE) // If we're moving outside the space of our projector, then just... don't var/obj/machinery/holopad/H = origin if(!H?.move_hologram(eye_user, destination)) @@ -24,7 +24,7 @@ var/list/dialed_holopads ///user's eye, once connected - var/mob/camera/ai_eye/remote/holo/eye + var/mob/eye/ai_eye/remote/holo/eye ///user's hologram, once connected var/obj/effect/overlay/holo_pad_hologram/hologram ///hangup action diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 10aa07e624232..0b46daebb01fb 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -618,7 +618,7 @@ buckled_mob.set_glide_size(target) /** - * meant for movement with zero side effects. only use for objects that are supposed to move "invisibly" (like camera mobs or ghosts) + * meant for movement with zero side effects. only use for objects that are supposed to move "invisibly" (like eye mobs or ghosts) * if you want something to move onto a tile with a beartrap or recycler or tripmine or mouse without that object knowing about it at all, use this * most of the time you want forceMove() */ diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 892536bf8315c..2a333de6dff5e 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -73,7 +73,7 @@ . = ..() if(!new_viewer || hud_users_all_z_levels.len != 1) return - for(var/mob/camera/ai_eye/eye as anything in GLOB.aiEyes) + for(var/mob/eye/ai_eye/eye as anything in GLOB.aiEyes) eye.update_ai_detect_hud() /datum/atom_hud/data/malf_apc diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 6640f5582fa20..80a06fa6b9fc1 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -8,7 +8,7 @@ var/list/z_lock = list() // Lock use to these z levels var/lock_override = NONE - var/mob/camera/ai_eye/remote/eyeobj + var/mob/eye/ai_eye/remote/eyeobj var/mob/living/current_user = null var/list/networks = list(CAMERANET_NETWORK_SS13) /// Typepath of the action button we use as "off" @@ -188,7 +188,7 @@ /obj/machinery/computer/camera_advanced/attack_ai(mob/user) return //AIs would need to disable their own camera procs to use the console safely. Bugs happen otherwise. -/mob/camera/ai_eye/remote +/mob/eye/ai_eye/remote name = "Inactive Camera Eye" ai_detector_visible = FALSE var/sprint = 10 @@ -200,24 +200,24 @@ var/visible_icon = 0 var/image/user_image = null -/mob/camera/ai_eye/remote/update_remote_sight(mob/living/user) +/mob/eye/ai_eye/remote/update_remote_sight(mob/living/user) user.set_invis_see(SEE_INVISIBLE_LIVING) //can't see ghosts through cameras user.set_sight(SEE_TURFS) return TRUE -/mob/camera/ai_eye/remote/Destroy() +/mob/eye/ai_eye/remote/Destroy() if(origin && eye_user) origin.remove_eye_control(eye_user,src) origin = null . = ..() eye_user = null -/mob/camera/ai_eye/remote/GetViewerClient() +/mob/eye/ai_eye/remote/GetViewerClient() if(eye_user) return eye_user.client return null -/mob/camera/ai_eye/remote/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/setLoc(turf/destination, force_update = FALSE) if(eye_user) destination = get_turf(destination) if (destination) @@ -237,7 +237,7 @@ SET_PLANE(user_image, ABOVE_GAME_PLANE, destination) eye_user.client.images += user_image -/mob/camera/ai_eye/remote/relaymove(mob/living/user, direction) +/mob/eye/ai_eye/remote/relaymove(mob/living/user, direction) var/initial = initial(sprint) var/max_sprint = 50 @@ -263,7 +263,7 @@ /datum/action/innate/camera_off/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/console = remote_eye.origin console.remove_eye_control(owner) @@ -275,7 +275,7 @@ /datum/action/innate/camera_jump/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin var/list/L = list() @@ -320,7 +320,7 @@ /datum/action/innate/camera_multiz_up/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control if(remote_eye.zMove(UP)) to_chat(owner, span_notice("You move upwards.")) else @@ -334,7 +334,7 @@ /datum/action/innate/camera_multiz_down/Activate() if(!owner || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control if(remote_eye.zMove(DOWN)) to_chat(owner, span_notice("You move downwards.")) else diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index c2fb218d50a33..6db5f9d4f1515 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -221,7 +221,7 @@ for(var/atom/movable/ROI in source) if(ROI == src) continue - if(!istype(ROI) || isdead(ROI) || iscameramob(ROI) || istype(ROI, /obj/effect/dummy/phased_mob)) + if(!istype(ROI) || isdead(ROI) || iseyemob(ROI) || istype(ROI, /obj/effect/dummy/phased_mob)) continue//don't teleport these var/on_chair = "" if(ROI.anchored)// if it's anchored, don't teleport diff --git a/code/game/objects/effects/anomalies/anomalies_bluespace.dm b/code/game/objects/effects/anomalies/anomalies_bluespace.dm index 0a71427776eea..7b1de41e5640a 100644 --- a/code/game/objects/effects/anomalies/anomalies_bluespace.dm +++ b/code/game/objects/effects/anomalies/anomalies_bluespace.dm @@ -65,7 +65,7 @@ for (var/atom/movable/A in urange(12, FROM )) // iterate thru list of mobs in the area if(istype(A, /obj/item/beacon)) continue // don't teleport beacons because that's just insanely stupid - if(iscameramob(A)) + if(iseyemob(A)) continue // Don't mess with AI eye, blob eye, xenobio or advanced cameras if(A.anchored) continue diff --git a/code/game/objects/effects/temporary_visuals/effect_trail.dm b/code/game/objects/effects/temporary_visuals/effect_trail.dm index 9b28dcf909da1..5eed9462dfdf3 100644 --- a/code/game/objects/effects/temporary_visuals/effect_trail.dm +++ b/code/game/objects/effects/temporary_visuals/effect_trail.dm @@ -2,7 +2,7 @@ /obj/effect/temp_visual/effect_trail name = "effect trail" desc = "An invisible effect, how did you examine this?" - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' icon_state = "marker" duration = 15 SECONDS invisibility = INVISIBILITY_ABSTRACT diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 4838d6c891614..e323c65b1ebc1 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -204,7 +204,7 @@ var/turf/our_turf = get_turf(src) detect_state = PROXIMITY_NONE - for(var/mob/camera/ai_eye/AI_eye as anything in GLOB.aiEyes) + for(var/mob/eye/ai_eye/AI_eye as anything in GLOB.aiEyes) if(!AI_eye.ai_detector_visible) continue @@ -253,7 +253,7 @@ // copied from camera chunks but we are doing a really big edge case here though /obj/item/multitool/ai_detect/proc/surrounding_chunks(turf/epicenter) . = list() - var/static_range = /mob/camera/ai_eye::static_visibility_range + var/static_range = /mob/eye/ai_eye::static_visibility_range var/x1 = max(1, epicenter.x - static_range) var/y1 = max(1, epicenter.y - static_range) var/x2 = min(world.maxx, epicenter.x + static_range) diff --git a/code/game/objects/structures/construction_console/construction_actions.dm b/code/game/objects/structures/construction_console/construction_actions.dm index 1a6b5deeeae26..b3a4e309ffa96 100644 --- a/code/game/objects/structures/construction_console/construction_actions.dm +++ b/code/game/objects/structures/construction_console/construction_actions.dm @@ -5,7 +5,7 @@ /datum/action/innate/construction button_icon = 'icons/mob/actions/actions_construction.dmi' ///Console's eye mob - var/mob/camera/ai_eye/remote/base_construction/remote_eye + var/mob/eye/ai_eye/remote/base_construction/remote_eye ///Console itself var/obj/machinery/computer/camera_advanced/base_construction/base_console ///Is this used to build only on the station z level? diff --git a/code/game/objects/structures/construction_console/construction_console.dm b/code/game/objects/structures/construction_console/construction_console.dm index f13dd1d78c64a..97b83acccae06 100644 --- a/code/game/objects/structures/construction_console/construction_console.dm +++ b/code/game/objects/structures/construction_console/construction_console.dm @@ -1,7 +1,7 @@ /** * Camera console used to control a base building drone * - * Using this console will put the user in control of a [base building drone][/mob/camera/ai_eye/remote/base_construction]. + * Using this console will put the user in control of a [base building drone][/mob/eye/ai_eye/remote/base_construction]. * The drone will appear somewhere within the allowed_area var, or if no area is specified, at the location of the console.area * Upon interacting, the user will be granted a set of base building actions that will generally be carried out at the drone's location. * To create a new base builder system, this class should be the only thing that needs to be subtyped. @@ -61,7 +61,7 @@ var/turf/spawn_spot = find_spawn_spot() if (!spawn_spot) return FALSE - eyeobj = new /mob/camera/ai_eye/remote/base_construction(spawn_spot, src) + eyeobj = new /mob/eye/ai_eye/remote/base_construction(spawn_spot, src) eyeobj.origin = src return TRUE @@ -95,7 +95,7 @@ * The mob is constrained to a given area defined by the base construction console. * */ -/mob/camera/ai_eye/remote/base_construction +/mob/eye/ai_eye/remote/base_construction name = "construction holo-drone" //Allows any curious crew to watch the base after it leaves. (This is safe as the base cannot be modified once it leaves) move_on_shuttle = TRUE @@ -105,20 +105,20 @@ ///Reference to the camera console controlling this drone var/obj/machinery/computer/camera_advanced/base_construction/linked_console -/mob/camera/ai_eye/remote/base_construction/Initialize(mapload, obj/machinery/computer/camera_advanced/console_link) +/mob/eye/ai_eye/remote/base_construction/Initialize(mapload, obj/machinery/computer/camera_advanced/console_link) linked_console = console_link if(!linked_console) stack_trace("A base consturuction drone was created with no linked console") return INITIALIZE_HINT_QDEL return ..() -/mob/camera/ai_eye/remote/base_construction/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/base_construction/setLoc(turf/destination, force_update = FALSE) var/area/curr_area = get_area(destination) //Only move if we're in the allowed area. If no allowed area is defined, then we're free to move wherever. if(!linked_console.allowed_area || istype(curr_area, linked_console.allowed_area)) return ..() -/mob/camera/ai_eye/remote/base_construction/relaymove(mob/living/user, direction) +/mob/eye/ai_eye/remote/base_construction/relaymove(mob/living/user, direction) //This camera eye is visible, and as such needs to keep its dir updated dir = direction return ..() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 7a3fcef368ada..6046d356892b8 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -518,7 +518,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) /obj/structure/closet/proc/insertion_allowed(atom/movable/AM) if(ismob(AM)) - if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets... + if(!isliving(AM)) //let's not put ghosts or eye mobs inside closets... return FALSE var/mob/living/L = AM if(L.anchored || L.buckled || L.incorporeal_move || L.has_buckled_mobs()) diff --git a/code/modules/admin/smites/imaginary_friend_special.dm b/code/modules/admin/smites/imaginary_friend_special.dm index 37425faf3b1c8..b9621f51ba2ca 100644 --- a/code/modules/admin/smites/imaginary_friend_special.dm +++ b/code/modules/admin/smites/imaginary_friend_special.dm @@ -138,8 +138,8 @@ if(isliving(client_mob)) client_mob.ghostize() - var/mob/camera/imaginary_friend/friend_mob = client_mob.change_mob_type( - new_type = /mob/camera/imaginary_friend, + var/mob/eye/imaginary_friend/friend_mob = client_mob.change_mob_type( + new_type = /mob/eye/imaginary_friend, location = get_turf(client_mob), delete_old_mob = TRUE, ) diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm index 09a8fdefa315f..f4ddd345075f8 100644 --- a/code/modules/antagonists/abductor/machinery/camera.dm +++ b/code/modules/antagonists/abductor/machinery/camera.dm @@ -23,7 +23,7 @@ /obj/machinery/computer/camera_advanced/abductor/CreateEye() ..() eyeobj.visible_icon = TRUE - eyeobj.icon = 'icons/mob/silicon/cameramob.dmi' + eyeobj.icon = 'icons/mob/eyemob.dmi' eyeobj.icon_state = "abductor_camera" eyeobj.SetInvisibility(INVISIBILITY_OBSERVER) @@ -57,7 +57,7 @@ to_chat(owner, span_warning("You must wait [DisplayTimeText(use_delay - world.time)] to use the [target] again!")) return var/mob/living/carbon/human/C = owner - var/mob/camera/ai_eye/remote/remote_eye = C.remote_control + var/mob/eye/ai_eye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/pad/P = target var/area/target_area = get_area(remote_eye) @@ -101,7 +101,7 @@ to_chat(owner, span_warning("You can only teleport to one place at a time!")) return var/mob/living/carbon/human/C = owner - var/mob/camera/ai_eye/remote/remote_eye = C.remote_control + var/mob/eye/ai_eye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/pad/P = target var/area/target_area = get_area(remote_eye) @@ -151,7 +151,7 @@ return var/mob/living/carbon/human/C = owner - var/mob/camera/ai_eye/remote/remote_eye = C.remote_control + var/mob/eye/ai_eye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/console/console = target console.SetDroppoint(remote_eye.loc,owner) diff --git a/code/modules/antagonists/blob/blob_antag.dm b/code/modules/antagonists/blob/blob_antag.dm index 9f9d97fac8dde..25bea4b083eaa 100644 --- a/code/modules/antagonists/blob/blob_antag.dm +++ b/code/modules/antagonists/blob/blob_antag.dm @@ -18,7 +18,7 @@ var/basic_report = ..() //Display max blobpoints for blebs that lost if(isovermind(owner.current)) //embarrasing if not - var/mob/camera/blob/overmind = owner.current + var/mob/eye/blob/overmind = owner.current if(!overmind.victory_in_progress) //if it won this doesn't really matter var/point_report = "
[owner.name] took over [overmind.max_count] tiles at the height of its growth." return basic_report+point_report @@ -58,7 +58,7 @@ if(!isovermind(user)) return data - var/mob/camera/blob/blob = user + var/mob/eye/blob/blob = user var/datum/blobstrain/reagent/blobstrain = blob.blobstrain if(!blobstrain) @@ -129,7 +129,7 @@ placement_override = BLOB_RANDOM_PLACEMENT to_chat(owner, span_warning("Because your current location is an invalid starting spot and you need to pop, you've been moved to a random location!")) - var/mob/camera/blob/blob_cam = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob) + var/mob/eye/blob/blob_cam = new /mob/eye/blob(get_turf(old_body), blobtag.starting_points_human_blob) owner.mind.transfer_to(blob_cam) old_body.gib() blob_cam.place_blob_core(placement_override, pop_override = TRUE) @@ -147,7 +147,7 @@ /datum/antagonist/blob/antag_listing_status() . = ..() if(owner?.current) - var/mob/camera/blob/blob_cam = owner.current + var/mob/eye/blob/blob_cam = owner.current if(istype(blob_cam)) . += "(Progress: [length(blob_cam.blobs_legit)]/[blob_cam.blobwincount])" diff --git a/code/modules/antagonists/blob/blob_minion.dm b/code/modules/antagonists/blob/blob_minion.dm index 9bf37e961d5dd..e0ff3beb9f98d 100644 --- a/code/modules/antagonists/blob/blob_minion.dm +++ b/code/modules/antagonists/blob/blob_minion.dm @@ -7,7 +7,7 @@ /// The blob core that this minion is attached to var/datum/weakref/overmind -/datum/antagonist/blob_minion/New(mob/camera/blob/overmind) +/datum/antagonist/blob_minion/New(mob/eye/blob/overmind) . = ..() src.overmind = WEAKREF(overmind) @@ -24,7 +24,7 @@ var/datum/weakref/overmind /datum/objective/blob_minion/check_completion() - var/mob/camera/blob/resolved_overmind = overmind.resolve() + var/mob/eye/blob/resolved_overmind = overmind.resolve() if(!resolved_overmind) return FALSE return resolved_overmind.stat != DEAD diff --git a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm index 27d177dde688a..54d393780b25b 100644 --- a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm +++ b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm @@ -24,7 +24,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ var/resource_delay = 0 /// For blob-mobs and extinguishing-based effects var/fire_based = FALSE - var/mob/camera/blob/overmind + var/mob/eye/blob/overmind /// The amount of health regenned on core_process var/base_core_regen = BLOB_CORE_HP_REGEN /// The amount of points gained on core_process @@ -63,7 +63,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ /// Makes blobbernauts inject a bonus amount of reagents, making their attacks more powerful var/blobbernaut_reagentatk_bonus = 0 -/datum/blobstrain/New(mob/camera/blob/new_overmind) +/datum/blobstrain/New(mob/eye/blob/new_overmind) if (!istype(new_overmind)) stack_trace("blobstrain created without overmind") overmind = new_overmind @@ -155,7 +155,7 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ /datum/blobstrain/proc/death_reaction(obj/structure/blob/B, damage_flag, coefficient = 1) //when a blob dies, do this return -/datum/blobstrain/proc/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this +/datum/blobstrain/proc/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O, coefficient = 1) //when the blob expands, do this return /datum/blobstrain/proc/tesla_reaction(obj/structure/blob/B, power, coefficient = 1) //when the blob is hit by a tesla bolt, do this diff --git a/code/modules/antagonists/blob/blobstrains/_reagent.dm b/code/modules/antagonists/blob/blobstrains/_reagent.dm index 65a50621b1717..bc9c61dd4b17b 100644 --- a/code/modules/antagonists/blob/blobstrains/_reagent.dm +++ b/code/modules/antagonists/blob/blobstrains/_reagent.dm @@ -1,7 +1,7 @@ /datum/blobstrain/reagent // Blobs that mess with reagents, all "legacy" ones // what do you mean "legacy" you never added an alternative var/datum/reagent/reagent -/datum/blobstrain/reagent/New(mob/camera/blob/new_overmind) +/datum/blobstrain/reagent/New(mob/eye/blob/new_overmind) . = ..() reagent = new reagent() @@ -42,12 +42,12 @@ description = "[name] is the reagent created by that type of blob." /// Used by blob reagents to calculate the reaction volume they should use when exposing mobs. -/datum/reagent/blob/proc/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/proc/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) return 0 //the dead, and blob mobs, don't cause reactions return round(reac_volume * min(1.5 - touch_protection, 1), 0.1) //full touch protection means 50% volume, any prot below 0.5 means 100% volume. /// Exists to earmark the new overmind arg used by blob reagents. -/datum/reagent/blob/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) return ..() diff --git a/code/modules/antagonists/blob/blobstrains/blazing_oil.dm b/code/modules/antagonists/blob/blobstrains/blazing_oil.dm index ded3be1458efc..f01f2c2faadc6 100644 --- a/code/modules/antagonists/blob/blobstrains/blazing_oil.dm +++ b/code/modules/antagonists/blob/blobstrains/blazing_oil.dm @@ -32,7 +32,7 @@ taste_description = "burning oil" color = "#B68D00" -/datum/reagent/blob/blazing_oil/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/blazing_oil/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.adjust_fire_stacks(round(reac_volume/10)) diff --git a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm index acb4d96c23ad8..64aa9c26f75fa 100644 --- a/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm +++ b/code/modules/antagonists/blob/blobstrains/cryogenic_poison.dm @@ -16,7 +16,7 @@ color = "#8BA6E9" taste_description = "brain freeze" -/datum/reagent/blob/cryogenic_poison/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/cryogenic_poison/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) if(exposed_mob.reagents) diff --git a/code/modules/antagonists/blob/blobstrains/debris_devourer.dm b/code/modules/antagonists/blob/blobstrains/debris_devourer.dm index 352d7c230a4d7..1a2cb9fe85411 100644 --- a/code/modules/antagonists/blob/blobstrains/debris_devourer.dm +++ b/code/modules/antagonists/blob/blobstrains/debris_devourer.dm @@ -25,7 +25,7 @@ I.forceMove(get_turf(spore)) I.throw_at(get_edge_target_turf(spore,pick(GLOB.alldirs)), 6, 5, spore, TRUE, FALSE, null, 3) -/datum/blobstrain/debris_devourer/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this +/datum/blobstrain/debris_devourer/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O, coefficient = 1) //when the blob expands, do this for (var/obj/item/I in T) I.forceMove(overmind.blob_core) diff --git a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm index ea2bf54d7692c..cb5f565ef5503 100644 --- a/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm +++ b/code/modules/antagonists/blob/blobstrains/distributed_neurons.dm @@ -22,7 +22,7 @@ color = "#E88D5D" taste_description = "fizzing" -/datum/reagent/blob/distributed_neurons/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/distributed_neurons/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.6*reac_volume, TOX) diff --git a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm index 4a5c49d851add..d4c9da7e0e4da 100644 --- a/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm +++ b/code/modules/antagonists/blob/blobstrains/electromagnetic_web.dm @@ -23,7 +23,7 @@ taste_description = "pop rocks" color = "#83ECEC" -/datum/reagent/blob/electromagnetic_web/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/electromagnetic_web/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) if(prob(reac_volume*2)) diff --git a/code/modules/antagonists/blob/blobstrains/energized_jelly.dm b/code/modules/antagonists/blob/blobstrains/energized_jelly.dm index 9fa5ed9ab96ae..43c18fc80909b 100644 --- a/code/modules/antagonists/blob/blobstrains/energized_jelly.dm +++ b/code/modules/antagonists/blob/blobstrains/energized_jelly.dm @@ -26,7 +26,7 @@ taste_description = "gelatin" color = "#EFD65A" -/datum/reagent/blob/energized_jelly/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/energized_jelly/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.losebreath += round(0.2*reac_volume) diff --git a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm index e1ae8294df350..d068373e86bc5 100644 --- a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm +++ b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm @@ -31,7 +31,7 @@ taste_description = "the bomb" color = "#8B2500" -/datum/reagent/blob/explosive_lattice/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/explosive_lattice/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() var/brute_loss = 0 var/burn_loss = 0 @@ -51,7 +51,7 @@ brute_loss = brute_loss*(2 - round(bomb_armor*0.01, 0.05)) burn_loss = brute_loss - + exposed_mob.take_overall_damage(brute_loss, burn_loss) for(var/mob/living/nearby_mob in orange(epicenter_turf, 1)) @@ -69,6 +69,6 @@ burn_loss = brute_loss nearby_mob.take_overall_damage(brute_loss, burn_loss) - + else exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/multiplex.dm b/code/modules/antagonists/blob/blobstrains/multiplex.dm index aaebf1d0526b6..aedb571c6b6da 100644 --- a/code/modules/antagonists/blob/blobstrains/multiplex.dm +++ b/code/modules/antagonists/blob/blobstrains/multiplex.dm @@ -2,7 +2,7 @@ var/list/blobstrains var/typeshare -/datum/blobstrain/multiplex/New(mob/camera/blob/new_overmind, list/blobstrains) +/datum/blobstrain/multiplex/New(mob/eye/blob/new_overmind, list/blobstrains) . = ..() for (var/bt in blobstrains) if (ispath(bt, /datum/blobstrain)) @@ -21,7 +21,7 @@ for (var/datum/blobstrain/bt in blobstrains) . += bt.death_reaction(B, damage_flag, coefficient*typeshare) -/datum/blobstrain/multiplex/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this +/datum/blobstrain/multiplex/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O, coefficient = 1) //when the blob expands, do this for (var/datum/blobstrain/bt in blobstrains) . += bt.expand_reaction(B, newB, T, O, coefficient*typeshare) diff --git a/code/modules/antagonists/blob/blobstrains/networked_fibers.dm b/code/modules/antagonists/blob/blobstrains/networked_fibers.dm index 4c84eb639d711..1dfb0bf407712 100644 --- a/code/modules/antagonists/blob/blobstrains/networked_fibers.dm +++ b/code/modules/antagonists/blob/blobstrains/networked_fibers.dm @@ -11,7 +11,7 @@ reagent = /datum/reagent/blob/networked_fibers core_regen_bonus = 3 -/datum/blobstrain/reagent/networked_fibers/expand_reaction(obj/structure/blob/spawning_blob, obj/structure/blob/new_blob, turf/chosen_turf, mob/camera/blob/overmind) +/datum/blobstrain/reagent/networked_fibers/expand_reaction(obj/structure/blob/spawning_blob, obj/structure/blob/new_blob, turf/chosen_turf, mob/eye/blob/overmind) if(!overmind && new_blob.overmind) new_blob.overmind.add_points(1) qdel(new_blob) @@ -33,7 +33,7 @@ taste_description = "efficiency" color = "#4F4441" -/datum/reagent/blob/networked_fibers/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/networked_fibers/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm b/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm index d035319219d2a..40019beb013ef 100644 --- a/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm +++ b/code/modules/antagonists/blob/blobstrains/pressurized_slime.dm @@ -39,7 +39,7 @@ taste_description = "a sponge" color = "#AAAABB" -/datum/reagent/blob/pressurized_slime/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/pressurized_slime/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) var/turf/open/location_turf = get_turf(exposed_mob) diff --git a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm index 1c8cb893df839..778b1a2278423 100644 --- a/code/modules/antagonists/blob/blobstrains/reactive_spines.dm +++ b/code/modules/antagonists/blob/blobstrains/reactive_spines.dm @@ -34,12 +34,12 @@ taste_description = "rock" color = "#9ACD32" -/datum/reagent/blob/reactive_spines/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/reactive_spines/return_mob_expose_reac_volume(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) if(exposed_mob.stat == DEAD || HAS_TRAIT(exposed_mob, TRAIT_BLOB_ALLY)) return 0 //the dead, and blob mobs, don't cause reactions return reac_volume -/datum/reagent/blob/reactive_spines/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/reactive_spines/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.adjustBruteLoss(reac_volume) diff --git a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm index d9010a965376e..101995f23d5be 100644 --- a/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm +++ b/code/modules/antagonists/blob/blobstrains/regenerative_materia.dm @@ -16,7 +16,7 @@ taste_description = "heaven" color = "#A88FB7" -/datum/reagent/blob/regenerative_materia/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/regenerative_materia/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) if(iscarbon(exposed_mob)) diff --git a/code/modules/antagonists/blob/blobstrains/replicating_foam.dm b/code/modules/antagonists/blob/blobstrains/replicating_foam.dm index 83d84618da54c..949c945e9c67f 100644 --- a/code/modules/antagonists/blob/blobstrains/replicating_foam.dm +++ b/code/modules/antagonists/blob/blobstrains/replicating_foam.dm @@ -21,7 +21,7 @@ return ..() -/datum/blobstrain/reagent/replicating_foam/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O) +/datum/blobstrain/reagent/replicating_foam/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O) if(prob(30)) newB.expand(null, null, 0) //do it again! @@ -30,7 +30,7 @@ taste_description = "duplication" color = "#7B5A57" -/datum/reagent/blob/replicating_foam/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/replicating_foam/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm b/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm index 3db0041b3100e..8dfe798c57e35 100644 --- a/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm +++ b/code/modules/antagonists/blob/blobstrains/shifting_fragments.dm @@ -9,7 +9,7 @@ complementary_color = "#3C6EC8" reagent = /datum/reagent/blob/shifting_fragments -/datum/blobstrain/reagent/shifting_fragments/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O) +/datum/blobstrain/reagent/shifting_fragments/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/eye/blob/O) if(istype(B, /obj/structure/blob/normal) || (istype(B, /obj/structure/blob/shield))) newB.forceMove(get_turf(B)) B.forceMove(T) @@ -31,7 +31,7 @@ name = "Shifting Fragments" color = "#C8963C" -/datum/reagent/blob/shifting_fragments/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/shifting_fragments/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm b/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm index 825104ddcc192..1030e44710697 100644 --- a/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm +++ b/code/modules/antagonists/blob/blobstrains/synchronous_mesh.dm @@ -30,7 +30,7 @@ taste_description = "toxic mold" color = "#65ADA2" -/datum/reagent/blob/synchronous_mesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/overmind) +/datum/reagent/blob/synchronous_mesh/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message, touch_protection, mob/eye/blob/overmind) . = ..() reac_volume = return_mob_expose_reac_volume(exposed_mob, methods, reac_volume, show_message, touch_protection, overmind) exposed_mob.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index 99a27429e61a7..db40090615b07 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -5,11 +5,11 @@ GLOBAL_LIST_EMPTY(overminds) GLOBAL_LIST_EMPTY(blob_nodes) -/mob/camera/blob +/mob/eye/blob name = "Blob Overmind" real_name = "Blob Overmind" desc = "The overmind. It controls the blob." - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' icon_state = "marker" mouse_opacity = MOUSE_OPACITY_ICON move_on_shuttle = TRUE @@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) /// The list of strains the blob can reroll for. var/list/strain_choices -/mob/camera/blob/Initialize(mapload, starting_points = OVERMIND_STARTING_POINTS) +/mob/eye/blob/Initialize(mapload, starting_points = OVERMIND_STARTING_POINTS) ADD_TRAIT(src, TRAIT_BLOB_ALLY, INNATE_TRAIT) validate_location() blob_points = starting_points @@ -74,7 +74,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) START_PROCESSING(SSobj, src) GLOB.blob_telepathy_mobs |= src -/mob/camera/blob/proc/validate_location() +/mob/eye/blob/proc/validate_location() var/turf/T = get_turf(src) if(is_valid_turf(T)) return @@ -96,7 +96,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) CRASH("No blobspawnpoints and blob spawned in nullspace.") forceMove(T) -/mob/camera/blob/proc/set_strain(datum/blobstrain/new_strain) +/mob/eye/blob/proc/set_strain(datum/blobstrain/new_strain) if (!ispath(new_strain)) return FALSE @@ -116,7 +116,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) to_chat(src, span_notice("The [blobstrain.name] strain [blobstrain.effectdesc]")) SEND_SIGNAL(src, COMSIG_BLOB_SELECTED_STRAIN, blobstrain) -/mob/camera/blob/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) +/mob/eye/blob/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) if(placed) // The blob can't expand vertically (yet) return FALSE . = ..() @@ -128,13 +128,13 @@ GLOBAL_LIST_EMPTY(blob_nodes) to_chat(src, span_warning("Your destination is invalid. Move somewhere else and try again.")) return null -/mob/camera/blob/proc/is_valid_turf(turf/tile) +/mob/eye/blob/proc/is_valid_turf(turf/tile) var/area/area = get_area(tile) if((area && !(area.area_flags & BLOBS_ALLOWED)) || !tile || !is_station_level(tile.z) || isgroundlessturf(tile)) return FALSE return TRUE -/mob/camera/blob/process() +/mob/eye/blob/process() if(!blob_core) if(!placed) if(manualplace_min_time && world.time >= manualplace_min_time) @@ -166,27 +166,27 @@ GLOBAL_LIST_EMPTY(blob_nodes) has_announced = TRUE /// Create a blob spore and link it to us -/mob/camera/blob/proc/create_spore(turf/spore_turf, spore_type = /mob/living/basic/blob_minion/spore/minion) +/mob/eye/blob/proc/create_spore(turf/spore_turf, spore_type = /mob/living/basic/blob_minion/spore/minion) var/mob/living/basic/blob_minion/spore/spore = new spore_type(spore_turf) assume_direct_control(spore) return spore /// Give our new minion the properties of a minion -/mob/camera/blob/proc/assume_direct_control(mob/living/minion) +/mob/eye/blob/proc/assume_direct_control(mob/living/minion) minion.AddComponent(/datum/component/blob_minion, src) /// Add something to our list of mobs and wait for it to die -/mob/camera/blob/proc/register_new_minion(mob/living/minion) +/mob/eye/blob/proc/register_new_minion(mob/living/minion) blob_mobs |= minion if (!istype(minion, /mob/living/basic/blob_minion/blobbernaut)) RegisterSignal(minion, COMSIG_LIVING_DEATH, PROC_REF(on_minion_death)) /// When a spore (or zombie) dies then we do this -/mob/camera/blob/proc/on_minion_death(mob/living/spore) +/mob/eye/blob/proc/on_minion_death(mob/living/spore) SIGNAL_HANDLER blobstrain.on_sporedeath(spore) -/mob/camera/blob/proc/victory() +/mob/eye/blob/proc/victory() sound_to_playing_players('sound/announcer/alarm/nuke_alarm.ogg', 70) sleep(10 SECONDS) for(var/mob/living/live_guy as anything in GLOB.mob_living_list) @@ -232,7 +232,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) SSticker.news_report = BLOB_WIN SSticker.force_ending = FORCE_END_ROUND -/mob/camera/blob/Destroy() +/mob/eye/blob/Destroy() QDEL_NULL(blobstrain) for(var/BL in GLOB.blobs) var/obj/structure/blob/B = BL @@ -255,7 +255,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) return ..() -/mob/camera/blob/Login() +/mob/eye/blob/Login() . = ..() if(!. || !client) return FALSE @@ -266,12 +266,12 @@ GLOBAL_LIST_EMPTY(blob_nodes) update_health_hud() add_points(0) -/mob/camera/blob/examine(mob/user) +/mob/eye/blob/examine(mob/user) . = ..() if(blobstrain) . += "Its strain is [blobstrain.name]." -/mob/camera/blob/update_health_hud() +/mob/eye/blob/update_health_hud() if(!blob_core) return FALSE var/current_health = round((blob_core.get_integrity() / blob_core.max_integrity) * 100) @@ -282,11 +282,11 @@ GLOBAL_LIST_EMPTY(blob_nodes) continue using_hud.blobpwrdisplay.maptext = MAPTEXT("
[current_health]%
") -/mob/camera/blob/proc/add_points(points) +/mob/eye/blob/proc/add_points(points) blob_points = clamp(blob_points + points, 0, max_blob_points) hud_used.blobpwrdisplay.maptext = MAPTEXT("
[round(blob_points)]
") -/mob/camera/blob/say( +/mob/eye/blob/say( message, bubble_type, list/spans = list(), @@ -314,7 +314,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) blob_talk(message) -/mob/camera/blob/proc/blob_talk(message) +/mob/eye/blob/proc/blob_talk(message) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) @@ -327,10 +327,10 @@ GLOBAL_LIST_EMPTY(blob_nodes) var/rendered = span_big(span_blob("\[Blob Telepathy\] [name]([blobstrain.name]) [message_a]")) relay_to_list_and_observers(rendered, GLOB.blob_telepathy_mobs, src) -/mob/camera/blob/blob_act(obj/structure/blob/B) +/mob/eye/blob/blob_act(obj/structure/blob/B) return -/mob/camera/blob/get_status_tab_items() +/mob/eye/blob/get_status_tab_items() . = ..() if(blob_core) . += "Core Health: [blob_core.get_integrity()]" @@ -343,7 +343,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) . += "Time Before Manual Placement: [max(round((manualplace_min_time - world.time)*0.1, 0.1), 0)]" . += "Time Before Automatic Placement: [max(round((autoplace_max_time - world.time)*0.1, 0.1), 0)]" -/mob/camera/blob/Move(NewLoc, Dir = 0) +/mob/eye/blob/Move(NewLoc, Dir = 0) if(placed) var/obj/structure/blob/B = locate() in range(OVERMIND_MAX_CAMERA_STRAY, NewLoc) if(B) @@ -357,7 +357,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) forceMove(NewLoc) return TRUE -/mob/camera/blob/mind_initialize() +/mob/eye/blob/mind_initialize() . = ..() var/datum/antagonist/blob/blob = mind.has_antag_datum(/datum/antagonist/blob) if(!blob) diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 2f3b51741f9b6..58e25cdd620c8 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -1,7 +1,7 @@ #define BLOB_REROLL_RADIUS 60 /** Simple price check */ -/mob/camera/blob/proc/can_buy(cost = 15) +/mob/eye/blob/proc/can_buy(cost = 15) if(blob_points < cost) to_chat(src, span_warning("You cannot afford this, you need at least [cost] resources!")) balloon_alert(src, "need [cost-blob_points] more resource\s!") @@ -10,7 +10,7 @@ return TRUE /** Places the core itself */ -/mob/camera/blob/proc/place_blob_core(placement_override = BLOB_NORMAL_PLACEMENT, pop_override = FALSE) +/mob/eye/blob/proc/place_blob_core(placement_override = BLOB_NORMAL_PLACEMENT, pop_override = FALSE) if(placed && placement_override != BLOB_FORCE_PLACEMENT) return TRUE @@ -50,7 +50,7 @@ return TRUE /** Checks proximity for mobs */ -/mob/camera/blob/proc/check_core_visibility() +/mob/eye/blob/proc/check_core_visibility() for(var/mob/living/player in range(7, src)) if(ROLE_BLOB in player.faction) continue @@ -69,7 +69,7 @@ /** Checks for previous blobs or denose objects on the tile. */ -/mob/camera/blob/proc/check_objects_tile(turf/placement) +/mob/eye/blob/proc/check_objects_tile(turf/placement) for(var/obj/object in placement) if(istype(object, /obj/structure/blob)) if(istype(object, /obj/structure/blob/normal)) @@ -85,12 +85,12 @@ return TRUE /** Moves the core elsewhere. */ -/mob/camera/blob/proc/transport_core() +/mob/eye/blob/proc/transport_core() if(blob_core) forceMove(blob_core.drop_location()) /** Jumps to a node */ -/mob/camera/blob/proc/jump_to_node() +/mob/eye/blob/proc/jump_to_node() if(!length(GLOB.blob_nodes)) return FALSE @@ -108,7 +108,7 @@ forceMove(chosen_node.loc) /** Places important blob structures */ -/mob/camera/blob/proc/create_special(price, blobstrain, min_separation, needs_node, turf/tile) +/mob/eye/blob/proc/create_special(price, blobstrain, min_separation, needs_node, turf/tile) if(!tile) tile = get_turf(src) var/obj/structure/blob/blob = (locate(/obj/structure/blob) in tile) @@ -142,7 +142,7 @@ return node /** Toggles requiring nodes */ -/mob/camera/blob/proc/toggle_node_req() +/mob/eye/blob/proc/toggle_node_req() nodes_required = !nodes_required if(nodes_required) to_chat(src, span_warning("You now require a nearby node or core to place factory and resource blobs.")) @@ -150,7 +150,7 @@ to_chat(src, span_warning("You no longer require a nearby node or core to place factory and resource blobs.")) /** Creates a shield to reflect projectiles */ -/mob/camera/blob/proc/create_shield(turf/tile) +/mob/eye/blob/proc/create_shield(turf/tile) var/obj/structure/blob/shield/shield = locate(/obj/structure/blob/shield) in tile if(!shield) shield = create_special(BLOB_UPGRADE_STRONG_COST, /obj/structure/blob/shield, 0, FALSE, tile) @@ -170,7 +170,7 @@ shield.balloon_alert(src, "upgraded to [shield.name]!") /** Preliminary check before polling ghosts. */ -/mob/camera/blob/proc/create_blobbernaut() +/mob/eye/blob/proc/create_blobbernaut() var/turf/current_turf = get_turf(src) var/obj/structure/blob/special/factory/factory = locate(/obj/structure/blob/special/factory) in current_turf if(!factory) @@ -190,7 +190,7 @@ pick_blobbernaut_candidate(factory) /// Polls ghosts to get a blobbernaut candidate. -/mob/camera/blob/proc/pick_blobbernaut_candidate(obj/structure/blob/special/factory/factory) +/mob/eye/blob/proc/pick_blobbernaut_candidate(obj/structure/blob/special/factory/factory) if(isnull(factory)) return var/icon/blobbernaut_icon = icon(icon, "blobbernaut") @@ -209,7 +209,7 @@ on_poll_concluded(factory, chosen_one) /// Called when the ghost poll concludes -/mob/camera/blob/proc/on_poll_concluded(obj/structure/blob/special/factory/factory, mob/dead/observer/ghost) +/mob/eye/blob/proc/on_poll_concluded(obj/structure/blob/special/factory/factory, mob/dead/observer/ghost) if(isnull(ghost)) to_chat(src, span_warning("You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later.")) add_points(BLOBMOB_BLOBBERNAUT_RESOURCE_COST) @@ -223,14 +223,14 @@ RegisterSignal(blobber, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(on_blobbernaut_attacked)) /// When one of our boys attacked something, we sometimes want to perform extra effects -/mob/camera/blob/proc/on_blobbernaut_attacked(mob/living/basic/blobbynaut, atom/target, success) +/mob/eye/blob/proc/on_blobbernaut_attacked(mob/living/basic/blobbynaut, atom/target, success) SIGNAL_HANDLER if (!success) return blobstrain.blobbernaut_attack(target, blobbynaut) /** Moves the core */ -/mob/camera/blob/proc/relocate_core() +/mob/eye/blob/proc/relocate_core() var/turf/tile = get_turf(src) var/obj/structure/blob/special/node/blob = locate(/obj/structure/blob/special/node) in tile @@ -258,7 +258,7 @@ blob.setDir(old_dir) /** Searches the tile for a blob and removes it. */ -/mob/camera/blob/proc/remove_blob(turf/tile) +/mob/eye/blob/proc/remove_blob(turf/tile) var/obj/structure/blob/blob = locate() in tile if(!blob) @@ -283,7 +283,7 @@ return TRUE /** Expands to nearby tiles */ -/mob/camera/blob/proc/expand_blob(turf/tile) +/mob/eye/blob/proc/expand_blob(turf/tile) if(world.time < last_attack) return FALSE var/list/possible_blobs = list() @@ -327,7 +327,7 @@ /** Finds cardinal and diagonal attack directions */ -/mob/camera/blob/proc/directional_attack(turf/tile, list/possible_blobs, attack_success = FALSE) +/mob/eye/blob/proc/directional_attack(turf/tile, list/possible_blobs, attack_success = FALSE) var/list/cardinal_blobs = list() var/list/diagonal_blobs = list() @@ -353,7 +353,7 @@ return TRUE /** Rally spores to a location */ -/mob/camera/blob/proc/rally_spores(turf/tile) +/mob/eye/blob/proc/rally_spores(turf/tile) to_chat(src, "You rally your spores.") var/list/surrounding_turfs = TURF_NEIGHBORS(tile) if(!length(surrounding_turfs)) @@ -365,7 +365,7 @@ blob_mob.ai_controller.set_blackboard_key(BB_TRAVEL_DESTINATION, pick(surrounding_turfs)) /** Opens the reroll menu to change strains */ -/mob/camera/blob/proc/strain_reroll() +/mob/eye/blob/proc/strain_reroll() if (!free_strain_rerolls && blob_points < BLOB_POWER_REROLL_COST) to_chat(src, span_warning("You need at least [BLOB_POWER_REROLL_COST] resources to reroll your strain again!")) return FALSE @@ -373,7 +373,7 @@ open_reroll_menu() /** Controls changing strains */ -/mob/camera/blob/proc/open_reroll_menu() +/mob/eye/blob/proc/open_reroll_menu() if (!strain_choices) strain_choices = list() diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index ce1b016dcb045..4d401a52189ab 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -29,7 +29,7 @@ var/ignore_syncmesh_share = 0 /// If the blob blocks atmos and heat spread var/atmosblock = FALSE - var/mob/camera/blob/overmind + var/mob/eye/blob/overmind /datum/armor/structure_blob @@ -144,7 +144,7 @@ O.setDir(dir) var/area/my_area = get_area(src) if(controller) - var/mob/camera/blob/BO = controller + var/mob/eye/blob/BO = controller O.color = BO.blobstrain.color if(!(my_area.area_flags & BLOBS_ALLOWED)) O.color = BlendRGB(O.color, COLOR_WHITE, 0.5) //lighten it to indicate an off-station blob @@ -416,7 +416,7 @@ if(SPT_PROB(BLOB_REINFORCE_CHANCE, seconds_per_tick)) B.change_to(/obj/structure/blob/shield/reflective/core, overmind) -/obj/structure/blob/special/proc/pulse_area(mob/camera/blob/pulsing_overmind, claim_range = 10, pulse_range = 3, expand_range = 2) +/obj/structure/blob/special/proc/pulse_area(mob/eye/blob/pulsing_overmind, claim_range = 10, pulse_range = 3, expand_range = 2) if(QDELETED(pulsing_overmind)) pulsing_overmind = overmind Be_Pulsed() diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index da3356e82509d..154aa2ce83a1d 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -444,7 +444,7 @@ if(ismob(to_insert)) if(!reverse_option_list["Mobs"]) return FALSE - if(!isliving(to_insert)) //let's not put ghosts or camera mobs inside + if(!isliving(to_insert)) //let's not put ghosts or eye mobs inside return FALSE var/mob/living/mob_to_insert = to_insert if(mob_to_insert.anchored || mob_to_insert.incorporeal_move) diff --git a/code/modules/events/ghost_role/blob.dm b/code/modules/events/ghost_role/blob.dm index 8e83351f5c045..097620646d875 100644 --- a/code/modules/events/ghost_role/blob.dm +++ b/code/modules/events/ghost_role/blob.dm @@ -37,7 +37,7 @@ if(isnull(chosen_one)) return NOT_ENOUGH_PLAYERS var/mob/dead/observer/new_blob = chosen_one - var/mob/camera/blob/BC = new_blob.become_overmind() + var/mob/eye/blob/BC = new_blob.become_overmind() spawned_mobs += BC message_admins("[ADMIN_LOOKUPFLW(BC)] has been made into a blob overmind by an event.") BC.log_message("was spawned as a blob overmind by an event.", LOG_GAME) diff --git a/code/modules/forensics/_forensics.dm b/code/modules/forensics/_forensics.dm index 5c43b9da0995c..8058a32e7fab4 100644 --- a/code/modules/forensics/_forensics.dm +++ b/code/modules/forensics/_forensics.dm @@ -109,10 +109,10 @@ /// Adds a single fingerprint /datum/forensics/proc/add_fingerprint(mob/living/suspect, ignoregloves = FALSE) if(!isliving(suspect)) - if(!iscameramob(suspect)) + if(!iseyemob(suspect)) return if(isaicamera(suspect)) - var/mob/camera/ai_eye/ai_camera = suspect + var/mob/eye/ai_eye/ai_camera = suspect if(!ai_camera.ai) return suspect = ai_camera.ai @@ -190,10 +190,10 @@ /// Adds a single hiddenprint /datum/forensics/proc/add_hiddenprint(mob/suspect) if(!isliving(suspect)) - if(!iscameramob(suspect)) + if(!iseyemob(suspect)) return if(isaicamera(suspect)) - var/mob/camera/ai_eye/ai_camera = suspect + var/mob/eye/ai_eye/ai_camera = suspect if(!ai_camera.ai) return suspect = ai_camera.ai diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 74be453b2b1d1..cc03fb05a301d 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -323,7 +323,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp ghostize(FALSE) // FALSE parameter is so we can never re-enter our body. U ded. return TRUE -/mob/camera/verb/ghost() +/mob/eye/verb/ghost() set category = "OOC" set name = "Ghost" set desc = "Relinquish your life and enter the land of the dead." @@ -704,7 +704,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //this is called when a ghost is drag clicked to something. /mob/dead/observer/mouse_drop_dragged(atom/over, mob/user) - if (isobserver(user) && user.client.holder && (isliving(over) || iscameramob(over))) + if (isobserver(user) && user.client.holder && (isliving(over) || iseyemob(over))) user.client.holder.cmd_ghost_drag(src, over) /mob/dead/observer/Topic(href, href_list) diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index bdb0b7ce37e88..d2823eae2b580 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -285,7 +285,7 @@ GLOBAL_DATUM_INIT(orbit_menu, /datum/orbit_menu, new) * Helper POI validation function passed as a callback to various SSpoints_of_interest procs. * * Provides extended validation above and beyond standard, limiting mob POIs without minds or ckeys - * unless they're mobs, camera mobs or megafauna. Also allows exceptions for mobs that are deadchat controlled. + * unless they're mobs, eye mobs or megafauna. Also allows exceptions for mobs that are deadchat controlled. * * If they satisfy that requirement, falls back to default validation for the POI. */ @@ -294,7 +294,7 @@ GLOBAL_DATUM_INIT(orbit_menu, /datum/orbit_menu, new) if(!potential_mob_poi.mind && !potential_mob_poi.ckey) if(!mob_allowed_typecache) mob_allowed_typecache = typecacheof(list( - /mob/camera, + /mob/eye, /mob/living/basic/regal_rat, /mob/living/simple_animal/bot, /mob/living/simple_animal/hostile/megafauna, diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 28b5575108d29..924498332ecc5 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -46,7 +46,7 @@ /datum/emote/help key = "help" - mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/camera/imaginary_friend) + mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/eye/imaginary_friend) /datum/emote/help/run_emote(mob/user, params, type_override, intentional) . = ..() @@ -78,8 +78,8 @@ key = "flip" key_third_person = "flips" hands_use_check = TRUE - mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/camera/imaginary_friend) - mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/camera/imaginary_friend) + mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/eye/imaginary_friend) + mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/living/silicon/ai, /mob/eye/imaginary_friend) /datum/emote/flip/run_emote(mob/user, params , type_override, intentional) . = ..() @@ -111,8 +111,8 @@ key = "spin" key_third_person = "spins" hands_use_check = TRUE - mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/camera/imaginary_friend) - mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/camera/imaginary_friend) + mob_type_allowed_typecache = list(/mob/living, /mob/dead/observer, /mob/eye/imaginary_friend) + mob_type_ignore_stat_typecache = list(/mob/dead/observer, /mob/eye/imaginary_friend) /datum/emote/spin/run_emote(mob/user, params, type_override, intentional) . = ..() diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/eye/eye.dm similarity index 71% rename from code/modules/mob/camera/camera.dm rename to code/modules/mob/eye/eye.dm index eb0d787f64b49..ca58e2969c588 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/eye/eye.dm @@ -1,6 +1,6 @@ -// Camera mob, used by AI camera and blob. -/mob/camera - name = "camera mob" +// Eye mob, used by cameras and overminds such as blobs. +/mob/eye + name = "eye mob" density = FALSE move_force = INFINITY move_resist = INFINITY @@ -13,42 +13,42 @@ /// Toggles if the camera can use emotes var/has_emotes = FALSE -/mob/camera/Initialize(mapload) +/mob/eye/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_GODMODE, INNATE_TRAIT) SSpoints_of_interest.make_point_of_interest(src) if(!move_on_shuttle) ADD_TRAIT(src, TRAIT_BLOCK_SHUTTLE_MOVEMENT, INNATE_TRAIT) -/mob/camera/experience_pressure_difference() +/mob/eye/experience_pressure_difference() return -/mob/camera/canUseStorage() +/mob/eye/canUseStorage() return FALSE -/mob/camera/up() +/mob/eye/up() set name = "Move Upwards" set category = "IC" if(zMove(UP, z_move_flags = ZMOVE_FEEDBACK)) to_chat(src, span_notice("You move upwards.")) -/mob/camera/down() +/mob/eye/down() set name = "Move Down" set category = "IC" if(zMove(DOWN, z_move_flags = ZMOVE_FEEDBACK)) to_chat(src, span_notice("You move down.")) -/mob/camera/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) +/mob/eye/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) z_move_flags |= ZMOVE_IGNORE_OBSTACLES //cameras do not respect these FLOORS you speak so much of return ..() -/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE, force_silence = FALSE) +/mob/eye/emote(act, m_type=1, message = null, intentional = FALSE, force_silence = FALSE) if(has_emotes) return ..() return FALSE -/mob/camera/update_sight() +/mob/eye/update_sight() lighting_color_cutoffs = list(lighting_cutoff_red, lighting_cutoff_green, lighting_cutoff_blue) return ..() diff --git a/code/modules/mob/living/basic/blob_minions/blob_mob.dm b/code/modules/mob/living/basic/blob_minions/blob_mob.dm index 6c30bdfe16db6..1ebd53bb59224 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_mob.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_mob.dm @@ -25,7 +25,7 @@ AddComponent(/datum/component/blob_minion, on_strain_changed = CALLBACK(src, PROC_REF(on_strain_updated))) /// Called when our blob overmind changes their variant, update some of our mob properties -/mob/living/basic/blob_minion/proc/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/mob/living/basic/blob_minion/proc/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain) return /// Associates this mob with a specific blob factory node diff --git a/code/modules/mob/living/basic/blob_minions/blob_spore.dm b/code/modules/mob/living/basic/blob_minions/blob_spore.dm index 9c7b8001e06fe..6a61e8a56a2c7 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_spore.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_spore.dm @@ -88,7 +88,7 @@ z_turf = get_turf(factory) /// If the blob changes to distributed neurons then you can control the spores -/mob/living/basic/blob_minion/spore/minion/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/mob/living/basic/blob_minion/spore/minion/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain) if (isnull(overmind)) REMOVE_TRAIT(src, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT) else diff --git a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm index 13146c3b5c51c..a548a30be6a7c 100644 --- a/code/modules/mob/living/basic/blob_minions/blobbernaut.dm +++ b/code/modules/mob/living/basic/blob_minions/blobbernaut.dm @@ -92,7 +92,7 @@ to_chat(src, span_infoplain("The [blobstrain.name] reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]")) /// Set our attack damage based on blob's properties -/mob/living/basic/blob_minion/blobbernaut/minion/on_strain_updated(mob/camera/blob/overmind, datum/blobstrain/new_strain) +/mob/living/basic/blob_minion/blobbernaut/minion/on_strain_updated(mob/eye/blob/overmind, datum/blobstrain/new_strain) if (isnull(overmind)) melee_damage_lower = initial(melee_damage_lower) melee_damage_upper = initial(melee_damage_upper) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index e41a07d52cd11..87c0cdd402918 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -62,7 +62,7 @@ var/nuking = FALSE var/obj/machinery/doomsday_device/doomsday_device - var/mob/camera/ai_eye/eyeobj + var/mob/eye/ai_eye/eyeobj var/sprint = 10 var/last_moved = 0 var/acceleration = TRUE @@ -1139,7 +1139,7 @@ target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct . = ..() -/mob/living/silicon/ai/proc/camera_visibility(mob/camera/ai_eye/moved_eye) +/mob/living/silicon/ai/proc/camera_visibility(mob/eye/ai_eye/moved_eye) GLOB.cameranet.visibility(moved_eye, client, all_eyes, TRUE) /mob/living/silicon/ai/forceMove(atom/destination) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index 2c5e809e5d921..b8bd1f443eafe 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -65,7 +65,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new) else other_eyes = list() - for(var/mob/camera/ai_eye/eye as anything in moved_eyes) + for(var/mob/eye/ai_eye/eye as anything in moved_eyes) var/list/visibleChunks = list() //Get the eye's turf in case its located in an object like a mecha var/turf/eye_turf = get_turf(eye) diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index c21f08e2d6b5b..7b2c57abc3cc9 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -16,7 +16,7 @@ ///list of all turfs, associative with that turf's static image ///turf -> /image var/list/turfs = list() - ///camera mobs that can see turfs in our grid + ///eye mobs that can see turfs in our grid var/list/seenby = list() ///images currently in use on obscured turfs. var/list/active_static_images = list() @@ -28,7 +28,7 @@ var/upper_z /// Add an AI eye to the chunk, then update if changed. -/datum/camerachunk/proc/add(mob/camera/ai_eye/eye) +/datum/camerachunk/proc/add(mob/eye/ai_eye/eye) eye.visibleCameraChunks += src seenby += eye if(changed) @@ -39,7 +39,7 @@ client.images += active_static_images /// Remove an AI eye from the chunk -/datum/camerachunk/proc/remove(mob/camera/ai_eye/eye, remove_static_with_last_chunk = TRUE) +/datum/camerachunk/proc/remove(mob/eye/ai_eye/eye, remove_static_with_last_chunk = TRUE) eye.visibleCameraChunks -= src seenby -= eye @@ -89,7 +89,7 @@ ///turfs that we could see last update but cant see now var/list/newly_obscured_turfs = visibleTurfs - updated_visible_turfs - for(var/mob/camera/ai_eye/client_eye as anything in seenby) + for(var/mob/eye/ai_eye/client_eye as anything in seenby) var/client/client = client_eye.ai?.client || client_eye.client if(!client) continue @@ -119,7 +119,7 @@ changed = FALSE - for(var/mob/camera/ai_eye/client_eye as anything in seenby) + for(var/mob/eye/ai_eye/client_eye as anything in seenby) var/client/client = client_eye.ai?.client || client_eye.client if(!client) continue diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 4570f93e0e98e..c93054d6d269f 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -2,11 +2,11 @@ // // An invisible (no icon) mob that the AI controls to look around the station with. // It streams chunks as it moves around, which will show it what the AI can and cannot see. -/mob/camera/ai_eye +/mob/eye/ai_eye name = "Inactive AI Eye" icon_state = "ai_camera" - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' invisibility = INVISIBILITY_MAXIMUM hud_possible = list(ANTAG_HUD, AI_DETECT_HUD = HUD_LIST_LIST) var/list/visibleCameraChunks = list() @@ -18,26 +18,26 @@ var/ai_detector_color = COLOR_RED interaction_range = INFINITY -/mob/camera/ai_eye/Initialize(mapload) +/mob/eye/ai_eye/Initialize(mapload) . = ..() GLOB.aiEyes += src update_ai_detect_hud() setLoc(loc, TRUE) -/mob/camera/ai_eye/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) +/mob/eye/ai_eye/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) . = ..() if(same_z_layer) return update_ai_detect_hud() -/mob/camera/ai_eye/examine(mob/user) //Displays a silicon's laws to ghosts +/mob/eye/ai_eye/examine(mob/user) //Displays a silicon's laws to ghosts . = ..() if(istype(ai) && ai.laws && isobserver(user)) . += "[ai] has the following laws:" for(var/law in ai.laws.get_law_list(include_zeroth = TRUE)) . += law -/mob/camera/ai_eye/proc/update_ai_detect_hud() +/mob/eye/ai_eye/proc/update_ai_detect_hud() var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT] var/list/old_images = hud_list[AI_DETECT_HUD] if(!ai_detector_visible) @@ -75,7 +75,7 @@ active_hud_list[AI_DETECT_HUD] = new_images hud.add_atom_to_hud(src) -/mob/camera/ai_eye/proc/get_visible_turfs() +/mob/eye/ai_eye/proc/get_visible_turfs() if(!isturf(loc)) return list() var/client/C = GetViewerClient() @@ -85,7 +85,7 @@ return block(lowerleft, upperright) /// Used in cases when the eye is located in a movable object (i.e. mecha) -/mob/camera/ai_eye/proc/update_visibility() +/mob/eye/ai_eye/proc/update_visibility() SIGNAL_HANDLER if(use_static) ai.camera_visibility(src) @@ -93,7 +93,7 @@ // Use this when setting the aiEye's location. // It will also stream the chunk that the new loc is in. -/mob/camera/ai_eye/proc/setLoc(destination, force_update = FALSE) +/mob/eye/ai_eye/proc/setLoc(destination, force_update = FALSE) if(!ai) return if(!isturf(ai.loc)) @@ -122,20 +122,20 @@ if(ai.master_multicam) ai.master_multicam.refresh_view() -/mob/camera/ai_eye/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs) +/mob/eye/ai_eye/zMove(dir, turf/target, z_move_flags = NONE, recursions_left = 1, list/falling_movs) . = ..() if(.) setLoc(loc, force_update = TRUE) -/mob/camera/ai_eye/Move() +/mob/eye/ai_eye/Move() return -/mob/camera/ai_eye/proc/GetViewerClient() +/mob/eye/ai_eye/proc/GetViewerClient() if(ai) return ai.client return null -/mob/camera/ai_eye/Destroy() +/mob/eye/ai_eye/Destroy() if(ai) ai.all_eyes -= src ai = null @@ -215,7 +215,7 @@ /mob/living/silicon/ai/proc/create_eye() if(eyeobj) return - eyeobj = new /mob/camera/ai_eye() + eyeobj = new /mob/eye/ai_eye() all_eyes += eyeobj eyeobj.ai = src eyeobj.setLoc(loc) @@ -241,7 +241,7 @@ acceleration = !acceleration to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].") -/mob/camera/ai_eye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) +/mob/eye/ai_eye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list(), message_range) . = ..() if(relay_speech && speaker && ai && !radio_freq && speaker != ai && GLOB.cameranet.checkCameraVis(speaker)) ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index 4ef437a53036a..12ee1ce3b5371 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -4,11 +4,11 @@ var/mob/living/silicon/ai/ai var/mutable_appearance/highlighted_background var/highlighted = FALSE - var/mob/camera/ai_eye/pic_in_pic/aiEye + var/mob/eye/ai_eye/pic_in_pic/aiEye /atom/movable/screen/movable/pic_in_pic/ai/Initialize(mapload, datum/hud/hud_owner) . = ..() - aiEye = new /mob/camera/ai_eye/pic_in_pic() + aiEye = new /mob/eye/ai_eye/pic_in_pic() aiEye.screen = src /atom/movable/screen/movable/pic_in_pic/ai/Destroy() @@ -126,7 +126,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) //Dummy camera eyes -/mob/camera/ai_eye/pic_in_pic +/mob/eye/ai_eye/pic_in_pic name = "Secondary AI Eye" invisibility = INVISIBILITY_OBSERVER mouse_opacity = MOUSE_OPACITY_ICON @@ -137,11 +137,11 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) var/telegraph_range = 7 ai_detector_color = COLOR_ORANGE -/mob/camera/ai_eye/pic_in_pic/GetViewerClient() +/mob/eye/ai_eye/pic_in_pic/GetViewerClient() if(screen?.ai) return screen.ai.client -/mob/camera/ai_eye/pic_in_pic/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/pic_in_pic/setLoc(turf/destination, force_update = FALSE) if (destination) abstract_move(destination) else @@ -153,10 +153,10 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) update_camera_telegraphing() update_ai_detect_hud() -/mob/camera/ai_eye/pic_in_pic/get_visible_turfs() +/mob/eye/ai_eye/pic_in_pic/get_visible_turfs() return screen ? screen.get_visible_turfs() : list() -/mob/camera/ai_eye/pic_in_pic/proc/update_camera_telegraphing() +/mob/eye/ai_eye/pic_in_pic/proc/update_camera_telegraphing() if(!telegraph_cameras) return var/list/obj/machinery/camera/add = list() @@ -185,7 +185,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) C.in_use_lights++ C.update_appearance() -/mob/camera/ai_eye/pic_in_pic/proc/disable_camera_telegraphing() +/mob/eye/ai_eye/pic_in_pic/proc/disable_camera_telegraphing() telegraph_cameras = FALSE for (var/obj/machinery/camera/C as anything in cameras_telegraphed) if(QDELETED(C)) @@ -194,7 +194,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) C.update_appearance() cameras_telegraphed.Cut() -/mob/camera/ai_eye/pic_in_pic/Destroy() +/mob/eye/ai_eye/pic_in_pic/Destroy() disable_camera_telegraphing() return ..() diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index dd3303f35230d..5e9018384bef6 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -379,7 +379,7 @@ if(!isliving(user)) return - if(!istype(AM) || isdead(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) + if(!istype(AM) || isdead(AM) || iseyemob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) return load(AM) @@ -809,7 +809,7 @@ if(user.incapacitated || (istype(L) && L.body_position == LYING_DOWN)) return - if(!istype(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) //allows ghosts! + if(!istype(AM) || iseyemob(AM) || istype(AM, /obj/effect/dummy/phased_mob)) //allows ghosts! return load(AM) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index a90a3fedc2489..df33c71305e78 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -261,7 +261,7 @@ return new_slime /mob/proc/become_overmind(starting_points = OVERMIND_STARTING_POINTS) - var/mob/camera/blob/B = new /mob/camera/blob(get_turf(src), starting_points) + var/mob/eye/blob/B = new /mob/eye/blob(get_turf(src), starting_points) B.key = key . = B qdel(src) diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 8816ec87dfb60..acde1703668e4 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -248,7 +248,7 @@ for(var/atom/movable/X in orange(range, T)) if(X.anchored) continue - if(iseffect(X) || iscameramob(X) || isdead(X)) + if(iseffect(X) || iseyemob(X) || isdead(X)) continue var/distance = get_dist(X, T) var/moving_power = max(range - distance, 1) @@ -413,7 +413,7 @@ live.apply_damage(damage)//Since this can be called multiple times if(movey.anchored) continue - if(iseffect(movey) || iscameramob(movey) || isdead(movey)) + if(iseffect(movey) || iseyemob(movey) || isdead(movey)) continue if(implosion) var/distance = get_dist(movey, this_turf) diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 68ffe5e9248be..820219a6e80a0 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -1,22 +1,22 @@ //Xenobio control console -/mob/camera/ai_eye/remote/xenobio +/mob/eye/ai_eye/remote/xenobio visible_icon = TRUE - icon = 'icons/mob/silicon/cameramob.dmi' + icon = 'icons/mob/eyemob.dmi' icon_state = "generic_camera" var/allowed_area = null -/mob/camera/ai_eye/remote/xenobio/Initialize(mapload) +/mob/eye/ai_eye/remote/xenobio/Initialize(mapload) var/area/our_area = get_area(loc) allowed_area = our_area.name . = ..() -/mob/camera/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/xenobio/setLoc(turf/destination, force_update = FALSE) var/area/new_area = get_area(destination) if(new_area && new_area.name == allowed_area || new_area && (new_area.area_flags & XENOBIOLOGY_COMPATIBLE)) return ..() -/mob/camera/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) +/mob/eye/ai_eye/remote/xenobio/can_z_move(direction, turf/start, turf/destination, z_move_flags = NONE, mob/living/rider) . = ..() if(!.) return @@ -84,10 +84,10 @@ stored_slimes -= gone /obj/machinery/computer/camera_advanced/xenobio/CreateEye() - eyeobj = new /mob/camera/ai_eye/remote/xenobio(get_turf(src)) + eyeobj = new /mob/eye/ai_eye/remote/xenobio(get_turf(src)) eyeobj.origin = src eyeobj.visible_icon = TRUE - eyeobj.icon = 'icons/mob/silicon/cameramob.dmi' + eyeobj.icon = 'icons/mob/eyemob.dmi' eyeobj.icon_state = "generic_camera" /obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user) @@ -151,7 +151,7 @@ Boilerplate check for a valid area to perform a camera action in. Checks if the AI eye is on a valid turf and then checks if the target turf is xenobiology compatible Due to keyboard shortcuts, the second one is not necessarily the remote eye's location. */ -/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/camera/ai_eye/remote/xenobio/remote_eye, turf/open/target_turf) +/obj/machinery/computer/camera_advanced/xenobio/proc/validate_area(mob/living/user, mob/eye/ai_eye/remote/xenobio/remote_eye, turf/open/target_turf) if(!GLOB.cameranet.checkTurfVis(remote_eye.loc)) to_chat(user, span_warning("Target is not near a camera. Cannot proceed.")) return FALSE @@ -226,7 +226,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -243,7 +243,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -262,7 +262,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/living_owner = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = living_owner.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = living_owner.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -280,7 +280,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target var/obj/machinery/monkey_recycler/recycler = xeno_console.connected_recycler @@ -303,7 +303,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!target || !isliving(owner)) return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -322,7 +322,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo return var/mob/living/owner_mob = owner - var/mob/camera/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = owner_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = target if(!xeno_console.validate_area(owner, remote_eye, remote_eye.loc)) @@ -373,7 +373,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!isslime(target_slime)) return - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_slime.loc)) @@ -389,7 +389,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo /obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/basic/slime/target_slime) SIGNAL_HANDLER - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_slime.loc)) @@ -402,7 +402,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo SIGNAL_HANDLER var/mob/living/user_mob = user - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user_mob.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user_mob.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_turf)) @@ -428,7 +428,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo return var/cleanup = FALSE - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_turf)) @@ -447,7 +447,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!ismonkey(target_mob)) return - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.connected_recycler) @@ -464,7 +464,7 @@ Due to keyboard shortcuts, the second one is not necessarily the remote eye's lo if(!isslime(target_slime)) return - var/mob/camera/ai_eye/remote/xenobio/remote_eye = user.remote_control + var/mob/eye/ai_eye/remote/xenobio/remote_eye = user.remote_control var/obj/machinery/computer/camera_advanced/xenobio/xeno_console = remote_eye.origin if(!xeno_console.validate_area(user, remote_eye, target_slime.loc)) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index 3eec11d0b40f4..fbe528b870380 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -107,8 +107,8 @@ shuttle_port = null return - eyeobj = new /mob/camera/ai_eye/remote/shuttle_docker(null, src) - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + eyeobj = new /mob/eye/ai_eye/remote/shuttle_docker(null, src) + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj the_eye.setDir(shuttle_port.dir) var/turf/origin = locate(shuttle_port.x + x_offset, shuttle_port.y + y_offset, shuttle_port.z) for(var/area/shuttle_area as anything in shuttle_port.shuttle_areas) @@ -128,7 +128,7 @@ /obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user) ..() if(!QDELETED(user) && user.client) - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/list/to_add = list() to_add += the_eye.placement_images to_add += the_eye.placed_images @@ -141,7 +141,7 @@ /obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user) ..() if(!QDELETED(user) && user.client) - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/list/to_remove = list() to_remove += the_eye.placement_images to_remove += the_eye.placed_images @@ -155,7 +155,7 @@ if(designating_target_loc || !current_user) return - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/landing_clear = checkLandingSpot() if(designate_time && (landing_clear != SHUTTLE_DOCKER_BLOCKED)) to_chat(current_user, span_warning("Targeting transit location, please wait [DisplayTimeText(designate_time)]...")) @@ -223,7 +223,7 @@ return TRUE /obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot() - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/list/image_cache = the_eye.placement_images the_eye.setDir(turn(the_eye.dir, -90)) for(var/i in 1 to image_cache.len) @@ -239,7 +239,7 @@ checkLandingSpot() /obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingSpot() - var/mob/camera/ai_eye/remote/shuttle_docker/the_eye = eyeobj + var/mob/eye/ai_eye/remote/shuttle_docker/the_eye = eyeobj var/turf/eyeturf = get_turf(the_eye) if(!eyeturf) return SHUTTLE_DOCKER_BLOCKED @@ -316,22 +316,22 @@ add_jumpable_port(dock.shuttle_id) return TRUE -/mob/camera/ai_eye/remote/shuttle_docker +/mob/eye/ai_eye/remote/shuttle_docker visible_icon = FALSE use_static = FALSE var/list/image/placement_images = list() var/list/image/placed_images = list() -/mob/camera/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin) +/mob/eye/ai_eye/remote/shuttle_docker/Initialize(mapload, obj/machinery/computer/camera_advanced/origin) src.origin = origin return ..() -/mob/camera/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE) +/mob/eye/ai_eye/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE) . = ..() var/obj/machinery/computer/camera_advanced/shuttle_docker/console = origin console.checkLandingSpot() -/mob/camera/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user) +/mob/eye/ai_eye/remote/shuttle_docker/update_remote_sight(mob/living/user) user.set_sight(BLIND|SEE_TURFS) // Pale blue, should look nice I think user.lighting_color_cutoffs = list(30, 40, 50) @@ -346,7 +346,7 @@ /datum/action/innate/shuttledocker_rotate/Activate() if(QDELETED(owner) || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin origin.rotateLandingSpot() @@ -358,7 +358,7 @@ /datum/action/innate/shuttledocker_place/Activate() if(QDELETED(owner) || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin origin.placeLandingSpot(owner) @@ -369,7 +369,7 @@ /datum/action/innate/camera_jump/shuttle_docker/Activate() if(QDELETED(owner) || !isliving(owner)) return - var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control + var/mob/eye/ai_eye/remote/remote_eye = owner.remote_control var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin playsound(console, 'sound/machines/terminal/terminal_prompt_deny.ogg', 25, FALSE) diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 98b998baf4229..4eed7f3e9a7e1 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -277,7 +277,7 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( for (var/list/zlevel_turfs as anything in shuttle_area.get_zlevel_turf_lists()) for(var/turf/shuttle_turf as anything in zlevel_turfs) for(var/atom/movable/exporting_atom in shuttle_turf) - if(iscameramob(exporting_atom)) + if(iseyemob(exporting_atom)) continue if(exporting_atom.anchored) continue diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 3e4a5be979fb3..b0497ed3b2e9c 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -136,7 +136,7 @@ /obj/structure/transport/linear/proc/add_item_on_transport(datum/source, atom/movable/new_transport_contents) SIGNAL_HANDLER - var/static/list/blacklisted_types = typecacheof(list(/obj/structure/fluff/tram_rail, /obj/effect/decal/cleanable, /obj/structure/transport/linear, /mob/camera)) + var/static/list/blacklisted_types = typecacheof(list(/obj/structure/fluff/tram_rail, /obj/effect/decal/cleanable, /obj/structure/transport/linear, /mob/eye)) if(is_type_in_typecache(new_transport_contents, blacklisted_types) || new_transport_contents.invisibility == INVISIBILITY_ABSTRACT || HAS_TRAIT(new_transport_contents, TRAIT_UNDERFLOOR)) //prevents the tram from stealing things like landmarks return FALSE if(new_transport_contents in transport_contents) diff --git a/code/modules/unit_tests/mob_faction.dm b/code/modules/unit_tests/mob_faction.dm index 554a1adda9d23..f5d64918038fd 100644 --- a/code/modules/unit_tests/mob_faction.dm +++ b/code/modules/unit_tests/mob_faction.dm @@ -8,10 +8,10 @@ /mob/dview, /mob/oranges_ear ) - ignored += typesof(/mob/camera/imaginary_friend) + ignored += typesof(/mob/eye/imaginary_friend) ignored += typesof(/mob/living/silicon/robot/model) - ignored += typesof(/mob/camera/ai_eye/remote/base_construction) - ignored += typesof(/mob/camera/ai_eye/remote/shuttle_docker) + ignored += typesof(/mob/eye/ai_eye/remote/base_construction) + ignored += typesof(/mob/eye/ai_eye/remote/shuttle_docker) for (var/mob_type in typesof(/mob) - ignored) var/mob/mob_instance = allocate(mob_type) if(!islist(mob_instance.faction)) diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index a7af7b168e2cb..ce59bd3d61d49 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -285,13 +285,13 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) //We have a baseturf limit of 10, adding more than 10 baseturf helpers will kill CI, so here's a future edge case to fix. returnable_list += typesof(/obj/effect/baseturf_helper) //No tauma to pass in - returnable_list += typesof(/mob/camera/imaginary_friend) + returnable_list += typesof(/mob/eye/imaginary_friend) //No heart to give returnable_list += typesof(/obj/structure/ethereal_crystal) //No linked console - returnable_list += typesof(/mob/camera/ai_eye/remote/base_construction) + returnable_list += typesof(/mob/eye/ai_eye/remote/base_construction) //See above - returnable_list += typesof(/mob/camera/ai_eye/remote/shuttle_docker) + returnable_list += typesof(/mob/eye/ai_eye/remote/shuttle_docker) //Hangs a ref post invoke async, which we don't support. Could put a qdeleted check but it feels hacky returnable_list += typesof(/obj/effect/anomaly/grav/high) //See above diff --git a/code/modules/vehicles/mecha/mecha_ai_interaction.dm b/code/modules/vehicles/mecha/mecha_ai_interaction.dm index 4259dff5c3426..6dc1e2307dc28 100644 --- a/code/modules/vehicles/mecha/mecha_ai_interaction.dm +++ b/code/modules/vehicles/mecha/mecha_ai_interaction.dm @@ -99,7 +99,7 @@ mecha_flags |= SILICON_PILOT moved_inside(AI) AI.eyeobj?.forceMove(src) - AI.eyeobj?.RegisterSignal(src, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/camera/ai_eye, update_visibility)) + AI.eyeobj?.RegisterSignal(src, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/eye/ai_eye, update_visibility)) AI.controlled_equipment = src AI.remote_control = src add_occupant(AI) diff --git a/icons/mob/silicon/cameramob.dmi b/icons/mob/eyemob.dmi similarity index 100% rename from icons/mob/silicon/cameramob.dmi rename to icons/mob/eyemob.dmi diff --git a/tgstation.dme b/tgstation.dme index cf218ba922fd1..6cb0db19d3c51 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4776,7 +4776,6 @@ #include "code\modules\mob\mob_update_icons.dm" #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm" -#include "code\modules\mob\camera\camera.dm" #include "code\modules\mob\dead\dead.dm" #include "code\modules\mob\dead\new_player\latejoin_menu.dm" #include "code\modules\mob\dead\new_player\login.dm" @@ -4791,6 +4790,7 @@ #include "code\modules\mob\dead\observer\observer_movement.dm" #include "code\modules\mob\dead\observer\observer_say.dm" #include "code\modules\mob\dead\observer\orbit.dm" +#include "code\modules\mob\eye\eye.dm" #include "code\modules\mob\living\blood.dm" #include "code\modules\mob\living\damage_procs.dm" #include "code\modules\mob\living\death.dm" From ab1d7466bb259fce0a7b03841f00914f4a289d86 Mon Sep 17 00:00:00 2001 From: "tgstation-ci[bot]" <179393467+tgstation-ci[bot]@users.noreply.github.com> Date: Sat, 9 Nov 2024 10:59:28 +0000 Subject: [PATCH 23/23] Automatic changelog for PR #87684 [ci skip] --- html/changelogs/AutoChangeLog-pr-87684.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-87684.yml diff --git a/html/changelogs/AutoChangeLog-pr-87684.yml b/html/changelogs/AutoChangeLog-pr-87684.yml new file mode 100644 index 0000000000000..e13ae3fcc6cf5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-87684.yml @@ -0,0 +1,4 @@ +author: "tontyGH" +delete-after: True +changes: + - server: "mob/camera has been renamed to mob/eye, which may break downstreams" \ No newline at end of file