From 832a16c75fc16df6224d07dd69ac3a7464272de9 Mon Sep 17 00:00:00 2001 From: PhantornRU <41479614+PhantornRU@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:10:10 +1000 Subject: [PATCH] [PORT FEAT] Borg Hats (#497) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Порт моего старого ПРа: https://github.com/ss220-space/Paradise/pull/1318 ## Что этот PR делает На силиконов теперь можно надеть шапки. Изменения: - У каждого силикона и модуля имеются свои оффсеты и правила - Хуманизированные борги могут носить шлема - Хуманизированные борги с встроенными шляпами - не могут носить шляпы. - Головной убор надевается в слот головы - HELP-intent с шляпой в руке - надевает её на силикона. - GRAB-intent с пустой рукой - снимает с силикона шляпу. - ГИБ и деконструкт - роняет головной убор - Смена модуля - изменяет ОФФсет под текущий модуль - Готовые борги с модулями (синди, дезсквад, дестроеры) сразу имеют нужные оффсеты и правила. - Дроны могут носить головной убор - ИИ может носить не-шлемовые головные уборы - Новые силиконы сразу корректно инициализируются, из-за чего можно создать сразу боргов со шляпами, если то требуется. - Кувырок силикона снимает с него шляпу. ПИИ ущемлены и не умеют носить шапки, так как у них имеются разные состояния анимации, а мне лень ими заниматься. ## Почему это хорошо для игры Ассистенты и экипаж получают возможности угнетать силиконов, у которых нет ручек снять шляпы. Портируем нашу возможность надевать на боргов шапки. Я накодил это кучу лет назад, я и портировал. Уот так уот. ## Изображения изменений ### Разные модули: ![image](https://user-images.githubusercontent.com/41479614/188896565-b8f47a7b-9d65-46f5-aab9-00bd6eb394ef.png) Скриншот чутка устарел. Коробочные борги во второй колонне были поправлены. ### Написание в чате производимых действий ![image](https://user-images.githubusercontent.com/41479614/188897764-20f0f8b5-6d59-4012-b0c2-6ac91c3cbf5a.png) ## Тестирование ![image](https://github.com/ss220club/Paradise-SS220/assets/41479614/f04c4526-c3c2-48b5-a8cf-801668d1ce4a) ![image](https://github.com/ss220club/Paradise-SS220/assets/41479614/09f9ad5f-b7ee-4a45-8d03-9b888f9e118d) ## Changelog :cl: add: Силиконы могут носить шляпы add: Обработка шляп, индивидуальные оффсеты для разных модулей боргов, установка шляпы хелп-интентом, снятие шляпы граб-интентом, разбор/гиб сбрасывают шляпу add: Кувырок силикона снимает с него шляпу /:cl: --- modular_ss220/modular_ss220.dme | 1 + modular_ss220/silicon_hats/_silicon_hats.dm | 4 + modular_ss220/silicon_hats/_silicon_hats.dme | 4 + .../silicon_hats/code/silicon_hats.dm | 218 ++++++++++++++++++ .../silicon_hats/code/silicon_interactions.dm | 101 ++++++++ 5 files changed, 328 insertions(+) create mode 100644 modular_ss220/silicon_hats/_silicon_hats.dm create mode 100644 modular_ss220/silicon_hats/_silicon_hats.dme create mode 100644 modular_ss220/silicon_hats/code/silicon_hats.dm create mode 100644 modular_ss220/silicon_hats/code/silicon_interactions.dm diff --git a/modular_ss220/modular_ss220.dme b/modular_ss220/modular_ss220.dme index 1dd6f4ce49d5..83f04b970dc9 100644 --- a/modular_ss220/modular_ss220.dme +++ b/modular_ss220/modular_ss220.dme @@ -32,6 +32,7 @@ #include "vending/vending.dme" #include "wire_splicing/wiresplicing.dme" #include "silicons/_silicons.dme" +#include "silicon_hats/_silicon_hats.dme" // --- MISC --- // #include "administration/_administration.dme" diff --git a/modular_ss220/silicon_hats/_silicon_hats.dm b/modular_ss220/silicon_hats/_silicon_hats.dm new file mode 100644 index 000000000000..96493c8ca55f --- /dev/null +++ b/modular_ss220/silicon_hats/_silicon_hats.dm @@ -0,0 +1,4 @@ +/datum/modpack/silicon_hats + name = "Silicon Hats" + desc = "На силиконов можно надеть шапочки." + author = "PhantomRU" diff --git a/modular_ss220/silicon_hats/_silicon_hats.dme b/modular_ss220/silicon_hats/_silicon_hats.dme new file mode 100644 index 000000000000..a858c11dcfbe --- /dev/null +++ b/modular_ss220/silicon_hats/_silicon_hats.dme @@ -0,0 +1,4 @@ +#include "_silicon_hats.dm" + +#include "code/silicon_hats.dm" +#include "code/silicon_interactions.dm" diff --git a/modular_ss220/silicon_hats/code/silicon_hats.dm b/modular_ss220/silicon_hats/code/silicon_hats.dm new file mode 100644 index 000000000000..a1c501300f31 --- /dev/null +++ b/modular_ss220/silicon_hats/code/silicon_hats.dm @@ -0,0 +1,218 @@ +/mob/living/silicon + var/obj/item/inventory_head + + var/hat_offset_y = -3 + var/is_centered = FALSE // центрирован ли синтетик. Если нет, то шляпа будет растянута + + var/list/blacklisted_hats = list( // Запрещенные шляпы на ношение для боргов с большими головами + /obj/item/clothing/head/helmet, + /obj/item/clothing/head/welding, + /obj/item/clothing/head/snowman, + /obj/item/clothing/head/bio_hood, + /obj/item/clothing/head/bomb_hood, + /obj/item/clothing/head/blob, + /obj/item/clothing/head/chicken, + /obj/item/clothing/head/corgi, + /obj/item/clothing/head/cueball, + /obj/item/clothing/head/hardhat/pumpkinhead, + /obj/item/clothing/head/radiation, + /obj/item/clothing/head/papersack, + /obj/item/clothing/head/human_head, + /obj/item/clothing/head/kitty, + /obj/item/clothing/head/hardhat/reindeer, + /obj/item/clothing/head/cardborg, + ) + + var/hat_icon_file = 'icons/mob/clothing/head.dmi' + var/hat_icon_state + var/hat_alpha + var/hat_color + + var/can_be_hatted = FALSE + var/can_wear_blacklisted_hats = FALSE + +/mob/living/silicon/robot/drone + hat_offset_y = -15 + is_centered = TRUE + can_be_hatted = TRUE + can_wear_blacklisted_hats = TRUE + +/mob/living/silicon/ai + hat_offset_y = 3 + is_centered = TRUE + can_be_hatted = TRUE + +/mob/living/silicon/robot/proc/robot_module_hat_offset(module) + switch(module) + // хуманоидные броботы с шляпами + if("Engineering", "Miner_old", "JanBot2", "Medbot", "engineerrobot", "maximillion", "secborg", "Hydrobot") + can_be_hatted = FALSE + hat_offset_y = -1 + if("Noble-CLN", "Noble-SRV", "Noble-DIG", "Noble-MED", "Noble-SEC", "Noble-ENG", "Noble-STD") //Высотой: 32 пикселя + can_be_hatted = TRUE + can_wear_blacklisted_hats = TRUE + hat_offset_y = 4 + if("droid-medical") // Высотой: 32 пикселя + can_be_hatted = TRUE + can_wear_blacklisted_hats = TRUE + hat_offset_y = 4 + if("droid-miner", "mk2", "mk3") // Высотой: 32 большая голова, шарообразные + can_be_hatted = TRUE + is_centered = TRUE + hat_offset_y = 3 + if("bloodhound", "nano_bloodhound", "syndie_bloodhound", "ertgamma")//Высотой: 31 + can_be_hatted = TRUE + hat_offset_y = 1 + if("Cricket-SEC", "Cricket-MEDI", "Cricket-JANI", "Cricket-ENGI", "Cricket-MINE", "Cricket-SERV") //Высотой: 31 + can_be_hatted = TRUE + hat_offset_y = 2 + if("droidcombat-shield", "droidcombat") // Высотой: 31 + can_be_hatted = TRUE + hat_alpha = 255 + hat_offset_y = 2 + if("droidcombat-roll") + can_be_hatted = TRUE + hat_alpha = 0 + hat_offset_y = 2 + if("syndi-medi", "surgeon", "toiletbot") // Высотой: 30 + can_be_hatted = TRUE + is_centered = TRUE + hat_offset_y = 1 + if("Security", "janitorrobot", "medicalrobot") // Высотой: 29 + can_be_hatted = TRUE + is_centered = TRUE + can_wear_blacklisted_hats = TRUE + hat_offset_y = -1 + if("Brobot", "Service", "robot+o+c", "robot_old", "securityrobot", //Высотой: 28 + "rowtree-engineering", "rowtree-lucy", "rowtree-medical", "rowtree-security") //Бабоботы + can_be_hatted = TRUE + is_centered = TRUE + can_wear_blacklisted_hats = TRUE + hat_offset_y = -1 + if("Miner", "lavaland") // Высотой: 27 + can_be_hatted = TRUE + hat_offset_y = -1 + if("robot", "Standard", "Standard-Secy", "Standard-Medi", "Standard-Engi", + "Standard-Jani", "Standard-Serv", "Standard-Mine", "xenoborg-state-a") //Высотой: 26 + can_be_hatted = TRUE + hat_offset_y = -3 + if("droid") // Высотой: 25 + can_be_hatted = TRUE + is_centered = TRUE + can_wear_blacklisted_hats = TRUE + hat_offset_y = -3 + if("landmate", "syndi-engi") // Высотой: 24 пикселя макушка + can_be_hatted = TRUE + hat_offset_y = -3 + if("mopgearrex") // Высотой: 22 + can_be_hatted = TRUE + hat_offset_y = -6 + + if(inventory_head) + if (!can_be_hatted) + remove_from_head(usr) + return + if (!can_wear_blacklisted_hats && is_type_in_list(inventory_head, blacklisted_hats)) + remove_from_head(usr) + return + +/mob/living/silicon/proc/hat_icons() + if(inventory_head) + overlays += get_hat_overlay() + +/mob/living/silicon/regenerate_icons() + overlays.Cut() + ..() + + if(inventory_head) + var/image/head_icon + + if(inventory_head.icon_override) // Для модульных шапок + hat_icon_file = inventory_head.icon_override + if(!hat_icon_state) + hat_icon_state = inventory_head.icon_state + if(!hat_alpha) + hat_alpha = inventory_head.alpha + if(!hat_color) + hat_color = inventory_head.color + + head_icon = get_hat_overlay() + + add_overlay(head_icon) + +/mob/living/silicon/proc/get_hat_overlay() + if(hat_icon_file && hat_icon_state) + var/image/borgI = image(hat_icon_file, hat_icon_state) + borgI.alpha = hat_alpha + borgI.color = hat_color + borgI.pixel_y = hat_offset_y + if (!is_centered) + borgI.transform = matrix(1.125, 0, 0.5, 0, 1, 0) + return borgI + +/mob/living/silicon/proc/place_on_head(obj/item/item_to_add, mob/user) + if(!item_to_add) + user.visible_message(span_notice("[user] похлопывает по голове [src]."), span_notice("Вы положили руку на голову [src].")) + if(flags_2 & HOLOGRAM_2) + return FALSE + return FALSE + + if(!istype(item_to_add, /obj/item/clothing/head/)) + to_chat(user, span_warning("[item_to_add] нельзя надеть на голову [src]!")) + return FALSE + + if(!can_be_hatted) + to_chat(user, span_warning("[item_to_add] нельзя надеть на голову [src]! Похоже у него уже есть встроенная шляпа.")) + return FALSE + + if(inventory_head) + if(user) + to_chat(user, span_warning("Нельзя надеть больше одного головного убора на голову [src]!")) + return FALSE + + if(user && !user.unEquip(item_to_add)) + to_chat(user, span_warning("[item_to_add] застрял в ваших руках, вы не можете его надеть на голову [src]!")) + return FALSE + + if (!can_wear_blacklisted_hats && is_type_in_list(item_to_add, blacklisted_hats)) + to_chat(user, span_warning("[item_to_add] не помещается на голову [src]!")) + return FALSE + + user.visible_message(span_notice("[user] надевает [item_to_add] на голову [real_name]."), + span_notice("Вы надеваете [item_to_add] на голову [real_name]."), + span_italics("Вы слышите как что-то нацепили.")) + item_to_add.forceMove(src) + inventory_head = item_to_add + regenerate_icons() + + return TRUE + +/mob/living/silicon/proc/remove_from_head(mob/user) + if(inventory_head) + if(inventory_head.flags & NODROP) + to_chat(user, span_warning("[inventory_head.name] застрял на головном корпусе [src]! Его невозможно снять!")) + return TRUE + + to_chat(user, span_warning("Вы сняли [inventory_head.name] с головного корпуса [src].")) + user.put_in_hands(inventory_head) + + null_hat() + + regenerate_icons() + else + to_chat(user, span_warning("На головном корпусе [src] нет головного убора!")) + return FALSE + + return TRUE + +/mob/living/silicon/proc/drop_hat() + if(inventory_head) + unEquip(inventory_head) + null_hat() + regenerate_icons() + +/mob/living/silicon/proc/null_hat() + inventory_head = null + hat_icon_state = null + hat_alpha = null + hat_color = null diff --git a/modular_ss220/silicon_hats/code/silicon_interactions.dm b/modular_ss220/silicon_hats/code/silicon_interactions.dm new file mode 100644 index 000000000000..7aefa091aa50 --- /dev/null +++ b/modular_ss220/silicon_hats/code/silicon_interactions.dm @@ -0,0 +1,101 @@ +/mob/living/silicon/robot/update_icons() + . = ..() + hat_icons() + +/mob/living/silicon/robot/drone/update_icons() + . = ..() + hat_icons() + +/mob/living/silicon/death(gibbed) + if(gibbed) + drop_hat() + . = ..() + +/mob/living/silicon/robot/deconstruct() + drop_hat() + . = ..() + +/mob/living/silicon/robot/get_module_sprites(selected_module) + . = ..() + robot_module_hat_offset(icon_state) + +/mob/living/silicon/grabbedby(mob/living/user) + remove_from_head(user) + +// Если вдруг кто-то захочет сразу спавнить боргов с шапками +/mob/living/silicon/Initialize(mapload) + . = ..() + regenerate_icons() + +// Для уже готовых спавнов боевых боргов +/mob/living/silicon/robot/Initialize(mapload) + . = ..() + robot_module_hat_offset(icon_state) + +/mob/living/silicon/robot/initialize_module(selected_module, selected_sprite, list/module_sprites) + . = ..() + robot_module_hat_offset(icon_state) + +/datum/emote/flip/run_emote(mob/user, params, type_override, intentional) + . = ..() + if(isrobot(user)) + var/mob/living/silicon/robot/borg = user + message = "кувырком опрокинул шляпу!" + borg.drop_hat() + +/mob/living/silicon/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/clothing/head) && user.a_intent == INTENT_HELP) + place_on_head(user.get_active_hand(), user) + return TRUE + . = ..() + +/mob/living/silicon/Topic(href, href_list) + if(..()) + return TRUE + + if(!(iscarbon(usr) || usr.incapacitated() || !Adjacent(usr))) + usr << browse(null, "window=mob[UID()]") + usr.unset_machine() + return FALSE + + if (!can_be_hatted) + return FALSE + + if(href_list["remove_inv"]) + var/remove_from = href_list["remove_inv"] + switch(remove_from) + if("head") + remove_from_head(usr) + show_inv(usr) + + else if(href_list["add_inv"]) + var/add_to = href_list["add_inv"] + switch(add_to) + if("head") + place_on_head(usr.get_active_hand(), usr) + show_inv(usr) + + if(usr != src) + return TRUE + +/mob/living/silicon/show_inv(mob/user) + if(user.incapacitated() || !Adjacent(user)) + return FALSE + user.set_machine(src) + + var/dat = {"
Inventory of [name]

"} + dat += "
Head: [inventory_head]" : "add_inv=head'>Nothing"]" + + var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 500) + popup.set_content(dat) + popup.open() + +/mob/living/silicon/robot/examine(mob/user) + . = ..() + if(inventory_head) + . += "\nНосит [bicon(inventory_head)] [inventory_head.name].\n" + +/mob/living/silicon/ai/examine(mob/user) + . = ..() + if(inventory_head) + . += "\nНа корпусе расположился [bicon(inventory_head)] [inventory_head.name].\n"