From 54b32737e18a12f12c9cf9624c803f9401300e8a Mon Sep 17 00:00:00 2001 From: KageIIte <58105793+msw7007@users.noreply.github.com> Date: Sun, 16 Feb 2025 13:16:31 +0300 Subject: [PATCH] [TM] GAS fixes (#1757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Что этот PR делает Фиксы ГБС которые обнаружились в ходе эксплуатации ## Почему это хорошо для игры Меньше ошибок ## Изображения изменений ## Тестирование Локальный сервер ## Changelog :cl: add: Добавление новых эмоций ГБС fix: Исправление спама ГБС fix: Исправление ошибок связанных с генокрадом-ГБС, fix: Блокировка братьяев, трейторов и вампиров для ГБС fix: Исправлена ошибка, которая ломала возможность двойной атаки клинками fix: Исправлена ошибка, которая позволяла ГБС уходить в невидимость при нарушении целостности панциря 2-ого уровня fix: Исправлена ошибка, которая не позволяла ГБС отключать трахеальный мешок fix: Исправлены ошибки, которые приводили к некорректному отображению надетых вещей на ГБС и не на ГБС tweak: Закрытие для ГБС культа tweak: Операции по восстановлению целостности панциря больше не требуют слома хитина tweak: Операции по работе с хитином и целостностью панциря были разделены для более понятного обозначения tweak: Анализаторы здоровья теперь показывают уровень нарушения целостности панциря ГБС tweak: Слегка снижено время необходимое для смерти органов ГБС tweak: Для усиленного захвата противника теперь ГБС необходимо находиться в скрытности и вытащить клинки tweak: Слегка исправлены коэффициенты потребления веществ для способностей ГБС tweak: Теперь нельзя залезать на ГБС самому (ГБС все-еще может сам на себя загружать ящики, членов экипажа) tweak: При падении, смерти, потери сознания ГБС теперь роняет переносимый ящик или члена экипажа /:cl: --- code/__DEFINES/dcs/mob_signals.dm | 5 + code/__DEFINES/modular_ss220/_ss220.dm | 5 +- code/datums/datacore.dm | 10 ++ code/game/gamemodes/cult/cult_mode.dm | 2 +- code/game/gamemodes/cult/runes.dm | 8 ++ code/game/gamemodes/game_mode.dm | 6 +- code/game/gamemodes/objective.dm | 4 + code/game/objects/items/devices/scanners.dm | 5 + .../changeling/powers/tiny_prick.dm | 5 + .../ruins/lavalandruin_code/sin_ruins.dm | 2 +- .../tgui/modules/appearance_changer.dm | 1 + config/names/serpentids_names.txt | 16 +++ .../code/signals_mob/signals_mob_carbon.dm | 3 +- modular_ss220/_defines220/code/signals_obj.dm | 2 + modular_ss220/_defines220/code/species.dm | 4 + .../pixel_shift/code/pixel_shift_component.dm | 2 +- modular_ss220/species/_code/common.dm | 1 + .../appearance/mob_overlay_shift.dm | 27 +++- .../_components/attacking/double_attack.dm | 6 +- .../species/_components/carapace/carapace.dm | 25 +++- .../_components/carapace/carapace_shell.dm | 42 +++++- .../carrying/grab_and_drag_on_mob_crates.dm | 6 +- .../carrying/grab_and_drag_on_mob_mobs.dm | 6 +- .../_components/organs/heart_defib_hunger.dm | 4 + .../organs/organ_actions_component.dm | 8 +- .../species/_components/organs/organ_decay.dm | 9 +- .../_components/organs/organ_hunger.dm | 15 +- .../species/serpentids/code/mob/emotes.dm | 133 ++++++++++++++++++ .../species/serpentids/code/mob/language.dm | 12 +- .../species/serpentids/code/mob/serpentids.dm | 93 ++++++++++-- .../external/serpentids_organs_torso.dm | 16 ++- .../implants/serpentid_mantis_blades.dm | 34 ++++- .../implants/serpentid_mantis_chest.dm | 64 +++++++-- .../internal/organs/serpentids_organs_ears.dm | 5 +- .../internal/organs/serpentids_organs_eyes.dm | 7 +- .../organs/serpentids_organs_heart.dm | 5 +- .../organs/serpentids_organs_kidneys.dm | 22 +-- .../organs/serpentids_organs_liver.dm | 2 +- .../organs/serpentids_organs_lungs.dm | 16 ++- .../icons/mob/r_serpentid_blood.dmi | Bin 5884 -> 5944 bytes .../species/serpentids/icons/organs.dmi | Bin 12421 -> 10981 bytes 41 files changed, 552 insertions(+), 86 deletions(-) create mode 100644 config/names/serpentids_names.txt diff --git a/code/__DEFINES/dcs/mob_signals.dm b/code/__DEFINES/dcs/mob_signals.dm index bcbdc4fbf73ce..597c9c1738efb 100644 --- a/code/__DEFINES/dcs/mob_signals.dm +++ b/code/__DEFINES/dcs/mob_signals.dm @@ -150,6 +150,11 @@ #define COMSIG_LIVING_FIRE_TICK "living_fire_tick" //sent from living mobs when they are ahealed #define COMSIG_LIVING_AHEAL "living_aheal" +//sent from base of /obj/item/healthanalyzer/get_carapace_damage_level: () +#define COMSIG_SHELL_GET_CARAPACE_LEVEL "surgery_get_carapace_level" +//sent from base of /datum/surgery_step/set_bone/end_step: () +#define COMSIG_SHELL_GET_CARAPACE_STATE "surgery_get_carapace_state" + #define CARAPACE_SHELL_BROKEN (1<<0) //sent from mobs when they exit their body as a ghost #define COMSIG_LIVING_GHOSTIZED "ghostized" //sent from mobs when they re-enter their body as a ghost diff --git a/code/__DEFINES/modular_ss220/_ss220.dm b/code/__DEFINES/modular_ss220/_ss220.dm index ad8b8c4069e32..800c38fd55b02 100644 --- a/code/__DEFINES/modular_ss220/_ss220.dm +++ b/code/__DEFINES/modular_ss220/_ss220.dm @@ -5,4 +5,7 @@ #define PREFTOGGLE_TOGGLE220 220 /// called by /datum/component/mob_overlay_shift/proc/get_list(mob/component_holder, overlay, list/info_data) : (/datum/component/mob_overlay_shift) -#define COMSIG_MOB_GET_OVERLAY_SHIFTS_LIST "mob_get_overlay_shifts_list" // SS220 EDIT +#define COMSIG_MOB_GET_OVERLAY_SHIFTS_LIST "mob_get_overlay_shifts_list" + +/// called by /datum/component/mob_overlay_shift/proc/get_list(mob/component_holder, overlay, list/info_data) : (/datum/component/mob_overlay_shift) +#define COMSIG_CMA_TRANSFORM "cma_transform" diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 07b21892ed8e2..755bf9fb9d28f 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -259,6 +259,12 @@ GLOBAL_VAR_INIT(record_id_num, 1001) temp = new /icon(icobase, "[head]_[g]") preview_icon.Blend(temp, ICON_OVERLAY) + // SS220 EDIT START - SERPENTIDS + if(is_species(H, /datum/species/serpentid)) + temp = new/icon("icon" = 'modular_ss220/species/serpentids/icons/mob/r_serpentid.dmi', "icon_state" = "preview") + preview_icon.Blend(temp, ICON_OVERLAY) + // SS220 EDIT END - SERPENTIDS + //Tail if(H.body_accessory && (istype(H.body_accessory, /datum/body_accessory/tail) || istype(H.body_accessory, /datum/body_accessory/wing))) temp = new/icon("icon" = H.body_accessory.icon, "icon_state" = H.body_accessory.icon_state) @@ -395,6 +401,10 @@ GLOBAL_VAR_INIT(record_id_num, 1001) job_clothes = custom_job else if(H.mind) job_clothes = H.mind.assigned_role + //SS220 EDIT START - SERPENTIDS + if(is_species(H, /datum/species/serpentid)) + job_clothes = "Naked" + //SS220 EDIT END - SERPENTIDS switch(job_clothes) if("Head of Personnel") clothes_s = new /icon('icons/mob/clothing/under/civilian.dmi', "hop_s") diff --git a/code/game/gamemodes/cult/cult_mode.dm b/code/game/gamemodes/cult/cult_mode.dm index f9f202e126c60..2bec8565465c8 100644 --- a/code/game/gamemodes/cult/cult_mode.dm +++ b/code/game/gamemodes/cult/cult_mode.dm @@ -25,7 +25,7 @@ if(GLOB.configuration.gamemode.prevent_mindshield_antags) restricted_jobs += protected_jobs - var/list/cultists_possible = get_players_for_role(ROLE_CULTIST) + var/list/cultists_possible = get_players_for_role(ROLE_CULTIST, species_exclude = list("Serpentids")) // SS220 EDIT - SERPENTIDS for(var/cultists_number = 1 to max_cultists_to_start) if(!length(cultists_possible)) break diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index ba936bb8fe16a..3e2d5d7a0d3b2 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -273,6 +273,14 @@ structure_check() searches for nearby cultist structures required for the invoca if(!IS_CULTIST(M) || (M.mind && IS_SACRIFICE_TARGET(M.mind))) if(isconstruct(M)) // No offering constructs please continue + // SS220 EDIT START - SERPENTIDS + if(is_species(M, /datum/species/serpentid)) + M.Paralyse(15 SECONDS) + M.AdjustSleeping(60 SECONDS, bound_lower = 60 SECONDS, bound_upper = 100 SECONDS) + for(var/I in invokers) + to_chat(I, "Предложенная кровь недостаточно хороша для подношения, найдите другую жертву!") + continue + // SS220 EDIT END - SERPENTIDS offer_targets += M // Offering a head/brain diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 143a8c90ff66c..f2ed89d4a9bb5 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -276,7 +276,7 @@ if(rev_team) rev_team.check_all_victory() -/datum/game_mode/proc/get_players_for_role(role, override_jobbans = FALSE, species_exclusive = null) +/datum/game_mode/proc/get_players_for_role(role, override_jobbans = FALSE, species_exclusive = null, list/species_exclude = null) var/list/players = list() var/list/candidates = list() @@ -302,6 +302,10 @@ if(!eligible_player.client.skip_antag) if(species_exclusive && (eligible_player.client.prefs.active_character.species != species_exclusive)) continue + // SS220 ADDITION START - SERPENTIDS + if(species_exclude && (eligible_player.client.prefs.active_character.species in species_exclude)) + continue + // SS220 ADDITION END - SERPENTIDS if(role in eligible_player.client.prefs.be_special) player_draft_log += "[eligible_player.key] had [roletext] enabled, so we are drafting them." candidates += eligible_player.mind diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 1d62c48d667ac..1e2cd45655afe 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -502,6 +502,10 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) /datum/objective/escape/escape_with_identity/is_invalid_target(datum/mind/possible_target) if(..() || !possible_target.current.client) return TRUE + // SS220 EDIT START - GAS FIXES AND REBALANCE + if(is_species(possible_target, /datum/species/serpentid)) + return TRUE + // SS220 EDIT END - GAS FIXES AND REBALANCE // If the target is geneless, then it's an invalid target. return HAS_TRAIT(possible_target.current, TRAIT_GENELESS) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 5b94f30a59776..5c4f56b389a33 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -397,6 +397,11 @@ SLIME SCANNER if(H.radiation > RAD_MOB_SAFE) msgs += "Subject is irradiated." + //SS220 ADDITION START - SERPENTIDS + if(SEND_SIGNAL(H, COMSIG_SHELL_GET_CARAPACE_STATE) & CARAPACE_SHELL_BROKEN) + msgs = get_carapace_damage_level(H, msgs) + //SS220 ADDITION END - SERPENTIDS + to_chat(user, chat_box_healthscan(msgs.Join("
"))) /obj/item/healthanalyzer/attackby__legacy__attackchain(obj/item/I, mob/user, params) diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm index 985fb92b83b85..58f9d6f056058 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -61,6 +61,11 @@ if(ismachineperson(target)) to_chat(user, "This won't work on synthetics.") return FALSE + // SS220 EDIT START - GAS FIXES AND REBALANCE + if(is_species(target, /datum/species/serpentid)) + to_chat(user, "This won't work on serpentids armor.") + return FALSE + // SS220 EDIT START - GAS FIXES AND REBALANCE if(IS_CHANGELING(target)) sting_feedback(user, target) take_chemical_cost() diff --git a/code/modules/ruins/lavalandruin_code/sin_ruins.dm b/code/modules/ruins/lavalandruin_code/sin_ruins.dm index cfa4c18f3c8b6..b28b3ecef62e7 100644 --- a/code/modules/ruins/lavalandruin_code/sin_ruins.dm +++ b/code/modules/ruins/lavalandruin_code/sin_ruins.dm @@ -200,7 +200,7 @@ return if(!istype(user)) return - if(ishuman(AM)) + if(ishuman(AM) && !is_species(AM, /datum/species/serpentid)) // SS220 EDIT - SERPENTIDS var/mob/living/carbon/human/H = AM if(user.real_name != H.dna.real_name) user.real_name = H.dna.real_name diff --git a/code/modules/tgui/modules/appearance_changer.dm b/code/modules/tgui/modules/appearance_changer.dm index d82fcec4efb8b..1e4aa87977bb8 100644 --- a/code/modules/tgui/modules/appearance_changer.dm +++ b/code/modules/tgui/modules/appearance_changer.dm @@ -397,3 +397,4 @@ valid_body_accessories = owner.generate_valid_body_accessories() if(!length(valid_alt_head_styles)) valid_alt_head_styles = owner.generate_valid_alt_heads() + SEND_SIGNAL(owner, COMSIG_CMA_TRANSFORM) //SS220 ADDITION - SERPENTIDS diff --git a/config/names/serpentids_names.txt b/config/names/serpentids_names.txt new file mode 100644 index 0000000000000..ba5b115c96135 --- /dev/null +++ b/config/names/serpentids_names.txt @@ -0,0 +1,16 @@ +Бламг +Брэцк +Вшиси +Вхус +Клатси +Клух +Звин +Зцохи +Рари +Ристи +Скрик +Скрум +Щерс +Шухса +Цвальк +Цвун diff --git a/modular_ss220/_defines220/code/signals_mob/signals_mob_carbon.dm b/modular_ss220/_defines220/code/signals_mob/signals_mob_carbon.dm index 1cce544ff6d0c..2a37301618b11 100644 --- a/modular_ss220/_defines220/code/signals_mob/signals_mob_carbon.dm +++ b/modular_ss220/_defines220/code/signals_mob/signals_mob_carbon.dm @@ -1,7 +1,8 @@ // Signals for /mob/living/carbon /// called by /mob/equip_to_slot() : (/datum/component/mob_overlay_shift) #define COMSIG_MOB_ON_EQUIP "mob_on_equip" - +/// called by /datum/action/changeling/transform/sting_action() : (/datum/component/mob_overlay_shift) +#define COMSIG_CHANGELING_FINISHED_TRANSFORM "changeling_finished_transform" /// called by /mob/ClickOn() : (/datum/component/mob_overlay_shift) #define COMSIG_MOB_ON_CLICK "mob_on_click" diff --git a/modular_ss220/_defines220/code/signals_obj.dm b/modular_ss220/_defines220/code/signals_obj.dm index 4d539f801f833..707f68c53d317 100644 --- a/modular_ss220/_defines220/code/signals_obj.dm +++ b/modular_ss220/_defines220/code/signals_obj.dm @@ -8,6 +8,8 @@ #define COMSIG_LIMB_RECEIVE_DAMAGE "limb_receive_damage" /// called by /obj/item/organ/external/heal_damage() : (/datum/component/carapace) #define COMSIG_LIMB_HEAL_DAMAGE "limb_heal_damage" +/// called by /datum/surgery_step/set_bone/end_step(), /datum/surgery_step/retract_carapace/end_step : (/datum/component/carapace) +#define COMSIG_LIMB_SHELL_OPERATION "limb_shell_operation" /// called by /obj/item/organ/internal/cyberimp/arm/Extend() /obj/item/organ/internal/cyberimp/arm/Retract() : (/datum/element/paired_implants) #define COMSIG_DOUBLEIMP_SYNCHONIZE "doubleimp_synchonize" /// called by /obj/item/organ/internal/remove() /obj/item/organ/internal/insert() : (/datum/element/paired_implants) diff --git a/modular_ss220/_defines220/code/species.dm b/modular_ss220/_defines220/code/species.dm index aa25bfb03f7f2..8ea70bf5aa43d 100644 --- a/modular_ss220/_defines220/code/species.dm +++ b/modular_ss220/_defines220/code/species.dm @@ -19,3 +19,7 @@ /mob/living/carbon/human var/atom/movable/loaded = null var/mob/living/passenger = null + +/mob/living/proc/isCarrying() + var/mob/living/carbon/human/check_one = src + return check_one?.loaded || check_one?.passenger diff --git a/modular_ss220/pixel_shift/code/pixel_shift_component.dm b/modular_ss220/pixel_shift/code/pixel_shift_component.dm index b6da4c78a331b..fb1af983c4006 100644 --- a/modular_ss220/pixel_shift/code/pixel_shift_component.dm +++ b/modular_ss220/pixel_shift/code/pixel_shift_component.dm @@ -63,7 +63,7 @@ /datum/component/pixel_shift/proc/pixel_shift(mob/target, direction) var/mob/living/owner = parent - if(HAS_TRAIT(owner, TRAIT_RESTRAINED) || HAS_TRAIT(owner, TRAIT_IMMOBILIZED) || length(owner.grabbed_by) || owner.stat != CONSCIOUS) + if(HAS_TRAIT(owner, TRAIT_RESTRAINED) || HAS_TRAIT(owner, TRAIT_IMMOBILIZED) || length(owner.grabbed_by) || owner.stat != CONSCIOUS || owner.isCarrying()) return passthroughable = NONE switch(direction) diff --git a/modular_ss220/species/_code/common.dm b/modular_ss220/species/_code/common.dm index cc3710debe5df..b9068bb977830 100644 --- a/modular_ss220/species/_code/common.dm +++ b/modular_ss220/species/_code/common.dm @@ -19,6 +19,7 @@ //Сколько голода потребляют уши (сонар) #define SERPENTID_ORGAN_HUNGER_EARS 0.1 //78 минут +#define TRAIT_CLOAKBLOCKED "cloak_block" //минимальное цветовосприятие #define SERPENTID_EYES_LOW_VISIBLE_VALUE 0.5 //Максимальное цветовосприяте diff --git a/modular_ss220/species/_components/appearance/mob_overlay_shift.dm b/modular_ss220/species/_components/appearance/mob_overlay_shift.dm index 849e8536b821f..280fc201f3ba5 100644 --- a/modular_ss220/species/_components/appearance/mob_overlay_shift.dm +++ b/modular_ss220/species/_components/appearance/mob_overlay_shift.dm @@ -35,17 +35,26 @@ shift_call(parent) /datum/component/mob_overlay_shift/RegisterWithParent() - RegisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_MOB_ON_EQUIP, COMSIG_MOB_ON_CLICK), PROC_REF(shift_call)) + RegisterSignal(parent, list(COMSIG_COMPONENT_CLEAN_ACT, COMSIG_MOVABLE_MOVED, COMSIG_MOB_ON_EQUIP, COMSIG_MOB_ON_CLICK, COMSIG_CHANGELING_FINISHED_TRANSFORM, COMSIG_CMA_TRANSFORM), PROC_REF(shift_call)) + RegisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE), PROC_REF(update_dir)) RegisterSignal(parent, list(COMSIG_MOB_GET_OVERLAY_SHIFTS_LIST), PROC_REF(get_list)) /datum/component/mob_overlay_shift/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_MOB_ON_EQUIP, COMSIG_MOB_ON_CLICK, COMSIG_MOB_GET_OVERLAY_SHIFTS_LIST)) + UnregisterSignal(parent, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_MOVABLE_MOVED, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_MOB_ON_EQUIP, COMSIG_MOB_ON_CLICK, COMSIG_MOB_GET_OVERLAY_SHIFTS_LIST, COMSIG_CHANGELING_FINISHED_TRANSFORM, COMSIG_CMA_TRANSFORM)) + +/datum/component/mob_overlay_shift/proc/update_dir(mob/living/carbon/human/mob, olddir, newdir) + SIGNAL_HANDLER + if(newdir) + dir = newdir + update_apperance(mob) /datum/component/mob_overlay_shift/proc/shift_call(mob/living/carbon/human/mob) SIGNAL_HANDLER if(mob.dir) dir = mob.dir + update_apperance(mob) +/datum/component/mob_overlay_shift/proc/update_apperance(mob/living/carbon/human/mob) var/list/body_parts = list(MOB_OVERLAY_SHIFT_HAND, MOB_OVERLAY_SHIFT_BELT, MOB_OVERLAY_SHIFT_BACK, MOB_OVERLAY_SHIFT_HEAD) var/position switch(dir) @@ -59,7 +68,8 @@ position = MOB_OVERLAY_SHIFT_FRONT var/flip = (dir == WEST || dir == SOUTH) ? -1 : 1 - + if(!position) + position = MOB_OVERLAY_SHIFT_SIDE //ГБС лежит // Update shift values based on direction for(var/body_part in body_parts) var/x_shift_key = "shift_x" @@ -70,8 +80,11 @@ var/x_central_value = shift_data[body_part][MOB_OVERLAY_SHIFT_CENTER]["x"] var/y_central_value = shift_data[body_part][MOB_OVERLAY_SHIFT_CENTER]["y"] - shift_data[body_part][x_shift_key] = flip * x_shift_value + x_central_value - shift_data[body_part][y_shift_key] = flip * y_shift_value + y_central_value + shift_data[body_part][y_shift_key] = 0 + shift_data[body_part][x_shift_key] = 0 + if(isserpentid(mob)) + shift_data[body_part][x_shift_key] = flip * x_shift_value + x_central_value + shift_data[body_part][y_shift_key] = flip * y_shift_value + y_central_value update_call(mob) @@ -97,3 +110,7 @@ #undef MOB_OVERLAY_SHIFT_SIDE #undef MOB_OVERLAY_SHIFT_FRONT #undef MOB_OVERLAY_SHIFT_CENTER + +/atom/movable/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change) + . = ..() + l_move_time = world.time diff --git a/modular_ss220/species/_components/attacking/double_attack.dm b/modular_ss220/species/_components/attacking/double_attack.dm index fe145efcc6889..f5e1c21c329b6 100644 --- a/modular_ss220/species/_components/attacking/double_attack.dm +++ b/modular_ss220/species/_components/attacking/double_attack.dm @@ -1,8 +1,6 @@ /* ===Компонент на атаку парного оружия -Срабатывает при атаке оружием. Второе оружие через паузу в 0.2 секунды запускает атаку. - -Срабатывает только, если оружие одинаковое. +Срабатывает при атаке оружием. Второе оружие через паузу в N секунд запускает атаку. */ /datum/component/double_attack @@ -28,6 +26,8 @@ /datum/component/double_attack/proc/hand_attack(mob/living/target, mob/living/user, def_zone, obj/item/hand_item) if(QDELETED(src) || QDELETED(target) || user != hand_item.loc || !user.Adjacent(target)) + state_attack = FALSE return hand_item.attack(target, user, def_zone) state_attack = FALSE + diff --git a/modular_ss220/species/_components/carapace/carapace.dm b/modular_ss220/species/_components/carapace/carapace.dm index 6a6b5c1d30dc2..4320b4d17baba 100644 --- a/modular_ss220/species/_components/carapace/carapace.dm +++ b/modular_ss220/species/_components/carapace/carapace.dm @@ -27,6 +27,7 @@ /datum/component/carapace var/self_mending = FALSE var/broken_treshold = CARAPACE_BROKEN_STATE + var/operation_in_process = FALSE /datum/component/carapace/Initialize(allow_self_mending, break_threshold) src.self_mending = allow_self_mending @@ -37,10 +38,16 @@ /datum/component/carapace/RegisterWithParent() RegisterSignal(parent, COMSIG_LIMB_RECEIVE_DAMAGE, PROC_REF(receive_damage)) RegisterSignal(parent, COMSIG_LIMB_HEAL_DAMAGE, PROC_REF(heal_damage)) + RegisterSignal(parent, COMSIG_LIMB_SHELL_OPERATION, PROC_REF(handle_operation_status)) /datum/component/carapace/UnregisterFromParent() UnregisterSignal(parent, COMSIG_LIMB_RECEIVE_DAMAGE) UnregisterSignal(parent, COMSIG_LIMB_HEAL_DAMAGE) + UnregisterSignal(parent, COMSIG_LIMB_SHELL_OPERATION) + +/datum/component/carapace/proc/handle_operation_status(obj/item/organ/external/affected_limb, state_to_apply) + SIGNAL_HANDLER + operation_in_process = state_to_apply //Проки, срабатываемые при получении или исцелении урона /datum/component/carapace/proc/receive_damage(obj/item/organ/external/affected_limb, brute, burn, sharp, used_weapon = null, list/forbidden_limbs = list(), ignore_resists = FALSE, updating_health = TRUE) @@ -49,12 +56,12 @@ affected_limb.fracture() if(length(affected_limb.internal_organs)) var/obj/item/organ/internal/O = pick(affected_limb.internal_organs) - O.receive_damage(burn * affected_limb.burn_dam) + O.receive_damage(burn) /datum/component/carapace/proc/heal_damage(obj/item/organ/external/affected_limb, brute, burn, internal = 0, robo_repair = 0, updating_health = TRUE) SIGNAL_HANDLER if((affected_limb.status & ORGAN_BROKEN) && affected_limb.get_damage() == 0) - if(self_mending || prob(CARAPACE_HEAL_BROKEN_PROB)) + if((self_mending || prob(CARAPACE_HEAL_BROKEN_PROB)) && !operation_in_process) affected_limb.mend_fracture() ////////////////////////////////////////////////////////////////// @@ -62,7 +69,7 @@ ////////////////////////////////////////////////////////////////// ///Датумы для операций /datum/surgery/carapace_break - name = "Break carapace" + name = "Break chitin" steps = list( /datum/surgery_step/saw_carapace, /datum/surgery_step/cut_carapace, @@ -83,7 +90,7 @@ requires_organic_bodypart = TRUE /datum/surgery/bone_repair/carapace - name = "Carapace Repair" + name = "Chitin Repair" steps = list( /datum/surgery_step/glue_bone, /datum/surgery_step/set_bone, @@ -133,7 +140,7 @@ //Блокировка простого скальпеля (базовый начальный шаг любой операции), если карапас не был сломан, но появилась какая-то операция, которая не должна быть /datum/surgery_step/generic/cut_open/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery) var/obj/item/organ/external/affected = target.get_organ(target_zone) - if((affected?.encased == CARAPACE_ENCASE_WORD) && !(affected.status & ORGAN_BROKEN)) + if((affected?.encased == CARAPACE_ENCASE_WORD) && !(affected.status & ORGAN_BROKEN) && !istype(surgery, /datum/surgery/carapace_shell_repair)) to_chat(user, span_notice("[capitalize(target.declent_ru(NOMINATIVE))] покрыта крепким хитином. Сломайте его, прежде чем начать операцию.")) return SURGERY_BEGINSTEP_ABORT . = .. () @@ -142,12 +149,18 @@ var/obj/item/organ/external/affected = target.get_organ(user.zone_selected) if((affected?.encased == CARAPACE_ENCASE_WORD) && !(affected.status & ORGAN_BROKEN)) affected.fracture() + REMOVE_TRAIT(target, TRAIT_PIERCEIMMUNE, "carapace_state") + SEND_SIGNAL(affected, COMSIG_LIMB_SHELL_OPERATION, TRUE) . = .. () /datum/surgery_step/set_bone/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(user.zone_selected) - if((affected?.encased == CARAPACE_ENCASE_WORD) && !(affected.status & ORGAN_BROKEN)) + if((affected?.encased == CARAPACE_ENCASE_WORD) && (affected.status & ORGAN_BROKEN)) affected.mend_fracture() + if(isserpentid(target)) + if(!(SEND_SIGNAL(target, COMSIG_SHELL_GET_CARAPACE_STATE) & CARAPACE_SHELL_BROKEN)) + ADD_TRAIT(target, TRAIT_PIERCEIMMUNE, "carapace_state") + SEND_SIGNAL(affected, COMSIG_LIMB_SHELL_OPERATION, FALSE) . = .. () #undef CARAPACE_BROKEN_STATE diff --git a/modular_ss220/species/_components/carapace/carapace_shell.dm b/modular_ss220/species/_components/carapace/carapace_shell.dm index fdf588bd6dc00..4566b3213b3d4 100644 --- a/modular_ss220/species/_components/carapace/carapace_shell.dm +++ b/modular_ss220/species/_components/carapace/carapace_shell.dm @@ -44,12 +44,35 @@ RegisterSignal(H, COMSIG_SURGERY_STOP, PROC_REF(check_surgery_perform)) RegisterSignal(H, COMSIG_SURGERY_REPAIR, PROC_REF(surgery_carapace_shell_repair)) RegisterSignal(H, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(update_attacked_time)) + RegisterSignal(H, COMSIG_LIVING_AHEAL, PROC_REF(clear_state)) + RegisterSignal(H, COMSIG_SHELL_GET_CARAPACE_STATE, PROC_REF(is_armor_piercied)) + RegisterSignal(H, COMSIG_SHELL_GET_CARAPACE_LEVEL, PROC_REF(get_broken_stage)) /datum/component/carapace_shell/UnregisterFromParent() UnregisterSignal(H, COMSIG_LIVING_LIFE) UnregisterSignal(H, COMSIG_SURGERY_STOP) UnregisterSignal(H, COMSIG_SURGERY_REPAIR) UnregisterSignal(H, COMSIG_MOB_APPLY_DAMAGE) + UnregisterSignal(H, COMSIG_LIVING_AHEAL) + UnregisterSignal(H, COMSIG_SHELL_GET_CARAPACE_STATE) + UnregisterSignal(H, COMSIG_SHELL_GET_CARAPACE_LEVEL) + +/datum/component/carapace_shell/proc/is_armor_piercied() + SIGNAL_HANDLER + return broken_stage > 0 ? CARAPACE_SHELL_BROKEN : FALSE + +/datum/component/carapace_shell/proc/get_broken_stage(mob/human, list/msg) + SIGNAL_HANDLER + var/level + switch(broken_stage) + if(1) + level = "умеренные" + if(2) + level = "опасные" + if(3) + level = "критические" + if(level) + msg += "Обнаружены [level] повреждения целостности панциря." /datum/component/carapace_shell/proc/stage_1_break() H.dna.species.brute_mod = CARAPACE_SHELL_BROKEN_BRUTE @@ -62,14 +85,15 @@ H.dna.species.brute_mod = CARAPACE_SHELL_ARMORED_BRUTE H.dna.species.burn_mod = CARAPACE_SHELL_ARMORED_BURN ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, "carapace_state") - H.clear_alert("carapace_break") broken_stage-- /datum/component/carapace_shell/proc/stage_2_break() H.throw_alert("carapace_break", /atom/movable/screen/alert/carapace/break_cloak) + ADD_TRAIT(H, TRAIT_CLOAKBLOCKED, "carapace_state") broken_stage++ /datum/component/carapace_shell/proc/stage_2_repair() + REMOVE_TRAIT(H, TRAIT_CLOAKBLOCKED, "carapace_state") broken_stage-- /datum/component/carapace_shell/proc/stage_3_break() @@ -155,10 +179,17 @@ if(istype(organ)) organ.switch_mode(force_off = TRUE) + if((broken_stage < 1 && character_damage < state_1_threshold) || !isserpentid(H)) + H.clear_alert("carapace_break") + +/datum/component/carapace_shell/proc/clear_state() + SIGNAL_HANDLER + broken_stage = 0 + ////////////////////////////////////////////////////////////////// // Хирургия для панциря // ////////////////////////////////////////////////////////////////// -/datum/surgery/bone_repair/carapace_shell +/datum/surgery/carapace_shell_repair name = "Carapace Integrity Repair" steps = list( /datum/surgery_step/generic/cut_open, @@ -219,7 +250,7 @@ ) return SURGERY_STEP_RETRY -/datum/surgery/bone_repair/carapace_shell/can_start(mob/user, mob/living/carbon/target) +/datum/surgery/carapace_shell_repair/can_start(mob/user, mob/living/carbon/target) var/can_start = (SEND_SIGNAL(target, COMSIG_SURGERY_STOP) & SURGERY_STOP) return can_start @@ -227,3 +258,8 @@ #undef CARAPACE_SHELL_ARMORED_BURN #undef CARAPACE_SHELL_BROKEN_BRUTE #undef CARAPACE_SHELL_BROKEN_BURN + +/proc/get_carapace_damage_level(mob/target, list/msgs) + . = msgs + SEND_SIGNAL(target, COMSIG_SHELL_GET_CARAPACE_LEVEL, .) + return . diff --git a/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_crates.dm b/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_crates.dm index d7503c89e5049..50a7ac66076e1 100644 --- a/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_crates.dm +++ b/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_crates.dm @@ -25,11 +25,13 @@ RegisterSignal(parent, COMSIG_GADOM_LOAD, PROC_REF(try_load_cargo)) RegisterSignal(parent, COMSIG_GADOM_UNLOAD, PROC_REF(try_unload_cargo)) RegisterSignal(parent, COMSIG_GADOM_CAN_GRAB, PROC_REF(block_operation)) + RegisterSignal(parent, COMSIG_CHANGELING_FINISHED_TRANSFORM, PROC_REF(try_unload_cargo)) /datum/component/gadom_cargo/UnregisterFromParent() UnregisterSignal(parent, COMSIG_GADOM_LOAD) UnregisterSignal(parent, COMSIG_GADOM_UNLOAD) UnregisterSignal(parent, COMSIG_GADOM_CAN_GRAB) + UnregisterSignal(parent, COMSIG_CHANGELING_FINISHED_TRANSFORM) /datum/component/gadom_cargo/proc/block_operation() SIGNAL_HANDLER @@ -74,6 +76,7 @@ if(!isliving(AM)) AM.crate_carrying_person = carrier + AM.density = FALSE AM.forceMove(carrier.loc) carrier.loaded = AM @@ -101,7 +104,8 @@ var/turf/newT = get_step(T,dirn) if(carrier.loaded.CanPass(carrier.loaded, newT)) step(carrier.loaded, dirn) + carrier.loaded.density = TRUE carrier.loaded.crate_carrying_person = null carrier.loaded = null - carrier.clear_alert("serpentid_holding") carrier.update_icon(UPDATE_OVERLAYS) + carrier.clear_alert("serpentid_holding") diff --git a/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_mobs.dm b/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_mobs.dm index fa7a34893d613..b2a8d4cb7dfb4 100644 --- a/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_mobs.dm +++ b/modular_ss220/species/_components/carrying/grab_and_drag_on_mob_mobs.dm @@ -8,17 +8,20 @@ /datum/component/gadom_living/Initialize() carrier = parent + carrier.can_buckle = FALSE START_PROCESSING(SSprojectiles, src) /datum/component/gadom_living/RegisterWithParent() RegisterSignal(parent, COMSIG_GADOM_LOAD, PROC_REF(try_load_mob)) RegisterSignal(parent, COMSIG_GADOM_UNLOAD, PROC_REF(try_unload_mob)) RegisterSignal(parent, COMSIG_GADOM_CAN_GRAB, PROC_REF(block_operation)) + RegisterSignal(parent, COMSIG_CHANGELING_FINISHED_TRANSFORM, PROC_REF(try_unload_mob)) /datum/component/gadom_living/UnregisterFromParent() UnregisterSignal(parent, COMSIG_GADOM_LOAD) UnregisterSignal(parent, COMSIG_GADOM_UNLOAD) UnregisterSignal(parent, COMSIG_GADOM_CAN_GRAB) + UnregisterSignal(parent, COMSIG_CHANGELING_FINISHED_TRANSFORM) /datum/component/gadom_living/proc/block_operation(datum/component_holder) SIGNAL_HANDLER @@ -78,7 +81,7 @@ carrier.loaded = null carrier.passenger = null carrier.unbuckle_all_mobs() - carrier.can_buckle = TRUE + carrier.can_buckle = FALSE carrier.update_icon(UPDATE_OVERLAYS) carrier.clear_alert("serpentid_holding") @@ -89,3 +92,4 @@ passenger = null M.layer = initial(M.layer) M.pixel_y = initial(M.pixel_y) + clear_alert("serpentid_holding") diff --git a/modular_ss220/species/_components/organs/heart_defib_hunger.dm b/modular_ss220/species/_components/organs/heart_defib_hunger.dm index b6dfd47bfb22e..873a5ed4a89e0 100644 --- a/modular_ss220/species/_components/organs/heart_defib_hunger.dm +++ b/modular_ss220/species/_components/organs/heart_defib_hunger.dm @@ -20,8 +20,12 @@ if(!owner) var/obj/item/organ/internal/limb = parent owner = limb.owner + if(!owner) return + var/obj/item/organ/internal/brain = owner.get_int_organ(/obj/item/organ/internal/brain) + if(!brain) + return var/damage_amount = owner.getBruteLoss() + owner.getFireLoss() + owner.getCloneLoss() if(owner?.nutrition < NUTRITION_LEVEL_HUNGRY || owner.stat != DEAD || damage_amount > AUTO_DEFIBRILATION_THRESHOLD) return diff --git a/modular_ss220/species/_components/organs/organ_actions_component.dm b/modular_ss220/species/_components/organs/organ_actions_component.dm index aff4eceb221eb..ad67960ccd746 100644 --- a/modular_ss220/species/_components/organs/organ_actions_component.dm +++ b/modular_ss220/species/_components/organs/organ_actions_component.dm @@ -38,7 +38,10 @@ for(var/obj/item/organ/internal/I in organs_list) if(I.radial_action_state && I.radial_action_icon) - choices["[I.name]"] = image(icon = I.radial_action_icon, icon_state = I.radial_action_state) + var/image/organ_image = image(icon = I.radial_action_icon, icon_state = I.radial_action_state) + if(I.get_active_state()) + organ_image.underlays += image(icon = 'icons/hud/radial.dmi', icon_state = "module_active") + choices["[I.name]"] = organ_image var/choice = show_radial_menu(user, user, choices, custom_check = CALLBACK(src, PROC_REF(check_actions), user)) if(!check_actions(user)) @@ -78,3 +81,6 @@ /obj/item/organ/internal var/radial_action_state var/radial_action_icon + +/obj/item/organ/internal/proc/get_active_state() + return diff --git a/modular_ss220/species/_components/organs/organ_decay.dm b/modular_ss220/species/_components/organs/organ_decay.dm index d061cde5c6027..1273b21e77015 100644 --- a/modular_ss220/species/_components/organs/organ_decay.dm +++ b/modular_ss220/species/_components/organs/organ_decay.dm @@ -15,12 +15,13 @@ var/recover_rate var/decay_rate var/death_state_timer - var/dead_last_state = FALSE + var/lt_live = FALSE /datum/component/organ_decay/Initialize(income_decay_rate = BASIC_RECOVER_VALUE, income_recover_rate = BASIC_DECAY_VALUE) organ = parent recover_rate = income_recover_rate decay_rate = income_decay_rate + death_state_timer = world.time START_PROCESSING(SSdcs, src) /datum/component/organ_decay/Destroy(force, silent) @@ -32,11 +33,11 @@ return var/is_no_owner = isnull(organ.owner) - if(!dead_last_state) + if(lt_live) death_state_timer = world.time - dead_last_state = organ?.owner.stat == DEAD + lt_live = (organ?.owner?.stat != DEAD) var/formaldehyde_found = organ.owner?.get_chemical_value("formaldehyde") > 0 - var/is_destroying = (dead_last_state || (is_no_owner && !organ.is_in_freezer)) + var/is_destroying = (!lt_live || (is_no_owner && !organ.is_in_freezer)) if(is_destroying && !formaldehyde_found && ((world.time - death_state_timer) >= ORGAN_DEATH_TIMER)) organ.receive_damage(decay_rate, 1) if((organ.damage <= (organ.max_damage / ORGAN_RECOVERY_THRESHOLD)) && (organ.damage > 0) && !is_destroying) diff --git a/modular_ss220/species/_components/organs/organ_hunger.dm b/modular_ss220/species/_components/organs/organ_hunger.dm index a3fe81100e7fb..7cc8d51300a8a 100644 --- a/modular_ss220/species/_components/organs/organ_hunger.dm +++ b/modular_ss220/species/_components/organs/organ_hunger.dm @@ -21,9 +21,22 @@ SIGNAL_HANDLER if(isnull(organ.owner)) return TRUE + var/active = FALSE + if(istype(organ, /obj/item/organ/internal/kidneys/serpentid)) + var/obj/item/organ/internal/kidneys/serpentid/checkorgan = organ + active = checkorgan.cloak_engaged + if(istype(organ, /obj/item/organ/internal/eyes/serpentid)) + var/obj/item/organ/internal/eyes/serpentid/checkorgan = organ + active = checkorgan.active + if(istype(organ, /obj/item/organ/internal/lungs/serpentid)) + var/obj/item/organ/internal/lungs/serpentid/checkorgan = organ + active = checkorgan.active_secretion + if(istype(organ, /obj/item/organ/internal/ears/serpentid)) + var/obj/item/organ/internal/ears/serpentid/checkorgan = organ + active = checkorgan.active if(consuption_count && organ.owner.nutrition > NUTRITION_LEVEL_HYPOGLYCEMIA) organ.owner.adjust_nutrition(-consuption_count) - else //Если количества недостаточно - выключить режим + else if(active) //Если количества недостаточно - выключить режим organ.switch_mode(force_off = TRUE) diff --git a/modular_ss220/species/serpentids/code/mob/emotes.dm b/modular_ss220/species/serpentids/code/mob/emotes.dm index a7aaef7e64e18..ebab24d934759 100644 --- a/modular_ss220/species/serpentids/code/mob/emotes.dm +++ b/modular_ss220/species/serpentids/code/mob/emotes.dm @@ -1,6 +1,11 @@ #define EMOTE_HUMAN_SERPENTIDROAR "Рычать" #define EMOTE_HUMAN_SERPENTIDHISS "Шипеть" #define EMOTE_HUMAN_SERPENTIDWIGGLE "Шевелить усиками" +#define EMOTE_HUMAN_SERPENTIDBLINK "Моргать щитками" +#define EMOTE_HUMAN_SERPENTIDBLINKBLADES "Чистить глаза" +#define EMOTE_HUMAN_SERPENTIDBUZZ "Стрекот крыльев" +#define EMOTE_HUMAN_SERPENTIDMANDIBLES "Стучать мандибулами" +#define EMOTE_HUMAN_SERPENTIDBLADES "Стучать клинками" /mob/living/carbon/human/proc/emote_serpentidroar() set name = "< " + EMOTE_HUMAN_SERPENTIDROAR + " >" @@ -17,6 +22,31 @@ set category = "Эмоции" emote("serpentidwiggles", intentional = TRUE) +/mob/living/carbon/human/proc/emote_serpentidblinks() + set name = "◦ " + EMOTE_HUMAN_SERPENTIDBLINK + " >" + set category = "Эмоции" + emote("serpentidblinks", intentional = TRUE) + +/mob/living/carbon/human/proc/emote_serpentidblinksblades() + set name = "◦ " + EMOTE_HUMAN_SERPENTIDBLINKBLADES + " >" + set category = "Эмоции" + emote("serpentidblinksblades", intentional = TRUE) + +/mob/living/carbon/human/proc/emote_serpentidbuzzes() + set name = "< " + EMOTE_HUMAN_SERPENTIDBUZZ + " >" + set category = "Эмоции" + emote("serpentidbuzzes", intentional = TRUE) + +/mob/living/carbon/human/proc/emote_serpentidmandibles() + set name = "< " + EMOTE_HUMAN_SERPENTIDMANDIBLES + " >" + set category = "Эмоции" + emote("serpentidmandibles", intentional = TRUE) + +/mob/living/carbon/human/proc/emote_serpentidblades() + set name = "< " + EMOTE_HUMAN_SERPENTIDBLADES + " >" + set category = "Эмоции" + emote("serpentidblades", intentional = TRUE) + /datum/emote/living/carbon/human/serpentidroar name = EMOTE_HUMAN_SERPENTIDROAR @@ -26,6 +56,21 @@ /datum/emote/living/carbon/human/serpentidwiggles name = EMOTE_HUMAN_SERPENTIDWIGGLE +/datum/emote/living/carbon/human/serpentidblinks + name = EMOTE_HUMAN_SERPENTIDBLINK + +/datum/emote/living/carbon/human/serpentidblinksblades + name = EMOTE_HUMAN_SERPENTIDBLINKBLADES + +/datum/emote/living/carbon/human/serpentidbuzzes + name = EMOTE_HUMAN_SERPENTIDBUZZ + +/datum/emote/living/carbon/human/serpentidblinksblades + name = EMOTE_HUMAN_SERPENTIDMANDIBLES + +/datum/emote/living/carbon/human/serpentidblades + name = EMOTE_HUMAN_SERPENTIDBLADES + /datum/emote/living/carbon/human/serpentidroar key = "serpentidroar" key_third_person = "serpentidroar" @@ -65,6 +110,74 @@ target_behavior = EMOTE_TARGET_BHVR_USE_PARAMS_ANYWAY emote_target_type = EMOTE_TARGET_ANY +/datum/emote/living/carbon/human/serpentidblinks + key = "serpentidblinks" + key_third_person = "serpentidblinks" + message = "опускает и поднимает глазные щитки." + message_param = "опускает и поднимает глазные щитки, смотря на %t." + species_type_whitelist_typecache = list(/datum/species/serpentid) + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + age_based = TRUE + sound = null + hands_use_check = FALSE + target_behavior = EMOTE_TARGET_BHVR_USE_PARAMS_ANYWAY + emote_target_type = EMOTE_TARGET_ANY + +/datum/emote/living/carbon/human/serpentidblinksblades + key = "serpentidblinksblades" + key_third_person = "serpentidblinksblades" + message = "прочищает глаза краями лезвий." + message_param = "прочищает глаза краями лезвий, смотря на %t." + species_type_whitelist_typecache = list(/datum/species/serpentid) + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + age_based = TRUE + sound = null + hands_use_check = FALSE + target_behavior = EMOTE_TARGET_BHVR_USE_PARAMS_ANYWAY + emote_target_type = EMOTE_TARGET_ANY + +/datum/emote/living/carbon/human/serpentidbuzzes + key = "serpentidbuzzes" + key_third_person = "serpentidbuzzes" + message = "слегка вибрирует спинным панцирем." + message_param = "слегка вибрирует спинным панцирем в сторону %t." + cooldown = 5 SECONDS + species_type_whitelist_typecache = list(/datum/species/serpentid) + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + age_based = TRUE + sound = 'sound/voice/scream_moth.ogg' + hands_use_check = FALSE + target_behavior = EMOTE_TARGET_BHVR_USE_PARAMS_ANYWAY + emote_target_type = EMOTE_TARGET_ANY + +/datum/emote/living/carbon/human/serpentidmandibles + key = "serpentidmandibles" + key_third_person = "serpentidmandibles" + message = "стучит мандибулами" + message_param = "стучит мандибулами в сторону %t." + cooldown = 5 SECONDS + species_type_whitelist_typecache = list(/datum/species/serpentid) + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + age_based = TRUE + sound = 'sound/effects/Kidanclack.ogg' + hands_use_check = FALSE + target_behavior = EMOTE_TARGET_BHVR_USE_PARAMS_ANYWAY + emote_target_type = EMOTE_TARGET_ANY + +/datum/emote/living/carbon/human/serpentidblades + key = "serpentidblades" + key_third_person = "serpentidblades" + message = "стучит лезвиями." + message_param = "стучит лезвиями в сторону %t." + cooldown = 5 SECONDS + species_type_whitelist_typecache = list(/datum/species/serpentid) + emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + age_based = TRUE + sound = 'sound/weapons/blade_unsheath.ogg' + hands_use_check = FALSE + target_behavior = EMOTE_TARGET_BHVR_USE_PARAMS_ANYWAY + emote_target_type = EMOTE_TARGET_ANY + /datum/keybinding/emote/carbon/human/serpentidroar linked_emote = /datum/emote/living/carbon/human/serpentidroar name = EMOTE_HUMAN_SERPENTIDROAR @@ -76,3 +189,23 @@ /datum/keybinding/emote/carbon/human/serpentidwiggles linked_emote = /datum/emote/living/carbon/human/serpentidwiggles name = EMOTE_HUMAN_SERPENTIDWIGGLE + +/datum/keybinding/emote/carbon/human/serpentidblinks + linked_emote = /datum/emote/living/carbon/human/serpentidblinks + name = EMOTE_HUMAN_SERPENTIDBLINK + +/datum/keybinding/emote/carbon/human/serpentidblinksblades + linked_emote = /datum/emote/living/carbon/human/serpentidblinksblades + name = EMOTE_HUMAN_SERPENTIDBLINKBLADES + +/datum/keybinding/emote/carbon/human/serpentidbuzzes + linked_emote = /datum/emote/living/carbon/human/serpentidbuzzes + name = EMOTE_HUMAN_SERPENTIDBUZZ + +/datum/keybinding/emote/carbon/human/serpentidmandibles + linked_emote = /datum/emote/living/carbon/human/serpentidmandibles + name = EMOTE_HUMAN_SERPENTIDMANDIBLES + +/datum/keybinding/emote/carbon/human/serpentidblades + linked_emote = /datum/emote/living/carbon/human/serpentidblades + name = EMOTE_HUMAN_SERPENTIDBLADES diff --git a/modular_ss220/species/serpentids/code/mob/language.dm b/modular_ss220/species/serpentids/code/mob/language.dm index f66ec43831f25..bcaafa6a684d6 100644 --- a/modular_ss220/species/serpentids/code/mob/language.dm +++ b/modular_ss220/species/serpentids/code/mob/language.dm @@ -3,20 +3,16 @@ /datum/language/serpentid name = "Nabberian" - desc = "Звук, издаваемый этим языком похоже на кононаду из скрежета мандибул, лезвий, стука конечностей, трения антенн и утробного рева" + desc = "Звук, издаваемый этим языком похоже на канонаду из скрежета мандибул, лезвий, стука конечностей, трения антенн и утробного рева" speech_verb = "стучит клинками и жестикулирует конечностями" ask_verb = "стучит жвалами и жестикулирует конечностями" exclaim_verbs = list("издает гремящие щелчки") - colour = "serpentid" - key = "g" + colour = "orangei" + key = "y" flags = RESTRICTED | WHITELISTED syllables = list("click","clack","cling","clang","cland","clog") no_tts = TRUE /datum/language/serpentid/get_random_name(gender) - var/new_name = "" - if(gender == FEMALE) - new_name = capitalize(pick(GLOB.first_names_female)) - else - new_name = capitalize(pick(GLOB.first_names_male)) + var/new_name = capitalize(pick(file2list("config/names/serpentids_names.txt"))) return new_name diff --git a/modular_ss220/species/serpentids/code/mob/serpentids.dm b/modular_ss220/species/serpentids/code/mob/serpentids.dm index e51cd3f591818..2dc5807699773 100644 --- a/modular_ss220/species/serpentids/code/mob/serpentids.dm +++ b/modular_ss220/species/serpentids/code/mob/serpentids.dm @@ -19,8 +19,9 @@ dangerous_existence = TRUE species_traits = list(LIPS, NO_HAIR, TTS_TRAIT_ROBOTIZE) - inherent_traits = list(TRAIT_NOPAIN) + inherent_traits = list(TRAIT_NOPAIN, TRAIT_CHUNKYFINGERS) inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID | MOB_REPTILE + no_equip = ITEM_SLOT_OUTER_SUIT | ITEM_SLOT_GLOVES | ITEM_SLOT_SHOES | ITEM_SLOT_JUMPSUIT | ITEM_SLOT_SUIT_STORE dietflags = DIET_OMNI taste_sensitivity = TASTE_SENSITIVITY_SHARP @@ -134,7 +135,6 @@ ) ) - //Перенести на карапас/грудь /datum/species/serpentid/handle_life(mob/living/carbon/human/H) if(gene_lastcall >= SERPENTID_GENE_DEGRADATION_CD) @@ -168,6 +168,11 @@ H.verbs |= /mob/living/carbon/human/proc/emote_serpentidroar H.verbs |= /mob/living/carbon/human/proc/emote_serpentidhiss H.verbs |= /mob/living/carbon/human/proc/emote_serpentidwiggles + H.verbs |= /mob/living/carbon/human/proc/emote_serpentidblinks + H.verbs |= /mob/living/carbon/human/proc/emote_serpentidblinksblades + H.verbs |= /mob/living/carbon/human/proc/emote_serpentidbuzzes + H.verbs |= /mob/living/carbon/human/proc/emote_serpentidmandibles + H.verbs |= /mob/living/carbon/human/proc/emote_serpentidblades H.verbs -= /mob/living/carbon/human/verb/emote_cry H.verbs -= /mob/living/carbon/human/verb/emote_cough H.verbs -= /mob/living/carbon/human/verb/emote_sneeze @@ -177,12 +182,19 @@ H.verbs -= /mob/living/carbon/human/verb/emote_blink H.verbs -= /mob/living/carbon/human/verb/emote_blink_r H.chat_message_y_offset = 11 + H.status_flags &= ~CANPUSH + H.move_resist = MOVE_FORCE_STRONG /datum/species/serpentid/on_species_loss(mob/living/carbon/human/H) ..() H.verbs -= /mob/living/carbon/human/proc/emote_serpentidroar H.verbs -= /mob/living/carbon/human/proc/emote_serpentidhiss H.verbs -= /mob/living/carbon/human/proc/emote_serpentidwiggles + H.verbs -= /mob/living/carbon/human/proc/emote_serpentidblinks + H.verbs -= /mob/living/carbon/human/proc/emote_serpentidblinksblades + H.verbs -= /mob/living/carbon/human/proc/emote_serpentidbuzzes + H.verbs -= /mob/living/carbon/human/proc/emote_serpentidmandibles + H.verbs -= /mob/living/carbon/human/proc/emote_serpentidblades H.verbs |= /mob/living/carbon/human/verb/emote_cough H.verbs |= /mob/living/carbon/human/verb/emote_cry H.verbs |= /mob/living/carbon/human/verb/emote_sneeze @@ -191,6 +203,8 @@ H.verbs |= /mob/living/carbon/human/verb/emote_sigh H.verbs |= /mob/living/carbon/human/verb/emote_blink H.verbs |= /mob/living/carbon/human/verb/emote_blink_r + H.status_flags |= CANPUSH + H.move_resist = MOVE_FORCE_DEFAULT //Работа с инвентарем /datum/species/serpentid/can_equip(obj/item/I, slot, disable_warning = FALSE, mob/living/carbon/human/H) @@ -203,21 +217,78 @@ return FALSE if(ITEM_SLOT_OUTER_SUIT) return FALSE + if(ITEM_SLOT_HEAD) + if(istype(I,/obj/item/clothing/head/helmet/changeling)) //Снятие шлема линга + return FALSE . = .. () //Ограничение на роли антагов (генокрад онли) -/datum/antag_scenario/vampire/New() - restricted_species += list("Serpentid") - . = .. () +/datum/antag_scenario/vampire + restricted_species = list("Machine","Serpentid") -/datum/antag_scenario/traitor/New() - restricted_species += list("Serpentid") - . = .. () +/datum/antag_scenario/traitor + restricted_species = list("Serpentid") -/datum/antag_scenario/team/blood_brothers/New() - restricted_species += list("Serpentid") - . = .. () +/datum/antag_scenario/mindflayer + restricted_species = list("Serpentid") + +/datum/antag_scenario/team/blood_brothers + restricted_species = list("Serpentid") + +/datum/ruleset/traitor + banned_species = list("Serpentid") + +/datum/ruleset/mindflayer + banned_species = list("Serpentid") + +/datum/ruleset/vampire + banned_species = list("Machine","Serpentid") + +/datum/game_mode/traitor/pre_setup() + . = ..() + for(var/datum/mind/posible_antag in pre_traitors) + if(isserpentid(posible_antag.current?.client?.prefs.active_character.species)) + pre_traitors -= posible_antag + posible_antag.special_role = null + +/datum/game_mode/traitor/autotraitor/pre_setup() + . = ..() + for(var/datum/mind/posible_antag in pre_traitors) + if(isserpentid(posible_antag.current?.client?.prefs.active_character.species)) + pre_traitors -= posible_antag + posible_antag.special_role = null + +/datum/game_mode/vampire/pre_setup() + . = ..() + for(var/datum/mind/posible_antag in pre_vampires) + if(isserpentid(posible_antag.current?.client?.prefs.active_character.species)) + pre_vampires -= posible_antag + posible_antag.special_role = null //Расширение для действий органов серпентидов /datum/action/item_action/organ_action/toggle/serpentid name = "serpentid organ selection" + +/datum/action/changeling/transform/sting_action(mob/living/carbon/human/user) + . = ..() + if(!.) + return + SEND_SIGNAL(user, COMSIG_CHANGELING_FINISHED_TRANSFORM) + +/mob/living/death(gibbed) + . = ..() + if(!.) + return + SEND_SIGNAL(src, COMSIG_GADOM_UNLOAD) + +/mob/living/on_immobilized_trait_gain(datum/source) + . = ..() + SEND_SIGNAL(src, COMSIG_GADOM_UNLOAD) + +/mob/living/on_knockedout_trait_gain(datum/source) + . = ..() + SEND_SIGNAL(src, COMSIG_GADOM_UNLOAD) + +/mob/living/on_floored_trait_gain(datum/source) + . = ..() + SEND_SIGNAL(src, COMSIG_GADOM_UNLOAD) diff --git a/modular_ss220/species/serpentids/code/organs/external/serpentids_organs_torso.dm b/modular_ss220/species/serpentids/code/organs/external/serpentids_organs_torso.dm index e8025e4ae5d9d..48b97802c8271 100644 --- a/modular_ss220/species/serpentids/code/organs/external/serpentids_organs_torso.dm +++ b/modular_ss220/species/serpentids/code/organs/external/serpentids_organs_torso.dm @@ -1,6 +1,6 @@ -#define SERPENTID_ARMOR_THRESHOLD_1 30 -#define SERPENTID_ARMOR_THRESHOLD_2 60 -#define SERPENTID_ARMOR_THRESHOLD_3 90 +#define SERPENTID_ARMOR_THRESHOLD_1 35 +#define SERPENTID_ARMOR_THRESHOLD_2 80 +#define SERPENTID_ARMOR_THRESHOLD_3 130 #define SERPENTID_ARMORED_LOW_TEMP 0 #define SERPENTID_ARMORED_HIGH_TEMP 400 @@ -18,6 +18,16 @@ . = ..() AddComponent(/datum/component/carapace_shell, owner, treshold_1 = SERPENTID_ARMOR_THRESHOLD_1, treshold_2 = SERPENTID_ARMOR_THRESHOLD_2, treshold_3 = SERPENTID_ARMOR_THRESHOLD_3, threshold_cold = SERPENTID_ARMORED_LOW_TEMP, threshold_heat = SERPENTID_ARMORED_HIGH_TEMP, temp_progression = SERPENTID_ARMORED_STEP_TEMP) +/obj/item/organ/external/chest/carapace/Destroy() + if(owner) + owner.clear_alert("carapace_break") + . = ..() + +/obj/item/organ/external/chest/carapace/rejuvenate() + . = ..() + if(owner) + owner.clear_alert("carapace_break") + #undef SERPENTID_ARMOR_THRESHOLD_1 #undef SERPENTID_ARMOR_THRESHOLD_2 #undef SERPENTID_ARMOR_THRESHOLD_3 diff --git a/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_blades.dm b/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_blades.dm index 0eb45db8c0dd1..c289832ddc2a0 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_blades.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_blades.dm @@ -8,13 +8,39 @@ desc = "Biological melee weapon. Sharp and durable. It can cut off some heads, or maybe not..." origin_tech = null force = 11 - armour_penetration_flat = 30 - tool_behaviour = TOOL_SAW + armour_penetration_flat = 20 new_attack_chain = TRUE + var/obj/item/organ/internal/cyberimp/chest/serpentid_blades/parent_blade_implant /obj/item/kitchen/knife/combat/serpentblade/Initialize(mapload) . = ..() - ADD_TRAIT(src, TRAIT_ADVANCED_SURGICAL, ROUNDSTART_TRAIT) - AddComponent(/datum/component/forces_doors_open) + AddComponent(/datum/component/forces_doors_open/serpentid_blades, time_to_open = 8 SECONDS) AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = NON_PROJECTILE_ATTACKS) AddComponent(/datum/component/double_attack) + +/obj/item/kitchen/knife/combat/serpentblade/equipped(mob/user, slot, initial) + . = ..() + var/mob/living/carbon/human/owner = loc + if(ishuman(owner)) + if(IS_CHANGELING(owner) && force == 11) + force = 8 + armour_penetration_flat = 10 + +/obj/item/kitchen/knife/combat/serpentblade/attack(mob/living/M, mob/living/user, def_zone) + . = ..() + var/mob/living/carbon/human/H = user + if(H.invisibility == INVISIBILITY_LEVEL_TWO || H.alpha != 255) + var/obj/item/organ/internal/kidneys/serpentid/kidneys= H.get_int_organ(/obj/item/organ/internal/kidneys/serpentid) + H.reset_visibility() + kidneys.switch_mode(force_off = TRUE) + +/// subtype for mantis blades +/datum/component/forces_doors_open/serpentid_blades/on_interact(datum/source, mob/user, atom/target) + if(check_intent(user)) + return + + if(try_to_open_firedoor(target)) + return ITEM_INTERACT_COMPLETE + + if(try_to_force_open_airlock(user, target)) + return ITEM_INTERACT_COMPLETE diff --git a/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_chest.dm b/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_chest.dm index 7ec2b5818b1ff..357ce7640b779 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_chest.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/implants/serpentid_mantis_chest.dm @@ -5,7 +5,7 @@ icon_state = "chest_implant" parent_organ = "chest" actions_types = list(/datum/action/item_action/organ_action/toggle/switch_blades) - contents = newlist(/obj/item/kitchen/knife/combat/serpentblade,/obj/item/kitchen/knife/combat/serpentblade) + contents = newlist(/obj/item/kitchen/knife/combat/serpentblade) action_icon = list(/datum/action/item_action/organ_action/toggle/switch_blades = 'modular_ss220/species/serpentids/icons/organs.dmi') action_icon_state = list(/datum/action/item_action/organ_action/toggle/switch_blades = "serpentid_hand_act") var/obj/item/holder_l = null @@ -19,6 +19,13 @@ unremovable = TRUE emp_proof = TRUE var/first_recollor = TRUE + destroy_on_removal = TRUE + stealth_level = 5 + +/obj/item/organ/internal/cyberimp/chest/serpentid_blades/Initialize(mapload) + . = ..() + var/obj/item/kitchen/knife/combat/serpentblade/blade = contents[1] + blade.parent_blade_implant = src /datum/action/item_action/organ_action/toggle/switch_blades name = "Switch Threat Mode" @@ -47,8 +54,8 @@ if(crit_fail || (!holder_l && !length(contents))) to_chat(owner, span_warning("Вы не можете поднять клинки")) return - var/extended = holder_l && !(holder_l in src) - if(extended) + + if(blades_active) if(!activation_in_progress) activation_in_progress = TRUE Retract() @@ -86,6 +93,21 @@ holder_l.w_class = WEIGHT_CLASS_HUGE holder_l.materials = null + if(IS_CHANGELING(owner)) //Если линг + for(var/arm_slot in list(ITEM_SLOT_LEFT_HAND,ITEM_SLOT_RIGHT_HAND)) //Если активны в одной руке щит или меч - убрать + var/obj/item/arm_item = owner.get_item_by_slot(arm_slot) + + if(arm_item) + if(istype(arm_item, /obj/item/melee/arm_blade) || istype(arm_item, /obj/item/shield/changeling)) + if(istype(arm_item, /obj/item/melee/arm_blade)) + var/obj/item/melee/arm_blade/armblade = arm_item + var/datum/action/changeling/weapon/item_datum = armblade.parent_action + item_datum.retract(owner, TRUE) + else + var/obj/item/shield/changeling/armshield = arm_item + qdel(armshield) + + for(var/arm_slot in list(ITEM_SLOT_LEFT_HAND,ITEM_SLOT_RIGHT_HAND)) var/obj/item/arm_item = owner.get_item_by_slot(arm_slot) @@ -100,11 +122,15 @@ else to_chat(owner, span_notice("You drop [arm_item] to activate [src]!")) - if(!owner.put_in_l_hand(holder_l)) - return + holder_l.forceMove(owner) + owner.l_hand = holder_l + holder_l.layer = ABOVE_HUD_LAYER //TODO: move to equipped? + holder_l.plane = ABOVE_HUD_PLANE //TODO: move to equipped? + holder_l.equipped(owner, ITEM_SLOT_LEFT_HAND) + owner.update_inv_l_hand() blades_active = TRUE - playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + playsound(get_turf(owner), 'sound/weapons/blade_unsheath.ogg', 50, 1) new_icon_state = "blades_1" update_icon(UPDATE_OVERLAYS) return TRUE @@ -116,7 +142,7 @@ owner.transfer_item_to(holder_l, src, force = TRUE) holder_l = null blades_active = FALSE - playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + playsound(get_turf(owner), 'sound/weapons/blade_unsheath.ogg', 50, 1) new_icon_state = "blades_0" update_icon(UPDATE_OVERLAYS) @@ -126,8 +152,6 @@ return var/obj/item/organ/internal/cyberimp/chest/serpentid_blades/blades_implant = M.get_int_organ(/obj/item/organ/internal/cyberimp/chest/serpentid_blades) if(blades_implant) - if(blades_implant.owner.invisibility != INVISIBILITY_OBSERVER) - blades_implant.owner.reset_visibility() if(blades_implant.blades_active) if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK)) add_attack_logs(M, H, "Melee attacked with blades (miss/block)") @@ -138,7 +162,6 @@ if(INTENT_HELP) help(M, H, attacker_style) - if(INTENT_GRAB) blades_grab(M, H, attacker_style) @@ -150,10 +173,21 @@ else . = ..() else + if(isserpentid(M)) + var/obj/item/organ/internal/kidneys/serpentid/kidneys = M.get_int_organ(/obj/item/organ/internal/kidneys/serpentid) + M.reset_visibility() + kidneys.switch_mode(force_off = TRUE) . = ..() //Модификация усиленного граба /datum/species/proc/blades_grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + var/grab_level = GRAB_AGGRESSIVE + if(isserpentid(user) && (user.invisibility == INVISIBILITY_LEVEL_TWO)) + var/obj/item/organ/internal/kidneys/serpentid/kidneys = user.get_int_organ(/obj/item/organ/internal/kidneys/serpentid) + user.reset_visibility() + kidneys.switch_mode(force_off = TRUE) + else + grab_level = GRAB_PASSIVE if(target.check_block()) target.visible_message(span_warning("[target] blocks [user]'s grab attempt!")) return FALSE @@ -164,11 +198,15 @@ user.swap_hand() target.grabbedby(user) var/obj/item/grab/grab_item = user.get_active_hand() - grab_item.state = GRAB_AGGRESSIVE + grab_item.state = grab_level grab_item.icon_state = "grabbed1" //Модификация усиленного дизарма /datum/species/proc/blades_disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) + if(isserpentid(user)) + var/obj/item/organ/internal/kidneys/serpentid/kidneys = user.get_int_organ(/obj/item/organ/internal/kidneys/serpentid) + user.reset_visibility() + kidneys.switch_mode(force_off = TRUE) if(user == target) return FALSE if(target.check_block()) @@ -265,5 +303,9 @@ return FALSE if(!user.hand) user.swap_hand() + if(isserpentid(user)) + var/obj/item/organ/internal/kidneys/serpentid/kidneys = user.get_int_organ(/obj/item/organ/internal/kidneys/serpentid) + user.reset_visibility() + kidneys.switch_mode(force_off = TRUE) var/obj/item/kitchen/knife/combat/serpentblade/blade = user.get_active_hand() blade.attack(target, user) diff --git a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_ears.dm b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_ears.dm index 7bbc3db1bc9a7..5096e08588b5c 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_ears.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_ears.dm @@ -16,7 +16,7 @@ /obj/item/organ/internal/ears/serpentid/Initialize(mapload) . = ..() - AddComponent(/datum/component/organ_decay, 0.05, BASIC_RECOVER_VALUE) + AddComponent(/datum/component/organ_decay, 0.2, BASIC_RECOVER_VALUE) AddComponent(/datum/component/organ_toxin_damage, 0.05) AddComponent(/datum/component/hunger_organ) AddComponent(/datum/component/organ_action, radial_action_state, radial_action_icon) @@ -39,6 +39,9 @@ owner.visible_message(span_notice("Тело [owner] перестает колыхаться.")) SEND_SIGNAL(src, COMSIG_ORGAN_CHANGE_CHEM_CONSUPTION, chemical_consuption) +/obj/item/organ/internal/ears/serpentid/get_active_state() + return active + /obj/item/organ/internal/ears/serpentid/proc/sense_creatures() for(var/mob/living/creature in range(9, owner)) var/last_movement_timer = world.time - creature.l_move_time diff --git a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_eyes.dm b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_eyes.dm index 6d4e0330acd58..b096554567736 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_eyes.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_eyes.dm @@ -18,7 +18,7 @@ /obj/item/organ/internal/eyes/serpentid/Initialize(mapload) . = ..() - AddComponent(/datum/component/organ_decay, 0.04, BASIC_RECOVER_VALUE) + AddComponent(/datum/component/organ_decay, 0.16, BASIC_RECOVER_VALUE) AddComponent(/datum/component/organ_toxin_damage, 0.02) AddComponent(/datum/component/hunger_organ) AddComponent(/datum/component/organ_action, radial_action_state, radial_action_icon) @@ -54,13 +54,18 @@ . = ..() if(!force_off && owner?.nutrition >= NUTRITION_LEVEL_HYPOGLYCEMIA && !(status & ORGAN_DEAD) && !active) see_in_dark = 8 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE chemical_consuption = initial(chemical_consuption) active = TRUE owner.visible_message(span_warning("Зрачки [owner] расширяются!")) else see_in_dark = initial(see_in_dark) + lighting_alpha = initial(lighting_alpha) chemical_consuption = 0 active = FALSE owner.visible_message(span_notice("Зрачки [owner] сужаются.")) owner?.update_sight() SEND_SIGNAL(src, COMSIG_ORGAN_CHANGE_CHEM_CONSUPTION, chemical_consuption) + +/obj/item/organ/internal/eyes/serpentid/get_active_state() + return active diff --git a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_heart.dm b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_heart.dm index f5054489ae04b..b722a66c5828d 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_heart.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_heart.dm @@ -1,13 +1,14 @@ /obj/item/organ/internal/heart/serpentid name = "double heart" icon = 'modular_ss220/species/serpentids/icons/organs.dmi' - icon_state = "heart_on" + icon_state = "heart-on" + dead_icon = "heart-off" dead_icon = "heart" base_icon_state = "heart" desc = "A pair of hearts." /obj/item/organ/internal/heart/serpentid/Initialize(mapload) . = ..() - AddComponent(/datum/component/organ_decay, 0.5, BASIC_RECOVER_VALUE) + AddComponent(/datum/component/organ_decay, 0.8, BASIC_RECOVER_VALUE) AddComponent(/datum/component/organ_toxin_damage, 0.03) AddComponent(/datum/component/defib_heart_hunger) diff --git a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_kidneys.dm b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_kidneys.dm index cee80221cc3d3..c7eaee5e866c6 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_kidneys.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_kidneys.dm @@ -14,7 +14,7 @@ /obj/item/organ/internal/kidneys/serpentid/Initialize(mapload) . = ..() - AddComponent(/datum/component/organ_decay, 0.03, BASIC_RECOVER_VALUE) + AddComponent(/datum/component/organ_decay, 0.12, BASIC_RECOVER_VALUE) AddComponent(/datum/component/organ_toxin_damage, 0.15) AddComponent(/datum/component/hunger_organ) AddComponent(/datum/component/organ_action, radial_action_state, radial_action_icon) @@ -33,12 +33,16 @@ /obj/item/organ/internal/kidneys/serpentid/switch_mode(force_off = FALSE) . = ..() - if(!force_off && owner?.nutrition >= NUTRITION_LEVEL_HYPOGLYCEMIA && !cloak_engaged && !(status & ORGAN_DEAD)) - cloak_engaged = TRUE - chemical_consuption = initial(chemical_consuption) - owner.visible_message(span_warning("Тело [owner] начинает покрываться пятнами и преломлять свет!")) - else - cloak_engaged = FALSE - chemical_consuption = 0 - owner.visible_message(span_notice("Тело [owner] перестает преломлять свет.")) + if(!(HAS_TRAIT(owner, TRAIT_CLOAKBLOCKED))) + if(!force_off && owner?.nutrition >= NUTRITION_LEVEL_HYPOGLYCEMIA && !cloak_engaged && !(status & ORGAN_DEAD)) + cloak_engaged = TRUE + chemical_consuption = initial(chemical_consuption) + owner.visible_message(span_warning("Тело [owner] начинает покрываться пятнами и преломлять свет!")) + else + cloak_engaged = FALSE + chemical_consuption = 0 + owner.visible_message(span_notice("Тело [owner] перестает преломлять свет.")) SEND_SIGNAL(src, COMSIG_ORGAN_CHANGE_CHEM_CONSUPTION, chemical_consuption) + +/obj/item/organ/internal/kidneys/serpentid/get_active_state() + return cloak_engaged diff --git a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_liver.dm b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_liver.dm index f24d54aec74aa..d641dfb37c3ca 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_liver.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_liver.dm @@ -10,7 +10,7 @@ /obj/item/organ/internal/liver/serpentid/Initialize(mapload) . = ..() - AddComponent(/datum/component/organ_decay, 0.04, BASIC_RECOVER_VALUE) + AddComponent(/datum/component/organ_decay, 0.3, BASIC_RECOVER_VALUE) AddComponent(/datum/component/organ_toxin_damage, 0.1) /obj/item/organ/internal/liver/serpentid/on_life() diff --git a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_lungs.dm b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_lungs.dm index b9a1f8e4a64f6..4c07d29fa4da3 100644 --- a/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_lungs.dm +++ b/modular_ss220/species/serpentids/code/organs/internal/organs/serpentids_organs_lungs.dm @@ -27,7 +27,7 @@ /obj/item/organ/internal/lungs/serpentid/Initialize(mapload) . = ..() - AddComponent(/datum/component/organ_decay, 0.05, BASIC_RECOVER_VALUE) + AddComponent(/datum/component/organ_decay, 0.25, BASIC_RECOVER_VALUE) AddComponent(/datum/component/organ_toxin_damage, 0.05) AddComponent(/datum/component/organ_action, radial_action_state, radial_action_icon) AddComponent(/datum/component/hunger_organ) @@ -58,6 +58,7 @@ chemical_consuption = initial(chemical_consuption) last_safe_zone_check = world.time owner.visible_message(span_warning("Рот [owner] замирает, переставая выдыхать воздух!")) + SEND_SIGNAL(src, COMSIG_ORGAN_CHANGE_CHEM_CONSUPTION, chemical_consuption) else switch_mode_off() @@ -65,6 +66,7 @@ active_secretion = FALSE chemical_consuption = 0 owner.visible_message(span_notice("Из рта [owner] снова начинает исходить воздух.")) + SEND_SIGNAL(src, COMSIG_ORGAN_CHANGE_CHEM_CONSUPTION, chemical_consuption) /obj/item/organ/internal/lungs/serpentid/switch_mode(force_off = FALSE) . = ..() @@ -72,7 +74,9 @@ switch_mode_on() else switch_mode_off() - SEND_SIGNAL(src, COMSIG_ORGAN_CHANGE_CHEM_CONSUPTION, chemical_consuption) + +/obj/item/organ/internal/lungs/serpentid/get_active_state() + return active_secretion /obj/item/organ/internal/lungs/serpentid/on_life() . = ..() @@ -95,7 +99,8 @@ owner.reagents.add_reagent("salbutamol", salbutamol_production) // Если Серпентид выделяет вещества, но среда опасна и не активен "болон" - дышать через мешок - if(danger_air && !owner.internal) + if(danger_air && !ispath(owner.internal, /obj/item/tank/internals/oxygen/)) + owner.internal = null //Необходимо для сброса баллона и переключения дыхания на мешок owner.internal = serpentid_vault // Если Серпентид выделяет вещества, но среда не опасна и с момента последней проверки на безопасность дыхание прошло более 10 секунд - прекращение выделения @@ -103,9 +108,12 @@ if(safe_zone_timer > SERPENTID_LUNGS_SAFE_TIMER && !danger_air) switch_mode_off() + else + if(owner.internal == serpentid_vault) + owner.internal = null // Если Серпентид не выделяет вещества, и среда опасна и он без сознания - начать выделять вещества if(danger_air && (owner.stat == UNCONSCIOUS) && !active_secretion) - if(!owner.internal) + if(!active_secretion) switch_mode_on() // Если среда не опасна и Серпентид дышит через мешок - дышать нормально diff --git a/modular_ss220/species/serpentids/icons/mob/r_serpentid_blood.dmi b/modular_ss220/species/serpentids/icons/mob/r_serpentid_blood.dmi index 3de76cd5019aecd7c957a2c91a66dd5509395aa1..f2d676aae5f44e853509b359f0504828c5a5a230 100644 GIT binary patch literal 5944 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 PaLD;HHUI^AE%x64E)K|Y literal 5884 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 Wxy*WI2>yEk@IvvmLY16($o~UDVmCej