diff --git a/code/__DEFINES/alerts.dm b/code/__DEFINES/alerts.dm index ff1b29e883e..af8eb6f8353 100644 --- a/code/__DEFINES/alerts.dm +++ b/code/__DEFINES/alerts.dm @@ -30,3 +30,10 @@ /** Silicon related */ #define ALERT_LOCKED "locked" +/** Mech related */ +// SCS-3 Cage +#define CAGE_STAGE_ZERO "stage_zero" +#define CAGE_STAGE_ONE "stage_one" +#define CAGE_STAGE_TWO "stage_two" +#define CAGE_STAGE_THREE "stage_three" + diff --git a/code/__DEFINES/traits/sources.dm b/code/__DEFINES/traits/sources.dm index 92565ab1354..d0ee17e48bd 100644 --- a/code/__DEFINES/traits/sources.dm +++ b/code/__DEFINES/traits/sources.dm @@ -110,6 +110,10 @@ #define STAMINA_TRAIT "stamina" +/// source trait for /obj/item/mecha_parts/mecha_equipment/cage +#define MECH_SUPRESSED_TRAIT "mech_supress" + + /// trait associated to resting #define RESTING_TRAIT "resting" /// trait associated to a stat value or range of diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 4a0132a6645..3a8e66de69b 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -563,6 +563,43 @@ so as to remain in compliance with the most up-to-date laws." desc = "Maintenance protocols are currently in effect, most actions disabled." icon_state = "locked" +/atom/movable/screen/alert/empty_alert + name = "" + desc = "" + +// MECH MODULES + +// cage module +/atom/movable/screen/alert/mech_cage + name = "Ты не должен это видеть" + desc = "Ну и это тоже" + icon = 'icons/obj/mecha/mecha_cage.dmi' + var/stage_define + +/atom/movable/screen/alert/mech_cage/zero + name = "Нулевой этап" + desc = "Модуль не работает." + icon_state = "stage_0" + stage_define = CAGE_STAGE_ZERO + +/atom/movable/screen/alert/mech_cage/one + name = "Первый этап" + desc = "Модуль работает в режиме удержания." + icon_state = "stage_1" + stage_define = CAGE_STAGE_ONE + +/atom/movable/screen/alert/mech_cage/two + name = "Второй этап" + desc = "Модуль работает в режиме удержания цели в наручниках." + icon_state = "stage_2" + stage_define = CAGE_STAGE_TWO + +/atom/movable/screen/alert/mech_cage/three + name = "Третий этап" + desc = "Модуль работает в режиме заключения." + icon_state = "stage_3" + stage_define = CAGE_STAGE_THREE + //GUARDIANS /atom/movable/screen/alert/cancharge name = "Charge Ready" diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index 35188b7f1fe..6fe7cb3797c 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -32,6 +32,9 @@ /obj/effect/proc_holder/spell/ethereal_jaunt/proc/do_jaunt(mob/living/target) playsound(get_turf(target), sound_in, 50, TRUE, -1) + // mech supress escape + if(HAS_TRAIT_FROM(target, TRAIT_IMMOBILIZED, MECH_SUPRESSED_TRAIT)) + target.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) ADD_TRAIT(target, TRAIT_NO_TRANSFORM, UNIQUE_TRAIT_SOURCE(src)) var/turf/mobloc = get_turf(target) var/obj/effect/dummy/spell_jaunt/holder = new jaunt_type_path(mobloc) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 6418d850862..78f287d2f27 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -134,6 +134,9 @@ return playsound(user.loc, 'sound/effects/bamf.ogg', 50, 1) + // mech supress escape + if(HAS_TRAIT_FROM(user, TRAIT_IMMOBILIZED, MECH_SUPRESSED_TRAIT)) + user.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) user.visible_message("[user] vanishes in a puff of black mist!", "You enter the space between worlds as a passageway.") user.SetStunned(0) user.SetWeakened(0) diff --git a/code/game/mecha/combat/sidewinder.dm b/code/game/mecha/combat/sidewinder.dm index fdd825087bc..93fe240bbd7 100644 --- a/code/game/mecha/combat/sidewinder.dm +++ b/code/game/mecha/combat/sidewinder.dm @@ -87,3 +87,5 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/cage + ME.attach(src) diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index cde0a1a6108..ae4b6796668 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -23,6 +23,7 @@ var/selectable = MODULE_SELECTABLE_FULL var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist. var/integrated = FALSE // Preventing modules from getting detached. + var/alert_category = "mecha_module" //change if you want custom alerts /obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() @@ -181,6 +182,9 @@ return if(chassis.occupant) remove_targeted_action() + if(chassis.selected == src) + if(selectable == MODULE_SELECTABLE_FULL) + chassis.occupant.clear_alert(alert_category) detach_act() moveto = moveto || get_turf(chassis) if(Move(moveto)) @@ -224,10 +228,27 @@ return /obj/item/mecha_parts/mecha_equipment/proc/select_module() + select_set_alert() chassis.selected = src chassis.occupant_message(span_notice("You switch to [src].")) chassis.visible_message("[chassis] raises [src]") send_byjax(chassis.occupant, "exosuit.browser", "eq_list", chassis.get_equipment_list()) +/obj/item/mecha_parts/mecha_equipment/proc/select_set_alert() + if(selectable == MODULE_SELECTABLE_FULL) + var/mob/living/carbon/occupant = chassis.occupant + if(chassis.selected) + occupant.clear_alert(chassis.selected.alert_category) + return throw_default_alert(occupant) + return FALSE + +/obj/item/mecha_parts/mecha_equipment/proc/throw_default_alert(var/mob/living/carbon/occupant) + if(alert_category == "mecha_module") + var/atom/movable/screen/alert/empty_alert/default_alert = occupant.throw_alert(alert_category, /atom/movable/screen/alert/empty_alert, new_master = src) + default_alert.name = name + default_alert.desc = "Выбран модуль [src.name]" + return TRUE + return FALSE + /obj/item/mecha_parts/mecha_equipment/proc/toggle_module() return diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index e4490d9fe6a..d201b4adb2e 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -1,5 +1,5 @@ // Teleporter, Wormhole generator, Gravitational catapult, Armor booster modules, -// Repair droid, Tesla Energy relay, Generators +// Repair droid, Tesla Energy relay, Generators, SCS-3 Cage ////////////////////////////////////////////// TELEPORTER /////////////////////////////////////////////// @@ -590,3 +590,285 @@ var/obj/mecha/working/W = loc W.slow_pressure_step_in = initial(W.slow_pressure_step_in) W.fast_pressure_step_in = initial(W.fast_pressure_step_in) + + +// SCS-3 CAGE + +/obj/item/mecha_parts/mecha_equipment/cage + name = "Клетка SCS-3" + desc = "Модуль для экзокостюмов, используемый в задержании преступников." + icon_state = "mecha_cage" + origin_tech = "combat=6;materials=5" + equip_cooldown = 3 SECONDS + energy_drain = 500 + range = MECHA_MELEE + salvageable = FALSE + harmful = FALSE + alert_category = "mecha_cage" + + var/mob/living/carbon/prisoner + var/mob/living/carbon/holding + ///for custom icons + var/datum/action/innate/mecha/select_module/button + ///wacky case + var/current_stage + var/obj/effect/supress/supress_effect + +/obj/item/mecha_parts/mecha_equipment/cage/can_attach(obj/mecha/M) + if(..()) + if(locate(src) in M.equipment) + return FALSE + if(istype(M, /obj/mecha/combat/durand) || istype(M, /obj/mecha/combat/lockersyndie) || istype(M, /obj/mecha/combat/marauder)) + return TRUE + else if(M.emagged == TRUE) + return TRUE + return FALSE + +/obj/item/mecha_parts/mecha_equipment/cage/Destroy() + for(var/atom/movable/AM in src) + AM.forceMove(get_turf(src)) + if(holding) + stop_supressing(holding) + + prisoner = null + holding = null + return ..() + +/obj/item/mecha_parts/mecha_equipment/cage/select_set_alert() + . = ..() + if(!.) + if(prisoner) + change_alert(CAGE_STAGE_THREE) + else if(holding) + if(!holding.handcuffed) + change_alert(CAGE_STAGE_ONE) + else + change_alert(CAGE_STAGE_TWO) + else + change_alert(CAGE_STAGE_ZERO) + +/obj/item/mecha_parts/mecha_equipment/cage/action(mob/living/carbon/target) + if(!action_checks(target)) + return FALSE + if(!istype(target)) + return FALSE + + var/same_target = target == holding + var/supress_check = target.IsStamcrited() || (target.health <= HEALTH_THRESHOLD_CRIT) || target.stat != CONSCIOUS + + //SUPRESSING + if(((holding && !same_target) || !holding) && supress_check) + supress_action(target) + return TRUE + + //HANDCUFFING + if(same_target && !target.handcuffed) + handcuff_action(target) + return TRUE + + //PUTTING INTO MECH + if(same_target && target.handcuffed) + insert_action(target) + return TRUE + + occupant_message(span_notice("[target] не может быть удержа[genderize_ru(target.gender, "н", "на", "но", "ны")], так как [target] не находится в критическом состоянии")) + return FALSE + +/obj/item/mecha_parts/mecha_equipment/cage/proc/supress_action(mob/living/carbon/target) + if(holding) + occupant_message(span_notice("Ты перестаёшь удерживать [holding], и начинаешь удерживать [target]...")) + chassis.visible_message(span_warning("[chassis] перестаёт удерживать [holding] и сменяется на [target].")) + stop_supressing(holding) + set_supress_effect(target) + if(!do_after_cooldown(target)) + qdel(supress_effect) + supress_effect = null + return FALSE + if(!prisoner) + change_alert(CAGE_STAGE_ONE) + supress(target) + else + occupant_message(span_notice("Ты начинаешь удерживать [target]...")) + chassis.visible_message(span_warning("[chassis] начинает удерживать [target].")) + supress_effect = new(target.loc) + set_supress_effect(target) + if(!do_after_cooldown(target)) + qdel(supress_effect) + supress_effect = null + return FALSE + if(!prisoner) + change_alert(CAGE_STAGE_ONE) + supress(target) + +/obj/item/mecha_parts/mecha_equipment/cage/proc/handcuff_action(mob/living/carbon/target) + occupant_message(span_notice("Ты начинаешь сковывать [target]...")) + chassis.visible_message(span_warning("[chassis] начинает сковывать [target].")) + if(!do_after_cooldown(target)) + return FALSE + if(!prisoner) + change_alert(CAGE_STAGE_TWO) + target.apply_restraints(new /obj/item/restraints/handcuffs, ITEM_SLOT_HANDCUFFED, TRUE) + occupant_message(span_notice("Ты успешно сковал [target]...")) + chassis.visible_message(span_warning("[chassis] успешно сковал [target].")) + add_attack_logs(chassis.occupant, target, "shackled") + +/obj/item/mecha_parts/mecha_equipment/cage/proc/insert_action(mob/living/carbon/target) + if(!prisoner_insertion_check(target)) + return FALSE + if(!button) + for(var/datum/action/innate/mecha/select_module/H in chassis.occupant.actions) + if(H.button_icon_state == "mecha_cage") + button = H + break + + change_state("mecha_cage_activate") + occupant_message(span_notice("Ты начинаешь помещать [target] внутрь клетки...")) + chassis.visible_message(span_warning("[chassis] начинает помещать [target] внутрь клетки.")) + if(!do_after_cooldown(target)) + change_state("mecha_cage") + return FALSE + change_state("mecha_cage_activated") + change_alert(CAGE_STAGE_THREE) + prisoner = target + target.forceMove(src) + stop_supressing(target) + UnregisterSignal(target, COMSIG_MOVABLE_MOVED) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_escape)) + update_equip_info() + occupant_message(span_notice("[target] успешно загруже[genderize_ru(target.gender, "н", "на", "но", "ны")].")) + chassis.visible_message(span_warning("[chassis] загружает [target] в клетку.")) + log_message("[target] loaded.") + +/obj/item/mecha_parts/mecha_equipment/cage/proc/supress(mob/living/carbon/target) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + holding = target + target.add_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) + target.move_resist = MOVE_FORCE_STRONG + supress_effect.icon_state = "applied" + +/obj/item/mecha_parts/mecha_equipment/cage/proc/stop_supressing(mob/living/carbon/target) + UnregisterSignal(target, COMSIG_MOVABLE_MOVED) + holding = null + target.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) + target.move_resist = MOVE_FORCE_DEFAULT + qdel(supress_effect) + supress_effect = null + + if(!prisoner) + change_alert(CAGE_STAGE_ZERO) + +/obj/item/mecha_parts/mecha_equipment/cage/proc/on_moved(mob/living/carbon/target) + SIGNAL_HANDLER + stop_supressing(target) + +/obj/item/mecha_parts/mecha_equipment/cage/proc/on_escape(mob/living/carbon/target) + SIGNAL_HANDLER + occupant_message("[prisoner] сбежа[genderize_ru(target.gender, "л", "ла", "ло", "лы")].") + log_message("[prisoner] сбежа[genderize_ru(target.gender, "л", "ла", "ло", "лы")].") + prisoner = null + if(holding) + if(holding.handcuffed) + change_alert(CAGE_STAGE_TWO) + else + change_alert(CAGE_STAGE_ONE) + else + change_alert(CAGE_STAGE_ZERO) + change_state("mecha_cage") + update_equip_info() + UnregisterSignal(target, COMSIG_MOVABLE_MOVED) + +/obj/item/mecha_parts/mecha_equipment/cage/proc/change_state(icon) + button.button_icon_state = icon + flick(icon, button) + button.UpdateButtonIcon() + +/obj/item/mecha_parts/mecha_equipment/cage/proc/change_alert(var/stage_define) + var/mob/living/carbon/H = chassis.occupant + for(var/I in subtypesof(/atom/movable/screen/alert/mech_cage)) + var/atom/movable/screen/alert/mech_cage/alert = I + if(alert.stage_define == stage_define) + H.throw_alert(alert_category, alert) + break + + current_stage = stage_define + + +/obj/item/mecha_parts/mecha_equipment/cage/proc/set_supress_effect(mob/living/carbon/target) + supress_effect = new(target.loc) + flick("effect_on_doll", supress_effect) + +/obj/item/mecha_parts/mecha_equipment/cage/proc/prisoner_insertion_check(mob/living/carbon/target) + if(target.buckled) + occupant_message(span_warning("[target] не помест[pluralize_ru(target.gender, "ится", "ятся")] в клетку, так как [target] прикова[genderize_ru(target.gender, "н", "нна", "нно", "нны")] к [target.buckled]!")) + return FALSE + if(target.has_buckled_mobs()) + occupant_message(span_warning("[target] не помест[pluralize_ru(target.gender, "ится", "ятся")] в клетку из-за прикованных к [genderize_ru(target.gender, "нему", "ней", "нему", "ним")] животным!")) + return FALSE + if(prisoner) + occupant_message(span_warning("Клетка уже занята!")) + return FALSE + return TRUE + +/obj/item/mecha_parts/mecha_equipment/cage/proc/eject(force) + if(!action_checks(src)) + return FALSE + if(!prisoner) + return FALSE + if(holding) + if(holding.handcuffed) + change_alert(CAGE_STAGE_TWO) + else + change_alert(CAGE_STAGE_ONE) + else + change_alert(CAGE_STAGE_ZERO) + UnregisterSignal(prisoner, COMSIG_MOVABLE_MOVED) + prisoner.forceMove(get_turf(src)) + if(!force) + occupant_message("[prisoner] извлеч[genderize_ru(prisoner.gender, "ён", "ена", "ено", "ены")].") + log_message("[prisoner] извлеч[genderize_ru(prisoner.gender, "ён", "ена", "ено", "ены")].") + else + occupant_message("[prisoner] сбежа[genderize_ru(prisoner.gender, "л", "ла", "ло", "ли")].") + log_message("[prisoner] сбежа[genderize_ru(prisoner.gender, "л", "ла", "ло", "ли")].") + prisoner = null + change_state("mecha_cage") + update_equip_info() + +/obj/item/mecha_parts/mecha_equipment/cage/can_detach() + if(prisoner || holding) + occupant_message(span_warning("Невозможно отсоединить [src] - модуль работает!")) + return FALSE + return TRUE + +/obj/item/mecha_parts/mecha_equipment/cage/detach_act() + button = null + +/obj/item/mecha_parts/mecha_equipment/cage/get_module_equip_info() + if(prisoner) + return "
\[Задержанн[genderize_ru(prisoner.gender, "ый", "ая", "ое", "ые")]: [prisoner] \]
Eject" + +/obj/item/mecha_parts/mecha_equipment/cage/Topic(href,href_list) + ..() + var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) + if(afilter.get("eject")) + eject(FALSE) + return + +/obj/item/mecha_parts/mecha_equipment/cage/container_resist() + if(prisoner.get_item_by_slot(ITEM_SLOT_CLOTH_OUTER)) + var/obj/item/clothing/suit/straight_jacket/H = prisoner.get_item_by_slot(ITEM_SLOT_CLOTH_OUTER) + prisoner.cuff_resist(H, FALSE) + return + if(prisoner.handcuffed) + prisoner.cuff_resist(prisoner.handcuffed, FALSE) + return + if(do_after(prisoner, 30 SECONDS, prisoner)) + eject(TRUE) + +/obj/effect/supress + name = "Клешни экзокостюма" + desc = "Сейчас кого-то своруют..." + icon = 'icons/misc/supress_effect.dmi' + icon_state = "effect_on_doll" + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + plane = ABOVE_GAME_PLANE diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 77bf40091d7..e155496d2db 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -21,6 +21,7 @@ var/can_move = 0 // time of next allowed movement var/mech_enter_time = 4 SECONDS // Entering mecha time var/mob/living/carbon/occupant = null + var/step_in = 10 //make a step in step_in/10 sec. var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South. var/normal_step_energy_drain = 10 @@ -409,6 +410,11 @@ occupant_message(span_danger("Unable to move while in zoom mode.")) last_message = world.time return FALSE + if(locate(/obj/item/mecha_parts/mecha_equipment/cage) in equipment) + var/obj/item/mecha_parts/mecha_equipment/cage/H = locate(/obj/item/mecha_parts/mecha_equipment/cage) in equipment + if(H.holding) + occupant_message(span_notice("Ты перестаёшь удерживать [H.holding].")) + H.stop_supressing(H.holding) //Turns strafe OFF if not enough energy to step (with actuator module only) if(strafe && actuator && !has_charge(actuator.energy_per_step)) @@ -1165,6 +1171,10 @@ GrantActions(AI, FALSE) else GrantActions(AI, !AI.can_dominate_mechs) + if(selected) + var/atom/movable/screen/alert/empty_alert/default_alert = AI.throw_alert(selected.alert_category, /atom/movable/screen/alert/empty_alert, new_master = selected) + default_alert.name = selected.name + default_alert.desc = "Выбран модуль [selected.name]" ///////////////////////////////////// //////// Atmospheric stuff //////// @@ -1321,6 +1331,10 @@ occupant << sound(nominalsound, volume = 50) if(state) H.throw_alert("locked", /atom/movable/screen/alert/mech_maintenance) + if(selected) + var/atom/movable/screen/alert/empty_alert/default_alert = H.throw_alert(selected.alert_category, /atom/movable/screen/alert/empty_alert, new_master = selected) + default_alert.name = selected.name + default_alert.desc = "Выбран модуль [selected.name]" return TRUE else return FALSE @@ -1406,11 +1420,20 @@ if(!occupant) return var/atom/movable/mob_container + if(selected) + occupant.clear_alert(selected.alert_category) occupant.clear_alert("charge") occupant.clear_alert("locked") occupant.clear_alert("mech damage") occupant.clear_alert("mechaport") occupant.clear_alert("mechaport_d") + + if(locate(/obj/item/mecha_parts/mecha_equipment/cage) in equipment) + var/obj/item/mecha_parts/mecha_equipment/cage/H = locate(/obj/item/mecha_parts/mecha_equipment/cage) in equipment + if(H.holding) + occupant_message(span_notice("Ты перестаёшь удерживать [H.holding].")) + H.stop_supressing(H.holding) + if(occupant && occupant.client) occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon) if(ishuman(occupant)) @@ -1655,7 +1678,6 @@ diag_hud_set_mechstat() diag_hud_set_mechtracking() - /obj/mecha/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list()) var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, FLY_LAYER) SET_PLANE_EXPLICIT(I, ABOVE_GAME_PLANE, src) diff --git a/code/game/objects/items/weapons/implants/implant_freedom.dm b/code/game/objects/items/weapons/implants/implant_freedom.dm index 50a020207b0..e5c18813223 100644 --- a/code/game/objects/items/weapons/implants/implant_freedom.dm +++ b/code/game/objects/items/weapons/implants/implant_freedom.dm @@ -15,6 +15,9 @@ to_chat(imp_in, "You feel a faint click.") if(iscarbon(imp_in)) var/mob/living/carbon/C_imp_in = imp_in + // mech supress escape + if(HAS_TRAIT_FROM(C_imp_in, TRAIT_IMMOBILIZED, MECH_SUPRESSED_TRAIT)) + C_imp_in.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) C_imp_in.uncuff() if(C_imp_in.pulledby) var/mob/living/grabber = C_imp_in.pulledby @@ -24,7 +27,12 @@ playsound(C_imp_in.loc, 'sound/weapons/egloves.ogg', 75, TRUE) grabber.stop_pulling() C_imp_in.client?.move_delay = world.time // to skip move delay we probably got from resisting the grab - + // mech cage container escape + if(istype(C_imp_in.loc, /obj/item/mecha_parts/mecha_equipment/cage)) + var/obj/item/mecha_parts/mecha_equipment/cage/container = C_imp_in.loc + C_imp_in.forceMove(get_turf(container)) + container.prisoner = null + container.update_equip_info() if(!uses) qdel(src) diff --git a/code/modules/antagonists/changeling/powers/biodegrade.dm b/code/modules/antagonists/changeling/powers/biodegrade.dm index 90e65b8ce30..15f0519895a 100644 --- a/code/modules/antagonists/changeling/powers/biodegrade.dm +++ b/code/modules/antagonists/changeling/powers/biodegrade.dm @@ -49,6 +49,21 @@ addtimer(CALLBACK(src, PROC_REF(dissolve_restraint), user, res_suit), 3 SECONDS) used = TRUE + // mech supress escape + if(HAS_TRAIT_FROM(user, TRAIT_IMMOBILIZED, MECH_SUPRESSED_TRAIT)) + user.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) + used = TRUE + + // mech cage container escape + if(istype(user.loc, /obj/item/mecha_parts/mecha_equipment/cage)) + var/obj/item/mecha_parts/mecha_equipment/cage/container = user.loc + var/obj/mecha/mech = container.chassis + mech.visible_message(span_warning("Камера содержания [mech] начинает плавиться!"), \ + span_warning("Мы изрыгаем кислотную жидкость на стенки клетки!")) + user.forceMove(get_turf(container)) + container.prisoner = null + container.update_equip_info() + if(istype(user.loc, /obj/structure/closet) && !used) var/obj/structure/closet/closet = user.loc if(!istype(closet)) diff --git a/code/modules/antagonists/vampire/vampire_powers/goon_vampire_powers.dm b/code/modules/antagonists/vampire/vampire_powers/goon_vampire_powers.dm index f4fd1721bff..575debedfec 100644 --- a/code/modules/antagonists/vampire/vampire_powers/goon_vampire_powers.dm +++ b/code/modules/antagonists/vampire/vampire_powers/goon_vampire_powers.dm @@ -58,6 +58,9 @@ /obj/effect/proc_holder/spell/vampire/goon/self/rejuvenate/cast(list/targets, mob/living/carbon/human/user = usr) + // mech supress escape + if(HAS_TRAIT_FROM(user, TRAIT_IMMOBILIZED, MECH_SUPRESSED_TRAIT)) + user.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) user.SetWeakened(0) user.SetStunned(0) user.SetKnockdown(0) diff --git a/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm b/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm index 96381501944..c07beebb0d5 100644 --- a/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm +++ b/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm @@ -97,6 +97,9 @@ /obj/effect/proc_holder/spell/vampire/self/rejuvenate/cast(list/targets, mob/living/user = usr) + // mech supress escape + if(HAS_TRAIT_FROM(user, TRAIT_IMMOBILIZED, MECH_SUPRESSED_TRAIT)) + user.remove_traits(list(TRAIT_IMMOBILIZED, TRAIT_FLOORED), MECH_SUPRESSED_TRAIT) user.SetWeakened(0) user.SetStunned(0) user.SetKnockdown(0) diff --git a/code/modules/economy/robotic_quests/mech_types.dm b/code/modules/economy/robotic_quests/mech_types.dm index edd66d9c5c7..0f0f0db5150 100644 --- a/code/modules/economy/robotic_quests/mech_types.dm +++ b/code/modules/economy/robotic_quests/mech_types.dm @@ -147,4 +147,5 @@ /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/amlg, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang, + /obj/item/mecha_parts/mecha_equipment/cage, ) diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index e361291f828..7b34d151ed3 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -1047,6 +1047,17 @@ construction_time = 10 SECONDS category = list("Exosuit Equipment") +/datum/design/mech_cage + name = "Клетка SCS-3" + desc = "Модуль для экзокостюмов, используемый для задержания и заключения преступников." + id = "mech_cage" + build_type = MECHFAB + req_tech = (list("materials" = 7, "combat" = 7)) + build_path = /obj/item/mecha_parts/mecha_equipment/cage + materials = list(MAT_METAL=10000, MAT_TITANIUM=4000, MAT_SILVER=2000, MAT_DIAMOND=1000) + construction_time = 10 SECONDS + category = list("Exosuit Equipment") + // Exosuit Weapons /datum/design/mech_grenade_launcher diff --git a/icons/misc/supress_effect.dmi b/icons/misc/supress_effect.dmi new file mode 100644 index 00000000000..e86a1be90b8 Binary files /dev/null and b/icons/misc/supress_effect.dmi differ diff --git a/icons/obj/mecha/mecha_cage.dmi b/icons/obj/mecha/mecha_cage.dmi new file mode 100644 index 00000000000..f121f03806a Binary files /dev/null and b/icons/obj/mecha/mecha_cage.dmi differ diff --git a/icons/obj/mecha/mecha_equipment.dmi b/icons/obj/mecha/mecha_equipment.dmi index d31ccb93fa1..b27c26e1012 100644 Binary files a/icons/obj/mecha/mecha_equipment.dmi and b/icons/obj/mecha/mecha_equipment.dmi differ