From cbb0fc429f67f860763e178b774eaa81820f8842 Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Mon, 24 Jul 2023 05:04:44 -0400 Subject: [PATCH 001/112] Lesser Drones (#3939) # About the pull request This PR adds lesser drones that can be joined as from ghost. You can have up to 1/3rd of the hive as lesser drones. Lesser drones can build basic resin walls/membranes/doors and can spread resin nodes. Lesser drones can give off weak pheromones. Lesser drones are very weak and die quickly. They will always gib to avoid intel bloat/clutter. When lesser drones die they do not change your last time of death so you do not lose your queue spot. Perfect to play while waiting to get in. You can spawn as a lesser drone by using the verb in the ghost tab or clicking on the hive core. Once you die as a lesser drone you must wait 3 minutes to become one again. # Explain why it's good for the game Having squishy and fast xenos with very little consequence of loss adds to the "horde-like" feel of xenos. Having something for xenos to do while waiting as a ghost is good. Makes the game feel more alive. # Testing Photographs and Procedure # Changelog :cl: Morrow add: Added lesser drones /:cl: --------- Co-authored-by: Ben10083 Co-authored-by: harryob --- code/__DEFINES/keybinding.dm | 1 + code/__DEFINES/mobs.dm | 1 + code/__DEFINES/typecheck/humanoids.dm | 2 +- code/__DEFINES/typecheck/xenos.dm | 1 + code/__DEFINES/xeno.dm | 10 +- code/_globalvars/global_lists.dm | 6 ++ code/game/gamemodes/cm_initialize.dm | 32 ++++++ code/game/jobs/role_authority.dm | 2 + .../admin/player_panel/actions/transform.dm | 5 + .../structures/special/pylon_core.dm | 17 +++ code/modules/mob/dead/observer/actions.dm | 23 +++++ code/modules/mob/dead/observer/observer.dm | 39 +++++-- .../living/carbon/xenomorph/XenoAttacks.dm | 2 +- .../lesser_drone/lesser_drone_abilities.dm | 1 + .../lesser_drone/lesser_drone_macros.dm | 1 + .../lesser_drone/lesser_drone_powers.dm | 6 ++ .../carbon/xenomorph/castes/lesser_drone.dm | 97 ++++++++++++++++++ .../living/carbon/xenomorph/xeno_defines.dm | 59 ++++++++++- colonialmarines.dme | 4 + icons/mob/hud/actions.dmi | Bin 21312 -> 21996 bytes icons/mob/xenonids/lesser_drone.dmi | Bin 0 -> 11221 bytes icons/mob/xenos/lesser_drone.dmi | Bin 0 -> 2081 bytes icons/ui_icons/map_blips.dmi | Bin 1537 -> 2672 bytes 23 files changed, 291 insertions(+), 18 deletions(-) create mode 100644 code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_abilities.dm create mode 100644 code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_macros.dm create mode 100644 code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_powers.dm create mode 100644 code/modules/mob/living/carbon/xenomorph/castes/lesser_drone.dm create mode 100644 icons/mob/xenonids/lesser_drone.dmi create mode 100644 icons/mob/xenos/lesser_drone.dmi diff --git a/code/__DEFINES/keybinding.dm b/code/__DEFINES/keybinding.dm index 422edb05508b..1878ca63f34e 100644 --- a/code/__DEFINES/keybinding.dm +++ b/code/__DEFINES/keybinding.dm @@ -189,6 +189,7 @@ #define COMSIG_KB_OBSERVER_JOIN_XENO "keybinding_observer_join_as_xeno" #define COMSIG_KB_OBSERVER_JOIN_ERT "keybinding_observer_join_ert" #define COMSIG_KB_OBSERVER_JOIN_PREDATOR "keybinding_observer_join_pred" +#define COMSIG_KB_OBSERVER_JOIN_LESSER_DRONE "keybinding_observer_join_lesser_drone" #define CATEGORY_CLIENT "CLIENT" #define CATEGORY_EMOTE "EMOTE" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index ba928e202cf0..673bb4fc6d81 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -221,6 +221,7 @@ //Mob sizes #define MOB_SIZE_SMALL 0 #define MOB_SIZE_HUMAN 1 +#define MOB_SIZE_XENO_VERY_SMALL 1.5 #define MOB_SIZE_XENO_SMALL 2 #define MOB_SIZE_XENO 3 #define MOB_SIZE_BIG 4 diff --git a/code/__DEFINES/typecheck/humanoids.dm b/code/__DEFINES/typecheck/humanoids.dm index 58d245c486e4..7076cf67c95c 100644 --- a/code/__DEFINES/typecheck/humanoids.dm +++ b/code/__DEFINES/typecheck/humanoids.dm @@ -25,7 +25,7 @@ #define isspeciessynth(A) (A.species?.group == SPECIES_SYNTHETIC) //Size checks for carbon to use instead of typechecks. (Hellhounds are deprecated) -#define iscarbonsizexeno(A) (A.mob_size >= MOB_SIZE_XENO_SMALL) +#define iscarbonsizexeno(A) (A.mob_size >= MOB_SIZE_XENO_VERY_SMALL) #define iscarbonsizehuman(A) (A.mob_size <= MOB_SIZE_HUMAN) //job/role helpers diff --git a/code/__DEFINES/typecheck/xenos.dm b/code/__DEFINES/typecheck/xenos.dm index 4d1b7819bdf1..d313090e8305 100644 --- a/code/__DEFINES/typecheck/xenos.dm +++ b/code/__DEFINES/typecheck/xenos.dm @@ -14,6 +14,7 @@ #define islarva(A) (istype(A, /mob/living/carbon/xenomorph/larva)) #define ispredalienlarva(A) (istype(A, /mob/living/carbon/xenomorph/larva/predalien)) #define isfacehugger(A) (istype(A, /mob/living/carbon/xenomorph/facehugger)) +#define islesserdrone(A) (istype(A, /mob/living/carbon/xenomorph/lesser_drone)) #define ispraetorian(A) (istype(A, /mob/living/carbon/xenomorph/praetorian)) #define isqueen(A) (istype(A, /mob/living/carbon/xenomorph/queen)) #define isravager(A) (istype(A, /mob/living/carbon/xenomorph/ravager)) diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index ac783b6f426e..82237cd793b2 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -70,6 +70,7 @@ #define HUD_ARMOR_STATES_XENO 10 /// Multiplier for time taken for a xeno to place down a resin structure +#define BUILD_TIME_MULT_LESSER_DRONE 2 #define BUILD_TIME_MULT_XENO 1 #define BUILD_TIME_MULT_BUILDER 1 #define BUILD_TIME_MULT_HIVELORD 0.5 @@ -206,6 +207,7 @@ // Health bands #define XENO_HEALTH_LARVA 35 * XENO_UNIVERSAL_HPMULT +#define XENO_HEALTH_LESSER_DRONE 160 * XENO_UNIVERSAL_HPMULT #define XENO_HEALTH_RUNNER 230 * XENO_UNIVERSAL_HPMULT // Killed by 1 PB #define XENO_HEALTH_TIER_1 250 * XENO_UNIVERSAL_HPMULT #define XENO_HEALTH_TIER_2 300 * XENO_UNIVERSAL_HPMULT @@ -603,7 +605,8 @@ #define XENO_CASTE_LARVA "Bloody Larva" #define XENO_CASTE_PREDALIEN_LARVA "Predalien Larva" #define XENO_CASTE_FACEHUGGER "Facehugger" -#define XENO_T0_CASTES list(XENO_CASTE_LARVA, XENO_CASTE_PREDALIEN_LARVA, XENO_CASTE_FACEHUGGER) +#define XENO_CASTE_LESSER_DRONE "Lesser Drone" +#define XENO_T0_CASTES list(XENO_CASTE_LARVA, XENO_CASTE_PREDALIEN_LARVA, XENO_CASTE_FACEHUGGER, XENO_CASTE_LESSER_DRONE) //t1 #define XENO_CASTE_DRONE "Drone" @@ -631,7 +634,7 @@ #define XENO_CASTE_HELLHOUND "Hellhound" #define XENO_SPECIAL_CASTES list(XENO_CASTE_QUEEN, XENO_CASTE_PREDALIEN, XENO_CASTE_HELLHOUND) -#define ALL_XENO_CASTES list(XENO_CASTE_LARVA, XENO_CASTE_PREDALIEN_LARVA, XENO_CASTE_FACEHUGGER, XENO_CASTE_DRONE, XENO_CASTE_RUNNER, XENO_CASTE_SENTINEL, XENO_CASTE_DEFENDER, XENO_CASTE_BURROWER, XENO_CASTE_CARRIER, XENO_CASTE_HIVELORD, XENO_CASTE_LURKER, XENO_CASTE_WARRIOR, XENO_CASTE_SPITTER, XENO_CASTE_BOILER, XENO_CASTE_PRAETORIAN, XENO_CASTE_CRUSHER, XENO_CASTE_RAVAGER, XENO_CASTE_QUEEN, XENO_CASTE_PREDALIEN, XENO_CASTE_HELLHOUND) +#define ALL_XENO_CASTES list(XENO_CASTE_LARVA, XENO_CASTE_PREDALIEN_LARVA, XENO_CASTE_FACEHUGGER, XENO_CASTE_LESSER_DRONE, XENO_CASTE_DRONE, XENO_CASTE_RUNNER, XENO_CASTE_SENTINEL, XENO_CASTE_DEFENDER, XENO_CASTE_BURROWER, XENO_CASTE_CARRIER, XENO_CASTE_HIVELORD, XENO_CASTE_LURKER, XENO_CASTE_WARRIOR, XENO_CASTE_SPITTER, XENO_CASTE_BOILER, XENO_CASTE_PRAETORIAN, XENO_CASTE_CRUSHER, XENO_CASTE_RAVAGER, XENO_CASTE_QUEEN, XENO_CASTE_PREDALIEN, XENO_CASTE_HELLHOUND) // Checks if two hives are allied to each other. // PARAMETERS: @@ -695,3 +698,6 @@ #define TAILSTAB_AIRLOCK_DAMAGE_MULTIPLIER 2 #define FRENZY_DAMAGE_MULTIPLIER 2 + +#define JOIN_AS_FACEHUGGER_DELAY (3 MINUTES) +#define JOIN_AS_LESSER_DRONE_DELAY (30 SECONDS) diff --git a/code/_globalvars/global_lists.dm b/code/_globalvars/global_lists.dm index 586d5e71a92d..7e65cfecd8b0 100644 --- a/code/_globalvars/global_lists.dm +++ b/code/_globalvars/global_lists.dm @@ -50,6 +50,12 @@ GLOBAL_LIST_EMPTY(mainship_pipes) // Resin constructions parameters GLOBAL_LIST_INIT_TYPED(resin_constructions_list, /datum/resin_construction, setup_resin_constructions()) +GLOBAL_LIST_INIT(resin_build_order_lesser_drone, list( + /datum/resin_construction/resin_turf/wall, + /datum/resin_construction/resin_turf/membrane, + /datum/resin_construction/resin_obj/door, +)) + GLOBAL_LIST_INIT(resin_build_order_drone, list( /datum/resin_construction/resin_turf/wall, /datum/resin_construction/resin_turf/membrane, diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index a42ff3f22e59..a7e8ab612bb4 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -548,6 +548,38 @@ Additional game mode variables. return TRUE +/datum/game_mode/proc/attempt_to_join_as_lesser_drone(mob/xeno_candidate) + var/list/active_hives = list() + var/datum/hive_status/hive + var/last_active_hive = 0 + for(var/hivenumber in GLOB.hive_datum) + hive = GLOB.hive_datum[hivenumber] + if(hive.totalXenos.len <= 0) + continue + active_hives[hive.name] = hive.hivenumber + last_active_hive = hive.hivenumber + + if(active_hives.len <= 0) + to_chat(xeno_candidate, SPAN_WARNING("There aren't any Hives active at this point for you to join.")) + return FALSE + + if(active_hives.len > 1) + var/hive_picked = tgui_input_list(xeno_candidate, "Select which Hive to attempt joining.", "Hive Choice", active_hives, theme="hive_status") + if(!hive_picked) + to_chat(xeno_candidate, SPAN_ALERT("Hive choice error. Aborting.")) + return + hive = GLOB.hive_datum[active_hives[hive_picked]] + else + hive = GLOB.hive_datum[last_active_hive] + + if(!hive.hive_location) + to_chat(xeno_candidate, SPAN_WARNING("The selected hive does not have a hive core to spawn from!")) + return + + hive.hive_location.spawn_lesser_drone(xeno_candidate) + + return TRUE + /datum/game_mode/proc/transfer_xeno(xeno_candidate, mob/living/new_xeno) if(!xeno_candidate || !isxeno(new_xeno) || QDELETED(new_xeno)) return FALSE diff --git a/code/game/jobs/role_authority.dm b/code/game/jobs/role_authority.dm index b909c38cd9e6..e7697d54f0de 100644 --- a/code/game/jobs/role_authority.dm +++ b/code/game/jobs/role_authority.dm @@ -762,6 +762,8 @@ I hope it's easier to tell what the heck this proc is even doing, unlike previou M = /mob/living/carbon/xenomorph/larva/predalien if(XENO_CASTE_FACEHUGGER) M = /mob/living/carbon/xenomorph/facehugger + if(XENO_CASTE_LESSER_DRONE) + M = /mob/living/carbon/xenomorph/lesser_drone if(XENO_CASTE_RUNNER) M = /mob/living/carbon/xenomorph/runner if(XENO_CASTE_DRONE) diff --git a/code/modules/admin/player_panel/actions/transform.dm b/code/modules/admin/player_panel/actions/transform.dm index 11dd7525bb07..185165357e05 100644 --- a/code/modules/admin/player_panel/actions/transform.dm +++ b/code/modules/admin/player_panel/actions/transform.dm @@ -38,6 +38,11 @@ GLOBAL_LIST_INIT(pp_transformables, list( name = "Facehugger", key = /mob/living/carbon/xenomorph/facehugger, color = "purple" + ), + list( + name = "Lesser Drone", + key = /mob/living/carbon/xenomorph/lesser_drone, + color = "purple" ) ), diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm index a29b49b7745a..993d4f833fa6 100644 --- a/code/modules/cm_aliens/structures/special/pylon_core.dm +++ b/code/modules/cm_aliens/structures/special/pylon_core.dm @@ -327,5 +327,22 @@ // Tell admins that this condition is reached so they know what has happened if it fails somehow return +/obj/effect/alien/resin/special/pylon/core/proc/spawn_lesser_drone(mob/xeno_candidate) + if(!linked_hive.can_spawn_as_lesser_drone(xeno_candidate)) + return FALSE + + var/mob/living/carbon/xenomorph/lesser_drone/new_drone = new /mob/living/carbon/xenomorph/lesser_drone(loc, null, linked_hive.hivenumber) + xeno_candidate.mind.transfer_to(new_drone, TRUE) + new_drone.visible_message(SPAN_XENODANGER("A lesser drone emerges out of [src]!"), SPAN_XENODANGER("You emerge out of [src] and awaken from your slumber. For the Hive!")) + playsound(new_drone, 'sound/effects/xeno_newlarva.ogg', 25, TRUE) + new_drone.generate_name() + + return TRUE + +/obj/effect/alien/resin/special/pylon/core/attack_ghost(mob/dead/observer/user) + . = ..() + if(SSticker.mode.check_xeno_late_join(user)) + SSticker.mode.attempt_to_join_as_lesser_drone(user) + #undef PYLON_REPAIR_TIME #undef PYLON_WEEDS_REGROWTH_TIME diff --git a/code/modules/mob/dead/observer/actions.dm b/code/modules/mob/dead/observer/actions.dm index 49a3890088f6..ff897db4a3f6 100644 --- a/code/modules/mob/dead/observer/actions.dm +++ b/code/modules/mob/dead/observer/actions.dm @@ -81,6 +81,22 @@ if(SSticker.mode.check_xeno_late_join(owner)) SSticker.mode.attempt_to_join_as_xeno(owner) +/datum/action/observer_action/join_lesser_drone + name = "Join as Lesser Drone" + action_icon_state = "join_lesser_drone" + listen_signal = COMSIG_KB_OBSERVER_JOIN_LESSER_DRONE + +/datum/action/observer_action/join_lesser_drone/action_activate() + if(!owner.client) + return + + if(SSticker.current_state < GAME_STATE_PLAYING || !SSticker.mode) + owner.balloon_alert(owner, "game must start!") + return + + if(SSticker.mode.check_xeno_late_join(owner)) + SSticker.mode.attempt_to_join_as_lesser_drone(owner) + /datum/keybinding/observer category = CATEGORY_OBSERVER weight = WEIGHT_DEAD @@ -108,3 +124,10 @@ name = "join_pred" full_name = "Join the Hunt" keybind_signal = COMSIG_KB_OBSERVER_JOIN_PREDATOR + +/datum/keybinding/observer/join_lesser_drone + hotkey_keys = list("Unbound") + classic_keys = list("Unbound") + name = "join_lesser_drone" + full_name = "Join as Lesser Drone" + keybind_signal = COMSIG_KB_OBSERVER_JOIN_LESSER_DRONE diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 3a35eecd8557..9e8fa264af1d 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -54,7 +54,7 @@ var/datum/health_scan/last_health_display var/ghost_orbit = GHOST_ORBIT_CIRCLE var/own_orbit_size = 0 - var/observer_actions = list(/datum/action/observer_action/join_xeno) + var/observer_actions = list(/datum/action/observer_action/join_xeno, /datum/action/observer_action/join_lesser_drone) var/datum/action/minimap/observer/minimap var/larva_queue_cached_message ///Used to bypass time of death checks such as when being selected for larva. @@ -368,12 +368,13 @@ Works together with spawning an observer, noted above. if(ghost.client.player_data) ghost.client.player_data.load_timestat_data() - // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers - // We don't change facehugger timeofdeath because they are still on cooldown if they died as a hugger - var/new_tod = isfacehugger(src) ? 1 : ghost.timeofdeath - // if they died as facehugger, bypass typical TOD checks - ghost.bypass_time_of_death_checks = isfacehugger(src) - ghost.client.player_details.larva_queue_time = max(ghost.client.player_details.larva_queue_time, new_tod) + // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers or lesser drone + var/new_tod = (isfacehugger(src) || islesserdrone(src)) ? 1 : ghost.timeofdeath + + // if they died as facehugger or lesser drone, bypass typical TOD checks + ghost.bypass_time_of_death_checks = (isfacehugger(src) || islesserdrone(src)) + + ghost.client?.player_details.larva_queue_time = max(ghost.client.player_details.larva_queue_time, new_tod) ghost.set_huds_from_prefs() @@ -418,9 +419,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(ghost && !is_admin_level(z)) ghost.timeofdeath = world.time - // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers - var/new_tod = isfacehugger(src) ? 1 : world.time - ghost.bypass_time_of_death_checks = isfacehugger(src) + // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers or lesser drone + var/new_tod = (isfacehugger(src) || islesserdrone(src)) ? 1 : ghost.timeofdeath + + // if they died as facehugger or lesser drone, bypass typical TOD checks + ghost.bypass_time_of_death_checks = (isfacehugger(src) || islesserdrone(src)) + ghost.client?.player_details.larva_queue_time = max(ghost.client.player_details.larva_queue_time, new_tod) if(is_nested && nest && !QDELETED(nest)) ghost.can_reenter_corpse = FALSE @@ -779,6 +783,21 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(SSticker.mode.check_xeno_late_join(src)) SSticker.mode.attempt_to_join_as_facehugger(src) +/mob/dead/verb/join_as_lesser_drone() + set category = "Ghost.Join" + set name = "Join as a Lesser Drone" + set desc = "Try joining as a Lesser Drone to support the hive." + + if (!client) + return + + if(SSticker.current_state < GAME_STATE_PLAYING || !SSticker.mode) + to_chat(src, SPAN_WARNING("The game hasn't started yet!")) + return + + if(SSticker.mode.check_xeno_late_join(src)) + SSticker.mode.attempt_to_join_as_lesser_drone(src) + /mob/dead/verb/join_as_zombie() //Adapted from join as hellhoud set category = "Ghost.Join" set name = "Join as Zombie" diff --git a/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm b/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm index b12ff5d6c3bb..6361ff595b10 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoAttacks.dm @@ -185,7 +185,7 @@ var/is_shover_queen = isqueen(M) var/can_resist_shove = M.hivenumber != src.hivenumber || ((isqueen(src) || IS_XENO_LEADER(src)) && !is_shover_queen) var/can_mega_shove = is_shover_queen || IS_XENO_LEADER(M) - if(can_mega_shove && !can_resist_shove) + if(can_mega_shove && !can_resist_shove || (mob_size < MOB_SIZE_XENO_SMALL && M.mob_size >= MOB_SIZE_XENO_SMALL)) playsound(loc, 'sound/weapons/alien_knockdown.ogg', 25, 1) M.visible_message(SPAN_WARNING("\The [M] shoves \the [src] out of her way!"), \ SPAN_WARNING("You shove \the [src] out of your way!"), null, 5, CHAT_TYPE_XENO_COMBAT) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_abilities.dm new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_abilities.dm @@ -0,0 +1 @@ + diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_macros.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_macros.dm new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_macros.dm @@ -0,0 +1 @@ + diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_powers.dm new file mode 100644 index 000000000000..515efea23d53 --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/abilities/lesser_drone/lesser_drone_powers.dm @@ -0,0 +1,6 @@ +/datum/action/xeno_action/onclick/plant_weeds/lesser/use_ability(atom/A) + if(!(locate(/obj/effect/alien/weeds/node) in orange(4, owner))) + to_chat(owner, SPAN_XENONOTICE("You can only plant resin nodes near other resin nodes!")) + return + + . = ..() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/lesser_drone.dm b/code/modules/mob/living/carbon/xenomorph/castes/lesser_drone.dm new file mode 100644 index 000000000000..48bf0d95ddcf --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/castes/lesser_drone.dm @@ -0,0 +1,97 @@ +/datum/caste_datum/lesser_drone + caste_type = XENO_CASTE_LESSER_DRONE + tier = 1 + melee_damage_lower = XENO_DAMAGE_TIER_1 + melee_damage_upper = XENO_DAMAGE_TIER_1 + melee_vehicle_damage = XENO_DAMAGE_TIER_1 + max_health = XENO_HEALTH_LESSER_DRONE + plasma_gain = XENO_PLASMA_GAIN_TIER_7 + plasma_max = XENO_PLASMA_TIER_3 + crystal_max = XENO_CRYSTAL_LOW + xeno_explosion_resistance = XENO_NO_EXPLOSIVE_ARMOR + armor_deflection = XENO_NO_ARMOR + evasion = XENO_EVASION_LOW + speed = XENO_SPEED_TIER_6 + + evolution_allowed = FALSE + can_be_revived = FALSE + + build_time_mult = BUILD_TIME_MULT_LESSER_DRONE + + caste_desc = "A builder of hives." + can_hold_facehuggers = 1 + can_hold_eggs = CAN_HOLD_TWO_HANDS + acid_level = 1 + weed_level = WEED_LEVEL_STANDARD + max_build_dist = 1 + + tackle_min = 4 + tackle_max = 5 + + aura_strength = 1 + + minimap_icon = "lesser_drone" + +/datum/caste_datum/lesser_drone/New() + . = ..() + + resin_build_order = GLOB.resin_build_order_lesser_drone + +/mob/living/carbon/xenomorph/lesser_drone + caste_type = XENO_CASTE_LESSER_DRONE + name = XENO_CASTE_LESSER_DRONE + desc = "An alien drone. Looks... smaller." + icon = 'icons/mob/xenos/drone.dmi' + icon_size = 48 + icon_state = "Lesser Drone Walking" + plasma_types = list(PLASMA_PURPLE) + tier = 0 + mob_flags = NOBIOSCAN + mob_size = MOB_SIZE_XENO_VERY_SMALL + life_value = 0 + default_honor_value = 0 + show_only_numbers = TRUE + counts_for_slots = FALSE + counts_for_roundend = FALSE + refunds_larva_if_banished = FALSE + crit_health = 0 + gib_chance = 100 + acid_blood_damage = 15 + base_actions = list( + /datum/action/xeno_action/onclick/xeno_resting, + /datum/action/xeno_action/onclick/regurgitate, + /datum/action/xeno_action/watch_xeno, + /datum/action/xeno_action/activable/tail_stab, + /datum/action/xeno_action/activable/corrosive_acid/weak, + /datum/action/xeno_action/onclick/emit_pheromones, + /datum/action/xeno_action/onclick/plant_weeds/lesser, //first macro + /datum/action/xeno_action/onclick/choose_resin, //second macro + /datum/action/xeno_action/activable/secrete_resin, //third macro + /datum/action/xeno_action/onclick/tacmap, + ) + inherent_verbs = list( + /mob/living/carbon/xenomorph/proc/vent_crawl, + /mob/living/carbon/xenomorph/proc/rename_tunnel, + /mob/living/carbon/xenomorph/proc/set_hugger_reserve_for_morpher, + ) + + mutation_type = DRONE_NORMAL + + icon_xeno = 'icons/mob/xenos/lesser_drone.dmi' + icon_xenonid = 'icons/mob/xenonids/lesser_drone.dmi' + +/mob/living/carbon/xenomorph/lesser_drone/age_xeno() + if(stat == DEAD || !caste || QDELETED(src) || !client) + return + + age = XENO_NORMAL + + hud_update() + + xeno_jitter(25) + +/mob/living/carbon/xenomorph/lesser_drone/initialize_pass_flags(datum/pass_flags_container/PF) + ..() + if (PF) + PF.flags_pass = PASS_MOB_IS_XENO|PASS_MOB_THRU_XENO + PF.flags_can_pass_all = PASS_MOB_IS_XENO|PASS_MOB_THRU_XENO diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index 060c3aea2814..fa01938a1203 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -1,5 +1,3 @@ -#define JOIN_AS_FACEHUGGER_DELAY 3 MINUTES - // Actual caste datum basedef /datum/caste_datum var/caste_type = "" @@ -352,6 +350,9 @@ /// How many huggers can the hive support var/playable_hugger_limit = 0 + /// How many lesser drones the hive can support + var/lesser_drone_limit = 0 + var/datum/tacmap/xeno/tacmap var/minimap_type = MINIMAP_FLAG_XENO @@ -893,8 +894,11 @@ qdel(S) for(var/mob/living/carbon/xenomorph/xeno as anything in totalXenos) if(get_area(xeno) != hijacked_dropship && xeno.loc && is_ground_level(xeno.loc.z)) - if(isfacehugger(xeno)) + if(isfacehugger(xeno) || islesserdrone(xeno)) to_chat(xeno, SPAN_XENOANNOUNCE("The Queen has left without you, you quickly find a hiding place to enter hibernation as you lose touch with the hive mind.")) + if(xeno.stomach_contents.len) + xeno.devour_timer = 0 + xeno.handle_stomach_contents() qdel(xeno) continue if(xeno.hunter_data.hunted && !isqueen(xeno)) @@ -908,7 +912,7 @@ qdel(xeno) stored_larva++ continue - if(!isfacehugger(xeno)) + if(xeno.tier >= 1) xenos_count++ for(var/i in GLOB.alive_mob_list) var/mob/living/potential_host = i @@ -1047,6 +1051,53 @@ playsound(hugger, 'sound/effects/xeno_newlarva.ogg', 25, TRUE) hugger.generate_name() +/datum/hive_status/proc/update_lesser_drone_limit() + lesser_drone_limit = Ceiling(totalXenos.len / 3) + +/datum/hive_status/proc/can_spawn_as_lesser_drone(mob/dead/observer/user) + if(!GLOB.hive_datum || ! GLOB.hive_datum[hivenumber]) + return FALSE + + if(jobban_isbanned(user, JOB_XENOMORPH)) // User is jobbanned + to_chat(user, SPAN_WARNING("You are banned from playing aliens and cannot spawn as a xenomorph.")) + return FALSE + + if(world.time - user.timeofdeath < JOIN_AS_LESSER_DRONE_DELAY) + var/time_left = round((user.timeofdeath + JOIN_AS_LESSER_DRONE_DELAY - world.time) / 10) + to_chat(user, SPAN_WARNING("You ghosted too recently. You cannot become a lesser drone until 30 seconds have passed ([time_left] seconds remaining).")) + return FALSE + + if(totalXenos.len <= 0) + to_chat(user, SPAN_WARNING("The hive has fallen, you can't join it!")) + return FALSE + + if(!living_xeno_queen) + to_chat(user, SPAN_WARNING("The selected hive does not have a Queen!")) + return FALSE + + if(!living_xeno_queen.ovipositor && !SSticker.mode.is_in_endgame) + to_chat(user, SPAN_WARNING("The selected hive does not have a Queen on Ovipositor!")) + return FALSE + + update_lesser_drone_limit() + + var/current_lesser_drone_count = 0 + for(var/mob/mob as anything in totalXenos) + if(islesserdrone(mob)) + current_lesser_drone_count++ + + if(lesser_drone_limit <= current_lesser_drone_count) + to_chat(user, SPAN_WARNING("[GLOB.hive_datum[hivenumber]] cannot support more lesser drones! Limit: [current_lesser_drone_count]/[lesser_drone_limit]")) + return FALSE + + if(tgui_alert(user, "Are you sure you want to become a lesser drone?", "Confirmation", list("Yes", "No")) != "Yes") + return FALSE + + if(!user.client) + return FALSE + + return TRUE + ///Called by /obj/item/alien_embryo when a host is bursting to determine extra larva per burst /datum/hive_status/proc/increase_larva_after_burst() var/extra_per_burst = CONFIG_GET(number/extra_larva_per_burst) diff --git a/colonialmarines.dme b/colonialmarines.dme index b241992cf172..4a5798995693 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -1855,6 +1855,9 @@ #include "code\modules\mob\living\carbon\xenomorph\abilities\facehugger\facehugger_powers.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\hivelord\hivelord_abilities.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\hivelord\hivelord_powers.dm" +#include "code\modules\mob\living\carbon\xenomorph\abilities\lesser_drone\lesser_drone_abilities.dm" +#include "code\modules\mob\living\carbon\xenomorph\abilities\lesser_drone\lesser_drone_macros.dm" +#include "code\modules\mob\living\carbon\xenomorph\abilities\lesser_drone\lesser_drone_powers.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\lurker\lurker_abilities.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\lurker\lurker_macros.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\lurker\lurker_powers.dm" @@ -1891,6 +1894,7 @@ #include "code\modules\mob\living\carbon\xenomorph\castes\Hellhound.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Hivelord.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Larva.dm" +#include "code\modules\mob\living\carbon\xenomorph\castes\lesser_drone.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Lurker.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Praetorian.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Predalien.dm" diff --git a/icons/mob/hud/actions.dmi b/icons/mob/hud/actions.dmi index 4d06977332078ca179f87621b7523a533d0c176e..9f885c44f50f133c73c834145e8925d06d86108f 100644 GIT binary patch delta 21536 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 z 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 LNkvXXu0mjf`83|T literal 0 HcmV?d00001 diff --git a/icons/ui_icons/map_blips.dmi b/icons/ui_icons/map_blips.dmi index 85ef9959027f3cb3de1da36b7a6b324e71dd80f6..829d9b8a43b09a6bab06c96c8145c04426b97288 100644 GIT binary patch delta 2659 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 ge7*k({r%4WAAEc4kh@ Date: Mon, 24 Jul 2023 10:12:41 +0100 Subject: [PATCH 002/112] Automatic changelog for PR #3939 [ci skip] --- html/changelogs/AutoChangeLog-pr-3939.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3939.yml diff --git a/html/changelogs/AutoChangeLog-pr-3939.yml b/html/changelogs/AutoChangeLog-pr-3939.yml new file mode 100644 index 000000000000..97bac6e085de --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3939.yml @@ -0,0 +1,4 @@ +author: "Morrow" +delete-after: True +changes: + - rscadd: "Added lesser drones" \ No newline at end of file From b9b353bd8f46bfe1aff832dfa43d82abcfb6d6c6 Mon Sep 17 00:00:00 2001 From: MPhonks <134622054+MPhonks@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:13:30 +0200 Subject: [PATCH 003/112] QOL Eggsac Carrier Changes - Sprites, Messages and Sounds (#3868) # About the pull request Adds new eggsac carrier sprites to the game. Includes eggsac overlay sprites that change based on how many eggs you carry. Implements a warning message for the hive when a carrier with eggs dies. Adds a sound effect to when an eggsac carrier dies. Fixes the egg drop chance upon death. **Huge thanks to ihatethisengine for helping me with the coding.** # Explain why it's good for the game Eggsac Carrier currently has no sprites, there's no differentiating one from a regular carrier. This PR attempts to give more flavor to the strain. Also fixes something, so that's nice. # Testing Photographs and Procedure (Updated)
Screenshots & Videos Sprites: ![layers](https://github.com/cmss13-devs/cmss13/assets/134622054/a967c407-b98f-43a2-a4c3-aae0b3f030db) Showcase Video: https://github.com/cmss13-devs/cmss13/assets/134622054/e6f1f978-4ad7-41eb-8917-96440f8fd974
# Changelog :cl: MarpleJones, ihatethisengine2 add: Added new sprites for the Eggsac Carrier. Includes an additional death sound for the eggsac bursting. add: Added a hive announcement for when a Carrier dies with eggs. fix: Carrier egg drop chance upon death now works as intended. /:cl: --------- Co-authored-by: harryob --- .../living/carbon/xenomorph/castes/Carrier.dm | 72 +++++++++++++++--- .../mutators/strains/carrier/eggsac.dm | 3 + icons/mob/xenos/carrier.dmi | Bin 17159 -> 22526 bytes 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm index ec1697f30081..6b847a6a4fec 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm @@ -82,15 +82,20 @@ var/list/hugger_image_index = list() var/mutable_appearance/hugger_overlays_icon + var/mutable_appearance/eggsac_overlays_icon /mob/living/carbon/xenomorph/carrier/update_icons() . = ..() - - update_hugger_overlays() + if (mutation_type == CARRIER_NORMAL) + update_hugger_overlays() + if (mutation_type == CARRIER_EGGSAC) + update_eggsac_overlays() /mob/living/carbon/xenomorph/carrier/proc/update_hugger_overlays() if(!hugger_overlays_icon) return + if(mutation_type != CARRIER_NORMAL) + return overlays -= hugger_overlays_icon hugger_overlays_icon.overlays.Cut() @@ -99,7 +104,7 @@ hugger_image_index.Cut() return - update_icon_maths(round(( huggers_cur / huggers_max ) * 3.999) + 1) + update_clinger_maths(round(( huggers_cur / huggers_max ) * 3.999) + 1) for(var/i in hugger_image_index) if(stat == DEAD) @@ -114,8 +119,8 @@ overlays += hugger_overlays_icon -/mob/living/carbon/xenomorph/carrier/proc/update_icon_maths(number) - var/funny_list = list(1,2,3,4) +/mob/living/carbon/xenomorph/carrier/proc/update_clinger_maths(number) + var/clinger_list = list(1,2,3,4) if(length(hugger_image_index) != number) if(length(hugger_image_index) > number) while(length(hugger_image_index) != number) @@ -123,20 +128,56 @@ else while(length(hugger_image_index) != number) for(var/i in hugger_image_index) - if(locate(i) in funny_list) - funny_list -= i - hugger_image_index += funny_list[rand(1,length(funny_list))] + if(locate(i) in clinger_list) + clinger_list -= i + hugger_image_index += clinger_list[rand(1,length(clinger_list))] + +/mob/living/carbon/xenomorph/carrier/proc/update_eggsac_overlays() + if(!eggsac_overlays_icon) + return + if(mutation_type != CARRIER_EGGSAC) + return + + overlays -= eggsac_overlays_icon + eggsac_overlays_icon.overlays.Cut() + + if(!eggs_cur) + return + + ///Simplified image index change. + var/i = 0 + if(eggs_cur > 8) + i = 3 + else if (eggs_cur > 4) + i = 2 + else if (eggs_cur > 0) + i = 1 + + if(stat != DEAD) + if(lying) + if((resting || sleeping) && (!knocked_down && !knocked_out && health > 0)) + eggsac_overlays_icon.overlays += icon(icon, "eggsac_[i] Sleeping") + else + eggsac_overlays_icon.overlays +=icon(icon, "eggsac_[i] Knocked Down") + else + eggsac_overlays_icon.overlays +=icon(icon, "eggsac_[i]") + + overlays += eggsac_overlays_icon /mob/living/carbon/xenomorph/carrier/Initialize(mapload, mob/living/carbon/xenomorph/oldxeno, h_number) . = ..() hugger_overlays_icon = mutable_appearance('icons/mob/xenos/overlay_effects64x64.dmi',"empty") + eggsac_overlays_icon = mutable_appearance('icons/mob/xenos/overlay_effects64x64.dmi',"empty") /mob/living/carbon/xenomorph/carrier/death(cause, gibbed) . = ..(cause, gibbed) if(.) - var/chance = 75 + var/chance = 75 //75% to drop an egg or hugger. + if(mutation_type == CARRIER_EGGSAC) + visible_message(SPAN_XENOWARNING("[src] throes as its eggsac bursts into a mess of acid!")) + playsound(src.loc, 'sound/effects/alien_egg_burst.ogg', 25, 1) - if (huggers_cur) + if(huggers_cur) //Hugger explosion, like an egg morpher var/obj/item/clothing/mask/facehugger/hugger visible_message(SPAN_XENOWARNING("The chittering mass of tiny aliens is trying to escape [src]!")) @@ -145,10 +186,15 @@ hugger = new(loc, hivenumber) step_away(hugger, src, 1) - while (eggs_cur > 0) + var/eggs_dropped = FALSE + for(var/i in 1 to eggs_cur) if(prob(chance)) new /obj/item/xeno_egg(loc, hivenumber) - eggs_cur-- + eggs_dropped = TRUE + eggs_cur = 0 + + if(eggs_dropped) //Checks whether or not to announce egg drop. + xeno_message(SPAN_XENOANNOUNCE("[src] has dropped some precious eggs!"), 2, hive.hivenumber) /mob/living/carbon/xenomorph/carrier/get_status_tab_items() . = ..() @@ -272,6 +318,7 @@ if(eggs_cur < eggs_max) if(stat == CONSCIOUS) eggs_cur++ + update_icons() to_chat(src, SPAN_NOTICE("You store the egg and carry it for safekeeping. Now sheltering: [eggs_cur] / [eggs_max].")) qdel(E) else @@ -306,6 +353,7 @@ return E = new(src, hivenumber) eggs_cur-- + update_icons() put_in_active_hand(E) to_chat(src, SPAN_XENONOTICE("You grab one of the eggs in your storage. Now sheltering: [eggs_cur] / [eggs_max].")) return diff --git a/code/modules/mob/living/carbon/xenomorph/mutators/strains/carrier/eggsac.dm b/code/modules/mob/living/carbon/xenomorph/mutators/strains/carrier/eggsac.dm index c8e6b768f2bc..436adb79e5aa 100644 --- a/code/modules/mob/living/carbon/xenomorph/mutators/strains/carrier/eggsac.dm +++ b/code/modules/mob/living/carbon/xenomorph/mutators/strains/carrier/eggsac.dm @@ -36,6 +36,8 @@ playsound(carrier.loc, 'sound/voice/alien_facehugger_dies.ogg', 25, 1) carrier.huggers_cur = 0 carrier.huggers_max = 0 + carrier.update_hugger_overlays() + carrier.update_eggsac_overlays() carrier.eggs_max = 12 carrier.extra_build_dist = 1 return TRUE @@ -73,3 +75,4 @@ if(egg_generation_progress >= 15) egg_generation_progress = 0 xeno.eggs_cur++ + xeno.update_icons() diff --git a/icons/mob/xenos/carrier.dmi b/icons/mob/xenos/carrier.dmi index 6832bbba87160a3ab5cb4b34d2b2b5433d55e31a..4b69cffd5313aee3d034f5d3b8d0852a88a0208f 100644 GIT binary patch literal 22526 zcmaI7bzED|qOT1h1PksSq_}(0;O_2PtZ0i{kmA}>ibJphEk%mEYYRn-7c0fxEnK>P z`<}D!d(VCU$S1ZkYu1`sS@S&eomedmMQlt8Oe7>EY-J@m9V8?G^zQ>51qlgBM~)SU zgoKRHQqz-vdMh9xKuN#P`D0^XXegUSa>t1!7|2z`(%o z-@jv{V_R6c>1aY2a@uO$sxd^9>GCecD z@r#$)1x3WfG?X;V^bFkW0#YhwFYxgRpsL#H=Jq188Z2Dg*qAtiBBBx!VoKWjlng9F zVlrYXI&$(_V$Zo5IC*h#@rjAZIr)Y36hsZwq*-|Qu)(+@@*1l0Qo=Iwl5$GIG8*J0 zq%soEO*G`FAaue|X#sHw5nfJpc}Xb+h3B$z!s6mA+#MBgnn1p1MS(pVVDH#AjbUH?6YAPlOD=$7iAvXsn0V$23 zsxA=)11TL7J~_RptQr^$jyK~HmQ#`EBBh{UP|`I~*3=P}SF^RXb@lOQWo6=(Q{~~| z9E?`vmsC+Uw&W9%6cU$V;}zv(7h>h&BBN#G6B84WQ5V-VRyMX)($G#*;^!hI^?UXc z^3=x2UOF1ONYFoX_D`=_1N4l%c;$gyff#n^xo8%Yzr?u)`|%HT@IG z{MR}mx;K7~QAyH9hNgWV;`e`6Su!UQvYB{osfRzNYOGK@vgXx}3X$%FeCzD;ZSc0? zobF|Ch!6}GbTf#n#dI;gkjk!{l}Pv||Lay^c3nQuy*pmmJimgSG>3ez^^7&AJ#e|p zpYyTbLMk^qjM_Og*)m7YQ*4%mnTOsLP4R{9IMWCf+p?o#1A&zhJ91P5fd?Zya{SkK zX)j8#zNR7dnqctMrG+vWV;H?pE2Q}hfW4m}RUc;d;*(}37G*tQb4Q(e`zDD+l-}u} zz0-l@!}ney?1*n*`hgva1kEWyGTM(jyN(PQ(cPkFz7p3$8j)`?Y*yUUMhiU5E#o*e zxuuSUtNzH)Co6x_MM8ogDa%Rg`Q;q6$J-JbeqgR>X;k?%_?{&)DW@+cb`wqLBQed# zZajAa@tq`kC7z65)L&bpR+lfv5*);K+_UY_;Ri4H7MIBz2j;tG!OBciE0TXY@5i1u zGN#$7elmS#!!9WW+}7Uu)v|>+Y~GUG%~Ol&w&EcJgChR#rz{>kCjz_}>*dj_&LE1W@_Vklyy^~ltUTzJ@i!Pr=?NWCHinBetZCpoL)o&r?!~T zZuKHA^h@F8Ho!@E5TXK$Rqy(Hfau@8XB))r>#~ifpvsb=mPoUfSfhm<$&lucQjf?B zX4J1@Y0=)30UMChCuc#i-}*F$o_=Nm>Sifb*CvH+(HZHRc5D`7dVI0yxYV%kYgB=V(-BMdH`V|m5+ ztQ>Ym?h*vY+LvQAvJ;z*J{B_t2Du;rZUA#N83lS&n)6fNo+~)ZvAYYPpdI*UT>>e- z8>NeM?)aLb_>#acD!m>jF!~Ee8{zx1JWSM<@TlrF15Bf|ZDjCtG?W`@uO0F%hGIKp zm-Pgm-iabfp!6pc8e%4#;`b8o3?(a;nOKJ5y{Dify0s40^+a+Pu^)0p^O|kA!ak8n zBY=%)k_DZRf`rwhIz3u(g@bOVGMl^ywB8Hrpbga0qO5~X z%R$~KoD|fr5pf7~(~=KhDO{rVMhJ{&@?89pE1S1h8%JeyT-;6ulgJGAH*|-GW+>lI zjhsF8ascf>o)TocSDfrm|6Wg*RyO=|*Y{L{0#r~KMYPcg8a-f3qf8UT-?{K+K&CM=VE{M9lYeE!-}_n!YdJDOq8f z|G4;D)Oof#kE~=uuS?FKBnG*UqO`vwz-jYu0z)rLZM%B)JaEQPmLHUMH0$8Hz{P<~ ze=V^L6fI04F2Z_SlJ8vDD%Y6aE;ju7vofO_OPycppFdsKooT#XD1-ATpc|1Rpd=m- z%YePHi$rvStTfYL;Ul72)T9a;AJ!IHn2o}$|U;^A2TRGkz{47I3b$r|MQJCm5 zL44j_!a5DW3fOPJ-mNX?kM?1<7D=qP?wl*{B6T(M1fYQ`SyJ|piYy&Nr>#;C%0yx| z2YJ&S!g~|klHFS-Q31$-)s($61pMR?IH=Ke`gr4fI;+$QcVE~!s|k_x!x%7y$U(%% zpd4gp%d)1Sq)5D`SvpyYzIb3uHOn(~KiLpo#&Xj)C`KVvU+*TpT?vhV=O<=7@Ge@c z(Uf(~AV2{_nRq8en-VkhmS(JAhZ2dZ)24ZXjzbBzbi06Jh)T63)%@1`mMz8Z^2B+Y zUz{wdORORmSTrAD6tZ0l-vF4(GNCo0gy79F#6C86(SD25gybkOtmY^zy;BUGGN#G& zD0og1I$&ed=pMlYG_o`M$#|E51qj}I_tDh@5@|q_gI0Z$5-#@=M|pQ1{#2?*Rtat| zXEqrSG<4>fiXP;4ibh713Uz)iFWAlaTASxk&XZ>?{JSSO_M@{$wd&NdRXToTIKF^8 z2K8bdMc+#JA2MMcOjLqFV?jOZ&qOu*!_pj5EuumPMAFO)AMz4$>JRW^zkZ0Nq_aI6 ztkVjsqr$$_+gv`!xGjTUwDRCaR78*B3HbTJLGn|&S_imd9xe|;dX{vel$t-=3@_>V zrlQ0k@CU)E8V1+u4N)!_mgIABF60B8bF-#LeD!zP`mL24msY#6E#vWeKV~DZl;Q)r zxpsN7I?I7WXh1>)V9s+B|MEx8rqg8MTRiKruU5X!TIZL_!`hC^I6FVM@UR`_G*r#Z zGd*t@j?EXG2XE` z5^9{!TaPuZGFGx7Oa;`kZW+~x28J9OUE7I#@O%6QR*9m_4_&AO_N<_}zbCs+XaoU& z*0c4k`VP>DF1&k}mnl{}6IOtDuRZ4Fj2CFwj1`9BRM%NjY7C|&MiJh{3g{@&j5@eX z?{-RtKEt1}V)tylns&ZpeuY$cTl93_bg=nXE7Cg3YQERL+KfKdQv~Jb=FD%roih)` zk}3QG4I{jHOG32&GpF$On}Bd?JhZ{VI&h2B3D!hhaDgm{?ur2_Xpn$U?Wo|HL3N27 z6*bv6y4)yF5Ma@iP3EbHJ@cWwKTG_#&?b^2k&X?K`KDx!Nx5)G_7r=%!YhY;7L6^# z9yAOocn!z>A6Y<%JF0>L$w+8pNOw7znNsxyvE#
{f(-u0k7b1dh#(=bGx5bb2Ql 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 HEyDgEmw(KW From fadd0701810295bb4a066d019a86894c66d41d85 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 13:23:00 +0100 Subject: [PATCH 004/112] Automatic changelog for PR #3868 [ci skip] --- html/changelogs/AutoChangeLog-pr-3868.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3868.yml diff --git a/html/changelogs/AutoChangeLog-pr-3868.yml b/html/changelogs/AutoChangeLog-pr-3868.yml new file mode 100644 index 000000000000..4bd11e9a6b0e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3868.yml @@ -0,0 +1,6 @@ +author: "MarpleJones, ihatethisengine2" +delete-after: True +changes: + - rscadd: "Added new sprites for the Eggsac Carrier. Includes an additional death sound for the eggsac bursting." + - rscadd: "Added a hive announcement for when a Carrier dies with eggs." + - bugfix: "Carrier egg drop chance upon death now works as intended." \ No newline at end of file From b97cd09cd17b129b50afacf150dabbcb777c3746 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Mon, 24 Jul 2023 05:56:01 -0700 Subject: [PATCH 005/112] Fix bodybags requiring ToD even if unreviveable (#3964) # About the pull request This PR adjusts the condition to close a mob in a body bag such that time of death only matters if the mob is reviveable. Also now doesn't care if a ghost exists or not since they could have just disconnected temporarily. # Explain why it's good for the game Fixes #3958 # Testing Photographs and Procedure
Screenshots & Videos ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/8b80e5db-2c16-4580-86c3-0d442a251b53)
# Changelog :cl: Drathek fix: Fix bodybags not accepting warm (recent) dead bodies even if unreviveable /:cl: --- code/game/objects/items/bodybag.dm | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 55f3c32cebba..3b84d2433e88 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -122,25 +122,27 @@ /obj/structure/closet/bodybag/store_mobs(stored_units) // overriding this var/list/dead_mobs = list() - for(var/mob/living/M in loc) - if(M.buckled) + for(var/mob/living/mob in loc) + if(mob.buckled) continue - if(M.stat != DEAD) // covers alive mobs + if(mob.stat != DEAD) // covers alive mobs continue - if(!ishuman(M)) // all the dead other shit - dead_mobs += M + if(!ishuman(mob)) // all the dead other shit + dead_mobs += mob continue - var/mob/living/carbon/human/H = M - if(H.check_tod() || issynth(H) || H.is_revivable() && H.get_ghost()) // revivable + var/mob/living/carbon/human/human = mob + if(issynth(human)) continue - dead_mobs += M + if(human.check_tod() && human.is_revivable()) // revivable + continue + dead_mobs += mob var/mob/living/mob_to_store if(dead_mobs.len) mob_to_store = pick(dead_mobs) mob_to_store.forceMove(src) stored_units += mob_size - for(var/obj/item/limb/L in loc) - L.forceMove(src) + for(var/obj/item/limb/limb in loc) + limb.forceMove(src) return stored_units /obj/structure/closet/bodybag/attack_hand(mob/living/user) From 1b1171a98bff98508f44b5834a3edfe188c6a5d8 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:05:13 +0100 Subject: [PATCH 006/112] Automatic changelog for PR #3964 [ci skip] --- html/changelogs/AutoChangeLog-pr-3964.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3964.yml diff --git a/html/changelogs/AutoChangeLog-pr-3964.yml b/html/changelogs/AutoChangeLog-pr-3964.yml new file mode 100644 index 000000000000..ccd54d9eda5f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3964.yml @@ -0,0 +1,4 @@ +author: "Drathek" +delete-after: True +changes: + - bugfix: "Fix bodybags not accepting warm (recent) dead bodies even if unreviveable" \ No newline at end of file From 6565f67f4ed996a6b5597c3719c233e7a571dc68 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Mon, 24 Jul 2023 08:11:25 -0700 Subject: [PATCH 007/112] Fix Some Preferences Not Saving (#3975) # About the pull request This PR increases the size of some settings (namely toggle_prefs) from 16 bits to 24 bits so preferences like TOGGLE_LATE_JOIN_CURRENT_SLOT and TOGGLE_ABILITY_DEACTIVATION_OFF will now actually stick. # Explain why it's good for the game Fixes at least two preferences not saving/loading correctly. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: Drathek fix: Fixed ability deactivation and late join current slot toggles not persisting. fix: Toggle the Ability to Hurt Yourself now says On when you can hurt yourself. /:cl: --- code/modules/client/preferences.dm | 2 +- code/modules/client/preferences_savefile.dm | 22 ++++++++++----------- code/modules/tgui/tgui_number_input.dm | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 5698c30c0acf..16afa8d1b4f2 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -590,7 +590,7 @@ var/const/MAX_SAVE_SLOTS = 10 dat += "
" dat += "

Gameplay Toggles:

" dat += "Toggle Being Able to Hurt Yourself: \ -
[toggle_prefs & TOGGLE_IGNORE_SELF ? "On" : "Off"]
" + [toggle_prefs & TOGGLE_IGNORE_SELF ? "Off" : "On"]
" dat += "Toggle Help Intent Safety: \ [toggle_prefs & TOGGLE_HELP_INTENT_SAFETY ? "On" : "Off"]
" dat += "Toggle Middle Mouse Ability Activation: \ diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 0a1b54112f18..0f482fa7f894 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -199,22 +199,22 @@ lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) UI_style = sanitize_inlist(UI_style, list("white", "dark", "midnight", "orange", "old"), initial(UI_style)) tgui_say = sanitize_integer(tgui_say, FALSE, TRUE, TRUE) - be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) + be_special = sanitize_integer(be_special, 0, SHORT_REAL_LIMIT, initial(be_special)) default_slot = sanitize_integer(default_slot, 1, MAX_SAVE_SLOTS, initial(default_slot)) - toggles_chat = sanitize_integer(toggles_chat, 0, 65535, initial(toggles_chat)) - chat_display_preferences = sanitize_integer(chat_display_preferences, 0, 65535, initial(chat_display_preferences)) - toggles_ghost = sanitize_integer(toggles_ghost, 0, 65535, initial(toggles_ghost)) - toggles_langchat = sanitize_integer(toggles_langchat, 0, 65535, initial(toggles_langchat)) - toggles_sound = sanitize_integer(toggles_sound, 0, 65535, initial(toggles_sound)) - toggle_prefs = sanitize_integer(toggle_prefs, 0, 65535, initial(toggle_prefs)) - toggles_flashing= sanitize_integer(toggles_flashing, 0, 65535, initial(toggles_flashing)) - toggles_ert = sanitize_integer(toggles_ert, 0, 65535, initial(toggles_ert)) - toggles_admin = sanitize_integer(toggles_admin, 0, 65535, initial(toggles_admin)) + toggles_chat = sanitize_integer(toggles_chat, 0, SHORT_REAL_LIMIT, initial(toggles_chat)) + chat_display_preferences = sanitize_integer(chat_display_preferences, 0, SHORT_REAL_LIMIT, initial(chat_display_preferences)) + toggles_ghost = sanitize_integer(toggles_ghost, 0, SHORT_REAL_LIMIT, initial(toggles_ghost)) + toggles_langchat = sanitize_integer(toggles_langchat, 0, SHORT_REAL_LIMIT, initial(toggles_langchat)) + toggles_sound = sanitize_integer(toggles_sound, 0, SHORT_REAL_LIMIT, initial(toggles_sound)) + toggle_prefs = sanitize_integer(toggle_prefs, 0, SHORT_REAL_LIMIT, initial(toggle_prefs)) + toggles_flashing= sanitize_integer(toggles_flashing, 0, SHORT_REAL_LIMIT, initial(toggles_flashing)) + toggles_ert = sanitize_integer(toggles_ert, 0, SHORT_REAL_LIMIT, initial(toggles_ert)) + toggles_admin = sanitize_integer(toggles_admin, 0, SHORT_REAL_LIMIT, initial(toggles_admin)) UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color)) UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha)) item_animation_pref_level = sanitize_integer(item_animation_pref_level, SHOW_ITEM_ANIMATIONS_NONE, SHOW_ITEM_ANIMATIONS_ALL, SHOW_ITEM_ANIMATIONS_ALL) pain_overlay_pref_level = sanitize_integer(pain_overlay_pref_level, PAIN_OVERLAY_BLURRY, PAIN_OVERLAY_LEGACY, PAIN_OVERLAY_BLURRY) - window_skin = sanitize_integer(window_skin, 0, 65535, initial(window_skin)) + window_skin = sanitize_integer(window_skin, 0, SHORT_REAL_LIMIT, initial(window_skin)) ghost_vision_pref = sanitize_inlist(ghost_vision_pref, list(GHOST_VISION_LEVEL_NO_NVG, GHOST_VISION_LEVEL_MID_NVG, GHOST_VISION_LEVEL_FULL_NVG), GHOST_VISION_LEVEL_MID_NVG) ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit)) playtime_perks = sanitize_integer(playtime_perks, 0, 1, 1) diff --git a/code/modules/tgui/tgui_number_input.dm b/code/modules/tgui/tgui_number_input.dm index 9c447ecd5a03..aa189b1d2039 100644 --- a/code/modules/tgui/tgui_number_input.dm +++ b/code/modules/tgui/tgui_number_input.dm @@ -31,7 +31,7 @@ qdel(number_input) ///A clone of tgui_input_number that defaults to accepting negative inputs too. -/proc/tgui_input_real_number(mob/user, message, title = "Number Input", default = 0, max_value = 16777216, min_value = -16777216, timeout = 0, integer_only = FALSE) +/proc/tgui_input_real_number(mob/user, message, title = "Number Input", default = 0, max_value = SHORT_REAL_LIMIT, min_value = -SHORT_REAL_LIMIT, timeout = 0, integer_only = FALSE) return tgui_input_number(user, message, title, default, max_value, min_value, timeout, integer_only) /** * Creates an asynchronous TGUI number input window with an associated callback. From 85d415a1e7474d956706459a5cedb5fa9a3bacac Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:23:15 +0100 Subject: [PATCH 008/112] Automatic changelog for PR #3975 [ci skip] --- html/changelogs/AutoChangeLog-pr-3975.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3975.yml diff --git a/html/changelogs/AutoChangeLog-pr-3975.yml b/html/changelogs/AutoChangeLog-pr-3975.yml new file mode 100644 index 000000000000..6f871b20bbb6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3975.yml @@ -0,0 +1,5 @@ +author: "Drathek" +delete-after: True +changes: + - bugfix: "Fixed ability deactivation and late join current slot toggles not persisting." + - bugfix: "Toggle the Ability to Hurt Yourself now says On when you can hurt yourself." \ No newline at end of file From b97bf7c29a15ce6db59b9a1df2902004c7d5b4dd Mon Sep 17 00:00:00 2001 From: morrowwolf Date: Mon, 24 Jul 2023 13:01:00 -0400 Subject: [PATCH 009/112] Stops multiple facehuggers spawning from one client (#3949) # About the pull request Stops stacking prompts to spawn multiple facehuggers. # Explain why it's good for the game Bug bad # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: Morrow fix: Stops multiple facehuggers spawning from one client /:cl: --- code/modules/mob/living/carbon/xenomorph/xeno_defines.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index fa01938a1203..eaff5a66309e 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -1040,8 +1040,12 @@ to_chat(user, SPAN_WARNING("\The [GLOB.hive_datum[hivenumber]] cannot support more facehuggers! Limit: [current_hugger_count]/[playable_hugger_limit]")) return FALSE - if(alert(user, "Are you sure you want to become a facehugger?", "Confirmation", "Yes", "No") != "Yes") + if(tgui_alert(user, "Are you sure you want to become a facehugger?", "Confirmation", list("Yes", "No")) != "Yes") return FALSE + + if(!user.client) + return FALSE + return TRUE /datum/hive_status/proc/spawn_as_hugger(mob/dead/observer/user, atom/A) From 89633586a6981756bef6afeef74ad2f7b6a8d3fe Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 18:15:37 +0100 Subject: [PATCH 010/112] Automatic changelog for PR #3949 [ci skip] --- html/changelogs/AutoChangeLog-pr-3949.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3949.yml diff --git a/html/changelogs/AutoChangeLog-pr-3949.yml b/html/changelogs/AutoChangeLog-pr-3949.yml new file mode 100644 index 000000000000..eca0cae6dc4a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3949.yml @@ -0,0 +1,4 @@ +author: "Morrow" +delete-after: True +changes: + - bugfix: "Stops multiple facehuggers spawning from one client" \ No newline at end of file From 31bbe21b751fc4c84e8a0a0efc8a1e355f74e6e7 Mon Sep 17 00:00:00 2001 From: ghostsheet <43085828+ghostsheet@users.noreply.github.com> Date: Tue, 25 Jul 2023 03:34:58 +1000 Subject: [PATCH 011/112] General Pouches Tweaks & Fixes (#3764) # About the pull request large general pouch has stricter restriction against internal boxes. Remove the one medium item restriction for large general pouch, makes it more competitive with other pouches Added Large general pouch to REQ at the same rarity as Large Shotgun pouch, why wasn't it there before? we can reduce further if it's necessary Reshuffled Req Pouch order, Grouped pouches by type, medical > engineering> Misc > Ammo, RIP muscle memory Remove some useless code # Explain why it's good for the game more gameplay option good, QOL good, useless code bad # Changelog :cl: ghostsheet add: Large General Pouch has stricter restriction against internal boxes. add: Large General Pouch no longer restricted to 1 medium item. add: Large General Pouch added to REQ. add: Shuffled REQ pouch order into Meds, Engi, Misc, Ammo. /:cl: --- .../vending/vendor_types/requisitions.dm | 27 +++++++++--------- code/game/objects/items/storage/pouch.dm | 28 ++----------------- 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index b8e3e55f1d89..f85657e887a8 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -92,26 +92,27 @@ list("POUCHES", -1, null, null), list("Autoinjector Pouch", round(scale * 2), /obj/item/storage/pouch/autoinjector, VENDOR_ITEM_REGULAR), - list("Bayonet Pouch", round(scale * 2), /obj/item/storage/pouch/bayonet, VENDOR_ITEM_REGULAR), + list("Medkit Pouch", round(scale * 2), /obj/item/storage/pouch/medkit, VENDOR_ITEM_REGULAR), + list("Medical Pouch", round(scale * 2), /obj/item/storage/pouch/medical, VENDOR_ITEM_REGULAR), + list("First-Aid Pouch (Full)", round(scale * 5), /obj/item/storage/pouch/firstaid/full, VENDOR_ITEM_REGULAR), + list("First Responder Pouch", round(scale * 2), /obj/item/storage/pouch/first_responder, VENDOR_ITEM_REGULAR), + list("Syringe Pouch", round(scale * 2), /obj/item/storage/pouch/syringe, VENDOR_ITEM_REGULAR), + list("Tools Pouch (Full)", round(scale * 2), /obj/item/storage/pouch/tools/full, VENDOR_ITEM_REGULAR), list("Construction Pouch", round(scale * 2), /obj/item/storage/pouch/construction, VENDOR_ITEM_REGULAR), - list("Document Pouch", round(scale * 2), /obj/item/storage/pouch/document/small, VENDOR_ITEM_REGULAR), list("Electronics Pouch", round(scale * 2), /obj/item/storage/pouch/electronics, VENDOR_ITEM_REGULAR), list("Explosive Pouch", round(scale * 2), /obj/item/storage/pouch/explosive, VENDOR_ITEM_REGULAR), - list("First-Aid Pouch (Full)", round(scale * 5), /obj/item/storage/pouch/firstaid/full, VENDOR_ITEM_REGULAR), - list("First Responder Pouch", round(scale * 2), /obj/item/storage/pouch/first_responder, VENDOR_ITEM_REGULAR), list("Flare Pouch (Full)", round(scale * 5), /obj/item/storage/pouch/flare/full, VENDOR_ITEM_REGULAR), - list("Fuel Tank Strap Pouch", round(scale * 4), /obj/item/storage/pouch/flamertank, VENDOR_ITEM_REGULAR), - list("Large Pistol Magazine Pouch", round(scale * 5), /obj/item/storage/pouch/magazine/pistol/large, VENDOR_ITEM_REGULAR), - list("Magazine Pouch", round(scale * 5), /obj/item/storage/pouch/magazine, VENDOR_ITEM_REGULAR), - list("Shotgun Shell Pouch", round(scale * 5), /obj/item/storage/pouch/shotgun, VENDOR_ITEM_REGULAR), + list("Document Pouch", round(scale * 2), /obj/item/storage/pouch/document/small, VENDOR_ITEM_REGULAR), + list("Sling Pouch", round(scale * 2), /obj/item/storage/pouch/sling, VENDOR_ITEM_REGULAR), list("Machete Pouch (Full)", round(scale * 4), /obj/item/storage/pouch/machete/full, VENDOR_ITEM_REGULAR), - list("Medical Pouch", round(scale * 2), /obj/item/storage/pouch/medical, VENDOR_ITEM_REGULAR), + list("Bayonet Pouch", round(scale * 2), /obj/item/storage/pouch/bayonet, VENDOR_ITEM_REGULAR), list("Medium General Pouch", round(scale * 2), /obj/item/storage/pouch/general/medium, VENDOR_ITEM_REGULAR), - list("Medkit Pouch", round(scale * 2), /obj/item/storage/pouch/medkit, VENDOR_ITEM_REGULAR), + list("Magazine Pouch", round(scale * 5), /obj/item/storage/pouch/magazine, VENDOR_ITEM_REGULAR), + list("Shotgun Shell Pouch", round(scale * 5), /obj/item/storage/pouch/shotgun, VENDOR_ITEM_REGULAR), list("Sidearm Pouch", round(scale * 5), /obj/item/storage/pouch/pistol, VENDOR_ITEM_REGULAR), - list("Syringe Pouch", round(scale * 2), /obj/item/storage/pouch/syringe, VENDOR_ITEM_REGULAR), - list("Tools Pouch (Full)", round(scale * 2), /obj/item/storage/pouch/tools/full, VENDOR_ITEM_REGULAR), - list("Sling Pouch", round(scale * 2), /obj/item/storage/pouch/sling, VENDOR_ITEM_REGULAR), + list("Large Pistol Magazine Pouch", round(scale * 5), /obj/item/storage/pouch/magazine/pistol/large, VENDOR_ITEM_REGULAR), + list("Fuel Tank Strap Pouch", round(scale * 4), /obj/item/storage/pouch/flamertank, VENDOR_ITEM_REGULAR), + list("Large General Pouch", round(scale * 2), /obj/item/storage/pouch/general/large, VENDOR_ITEM_REGULAR), list("Large Magazine Pouch", round(scale * 2), /obj/item/storage/pouch/magazine/large, VENDOR_ITEM_REGULAR), list("Large Shotgun Shell Pouch", round(scale * 2), /obj/item/storage/pouch/shotgun/large, VENDOR_ITEM_REGULAR), diff --git a/code/game/objects/items/storage/pouch.dm b/code/game/objects/items/storage/pouch.dm index 7a49f48cdc92..dc3ee0ba1506 100644 --- a/code/game/objects/items/storage/pouch.dm +++ b/code/game/objects/items/storage/pouch.dm @@ -58,29 +58,12 @@ max_w_class = SIZE_MEDIUM cant_hold = list( //Prevent inventory bloat /obj/item/storage/firstaid, - /obj/item/storage/bible + /obj/item/storage/bible, + /obj/item/storage/box, ) storage_slots = null max_storage_space = 2 -/obj/item/storage/pouch/general/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/ammo_magazine/shotgun)) - var/obj/item/ammo_magazine/shotgun/M = W - dump_ammo_to(M,user) - else if(istype(W, /obj/item/storage/box/nade_box) || istype(W, /obj/item/storage/box/m94)) - dump_into(W, user) - else - return ..() - -/obj/item/storage/pouch/general/can_be_inserted(obj/item/W, stop_messages) - . = ..() - if(. && W.w_class == SIZE_MEDIUM) - for(var/obj/item/I in return_inv()) - if(I.w_class >= SIZE_MEDIUM) - if(!stop_messages) - to_chat(usr, SPAN_NOTICE("[src] is already too bulky with [I].")) - return FALSE - /obj/item/storage/pouch/general/medium name = "medium general pouch" desc = "A general-purpose pouch used to carry a variety of differently sized items." @@ -468,13 +451,6 @@ for(var/i = 1 to storage_slots) new /obj/item/ammo_magazine/pistol/vp78(src) -/obj/item/storage/pouch/magazine/shotgun/attackby(obj/item/W, mob/living/user) - if(istype(W, /obj/item/ammo_magazine/shotgun)) - var/obj/item/ammo_magazine/shotgun/M = W - dump_ammo_to(M, user, M.transfer_handful_amount) - else - return ..() - /obj/item/storage/pouch/magazine/pulse_rifle/fill_preset_inventory() for(var/i = 1 to storage_slots) new /obj/item/ammo_magazine/rifle(src) From 047307c53ee427e65d6ecaf7bc0dea77d9000f49 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:03:35 +0100 Subject: [PATCH 012/112] Automatic changelog for PR #3764 [ci skip] --- html/changelogs/AutoChangeLog-pr-3764.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3764.yml diff --git a/html/changelogs/AutoChangeLog-pr-3764.yml b/html/changelogs/AutoChangeLog-pr-3764.yml new file mode 100644 index 000000000000..ecb789daaf91 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3764.yml @@ -0,0 +1,7 @@ +author: "ghostsheet" +delete-after: True +changes: + - rscadd: "Large General Pouch has stricter restriction against internal boxes." + - rscadd: "Large General Pouch no longer restricted to 1 medium item." + - rscadd: "Large General Pouch added to REQ." + - rscadd: "Shuffled REQ pouch order into Meds, Engi, Misc, Ammo." \ No newline at end of file From 894e15f28298ca1bafab04bdfc5dd6e9867eecea Mon Sep 17 00:00:00 2001 From: harryob Date: Mon, 24 Jul 2023 19:14:27 +0100 Subject: [PATCH 013/112] adds comments to conflicts.yml --- .github/workflows/conflicts.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/conflicts.yml b/.github/workflows/conflicts.yml index 02d9da40342b..b65a5213ab4a 100644 --- a/.github/workflows/conflicts.yml +++ b/.github/workflows/conflicts.yml @@ -12,4 +12,6 @@ jobs: - uses: eps1lon/actions-label-merge-conflict@v2.1.0 with: dirtyLabel: 'Merge Conflict' + commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request." + commentOnClean: "Conflicts have been resolved. A maintainer will review the pull request shortly." repoToken: ${{ secrets.BOT_TOKEN_CM || secrets.GITHUB_TOKEN }} From 49855f1fe043b0a1053dad83784081075bc0dfbc Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Mon, 24 Jul 2023 18:50:35 +0100 Subject: [PATCH 014/112] Yautja cloak changes (#3757) # About the pull request Makes Yautja cloak permanent and cost no power. Also adds various multipliers for forced decloak source, resulting in differing durations it is unusable. # Explain why it's good for the game Following discussions with Yautja Council and MorrowWolf, as referenced in #3261, Yautja overall are going to go through an overhaul to their dynamic and how they interact with the round, moving them more towards glass canons. The reason for permanent cloak however, is to prevent/reduce instances of Yautja players standing around in the open like football spectators as this detracts from their atmosphere. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Made Yautja cloak cost no power to operate, and created multipliers for disabled duration based upon what caused the Yautja to decloak. /:cl: --- code/__DEFINES/combat.dm | 15 +++++++ code/game/turfs/open.dm | 2 +- code/modules/cm_preds/yaut_bracers.dm | 41 +++++++------------ .../abilities/predalien/predalien_powers.dm | 2 +- 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 60c4116df330..31df07648fc0 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -20,3 +20,18 @@ #define DEFAULT_MESSAGE_RANGE 7 #define BAYONET_DRAW_DELAY (1 SECONDS) + +//Predator decloak multpliers based on the standard. +#define DECLOAK_STANDARD (10 SECONDS) +/// Forced for any unspecified reason. +#define DECLOAK_FORCED 1 +/// Caused by being worn by non humans. +#define DECLOAK_SPECIES 0.75 +/// Caused by fire extinguisher. +#define DECLOAK_EXTINGUISHER 1.5 +/// Caused by predalien screech. +#define DECLOAK_PREDALIEN 2 +/// Caused by being in a body of water. +#define DECLOAK_SUBMERGED 2 +/// Caused by an EMP. +#define DECLOAK_EMP 3 diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 3f7192b0090b..41ac80bfdc58 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -517,7 +517,7 @@ var/obj/item/clothing/gloves/yautja/hunter/Y = H.gloves if(Y && istype(Y) && Y.cloaked) to_chat(H, SPAN_WARNING(" Your bracers hiss and spark as they short out!")) - Y.decloak(H, TRUE) + Y.decloak(H, TRUE, DECLOAK_SUBMERGED) else if(isxeno(C)) river_slowdown -= 0.7 diff --git a/code/modules/cm_preds/yaut_bracers.dm b/code/modules/cm_preds/yaut_bracers.dm index 5c4079b2be23..05e4a8205c94 100644 --- a/code/modules/cm_preds/yaut_bracers.dm +++ b/code/modules/cm_preds/yaut_bracers.dm @@ -101,15 +101,6 @@ var/perc = (charge / charge_max * 100) human.update_power_display(perc) - //Non-Yautja have a chance to get stunned with each power drain - if(!HAS_TRAIT(human, TRAIT_YAUTJA_TECH) && !human.hunter_data.thralled) - if(prob(15)) - if(cloaked) - decloak(human) - cloak_timer = world.time + 5 SECONDS - shock_user(human) - return FALSE - return TRUE /obj/item/clothing/gloves/yautja/proc/shock_user(mob/living/carbon/human/M) @@ -242,7 +233,7 @@ if(wearer.gloves == src) wearer.visible_message(SPAN_DANGER("You hear a hiss and crackle!"), SPAN_DANGER("Your bracers hiss and spark!"), SPAN_DANGER("You hear a hiss and crackle!")) if(cloaked) - decloak(wearer) + decloak(wearer, TRUE, DECLOAK_EMP) else var/turf/our_turf = get_turf(src) our_turf.visible_message(SPAN_DANGER("You hear a hiss and crackle!"), SPAN_DANGER("You hear a hiss and crackle!")) @@ -282,29 +273,25 @@ var/mob/living/carbon/human/human = loc - if(cloaked) - charge = max(charge - 10, 0) - if(charge <= 0) - decloak(loc) - //Non-Yautja have a chance to get stunned with each power drain - if(!isyautja(human)) - if(prob(15)) - decloak(human) - shock_user(human) - return + //Non-Yautja have a chance to get stunned with each power drain + if((!HAS_TRAIT(human, TRAIT_YAUTJA_TECH) && !human.hunter_data.thralled) && prob(15)) + if(cloaked) + decloak(human, TRUE, DECLOAK_SPECIES) + shock_user(human) + return ..() /obj/item/clothing/gloves/yautja/hunter/dropped(mob/user) move_chip_to_bracer() if(cloaked) - decloak(user) + decloak(user, TRUE) ..() /obj/item/clothing/gloves/yautja/hunter/on_enter_storage(obj/item/storage/S) if(ishuman(loc)) var/mob/living/carbon/human/human = loc if(cloaked) - decloak(human) + decloak(human, TRUE) . = ..() //We use this to activate random verbs for non-Yautja @@ -528,7 +515,6 @@ if(true_cloak) M.invisibility = INVISIBILITY_LEVEL_ONE M.see_invisible = SEE_INVISIBLE_LEVEL_ONE - new_alpha = 75 log_game("[key_name_admin(usr)] has enabled their cloaking device.") M.visible_message(SPAN_WARNING("[M] vanishes into thin air!"), SPAN_NOTICE("You are now invisible to normal detection.")) @@ -553,17 +539,18 @@ sparks.set_up(5, 4, src) sparks.start() - decloak(wearer, TRUE) + decloak(wearer, TRUE, DECLOAK_EXTINGUISHER) -/obj/item/clothing/gloves/yautja/hunter/decloak(mob/user, forced) +/obj/item/clothing/gloves/yautja/hunter/decloak(mob/user, forced, force_multipler = DECLOAK_FORCED) if(!user) return UnregisterSignal(user, COMSIG_HUMAN_EXTINGUISH) UnregisterSignal(user, COMSIG_HUMAN_PRE_BULLET_ACT) + var/decloak_timer = (DECLOAK_STANDARD * force_multipler) if(forced) - cloak_malfunction = world.time + 10 SECONDS + cloak_malfunction = world.time + decloak_timer cloaked = FALSE log_game("[key_name_admin(usr)] has disabled their cloaking device.") @@ -573,7 +560,7 @@ if(true_cloak) user.invisibility = initial(user.invisibility) user.see_invisible = initial(user.see_invisible) - cloak_timer = world.time + 5 SECONDS + cloak_timer = world.time + (DECLOAK_STANDARD / 2) var/datum/mob_hud/security/advanced/SA = huds[MOB_HUD_SECURITY_ADVANCED] SA.add_to_hud(user) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm index 058e643f5c64..5c1584c565c6 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/predalien/predalien_powers.dm @@ -25,7 +25,7 @@ var/obj/item/clothing/gloves/yautja/hunter/YG = locate(/obj/item/clothing/gloves/yautja/hunter) in human if(isyautja(human) && YG) if(YG.cloaked) - YG.decloak(human) + YG.decloak(human, TRUE, DECLOAK_PREDALIEN) YG.cloak_timer = xeno_cooldown * 0.1 else if(isxeno(carbon) && xeno.can_not_harm(carbon)) From f7c04d8fe023f2d81a893620ee3998190ae8e7a9 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:50:42 +0100 Subject: [PATCH 015/112] Automatic changelog for PR #3757 [ci skip] --- html/changelogs/AutoChangeLog-pr-3757.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3757.yml diff --git a/html/changelogs/AutoChangeLog-pr-3757.yml b/html/changelogs/AutoChangeLog-pr-3757.yml new file mode 100644 index 000000000000..4cc6cc928423 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3757.yml @@ -0,0 +1,4 @@ +author: "realforest2001" +delete-after: True +changes: + - rscadd: "Made Yautja cloak cost no power to operate, and created multipliers for disabled duration based upon what caused the Yautja to decloak." \ No newline at end of file From cb855f807b4f5538d623e78363e76aabd5f8d80a Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:03:50 +0100 Subject: [PATCH 016/112] Yautja Gear Recovery Changes (#3455) # About the pull request Makes pred gear recovery more dynamic and less blood thirsty. # Explain why it's good for the game # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Adds a plasma breaching charge that detonates a plasma wave stunning those opposite it. add: Adds the name of the tracked item to the Yautja gear tracker. add: Added an alternate mode for the Plasma Pistol and moved the incendiary property to it. add: Added MINIMAP_FLAG_ALL to Yautja globe map. /:cl: --------- Co-authored-by: harryob Co-authored-by: Morrow --- code/__DEFINES/equipment.dm | 1 - code/game/objects/items/explosives/plastic.dm | 86 +++++++++++++----- code/modules/cm_preds/yaut_bracers.dm | 17 ++-- code/modules/cm_preds/yaut_items.dm | 5 +- code/modules/cm_preds/yaut_machines.dm | 2 +- code/modules/cm_preds/yaut_shield.dm | 6 +- code/modules/cm_preds/yaut_weapons.dm | 41 ++++++++- code/modules/projectiles/ammo_datums.dm | 17 +++- icons/obj/items/assemblies.dmi | Bin 16447 -> 16824 bytes 9 files changed, 131 insertions(+), 44 deletions(-) diff --git a/code/__DEFINES/equipment.dm b/code/__DEFINES/equipment.dm index 4212f6a52301..461eae27a2a3 100644 --- a/code/__DEFINES/equipment.dm +++ b/code/__DEFINES/equipment.dm @@ -82,7 +82,6 @@ #define NOTABLEMERGE (1<<13) /// Has heat source but isn't 'on fire' and thus can be stored #define IGNITING_ITEM (1<<14) - //========================================================================================== diff --git a/code/game/objects/items/explosives/plastic.dm b/code/game/objects/items/explosives/plastic.dm index 4c2a1774d4db..830df9659070 100644 --- a/code/game/objects/items/explosives/plastic.dm +++ b/code/game/objects/items/explosives/plastic.dm @@ -213,23 +213,6 @@ return TRUE -/obj/item/explosive/plastic/breaching_charge/can_place(mob/user, atom/target) - if(!is_type_in_list(target, breachable))//only items on the list are allowed - to_chat(user, SPAN_WARNING("You cannot plant \the [name] on \the [target]!")) - return FALSE - - if(SSinterior.in_interior(target))// vehicle checks again JUST IN CASE - to_chat(user, SPAN_WARNING("It's too cramped in here to deploy \the [src].")) - return FALSE - - if(istype(target, /obj/structure/window))//no breaching charges on the briefing windows / brig / CIC e.e - var/obj/structure/window/W = target - if(W.not_damageable) - to_chat(user, SPAN_WARNING("[W] is much too tough for you to do anything to it with [src].")) //On purpose to mimic wall message - return FALSE - - return TRUE - /obj/item/explosive/plastic/proc/calculate_pixel_offset(mob/user, atom/target) switch(get_dir(user, target)) if(NORTH) @@ -312,13 +295,6 @@ cell_explosion(target_turf, 120, 30, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, cause_data) qdel(src) -/obj/item/explosive/plastic/breaching_charge/handle_explosion(turf/target_turf, dir, cause_data) - var/explosion_target = get_step(target_turf, dir) - create_shrapnel(explosion_target, 40, dir, angle,/datum/ammo/bullet/shrapnel/metal, cause_data) - sleep(1)// prevents explosion from eating shrapnel - cell_explosion(target_turf, 60, 60, EXPLOSION_FALLOFF_SHAPE_EXPONENTIAL, dir, cause_data) - qdel(src) - /obj/item/explosive/plastic/proc/delayed_prime(turf/target_turf) prime(TRUE) @@ -342,3 +318,65 @@ min_timer = 3 penetration = 0.60 deploying_time = 10 + var/shrapnel_volume = 40 + +/obj/item/explosive/plastic/breaching_charge/can_place(mob/user, atom/target) + if(!is_type_in_list(target, breachable))//only items on the list are allowed + to_chat(user, SPAN_WARNING("You cannot plant [name] on [target]!")) + return FALSE + + if(SSinterior.in_interior(target))// vehicle checks again JUST IN CASE + to_chat(user, SPAN_WARNING("It's too cramped in here to deploy [src].")) + return FALSE + + if(istype(target, /obj/structure/window))//no breaching charges on the briefing windows / brig / CIC e.e + var/obj/structure/window/window = target + if(window.not_damageable) + to_chat(user, SPAN_WARNING("[window] is much too tough for you to do anything to it with [src].")) //On purpose to mimic wall message + return FALSE + + if(istype(target, /turf/closed/wall)) + var/turf/closed/wall/targeted_wall = target + if(targeted_wall.hull) + to_chat(user, SPAN_WARNING("You are unable to stick [src] to [targeted_wall]!")) + return FALSE + + return TRUE + +/obj/item/explosive/plastic/breaching_charge/handle_explosion(turf/target_turf, dir, cause_data) + var/explosion_target = get_step(target_turf, dir) + create_shrapnel(explosion_target, shrapnel_volume, dir, angle,/datum/ammo/bullet/shrapnel/metal, cause_data) + addtimer(CALLBACK(src, PROC_REF(trigger_explosion), target_turf, dir, cause_data), 1) + +/obj/item/explosive/plastic/breaching_charge/proc/trigger_explosion(turf/target_turf, dir, cause_data) + cell_explosion(target_turf, 60, 60, EXPLOSION_FALLOFF_SHAPE_EXPONENTIAL, dir, cause_data) + qdel(src) + +/obj/item/explosive/plastic/breaching_charge/plasma + name = "plasma charge" + desc = "An alien explosive device. Who knows what it might do." + icon_state = "plasma-charge" + overlay_image = "plasma-active" + w_class = SIZE_SMALL + angle = 55 + timer = 5 + min_timer = 5 + penetration = 0.60 + deploying_time = 10 + flags_item = NOBLUDGEON|ITEM_PREDATOR + shrapnel_volume = 10 + +/obj/item/explosive/plastic/breaching_charge/plasma/can_place(mob/user, atom/target) + if(!HAS_TRAIT(user, TRAIT_YAUTJA_TECH)) + to_chat(user, SPAN_WARNING("You don't quite understand how the device works...")) + return FALSE + . = ..() + +/obj/item/explosive/plastic/breaching_charge/plasma/handle_explosion(turf/target_turf, dir, cause_data) + var/explosion_target = get_step(target_turf, dir) + create_shrapnel(explosion_target, shrapnel_volume, dir, angle,/datum/ammo/bullet/shrapnel/plasma, cause_data) + addtimer(CALLBACK(src, PROC_REF(trigger_explosion), target_turf, dir, cause_data), 1) + +/obj/item/explosive/plastic/breaching_charge/plasma/trigger_explosion(turf/target_turf, dir, cause_data) + cell_explosion(target_turf, 90, 90, EXPLOSION_FALLOFF_SHAPE_EXPONENTIAL, dir, cause_data) + qdel(src) diff --git a/code/modules/cm_preds/yaut_bracers.dm b/code/modules/cm_preds/yaut_bracers.dm index 05e4a8205c94..b526e11d99bb 100644 --- a/code/modules/cm_preds/yaut_bracers.dm +++ b/code/modules/cm_preds/yaut_bracers.dm @@ -408,15 +408,17 @@ var/gear_on_almayer = 0 var/gear_low_orbit = 0 var/closest = 10000 + /// The item itself, to be referenced so Yautja know what to look for. + var/obj/closest_item var/direction = -1 var/atom/areaLoc = null - for(var/obj/item/I as anything in GLOB.loose_yautja_gear) - var/atom/loc = get_true_location(I) - if(I.anchored) + for(var/obj/item/tracked_item as anything in GLOB.loose_yautja_gear) + var/atom/loc = get_true_location(tracked_item) + if(tracked_item.anchored) continue - if(is_honorable_carrier(recursive_holder_check(I))) + if(is_honorable_carrier(recursive_holder_check(tracked_item))) continue - if(istype(get_area(I), /area/yautja)) + if(istype(get_area(tracked_item), /area/yautja)) continue if(is_reserved_level(loc.z)) gear_low_orbit++ @@ -428,6 +430,7 @@ var/dist = get_dist(M,loc) if(dist < closest) closest = dist + closest_item = tracked_item direction = get_dir(M,loc) areaLoc = loc for(var/mob/living/carbon/human/Y as anything in GLOB.yautja_mob_list) @@ -459,9 +462,9 @@ output = TRUE var/areaName = get_area_name(areaLoc) if(closest == 0) - to_chat(M, SPAN_NOTICE("You are directly on top of the closest signature.")) + to_chat(M, SPAN_NOTICE("You are directly on top of the[closest_item ? " [closest_item.name]'s" : ""] signature.")) else - to_chat(M, SPAN_NOTICE("The closest signature is [closest > 10 ? "approximately [round(closest, 10)]" : "[closest]"] paces [dir2text(direction)] in [areaName].")) + to_chat(M, SPAN_NOTICE("The closest signature[closest_item ? ", a [closest_item.name]" : ""], is [closest > 10 ? "approximately [round(closest, 10)]" : "[closest]"] paces [dir2text(direction)] in [areaName].")) if(!output) to_chat(M, SPAN_NOTICE("There are no signatures that require your attention.")) return TRUE diff --git a/code/modules/cm_preds/yaut_items.dm b/code/modules/cm_preds/yaut_items.dm index 8a3306817078..47b2408c4f37 100644 --- a/code/modules/cm_preds/yaut_items.dm +++ b/code/modules/cm_preds/yaut_items.dm @@ -327,6 +327,7 @@ unacidable = TRUE ignore_z = TRUE black_market_value = 100 + flags_item = ITEM_PREDATOR /obj/item/device/radio/headset/yautja/talk_into(mob/living/M as mob, message, channel, verb = "commands", datum/language/speaking) if(!isyautja(M)) //Nope. @@ -338,9 +339,6 @@ to_chat(hellhound, "\[Radio\]: [M.real_name] [verb], '[message]'.") ..() -/obj/item/device/radio/headset/yautja/attackby() - return - /obj/item/device/radio/headset/yautja/elder //primarily for use in another MR name = "\improper Elder Communicator" volume_settings = list(RADIO_VOLUME_QUIET_STR, RADIO_VOLUME_RAISED_STR, RADIO_VOLUME_IMPORTANT_STR, RADIO_VOLUME_CRITICAL_STR) @@ -697,6 +695,7 @@ var/tether_range = 5 var/mob/trapped_mob layer = LOWER_ITEM_LAYER + flags_item = ITEM_PREDATOR /obj/item/hunting_trap/Destroy() cleanup_tether() diff --git a/code/modules/cm_preds/yaut_machines.dm b/code/modules/cm_preds/yaut_machines.dm index adba69043dcc..a1782ca22b85 100644 --- a/code/modules/cm_preds/yaut_machines.dm +++ b/code/modules/cm_preds/yaut_machines.dm @@ -5,7 +5,7 @@ icon_state = "globe" breakable = FALSE - minimap_type = MINIMAP_FLAG_XENO|MINIMAP_FLAG_USCM + minimap_type = MINIMAP_FLAG_ALL /obj/structure/machinery/autolathe/yautja name = "yautja autolathe" diff --git a/code/modules/cm_preds/yaut_shield.dm b/code/modules/cm_preds/yaut_shield.dm index 2e036b4a5357..7b84f935f4c5 100644 --- a/code/modules/cm_preds/yaut_shield.dm +++ b/code/modules/cm_preds/yaut_shield.dm @@ -45,10 +45,10 @@ M.apply_effect(3, DAZE) M.apply_effect(5, SLOW) -/obj/item/weapon/shield/riot/yautja/attackby(obj/item/I, mob/user) +/obj/item/weapon/shield/riot/yautja/attackby(obj/item/attacking_item, mob/user) if(cooldown < world.time - 25) - if(istype(I, /obj/item/weapon) && (I.flags_item & ITEM_PREDATOR)) - user.visible_message(SPAN_WARNING("[user] bashes \the [src] with \the [I]!")) + if(istype(attacking_item, /obj/item/weapon) && (attacking_item.flags_item & ITEM_PREDATOR)) + user.visible_message(SPAN_WARNING("[user] bashes [src] with [attacking_item]!")) playsound(user.loc, 'sound/effects/shieldbash.ogg', 25, 1) cooldown = world.time else diff --git a/code/modules/cm_preds/yaut_weapons.dm b/code/modules/cm_preds/yaut_weapons.dm index 40006dafe60b..986b30c27ddf 100644 --- a/code/modules/cm_preds/yaut_weapons.dm +++ b/code/modules/cm_preds/yaut_weapons.dm @@ -891,7 +891,7 @@ /obj/item/weapon/gun/energy/yautja/plasmarifle/load_into_chamber() if(charge_time >= 80) ammo = GLOB.ammo_list[/datum/ammo/energy/yautja/rifle/blast] - charge_time = 0 + charge_time -= 80 else ammo = GLOB.ammo_list[/datum/ammo/energy/yautja/rifle/bolt] charge_time -= 10 @@ -912,6 +912,8 @@ if(refund) charge_time *= 2 return TRUE +#define FIRE_MODE_STANDARD "Standard" +#define FIRE_MODE_INCENDIARY "Incendiary" /obj/item/weapon/gun/energy/yautja/plasmapistol name = "plasma pistol" desc = "A plasma pistol capable of rapid fire. It has an integrated battery. Can be used to set fires, either to braziers or on people." @@ -924,7 +926,12 @@ ammo = /datum/ammo/energy/yautja/pistol muzzle_flash = null // TO DO, add a decent one. w_class = SIZE_MEDIUM + /// Max amount of shots var/charge_time = 40 + /// Amount of charge_time drained per shot + var/shot_cost = 1 + /// standard (sc = 1) or incendiary (sc = 5) + var/mode = FIRE_MODE_STANDARD flags_gun_features = GUN_UNUSUAL_DESIGN flags_item = ITEM_PREDATOR|IGNITING_ITEM|TWOHANDED @@ -965,9 +972,14 @@ if(isyautja(user)) . = ..() . += SPAN_NOTICE("It currently has [charge_time]/40 charge.") + + if(mode == FIRE_MODE_INCENDIARY) + . += SPAN_RED("It is set to fire incendiary plasma bolts.") + else + . += SPAN_ORANGE("It is set to fire plasma bolts.") else . = list() - . += SPAN_NOTICE("This thing looks like an alien rifle of some kind. Strange.") + . += SPAN_NOTICE("This thing looks like an alien gun of some kind. Strange.") /obj/item/weapon/gun/energy/yautja/plasmapistol/able_to_fire(mob/user) @@ -983,7 +995,7 @@ var/obj/item/projectile/projectile = create_bullet(ammo, initial(name)) projectile.SetLuminosity(1) in_chamber = projectile - charge_time-- + charge_time -= shot_cost return in_chamber /obj/item/weapon/gun/energy/yautja/plasmapistol/has_ammunition() @@ -995,9 +1007,30 @@ /obj/item/weapon/gun/energy/yautja/plasmapistol/delete_bullet(obj/item/projectile/projectile_to_fire, refund = 0) qdel(projectile_to_fire) - if(refund) charge_time *= 2 + if(refund) + charge_time += shot_cost + log_debug("Plasma Pistol refunded shot.") return TRUE +/obj/item/weapon/gun/energy/yautja/plasmapistol/use_unique_action() + switch(mode) + if(FIRE_MODE_STANDARD) + mode = FIRE_MODE_INCENDIARY + shot_cost = 5 + fire_delay = FIRE_DELAY_TIER_5 + to_chat(usr, SPAN_NOTICE("[src] will now fire incendiary plasma bolts.")) + ammo = GLOB.ammo_list[/datum/ammo/energy/yautja/pistol/incendiary] + + if(FIRE_MODE_INCENDIARY) + mode = FIRE_MODE_STANDARD + shot_cost = 1 + fire_delay = FIRE_DELAY_TIER_7 + to_chat(usr, SPAN_NOTICE("[src] will now fire plasma bolts.")) + ammo = GLOB.ammo_list[/datum/ammo/energy/yautja/pistol] + +#undef FIRE_MODE_STANDARD +#undef FIRE_MODE_INCENDIARY + /obj/item/weapon/gun/energy/yautja/plasma_caster name = "plasma caster" desc = "A powerful, shoulder-mounted energy weapon." diff --git a/code/modules/projectiles/ammo_datums.dm b/code/modules/projectiles/ammo_datums.dm index 7114c924fe61..f97195d5ac32 100644 --- a/code/modules/projectiles/ammo_datums.dm +++ b/code/modules/projectiles/ammo_datums.dm @@ -2217,12 +2217,27 @@ damage = 40 shell_speed = AMMO_SPEED_TIER_2 -/datum/ammo/energy/yautja/pistol/set_bullet_traits() +/datum/ammo/energy/yautja/pistol/incendiary + damage = 10 + +/datum/ammo/energy/yautja/pistol/incendiary/set_bullet_traits() . = ..() LAZYADD(traits_to_give, list( BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_incendiary) )) +/datum/ammo/bullet/shrapnel/plasma + name = "plasma wave" + shrapnel_chance = 0 + penetration = ARMOR_PENETRATION_TIER_10 + accuracy = HIT_ACCURACY_TIER_MAX + damage = 15 + icon_state = "shrapnel_plasma" + damage_type = BURN + +/datum/ammo/bullet/shrapnel/plasma/on_hit_mob(mob/hit_mob, obj/item/projectile/hit_projectile) + hit_mob.apply_effect(2, WEAKEN) + /datum/ammo/energy/yautja/caster name = "root caster bolt" icon_state = "ion" diff --git a/icons/obj/items/assemblies.dmi b/icons/obj/items/assemblies.dmi index 668d62d23d4e04f3fab19954c31a4739f779889b..522e0fb5e55d8d1c9a62dcd3c4e30f7e6d4d0674 100644 GIT binary patch literal 16824 zcmb`v2UHYI*Dg9p&L~I@A`+COMrfj}VA7b=R{AQ0Ar z+k*fP1Oib7mj?nTfj+Md+!Wutn!8v#xmi0pfIwbp>E8w%emKQCF z-WL(-6nPw)x*3EWdLgHs_|$2 zXzSkn(faWvg)cD5RQ_?EWUm%yT%r5BKmMHW@6CXsjLWFBwM5c#EQT$}-8N9@&79ZR z(kEgcLY+Adv&1uuKAEcpli#^>!bL>%hB&3ypH5|uJy5+g;c$Ji{VU~5(Bc|S>$63T zo|Yr5PJsZG&B&#<$W4>gbTvZznBLlDp)aAUtuX*-{2A2_?8hC9G`R{zelLbj zm=e(cL+ z&5Z17RQ}?lbSx=~t?|Ek$IkCaOUV(9^Y&**-01XpevJ8Ct#j*f4~kIS{yud1lsKZm zmp4mNoSKKzhLHW4A2q*eY3t2l3-Wpzchnje7dCY^U(qh3V#@q2VbblpzMh_fzrU7h z8^Zmfx7v2PhfL0ME1Bj|+4(v0beMa8y25fa2lICteV7^Keqa6tQKrgKn(txL?NMqp z*%5@><#pKfGLaur2=Y6h)CZc5Zs17^OtShWeoWj)am4BQ2zTVcLYONvC zzmvQ-sMn@$&4U~-tG&H^P-=vaDD;A7qJc_(CGBVOJ_Cxh16n2A! z(@V}8(`9+Q)=kvW0&geoXxh#gs5I*W6&4k(cGK8CO^wyvjNr_#aaxsUAC-Hpqti82 zW}J%w8>Qv32KXbZI`1(^-Ca2BoS2?At24?SpK8DK#C^~~RGVUcTJLR;j5)m>M7Zwzg2 z{X!A>?MGo@A`H1n9DrPB!9LoE*F4E(QRe`ITHqE+F9W+8^tVUy!_LSDQTr^0!+GIhPCIc5Z6}vJfnQZjm!2+p z7lbXNJs!?CBxyq+FW@e0*@+1+VQ$qt@`qzTeKr&H zb58ZjY*waWXa*4Y#?S@1d^P0hcHWyoM*12yFa2FME2y-TvAFn2jvN*1*c{gHzM<}I z+m~s`Ld%iq@+Jv{p!S|QwC=XNxWw$~w_O5tlaR!X+Lp)` z`*dKH_SEc=CfKBFp(*(BlVbZCY>nivi>qxBWVthX(`UQmO?ywy&n4lt=>_-KG}~eA z?Vo{{2kyXhb?+nm)JGjJ)BY~(oOt*eojp)fq*XLBxQpS3UikvP!%$czJ@cVyMnG|g z9F4#(tRdSzL@H*=E*!oVaV+0>4o)e(P+|;Myug4)^%CdP`z7H{wSDATU6h(?1?@7w zw+0g;#v)*`S8N7ldQYAVIJdl+Ik2|hQX*?s5o6Dxy!Jwe5<9LH6_`pKy0jf&UW9?$ zK@v+9CW~zvTpC0~0rmzBhtouP+Io7FHC;s{fIGB*uJw56FJpuxAy?%03$CBe0i2(W zpL~!Ubj&#n1tJNp$H817V+DqDY%aq7{E>jy!vHPghv`>rwU?Z0(-jto77Vw6XMhdd zB6$f-L~RBP@qS(XqQL`6IAf3Nu>Ax6VLE%P!SBxWfgfNUiij?jfI?7+e8F3RBBqS0 zif-^zR2-S1){T}{8!#+KWt zwLB|MM+@0;Dy>FytZc0g=6;Ht*4iAng-zjqN8IFt>xH$9TO=h+O2*SJq|PUFUSTq% zTju|a@8xs>^>x7NHg#GGPJPutdk-V_xjTx6yYIT^e#ph&xw=R@@ioI)IZQ8r@IkgFjt3dgS|X;@`z-kZH*d;OV-+28)gO%l{U zzdx(rn4WTS4@9D`iJR5j8iEUM%AApjR1~zG;(0$+YM4?6fnReDuv|W#+0Lxc^^;+_ zxnTP6=Q|1L;y_YOIjp&Ow#ISv%=kI-`Z~U|8ZcOJvB~KyRn%kKQPaa&I3bXprX66CAeo-+qMa; z3SrM|zDYbfEPQ32Q!y;Q%{T-cdgaK}56eVr)6M?YvUIMQ2rj4oGQ4g6n?lU3Fu$u+ zA>8KZ%I~<8&*4`^8QA54Qv0ZF0b>N zzLLev7&kq8(Eg(awh#<$lz8cIm678WStc2G;HI!gP#slb=pGZn6t6Aj8zlj2Ifv*| zJoIvAvt%rTdN#nA(T#VkmfO2ZO;LA20ERfaK4`s|lLSpnPCoO!;5{zYL;81sflkmEKH$(i>)N`mQskP-HO=p_!r0(&asTGIAP(MYMP z06RVO_1<%1v9r;{jN&E-G;jZY1*)v;qt7DJ_}jibmMN&!6kfHP-9flKK6_SP=ss^% zH!Jq8F3!-9+zp0KO!pO^xR+OSMev2DqFD!{kP2Q?+MWryStrU$7Ub`CXwWhA4ou(% zX8}wCbh5?x?&9yj?;+;SDSOFv!}o7$FOw2A@ZWCy_H;kSG?kJBww#`v6=4*Lp&M)w z$I#>MZN+w6??A|)ufv6Or|eT<*BXECE5sZFH}{ho?tX5U_Dm6Tv%fb>c1EYKH5@dQ zJTyGsA71}SvMs>b#>4KMxMViKl>B63@Ul2|^#dN~oWOpOT3@55v75*go#rM|yPx{0 zm9szpq_H*b%kC4g)}{QAGH&_57c9M@7BS+os!I>5OEgz&j`0a3ZMmvg*0#G9<|Z&u zVzSlxIVWTCBh-BlJrnbvluutZThkufVJNS%zv7a1rzN|8GD+PxbA1-8*7OY*XqG>Q z4hwn=neF9aucgq9&@dJO3tB#X2~d1}Aru6BQ3xZE?3AQbC6DNOyV=Md#W1I;D$M#AMHWYFXipsZ=COV=V9V zmJ2Hi+AAC#0v#%}EHvou*iexl+WJ7-SM-#++GPlBU^{V`DZzaIbzTg_=k9Xwd9wsu{hS#LwnEt5A^AAr(pr?Du4#bM-NFf;5UM#*H=A&y&zY6@YUyPn&o$@s^dnCRfFm2Q9P& zxG$6qQ(id+T($7D9e3|k&vs9~sYejW7@RT7#v+~T0;eh)kBK6k z-0?a^RW>?Qu38)mwnM8kCi_UuA^11;Cc632;hdH8H2DSz*J(s*?fxUdG_` zIFmOqCx&zbiM$F|YSQPWjFPQ`wM+GW4_j~T2J9#^=grm%r1{Jk5vKX##WQ#JIw1CG zYipN=jnvz>I&G-9U1fx5-W)*T*OMSSh-HV-dS^pLiYi|_&W|b2QgodRUlZb<-%WAV zl-EqV#^hp4fbg*crW{$dda5>~usO3jdW3~IN~mr`0fzB4BN%%!MCe-q*c zU`*$%>HzG~bDvZGMvtO{I0|~#esZFo`IU{R{nocFRM`8jir0>GD+bT)HI2Ykzv@H6 z$XSM>ZR$wa*}L<8ysz}%=LD&VU9MRXV9|z?7c@6Z93Dlmd)y4STPS9cdBE~_89-LXT<5;pQt$_;UV-zVf8cV9|h7c84j5B>)GzK$^=Ia^>;T@nlshb zg0yBDGyU~dxmar#z5eWO8$U&@=9@$LeAajml?hPRO|OplC`5u6vAYZ zj|%lH(JK?6I-CJfn8;M0p68!a5@zqf4O9Dbv+ptRaT=A2Dk|)pz@Paw`p_F_YyVm4 zOpX>mR|DaZ59Jl@I=KZnb`=a9Krce60sT9Np-s?0=oydmmKO_rkXD<3$C$b=_3m5tjn$f~@&4sQm$oA>+`LArCAq<&j;y z%fNhG`A~mxb?Y1C(!O82qpMICJ$_Zl%Fx_w+4aR%v~1$*Qm)|^bHiNcJcVZGn9;f%nYRIA?x^Ttz!1& zg=QG!j*1v-+?JQc^Jr9&NaDpQz7b+4bZH)93&Z&`!rR=OS;%?mOSt$Peo&DB+$vtm6W2y##X{qJ4Adx_n5O{6J({_R~&ktPAElRV&os4S5@ zI1f@E=+Jts%+AgpYFpkEcD&x}I>6h&Wdc*B2x(V_kz^5Y#7AsxeQ1kfC6FiIoyN-J zBI1aD0e?pjG@{_cD0|zIbKo>7!;mgBS$nJ(AVPV}kLT$lx7X>JkB`n4<2A)r+NNk@ zP|aAPZ>_yP3|&S>MRS`MsEc)Z8TXSXwPooihqS*)<$PEVEq!-Dwfv@Jkh-!$w3Vqv zt&5Gh+|QVa^zG2R5^|xbVKA50AD|-G0kD5i(sKWR&~SXhz|3p7n;tgDR zdI?{T-_P^eh*{%uhSRe2rCZYT3c--F>nX7Ix=g+$)2Q-C~ z7Ym&6WsKm9A3iqds37a!A99*zAnCE%@3L|2RN&*g;XjwfToqtm7j$QFnFTMy8*q_W zwmHPD4S6_$N~(z)Yo5?MBzk2Ks z<5-iQ{Bo{3=Sz#X*SFvg|9B1~!V4+_7{p}z(vin4gJ3Z^w%kndw!~UF_c``y1HBQ1 z^DqO~e)#zv#9W+*HL$^bZ_7PdsLCF|+SB~C(BztMQ2>cbH2^)=A zinp4&PsLRQHEO;lHp7+8cDKSVQ(%xKj6bM+%jd?J?s;;u8qV^BLBvkXy5Z;X9t&yK z%*S0UV32hGXC&`}U(Qnn%M+XBFZi*VI#L3k?FBz(-jG)$L_l!gx&?cH{#@ObiH@cs zY-8Z!<&>1XzOK$)HNQGh1@S-v`qt(h)~ml$M4Fg#6HS!~mS%{>O;U1dS30Dh+5gIs zRgJnHvlAMT7%Fk}4h(`!J;5c{GKUIq*%#%A%j}J0Up5E(86kS%`d}sig5{W=39MY66`xbC zb~8x^nioKlcnyF4n6E#s8vPCYQR?Cp09Uu_E%==d_793KmrhJgX&W0epkVo90l{&> z?nJ&9;ki0$ksqCGOZa{~_NsjO7@-vNj#->eo|j7MNL^c|zAx!#bBCqjR?XV#H_E$O3O9x$|42Gl(5`KWCGWFm_xhY$|fA73MsBd1^ zMC-bjjO-1e`b^?n-E;w(6*qrtS$rLKEcb-_;u*UuPB5A9(dxwqpo5e;;H#lO908o^ zR)}(dJMUW_E;PN=@DRD5kf0{D&!b#s{CvlXc&FWd-s^9gt5vet-SMyN->9gLHuWKQ z4NXfRU3#Sk+24|q;!{(JWjD^##9cM^5=U01EA&Zd2}18jE7P(tcWSI-so{lg$qHuR z_T9Kwuh0k+1$v+1j;y^Ow8uvrVgyIu-4%J}wp;e1Zh6Ivt24LfkSul+T3 zz$VJ_;a1vlEj29mnb#+{%;e7jQAQ4TgvwJZeIRF<=C;%n3!iw+T~=21Mxrh-@ zEq6-CL%M!VPD~Iu;B>i{daeqGM}ze56X_z1a|L!JDXSHWB7@i2tGajGhZtN&>BT!a z1#gT(hLa%v3BM=LzfYU`s>2_GMzrWhS_pdCEfv*3bn3K1QU?)Fi?_^_^FMFYoZ(xQ zU*i#&)5U%MIm*eAM~2m(rJD-bq*Cg%6FG%LF{#3~Q(8twFQ3v{tmXBkAm*A9Rdo^nvaz9jy>sP#8;E2l+OV(zpd#Nw-je2Zc#sq92 z^%a}k*d*#rMB{Qvi{e-5iS`;+!i~+%^9Xceb+tf$fBzYua#F}oqL)U2#bbJS?49~R zqiF2Bc)34`4eD5M`84Gu7!vC=S)BJXeY9Kl){PzDng=bbEkubH zIGTETdLMLkb<6rJe%gubyNLQh2v`Cw+&y{~*5jTUfYz&Q1D~|=lFYq-Kf*M({K-h* zZxSGksk7H6+T%TVzwzj2FkW!g$ElNp(i@a@NwSX}NY`9nJv^?h_q;Hz;od7vs^(=X7T=4hN= zbLZPn8k*GmXt5Vb`~^VkFXL$O#PvUpeB-y!J5$-ylKI!I&arrGK4|^(CJnnPGvW6j ze372Nw8AO)n!foO>2upg1$~b)t}jzTk+lJ`{uG9)s>In^DoFtkvR$UQ@IQY`R4kGM)KM2^Q7-Sj02=lxgE}5%m|PS^ivuS4d}k^ zo|b|UUL17*VOD%#dZ^N9zDwdIpTH2@cQ~HA1GZ*x5>VtkgG1d& z(de2z5btTY=zT6w{K+H+s)MCKvseKGBZgU zu8}Xo7a2)|6hppDp#x4;^s;aKPE9|qX@IGv?rQXX+*7v{I9nrSL~h6{$rr+PTq{3M zOuPnFhXv0kgcV=~VS!gGB{qD+=H*nQBvjs;#Yv!zp3?rMLFb`}^o+H#zR^(aOxZf} zKi2vgdVLk&y{c}50NFj(#tbqnT`U(DW53{^h6h|qZhFFQ(jDeu;G43?W?`23+PaG> zX0O=A4f+0xP|`Wz17D1c?!49&1%CK6Z*At5A({PtdaS}5qzmxCNnG51#rOz{O3_)? z+7{Utv&LC!GT6vY^8)t1mDGmzTt#$!yM%(_O`q><%Jq`YzDNs5#IEYqa$%U3;d#{& z)^8~>{egG2tS&3>Ei7(l19Oz3zFuFEQ$gcl_ibO&+P?h$Gv{S-F@y8W;OKN5_A;E@ zv#nZYW11(hI2LcX;m?Pji{ef}_lJJ_JO=YeGBlak!r^9@ zl5^LdD3oOX#k3_C)D%j8d&FzhI34^5{>^oz6Pjr1*-S4p9^j1Y7$Ea)(RYF(^2nR@ zHFMBh_COsE-pEBq6bbW}_;~Cu-zaE51wbnA=ZgPOrvRMCG;lxBTXa|@f|t-(_UwsIay@R;bF z)O2k8pp6eIfFc|Yst&sIK5bTwg5b`&I!C>z=(;d{)sh=FFMnH(^{}T?3%$(U4>TRz zn4mq0?-nTo4g)Tw^rYJ8O>RLd+)z3lZN!zZh><*zt%&I9SQ*6SG>UT4d93c0=UWT| z`y0WwCq_w%Cn6B4?{s;hgoywYt`_cbHm1YxzQX$3lvo;$(fdPe_PfWAnOwz0z^hlAF_ zf=kiCf$wp|w;m@iosTY?xO@9+0*E8xI?Q^xc;zVrZ9HjHQUl9<7T2U4=?L? zPwOXOLz(1JaJ4I(ks+9;H_`B<;(=b-6LKkJKbI_NW~TIq^;Tz_5-t%x**0nw;yD(- zyI=3$!Jb{-&?WZ@?@~5uVG@%b)X<5K?cspLPFEy>v$4*WbCsPhm1tgl5UPeXB`XXL zhLGTWW@LIPe!Al_mzMpr4N9lfIb5KvjSGj8LHw~hKZuPjcr>MSMR;;Yjv=9Nat^k^ zj%f&V(Ja8;o|l6%?W7HAGj`H=wUwISB=!d_`ZC8~_7W}E=D>DO=KZ8iL9Jd{W(5qL z0!(Te85tE87G~whkMmW;_rTTk$*(yoSm2`%KK-cbdpiIQ7#dd z{Q$3Gy$0$QFE0LFRrM8BU2pD`U4Bzt!iOxEYatDjf<-xi0QKwKxBx2xuA*K(xVP}} zU|dL?;1<9UXQ3qtiF%D^JjB7{(X=FAQtrV0M*pbtx8?1Agt_f%cZtI9b4kMLPqsMf z%C2Tm0g0u0+nj8EvWw_!ErOa^#zpj99%^D>Jl(EDNC`k=_dzi^m}gSW2szvd{#V#G z5Ve#+wJecO1G`y!vTP!$cT)#{AFg4KUb5%N7~N3%aQ7?$LBOvj`QBSqTW-*He%@1@ znc30|{Fuq7eq@eMw19Ed{?g0mhr|KC;A-s~uhZo{Ot@(wO0ID;fo@dVag21X-baGX zMVf-q_KKa&kDAvgFPd3e!iVV2UITQa16xQMf!~ZVpeSUD`1pY>_jJLFzLl}i`p!KX zslF3VsX)+>XeuyHUf?Q+cG*eLD;w4Ot;{He)ex@?JXC4uDr(x(JpPgvd}P7l;;*{# z0Oza6QKlMNg(5FMU)j-nM8K=|%+^KF=B6aQjx6J%7B*)X#Mx8}8`0Ru##o$#ftFxT z?#vB^9EQ;V6Pg=wrT;I*sQ(GOl`HOW30Sq6eu5y^;LB)c>CbEr>;J*+w-$?ZpJZO$ z{=h;DOapQ0k*u7C|L$|a(t5SIt1I`5Kj1ji5AA@fW%({?ymQruAHc2*JbnPa_N3KQ z9#tcBF`YDe)pJ&B7si0Li9rP`3yAnt4%=bgt!r@@k)OVQ5S)E}^Yw7L1&x|re$O(Z zs>-YbV4z1TVN`cy_d9mRu(z(Xsf)^$;%Z_frVwuGs04rlc%(iy+b&pxs)_F~cWrM& z`erg0exbnarkB?W%X8>t_nV_@BRU2d6^+EGZFIfS^e`sN_fOy)ruNKJoJVu8Q$kxu z2kSRInS(xk1|9((GNkLRko+yItAYZ5<|qg5bQSwXA@)`5&zyaB^=nBq;gsi`AeMB0 z!ra5=s7YnYOAO*#rVdq+?4MkYmV2!&_~imjidv+n`IB<5C)pvlxH+zPPq}B)QU`AR z^Ig?iWopr-&@0`t$VClez5+H08LfvS^O(y7mdc}WLAO&Dx*{?Ui0-v+<_wzh^y8Ye z6Wkv;=kt9H-1aN0Y5eP!BLu^bO-E9UeklsQIe;Cv!UaxPD)zR3hC4>IpalK?9dbJq zgpPVUAkj|4HnZU|8SgEw1rsz23 z&x4%AnY{d2A)!fyO!O~D|t@ED=+ zvcc9fAxU+08TwSeMH7>SRzyF{?R?(^dVI+O(WMF z41k*feyv{7)AI|CGvvlV?9li%On*812;83JhEZ8&UfkzLqt`XvShS!eP$@U=Kze#q zh;gd3_(5Zu2lAtA>XkzQcGT>rzPAr-6@A{|e(KG19-mZ0SluV>8lLC|CeFK;!AMV@ z@8u;hi@(;Wp5-#*XUrzZtUD_jnphoH8mxmK@|#6|??{R2;?q~nPVh)-jpN8V;+KKr zmIdG4Ve|KOJH53c3YvvjZ>FpBm%B5lti0WHEaW9zgg8cqjTfv)RGNswmdeLc z^Vs!IRF8y(g?;+!67K`oZWo706J^Z=J*rt-yS*n7rhlu5k1%W`kNp1`mtL)FMgh?W zERK@)VSKJ=*N}X4HQD+5U+F}WB65ue({a>$U$*KUC=;xxkw_dE`9!mV=wZNd6lUYp zlRHp?vL%g-Y}&WaN%Ba@tFO=H72JC4QCv4ax_tw>#?Re^>7C|WgpNpaNZ8vUviQ)W z&tFnDqgwuA`&jpxM=pN&=^$uUWl&{M8q!5!M`m6#PaqOb7~Z*W+x@QUYy2kgGy7lU zYanvkqLWv(v{CpFgT8+v(ve(G82O#PGR*Cn+$Ak=#^HD4DK6ytzX(535_(!@uh?YI z%qH8E{(0zE82Y|;c)Vc)zc{*ST#U(zF5~ljLeEICKMt$)IT+P;pJH8e;{rZ4b2Rns zDd2CqlQBTzAixJs_0goHj=CSdsMb~xQEa38*TV=HZh!e?C_LW-_M=xayExh(1p|3i z_~M_)h0|R8-99ah;x*vTAa%4}>0>hxQPdMG+N4Zsf2O z{5y2;ezOBK3le}{l)=STah*95LOe|-2{GmkybI)$91wz%$;j@~gLI}f_yQ0FIBUEi z+DQJk_Qd2>iq)&6_`lbZC7$Pf2NeylxdhFvReyuAT2d%4pi6iPd80sLj3Q%<^&+QZ z<9~&OudM7&x=jK;s)bYG1#uTnek6!tk-DLhn|LMA+b)PnAo?1?l=5v5H+$qc+ z)oiSzOB(+?VBO0?P@4?*kf{6~^PL2*S~;&*H}K;I*mv>CNdi%rZ{*i47ND$uJ{nkc z1H{I$N%CI@@ToG|SiS%)ET@735YPo*J_zcVFj%-{q!wex%-Gprkxd9;jm*pKcLRLj zk{{D^+CK0b+De}UE>C?mPxENR4!D;=Ggv=9@^&z@%>2VKw7*PDOzf~v8|l6IXBeMd zas|F4{`%)%_ZXl}ae;|8dB-o7^2GmN=HC7@-DxArQj7uf{u3O|E_a+6?^Xc=d|SWw zQS)y7&DV=JU)$GMz{+OZGQke$SsKxrlX$8{B)Da2m?d%6?G$_(uY8EmX-2r8aIT%k zatFR6_xpc@ov}=00omo3ly{F*$U61R$51+&%c{!F5g%?|*VBk{EJC}y8T#nou}Yok zEg|#`$57;I#$AuaAJZy>|2U$n6_773I8ROiA8_|r`8Q!JPiaj5_5~yKcWPc`i+qn# zf86Exn{E7%RfU7kl}>Wt9wvs0LF##mS>^cef}7#3=;*S)GJbqC>88CGk!EUrOa1+W zxx%N*PD{$ISYqtGf4-99s)5h_mll1+8%#{Qs)wtSp@;ZLv%yD$NT6=Py~Ob+I*6;2 z*#&PjgH)R}Gsf5UKFlPs7pjht^yF!hN77%_A&~!v(Xy5w(HrajOr|1kPL?cVi}7ce zP|%lY*;UAd=X7mn8B`OBgwGmDe*{?J zrV2Yi2wA8zl>nAUtPEE##B4WY4i0~?GaH;vs%ii0QkfxFDgMW}rCq&JoTPox%fC$O zrth^&^_xEuw&wDvVHv;2!wVP8nvN;G456nFP<}u)G7t#*$>m1Eii(6x{!De?(USac z*w6tdSN}VqJI?1Ng|~sb<1R5eOqu2FyRjLfpq^JkHw@0n3{^kqpV9-}rkY>of2J89xaHU^vti4Fc?c_5h_9%=E%mj_$!KqI&q_-=^&1WRmMHSG#xegvu!om)Oc~pZHi=eWBl1~Z{WqsZas2Sb zXzm{&yxr6wj?ArsLlqBs)OZiv^7%Pk>5|l)!Vu)+4U+31Qg+Mr%GADL#M+KjQJyFH7KF=C+Q#Bb0RQAh5@*>)wzN(9p4dYfgPpyhXM+|LjGGY6F({;6IyfWdDRlI z;z(MAj-xwgJd=o(;Ef&-eGYk!6n0nt&J=NupQ?+w%Dt$`wRse(lt3l$aF5?YaROFQ z%2Vai!Jvhz8CvR}%OQN8ZrP0(j=YA=EPi!@^_E=2TP>JWMNNt&qKH0UMG@top^nzn z(4f(i)7X892mi=exc{NDEocw}V241NwaV0C&y26clu-CDvS{lMppAU-G2d#!tPa60 zZkgA15D$Dzj9{QG`>Wl5VxU8o;6fU zr4ztjAU#3D|7X1Pxgz&T?>%q8E6GKFbHbHV@c4<6ELLWohQ7u0zQU;V>i>15&ve27 z_Vu2_XO8?PpmG<_{q($F{6qn^`Mkm4JIYX;4~x4Bb9)R@{mVM;z%fP9XeRvmvY14*Lw-RnZ3UT@67}N@pp3h%hc9@*5}0c zRL$dKYjewD0k-al(}sE;%?3~er|-p*2toUECS-E`b;z}9o8_0SN@t%B&iI&Qg-iFN zOmR1eJSw%gT`8rj=Y4_w;R-+PsS-Z4^E>~&JxHCegf$sML)xVrKBmqRHr)w5n1x4x zKU!T~0fh8_N%k8y7k^YBu%mZYD$ZLZ5w<7?b)@gUCVXYt-AN4}Qyy$CbX+m-X^M|& z_K%lDOdq6{MqoC1lRS_3=be@CG1W}^pCH&UYQRW`ZZEgvV4^@tleVM2|3yyl51T(i zIWI=fwLka|VI$@Bzd-ro7A50?{<}s|{V%eg4||S9W&FkBzXSKl|5E2k%u8pu1AG02Fl+jQi$ z-$nOeDN@m2VotqbF{yU@t0Ho}m+S9><;bApZI++_qy{fG;nB7gZF+|Fc7_Y@KXC^> zyr1cFZ7MLPE;L_I-DbcP-n3wnGi%2&X<@NzTfvErE3N8u&7;GUjPYy6*bV)j=|Ak+b{XAux2vG- z`S!Q0bU}(<RjsMAc5jy|t1C;#W0)$afQXJI5h# z6B+j>qdN0oa$Cy{!APYl(z*52xP%kPRB{=Me(l?CcCFO_SnAxl(?%!>_6Jg$enb^t z&$h5O!|%@VG=-TjfU@#uHIWfOzMs7607AYNvWSb{d^bU%DUSkFn3lni?sq_{bB|1+ zQapOlK?h|9NGm`(v|-UyIj;sZa^TT(D?7ViyKaEAIk(FaIKG=#RrRd=Jf+1bYwIl& zKi?&mLbCXKhGil39v%Ij4u^yAHB`C^2ytRjQys56SldkGUxUkL?k%yqey0>&WhU>Up?8HjtQxZr#7hNwP zIxbdN(?m0wYMSp8)Kg)<7T|-D6!Ee%It+E1iLSqVY^GX;8`xKHRV4W}T?;169xb@2 ztn1DOpbO;`8=+SI(SsBKR!o5o71jK4;l!p1Yi14vmI`KgZzXFa z>6U9hO}AMKt96V^jvLZZo%U?H72GQ6Qjle7U>h(Hv;h=N zedaRONw7d}MzAR-fL(#?d-$po5S{6e*|?*JBO8w0DfjTi_ClPmtVgHsLMJ~eztI5X zfVT*9g}hE;aO1^80YQn+GOdkg_SN<8pVc(ddeM+~RGOKT!;G=0b`fYhh=}!Ps?tJA zAVX|&-ZGF`^!NlM1K$T(!}2~Bbk3(wdZd1ttLXW^Kul|Xg#NtXs}~dpQkeiKD=~oM zi>6KnMM99+oh-iBLY6~}xLJh@#GCfhmR9$`%yvOjlb!DUq;KEcc6X*iKLMuR zq4-a;EWI}!=-A_b62Z976*J31?UE(YQNgC$&Zx4^y+Sbi8@Z7$=}yp)AtWHV?NvA) zea&#VRV(sX9)PDuSBKZCoKz35{_ybSKcZNf%xt$oyw%fdn3^u59{Kj_hh32vAOewU z29wA4$u>^jp?xJkI3em)WmNXpmNE84aH^!T7(?MP>Fxvz0ZyS~<=Z+V!neKOy!^in zApsFoy`4g@@=$5!Cky8k2w*)VcrPO$O6E|W}0@v2+HFsMB+U<=7F7!d5w66a?09a0v zW&bhJFzfC_GC~C@YhES){@m?o`g)NGSx2g@4s=htR$&=S$AMezF=sQSHgavcYZ)!^ zAkaDq@|(qU3Dm)2s#j1}IiKut75bN3oPg0+WF!ce_*;27_TK-UotB7Z&<{S&oBi{8 z8jmi0JO7`Vg1PS!TDi=KHl|urAkT!gqj8C;xvHkIHn+B1&e_dBw;<X_6J0 z^lfBZtXNdps4xN{2H*)j<13REUAIZ=^e~Gx)<++1Wgj1jZ4I%5#sSC0cFyKEAt88L zA-}^^)YW55Ps%pKZsD||0y>l?-j5J;Np_zV?=|@_i9bKn)RK0eThFb92hhz3ZnNnZ zTmQN_6YTPAE#ecWUslrphJ>aJ06PUv8L+MhSj`gjS%vt2+%@~3AXh~Nm@wK^=b{h_jV3wd_KRycXMI$zg_97 zyuh0^#Qf4iB-Ps9KIX?PO|eESLlz5w(_g^-8s$u;dzLWET^b5 z?g+5_?Asp_8ac>(wp>v5({eZbx^U?fW*nbuw&C8v;bFKNItdaGF_`~(dScSm$+us2 z0e$bb=rZw#x&pIm5*tBY1O4#H47_k@LT&@dsi=s^*VI&1YwKO-Bxi|qV4<6>9-f$Y z1MKP3T|H2@NJ~1Im>ccZP&z|8#ME>M-8Rn^YbX-8{LANRJ~nD1xur&6K?)<$Eyi_U zMa_1{ViEnbqhKD`$y<@xKVDIepH*J|*)qdBe-McrS9UYti`&_ZWun>jI=pz_Xm;3; zv;L4hGT!}$7(3MgU(2Gv=IAGRdE2Ky(dOou31)|lrhH8xKL11_TaeHQ{sIT|48`sr zrhzftd63sZrZJ_#orLl|%ti0b9FOP-@@L1RLyet<8X`aDFzd z>3X`S2@#fpXl1!s+UyND37&E&Lyi&pyNu`Jf8E@cm_tH! znnIJiyT9SwX}uozB$>t>`)pQ+P*uRMPFK#vRjy#U(`Qr)v2X1Qz`}`AHak z{8-nFS*VUriut|vgC9EdNoRhQ4HTxMi{LTNJOcwUgpmw?Si(3LN){f>2{9;X0vhnq z{NfU(v_^P0z-(nC7vysiT32e&$PnJu85!E*4V?Y`{uC>4ALG^LGF$xQp8xga5(f44 z9`K}P{>LwxSytc|tD`V*%2&+kDT_Mu;=2|qbacZ^!TjlUL9ZOb^Tug$AFXVF@*&|WW zq!NC*@%&lTx^clV(AHf1{FXhdU8Q}$NB&BDv$!^|z&>HN<`~0jxj>OJC8h&WWc0H^ zZx&T;Gg)ED_45(io8J8-jh*<^#tLjAL<-lFOM!zEATf*VZ^Q9Z2W>1!GYGYkvCpC} zfWWaW@f+rDR4||{@vg4*w!E!B(-+eKv$yvy-DSJNe>fk9l#-q9+mLJf&g5RXbM;*` zG?5i%f6Q@#J15y&S%GTX$aXB|0YBtm_3U~+vhVQM02mSmWe?z-?^&%ZJz zy`>IDz3p{+y?&9TQyHHcBK763#i}Ac1g8oAiOi!w4F?O039&CucSC+X)KsMUuXj13 bp{^Lhz^lTor@((?0KHJsP%M{!8}#1*TVd0g literal 16447 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 From c1a9ca7cbc5479bc3e4000aa5cf4875fca4c59fe Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 24 Jul 2023 20:08:33 +0100 Subject: [PATCH 017/112] Automatic changelog for PR #3455 [ci skip] --- html/changelogs/AutoChangeLog-pr-3455.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-3455.yml diff --git a/html/changelogs/AutoChangeLog-pr-3455.yml b/html/changelogs/AutoChangeLog-pr-3455.yml new file mode 100644 index 000000000000..c3189ad233bd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3455.yml @@ -0,0 +1,7 @@ +author: "realforest2001" +delete-after: True +changes: + - rscadd: "Adds a plasma breaching charge that detonates a plasma wave stunning those opposite it." + - rscadd: "Adds the name of the tracked item to the Yautja gear tracker." + - rscadd: "Added an alternate mode for the Plasma Pistol and moved the incendiary property to it." + - rscadd: "Added MINIMAP_FLAG_ALL to Yautja globe map." \ No newline at end of file From 4ef3b9ec88bebe3e3b77c59aa1353f35e2229d32 Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:05:17 +0100 Subject: [PATCH 018/112] Yautja Bracer Charging Rework (#3456) # About the pull request Changes how bracers recharge, requiring drain from APC in the field. Change made as atomisation from #3271 as part of an ongoing project to make Yautja a more balanced role for what it is. # Explain why it's good for the game Balances out power usage and makes things more dynamic. Will tie in with cloak not using power but being more vulnerable to the methods to force decloak. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Yautja bracers can now be recharged from APCs. remove: Yautja bracers no longer naturally recharge on the colony. /:cl: --------- Co-authored-by: harryob --- code/__DEFINES/misc.dm | 2 + code/modules/cm_preds/yaut_bracers.dm | 29 ++++++- code/modules/power/apc.dm | 120 ++++++++++++++++++-------- 3 files changed, 110 insertions(+), 41 deletions(-) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index bed2ceeced7d..4464a0b16a1d 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -284,6 +284,8 @@ #define COOLDOWN_COMM_CENTRAL 30 SECONDS #define COOLDOWN_COMM_DESTRUCT 5 MINUTES +///Cooldown for pred recharge +#define COOLDOWN_BRACER_CHARGE 3 MINUTES // magic value to use for indicating a proc slept #define PROC_RETURN_SLEEP -1 diff --git a/code/modules/cm_preds/yaut_bracers.dm b/code/modules/cm_preds/yaut_bracers.dm index b526e11d99bb..9642b4b9f5a5 100644 --- a/code/modules/cm_preds/yaut_bracers.dm +++ b/code/modules/cm_preds/yaut_bracers.dm @@ -31,6 +31,10 @@ var/notification_sound = TRUE // Whether the bracer pings when a message comes or not var/charge = 1500 var/charge_max = 1500 + /// The amount charged per process + var/charge_rate = 30 + /// Cooldown on draining power from APC + var/charge_cooldown = COOLDOWN_BRACER_CHARGE var/cloaked = 0 var/cloak_timer = 0 var/cloak_malfunction = 0 @@ -41,6 +45,7 @@ var/mob/living/carbon/human/owner //Pred spawned on, or thrall given to. var/obj/item/clothing/gloves/yautja/linked_bracer //Bracer linked to this one (thrall or mentor). + COOLDOWN_DECLARE(bracer_recharge) /obj/item/clothing/gloves/yautja/equipped(mob/user, slot) . = ..() @@ -75,11 +80,27 @@ if(!ishuman(loc)) STOP_PROCESSING(SSobj, src) return - var/mob/living/carbon/human/H = loc + var/mob/living/carbon/human/human_holder = loc - charge = min(charge + 30, charge_max) - var/perc_charge = (charge / charge_max * 100) - H.update_power_display(perc_charge) + if(charge < charge_max) + var/charge_increase = charge_rate + if(is_ground_level(human_holder.z)) + charge_increase = charge_rate / 6 + else if(is_mainship_level(human_holder.z)) + charge_increase = charge_rate / 3 + + charge = min(charge + charge_increase, charge_max) + var/perc_charge = (charge / charge_max * 100) + human_holder.update_power_display(perc_charge) + + //Non-Yautja have a chance to get stunned with each power drain + if(!cloaked) + return + if(human_holder.stat == DEAD) + decloak(human_holder, TRUE) + if(!HAS_TRAIT(human_holder, TRAIT_YAUTJA_TECH) && !human_holder.hunter_data.thralled && prob(15)) + decloak(human_holder) + shock_user(human_holder) /// handles decloaking only on HUNTER gloves /obj/item/clothing/gloves/yautja/proc/decloak() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 7247e9b87b16..e7a160095705 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -676,9 +676,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( var/turf/T = get_turf(src) var/obj/structure/cable/N = T.get_cable_node() if(prob(50) && electrocute_mob(usr, N, N)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(5, 1, src) + spark.start() return if(C.use(10)) user.visible_message(SPAN_NOTICE("[user] wires [src]'s frame."), @@ -700,9 +700,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( to_chat(user, SPAN_WARNING("\The [src] lacks a terminal to remove.")) return if (prob(50) && electrocute_mob(user, terminal.powernet, terminal)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(5, 1, src) + spark.start() return new /obj/item/stack/cable_coil(loc,10) user.visible_message(SPAN_NOTICE("[user] removes [src]'s wiring and terminal."), @@ -798,41 +798,87 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( //Human mob special interaction goes here. if(ishuman(user)) - var/mob/living/carbon/human/H = user + var/mob/living/carbon/human/grabber = user - if(H.species.flags & IS_SYNTHETIC && H.a_intent == INTENT_GRAB) - if(H.action_busy) - return - - if(!do_after(H, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC)) - return + if(grabber.a_intent == INTENT_GRAB) - playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + //Synthpack recharge + if((grabber.species.flags & IS_SYNTHETIC) && istype(grabber.back, /obj/item/storage/backpack/marine/smartpack)) + var/obj/item/storage/backpack/marine/smartpack/s_pack = grabber.back + if(grabber.action_busy) + return - if(stat & BROKEN) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(3, 1, src) - s.start() - to_chat(H, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) - H.apply_damage(10,0, BURN) - else if(cell && cell.charge > 0) - if(!istype(H.back, /obj/item/storage/backpack/marine/smartpack)) + if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC)) return - var/obj/item/storage/backpack/marine/smartpack/S = H.back - if(S.battery_charge < SMARTPACK_MAX_POWER_STORED) - var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - S.battery_charge) - if(!(cell.use(charge_to_use))) + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + + if(stat & BROKEN) + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(3, 1, src) + spark.start() + to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) + grabber.apply_damage(10,0, BURN) + else if(cell && cell.charge > 0) + if(!istype(s_pack)) return - S.battery_charge += charge_to_use - to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [S.name] now has [S.battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) - charging = APC_CHARGING + + if(s_pack.battery_charge < SMARTPACK_MAX_POWER_STORED) + var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - s_pack.battery_charge) + if(!(cell.use(charge_to_use))) + return + s_pack.battery_charge += charge_to_use + to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [s_pack.name] now has [s_pack.battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) + charging = APC_CHARGING + else + to_chat(user, SPAN_WARNING("[s_pack.name] is already fully charged.")) else - to_chat(user, SPAN_WARNING("[S.name] is already fully charged.")) - else - to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) - return - else if(H.species.can_shred(H)) + to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) + return + + // Yautja Bracer Recharge + var/obj/item/clothing/gloves/yautja/bracer = grabber.gloves + if(istype(bracer)) + if(grabber.action_busy) + return FALSE + if(!COOLDOWN_FINISHED(bracer, bracer_recharge)) + to_chat(user, SPAN_WARNING("It is too soon for [bracer.name] to siphon power again. Wait [COOLDOWN_SECONDSLEFT(bracer, bracer_recharge)] seconds.")) + return FALSE + to_chat(user, SPAN_NOTICE("You rest your bracer against the APC interface and begin to siphon off some of the stored energy.")) + if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_HOSTILE)) + return FALSE + + if(stat & BROKEN) + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(3, 1, src) + spark.start() + to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, super-heating your bracer!")) + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + grabber.apply_damage(10,0, BURN) + return FALSE + if(!cell || cell.charge <= 0) + to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) + return FALSE + + if(bracer.charge_max <= bracer.charge) + to_chat(user, SPAN_WARNING("[bracer.name] is already fully charged.")) + return FALSE + + var/charge_to_use = min(cell.charge, bracer.charge_max - bracer.charge) + if(!(cell.use(charge_to_use))) + return FALSE + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + bracer.charge += charge_to_use + COOLDOWN_START(bracer, bracer_recharge, bracer.charge_cooldown) + to_chat(grabber, SPAN_YAUTJABOLD("[icon2html(bracer)] \The [bracer] beep: Power siphon complete. Charge at [bracer.charge]/[bracer.charge_max].")) + if(bracer.notification_sound) + playsound(bracer.loc, 'sound/items/pred_bracer.ogg', 75, 1) + charging = APC_CHARGING + set_broken() // Breaks the APC + + return TRUE + + else if(grabber.species.can_shred(grabber)) var/allcut = TRUE for(var/wire = 1; wire < length(get_wire_descriptions()); wire++) if(!isWireCut(wire)) @@ -1011,9 +1057,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( smoke.set_up(1, 0, loc) smoke.attach(src) smoke.start() - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(1, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(1, 1, src) + spark.start() visible_message(SPAN_WARNING("[src] suddenly lets out a blast of smoke and some sparks!")) /obj/structure/machinery/power/apc/surplus() From b98f57b5edec7bd5b1057d89e40c19243ae2b3a8 Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:29:33 +0100 Subject: [PATCH 019/112] Project ARES - Apollo Controller (#3783) # About the pull request Further to #3298 develops the Apollo Maintenance Controller to be functional properly. At present it only functions for maintenance tickets, but will eventually allow for proper use of access tickets, and remote access of the console by working joes (hopefully) # Explain why it's good for the game # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Adds functional maintenance ticket control to the Apollo Console add: Adds a unique ID system for each ticket. Credit to Ben10083 for the idea. add: Adds procs for vents to spew gas within a radius. Not currently usable without proccall. code: Starts work on Access Tickets. code: START of contribs from Ben10083 add: ARES now announces when Bioscan fails. code: new procs to see if ARES can talk, or log something. Bioscan proc renamed for consistency. admin: Admins can now force an ARES announcement or communication if subsystem is offline. add: new emergency protocol from ARES; call General Quarters, which sets the ship to immediate Red Alert. add: New APOLLO maintenance ticket categories; Janitorial and Support. Fire now a priority ticket qol: Claimed APOLLO tickets can be unclaimed qol: APOLLO tickets can be rejected/completed if unclaimed by any Working Joe code: END of contribs from Ben10083 /:cl: --------- Co-authored-by: Ben10083 Co-authored-by: Ben <91219575+Ben10083@users.noreply.github.com> Co-authored-by: harryob --- code/__DEFINES/ARES.dm | 13 +- code/__DEFINES/atmospherics.dm | 4 + code/__DEFINES/typecheck/mobs_generic.dm | 1 + code/defines/procs/announcement.dm | 6 +- code/game/bioscans.dm | 21 +- code/game/machinery/ARES/ARES_procs.dm | 202 +++++++++- code/game/machinery/ARES/ARES_records.dm | 14 +- .../game/machinery/ARES/ARES_step_triggers.dm | 14 +- .../objects/effects/effect_system/smoke.dm | 76 +++- .../objects/structures/pipes/vents/vents.dm | 29 ++ code/modules/admin/tabs/event_tab.dm | 35 +- code/modules/cm_tech/droppod/lz_effect.dm | 5 +- code/modules/mob/language/languages.dm | 15 +- code/span_macros.dm | 1 + tgui/packages/tgui/index.js | 1 + .../packages/tgui/interfaces/AresInterface.js | 27 +- tgui/packages/tgui/interfaces/WorkingJoe.js | 353 ++++++++++++++++-- .../tgui/styles/themes/crt/crt-red.scss | 37 ++ 18 files changed, 752 insertions(+), 102 deletions(-) create mode 100644 tgui/packages/tgui/styles/themes/crt/crt-red.scss diff --git a/code/__DEFINES/ARES.dm b/code/__DEFINES/ARES.dm index 05a42738c499..ec84a6ab5992 100644 --- a/code/__DEFINES/ARES.dm +++ b/code/__DEFINES/ARES.dm @@ -43,11 +43,20 @@ #define APOLLO_ACCESS_DEBUG 5 /// Ticket statuses, both for Access and Maintenance +/// Pending assignment/rejection #define TICKET_PENDING "pending" +/// Assigned to a WJ #define TICKET_ASSIGNED "assigned" -#define TICKET_REJECTED "rejected" +/// Cancelled by reporter #define TICKET_CANCELLED "cancelled" -#define TICKET_COMPLETED "complete" +/// Rejected by WJs +#define TICKET_REJECTED "rejected" +/// Completed by WJs +#define TICKET_COMPLETED "completed" + +/// Checks for if buttons can be used, these may yet be removed and internalised to the UI programming +#define TICKET_OPEN "OPEN" +#define TICKET_CLOSED "CLOSED" /// Cooldowns #define COOLDOWN_ARES_SENSOR 60 SECONDS diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 5869650da273..fcc3e7784cb5 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -37,3 +37,7 @@ /// This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage var/MAX_EXPLOSION_RANGE = 14 + +/// Used in /obj/structure/pipes/vents/proc/create_gas +#define VENT_GAS_SMOKE "Smoke" +#define VENT_GAS_CN20 "CN20 Nerve Gas" diff --git a/code/__DEFINES/typecheck/mobs_generic.dm b/code/__DEFINES/typecheck/mobs_generic.dm index 49e4463435a6..1d848decda4e 100644 --- a/code/__DEFINES/typecheck/mobs_generic.dm +++ b/code/__DEFINES/typecheck/mobs_generic.dm @@ -1,4 +1,5 @@ #define isAI(A) (istype(A, /mob/living/silicon/ai)) +#define isARES(A) (istype(A, /mob/living/silicon/decoy/ship_ai)) #define isSilicon(A) (istype(A, /mob/living/silicon)) #define isRemoteControlling(M) (M && M.client && M.client.remote_control) #define isRemoteControllingOrAI(M) ((M && M.client && M.client.remote_control) || (istype(M, /mob/living/silicon/ai))) diff --git a/code/defines/procs/announcement.dm b/code/defines/procs/announcement.dm index 323fb526d527..5223d63b8e59 100644 --- a/code/defines/procs/announcement.dm +++ b/code/defines/procs/announcement.dm @@ -46,7 +46,7 @@ targets.Remove(H) var/datum/ares_link/link = GLOB.ares_link - if(link.interface && !(link.interface.inoperable())) + if(ares_can_log()) switch(logging) if(ARES_LOG_MAIN) link.log_ares_announcement(title, message) @@ -99,7 +99,7 @@ INVOKE_ASYNC(AI, TYPE_PROC_REF(/mob/living/silicon/decoy/ship_ai, say), message) var/datum/ares_link/link = GLOB.ares_link - if(link.interface && !(link.interface.inoperable())) + if(ares_can_log()) switch(logging) if(ARES_LOG_MAIN) link.log_ares_announcement("[MAIN_AI_SYSTEM] Comms Update", message) @@ -151,7 +151,7 @@ targets.Remove(T) var/datum/ares_link/link = GLOB.ares_link - if(link.interface && !(link.interface.inoperable())) + if(ares_can_log()) link.log_ares_announcement("[title] Shipwide Update", message) announcement_helper(message, title, targets, sound_to_play) diff --git a/code/game/bioscans.dm b/code/game/bioscans.dm index 5f07b307751a..62c801a02d29 100644 --- a/code/game/bioscans.dm +++ b/code/game/bioscans.dm @@ -110,7 +110,7 @@ GLOBAL_DATUM_INIT(bioscan_data, /datum/bioscan_data, new) /// This will do something after Project ARES. -/datum/bioscan_data/proc/can_ares_bioscan() +/datum/bioscan_data/proc/ares_can_bioscan() var/datum/ares_link/link = GLOB.ares_link if(!istype(link)) return FALSE @@ -120,8 +120,15 @@ GLOBAL_DATUM_INIT(bioscan_data, /datum/bioscan_data, new) /// The announcement to all Humans. Slightly off for the planet and elsewhere, accurate for the ship. /datum/bioscan_data/proc/ares_bioscan(forced = FALSE, variance = 2) - if(!forced && !can_ares_bioscan()) - message_admins("BIOSCAN: An ARES bioscan has failed.") + var/datum/ares_link/link = GLOB.ares_link + if(!forced && !ares_can_bioscan()) + message_admins("An ARES Bioscan has failed.") + var/name = "[MAIN_AI_SYSTEM] Bioscan Status" + var/input = "Bioscan failed. \n\nInvestigation into Bioscan subsystem recommended." + if(ares_can_log()) + link.log_ares_bioscan(name, input) + if(ares_can_interface()) + marine_announcement(input, name, 'sound/misc/interference.ogg', logging = ARES_LOG_NONE) return //Adjust the randomness there so everyone gets the same thing var/fake_xenos_on_planet = max(0, xenos_on_planet + rand(-variance, variance)) @@ -130,10 +137,12 @@ GLOBAL_DATUM_INIT(bioscan_data, /datum/bioscan_data, new) log_game("BIOSCAN: ARES bioscan completed. [input]") - var/datum/ares_link/link = GLOB.ares_link - link.log_ares_bioscan(name, input) - if(forced || (link.p_interface && !link.p_interface.inoperable())) + if(forced || ares_can_log()) + link.log_ares_bioscan(name, input) //if interface is down, bioscan still logged, just have to go read it. + if(forced || ares_can_interface()) marine_announcement(input, name, 'sound/AI/bioscan.ogg', logging = ARES_LOG_NONE) + else + message_admins("An ARES Bioscan has succeeded, but was not announced.") /// The announcement to all Xenos. Slightly off for the human ship, accurate otherwise. /datum/bioscan_data/proc/qm_bioscan(variance = 2) diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm index 79c49818595c..8b5f77fa6d84 100644 --- a/code/game/machinery/ARES/ARES_procs.dm +++ b/code/game/machinery/ARES/ARES_procs.dm @@ -1,4 +1,18 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) +GLOBAL_LIST_INIT(maintenance_categories, list( + "Broken Light", + "Shattered Glass", + "Minor Structural Damage", + "Major Structural Damage", + "Janitorial", + "Chemical Spill", + "Fire", + "Communications Failure", + "Power Generation Failure", + "Electrical Fault", + "Support", + "Other" + )) /datum/ares_link var/link_id = MAIN_SHIP_DEFAULT_NAME @@ -35,14 +49,12 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) speaker = "Unknown" var/datum/ares_link/link = GLOB.ares_link if(!link.p_apollo || link.p_apollo.inoperable()) - return + return FALSE if(!link.p_interface || link.p_interface.inoperable()) - return + return FALSE link.apollo_log.Add("[worldtime2text()]: [speaker], '[message]'") /datum/ares_link/proc/log_ares_bioscan(title, input) - if(!p_bioscan || p_bioscan.inoperable() || !interface) - return FALSE interface.records_bioscan.Add(new /datum/ares_record/bioscan(title, input)) /datum/ares_link/proc/log_ares_bombardment(mob/living/user, ob_name, coordinates) @@ -61,6 +73,32 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) interface.records_security.Add(new /datum/ares_record/security(title, details)) // ------ End ARES Logging Procs ------ // +/proc/ares_apollo_talk(broadcast_message) + var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] + for(var/mob/living/silicon/decoy/ship_ai/ai in ai_mob_list) + if(ai.stat == DEAD) + return FALSE + apollo.broadcast(ai, broadcast_message) + for(var/mob/listener in (GLOB.human_mob_list + GLOB.dead_mob_list)) + if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. + playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + +/proc/ares_can_interface() + var/obj/structure/machinery/ares/processor/interface/processor = GLOB.ares_link.p_interface + if(!istype(GLOB.ares_link)) + return FALSE + if(processor && !processor.inoperable()) + return TRUE + return FALSE //interface processor not found or is broken + +/proc/ares_can_log() + var/obj/structure/machinery/computer/ares_console/interface = GLOB.ares_link.interface + if(!istype(GLOB.ares_link)) + return FALSE + if(interface && !interface.inoperable()) + return TRUE + return FALSE //ares interface not found or is broken + // ------ ARES Interface Procs ------ // /obj/structure/machinery/computer/proc/get_ares_access(obj/item/card/id/card) if(ACCESS_ARES_DEBUG in card.access) @@ -463,6 +501,19 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) current_menu = "read_deleted" // -- Emergency Buttons -- // + if("general_quarters") + if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA) + to_chat(usr, SPAN_WARNING("Alert level is already red or above, General Quarters cannot be called.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + set_security_level(2, no_sound = TRUE, announce = FALSE) + shipwide_ai_announcement("ATTENTION! GENERAL QUARTERS. ALL HANDS, MAN YOUR BATTLESTATIONS.", MAIN_AI_SYSTEM, 'sound/effects/GQfullcall.ogg') + log_game("[key_name(usr)] has called for general quarters via ARES.") + message_admins("[key_name_admin(usr)] has called for general quarters via ARES.") + var/datum/ares_link/link = GLOB.ares_link + link.log_ares_security("General Quarters", "[last_login] has called for general quarters via ARES.") + . = TRUE + if("evacuation_start") if(security_level < SEC_LEVEL_RED) to_chat(usr, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) @@ -551,7 +602,7 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) return APOLLO_ACCESS_AUTHED if(ACCESS_MARINE_AI_TEMP in card.access) return APOLLO_ACCESS_TEMP - if((ACCESS_MARINE_COMMAND in card.access ) || (ACCESS_MARINE_ENGINEERING in card.access) || (ACCESS_WY_CORPORATE in card.access)) + if((ACCESS_MARINE_SENIOR in card.access ) || (ACCESS_MARINE_ENGINEERING in card.access) || (ACCESS_WY_CORPORATE in card.access)) return APOLLO_ACCESS_REPORTER else return APOLLO_ACCESS_REQUEST @@ -577,7 +628,8 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) set name = "Eject ID Card" set src in oview(1) - if(!usr || usr.stat || usr.lying) return + if(!usr || usr.stat || usr.lying) + return FALSE if(authenticator_id) authenticator_id.loc = get_turf(src) @@ -604,11 +656,14 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) /obj/structure/machinery/computer/working_joe/attackby(obj/object, mob/user) if(istype(object, /obj/item/card/id)) + if(!ticket_console) + to_chat(user, SPAN_WARNING("This console doesn't have an ID port!")) + return FALSE if(!operable()) to_chat(user, SPAN_NOTICE("You try to insert [object] but [src] remains silent.")) - return + return FALSE var/obj/item/card/id/idcard = object - if((ACCESS_MARINE_AI in idcard.access) || (ACCESS_ARES_DEBUG in idcard.access)) + if((idcard.assignment == JOB_WORKING_JOE) || (ACCESS_ARES_DEBUG in idcard.access)) if(!authenticator_id) if(user.drop_held_item()) object.forceMove(src) @@ -620,7 +675,7 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) target_id = object else to_chat(user, "Both slots are full already. Remove a card first.") - return + return FALSE else if(!target_id) if(user.drop_held_item()) @@ -628,7 +683,7 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) target_id = object else to_chat(user, "Both slots are full already. Remove a card first.") - return + return FALSE else ..() @@ -689,26 +744,42 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance) if(!istype(maint_ticket)) continue + var/lock_status = TICKET_OPEN + switch(maint_ticket.ticket_status) + if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) + lock_status = TICKET_CLOSED + var/list/current_maint = list() + current_maint["id"] = maint_ticket.ticket_id current_maint["time"] = maint_ticket.ticket_time - current_maint["title"] = maint_ticket.ticket_name + current_maint["priority_status"] = maint_ticket.ticket_priority + current_maint["category"] = maint_ticket.ticket_name current_maint["details"] = maint_ticket.ticket_details current_maint["status"] = maint_ticket.ticket_status current_maint["submitter"] = maint_ticket.ticket_submitter current_maint["assignee"] = maint_ticket.ticket_assignee + current_maint["lock_status"] = lock_status current_maint["ref"] = "\ref[maint_ticket]" logged_maintenance += list(current_maint) data["maintenance_tickets"] = logged_maintenance var/list/logged_access = list() - for(var/datum/ares_ticket/access_ticket/access_ticket as anything in link.tickets_access) + for(var/datum/ares_ticket/access/access_ticket as anything in link.tickets_access) + var/lock_status = TICKET_OPEN + switch(access_ticket.ticket_status) + if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) + lock_status = TICKET_CLOSED + var/list/current_ticket = list() + current_ticket["id"] = access_ticket.ticket_id current_ticket["time"] = access_ticket.ticket_time + current_ticket["priority_status"] = access_ticket.ticket_priority current_ticket["title"] = access_ticket.ticket_name current_ticket["details"] = access_ticket.ticket_details current_ticket["status"] = access_ticket.ticket_status current_ticket["submitter"] = access_ticket.ticket_submitter current_ticket["assignee"] = access_ticket.ticket_assignee + current_ticket["lock_status"] = lock_status current_ticket["ref"] = "\ref[access_ticket]" logged_access += list(current_ticket) data["access_tickets"] = logged_access @@ -758,7 +829,7 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) authentication = get_ares_access(idcard) last_login = idcard.registered_name else - to_chat(usr, SPAN_WARNING("You require an ID card to access this terminal!")) + to_chat(operator, SPAN_WARNING("You require an ID card to access this terminal!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(authentication) @@ -796,20 +867,113 @@ GLOBAL_DATUM_INIT(ares_link, /datum/ares_link, new) current_menu = "maint_claim" if("new_report") - var/name = tgui_input_text(usr, "What is the type of maintenance item you wish to report?\n\nExample:\n 'Broken light in Aft Hallway.'", "Ticket Name", encode = FALSE) - if(!name) + var/priority_report = FALSE + var/maint_type = tgui_input_list(operator, "What is the type of maintenance item you wish to report?", "Report Category", GLOB.maintenance_categories, 30 SECONDS) + switch(maint_type) + if("Major Structural Damage", "Fire", "Communications Failure", "Power Generation Failure") + priority_report = TRUE + + if(!maint_type) return FALSE - var/details = tgui_input_text(usr, "What are the details for this report?", "Ticket Details", encode = FALSE) + var/details = tgui_input_text(operator, "What are the details for this report?", "Ticket Details", encode = FALSE) if(!details) return FALSE - var/confirm = tgui_alert(usr, "Please confirm the submission of your maintenance report. \n\n [name] \n\n [details] \n\n Is this correct?", "Confirmation", list("Yes", "No")) + + if((authentication >= APOLLO_ACCESS_REPORTER) && !priority_report) + var/is_priority = tgui_alert(operator, "Is this a priority report?", "Priority designation", list("Yes", "No")) + if(is_priority == "Yes") + priority_report = TRUE + + var/confirm = alert(operator, "Please confirm the submission of your maintenance report. \n\n Priority: [priority_report ? "Yes" : "No"] \n Category: '[maint_type]' \n Details: '[details]' \n\n Is this correct?", "Confirmation", "Yes", "No") if(confirm == "Yes") if(link) - var/datum/ares_ticket/maintenance/maint_ticket = new(last_login, name, details) + var/datum/ares_ticket/maintenance/maint_ticket = new(last_login, maint_type, details, priority_report) link.tickets_maintenance += maint_ticket - log_game("ARES: Maintenance Ticket created by [key_name(operator)] as [last_login] with Header '[name]' and Details of '[details]'.") + if(priority_report) + ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.") + log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(operator)] as [last_login] with Category '[maint_type]' and Details of '[details]'.") return TRUE return FALSE + if("claim_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + var/claim = TRUE + var/assigned = ticket.ticket_assignee + if(assigned) + if(assigned == last_login) + var/prompt = tgui_alert(usr, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No")) + if(prompt != "Yes") + return FALSE + /// set ticket back to pending + ticket.ticket_assignee = null + ticket.ticket_status = TICKET_PENDING + return claim + var/choice = tgui_alert(usr, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No")) + if(choice != "Yes") + claim = FALSE + if(claim) + ticket.ticket_assignee = last_login + ticket.ticket_status = TICKET_ASSIGNED + return claim + + if("cancel_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + if(ticket.ticket_submitter != last_login) + to_chat(usr, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!")) + return FALSE + to_chat(usr, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled.")) + ticket.ticket_status = TICKET_CANCELLED + if(ticket.ticket_priority) + ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been cancelled.") + return TRUE + + if("mark_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + if(ticket.ticket_assignee != last_login && ticket.ticket_assignee) //must be claimed by you or unclaimed.) + to_chat(usr, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + return FALSE + var/choice = tgui_alert(usr, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS) + switch(choice) + if(TICKET_COMPLETED) + ticket.ticket_status = TICKET_COMPLETED + if(TICKET_REJECTED) + ticket.ticket_status = TICKET_REJECTED + else + return FALSE + if(ticket.ticket_priority) + ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by [last_login].") + to_chat(usr, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) + return TRUE + + if("new_access") + var/priority_report = FALSE + var/ticket_holder = tgui_input_text(operator, "Who is the ticket for?", "Ticket Holder", encode = FALSE) + if(!ticket_holder) + return FALSE + var/details = tgui_input_text(operator, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE) + if(!details) + return FALSE + + if(authentication >= APOLLO_ACCESS_AUTHED) + var/is_priority = tgui_alert(operator, "Is this a priority request?", "Priority designation", list("Yes", "No")) + if(is_priority == "Yes") + priority_report = TRUE + + var/confirm = alert(operator, "Please confirm the submission of your access ticket request. \n\n Priority: [priority_report ? "Yes" : "No"] \n Holder: '[ticket_holder]' \n Details: '[details]' \n\n Is this correct?", "Confirmation", "Yes", "No") + if(confirm != "Yes" || !link) + return FALSE + var/datum/ares_ticket/access/access_ticket = new(last_login, ticket_holder, details, priority_report) + link.tickets_access += access_ticket + if(priority_report) + ares_apollo_talk("Priority Access Request: [ticket_holder] - ID [access_ticket.ticket_id]. Seek and resolve.") + log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(operator)] as [last_login] with Holder '[ticket_holder]' and Details of '[details]'.") + return TRUE + if(playsound) playsound(src, "keyboard_alt", 15, 1) diff --git a/code/game/machinery/ARES/ARES_records.dm b/code/game/machinery/ARES/ARES_records.dm index 9cb8574e58f7..4e2b479e71a2 100644 --- a/code/game/machinery/ARES/ARES_records.dm +++ b/code/game/machinery/ARES/ARES_records.dm @@ -77,6 +77,8 @@ var/ticket_status = TICKET_PENDING /// Name of who is handling the ticket. Derived from last login. var/ticket_assignee + /// Numerical designation of the ticket. + var/ticket_id = "1111" /// World time in text format. var/ticket_time /// Who submitted the ticket. Derived from last login. @@ -85,15 +87,23 @@ var/ticket_name /// The content of the ticket, usually an explanation of what it is for. var/ticket_details + /// Whether or not the tickey is a priority. + var/ticket_priority = FALSE + +/datum/ares_ticket/New(user, name, details, priority) + var/ref_holder = "\ref[src]" + var/pos = length(ref_holder) + var/new_id = "#[copytext("\ref[src]", pos - 4, pos)]" -/datum/ares_ticket/New(user, name, details) ticket_time = worldtime2text() ticket_submitter = user ticket_details = details ticket_name = name + ticket_priority = priority + ticket_id = new_id /datum/ares_ticket/maintenance ticket_type = ARES_RECORD_MAINTENANCE -/datum/ares_ticket/access_ticket +/datum/ares_ticket/access ticket_type = ARES_RECORD_ACCESS diff --git a/code/game/machinery/ARES/ARES_step_triggers.dm b/code/game/machinery/ARES/ARES_step_triggers.dm index 1562f1badaab..a50aa40abd90 100644 --- a/code/game/machinery/ARES/ARES_step_triggers.dm +++ b/code/game/machinery/ARES/ARES_step_triggers.dm @@ -74,12 +74,7 @@ return FALSE to_chat(passer, SPAN_BOLDWARNING("You hear a soft beeping sound as you cross the threshold.")) - var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] - for(var/mob/living/silicon/decoy/ship_ai/ai in ai_mob_list) - apollo.broadcast(ai, broadcast_message) - for(var/mob/listener as anything in (GLOB.human_mob_list + GLOB.dead_mob_list)) - if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. - playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + ares_apollo_talk(broadcast_message) COOLDOWN_START(src, sensor_cooldown, cooldown_duration) if(alert_id && link) for(var/obj/effect/step_trigger/ares_alert/sensor in link.linked_alerts) @@ -166,12 +161,7 @@ return FALSE to_chat(passer, SPAN_BOLDWARNING("You hear a harsh buzzing sound as you cross the threshold!")) - var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] - for(var/mob/living/silicon/decoy/ship_ai/ai in ai_mob_list) - apollo.broadcast(ai, broadcast_message) - for(var/mob/listener in (GLOB.human_mob_list + GLOB.dead_mob_list)) - if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. - playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + ares_apollo_talk(broadcast_message) if(idcard) idcard.access -= ACCESS_MARINE_AI_TEMP COOLDOWN_START(src, sensor_cooldown, COOLDOWN_ARES_ACCESS_CONTROL) diff --git a/code/game/objects/effects/effect_system/smoke.dm b/code/game/objects/effects/effect_system/smoke.dm index 9f7a9c8143c7..2eb36930c542 100644 --- a/code/game/objects/effects/effect_system/smoke.dm +++ b/code/game/objects/effects/effect_system/smoke.dm @@ -180,18 +180,20 @@ /obj/effect/particle_effect/smoke/mustard/Move() . = ..() - for(var/mob/living/carbon/human/R in get_turf(src)) - affect(R) + for(var/mob/living/carbon/human/creature in get_turf(src)) + affect(creature) -/obj/effect/particle_effect/smoke/mustard/affect(mob/living/carbon/human/R) - ..() - R.burn_skin(0.75) - if(R.coughedtime != 1) - R.coughedtime = 1 - if(ishuman(R)) //Humans only to avoid issues - R.emote("gasp") - addtimer(VARSET_CALLBACK(R, coughedtime, 0), 2 SECONDS) - R.updatehealth() +/obj/effect/particle_effect/smoke/mustard/affect(mob/living/carbon/human/creature) + if(!istype(creature) || issynth(creature)) + return FALSE + + creature.burn_skin(0.75) + if(creature.coughedtime != 1) + creature.coughedtime = 1 + if(ishuman(creature)) //Humans only to avoid issues + creature.emote("gasp") + addtimer(VARSET_CALLBACK(creature, coughedtime, 0), 2 SECONDS) + creature.updatehealth() return ///////////////////////////////////////////// @@ -244,6 +246,55 @@ M.updatehealth() +///////////////////////////////////////////// +// CN20 Nerve Gas +///////////////////////////////////////////// + +/obj/effect/particle_effect/smoke/cn20 + name = "CN20 nerve gas" + smokeranking = SMOKE_RANK_HIGH + color = "#80c7e4" + +/obj/effect/particle_effect/smoke/cn20/Move() + . = ..() + for(var/mob/living/carbon/human/creature in get_turf(src)) + affect(creature) + +/obj/effect/particle_effect/smoke/cn20/affect(mob/living/carbon/human/creature) + if(!istype(creature) || issynth(creature) || creature.stat == DEAD) + return FALSE + if(isyautja(creature) && prob(75)) + return FALSE + + if (creature.wear_mask && (creature.wear_mask.flags_inventory & BLOCKGASEFFECT)) + return FALSE + + var/effect_amt = round(6 + amount*6) + + creature.apply_damage(12, OXY) + creature.SetEarDeafness(max(creature.ear_deaf, round(effect_amt*1.5))) //Paralysis of hearing system, aka deafness + if(!creature.eye_blind) //Eye exposure damage + to_chat(creature, SPAN_DANGER("Your eyes sting. You can't see!")) + creature.SetEyeBlind(round(effect_amt/3)) + if(creature.coughedtime != 1 && !creature.stat) //Coughing/gasping + creature.coughedtime = 1 + if(prob(50)) + creature.emote("cough") + else + creature.emote("gasp") + addtimer(VARSET_CALLBACK(creature, coughedtime, 0), 1.5 SECONDS) + if (prob(20)) + creature.apply_effect(1, WEAKEN) + + //Topical damage (neurotoxin on exposed skin) + to_chat(creature, SPAN_DANGER("Your body is going numb, almost as if paralyzed!")) + if(prob(60 + round(amount*15))) //Highly likely to drop items due to arms/hands seizing up + creature.drop_held_item() + if(ishuman(creature)) + creature.temporary_slowdown = max(creature.temporary_slowdown, 4) //One tick every two second + creature.recalculate_move_delay = TRUE + return TRUE + ////////////////////////////////////// // FLASHBANG SMOKE //////////////////////////////////// @@ -541,6 +592,9 @@ /datum/effect_system/smoke_spread/phosphorus/weak smoke_type = /obj/effect/particle_effect/smoke/phosphorus/weak +/datum/effect_system/smoke_spread/cn20 + smoke_type = /obj/effect/particle_effect/smoke/cn20 + // XENO SMOKES /datum/effect_system/smoke_spread/xeno_acid diff --git a/code/game/objects/structures/pipes/vents/vents.dm b/code/game/objects/structures/pipes/vents/vents.dm index fa3395d9e91d..2b3d5409dc8a 100644 --- a/code/game/objects/structures/pipes/vents/vents.dm +++ b/code/game/objects/structures/pipes/vents/vents.dm @@ -12,6 +12,7 @@ var/uid var/vent_icon = "vent" + var/datum/effect_system/smoke_spread/gas_holder /obj/structure/pipes/vents/Initialize() . = ..() @@ -123,7 +124,35 @@ qdel(src) /obj/structure/pipes/vents/Destroy() + qdel(gas_holder) if(initial_loc) initial_loc.air_vent_info -= id_tag initial_loc.air_vent_names -= id_tag . = ..() + +/obj/structure/pipes/vents/proc/create_gas(gas_type = VENT_GAS_SMOKE, radius = 4, warning_time = 5 SECONDS) + if(welded) + to_chat(usr, SPAN_WARNING("You cannot release gas from a welded vent.")) + return FALSE + var/datum/effect_system/smoke_spread/spreader + switch(gas_type) + if(VENT_GAS_SMOKE) + spreader = new /datum/effect_system/smoke_spread/bad + if(VENT_GAS_CN20) + spreader = new /datum/effect_system/smoke_spread/cn20 + if(!spreader) + return FALSE + gas_holder = spreader + spreader.attach(src) + + new /obj/effect/warning/explosive/gas(loc, warning_time) + visible_message(SPAN_HIGHDANGER("[src] begins to hiss as gas builds up within it."), SPAN_HIGHDANGER("You hear a hissing."), radius) + addtimer(CALLBACK(src, PROC_REF(release_gas), radius), warning_time) + +/obj/structure/pipes/vents/proc/release_gas(radius = 4) + radius = Clamp(radius, 1, 10) + if(!gas_holder || welded) + return FALSE + playsound(loc, 'sound/effects/smoke.ogg', 25, 1, 4) + gas_holder.set_up(radius, 0, get_turf(src), null, 10 SECONDS) + gas_holder.start() diff --git a/code/modules/admin/tabs/event_tab.dm b/code/modules/admin/tabs/event_tab.dm index febc1550fca0..89d709cbdda3 100644 --- a/code/modules/admin/tabs/event_tab.dm +++ b/code/modules/admin/tabs/event_tab.dm @@ -535,10 +535,11 @@ if(!input) return FALSE - var/datum/ares_link/link = GLOB.ares_link - if(link.p_interface.inoperable()) - to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) - return + if(!ares_can_interface()) + var/prompt = tgui_alert(src, "ARES interface processor is offline or destroyed, send the message anyways?", "Choose.", list("Yes", "No"), 20 SECONDS) + if(prompt == "No") + to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It's interface processor may be offline or destroyed.")) + return ai_announcement(input) message_admins("[key_name_admin(src)] has created an AI comms report") @@ -558,15 +559,12 @@ var/datum/ares_link/link = GLOB.ares_link if(link.p_apollo.inoperable()) - to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) - return FALSE + var/prompt = tgui_alert(src, "ARES APOLLO processor is offline or destroyed, send the message anyways?", "Choose.", list("Yes", "No"), 20 SECONDS) + if(prompt == "No") + to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It's APOLLO processor may be offline or destroyed.")) + return FALSE - var/datum/language/apollo/apollo = GLOB.all_languages[LANGUAGE_APOLLO] - for(var/mob/living/silicon/decoy/ship_ai/AI in ai_mob_list) - apollo.broadcast(AI, input) - for(var/mob/listener as anything in (GLOB.human_mob_list + GLOB.dead_mob_list)) - if(listener.hear_apollo())//Only plays sound to mobs and not observers, to reduce spam. - playsound_client(listener.client, sound('sound/misc/interference.ogg'), listener, vol = 45) + ares_apollo_talk(input) message_admins("[key_name_admin(src)] has created an AI APOLLO report") log_admin("AI APOLLO report: [input]") @@ -580,14 +578,15 @@ var/input = input(usr, "This is an announcement type message from the ship's AI. This will be announced to every conscious human on Almayer z-level. Be aware, this will work even if ARES unpowered/destroyed. Check with online staff before you send this.", "What?", "") as message|null if(!input) return FALSE - for(var/obj/structure/machinery/ares/processor/interface/processor in machines) - if(processor.inoperable()) - to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It may be offline or destroyed.")) + if(!ares_can_interface()) + var/prompt = tgui_alert(src, "ARES interface processor is offline or destroyed, send the message anyways?", "Choose.", list("Yes", "No"), 20 SECONDS) + if(prompt == "No") + to_chat(usr, SPAN_WARNING("[MAIN_AI_SYSTEM] is not responding. It's interface processor may be offline or destroyed.")) return - shipwide_ai_announcement(input) - message_admins("[key_name_admin(src)] has created an AI shipwide report") - log_admin("[key_name_admin(src)] AI shipwide report: [input]") + shipwide_ai_announcement(input) + message_admins("[key_name_admin(src)] has created an AI shipwide report") + log_admin("[key_name_admin(src)] AI shipwide report: [input]") /client/proc/cmd_admin_create_predator_report() set name = "Report: Yautja AI" diff --git a/code/modules/cm_tech/droppod/lz_effect.dm b/code/modules/cm_tech/droppod/lz_effect.dm index 32e0bed74388..6a73916c7b3f 100644 --- a/code/modules/cm_tech/droppod/lz_effect.dm +++ b/code/modules/cm_tech/droppod/lz_effect.dm @@ -24,8 +24,6 @@ name = "hoverpack warning" color = "#D4AE1E" - color = "#D4AE1E" - /obj/effect/warning/explosive name = "explosive warning" color = "#ff0000" @@ -36,3 +34,6 @@ /obj/effect/warning/explosive/proc/disappear() qdel(src) +/obj/effect/warning/explosive/gas + name = "gas warning" + color = "#42acd6" diff --git a/code/modules/mob/language/languages.dm b/code/modules/mob/language/languages.dm index e5b693e02b80..2844b5841781 100644 --- a/code/modules/mob/language/languages.dm +++ b/code/modules/mob/language/languages.dm @@ -162,24 +162,31 @@ if (!message) return + ///Font size + var/scale = "message" + if(isARES(speaker)) + scale = "large" + var/message_start = "[name], [speaker.name]" var/message_body = "broadcasts, \"[message]\"" + var/full_message = "[message_start] [message_body]" + + GLOB.STUI.game.Add("\[[time_stamp()]]APOLLO: [key_name(speaker)] : [message]
") GLOB.STUI.processing |= STUI_LOG_GAME_CHAT log_say("[speaker.name != "Unknown" ? speaker.name : "([speaker.real_name])"] \[APOLLO\]: [message] (CKEY: [speaker.key]) (JOB: [speaker.job])") log_ares_apollo(speaker.real_name, message) for (var/mob/dead in GLOB.dead_mob_list) if(!istype(dead,/mob/new_player) && !istype(dead,/mob/living/brain)) //No meta-evesdropping - dead.show_message("[message_start] [message_body]", SHOW_MESSAGE_VISIBLE) + var/dead_message = "[message_start](F) [message_body]" + dead.show_message(dead_message, SHOW_MESSAGE_VISIBLE) for (var/mob/living/listener in GLOB.alive_mob_list) if (!listener.hear_apollo()) continue - else if(isAI(listener)) - message_start = "[name], [speaker.name]" - listener.show_message("[message_start] [message_body]", SHOW_MESSAGE_VISIBLE) + listener.show_message(full_message, SHOW_MESSAGE_VISIBLE) var/list/listening = hearers(1, src) listening -= src diff --git a/code/span_macros.dm b/code/span_macros.dm index d5e9cdcb9c36..1eca82ea563f 100644 --- a/code/span_macros.dm +++ b/code/span_macros.dm @@ -55,6 +55,7 @@ // Misc #define SPAN_BOLD(X) "[X]" #define SPAN_UNDERLINE(X) "[X]" +#define SPAN_LARGE(X) "[X]" #define SPAN_BOLDANNOUNCE(X) "[X]" #define SPAN_BOLDNOTICE(X) "[X]" diff --git a/tgui/packages/tgui/index.js b/tgui/packages/tgui/index.js index 727973378649..97640d062a86 100644 --- a/tgui/packages/tgui/index.js +++ b/tgui/packages/tgui/index.js @@ -10,6 +10,7 @@ import './styles/themes/abductor.scss'; import './styles/themes/cardtable.scss'; import './styles/themes/crt/crt-blue.scss'; import './styles/themes/crt/crt-green.scss'; +import './styles/themes/crt/crt-red.scss'; import './styles/themes/crt/crt-yellow.scss'; import './styles/themes/spookyconsole.scss'; import './styles/themes/hackerman.scss'; diff --git a/tgui/packages/tgui/interfaces/AresInterface.js b/tgui/packages/tgui/interfaces/AresInterface.js index 6bf85e96522f..5cd78011a81c 100644 --- a/tgui/packages/tgui/interfaces/AresInterface.js +++ b/tgui/packages/tgui/interfaces/AresInterface.js @@ -22,11 +22,18 @@ const PAGES = { export const AresInterface = (props, context) => { const { data } = useBackend(context); - const { current_menu } = data; + const { current_menu, sudo } = data; const PageComponent = PAGES[current_menu](); + let themecolor = 'crtblue'; + if (sudo >= 1) { + themecolor = 'crtred'; + } else if (current_menu === 'emergency') { + themecolor = 'crtred'; + } + return ( - + @@ -1364,6 +1371,8 @@ const Emergency = (props, context) => { nuketimelock, nuke_available, } = data; + const canQuarters = alert_level < 2; + let quarters_reason = 'Call for General Quarters.'; const minimumEvacTime = worldtime > distresstimelock; const distressCooldown = worldtime < distresstime; const canDistress = alert_level === 2 && !distressCooldown && minimumEvacTime; @@ -1445,6 +1454,20 @@ const Emergency = (props, context) => {

Emergency Protocols

+ act('general_quarters')} + disabled={!canQuarters} + /> { const PageComponent = PAGES[current_menu](); return ( - + @@ -44,7 +44,7 @@ const Login = (props, context) => { WY-DOS Executive - Version 12.7.1 + Version 12.8.3 Copyright © 2182, Weyland Yutani Corp.