From d046c97ff4db281c6fba31f6b44092bbc833af86 Mon Sep 17 00:00:00 2001 From: Lexanx <61974560+Lexanx@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:35:42 +0300 Subject: [PATCH 1/2] Adherent Discharge (#2102) --- baystation12.dme | 4 +- mods/_master_files/code/_onclick/click.dm | 55 +++++++++++++ .../code/modules/species/station/adherent.dm | 4 + mods/adherent_discharge/README.md | 74 ++++++++++++++++++ .../adherent_discharge/_adherent_discharge.dm | 4 + .../_adherent_discharge.dme | 6 ++ mods/adherent_discharge/code/adherent.dm | 21 +++++ .../sounds/discharge_on.ogg | Bin 0 -> 15051 bytes mods/global_modpacks.dm | 1 + 9 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 mods/_master_files/code/_onclick/click.dm create mode 100644 mods/_master_files/code/modules/species/station/adherent.dm create mode 100644 mods/adherent_discharge/README.md create mode 100644 mods/adherent_discharge/_adherent_discharge.dm create mode 100644 mods/adherent_discharge/_adherent_discharge.dme create mode 100644 mods/adherent_discharge/code/adherent.dm create mode 100644 mods/adherent_discharge/sounds/discharge_on.ogg diff --git a/baystation12.dme b/baystation12.dme index e493fdfdd29ba..f22a037290f3b 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -3416,6 +3416,7 @@ #include "maps\sierra\loadout\loadout_documents.dm" #include "mods\_modpack.dm" #include "mods\global_modpacks.dm" +#include "mods\_master_files\code\_onclick\click.dm" #include "mods\_master_files\code\game\world.dm" #include "mods\_master_files\code\game\gamemodes\ert.dm" #include "mods\_master_files\code\game\objects\effects\decals\contraband.dm" @@ -3452,9 +3453,10 @@ #include "mods\_master_files\code\modules\mob\new_player\new_player.dm" #include "mods\_master_files\code\modules\power\gravitygenerator.dm" #include "mods\_master_files\code\modules\projectiles\projectile\bullets.dm" -#include "mods\_master_files\code\modules\species\station\machine.dm" +#include "mods\_master_files\code\modules\species\station\adherent.dm" #include "mods\_master_files\code\modules\sounds\connector.dm" #include "mods\_master_files\code\modules\sounds\throw.dm" +#include "mods\_master_files\code\modules\species\station\machine.dm" #include "mods\_master_files\maps\sierra\sierra_ranks.dm" #include "mods\_master_files\maps\sierra\items\rigs.dm" #include "~code\global_init.dm" diff --git a/mods/_master_files/code/_onclick/click.dm b/mods/_master_files/code/_onclick/click.dm new file mode 100644 index 0000000000000..3b1bdf224b6bb --- /dev/null +++ b/mods/_master_files/code/_onclick/click.dm @@ -0,0 +1,55 @@ +/mob/living/carbon/human/AltClickOn(atom/A) + if(get_dist(src, A) > 1) + return ..() + if(!stat && mind && ismob(A) && (A != src) && (src.species.name == SPECIES_ADHERENT)) + var/mob/living/carbon/human/adherent = src + var/obj/item/organ/internal/cell/adherent/adherent_core = adherent.internal_organs_by_name[BP_CELL] + if(adherent_core.ready_to_charge) + var/mob/living/carbon/human/target_human = A + var/mob/living/target = A + var/obj/item/cell/target_cell + var/obj/item/cell/adherent_cell + var/obj/item/organ/internal/cell/acell = locate() in adherent.internal_organs + if(acell && acell.cell) + adherent_cell = acell.cell + + if(adherent_cell && adherent_cell.charge <= 2000) + to_chat(src, SPAN_WARNING("Your cell charge is too low for this action.")) + return + + if(ishuman(target_human)) + var/obj/item/organ/internal/cell/cell = locate() in target_human.internal_organs + if(cell && cell.cell) + target_cell = cell.cell + else if(isrobot(target)) + var/mob/living/silicon/robot/robot = target + target_cell = robot.get_cell() + + target.visible_message(SPAN_WARNING("There is a loud crack and the smell of ozone as \the [adherent] touches \the [target].")) + playsound(loc, 'sound/effects/snap.ogg', 50, 1) + + if(target_cell) + if(target_cell.maxcharge > (target_cell.charge + 2000)) + target_cell.charge += 2000 + else + target_cell.charge = target_cell.maxcharge + to_chat(target, SPAN_NOTICE("<b>Your [target_cell] has been charged.</b>")) + adherent_cell.charge -= 2000 + if(istype(target_human) && target_human.species.name == SPECIES_ADHERENT) + next_click = world.time + 2 SECONDS + return + if(isrobot(target)) + target.apply_damage(100, DAMAGE_BURN, def_zone = src.zone_sel.selecting) + visible_message(SPAN_DANGER("[adherent] touches [target] with bright electrical arc connecting them.")) + to_chat(target, SPAN_DANGER("<b>You detect damage to your components!</b>")) + else if(ishuman(target)) + target.electrocute_act(100, src, def_zone = src.zone_sel.selecting) + visible_message(SPAN_DANGER("With bright electrical flash [adherent] touches [target] using it's tentacles.")) + else + target.apply_damage(100, DAMAGE_BURN, def_zone = src.zone_sel.selecting) + visible_message(SPAN_DANGER("With bright electrical flash [adherent] touches [target] using it's tentacles.")) + admin_attack_log(src, target, "Has electrocuted", "Has been electrocuted", "electrocuted") + target.throw_at(get_step(target,get_dir(src,target)), 5, 10) + next_click = world.time + 2 SECONDS + return + return ..() \ No newline at end of file diff --git a/mods/_master_files/code/modules/species/station/adherent.dm b/mods/_master_files/code/modules/species/station/adherent.dm new file mode 100644 index 0000000000000..8884960d049c8 --- /dev/null +++ b/mods/_master_files/code/modules/species/station/adherent.dm @@ -0,0 +1,4 @@ +/datum/species/adherent/New() + LAZYINITLIST(inherent_verbs) + inherent_verbs += /mob/living/carbon/human/proc/toggle_emergency_discharge + ..() \ No newline at end of file diff --git a/mods/adherent_discharge/README.md b/mods/adherent_discharge/README.md new file mode 100644 index 0000000000000..7aa1bf23c2ee0 --- /dev/null +++ b/mods/adherent_discharge/README.md @@ -0,0 +1,74 @@ + +#### Список PRов: + +- https://github.com/SierraBay/SierraBay12/pull/1653 +<!-- + Ссылки на PRы, связанные с модом: + - Создание + - Большие изменения +--> + +<!-- Название мода. Не важно на русском или на английском. --> +## Adherent Discharge + +ID мода: ADHERENT_DISCHARGE +<!-- + Название модпака прописными буквами, СОЕДИНЁННЫМИ_ПОДЧЁРКИВАНИЕМ, + которое ты будешь использовать для обозначения файлов. +--> + +### Описание мода + +Этот мод служит примером для разработчиков и существует лишь для того, +чтобы его можно было легко скопировать и вставить в другое место. +<!-- + Что он делает, что добавляет: что, куда, зачем и почему - всё здесь. + А также любая полезная информация. +--> + +### Изменения *кор кода* + +- Отсутствуют +<!-- + Если вы редактировали какие-либо процедуры или переменные в кор коде, + они должны быть указаны здесь. + Нужно указать и файл, и процедуры/переменные. + + Изменений нет - напиши "Отсутствуют" +--> + +### Оверрайды + +- `mods/_master_files/code/_onclick/click.dm`: `/mob/living/carbon/human/AltClickOn()` +- `mods/_master_files/code/modules/species/station/adherent.dm`: `/datum/species/adherent/New()` +<!-- + Если ты добавлял новый модульный оверрайд, его нужно указать здесь. + Здесь указываются оверрайды в твоём моде и папке `_master_files` + + Изменений нет - напиши "Отсутствуют" +--> + +### Дефайны + +- Отсутствуют +<!-- + Если требовалось добавить какие-либо дефайны, укажи файлы, + в которые ты их добавил, а также перечисли имена. + И то же самое, если ты используешь дефайны, определённые другим модом. + + Не используешь - напиши "Отсутствуют" +--> + +### Используемые файлы, не содержащиеся в модпаке + +- Отсутствуют +<!-- + Будь то немодульный файл или модульный файл, который не содержится в папке, + принадлежащей этому конкретному моду, он должен быть упомянут здесь. + Хорошими примерами являются иконки или звуки, которые используются одновременно + несколькими модулями, или что-либо подобное. +--> + +### Авторы: + +Lexanx diff --git a/mods/adherent_discharge/_adherent_discharge.dm b/mods/adherent_discharge/_adherent_discharge.dm new file mode 100644 index 0000000000000..ee2718ce2524d --- /dev/null +++ b/mods/adherent_discharge/_adherent_discharge.dm @@ -0,0 +1,4 @@ +/singleton/modpack/adherent_discharge + name = "Adherent Discharge" + desc = "Добавляет Адхерентам кнопку удара электричеством." + author = "Lexanx" diff --git a/mods/adherent_discharge/_adherent_discharge.dme b/mods/adherent_discharge/_adherent_discharge.dme new file mode 100644 index 0000000000000..c8a66146a6812 --- /dev/null +++ b/mods/adherent_discharge/_adherent_discharge.dme @@ -0,0 +1,6 @@ +#ifndef MODPACK_ADHERENT_DISCHARGE +#define MODPACK_ADHERENT_DISCHARGE + +#include "_adherent_discharge.dm" +#include "code/adherent.dm" +#endif diff --git a/mods/adherent_discharge/code/adherent.dm b/mods/adherent_discharge/code/adherent.dm new file mode 100644 index 0000000000000..681dec209ae83 --- /dev/null +++ b/mods/adherent_discharge/code/adherent.dm @@ -0,0 +1,21 @@ +/obj/item/organ/internal/cell/adherent + var/ready_to_charge + + +/mob/living/carbon/human/proc/toggle_emergency_discharge() + set category = "Abilities" + set name = "Toggle emergency discharge" + set desc = "Allows you to overload your piezo capacitors." + + var/mob/living/carbon/human/adherent = src + var/obj/item/organ/internal/cell/adherent/adherent_core = adherent.internal_organs_by_name[BP_CELL] + if(!adherent_core.ready_to_charge) + adherent_core.ready_to_charge = TRUE + to_chat(src, SPAN_WARNING("The emergency discharge is ready for use.")) + to_chat(src, SPAN_GOOD("You are ready to discharge, use alt+click on target to electrocute them.")) + adherent.visible_message(SPAN_WARNING("You hear silent crackle sounds from [adherent] tentacles")) + playsound(loc, 'mods/adherent_discharge/sounds/discharge_on.ogg', 40, 1) + return + + adherent_core.ready_to_charge = FALSE + to_chat(src, SPAN_WARNING("You have relieved the tension of your tentacles.")) diff --git a/mods/adherent_discharge/sounds/discharge_on.ogg b/mods/adherent_discharge/sounds/discharge_on.ogg new file mode 100644 index 0000000000000000000000000000000000000000..dcb9e407eb65cbde8fb87b4495e3225ecf816c72 GIT binary patch literal 15051 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 P=1)5_Riv8`2*LjXo8FD! literal 0 HcmV?d00001 diff --git a/mods/global_modpacks.dm b/mods/global_modpacks.dm index 7ae1b7c1fa410..f69275e197813 100644 --- a/mods/global_modpacks.dm +++ b/mods/global_modpacks.dm @@ -1,5 +1,6 @@ // SIERRA TODO: GET RID OF IT!!! #include "ai/_ai.dme" +#include "adherent_discharge/_adherent_discharge.dme" #include "body_markings/_body_markings.dme" #include "client_verbs/_client_verbs.dme" #include "don_loadout/_don_loadout.dme" From 5761ecd3dad408f8b06d106d7bf6f99f091be2d3 Mon Sep 17 00:00:00 2001 From: UEDCommander <52104104+UEDCommander@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:36:06 +0300 Subject: [PATCH 2/2] Downstream refactors (#2104) --- baystation12.dme | 1 + code/__defines/dcs/signals/signals_area.dm | 10 ++ code/controllers/subsystems/atoms.dm | 45 +++-- code/controllers/subsystems/garbage.dm | 4 + code/controllers/subsystems/overlays.dm | 163 ++++++++++-------- .../subsystems/processing/icon_updates.dm | 69 ++++---- code/game/area/area_power.dm | 22 +++ .../objects/items/devices/radio/intercom.dm | 68 ++++---- code/modules/power/apc.dm | 6 +- 9 files changed, 230 insertions(+), 158 deletions(-) create mode 100644 code/__defines/dcs/signals/signals_area.dm diff --git a/baystation12.dme b/baystation12.dme index f22a037290f3b..f8da9d1219587 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -98,6 +98,7 @@ #include "code\__defines\zmimic.dm" #include "code\__defines\dcs\flags.dm" #include "code\__defines\dcs\helpers.dm" +#include "code\__defines\dcs\signals\signals_area.dm" #include "code\__defines\dcs\signals\signals_atom.dm" #include "code\__defines\dcs\signals\signals_atom_movable.dm" #include "code\__defines\dcs\signals\signals_datum.dm" diff --git a/code/__defines/dcs/signals/signals_area.dm b/code/__defines/dcs/signals/signals_area.dm new file mode 100644 index 0000000000000..7e05ef6a0479f --- /dev/null +++ b/code/__defines/dcs/signals/signals_area.dm @@ -0,0 +1,10 @@ +// Main area signals. Format: +// When the signal is called: (signal arguments) +// All signals send the source datum of the signal as the first argument + +///from base of /area/proc/power_change(): (area/apc_area) +#define COMSIG_AREA_POWER_CHANGE "area_apc_power_change" +///from base of /area/proc/set_apc(): (area/apc_area) +#define COMSIG_AREA_APC_ADDED "area_apc_added" +///from base of /area/proc/remove_apc(): (area/apc_area) +#define COMSIG_AREA_APC_REMOVED "area_apc_removed" diff --git a/code/controllers/subsystems/atoms.dm b/code/controllers/subsystems/atoms.dm index d7236a00638c9..cc550d2ede5e8 100644 --- a/code/controllers/subsystems/atoms.dm +++ b/code/controllers/subsystems/atoms.dm @@ -44,33 +44,32 @@ SUBSYSTEM_DEF(atoms) return atom_init_stage = INITIALIZATION_INNEW_MAPLOAD var/list/mapload_arg = list(TRUE) - var/atom/atom - var/list/params var/count = 0 var/time = Uptime() - if (!initialized) - for (atom in world) - if (!atom || atom.atom_flags & ATOM_FLAG_INITIALIZED) - continue - InitAtom(atom, mapload_arg) - if (++count % 1000) + if(!initialized) + for(var/atom/atom_to_initialize as anything in world) + if(!atom_to_initialize || atom_to_initialize.atom_flags & ATOM_FLAG_INITIALIZED) continue + InitAtom(atom_to_initialize, mapload_arg) + count++ CHECK_TICK + var/init_queue_length = length(init_queue) - if (init_queue_length) - for (var/i = 1 to init_queue_length) - atom = init_queue[i] - if (!atom || atom.atom_flags & ATOM_FLAG_INITIALIZED) + if(init_queue_length) + for(var/i = 1 to init_queue_length) + var/atom/atom_to_initialize = init_queue[i] + if (!atom_to_initialize || atom_to_initialize.atom_flags & ATOM_FLAG_INITIALIZED) continue - params = init_queue[atom] + + var/list/params = init_queue[atom_to_initialize] if (params) - InitAtom(atom, mapload_arg + params) + InitAtom(atom_to_initialize, mapload_arg + params) else - InitAtom(atom, mapload_arg) - if (++count % 500) - continue + InitAtom(atom_to_initialize, mapload_arg) + count++ CHECK_TICK init_queue.Cut(1, init_queue_length + 1) + time = max((Uptime() - time) * 0.1, 0.1) report_progress("Initialized [count] atom\s in [time]s ([floor(count/time)]/s)") atom_init_stage = INITIALIZATION_INNEW_REGULAR @@ -78,13 +77,13 @@ SUBSYSTEM_DEF(atoms) if (late_queue_length) count = 0 time = Uptime() - for (var/i = 1 to late_queue_length) - atom = late_init_queue[i] - if (!atom) - continue - atom.LateInitialize(arglist(late_init_queue[atom])) - if (++count % 250) + for(var/i = 1 to late_queue_length) + var/atom/atom_to_late_init = late_init_queue[i] + if (!atom_to_late_init) continue + + atom_to_late_init.LateInitialize(arglist(late_init_queue[atom_to_late_init])) + count++ CHECK_TICK late_init_queue.Cut(1, late_queue_length + 1) time = max((Uptime() - time) * 0.1, 0.1) diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index d8cfe79fe21ce..a0a1bbf954cb0 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -219,9 +219,13 @@ SUBSYSTEM_DEF(garbage) ++details.qdels switch (datum.gc_destroyed) if (null) + if(SEND_SIGNAL(datum, COMSIG_PREQDELETED)) // Gives any signal listener a chance to prevent atom qdel + return + datum.gc_destroyed = GC_CURRENTLY_BEING_QDELETED var/start_time = world.time var/start_tick = world.tick_usage + SEND_SIGNAL(datum, COMSIG_QDELETING) // Leting signal listeners know, that datum is being qdeleted var/hint = datum.Destroy() if (world.time != start_time) ++details.slept_destroy diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm index 6090afe02c78e..baf3141f9a0b2 100644 --- a/code/controllers/subsystems/overlays.dm +++ b/code/controllers/subsystems/overlays.dm @@ -11,21 +11,17 @@ var/global/const/ATOM_ICON_CACHE_ALL = (ATOM_ICON_CACHE_NORMAL | ATOM_ICON_CACHE SUBSYSTEM_DEF(overlays) name = "Overlays" flags = SS_TICKER - wait = 1 // ticks + wait = 1 priority = FIRE_PRIORITY_OVERLAYS init_order = SS_INIT_OVERLAYS - /// The queue of atoms that need under/overlay updates. - var/static/list/atom/queue = list() - + VAR_PRIVATE/static/list/atom/queue = list() /// A list([icon] = list([state] = [appearance], ...), ...) cache of appearances. - var/static/list/state_cache = list() - + VAR_PRIVATE/static/list/state_cache = list() /// A list([icon] = [appearance], ...) cache of appearances. - var/static/list/icon_cache = list() - + VAR_PRIVATE/static/list/icon_cache = list() /// The number of appearances currently cached. - var/static/cache_size = 0 + VAR_PRIVATE/static/cache_size = 0 /datum/controller/subsystem/overlays/Recover() @@ -33,16 +29,15 @@ SUBSYSTEM_DEF(overlays) LIST_RESIZE(state_cache, 0) LIST_RESIZE(icon_cache, 0) cache_size = 0 - var/count = 0 - for (var/atom/atom) - atom.atom_flags &= ~ATOM_AWAITING_OVERLAY_UPDATE - if (++count % 500) - continue + for(var/atom/atom as anything in world) + if(atom.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) + SSoverlays.queue += atom + CHECK_TICK /datum/controller/subsystem/overlays/Initialize(start_uptime) - fire(FALSE, TRUE) + flush_queue() /datum/controller/subsystem/overlays/UpdateStat(time) @@ -51,73 +46,100 @@ SUBSYSTEM_DEF(overlays) ..({"Queued Atoms: [length(queue)], Cache Size: [cache_size]"}) -/datum/controller/subsystem/overlays/fire(resumed, no_mc_tick) - var/queue_length = length(queue) - if (queue_length) - var/atom/atom - for (var/i = 1 to queue_length) - atom = queue[i] - if (QDELETED(atom)) - continue - if (atom.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) - atom.UpdateOverlays() - if (no_mc_tick) - if (i % 1000) - continue - CHECK_TICK - else if (MC_TICK_CHECK) - queue.Cut(1, i + 1) - return - queue.Cut(1, queue_length + 1) +/datum/controller/subsystem/overlays/fire(resumed) + var/queue_position = 1 + while(length(queue) >= queue_position) + var/atom/atom_to_update = queue[queue_position] + if(!QDELETED(atom_to_update) && atom_to_update.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) + atom_to_update.UpdateOverlays() + + queue_position++ + if(MC_TICK_CHECK) + break + + queue.Cut(1, queue_position) + +/datum/controller/subsystem/overlays/proc/flush_queue() + var/queue_position = 1 + while(length(queue) >= queue_position) + process_atom_overlays_update(queue[queue_position]) + queue_position++ + CHECK_TICK + + LIST_RESIZE(queue, 0) + +/datum/controller/subsystem/overlays/proc/process_atom_overlays_update(atom/atom_to_update) + if(!QDELETED(atom_to_update) && atom_to_update.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) + atom_to_update.UpdateOverlays() /datum/controller/subsystem/overlays/proc/GetStateAppearance(icon, state) - var/list/subcache = state_cache[icon] - if (!subcache) - subcache = list() - state_cache[icon] = subcache - if (!subcache[state]) - var/image/image = image(icon, null, state) - subcache[state] = image.appearance - ++cache_size - return subcache[state] + var/list/state_to_appearance = state_cache[icon] + if(!state_to_appearance) + state_to_appearance = list() + state_cache[icon] = state_to_appearance + + var/state_appearance = state_to_appearance[state] + if(!state_appearance) + var/image/state_image = image(icon, null, state) + state_appearance = state_image.appearance + state_to_appearance[state] = state_appearance + cache_size++ + + return state_appearance /datum/controller/subsystem/overlays/proc/GetIconAppearance(icon) - if (!icon_cache[icon]) - var/image/image = image(icon) - icon_cache[icon] = image.appearance - ++cache_size - return icon_cache[icon] + var/icon_appearance = icon_cache[icon] + if (!icon_appearance) + var/image/icon_image = image(icon) + icon_appearance = icon_image.appearance + icon_cache[icon] = icon_appearance + cache_size++ + + return icon_appearance -/datum/controller/subsystem/overlays/proc/GetAppearanceList(atom/subject, list/sources) +/datum/controller/subsystem/overlays/proc/getAppearanceList(atom/subject, list/sources) if (!sources) return list() + if (!islist(sources)) sources = list(sources) + var/list/result = list() - var/icon/icon = subject.icon - var/atom/entry - for (var/i = 1 to length(sources)) - entry = sources[i] - if (!entry) + for (var/atom/source as anything in sources) + if(!source) continue - else if (istext(entry)) - result += GetStateAppearance(icon, entry) - else if (isicon(entry)) - result += GetIconAppearance(entry) + + if(istext(source)) + result += GetStateAppearance(subject.icon, source) + + else if(isicon(source)) + result += GetIconAppearance(source) + else - if (isloc(entry)) - if (entry.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) - entry.UpdateOverlays() - if (!ispath(entry)) - result += entry.appearance + if(isatom(source) && source.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) + source.UpdateOverlays() + + if(!ispath(source)) + result += source.appearance else - var/image/image = entry + var/image/image = source result += image.appearance + return result +/datum/controller/subsystem/overlays/proc/enque_atom_overlay_update(atom/atom_to_update) + if(!atom_to_update) + return + + if(atom_to_update.atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) + return + + atom_to_update.atom_flags |= ATOM_AWAITING_OVERLAY_UPDATE + SSoverlays.queue += atom_to_update + /// Immediately runs an overlay update. /atom/proc/ImmediateOverlayUpdate() @@ -147,11 +169,7 @@ SUBSYSTEM_DEF(overlays) /// Enqueues the atom for an overlay update if not already queued /atom/proc/QueueOverlayUpdate() SHOULD_NOT_OVERRIDE(TRUE) - if (atom_flags & ATOM_AWAITING_OVERLAY_UPDATE) - return - atom_flags |= ATOM_AWAITING_OVERLAY_UPDATE - SSoverlays.queue += src - + SSoverlays.enque_atom_overlay_update(src) /// Builds the atom's overlay state from caches /atom/proc/UpdateOverlays() @@ -160,6 +178,7 @@ SUBSYSTEM_DEF(overlays) if (QDELING(src)) LIST_RESIZE(overlays, 0) return + if (length(atom_protected_overlay_cache)) if (length(atom_overlay_cache)) overlays = atom_protected_overlay_cache + atom_overlay_cache @@ -203,7 +222,7 @@ SUBSYSTEM_DEF(overlays) SHOULD_NOT_OVERRIDE(TRUE) if (!sources) return - sources = SSoverlays.GetAppearanceList(src, sources) + sources = SSoverlays.getAppearanceList(src, sources) if (!length(sources)) return if (cache_target & ATOM_ICON_CACHE_PROTECTED) @@ -228,9 +247,11 @@ SUBSYSTEM_DEF(overlays) SHOULD_NOT_OVERRIDE(TRUE) if (!sources) return - sources = SSoverlays.GetAppearanceList(src, sources) + + sources = SSoverlays.getAppearanceList(src, sources) if (!length(sources)) return + var/update if (cache_target & ATOM_ICON_CACHE_PROTECTED) var/outcome = CutCacheBehavior(sources, atom_protected_overlay_cache) @@ -238,12 +259,14 @@ SUBSYSTEM_DEF(overlays) update = TRUE if (outcome == TRUE) atom_protected_overlay_cache = null + if (cache_target & ATOM_ICON_CACHE_NORMAL) var/outcome = CutCacheBehavior(sources, atom_overlay_cache) if (!isnull(outcome)) update = TRUE if (outcome == TRUE) atom_overlay_cache = null + if (update) QueueOverlayUpdate() diff --git a/code/controllers/subsystems/processing/icon_updates.dm b/code/controllers/subsystems/processing/icon_updates.dm index 1d2c918118104..5ce611a23d7f2 100644 --- a/code/controllers/subsystems/processing/icon_updates.dm +++ b/code/controllers/subsystems/processing/icon_updates.dm @@ -4,7 +4,7 @@ SUBSYSTEM_DEF(icon_update) flags = SS_TICKER priority = FIRE_PRIORITY_ICON_UPDATE init_order = SS_INIT_ICON_UPDATE - var/static/list/queue = list() + VAR_PRIVATE/static/list/queue = list() /datum/controller/subsystem/icon_update/Recover() @@ -19,44 +19,47 @@ SUBSYSTEM_DEF(icon_update) /datum/controller/subsystem/icon_update/Initialize(start_uptime) - fire(FALSE, TRUE) - - -/datum/controller/subsystem/icon_update/fire(resumed, no_mc_tick) - var/atom/atom - var/list/params - var/queue_length = length(queue) - for (var/i = 1 to queue_length) - atom = queue[i] - if (QDELETED(atom)) - continue - params = queue[atom] - if (islist(params)) - atom.update_icon(arglist(params)) - else - atom.update_icon() - if (no_mc_tick) - if (i % 100) - continue - CHECK_TICK - else if (MC_TICK_CHECK) - queue.Cut(1, i + 1) - return - if (queue_length) - queue.Cut(1, queue_length + 1) - suspend() + flush_queue() +/datum/controller/subsystem/icon_update/fire(resumed) + var/queue_position = 1 + while(length(queue) >= queue_position) + process_atom_icon_update(queue[queue_position]) + queue_position++ + if(MC_TICK_CHECK) + break + + queue.Cut(1, queue_position) + +/datum/controller/subsystem/icon_update/proc/flush_queue() + var/queue_position = 1 + while(length(queue) >= queue_position) + process_atom_icon_update(queue[queue_position]) + queue_position++ + CHECK_TICK + + LIST_RESIZE(queue, 0) + +/datum/controller/subsystem/icon_update/proc/process_atom_icon_update(atom/atom_to_update) + if(QDELETED(atom_to_update)) + return + + var/list/params = queue[atom_to_update] + if (islist(params)) + atom_to_update.update_icon(arglist(params)) + else + atom_to_update.update_icon() + +/datum/controller/subsystem/icon_update/proc/enque_atom_icon_update(atom/atom_to_update, arguments) + SSicon_update.queue[atom_to_update] = arguments /** * Adds the atom to the icon_update subsystem to be queued for icon updates. Use this if you're going to be pushing a * lot of icon updates at once. */ /atom/proc/queue_icon_update(...) - SSicon_update.queue[src] = length(args) ? args : TRUE - if (SSicon_update.suspended) - SSicon_update.wake() - + SSicon_update.enque_atom_icon_update(src, length(args) ? args : TRUE) -/hook/game_ready/proc/FlushIconUpdateQueue() - SSicon_update.fire(FALSE, TRUE) +/hook/game_ready/proc/flush_icon_update_queue() + SSicon_update.flush_queue() return TRUE diff --git a/code/game/area/area_power.dm b/code/game/area/area_power.dm index 963a86903be97..f67f32b2b282e 100644 --- a/code/game/area/area_power.dm +++ b/code/game/area/area_power.dm @@ -28,9 +28,31 @@ /area/proc/power_change() for(var/obj/machinery/M as anything in machinery_list) // for each machine in the area M.power_change() // reverify power status (to update icons etc.) + SEND_SIGNAL(src, COMSIG_AREA_POWER_CHANGE) if (fire || eject || party) update_icon() +/// Sets the apc in area. Sends COMSIG_AREA_APC_ADDED signal +/area/proc/set_apc(obj/machinery/power/apc/new_apc) + if(!istype(new_apc)) + CRASH("Invalid apc passed [log_info_line(new_apc)]") + + if(apc) + stack_trace("Apc set in area when old one is still present") + remove_apc() + + apc = new_apc + SEND_SIGNAL(src, COMSIG_AREA_APC_ADDED, new_apc) + +/// Removes current apc from area, if present. Sends COMSIG_AREA_APC_REMOVED signal +/area/proc/remove_apc() + if(!apc) + return + + SEND_SIGNAL(src, COMSIG_AREA_APC_REMOVED, apc) + apc = null + + /// Returns Integer. The total amount of power usage queued for the area from both `used_*` and `oneoff_*` for the given power channel, or all channels if `TOTAL` is passed instead. /area/proc/usage(chan) switch(chan) diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index d2e549fb6405e..ccbb2f4ac2d85 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -15,7 +15,7 @@ ///2 = wired/built, 1 = circuit installed, 0 = frame var/buildstage = 2 var/number = 0 - var/last_tick //used to delay the powercheck + var/area/linked_area intercom_handling = TRUE /obj/item/device/radio/intercom/get_storage_cost() @@ -93,7 +93,7 @@ /obj/item/device/radio/intercom/Initialize(loc, dir, atom/frame) . = ..() - START_PROCESSING(SSobj, src) + find_and_set_linked_area() if (dir) set_dir(dir) @@ -148,10 +148,6 @@ . = ..() internal_channels[num2text(RAID_FREQ)] = list(access_syndicate) -/obj/item/device/radio/intercom/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - /obj/item/device/radio/intercom/attack_ai(mob/user) add_fingerprint(user) if (buildstage == 2) @@ -322,26 +318,6 @@ .["Wirecutters"] += "<p>Used for deconstruction. See deconstruction steps.</p>" .["Wrench"] += "<p>Used for deconstruction. See deconstruction steps.</p>" -/obj/item/device/radio/intercom/Process() - if (wiresexposed) - on = FALSE - return - if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0)) - last_tick = world.timeofday - var/old_on = on - - if(!src.loc) - on = FALSE - else - var/area/A = get_area(src) - if(!A) - on = FALSE - else - on = A.powered(EQUIP) // set "on" to the power status - - if (on != old_on) - update_icon() - /obj/item/device/radio/intercom/on_update_icon() if (buildstage == 2 && wiresexposed) icon_state = "intercom-b2" @@ -349,10 +325,11 @@ icon_state = "intercom-b1" else if (buildstage == 0) icon_state = "intercom-f" - else if (!on) - icon_state = "intercom-p" else - icon_state = "intercom_[broadcasting][listening]" + if(on) + icon_state = "intercom_[broadcasting][listening]" + else + icon_state = "intercom-p" /obj/item/device/radio/intercom/ToggleBroadcast() ..() @@ -362,6 +339,39 @@ ..() update_icon() +/obj/item/device/radio/intercom/proc/find_and_set_linked_area() + var/area/target_area = get_area(src) + if(!target_area.apc) + RegisterSignal(target_area, COMSIG_AREA_APC_ADDED, PROC_REF(on_apc_add)) + return + + on_apc_add(target_area) + +/obj/item/device/radio/intercom/proc/on_apc_add(area/apc_area) + SIGNAL_HANDLER + + UnregisterSignal(apc_area, COMSIG_AREA_APC_ADDED) + linked_area = apc_area + RegisterSignal(apc_area, COMSIG_AREA_APC_REMOVED, PROC_REF(on_apc_removal)) + RegisterSignal(apc_area, COMSIG_AREA_POWER_CHANGE, PROC_REF(change_status)) + +/obj/item/device/radio/intercom/proc/on_apc_removal(area/apc_area) + SIGNAL_HANDLER + + UnregisterSignal(apc_area, COMSIG_AREA_APC_REMOVED) + UnregisterSignal(apc_area, COMSIG_AREA_POWER_CHANGE) + linked_area = null + on = FALSE + update_icon() + + RegisterSignal(apc_area, COMSIG_AREA_APC_ADDED, PROC_REF(on_apc_add)) + +/obj/item/device/radio/intercom/proc/change_status() + SIGNAL_HANDLER + + on = linked_area.powered(EQUIP) + update_icon() + /obj/item/device/radio/intercom/broadcasting broadcasting = 1 diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 649e52794e871..01c6ea536ad95 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -176,7 +176,7 @@ area = A if(autoname) SetName("\improper [area.name] APC") - area.apc = src + area.set_apc(src) . = ..() @@ -193,8 +193,8 @@ power_change() /obj/machinery/power/apc/Destroy() - src.update() - area.apc = null + update() + area.remove_apc() area.power_light = 0 area.power_equip = 0 area.power_environ = 0