diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 31103fee93ee..3137088d1c90 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -17,12 +17,10 @@ #define NOTE_ADMIN 1 ///This note is used by staff for positive record keeping. #define NOTE_MERIT 2 -///These notes are used by respective whitelist councils for record keeping. -#define NOTE_COMMANDER 3 -#define NOTE_SYNTHETIC 4 -#define NOTE_YAUTJA 5 +///These notes are automatically applied by the Whitelist Panel. +#define NOTE_WHITELIST 3 ///Note categories in text form, in order of their numerical #defines. -GLOBAL_LIST_INIT(note_categories, list("Admin", "Merit", "Commanding Officer", "Synthetic", "Yautja")) +GLOBAL_LIST_INIT(note_categories, list("Admin", "Merit", "Whitelist")) #define ADMIN_FLW(user) "(FLW)" #define ADMIN_PP(user) "(PP)" diff --git a/code/__DEFINES/dcs/signals/atom/signals_item.dm b/code/__DEFINES/dcs/signals/atom/signals_item.dm index f038d4c5dbce..5ba79960657b 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_item.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_item.dm @@ -29,8 +29,10 @@ #define COMSIG_ITEM_PICKUP "item_pickup" -///from /obj/item/device/camera/broadcasting/attack_self +///from /obj/item/device/camera/broadcasting #define COMSIG_BROADCAST_GO_LIVE "broadcast_live" +#define COMSIG_BROADCAST_HEAR_TALK "broadcast_hear_talk" +#define COMSIG_BROADCAST_SEE_EMOTE "broadcast_see_emote" /// from /obj/item/proc/mob_can_equip #define COMSIG_ITEM_ATTEMPTING_EQUIP "item_attempting_equip" diff --git a/code/__DEFINES/dcs/signals/atom/signals_obj.dm b/code/__DEFINES/dcs/signals/atom/signals_obj.dm index ed27c26b2115..c850b2a52e03 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_obj.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_obj.dm @@ -30,8 +30,16 @@ #define COMSIG_TENT_COLLAPSING "tent_collapsing" /// from /obj/proc/afterbuckle() -#define COSMIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle" +#define COMSIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle" +/// from /datum/cm_objective/retrieve_data/disk/process() +#define COMSIG_INTEL_DISK_LOST_POWER "intel_disk_lost_power" + +/// from /datum/cm_objective/retrieve_data/disk/complete() +#define COMSIG_INTEL_DISK_COMPLETED "intel_disk_completed" + +/// from /obj/vehicle/multitile/arc/toggle_antenna() +#define COMSIG_ARC_ANTENNA_TOGGLED "arc_antenna_toggled" /// from /obj/structure/machinery/cryopod/go_out() #define COMSIG_CRYOPOD_GO_OUT "cryopod_go_out" diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index f975a67824ef..306f37deb8cb 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -69,6 +69,9 @@ /// From /proc/biohazard_lockdown() #define COMSIG_GLOB_RESEARCH_LOCKDOWN "!research_lockdown_closed" #define COMSIG_GLOB_RESEARCH_LIFT "!research_lockdown_opened" +/// From /proc/aicore_lockdown() +#define COMSIG_GLOB_AICORE_LOCKDOWN "!aicore_lockdown_closed" +#define COMSIG_GLOB_AICORE_LIFT "!aicore_lockdown_opened" /// From /obj/structure/machinery/power/reactor/proc/set_overloading() : (set_overloading) #define COMSIG_GLOB_GENERATOR_SET_OVERLOADING "!generator_set_overloading" diff --git a/code/__DEFINES/equipment.dm b/code/__DEFINES/equipment.dm index 4368bf304a48..b37ae0d59d64 100644 --- a/code/__DEFINES/equipment.dm +++ b/code/__DEFINES/equipment.dm @@ -44,6 +44,8 @@ #define USES_HEARING (1<<17) /// Should we use the initial icon for display? Mostly used by overlay only objects #define HTML_USE_INITAL_ICON (1<<18) +// Whether or not the object sees emotes +#define USES_SEEING (1<<19) //========================================================================================== diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm index 1b2907cf57ce..f869357efd1b 100644 --- a/code/__DEFINES/job.dm +++ b/code/__DEFINES/job.dm @@ -206,6 +206,7 @@ GLOBAL_LIST_INIT(job_command_roles, JOB_COMMAND_ROLES_LIST) //-------- WY Goons --------// #define JOB_WY_GOON "WY Corporate Security" +#define JOB_WY_GOON_TECH "WY Corporate Security Technician" #define JOB_WY_GOON_LEAD "WY Corporate Security Lead" #define JOB_WY_GOON_RESEARCHER "WY Research Consultant" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index e2bd868f9a80..dbd8dbe7ce41 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -120,6 +120,7 @@ #define CANDAZE (1<<18) #define CANSLOW (1<<19) #define NO_PERMANENT_DAMAGE (1<<20) +#define CORRUPTED_ALLY (1<<21) // ============================= // hive types diff --git a/code/__DEFINES/vehicle.dm b/code/__DEFINES/vehicle.dm index 8a1617229926..5eb6a824d8ac 100644 --- a/code/__DEFINES/vehicle.dm +++ b/code/__DEFINES/vehicle.dm @@ -7,7 +7,7 @@ #define HDPT_TURRET "turret" #define HDPT_SPECIAL "special" //special pre-installed hardpoints with unique behaviour -#define HDPT_LAYER_WHEELS 1 +#define HDPT_LAYER_WHEELS 0.01 // so it appears below xenomorphs and other mobs #define HDPT_LAYER_SUPPORT 2 #define HDPT_LAYER_ARMOR 3 #define HDPT_LAYER_TURRET 4 diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 8d77920a59cc..71fc9162dcaa 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -16,7 +16,8 @@ return FALSE /atom/movable/attackby(obj/item/W, mob/living/user) - if(W) + . = ..() + if(W && !.) if(!(W.flags_item & NOBLUDGEON)) visible_message(SPAN_DANGER("[src] has been hit by [user] with [W]."), null, null, 5, CHAT_TYPE_MELEE_HIT) user.animation_attack_on(src) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index f265315460e3..40400f2a151c 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -50,7 +50,7 @@ SUBSYSTEM_DEF(ticker) var/totalPlayers = 0 //used for pregame stats on statpanel var/totalPlayersReady = 0 //used for pregame stats on statpanel - var/tutorial_disabled = FALSE //zonenote + var/tutorial_disabled = FALSE /datum/controller/subsystem/ticker/Initialize(timeofday) load_mode() diff --git a/code/datums/ammo/bullet/arc.dm b/code/datums/ammo/bullet/arc.dm new file mode 100644 index 000000000000..5e74508e04b2 --- /dev/null +++ b/code/datums/ammo/bullet/arc.dm @@ -0,0 +1,14 @@ +/datum/ammo/bullet/re700 + name = "rotary cannon bullet" + icon_state = "autocannon" + damage_falloff = 0 + flags_ammo_behavior = AMMO_BALLISTIC + + accuracy = HIT_ACCURACY_TIER_7 + scatter = 0 + damage = 30 + damage_var_high = PROJECTILE_VARIANCE_TIER_8 + penetration = ARMOR_PENETRATION_TIER_2 + accurate_range = 10 + max_range = 12 + shell_speed = AMMO_SPEED_TIER_6 diff --git a/code/datums/components/disk_reader.dm b/code/datums/components/disk_reader.dm new file mode 100644 index 000000000000..6292519893e9 --- /dev/null +++ b/code/datums/components/disk_reader.dm @@ -0,0 +1,87 @@ +/datum/component/disk_reader + dupe_mode = COMPONENT_DUPE_UNIQUE + /// Ref to the inserted disk + var/obj/item/disk/objective/disk + +/datum/component/disk_reader/Initialize() + . = ..() + if(!istype(parent, /obj/structure/machinery)) + return COMPONENT_INCOMPATIBLE + +/datum/component/disk_reader/Destroy(force, silent) + handle_qdel() + return ..() + +/datum/component/disk_reader/RegisterWithParent() + ..() + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, PROC_REF(on_disk_insert)) + RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(handle_qdel)) + RegisterSignal(parent, COMSIG_INTEL_DISK_COMPLETED, PROC_REF(on_disk_complete)) + RegisterSignal(parent, COMSIG_INTEL_DISK_LOST_POWER, PROC_REF(on_power_lost)) + +/datum/component/disk_reader/UnregisterFromParent() + ..() + handle_qdel() + +/datum/component/disk_reader/proc/handle_qdel() + SIGNAL_HANDLER + QDEL_NULL(disk) + +/datum/component/disk_reader/proc/on_disk_insert(datum/source, obj/item/disk/objective/potential_disk, mob/living/inserter, params) + SIGNAL_HANDLER + + if(!istype(potential_disk) || !potential_disk.objective) + return + + if(disk) + to_chat(inserter, SPAN_WARNING("There's already a disk inside [parent], wait for it to finish first!")) + return COMPONENT_NO_AFTERATTACK + + if(potential_disk.objective.state == OBJECTIVE_COMPLETE) + to_chat(inserter, SPAN_WARNING("The reader displays a message stating this disk has already been read and refuses to accept it.")) + return COMPONENT_NO_AFTERATTACK + + INVOKE_ASYNC(src, PROC_REF(handle_disk_insert), potential_disk, inserter) + return COMPONENT_NO_AFTERATTACK + +/datum/component/disk_reader/proc/handle_disk_insert(obj/item/disk/objective/potential_disk, mob/living/inserter) + if(tgui_input_text(inserter, "Enter the encryption key", "Decrypting [potential_disk]", "") != potential_disk.objective.decryption_password) + to_chat(inserter, SPAN_WARNING("The reader buzzes, ejecting the disk.")) + return + + if(disk) + to_chat(inserter, SPAN_WARNING("There's already a disk inside [parent], wait for it to finish first!")) + return + + if(!(potential_disk in inserter.contents)) + return + + potential_disk.objective.activate() + + inserter.drop_inv_item_to_loc(potential_disk, parent) + disk = potential_disk + to_chat(inserter, SPAN_NOTICE("You insert [potential_disk] and enter the decryption key.")) + inserter.count_niche_stat(STATISTICS_NICHE_DISK) + +/datum/component/disk_reader/proc/on_disk_complete(datum/source) + SIGNAL_HANDLER + var/atom/atom_parent = parent + + atom_parent.visible_message("[atom_parent] pings softly as the upload finishes and ejects [disk].") + playsound(atom_parent, 'sound/machines/screen_output1.ogg', 25, 1) + disk.forceMove(get_turf(atom_parent)) + disk.name = "[disk.name] (complete)" + disk.objective.award_points() + disk.retrieve_objective.state = OBJECTIVE_ACTIVE + disk.retrieve_objective.activate() + disk = null + +/datum/component/disk_reader/proc/on_power_lost(datum/source) + SIGNAL_HANDLER + var/atom/atom_parent = parent + + atom_parent.visible_message(SPAN_WARNING("[atom_parent] powers down mid-operation as the area loses power.")) + playsound(atom_parent, 'sound/machines/terminal_shutdown.ogg', 25, 1) + SSobjectives.stop_processing_objective(src) + disk.forceMove(get_turf(atom_parent)) + disk = null diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index 8737fba08db9..ce6fe35e4a28 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -87,7 +87,7 @@ parent_buckle = null /datum/component/weed_food/RegisterWithParent() - RegisterSignal(parent_mob, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + RegisterSignal(parent_mob, COMSIG_MOVABLE_TURF_ENTERED, PROC_REF(on_move)) RegisterSignal(parent_mob, list(COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED), PROC_REF(on_rejuv)) RegisterSignal(parent_mob, COMSIG_HUMAN_SET_UNDEFIBBABLE, PROC_REF(on_update)) RegisterSignal(parent_mob, COMSIG_LIVING_PREIGNITION, PROC_REF(on_preignition)) @@ -98,7 +98,7 @@ /datum/component/weed_food/UnregisterFromParent() if(parent_mob) UnregisterSignal(parent_mob, list( - COMSIG_MOVABLE_MOVED, + COMSIG_MOVABLE_TURF_ENTERED, COMSIG_LIVING_REJUVENATED, COMSIG_HUMAN_REVIVED, COMSIG_HUMAN_SET_UNDEFIBBABLE, @@ -109,12 +109,12 @@ if(parent_turf) UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) if(parent_buckle) - UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE) if(parent_nest) UnregisterSignal(parent_nest, COMSIG_PARENT_QDELETING) UnregisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING) -/// SIGNAL_HANDLER for COMSIG_MOVABLE_MOVED +/// SIGNAL_HANDLER for COMSIG_MOVABLE_TURF_ENTERED /datum/component/weed_food/proc/on_move() SIGNAL_HANDLER @@ -148,7 +148,7 @@ qdel(src) -/// SIGNAL_HANDLER for COSMIG_OBJ_AFTER_BUCKLE +/// SIGNAL_HANDLER for COMSIG_OBJ_AFTER_BUCKLE /datum/component/weed_food/proc/on_after_buckle(obj/source, mob/buckled) SIGNAL_HANDLER @@ -220,12 +220,12 @@ return FALSE // Still buckled to the same thing if(!istype(parent_mob.buckled, /obj/structure/bed/nest)) if(parent_buckle) // Still have a lingering reference somehow? - UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE) parent_buckle = parent_mob.buckled - RegisterSignal(parent_mob.buckled, COSMIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) + RegisterSignal(parent_mob.buckled, COMSIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) return FALSE if(parent_buckle) - UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE) parent_buckle = null if(parent_mob.is_xeno_grabbable()) @@ -282,16 +282,16 @@ return FALSE // Still buckled to the same thing somehow? if(!istype(parent_mob.buckled, /obj/structure/bed/nest)) if(parent_buckle) // Still have a lingering reference somehow? - UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE) parent_buckle = parent_mob.buckled - RegisterSignal(parent_mob.buckled, COSMIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) + RegisterSignal(parent_mob.buckled, COMSIG_OBJ_AFTER_BUCKLE, PROC_REF(on_after_buckle)) return FALSE else parent_nest = parent_mob.buckled RegisterSignal(parent_nest, COMSIG_PARENT_QDELETING, PROC_REF(on_nest_deletion)) if(parent_buckle) - UnregisterSignal(parent_buckle, COSMIG_OBJ_AFTER_BUCKLE) + UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE) parent_buckle = null if(SEND_SIGNAL(parent_mob, COMSIG_ATTEMPT_MOB_PULL) & COMPONENT_CANCEL_MOB_PULL) diff --git a/code/datums/effects/neurotoxin.dm b/code/datums/effects/neurotoxin.dm index 490ed213292b..b7402ca370fd 100644 --- a/code/datums/effects/neurotoxin.dm +++ b/code/datums/effects/neurotoxin.dm @@ -37,6 +37,10 @@ return FALSE if(affected_mob.stat == DEAD) return + + if(issynth(affected_atom)) + return + // General effects affected_mob.last_damage_data = cause_data affected_mob.apply_stamina_damage(stam_dam) diff --git a/code/datums/elements/bullet_trait/iff.dm b/code/datums/elements/bullet_trait/iff.dm index ab48b29f4812..cee36acbed80 100644 --- a/code/datums/elements/bullet_trait/iff.dm +++ b/code/datums/elements/bullet_trait/iff.dm @@ -46,7 +46,7 @@ // The cache is reset when the user drops their ID /datum/element/bullet_trait_iff/proc/get_user_iff_group(mob/living/carbon/human/user) if(!ishuman(user)) - return user.faction_group + return user?.faction_group var/iff_group = LAZYACCESS(iff_group_cache, user) if(isnull(iff_group)) diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index b691d87a2169..6e84052720d4 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -112,6 +112,7 @@ var/paygrade = user.get_paygrade() var/formatted_message = "[paygrade][user] [msg]" var/user_turf = get_turf(user) + var/list/seeing_obj = list() if (user.client) for(var/mob/ghost as anything in GLOB.dead_mob_list) if(!ghost.client || isnewplayer(ghost)) @@ -132,12 +133,18 @@ if(emote_type & EMOTE_VISIBLE) var/list/viewers = get_mobs_in_view(7, user) for(var/mob/current_mob in viewers) + for(var/obj/object in current_mob.contents) + if((object.flags_atom & USES_SEEING)) + seeing_obj |= object if(!(current_mob.client?.prefs.toggles_langchat & LANGCHAT_SEE_EMOTES)) viewers -= current_mob run_langchat(user, viewers) else if(emote_type & EMOTE_AUDIBLE) var/list/heard = get_mobs_in_view(7, user) for(var/mob/current_mob in heard) + for(var/obj/object in current_mob.contents) + if((object.flags_atom & USES_HEARING)) + seeing_obj |= object if(current_mob.ear_deaf) heard -= current_mob continue @@ -145,6 +152,9 @@ heard -= current_mob run_langchat(user, heard) + for(var/obj/object as anything in seeing_obj) + object.see_emote(user, msg, (emote_type & EMOTE_AUDIBLE)) + SEND_SIGNAL(user, COMSIG_MOB_EMOTED(key)) diff --git a/code/datums/entities/player.dm b/code/datums/entities/player.dm index aefa81672b54..a62e663ba21c 100644 --- a/code/datums/entities/player.dm +++ b/code/datums/entities/player.dm @@ -90,11 +90,12 @@ BSQL_PROTECT_DATUM(/datum/entity/player) /datum/entity/player/proc/add_note(note_text, is_confidential, note_category = NOTE_ADMIN, is_ban = FALSE, duration = null) var/client/admin = usr.client // do all checks here, especially for sensitive stuff like this - if(!admin || !admin.player_data) - return FALSE - if(note_category == NOTE_ADMIN || is_confidential) - if (!AHOLD_IS_MOD(admin.admin_holder)) + if(!(note_category == NOTE_WHITELIST)) + if(!admin || !admin.player_data) return FALSE + if(note_category == NOTE_ADMIN || is_confidential) + if (!AHOLD_IS_MOD(admin.admin_holder)) + return FALSE // this is here for a short transition period when we still are testing DB notes and constantly deleting the file if(CONFIG_GET(flag/duplicate_notes_to_file)) @@ -119,7 +120,7 @@ BSQL_PROTECT_DATUM(/datum/entity/player) note.note_category = note_category note.is_ban = is_ban note.ban_time = duration - note.admin_rank = admin.admin_holder.rank + note.admin_rank = admin.admin_holder ? admin.admin_holder.rank : "Non-Staff" // since admin is in game, their player_data has to be populated. This is also checked above note.admin_id = admin.player_data.id note.admin = admin.player_data @@ -134,13 +135,17 @@ BSQL_PROTECT_DATUM(/datum/entity/player) notes.Add(note) return TRUE -/datum/entity/player/proc/remove_note(note_id) +/datum/entity/player/proc/remove_note(note_id, whitelist = FALSE) + if(IsAdminAdvancedProcCall()) + return PROC_BLOCKED var/client/admin = usr.client // do all checks here, especially for sensitive stuff like this if(!admin || !admin.player_data) return FALSE - if (!AHOLD_IS_MOD(admin.admin_holder)) + if((!AHOLD_IS_MOD(admin.admin_holder)) && !whitelist) + return FALSE + if(whitelist && !(isSenator(admin) || CLIENT_HAS_RIGHTS(admin, R_PERMISSIONS))) return FALSE // this is here for a short transition period when we still are testing DB notes and constantly deleting the file diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index 5e57b8f5616c..88785474bc23 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -422,6 +422,10 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list( if(hive && hive.color) holder3.color = hive.color + if(status_flags & CORRUPTED_ALLY) + holder4.color = "#80ff80" + holder4.icon_state = "hudalien_ally" + if(stat == DEAD || status_flags & FAKEDEATH) if(revive_enabled) if(!client) diff --git a/code/datums/skills/uscm.dm b/code/datums/skills/uscm.dm index 1e0dedf5dd05..9c56e7f62a88 100644 --- a/code/datums/skills/uscm.dm +++ b/code/datums/skills/uscm.dm @@ -239,7 +239,8 @@ COMMAND STAFF SKILL_JTAC = SKILL_JTAC_MASTER, SKILL_SPEC_WEAPONS = SKILL_SPEC_ALL, SKILL_EXECUTION = SKILL_EXECUTION_TRAINED, //can BE people - SKILL_INTEL = SKILL_INTEL_EXPERT + SKILL_INTEL = SKILL_INTEL_EXPERT, + SKILL_VEHICLE = SKILL_VEHICLE_LARGE, ) /datum/skills/commander @@ -261,7 +262,8 @@ COMMAND STAFF SKILL_JTAC = SKILL_JTAC_MASTER, SKILL_EXECUTION = SKILL_EXECUTION_TRAINED, //can BE people SKILL_INTEL = SKILL_INTEL_EXPERT, - SKILL_NAVIGATIONS = SKILL_NAVIGATIONS_TRAINED //can change ship alt + SKILL_NAVIGATIONS = SKILL_NAVIGATIONS_TRAINED, //can change ship alt + SKILL_VEHICLE = SKILL_VEHICLE_LARGE, ) /datum/skills/XO @@ -282,6 +284,7 @@ COMMAND STAFF SKILL_JTAC = SKILL_JTAC_MASTER, SKILL_INTEL = SKILL_INTEL_EXPERT, SKILL_NAVIGATIONS = SKILL_NAVIGATIONS_TRAINED, + SKILL_VEHICLE = SKILL_VEHICLE_LARGE, ) /datum/skills/SO @@ -299,6 +302,7 @@ COMMAND STAFF SKILL_POWERLOADER = SKILL_POWERLOADER_TRAINED, SKILL_JTAC = SKILL_JTAC_EXPERT, SKILL_INTEL = SKILL_INTEL_TRAINED, + SKILL_VEHICLE = SKILL_VEHICLE_LARGE, ) /datum/skills/SEA diff --git a/code/datums/skills/wygoons.dm b/code/datums/skills/wygoons.dm new file mode 100644 index 000000000000..2d2c247bd1ea --- /dev/null +++ b/code/datums/skills/wygoons.dm @@ -0,0 +1,36 @@ +/datum/skills/wy_goon + name = "Corporate Security" + skills = list( + SKILL_CQC = SKILL_CQC_SKILLED, + SKILL_POLICE = SKILL_POLICE_SKILLED, + SKILL_FIREMAN = SKILL_FIREMAN_SKILLED, + SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED, + SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED, + ) + +/datum/skills/wy_goon_tech + name = "Corporate Security Support Technician" + skills = list( + SKILL_CQC = SKILL_CQC_SKILLED, + SKILL_POLICE = SKILL_POLICE_SKILLED, + SKILL_FIREMAN = SKILL_FIREMAN_TRAINED, + SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED, + SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED, + SKILL_MEDICAL = SKILL_MEDICAL_TRAINED, + SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI, + SKILL_ENGINEER = SKILL_ENGINEER_ENGI, + ) + +/datum/skills/wy_goon_lead + name = "Corporate Security Leader" + skills = list( + SKILL_CQC = SKILL_CQC_SKILLED, + SKILL_POLICE = SKILL_POLICE_SKILLED, + SKILL_FIREMAN = SKILL_FIREMAN_SKILLED, + SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED, + SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED, + SKILL_MEDICAL = SKILL_MEDICAL_TRAINED, + SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI, + SKILL_ENGINEER = SKILL_ENGINEER_ENGI, + SKILL_LEADERSHIP = SKILL_LEAD_TRAINED, + ) diff --git a/code/datums/supply_packs/ammo.dm b/code/datums/supply_packs/ammo.dm index 0929f24f7c95..2e81d8fed164 100644 --- a/code/datums/supply_packs/ammo.dm +++ b/code/datums/supply_packs/ammo.dm @@ -135,7 +135,7 @@ group = "Ammo" /datum/supply_packs/ammo_m4ra_mag_box_ap - name = "Magazine box (MRRA, 16x AP mags)" + name = "Magazine box (M4RA, 16x AP mags)" contains = list( /obj/item/ammo_box/magazine/m4ra/ap, ) diff --git a/code/datums/supply_packs/vehicle_ammo.dm b/code/datums/supply_packs/vehicle_ammo.dm index 5dad91d27ed4..43ce36ec2b64 100644 --- a/code/datums/supply_packs/vehicle_ammo.dm +++ b/code/datums/supply_packs/vehicle_ammo.dm @@ -148,3 +148,15 @@ containertype = /obj/structure/closet/crate/ammo containername = "M-87F Flare Launcher ammo crate" group = "Vehicle Ammo" + +/datum/supply_packs/ammo_arcsentry + name = "RE700 Rotary Cannon magazines (x3)" + contains = list( + /obj/item/ammo_magazine/hardpoint/arc_sentry, + /obj/item/ammo_magazine/hardpoint/arc_sentry, + /obj/item/ammo_magazine/hardpoint/arc_sentry, + ) + cost = 20 + containertype = /obj/structure/closet/crate/ammo + containername = "RE700 Rotary Cannon ammo crate" + group = "Vehicle Ammo" diff --git a/code/datums/supply_packs/vehicle_equipment.dm b/code/datums/supply_packs/vehicle_equipment.dm new file mode 100644 index 000000000000..df106761d467 --- /dev/null +++ b/code/datums/supply_packs/vehicle_equipment.dm @@ -0,0 +1,9 @@ +/datum/supply_packs/arcsentry_replacement + name = "Replacement RE700 Rotary Cannon (x1)" + contains = list( + /obj/item/hardpoint/primary/arc_sentry, + ) + cost = 25 + containertype = /obj/structure/closet/crate/weapon + containername = "RE700 Rotary Cannon crate" + group = "Vehicle Equipment" diff --git a/code/datums/tutorial/xenomorph/xenomorph_basic.dm b/code/datums/tutorial/xenomorph/xenomorph_basic.dm index 965f7b55d3c0..276d2ac824f0 100644 --- a/code/datums/tutorial/xenomorph/xenomorph_basic.dm +++ b/code/datums/tutorial/xenomorph/xenomorph_basic.dm @@ -160,7 +160,16 @@ add_highlight(hugger, COLOR_YELLOW) message_to_player("This is a facehugger, highlighted in yellow. Pick up the facehugger by clicking it.") message_to_player("Stand next to the downed human and click them to apply the facehugger. Or drop the facehugger near them to see it leap onto their face automatically.") - RegisterSignal(human_dummy, COMSIG_HUMAN_IMPREGNATE, PROC_REF(nest_cap_phase)) + RegisterSignal(hugger, COMSIG_PARENT_QDELETING, PROC_REF(on_hugger_deletion)) + RegisterSignal(human_dummy, COMSIG_HUMAN_IMPREGNATE, PROC_REF(nest_cap_phase), override = TRUE) + +/datum/tutorial/xenomorph/basic/proc/on_hugger_deletion(hugger) + SIGNAL_HANDLER + TUTORIAL_ATOM_FROM_TRACKING(/obj/effect/alien/resin/special/eggmorph, morpher) + morpher.stored_huggers = 1 + add_highlight(morpher, COLOR_YELLOW) + message_to_player("Click the egg morpher to take a facehugger.") + RegisterSignal(xeno, COMSIG_XENO_TAKE_HUGGER_FROM_MORPHER, PROC_REF(take_facehugger_phase)) /datum/tutorial/xenomorph/basic/proc/nest_cap_phase() SIGNAL_HANDLER @@ -168,6 +177,7 @@ TUTORIAL_ATOM_FROM_TRACKING(/obj/item/clothing/mask/facehugger, hugger) UnregisterSignal(human_dummy, COMSIG_MOB_TAKE_DAMAGE) UnregisterSignal(human_dummy, COMSIG_HUMAN_IMPREGNATE) + UnregisterSignal(hugger, COMSIG_PARENT_QDELETING) remove_highlight(hugger) message_to_player("We should nest the infected human to make sure they don't get away.") diff --git a/code/datums/vehicles.dm b/code/datums/vehicles.dm index 36ac96938c6b..67070dd04c0b 100644 --- a/code/datums/vehicles.dm +++ b/code/datums/vehicles.dm @@ -37,3 +37,7 @@ /datum/map_template/interior/van name = "Van" interior_id = "van" + +/datum/map_template/interior/arc + name = "ARC" + interior_id = "arc" diff --git a/code/defines/procs/announcement.dm b/code/defines/procs/announcement.dm index 2ebba6a774e8..bad07104db22 100644 --- a/code/defines/procs/announcement.dm +++ b/code/defines/procs/announcement.dm @@ -42,14 +42,19 @@ continue if(is_mainship_level(H.z)) // People on ship see everything continue + + // If they have iff AND a marine headset they will recieve announcements + if ((FACTION_MARINE in H.wear_id?.faction_group) && (istype(H.wear_l_ear, /obj/item/device/radio/headset/almayer) || istype(H.wear_r_ear, /obj/item/device/radio/headset/almayer))) + continue + if((H.faction != faction_to_display && !add_PMCs) || (H.faction != faction_to_display && add_PMCs && !(H.faction in FACTION_LIST_WY)) && !(faction_to_display in H.faction_group)) //faction checks targets.Remove(H) switch(logging) if(ARES_LOG_MAIN) - log_ares_announcement(title, message) + log_ares_announcement(title, message, signature) if(ARES_LOG_SECURITY) - log_ares_security(title, message) + log_ares_security(title, message, signature) else if(faction_to_display == "Everyone (-Yautja)") for(var/mob/M in targets) @@ -98,9 +103,9 @@ switch(logging) if(ARES_LOG_MAIN) - log_ares_announcement("[MAIN_AI_SYSTEM] Comms Update", message) + log_ares_announcement("Comms Update", message, MAIN_AI_SYSTEM) if(ARES_LOG_SECURITY) - log_ares_security("[MAIN_AI_SYSTEM] Security Update", message) + log_ares_security("Security Update", message, MAIN_AI_SYSTEM) /proc/ai_silent_announcement(message, channel_prefix, bypass_cooldown = FALSE) if(!message) @@ -133,9 +138,9 @@ message += "

Signed by,
[signature]
" switch(ares_logging) if(ARES_LOG_MAIN) - log_ares_announcement(title, message) + log_ares_announcement(title, message, signature) if(ARES_LOG_SECURITY) - log_ares_security(title, message) + log_ares_security(title, message, signature) announcement_helper(message, title, targets, sound_to_play) @@ -148,7 +153,7 @@ if(!ishuman(T) || isyautja(T) || !is_mainship_level((get_turf(T))?.z)) targets.Remove(T) - log_ares_announcement("[title] Shipwide Update", message) + log_ares_announcement("Shipwide Update", message, title) announcement_helper(message, title, targets, sound_to_play) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 21f7b6b0a9be..52a35b715b1a 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -45,7 +45,10 @@ if(orbiting) orbiting.end_orbit(src) orbiting = null - vis_contents.Cut() + + vis_locs = null //clears this atom out of all viscontents + if(length(vis_contents)) + vis_contents.Cut() . = ..() moveToNullspace() //so we move into null space. Must be after ..() b/c atom's Dispose handles deleting our lighting stuff diff --git a/code/game/cas_manager/datums/cas_fire_envelope.dm b/code/game/cas_manager/datums/cas_fire_envelope.dm index cc38b034c764..864d7f23a3e8 100644 --- a/code/game/cas_manager/datums/cas_fire_envelope.dm +++ b/code/game/cas_manager/datums/cas_fire_envelope.dm @@ -3,7 +3,10 @@ var/list/datum/cas_fire_mission/missions var/fire_length var/grace_period //how much time you have after initiating fire mission and before you can't change firemissions - var/flyto_period //how much time it takes from sound alarm start to first hit. CAS is vulnerable here + var/first_warning + var/second_warning + var/third_warning + var/execution_start var/flyoff_period //how much time it takes after shots fired to get off the map. CAS is vulnerable here var/cooldown_period //how much time you have to wait before new Fire Mission run var/soundeffect //what sound effect to play @@ -36,10 +39,6 @@ for(var/datum/cas_fire_mission/mission in missions) .["missions"] += list(mission.ui_data(user)) - -/datum/cas_fire_envelope/proc/get_total_duration() - return grace_period+flyto_period+flyoff_period - /datum/cas_fire_envelope/proc/update_weapons(list/obj/structure/dropship_equipment/weapon/weapons) for(var/datum/cas_fire_mission/mission in missions) mission.update_weapons(weapons, fire_length) @@ -242,14 +241,60 @@ /datum/cas_fire_envelope/proc/check_firemission_loc(datum/cas_signal/target_turf) return TRUE //redefined in child class -/** - * Execute firemission. - */ +/// Step 1: Sets the stat to FIRE_MISSION_STATE_ON_TARGET and starts the sound effect for the fire mission. +/datum/cas_fire_envelope/proc/play_sound(atom/target_turf) + stat = FIRE_MISSION_STATE_ON_TARGET + change_current_loc(target_turf) + playsound(target_turf, soundeffect, vol = 70, vary = TRUE, sound_range = 50, falloff = 8) + +/// Step 2, 3, 4: Warns nearby mobs of the incoming fire mission. Warning as 1 is non-precise, whereas 2 and 3 are precise. +/datum/cas_fire_envelope/proc/chat_warning(atom/target_turf, range = 10, warning_number = 1) + var/ds_identifier = "LARGE BIRD" + var/fm_identifier = "SPIT FIRE" + var/relative_dir + for(var/mob/mob in range(15, target_turf)) + if (mob.mob_flags & KNOWS_TECHNOLOGY) + ds_identifier = "DROPSHIP" + fm_identifier = "FIRE" + if(get_turf(mob) == target_turf) + relative_dir = 0 + else + relative_dir = Get_Compass_Dir(mob, target_turf) + switch(warning_number) + if(1) + mob.show_message( \ + SPAN_HIGHDANGER("YOU HEAR THE [ds_identifier] ROAR AS IT PREPARES TO [fm_identifier] NEAR YOU!"),SHOW_MESSAGE_VISIBLE, \ + SPAN_HIGHDANGER("YOU HEAR SOMETHING FLYING CLOSER TO YOU!") , SHOW_MESSAGE_AUDIBLE \ + ) + if(2) + mob.show_message( \ + SPAN_HIGHDANGER("A [ds_identifier] FLIES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \ + SPAN_HIGHDANGER("YOU HEAR SOMETHING GO [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \ + ) + if(3) + mob.show_message( \ + SPAN_HIGHDANGER("A [ds_identifier] FLIES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \ + SPAN_HIGHDANGER("YOU HEAR SOMETHING GO [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \ + ) + +/// Step 5: Actually executes the fire mission updating stat to FIRE_MISSION_STATE_FIRING and then FIRE_MISSION_STATE_OFF_TARGET +/datum/cas_fire_envelope/proc/open_fire(atom/target_turf,datum/cas_fire_mission/mission,dir) + stat = FIRE_MISSION_STATE_FIRING + mission.execute_firemission(linked_console, target_turf, dir, fire_length, step_delay, src) + stat = FIRE_MISSION_STATE_OFF_TARGET + +/// Step 6: Sets the fire mission stat to FIRE_MISSION_STATE_COOLDOWN +/datum/cas_fire_envelope/proc/flyoff() + stat = FIRE_MISSION_STATE_COOLDOWN + +/// Step 7: Sets the fire mission stat to FIRE_MISSION_STATE_IDLE +/datum/cas_fire_envelope/proc/end_cooldown() + stat = FIRE_MISSION_STATE_IDLE + + /datum/cas_fire_envelope/proc/execute_firemission_unsafe(datum/cas_signal/signal, turf/target_turf, dir, datum/cas_fire_mission/mission) stat = FIRE_MISSION_STATE_IN_TRANSIT to_chat(usr, SPAN_ALERT("Firemission underway!")) - sleep(grace_period) - stat = FIRE_MISSION_STATE_ON_TARGET if(!target_turf) stat = FIRE_MISSION_STATE_IDLE mission_error = "Target Lost." @@ -258,29 +303,27 @@ stat = FIRE_MISSION_STATE_IDLE mission_error = "Target is off bounds or obstructed." return - change_current_loc(target_turf) - playsound(source = target_turf, soundin = soundeffect, vol = 70, vary = TRUE, sound_range = 50, falloff = 8) - for(var/mob/mob in range(15, target_turf)) - var/ds_identifier = "LARGE BIRD" - var/fm_identifier = "SPIT FIRE" - if (mob.mob_flags & KNOWS_TECHNOLOGY) - ds_identifier = "DROPSHIP" - fm_identifier = "FIRE" + var/obj/effect/firemission_effect = new(target_turf) - mob.show_message( \ - SPAN_HIGHDANGER("YOU HEAR THE [ds_identifier] ROAR AS IT PREPARES TO [fm_identifier] NEAR YOU!"),SHOW_MESSAGE_VISIBLE, \ - SPAN_HIGHDANGER("YOU HEAR SOMETHING FLYING CLOSER TO YOU!") , SHOW_MESSAGE_AUDIBLE \ - ) + firemission_effect.icon = 'icons/obj/items/weapons/projectiles.dmi' + firemission_effect.icon_state = "laser_target2" + firemission_effect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + firemission_effect.invisibility = INVISIBILITY_MAXIMUM + QDEL_IN(firemission_effect, 12 SECONDS) - sleep(flyto_period) - stat = FIRE_MISSION_STATE_FIRING - mission.execute_firemission(linked_console, target_turf, dir, fire_length, step_delay, src) - stat = FIRE_MISSION_STATE_OFF_TARGET - sleep(flyoff_period) - stat = FIRE_MISSION_STATE_COOLDOWN - sleep(cooldown_period) - stat = FIRE_MISSION_STATE_IDLE + + notify_ghosts(header = "CAS Fire Mission", message = "[usr ? usr : "Someone"] is launching Fire Mission '[mission.name]' at [get_area(target_turf)].", source = firemission_effect) + msg_admin_niche("[usr ? key_name(usr) : "Someone"] is launching Fire Mission '[mission.name]' at ([target_turf.x],[target_turf.y],[target_turf.z]) [ADMIN_JMP(target_turf)]") + + + addtimer(CALLBACK(src, PROC_REF(play_sound), target_turf), grace_period) + addtimer(CALLBACK(src, PROC_REF(chat_warning), target_turf, 15, 1), first_warning) + addtimer(CALLBACK(src, PROC_REF(chat_warning), target_turf, 15, 2), second_warning) + addtimer(CALLBACK(src, PROC_REF(chat_warning), target_turf, 10, 3), third_warning) + addtimer(CALLBACK(src, PROC_REF(open_fire), target_turf, mission,dir), execution_start) + addtimer(CALLBACK(src, PROC_REF(flyoff)), flyoff_period) + addtimer(CALLBACK(src, PROC_REF(end_cooldown)), cooldown_period) /** * Change attack vector for firemission @@ -324,10 +367,13 @@ /datum/cas_fire_envelope/uscm_dropship fire_length = 12 - grace_period = 5 SECONDS - flyto_period = 4 SECONDS //sleep in the FM itself has been increased by one more second - flyoff_period = 5 SECONDS - cooldown_period = 10 SECONDS + grace_period = 5 SECONDS + first_warning = 6 SECONDS + second_warning = 8 SECONDS + third_warning = 9 SECONDS + execution_start = 10 SECONDS + flyoff_period = 15 SECONDS + cooldown_period = 25 SECONDS soundeffect = 'sound/weapons/dropship_sonic_boom.ogg' //BOOM~WOOOOOSH~HSOOOOOW~BOOM step_delay = 3 max_offset = 12 diff --git a/code/game/cas_manager/datums/cas_fire_mission.dm b/code/game/cas_manager/datums/cas_fire_mission.dm index 927dded210f0..dc55e057edcd 100644 --- a/code/game/cas_manager/datums/cas_fire_mission.dm +++ b/code/game/cas_manager/datums/cas_fire_mission.dm @@ -164,51 +164,6 @@ if(initial_turf == null || check(linked_console) != FIRE_MISSION_ALL_GOOD) return FIRE_MISSION_NOT_EXECUTABLE - var/obj/effect/firemission_effect = new(initial_turf) - - firemission_effect.icon = 'icons/obj/items/weapons/projectiles.dmi' - firemission_effect.icon_state = "laser_target2" - firemission_effect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT - firemission_effect.invisibility = INVISIBILITY_MAXIMUM - QDEL_IN(firemission_effect, 5 SECONDS) - - notify_ghosts(header = "CAS Fire Mission", message = "[usr ? usr : "Someone"] is launching Fire Mission '[name]' at [get_area(initial_turf)].", source = firemission_effect) - msg_admin_niche("[usr ? key_name(usr) : "Someone"] is launching Fire Mission '[name]' at ([initial_turf.x],[initial_turf.y],[initial_turf.z]) [ADMIN_JMP(initial_turf)]") - - var/relative_dir - for(var/mob/mob in range(15, initial_turf)) - if(get_turf(mob) == initial_turf) - relative_dir = 0 - else - relative_dir = Get_Compass_Dir(mob, initial_turf) - - var/ds_identifier = "LARGE BIRD" - if (mob.mob_flags & KNOWS_TECHNOLOGY) - ds_identifier = "DROPSHIP" - - mob.show_message( \ - SPAN_HIGHDANGER("A [ds_identifier] FLIES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \ - SPAN_HIGHDANGER("YOU HEAR SOMETHING GO [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \ - ) - - // Xenos have time to react to the first message - sleep(1.5 SECONDS) - - for(var/mob/mob in range(10, initial_turf)) - if(get_turf(mob) == initial_turf) - relative_dir = 0 - else - relative_dir = Get_Compass_Dir(mob, initial_turf) - - var/ds_identifier = "LARGE BIRD" - if (mob.mob_flags & KNOWS_TECHNOLOGY) - ds_identifier = "DROPSHIP" - - mob.show_message( \ - SPAN_HIGHDANGER("A [ds_identifier] FIRES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), 1, \ - SPAN_HIGHDANGER("YOU HEAR SOMETHING FIRE [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), 2 \ - ) - var/turf/current_turf = initial_turf var/tally_step = steps / mission_length //how much shots we need before moving to next turf var/next_step = tally_step //when we move to next turf diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 09db84fec2c2..8cd91a494c83 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -24,6 +24,8 @@ if(isSenator(src)) add_verb(src, /client/proc/whitelist_panel) + if(isCouncil(src)) + add_verb(src, /client/proc/other_records) /client var/datum/whitelist_panel/wl_panel @@ -144,8 +146,10 @@ GLOBAL_LIST_INIT(misc_flags, list( /datum/whitelist_panel/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) - return + return FALSE var/mob/user = ui.user + if(!isSenator(user.client) && !CLIENT_HAS_RIGHTS(user.client, R_PERMISSIONS)) + return FALSE switch(action) if("go_back") go_back() @@ -165,6 +169,7 @@ GLOBAL_LIST_INIT(misc_flags, list( return var/datum/entity/player/player = get_player_from_key(player_key) player.set_whitelist_status(new_rights) + player.add_note("Whitelists updated by [user.key]. Reason: '[reason]'.", FALSE, NOTE_WHITELIST) to_chat(user, SPAN_HELPFUL("Whitelists for [player_key] updated.")) message_admins("Whitelists for [player_key] updated by [key_name(user)]. Reason: '[reason]'.") log_admin("WHITELISTS: Flags for [player_key] changed from [target_rights] to [new_rights]. Reason: '[reason]'.") diff --git a/code/game/machinery/ARES/ARES_interface.dm b/code/game/machinery/ARES/ARES_interface.dm index 6cc7c220fd04..04547d079664 100644 --- a/code/game/machinery/ARES/ARES_interface.dm +++ b/code/game/machinery/ARES/ARES_interface.dm @@ -368,6 +368,10 @@ new_title = "[record.title] at [record.time]" new_details = record.details datacore.records_tech -= record + if(ARES_RECORD_FLIGHT) + new_title = "[record.title] at [record.time]" + new_details = record.details + datacore.records_flight -= record new_delete.details = new_details new_delete.user = last_login @@ -416,7 +420,7 @@ shipwide_ai_announcement("ATTENTION! GENERAL QUARTERS. ALL HANDS, MAN YOUR BATTLESTATIONS.", MAIN_AI_SYSTEM, 'sound/effects/GQfullcall.ogg') log_game("[key_name(user)] has called for general quarters via ARES.") message_admins("[key_name_admin(user)] has called for general quarters via ARES.") - log_ares_security("General Quarters", "[last_login] has called for general quarters via ARES.") + log_ares_security("General Quarters", "Called for general quarters via ARES.", last_login) COOLDOWN_START(datacore, ares_quarters_cooldown, 10 MINUTES) . = TRUE @@ -438,7 +442,7 @@ log_game("[key_name(user)] has called for an emergency evacuation via ARES.") message_admins("[key_name_admin(user)] has called for an emergency evacuation via ARES.") - log_ares_security("Initiate Evacuation", "[last_login] has called for an emergency evacuation via ARES.") + log_ares_security("Initiate Evacuation", "Called for an emergency evacuation via ARES.", last_login) . = TRUE if("distress") @@ -492,7 +496,7 @@ playsound_client(admin,'sound/effects/sos-morse-code.ogg',10) message_admins("[key_name(user)] has requested use of Nuclear Ordnance (via ARES)! Reason: [reason] [CC_MARK(user)] (APPROVE) (DENY) [ADMIN_JMP_USER(user)] [CC_REPLY(user)]") to_chat(user, SPAN_NOTICE("A nuclear ordnance request has been sent to USCM High Command for the following reason: [reason]")) - log_ares_security("Nuclear Ordnance Request", "[last_login] has sent a request for nuclear ordnance for the following reason: [reason]") + log_ares_security("Nuclear Ordnance Request", "Sent a request for nuclear ordnance for the following reason: [reason]", last_login) if(ares_can_interface()) ai_silent_announcement("[last_login] has sent a request for nuclear ordnance to USCM High Command.", ".V") ai_silent_announcement("Reason given: [reason].", ".V") @@ -514,9 +518,16 @@ playsound(src, 'sound/machines/chime.ogg', 15, 1) COOLDOWN_START(sec_vent, vent_trigger_cooldown, COOLDOWN_ARES_VENT) ares_apollo_talk("Nerve Gas release imminent from [sec_vent.vent_tag].") - log_ares_security("Nerve Gas Release", "[last_login] released Nerve Gas from Vent '[sec_vent.vent_tag]'.") + log_ares_security("Nerve Gas Release", "Released Nerve Gas from Vent '[sec_vent.vent_tag]'.", last_login) sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS) log_admin("[key_name(user)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + if("security_lockdown") + if(!COOLDOWN_FINISHED(datacore, aicore_lockdown)) + to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(datacore, aicore_lockdown)] seconds!")) + return FALSE + aicore_lockdown(user) + return TRUE + if(playsound) playsound(src, "keyboard_alt", 15, 1) diff --git a/code/game/machinery/ARES/ARES_interface_admin.dm b/code/game/machinery/ARES/ARES_interface_admin.dm index 586b01a51af9..758ba9fbb5e7 100644 --- a/code/game/machinery/ARES/ARES_interface_admin.dm +++ b/code/game/machinery/ARES/ARES_interface_admin.dm @@ -511,6 +511,6 @@ playsound(src, 'sound/machines/chime.ogg', 15, 1) COOLDOWN_START(sec_vent, vent_trigger_cooldown, COOLDOWN_ARES_VENT) ares_apollo_talk("Nerve Gas release imminent from [sec_vent.vent_tag].") - log_ares_security("Nerve Gas Release", "[MAIN_AI_SYSTEM] released Nerve Gas from Vent '[sec_vent.vent_tag]'.") + log_ares_security("Nerve Gas Release", "Released Nerve Gas from Vent '[sec_vent.vent_tag]'.", MAIN_AI_SYSTEM) sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS) log_admin("[key_name(user)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") diff --git a/code/game/machinery/ARES/ARES_interface_apollo.dm b/code/game/machinery/ARES/ARES_interface_apollo.dm index 48fcad588574..243ecdf1355f 100644 --- a/code/game/machinery/ARES/ARES_interface_apollo.dm +++ b/code/game/machinery/ARES/ARES_interface_apollo.dm @@ -158,29 +158,29 @@ return var/playsound = TRUE - var/mob/living/carbon/human/operator = ui.user + var/mob/living/carbon/human/user = ui.user switch (action) if("go_back") if(!last_menu) - return to_chat(operator, SPAN_WARNING("Error, no previous page detected.")) + return to_chat(user, SPAN_WARNING("Error, no previous page detected.")) var/temp_holder = current_menu current_menu = last_menu last_menu = temp_holder if("login") - var/obj/item/card/id/idcard = operator.get_active_hand() + var/obj/item/card/id/idcard = user.get_active_hand() if(istype(idcard)) authentication = get_ares_access(idcard) last_login = idcard.registered_name - else if(operator.wear_id) - idcard = operator.wear_id + else if(user.wear_id) + idcard = user.wear_id if(istype(idcard)) authentication = get_ares_access(idcard) last_login = idcard.registered_name else - to_chat(operator, SPAN_WARNING("You require an ID card to access this terminal!")) + to_chat(user, SPAN_WARNING("You require an ID card to access this terminal!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(authentication) @@ -222,23 +222,23 @@ if("new_report") 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) + var/maint_type = tgui_input_list(user, "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(operator, "What are the details for this report?", "Ticket Details", encode = FALSE) + var/details = tgui_input_text(user, "What are the details for this report?", "Ticket Details", encode = FALSE) if(!details) return FALSE if((authentication >= APOLLO_ACCESS_REPORTER) && !priority_report) - var/is_priority = tgui_alert(operator, "Is this a priority report?", "Priority designation", list("Yes", "No")) + var/is_priority = tgui_alert(user, "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") + var/confirm = alert(user, "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, maint_type, details, priority_report) @@ -247,7 +247,7 @@ ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.") else send_notifcation() - log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(operator)] as [last_login] with Category '[maint_type]' and Details of '[details]'.") + log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(user)] as [last_login] with Category '[maint_type]' and Details of '[details]'.") return TRUE return FALSE @@ -259,14 +259,14 @@ var/assigned = ticket.ticket_assignee if(assigned) if(assigned == last_login) - var/prompt = tgui_alert(operator, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No")) + var/prompt = tgui_alert(user, "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(operator, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No")) + var/choice = tgui_alert(user, "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) @@ -279,9 +279,9 @@ if(!istype(ticket)) return FALSE if(ticket.ticket_submitter != last_login) - to_chat(operator, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!")) + to_chat(user, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!")) return FALSE - to_chat(operator, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled.")) + to_chat(user, 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.") @@ -294,9 +294,9 @@ if(!istype(ticket)) return FALSE if(ticket.ticket_assignee != last_login && ticket.ticket_assignee) //must be claimed by you or unclaimed.) - to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) return FALSE - var/choice = tgui_alert(operator, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS) + var/choice = tgui_alert(user, "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 @@ -308,39 +308,39 @@ ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by [last_login].") else send_notifcation() - to_chat(operator, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) + to_chat(user, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) return TRUE if("new_access") - var/obj/item/card/id/idcard = operator.get_active_hand() + var/obj/item/card/id/idcard = user.get_active_hand() var/has_id = FALSE if(istype(idcard)) has_id = TRUE - else if(operator.wear_id) - idcard = operator.wear_id + else if(user.wear_id) + idcard = user.wear_id if(istype(idcard)) has_id = TRUE if(!has_id) - to_chat(operator, SPAN_WARNING("You require an ID card to request an access ticket!")) + to_chat(user, SPAN_WARNING("You require an ID card to request an access ticket!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(idcard.registered_name != last_login) - to_chat(operator, SPAN_WARNING("This ID card does not match the active login!")) + to_chat(user, SPAN_WARNING("This ID card does not match the active login!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE - var/details = tgui_input_text(operator, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE) + var/details = tgui_input_text(user, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE) if(!details) return FALSE - var/confirm = alert(operator, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No") + var/confirm = alert(user, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No") if(confirm != "Yes" || !link) return FALSE var/datum/ares_ticket/access/access_ticket = new(last_login, details, FALSE, idcard.registered_gid) link.waiting_ids += idcard link.tickets_access += access_ticket - log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(operator)] as [last_login] with Details of '[details]'.") - message_admins(SPAN_STAFF_IC("[key_name_admin(operator)] created a new ARES Access Ticket."), 1) + log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(user)] as [last_login] with Details of '[details]'.") + message_admins(SPAN_STAFF_IC("[key_name_admin(user)] created a new ARES Access Ticket."), 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] requesting access for '[details].") return TRUE @@ -361,9 +361,9 @@ access_ticket.ticket_status = TICKET_RETURNED identification.access -= ACCESS_MARINE_AI_TEMP - identification.modification_log += "Temporary AI Access self-returned by [key_name(operator)]." + identification.modification_log += "Temporary AI Access self-returned by [key_name(user)]." - to_chat(operator, SPAN_NOTICE("Temporary Access Ticket surrendered.")) + to_chat(user, SPAN_NOTICE("Temporary Access Ticket surrendered.")) playsound(src, 'sound/machines/chime.ogg', 15, 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] surrendered their access.") @@ -372,7 +372,7 @@ datacore.apollo_login_list += "[last_login] at [worldtime2text()], Surrendered Temporary Access Ticket." return TRUE - to_chat(operator, SPAN_WARNING("This ID card does not have an access ticket!")) + to_chat(user, SPAN_WARNING("This ID card does not have an access ticket!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE @@ -384,7 +384,7 @@ for(var/obj/item/card/id/identification in link.waiting_ids) if(identification.registered_gid != access_ticket.user_id_num) continue - identification.handle_ares_access(last_login, operator) + identification.handle_ares_access(last_login, user) access_ticket.ticket_status = TICKET_GRANTED playsound(src, 'sound/machines/chime.ogg', 15, 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] was granted access by [last_login].") @@ -392,7 +392,7 @@ for(var/obj/item/card/id/identification in link.active_ids) if(identification.registered_gid != access_ticket.user_id_num) continue - identification.handle_ares_access(last_login, operator) + identification.handle_ares_access(last_login, user) access_ticket.ticket_status = TICKET_REVOKED playsound(src, 'sound/machines/chime.ogg', 15, 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] had access revoked by [last_login].") @@ -404,10 +404,10 @@ if(!istype(access_ticket)) return FALSE if(access_ticket.ticket_assignee != last_login && access_ticket.ticket_assignee) //must be claimed by you or unclaimed.) - to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) return FALSE access_ticket.ticket_status = TICKET_REJECTED - to_chat(operator, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as rejected.")) + to_chat(user, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as rejected.")) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] was rejected access by [last_login].") for(var/obj/item/card/id/identification in link.waiting_ids) if(identification.registered_gid != access_ticket.user_id_num) @@ -422,36 +422,41 @@ playsound = FALSE var/obj/structure/pipes/vents/pump/no_boom/gas/sec_vent = locate(params["vent"]) if(!istype(sec_vent) || sec_vent.welded) - to_chat(operator, SPAN_WARNING("ERROR: Gas release failure.")) + to_chat(user, SPAN_WARNING("ERROR: Gas release failure.")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(!COOLDOWN_FINISHED(sec_vent, vent_trigger_cooldown)) - to_chat(operator, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent.")) + to_chat(user, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent.")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE - to_chat(operator, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag].")) + to_chat(user, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag].")) playsound(src, 'sound/machines/chime.ogg', 15, 1) COOLDOWN_START(sec_vent, vent_trigger_cooldown, COOLDOWN_ARES_VENT) ares_apollo_talk("Nerve Gas release imminent from [sec_vent.vent_tag].") - log_ares_security("Nerve Gas Release", "[last_login] released Nerve Gas from Vent '[sec_vent.vent_tag]'.") + log_ares_security("Nerve Gas Release", "Released Nerve Gas from Vent '[sec_vent.vent_tag]'.", last_login) sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS) - log_admin("[key_name(operator)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + log_admin("[key_name(user)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + + if("security_lockdown") + if(!COOLDOWN_FINISHED(datacore, aicore_lockdown)) + to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(datacore, aicore_lockdown)] seconds!")) + return FALSE + aicore_lockdown(user) + return TRUE if(playsound) playsound(src, "keyboard_alt", 15, 1) /obj/item/card/id/proc/handle_ares_access(logged_in = MAIN_AI_SYSTEM, mob/user) - var/operator = key_name(user) + var/changer = logged_in + if(user) + changer = key_name(user) var/datum/ares_link/link = GLOB.ares_link - if(logged_in == MAIN_AI_SYSTEM) - if(!user) - operator = "[MAIN_AI_SYSTEM] (Automated)" - else - operator = "[user.ckey]/([MAIN_AI_SYSTEM])" + if(ACCESS_MARINE_AI_TEMP in access) access -= ACCESS_MARINE_AI_TEMP link.active_ids -= src - modification_log += "Temporary AI access revoked by [operator]" + log_idmod(src, "Temporary AI access revoked by [logged_in]", changer) to_chat(user, SPAN_NOTICE("Access revoked from [registered_name].")) var/mob/living/carbon/human/id_owner = registered_ref?.resolve() if(id_owner) @@ -459,7 +464,7 @@ playsound_client(id_owner?.client, 'sound/machines/pda_ping.ogg', src, 25, 0) else access += ACCESS_MARINE_AI_TEMP - modification_log += "Temporary AI access granted by [operator]" + log_idmod(src, "Temporary AI access granted by [logged_in]", changer) to_chat(user, SPAN_NOTICE("Access granted to [registered_name].")) link.waiting_ids -= src link.active_ids += src diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm index 05f110ec1a0c..ef1b836a3d4b 100644 --- a/code/game/machinery/ARES/ARES_procs.dm +++ b/code/game/machinery/ARES/ARES_procs.dm @@ -106,9 +106,13 @@ GLOBAL_LIST_INIT(maintenance_categories, list( /// Is nuke request usable or not? var/nuke_available = TRUE + /// Status of the AI Core Lockdown + var/ai_lockdown_active = FALSE + COOLDOWN_DECLARE(ares_distress_cooldown) COOLDOWN_DECLARE(ares_nuclear_cooldown) COOLDOWN_DECLARE(ares_quarters_cooldown) + COOLDOWN_DECLARE(aicore_lockdown) // ------ ARES Logging Procs ------ // /proc/ares_is_active() @@ -171,11 +175,14 @@ GLOBAL_LIST_INIT(maintenance_categories, list( var/datum/ares_datacore/datacore = GLOB.ares_datacore datacore.records_bombardment.Add(new /datum/ares_record/bombardment(ob_name, message, user_name)) -/proc/log_ares_announcement(title, message) +/proc/log_ares_announcement(title, message, signature) if(!ares_can_log()) return FALSE + var/final_msg = message + if(signature) + final_msg = "[signature]: - [final_msg]" var/datum/ares_datacore/datacore = GLOB.ares_datacore - datacore.records_announcement.Add(new /datum/ares_record/announcement(title, message)) + datacore.records_announcement.Add(new /datum/ares_record/announcement(title, final_msg)) /proc/log_ares_requisition(source, details, user_name) if(!ares_can_log()) @@ -183,11 +190,14 @@ GLOBAL_LIST_INIT(maintenance_categories, list( var/datum/ares_datacore/datacore = GLOB.ares_datacore datacore.records_asrs.Add(new /datum/ares_record/requisition_log(source, details, user_name)) -/proc/log_ares_security(title, details) +/proc/log_ares_security(title, details, signature) if(!ares_can_log()) return FALSE + var/final_msg = details + if(signature) + final_msg = "[signature]: - [final_msg]" var/datum/ares_datacore/datacore = GLOB.ares_datacore - datacore.records_security.Add(new /datum/ares_record/security(title, details)) + datacore.records_security.Add(new /datum/ares_record/security(title, final_msg)) /proc/log_ares_antiair(details) if(!ares_can_log()) diff --git a/code/game/machinery/ARES/apollo_pda.dm b/code/game/machinery/ARES/apollo_pda.dm index e447bb6f7ee7..787b194ffb44 100644 --- a/code/game/machinery/ARES/apollo_pda.dm +++ b/code/game/machinery/ARES/apollo_pda.dm @@ -181,29 +181,29 @@ return var/playsound = TRUE - var/mob/living/carbon/human/operator = ui.user + var/mob/living/carbon/human/user = ui.user switch (action) if("go_back") if(!last_menu) - return to_chat(operator, SPAN_WARNING("Error, no previous page detected.")) + return to_chat(user, SPAN_WARNING("Error, no previous page detected.")) var/temp_holder = current_menu current_menu = last_menu last_menu = temp_holder if("login") - var/obj/item/card/id/idcard = operator.get_active_hand() + var/obj/item/card/id/idcard = user.get_active_hand() if(istype(idcard)) authentication = get_ares_access(idcard) last_login = idcard.registered_name - else if(operator.wear_id) - idcard = operator.wear_id + else if(user.wear_id) + idcard = user.wear_id if(istype(idcard)) authentication = get_ares_access(idcard) last_login = idcard.registered_name else - to_chat(operator, SPAN_WARNING("You require an ID card to access this terminal!")) + to_chat(user, SPAN_WARNING("You require an ID card to access this terminal!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(authentication) @@ -248,23 +248,23 @@ if("new_report") 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) + var/maint_type = tgui_input_list(user, "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(operator, "What are the details for this report?", "Ticket Details", encode = FALSE) + var/details = tgui_input_text(user, "What are the details for this report?", "Ticket Details", encode = FALSE) if(!details) return FALSE if((authentication >= APOLLO_ACCESS_REPORTER) && !priority_report) - var/is_priority = tgui_alert(operator, "Is this a priority report?", "Priority designation", list("Yes", "No")) + var/is_priority = tgui_alert(user, "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") + var/confirm = alert(user, "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, maint_type, details, priority_report) @@ -273,7 +273,7 @@ ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.") else send_notifcation() - log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(operator)] as [last_login] with Category '[maint_type]' and Details of '[details]'.") + log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(user)] as [last_login] with Category '[maint_type]' and Details of '[details]'.") return TRUE return FALSE @@ -285,14 +285,14 @@ var/assigned = ticket.ticket_assignee if(assigned) if(assigned == last_login) - var/prompt = tgui_alert(operator, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No")) + var/prompt = tgui_alert(user, "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(operator, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No")) + var/choice = tgui_alert(user, "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) @@ -305,9 +305,9 @@ if(!istype(ticket)) return FALSE if(ticket.ticket_submitter != last_login) - to_chat(operator, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!")) + to_chat(user, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!")) return FALSE - to_chat(operator, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled.")) + to_chat(user, 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.") @@ -320,9 +320,9 @@ if(!istype(ticket)) return FALSE if(ticket.ticket_assignee != last_login && ticket.ticket_assignee) //must be claimed by you or unclaimed.) - to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) return FALSE - var/choice = tgui_alert(operator, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS) + var/choice = tgui_alert(user, "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 @@ -334,39 +334,39 @@ ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by [last_login].") else send_notifcation() - to_chat(operator, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) + to_chat(user, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) return TRUE if("new_access") - var/obj/item/card/id/idcard = operator.get_active_hand() + var/obj/item/card/id/idcard = user.get_active_hand() var/has_id = FALSE if(istype(idcard)) has_id = TRUE - else if(operator.wear_id) - idcard = operator.wear_id + else if(user.wear_id) + idcard = user.wear_id if(istype(idcard)) has_id = TRUE if(!has_id) - to_chat(operator, SPAN_WARNING("You require an ID card to request an access ticket!")) + to_chat(user, SPAN_WARNING("You require an ID card to request an access ticket!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(idcard.registered_name != last_login) - to_chat(operator, SPAN_WARNING("This ID card does not match the active login!")) + to_chat(user, SPAN_WARNING("This ID card does not match the active login!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE - var/details = tgui_input_text(operator, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE) + var/details = tgui_input_text(user, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE) if(!details) return FALSE - var/confirm = alert(operator, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No") + var/confirm = alert(user, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No") if(confirm != "Yes" || !link) return FALSE var/datum/ares_ticket/access/access_ticket = new(last_login, details, FALSE, idcard.registered_gid) link.waiting_ids += idcard link.tickets_access += access_ticket - log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(operator)] as [last_login] with Details of '[details]'.") - message_admins(SPAN_STAFF_IC("[key_name_admin(operator)] created a new ARES Access Ticket."), 1) + log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(user)] as [last_login] with Details of '[details]'.") + message_admins(SPAN_STAFF_IC("[key_name_admin(user)] created a new ARES Access Ticket."), 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] requesting access for '[details].") return TRUE @@ -387,9 +387,9 @@ access_ticket.ticket_status = TICKET_RETURNED identification.access -= ACCESS_MARINE_AI_TEMP - identification.modification_log += "Temporary AI Access self-returned by [key_name(operator)]." + identification.modification_log += "Temporary AI Access self-returned by [key_name(user)]." - to_chat(operator, SPAN_NOTICE("Temporary Access Ticket surrendered.")) + to_chat(user, SPAN_NOTICE("Temporary Access Ticket surrendered.")) playsound(src, 'sound/machines/chime.ogg', 15, 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] surrendered their access.") @@ -398,7 +398,7 @@ datacore.apollo_login_list += "[last_login] at [worldtime2text()], Surrendered Temporary Access Ticket." return TRUE - to_chat(operator, SPAN_WARNING("This ID card does not have an access ticket!")) + to_chat(user, SPAN_WARNING("This ID card does not have an access ticket!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE @@ -410,7 +410,7 @@ for(var/obj/item/card/id/identification in link.waiting_ids) if(identification.registered_gid != access_ticket.user_id_num) continue - identification.handle_ares_access(last_login, operator) + identification.handle_ares_access(last_login, user) access_ticket.ticket_status = TICKET_GRANTED playsound(src, 'sound/machines/chime.ogg', 15, 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] was granted access by [last_login].") @@ -418,7 +418,7 @@ for(var/obj/item/card/id/identification in link.active_ids) if(identification.registered_gid != access_ticket.user_id_num) continue - identification.handle_ares_access(last_login, operator) + identification.handle_ares_access(last_login, user) access_ticket.ticket_status = TICKET_REVOKED playsound(src, 'sound/machines/chime.ogg', 15, 1) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] had access revoked by [last_login].") @@ -430,10 +430,10 @@ if(!istype(access_ticket)) return FALSE if(access_ticket.ticket_assignee != last_login && access_ticket.ticket_assignee) //must be claimed by you or unclaimed.) - to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) return FALSE access_ticket.ticket_status = TICKET_REJECTED - to_chat(operator, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as rejected.")) + to_chat(user, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as rejected.")) ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] was rejected access by [last_login].") for(var/obj/item/card/id/identification in link.waiting_ids) if(identification.registered_gid != access_ticket.user_id_num) @@ -448,20 +448,27 @@ playsound = FALSE var/obj/structure/pipes/vents/pump/no_boom/gas/sec_vent = locate(params["vent"]) if(!istype(sec_vent) || sec_vent.welded) - to_chat(operator, SPAN_WARNING("ERROR: Gas release failure.")) + to_chat(user, SPAN_WARNING("ERROR: Gas release failure.")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE if(!COOLDOWN_FINISHED(sec_vent, vent_trigger_cooldown)) - to_chat(operator, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent.")) + to_chat(user, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent.")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE - to_chat(operator, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag].")) + to_chat(user, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag].")) playsound(src, 'sound/machines/chime.ogg', 15, 1) COOLDOWN_START(sec_vent, vent_trigger_cooldown, COOLDOWN_ARES_VENT) ares_apollo_talk("Nerve Gas release imminent from [sec_vent.vent_tag].") - log_ares_security("Nerve Gas Release", "[last_login] released Nerve Gas from Vent '[sec_vent.vent_tag]'.") + log_ares_security("Nerve Gas Release", "Released Nerve Gas from Vent '[sec_vent.vent_tag]'.", last_login) sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS) - log_admin("[key_name(operator)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + log_admin("[key_name(user)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + + if("security_lockdown") + if(!COOLDOWN_FINISHED(datacore, aicore_lockdown)) + to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(datacore, aicore_lockdown)] seconds!")) + return FALSE + aicore_lockdown(user) + return TRUE if(playsound) var/sound = pick('sound/machines/pda_button1.ogg', 'sound/machines/pda_button2.ogg') diff --git a/code/game/machinery/aicore_lockdown.dm b/code/game/machinery/aicore_lockdown.dm new file mode 100644 index 000000000000..8120e98977dc --- /dev/null +++ b/code/game/machinery/aicore_lockdown.dm @@ -0,0 +1,119 @@ +/obj/structure/machinery/aicore_lockdown + name = "AI Core Lockdown" + icon_state = "big_red_button_tablev" + unslashable = TRUE + unacidable = TRUE + +/obj/structure/machinery/aicore_lockdown/ex_act(severity) + return FALSE + +/obj/structure/machinery/aicore_lockdown/attack_remote(mob/user as mob) + return FALSE + +/obj/structure/machinery/aicore_lockdown/attack_alien(mob/user as mob) + return FALSE + +/obj/structure/machinery/aicore_lockdown/attackby(obj/item/attacking_item, mob/user) + return attack_hand(user) + +/obj/structure/machinery/aicore_lockdown/attack_hand(mob/living/user) + if(isxeno(user)) + return FALSE + if(!allowed(user)) + to_chat(user, SPAN_DANGER("Access Denied")) + flick(initial(icon_state) + "-denied", src) + return FALSE + + if(!COOLDOWN_FINISHED(GLOB.ares_datacore, aicore_lockdown)) + to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(GLOB.ares_datacore, aicore_lockdown)] seconds!")) + return FALSE + + add_fingerprint(user) + aicore_lockdown(user) + +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown + name = "ARES Emergency Lockdown Shutter" + density = FALSE + open_layer = 1.9 + plane = FLOOR_PLANE + +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore + icon_state = "aidoor1" + base_icon_state = "aidoor" + +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore/white + icon_state = "w_aidoor1" + base_icon_state = "w_aidoor" + +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/white + icon_state = "w_almayer_pdoor1" + base_icon_state = "w_almayer_pdoor" + +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/Initialize() + . = ..() + RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LOCKDOWN, PROC_REF(close)) + RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LIFT, PROC_REF(open)) + + +/client/proc/admin_aicore_alert() + set name = "AI Core Lockdown" + set category = "Admin.Ship" + + if(!admin_holder ||!check_rights(R_EVENT)) + return FALSE + + var/prompt = "Are you sure you want to trigger an AI Core lockdown? This will raise to red alert, and lockdown the AI Core." + + if(GLOB.ares_datacore.ai_lockdown_active == TRUE) + prompt = "Are you sure you want to lift the AI Core lockdown? This will lower to blue alert." + + var/choice = tgui_alert(src, prompt, "Choose.", list("Yes", "No"), 20 SECONDS) + if(choice != "Yes") + return FALSE + + choice = tgui_alert(src, "Do you want to use a custom announcement?", "Choose.", list("Yes", "No"), 20 SECONDS) + if(choice == "Yes") + var/message = tgui_input_text(src, "Please enter announcement text.", "what?") + aicore_lockdown(usr, message, admin = TRUE) + else + aicore_lockdown(usr, admin = TRUE) + return TRUE + +/proc/aicore_lockdown(mob/user, message, admin = FALSE) + if(IsAdminAdvancedProcCall()) + return PROC_BLOCKED + + var/log = "[key_name(user)] triggered AI core lockdown!" + var/ares_log = "Triggered triggered AI Core Emergency Lockdown." + var/person = user.name + if(message) + log = "[key_name(user)] triggered AI core emergency lockdown! (Using a custom announcement)." + if(admin) + log += " (Admin Triggered)." + person = MAIN_AI_SYSTEM + + if(GLOB.ares_datacore.ai_lockdown_active) + GLOB.ares_datacore.ai_lockdown_active = FALSE + if(!message) + message = "ATTENTION! \n\nAI CORE EMERGENCY LOCKDOWN LIFTED." + log = "[key_name(user)] lifted AI core lockdown!" + ares_log = "Lifted AI Core Emergency Lockdown." + if(admin) + log += " (Admin Triggered)." + person = MAIN_AI_SYSTEM + + if(GLOB.security_level > SEC_LEVEL_GREEN) + set_security_level(SEC_LEVEL_BLUE, TRUE, FALSE) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_AICORE_LIFT) + else + GLOB.ares_datacore.ai_lockdown_active = TRUE + if(!message) + message = "ATTENTION! \n\nCORE SECURITY ALERT. \n\nAI CORE UNDER LOCKDOWN." + if(GLOB.security_level < SEC_LEVEL_RED) + set_security_level(SEC_LEVEL_RED, TRUE, FALSE) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_AICORE_LOCKDOWN) + + COOLDOWN_START(GLOB.ares_datacore, aicore_lockdown, 2 MINUTES) + shipwide_ai_announcement(message, MAIN_AI_SYSTEM, 'sound/effects/biohazard.ogg') + message_admins(log) + log_ares_security("AI Core Lockdown", ares_log, person) diff --git a/code/game/machinery/biohazard_lockdown.dm b/code/game/machinery/biohazard_lockdown.dm index 2e3cbf6de234..bb2674ccca6f 100644 --- a/code/game/machinery/biohazard_lockdown.dm +++ b/code/game/machinery/biohazard_lockdown.dm @@ -1,6 +1,6 @@ #define LOCKDOWN_READY 0 #define LOCKDOWN_ACTIVE 1 -GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY) +GLOBAL_VAR_INIT(med_lockdown_state, LOCKDOWN_READY) /obj/structure/machinery/biohazard_lockdown name = "Emergency Containment Breach" @@ -51,7 +51,7 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY) base_icon_state = "w_almayer_pdoor" /client/proc/admin_biohazard_alert() - set name = "Containment Breach Alert" + set name = "Research Containment Lockdown" set category = "Admin.Ship" if(!admin_holder ||!check_rights(R_EVENT)) @@ -63,8 +63,8 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY) prompt = tgui_alert(src, "Do you want to use a custom announcement?", "Choose.", list("Yes", "No"), 20 SECONDS) if(prompt == "Yes") - var/whattoannounce = tgui_input_text(src, "Please enter announcement text.", "what?") - biohazard_lockdown(usr, whattoannounce, TRUE) + var/message = tgui_input_text(src, "Please enter announcement text.", "what?") + biohazard_lockdown(usr, message, admin = TRUE) else biohazard_lockdown(usr, admin = TRUE) return TRUE @@ -74,35 +74,38 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY) return PROC_BLOCKED var/log = "[key_name(user)] triggered research bio lockdown!" - var/ares_log = "[user.name] triggered Medical Research Biohazard Containment Lockdown." + var/ares_log = "Triggered Medical Research Biohazard Containment Lockdown." + var/person = user.name if(!message) message = "ATTENTION! \n\nBIOHAZARD CONTAINMENT BREACH. \n\nRESEARCH DEPARTMENT UNDER LOCKDOWN." else log = "[key_name(user)] triggered research bio lockdown! (Using a custom announcement)." if(admin) log += " (Admin Triggered)." - ares_log = "[MAIN_AI_SYSTEM] triggered Medical Research Biohazard Containment Lockdown." + person = MAIN_AI_SYSTEM - switch(GLOB.lockdown_state) + switch(GLOB.med_lockdown_state) if(LOCKDOWN_READY) - GLOB.lockdown_state = LOCKDOWN_ACTIVE - set_security_level(SEC_LEVEL_RED, TRUE, FALSE) + GLOB.med_lockdown_state = LOCKDOWN_ACTIVE + if(GLOB.security_level < SEC_LEVEL_RED) + set_security_level(SEC_LEVEL_RED, TRUE, FALSE) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_RESEARCH_LOCKDOWN) if(LOCKDOWN_ACTIVE) - GLOB.lockdown_state = LOCKDOWN_READY + GLOB.med_lockdown_state = LOCKDOWN_READY message = "ATTENTION! \n\nBIOHAZARD CONTAINMENT LOCKDOWN LIFTED." log = "[key_name(user)] lifted research bio lockdown!" - ares_log = "[user.name] lifted Medical Research Biohazard Containment Lockdown." + ares_log = "Lifted Medical Research Biohazard Containment Lockdown." if(admin) log += " (Admin Triggered)." - ares_log = "[MAIN_AI_SYSTEM] lifted Medical Research Biohazard Containment Lockdown." + person = MAIN_AI_SYSTEM - set_security_level(SEC_LEVEL_BLUE, TRUE, FALSE) + if(GLOB.security_level > SEC_LEVEL_GREEN) + set_security_level(SEC_LEVEL_BLUE, TRUE, FALSE) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_RESEARCH_LIFT) shipwide_ai_announcement(message, MAIN_AI_SYSTEM, 'sound/effects/biohazard.ogg') message_admins(log) - log_ares_security("Containment Lockdown", ares_log) + log_ares_security("Containment Lockdown", ares_log, person) #undef LOCKDOWN_READY #undef LOCKDOWN_ACTIVE diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 948d83e76148..6943544e30d4 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -312,8 +312,8 @@ GLOBAL_LIST_EMPTY_TYPED(all_cameras, /obj/structure/machinery/camera) . = ..() if(!camera_item) return INITIALIZE_HINT_QDEL - c_tag = camera_item.get_broadcast_name() linked_broadcasting = camera_item + c_tag = linked_broadcasting.get_broadcast_name() /obj/structure/machinery/camera/mortar alpha = 0 diff --git a/code/game/machinery/computer/almayer_control.dm b/code/game/machinery/computer/almayer_control.dm index 1f3338e15bf7..0090a6673961 100644 --- a/code/game/machinery/computer/almayer_control.dm +++ b/code/game/machinery/computer/almayer_control.dm @@ -108,33 +108,34 @@ . = ..() if(.) return + var/mob/user = ui.user switch(action) if("award") - open_medal_panel(usr, src) + open_medal_panel(user, src) . = TRUE // evac stuff start \\ if("evacuation_start") if(GLOB.security_level < SEC_LEVEL_RED) - to_chat(usr, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) + to_chat(user, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) return FALSE if(SShijack.evac_admin_denied) - to_chat(usr, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) + to_chat(user, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) return FALSE if(!SShijack.initiate_evacuation()) - to_chat(usr, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) + to_chat(user, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) return FALSE - log_game("[key_name(usr)] has called for an emergency evacuation.") - message_admins("[key_name_admin(usr)] has called for an emergency evacuation.") - log_ares_security("Initiate Evacuation", "[usr] has called for an emergency evacuation.") + log_game("[key_name(user)] has called for an emergency evacuation.") + message_admins("[key_name_admin(user)] has called for an emergency evacuation.") + log_ares_security("Initiate Evacuation", "Called for an emergency evacuation.", user) . = TRUE if("evacuation_cancel") - var/mob/living/carbon/human/human_user = usr + var/mob/living/carbon/human/human_user = user var/obj/item/card/id/idcard = human_user.get_active_hand() var/bio_fail = FALSE if(!istype(idcard)) @@ -148,12 +149,12 @@ return FALSE if(!SShijack.cancel_evacuation()) - to_chat(usr, SPAN_WARNING("You are unable to cancel the evacuation right now!")) + to_chat(user, SPAN_WARNING("You are unable to cancel the evacuation right now!")) return FALSE - log_game("[key_name(usr)] has canceled the emergency evacuation.") - message_admins("[key_name_admin(usr)] has canceled the emergency evacuation.") - log_ares_security("Cancel Evacuation", "[usr] has cancelled the emergency evacuation.") + log_game("[key_name(user)] has canceled the emergency evacuation.") + message_admins("[key_name_admin(user)] has canceled the emergency evacuation.") + log_ares_security("Cancel Evacuation", "Cancelled the emergency evacuation.", user) . = TRUE // evac stuff end \\ @@ -168,32 +169,32 @@ if(SEC_LEVEL_DELTA) return - var/level_selected = tgui_input_list(usr, "What alert would you like to set it as?", "Alert Level", alert_list) + var/level_selected = tgui_input_list(user, "What alert would you like to set it as?", "Alert Level", alert_list) if(!level_selected) return set_security_level(seclevel2num(level_selected), log = ARES_LOG_NONE) - log_game("[key_name(usr)] has changed the security level to [get_security_level()].") - message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].") - log_ares_security("Manual Security Update", "[usr] has changed the security level to [get_security_level()].") + log_game("[key_name(user)] has changed the security level to [get_security_level()].") + message_admins("[key_name_admin(user)] has changed the security level to [get_security_level()].") + log_ares_security("Manual Security Update", "Changed the security level to [get_security_level()].", user) . = TRUE if("messageUSCM") if(!COOLDOWN_FINISHED(src, cooldown_central)) - to_chat(usr, SPAN_WARNING("Arrays are re-cycling. Please stand by.")) + to_chat(user, SPAN_WARNING("Arrays are re-cycling. Please stand by.")) return FALSE - var/input = stripped_input(usr, "Please choose a message to transmit to USCM. Please be aware that this process is very expensive, and abuse will lead to termination. Transmission does not guarantee a response. There is a small delay before you may send another message. Be clear and concise.", "To abort, send an empty message.", "") - if(!input || !(usr in view(1,src)) || !COOLDOWN_FINISHED(src, cooldown_central)) + var/input = stripped_input(user, "Please choose a message to transmit to USCM. Please be aware that this process is very expensive, and abuse will lead to termination. Transmission does not guarantee a response. There is a small delay before you may send another message. Be clear and concise.", "To abort, send an empty message.", "") + if(!input || !(user in view(1,src)) || !COOLDOWN_FINISHED(src, cooldown_central)) return FALSE - high_command_announce(input, usr) - to_chat(usr, SPAN_NOTICE("Message transmitted.")) - log_announcement("[key_name(usr)] has made an USCM announcement: [input]") + high_command_announce(input, user) + to_chat(user, SPAN_NOTICE("Message transmitted.")) + log_announcement("[key_name(user)] has made an USCM announcement: [input]") COOLDOWN_START(src, cooldown_central, COOLDOWN_COMM_CENTRAL) . = TRUE if("ship_announce") - var/mob/living/carbon/human/human_user = usr + var/mob/living/carbon/human/human_user = user var/obj/item/card/id/idcard = human_user.get_active_hand() var/bio_fail = FALSE if(!istype(idcard)) @@ -207,10 +208,10 @@ return FALSE if(!COOLDOWN_FINISHED(src, cooldown_message)) - to_chat(usr, SPAN_WARNING("Please allow at least [COOLDOWN_TIMELEFT(src, cooldown_message)/10] second\s to pass between announcements.")) + to_chat(user, SPAN_WARNING("Please allow at least [COOLDOWN_TIMELEFT(src, cooldown_message)/10] second\s to pass between announcements.")) return FALSE - var/input = stripped_multiline_input(usr, "Please write a message to announce to the station crew.", "Priority Announcement", "") - if(!input || !COOLDOWN_FINISHED(src, cooldown_message) || !(usr in view(1,src))) + var/input = stripped_multiline_input(user, "Please write a message to announce to the station crew.", "Priority Announcement", "") + if(!input || !COOLDOWN_FINISHED(src, cooldown_message) || !(user in view(1,src))) return FALSE var/signed = null @@ -219,35 +220,35 @@ COOLDOWN_START(src, cooldown_message, COOLDOWN_COMM_MESSAGE) shipwide_ai_announcement(input, COMMAND_SHIP_ANNOUNCE, signature = signed) - message_admins("[key_name(usr)] has made a shipwide annoucement.") - log_announcement("[key_name(usr)] has announced the following to the ship: [input]") + message_admins("[key_name(user)] has made a shipwide annoucement.") + log_announcement("[key_name(user)] has announced the following to the ship: [input]") . = TRUE if("distress") if(world.time < DISTRESS_TIME_LOCK) - to_chat(usr, SPAN_WARNING("The distress beacon cannot be launched this early in the operation. Please wait another [time_left_until(DISTRESS_TIME_LOCK, world.time, 1 MINUTES)] minutes before trying again.")) + to_chat(user, SPAN_WARNING("The distress beacon cannot be launched this early in the operation. Please wait another [time_left_until(DISTRESS_TIME_LOCK, world.time, 1 MINUTES)] minutes before trying again.")) return FALSE if(!SSticker.mode) return FALSE //Not a game mode? if(SSticker.mode.force_end_at == 0) - to_chat(usr, SPAN_WARNING("ARES has denied your request for operational security reasons.")) + to_chat(user, SPAN_WARNING("ARES has denied your request for operational security reasons.")) return FALSE if(!COOLDOWN_FINISHED(src, cooldown_request)) - to_chat(usr, SPAN_WARNING("The distress beacon has recently broadcast a message. Please wait.")) + to_chat(user, SPAN_WARNING("The distress beacon has recently broadcast a message. Please wait.")) return FALSE if(GLOB.security_level == SEC_LEVEL_DELTA) - to_chat(usr, SPAN_WARNING("The ship is already undergoing self-destruct procedures!")) + to_chat(user, SPAN_WARNING("The ship is already undergoing self-destruct procedures!")) return FALSE for(var/client/admin_client as anything in GLOB.admins) if((R_ADMIN|R_MOD) & admin_client.admin_holder.rights) admin_client << 'sound/effects/sos-morse-code.ogg' - SSticker.mode.request_ert(usr) - to_chat(usr, SPAN_NOTICE("A distress beacon request has been sent to USCM Central Command.")) + SSticker.mode.request_ert(user) + to_chat(user, SPAN_NOTICE("A distress beacon request has been sent to USCM Central Command.")) COOLDOWN_START(src, cooldown_request, COOLDOWN_COMM_REQUEST) . = TRUE @@ -256,29 +257,29 @@ if("destroy") if(world.time < DISTRESS_TIME_LOCK) - to_chat(usr, SPAN_WARNING("The self-destruct cannot be activated this early in the operation. Please wait another [time_left_until(DISTRESS_TIME_LOCK, world.time, 1 MINUTES)] minutes before trying again.")) + to_chat(user, SPAN_WARNING("The self-destruct cannot be activated this early in the operation. Please wait another [time_left_until(DISTRESS_TIME_LOCK, world.time, 1 MINUTES)] minutes before trying again.")) return FALSE if(!SSticker.mode) return FALSE //Not a game mode? if(SSticker.mode.force_end_at == 0) - to_chat(usr, SPAN_WARNING("ARES has denied your request for operational security reasons.")) + to_chat(user, SPAN_WARNING("ARES has denied your request for operational security reasons.")) return FALSE if(!COOLDOWN_FINISHED(src, cooldown_destruct)) - to_chat(usr, SPAN_WARNING("A self-destruct request has already been sent to high command. Please wait.")) + to_chat(user, SPAN_WARNING("A self-destruct request has already been sent to high command. Please wait.")) return FALSE if(get_security_level() == "delta") - to_chat(usr, SPAN_WARNING("The [MAIN_SHIP_NAME]'s self-destruct is already activated.")) + to_chat(user, SPAN_WARNING("The [MAIN_SHIP_NAME]'s self-destruct is already activated.")) return FALSE for(var/client/admin_client as anything in GLOB.admins) if((R_ADMIN|R_MOD) & admin_client.admin_holder.rights) admin_client << 'sound/effects/sos-morse-code.ogg' - message_admins("[key_name(usr)] has requested Self-Destruct! [CC_MARK(usr)] (GRANT) (DENY) [ADMIN_JMP_USER(usr)] [CC_REPLY(usr)]") - to_chat(usr, SPAN_NOTICE("A self-destruct request has been sent to USCM Central Command.")) + message_admins("[key_name(user)] has requested Self-Destruct! [CC_MARK(user)] (GRANT) (DENY) [ADMIN_JMP_USER(user)] [CC_REPLY(user)]") + to_chat(user, SPAN_NOTICE("A self-destruct request has been sent to USCM Central Command.")) COOLDOWN_START(src, cooldown_destruct, COOLDOWN_COMM_DESTRUCT) . = TRUE diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm index cd0ee780f478..1e2cb427cab4 100644 --- a/code/game/machinery/computer/camera_console.dm +++ b/code/game/machinery/computer/camera_console.dm @@ -17,6 +17,7 @@ var/colony_camera_mapload = TRUE var/admin_console = FALSE + var/stay_connected = FALSE /obj/structure/machinery/computer/cameras/Initialize(mapload) . = ..() @@ -33,7 +34,7 @@ /obj/structure/machinery/computer/cameras/Destroy() SStgui.close_uis(src) - QDEL_NULL(current) + current = null UnregisterSignal(src, COMSIG_CAMERA_MAPNAME_ASSIGNED) last_camera_turf = null concurrent_users = null @@ -147,7 +148,7 @@ // Unregister map objects SEND_SIGNAL(src, COMSIG_CAMERA_UNREGISTER_UI, user) // Turn off the console - if(length(concurrent_users) == 0 && is_living) + if(length(concurrent_users) == 0 && is_living && !stay_connected) current = null SEND_SIGNAL(src, COMSIG_CAMERA_CLEAR) last_camera_turf = null @@ -206,6 +207,8 @@ name = "Television Set" desc = "An old TV hooked up to a video cassette recorder, you can even use it to time shift WOW." network = list(CAMERA_NET_CORRESPONDENT) + stay_connected = TRUE + circuit = /obj/item/circuitboard/computer/cameras/tv var/obj/item/device/camera/broadcasting/broadcastingcamera = null /obj/structure/machinery/computer/cameras/wooden_tv/broadcast/Destroy() @@ -213,38 +216,76 @@ return ..() /obj/structure/machinery/computer/cameras/wooden_tv/broadcast/ui_state(mob/user) - return GLOB.default_state + return GLOB.in_view /obj/structure/machinery/computer/cameras/wooden_tv/broadcast/ui_act(action, params) . = ..() if(action != "switch_camera") return - broadcastingcamera = null - if (!istype(current, /obj/structure/machinery/camera/correspondent)) + if(broadcastingcamera) + clear_camera() + if(!istype(current, /obj/structure/machinery/camera/correspondent)) return var/obj/structure/machinery/camera/correspondent/corr_cam = current - if (!corr_cam.linked_broadcasting) + if(!corr_cam.linked_broadcasting) return broadcastingcamera = corr_cam.linked_broadcasting RegisterSignal(broadcastingcamera, COMSIG_BROADCAST_GO_LIVE, PROC_REF(go_back_live)) + RegisterSignal(broadcastingcamera, COMSIG_COMPONENT_ADDED, PROC_REF(handle_rename)) RegisterSignal(broadcastingcamera, COMSIG_PARENT_QDELETING, PROC_REF(clear_camera)) + RegisterSignal(broadcastingcamera, COMSIG_BROADCAST_HEAR_TALK, PROC_REF(transfer_talk)) + RegisterSignal(broadcastingcamera, COMSIG_BROADCAST_SEE_EMOTE, PROC_REF(transfer_emote)) /obj/structure/machinery/computer/cameras/wooden_tv/broadcast/ui_close(mob/user) . = ..() - if (!current && broadcastingcamera) + if(!broadcastingcamera) + return + if(!current) clear_camera() /obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/clear_camera() SIGNAL_HANDLER - UnregisterSignal(broadcastingcamera, list(COMSIG_BROADCAST_GO_LIVE, COMSIG_PARENT_QDELETING)) + UnregisterSignal(broadcastingcamera, list(COMSIG_BROADCAST_GO_LIVE, COMSIG_PARENT_QDELETING, COMSIG_COMPONENT_ADDED, COMSIG_BROADCAST_HEAR_TALK, COMSIG_BROADCAST_SEE_EMOTE)) broadcastingcamera = null /obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/go_back_live(obj/item/device/camera/broadcasting/broadcastingcamera) SIGNAL_HANDLER - if (current.c_tag == broadcastingcamera.get_broadcast_name()) + if(current.c_tag == broadcastingcamera.get_broadcast_name()) current = broadcastingcamera.linked_cam SEND_SIGNAL(src, COMSIG_CAMERA_SET_TARGET, broadcastingcamera.linked_cam, broadcastingcamera.linked_cam.view_range, broadcastingcamera.linked_cam.view_range) +/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/transfer_talk(obj/item/camera, mob/living/sourcemob, message, verb = "says", datum/language/language, italics = FALSE, show_message_above_tv = FALSE) + SIGNAL_HANDLER + if(inoperable()) + return + if(show_message_above_tv) + langchat_speech(message, get_mobs_in_view(7, src), language, sourcemob.langchat_color, FALSE, LANGCHAT_FAST_POP, list(sourcemob.langchat_styles)) + for(var/datum/weakref/user_ref in concurrent_users) + var/mob/user = user_ref.resolve() + if(user?.client?.prefs && !user.client.prefs.lang_chat_disabled && !user.ear_deaf && user.say_understands(sourcemob, language)) + sourcemob.langchat_display_image(user) + +/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/transfer_emote(obj/item/camera, mob/living/sourcemob, emote, audible = FALSE, show_message_above_tv = FALSE) + SIGNAL_HANDLER + if(inoperable()) + return + if(show_message_above_tv) + langchat_speech(emote, get_mobs_in_view(7, src), null, null, TRUE, LANGCHAT_FAST_POP, list("emote")) + for(var/datum/weakref/user_ref in concurrent_users) + var/mob/user = user_ref.resolve() + if(user?.client?.prefs && (user.client.prefs.toggles_langchat & LANGCHAT_SEE_EMOTES) && (!audible || !user.ear_deaf)) + sourcemob.langchat_display_image(user) + +/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/examine(mob/user) + . = ..() + attack_hand(user) //watch tv on examine + +/obj/structure/machinery/computer/cameras/wooden_tv/broadcast/proc/handle_rename(obj/item/camera, datum/component/label) + SIGNAL_HANDLER + if(!istype(label, /datum/component/label)) + return + current.c_tag = broadcastingcamera.get_broadcast_name() + /obj/structure/machinery/computer/cameras/wooden_tv/ot name = "Mortar Monitoring Set" desc = "A Console linked to Mortar launched cameras." diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index beed3610b53f..6ed2a8c7be64 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -161,7 +161,7 @@ log_game("[key_name(usr)] has called for an emergency evacuation.") message_admins("[key_name_admin(usr)] has called for an emergency evacuation.") - log_ares_security("Initiate Evacuation", "[usr] has called for an emergency evacuation.") + log_ares_security("Initiate Evacuation", "Called for an emergency evacuation.", usr) return TRUE state = STATE_EVACUATION @@ -187,7 +187,7 @@ log_game("[key_name(usr)] has canceled the emergency evacuation.") message_admins("[key_name_admin(usr)] has canceled the emergency evacuation.") - log_ares_security("Cancel Evacuation", "[usr] has cancelled the emergency evacuation.") + log_ares_security("Cancel Evacuation", "Cancelled the emergency evacuation.", usr) return TRUE state = STATE_EVACUATION_CANCEL diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index c33517796271..f6efe6edb5e2 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -126,7 +126,7 @@ src.attack_alien(user) return src.attack_hand(user) - return + return ..() /obj/structure/machinery/computer/attack_hand() . = ..() diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm index dce026f4ce33..017a5f0736ca 100644 --- a/code/game/machinery/computer/dropship_weapons.dm +++ b/code/game/machinery/computer/dropship_weapons.dm @@ -754,7 +754,7 @@ if (!dropship.in_flyby || dropship.mode != SHUTTLE_CALL) to_chat(user, SPAN_WARNING("Has to be in Fly By mode")) return FALSE - if (dropship.timer && dropship.timeLeft(1) < firemission_envelope.get_total_duration()) + if (dropship.timer && dropship.timeLeft(1) < firemission_envelope.flyoff_period) to_chat(user, SPAN_WARNING("Not enough time to complete the Fire Mission")) return FALSE var/datum/cas_signal/recorded_loc = firemission_envelope.recorded_loc diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index 220772e98b17..5a7e690fc3ca 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -229,8 +229,9 @@ //************************************/ /obj/structure/machinery/microwave/proc/cook(time_multiplier = 1) - if(inoperable()) + if(inoperable() || operating) return + start() if (reagents.total_volume==0 && !(locate(/obj) in contents)) //dry run if (!wzhzhzh(10 * time_multiplier)) diff --git a/code/game/machinery/vending/vendor_types/crew/sea.dm b/code/game/machinery/vending/vendor_types/crew/sea.dm index 44f530271037..37cacfd14a6f 100644 --- a/code/game/machinery/vending/vendor_types/crew/sea.dm +++ b/code/game/machinery/vending/vendor_types/crew/sea.dm @@ -29,17 +29,20 @@ GLOBAL_LIST_INIT(cm_vending_gear_sea, list( GLOBAL_LIST_INIT(cm_vending_clothing_sea, list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), list("Officer Uniform", 0, /obj/item/clothing/under/marine/dress, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), - list("Marine Combat Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/almayer/mcom/cdrcom, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), list("Satchel", 0, /obj/item/storage/backpack/satchel/lockable, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY), list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY), list("Marine Combat Boots", 0, /obj/item/clothing/shoes/marine/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("GLOVES (CHOOSE 1)", 0, null, null, null), + list("Insulated Gloves", 0, /obj/item/clothing/gloves/yellow, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_REGULAR), + list("Marine Combat Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_REGULAR), + list("BELT (CHOOSE 1)", 0, null, null, null), list("G8-A General Utility Pouch", 0, /obj/item/storage/backpack/general_belt, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR), list("M276 Lifesaver Bag (Full)", 0, /obj/item/storage/belt/medical/lifesaver/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_RECOMMENDED), list("M276 Toolbelt Rig (Full)", 0, /obj/item/storage/belt/utility/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR), - list("M276 Combat Toolbelt Rig (Full)", 0, /obj/item/storage/belt/gun/utility, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR), + list("M276 Combat Toolbelt Rig (Full)", 0, /obj/item/storage/belt/gun/utility/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_REGULAR), list("POUCHES (CHOOSE 2)", 0, null, null, null), list("Autoinjector Pouch", 0, /obj/item/storage/pouch/autoinjector/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), @@ -58,6 +61,12 @@ GLOBAL_LIST_INIT(cm_vending_clothing_sea, list( list("Bulletproof Vest", 0, /obj/item/clothing/suit/armor/bulletproof, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), list("USCM Service Jacket", 0, /obj/item/clothing/suit/storage/jacket/marine/service, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + list("EYEWEAR (CHOOSE 1)", 0, null, null, null), + list("Welding Goggles", 0, /obj/item/clothing/glasses/welding, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR), + list("Medical HUD Glasses", 0, /obj/item/clothing/glasses/hud/health, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR), + list("Prescription Medical HUD Glasses", 0, /obj/item/clothing/glasses/hud/health/prescription, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR), + list("Sunglasses", 0, /obj/item/clothing/glasses/sunglasses, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_REGULAR), + list("ACCESSORIES (CHOOSE 1)", 0, null, null, null), list("Brown Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest/brown_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Black Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), @@ -68,9 +77,6 @@ GLOBAL_LIST_INIT(cm_vending_clothing_sea, list( list("HEADWEAR (CHOOSE 1)", 0, null, null, null), list("Drill Hat", 0, /obj/item/clothing/head/drillhat, MARINE_CAN_BUY_MASK, VENDOR_ITEM_RECOMMENDED), list("M10 Helmet", 0, /obj/item/clothing/head/helmet/marine, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_REGULAR), - - list("TOOLS OF THE TRADE", 0, null, null, null), - list("CPR Dummy", 5, /obj/item/cpr_dummy, null, VENDOR_ITEM_REGULAR) )) /obj/structure/machinery/cm_vending/clothing/sea diff --git a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm index 6877c2b4b5b3..0586f4b72fa5 100644 --- a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm +++ b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm @@ -76,6 +76,9 @@ else display_list = GLOB.cm_vending_vehicle_crew_tank_spare + else if(selected_vehicle == "ARC") + display_list = GLOB.cm_vending_vehicle_crew_arc + else if(selected_vehicle == "APC") if(available_categories) display_list = GLOB.cm_vending_vehicle_crew_apc @@ -245,6 +248,11 @@ GLOBAL_LIST_INIT(cm_vending_vehicle_crew_apc_spare, list( list("WHEELS", 0, null, null, null), list("APC Wheels", 200, /obj/item/hardpoint/locomotion/apc_wheels, null, VENDOR_ITEM_REGULAR))) +GLOBAL_LIST_INIT(cm_vending_vehicle_crew_arc, list( + list("STARTING KIT SELECTION:", 0, null, null, null), + + list("WHEELS", 0, null, null, null), + list("Replacement ARC Wheels", 0, /obj/item/hardpoint/locomotion/arc_wheels, VEHICLE_TREADS_AVAILABLE, VENDOR_ITEM_MANDATORY))) //------------WEAPONS RACK--------------- diff --git a/code/game/objects/items/devices/binoculars.dm b/code/game/objects/items/devices/binoculars.dm index 84da7d9acff4..b39526e231b5 100644 --- a/code/game/objects/items/devices/binoculars.dm +++ b/code/game/objects/items/devices/binoculars.dm @@ -354,13 +354,16 @@ /obj/item/device/binoculars/range/designator/scout name = "scout laser designator" desc = "An improved laser designator, issued to USCM scouts, with two modes: target marking for CAS with IR laser and rangefinding. Ctrl + Click turf to target something. Ctrl + Click designator to stop lasing. Alt + Click designator to switch modes." + unacidable = TRUE + indestructible = TRUE cooldown_duration = 80 target_acquisition_delay = 30 /obj/item/device/binoculars/range/designator/spotter name = "spotter's laser designator" desc = "A specially-designed laser designator, issued to USCM spotters, with two modes: target marking for CAS with IR laser and rangefinding. Ctrl + Click turf to target something. Ctrl + Click designator to stop lasing. Alt + Click designator to switch modes. Additionally, a trained spotter can laze targets for a USCM marksman, increasing the speed of target acquisition. A targeting beam will connect the binoculars to the target, but it may inherit the user's cloak, if possible." - + unacidable = TRUE + indestructible = TRUE var/is_spotting = FALSE var/spotting_time = 10 SECONDS var/spotting_cooldown_delay = 5 SECONDS diff --git a/code/game/objects/items/devices/cictablet.dm b/code/game/objects/items/devices/cictablet.dm index 664054fb59e2..de03f1779f2b 100644 --- a/code/game/objects/items/devices/cictablet.dm +++ b/code/game/objects/items/devices/cictablet.dm @@ -91,43 +91,43 @@ . = ..() if(.) return - + var/mob/user = ui.user switch(action) if("announce") - if(usr.client.prefs.muted & MUTE_IC) - to_chat(usr, SPAN_DANGER("You cannot send Announcements (muted).")) + if(user.client.prefs.muted & MUTE_IC) + to_chat(user, SPAN_DANGER("You cannot send Announcements (muted).")) return if(!COOLDOWN_FINISHED(src, announcement_cooldown)) - to_chat(usr, SPAN_WARNING("Please wait [COOLDOWN_TIMELEFT(src, announcement_cooldown)/10] second\s before making your next announcement.")) + to_chat(user, SPAN_WARNING("Please wait [COOLDOWN_TIMELEFT(src, announcement_cooldown)/10] second\s before making your next announcement.")) return FALSE - var/input = stripped_multiline_input(usr, "Please write a message to announce to the [MAIN_SHIP_NAME]'s crew and all groundside personnel.", "Priority Announcement", "") - if(!input || !COOLDOWN_FINISHED(src, announcement_cooldown) || !(usr in view(1, src))) + var/input = stripped_multiline_input(user, "Please write a message to announce to the [MAIN_SHIP_NAME]'s crew and all groundside personnel.", "Priority Announcement", "") + if(!input || !COOLDOWN_FINISHED(src, announcement_cooldown) || !(user in view(1, src))) return FALSE var/signed = null - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - var/obj/item/card/id/id = H.wear_id + if(ishuman(user)) + var/mob/living/carbon/human/human_user = user + var/obj/item/card/id/id = human_user.wear_id if(istype(id)) - var/paygrade = get_paygrades(id.paygrade, FALSE, H.gender) + var/paygrade = get_paygrades(id.paygrade, FALSE, human_user.gender) signed = "[paygrade] [id.registered_name]" marine_announcement(input, announcement_title, faction_to_display = announcement_faction, add_PMCs = add_pmcs, signature = signed) - message_admins("[key_name(usr)] has made a command announcement.") - log_announcement("[key_name(usr)] has announced the following: [input]") + message_admins("[key_name(user)] has made a command announcement.") + log_announcement("[key_name(user)] has announced the following: [input]") COOLDOWN_START(src, announcement_cooldown, cooldown_between_messages) . = TRUE if("award") if(announcement_faction != FACTION_MARINE) return - open_medal_panel(usr, src) + open_medal_panel(user, src) . = TRUE if("mapview") - tacmap.tgui_interact(usr) + tacmap.tgui_interact(user) . = TRUE if("evacuation_start") @@ -135,20 +135,20 @@ return if(GLOB.security_level < SEC_LEVEL_RED) - to_chat(usr, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) + to_chat(user, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) return FALSE if(SShijack.evac_admin_denied) - to_chat(usr, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) + to_chat(user, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) return FALSE if(!SShijack.initiate_evacuation()) - to_chat(usr, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) + to_chat(user, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) return FALSE - log_game("[key_name(usr)] has called for an emergency evacuation.") - message_admins("[key_name_admin(usr)] has called for an emergency evacuation.") - log_ares_security("Initiate Evacuation", "[usr] has called for an emergency evacuation.") + log_game("[key_name(user)] has called for an emergency evacuation.") + message_admins("[key_name_admin(user)] has called for an emergency evacuation.") + log_ares_security("Initiate Evacuation", "Called for an emergency evacuation.", user) . = TRUE if("distress") @@ -156,14 +156,14 @@ return FALSE //Not a game mode? if(GLOB.security_level == SEC_LEVEL_DELTA) - to_chat(usr, SPAN_WARNING("The ship is already undergoing self destruct procedures!")) + to_chat(user, SPAN_WARNING("The ship is already undergoing self destruct procedures!")) return FALSE for(var/client/C in GLOB.admins) if((R_ADMIN|R_MOD) & C.admin_holder.rights) playsound_client(C,'sound/effects/sos-morse-code.ogg',10) - SSticker.mode.request_ert(usr) - to_chat(usr, SPAN_NOTICE("A distress beacon request has been sent to USCM Central Command.")) + SSticker.mode.request_ert(user) + to_chat(user, SPAN_NOTICE("A distress beacon request has been sent to USCM Central Command.")) COOLDOWN_START(src, distress_cooldown, COOLDOWN_COMM_REQUEST) return TRUE diff --git a/code/game/objects/items/frames/table_rack.dm b/code/game/objects/items/frames/table_rack.dm index c7aa53a2c4c1..eda9b9c5749b 100644 --- a/code/game/objects/items/frames/table_rack.dm +++ b/code/game/objects/items/frames/table_rack.dm @@ -100,6 +100,7 @@ desc = "A kit for a table, including a large, flat wooden surface and four legs. Some assembly required." icon_state = "wood_tableparts" flags_atom = FPRINT + matter = null table_type = /obj/structure/surface/table/woodentable /obj/item/frame/table/wood/attackby(obj/item/W, mob/user) @@ -140,6 +141,7 @@ desc = "A kit for a table, including a large, flat wooden and carpet surface and four legs. Some assembly required." icon_state = "gamble_tableparts" flags_atom = null + matter = null table_type = /obj/structure/surface/table/gamblingtable /obj/item/frame/table/gambling/attackby(obj/item/W as obj, mob/user as mob) diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 5e4bc8c726bd..4882db3b83ea 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -729,6 +729,8 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r name = "\improper M68 Thermal Cloak" desc = "The lightweight thermal dampeners and optical camouflage provided by this cloak are weaker than those found in standard USCM ghillie suits. In exchange, the cloak can be worn over combat armor and offers the wearer high maneuverability and adaptability to many environments." icon_state = "scout_cloak" + unacidable = TRUE + indestructible = TRUE uniform_restricted = list(/obj/item/clothing/suit/storage/marine/M3S) //Need to wear Scout armor and helmet to equip this. has_gamemode_skin = FALSE //same sprite for all gamemode. var/camo_active = FALSE diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 3e7c00f3d0ff..201e34654624 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -510,6 +510,34 @@ /obj/item/storage/pill_bottle/proc/error_idlock(mob/user) to_chat(user, SPAN_WARNING("It must have some kind of ID lock...")) +/obj/item/storage/pill_bottle/proc/choose_color(mob/user) + if(!user) + user = usr + var/static/list/possible_colors = list( + "Orange" = "", + "Blue" = "1", + "Yellow" = "2", + "Light Purple" = "3", + "Light Grey" = "4", + "White" = "5", + "Light Green" = "6", + "Cyan" = "7", + "Bordeaux" = "8", + "Aquamarine" = "9", + "Grey" = "10", + "Red" = "11", + "Black" = "12", + ) + var/selected_color = tgui_input_list(user, "Select a color.", "Color choice", possible_colors) + if(!selected_color) + return + + selected_color = possible_colors[selected_color] + + icon_state = "pill_canister" + selected_color + to_chat(user, SPAN_NOTICE("You color [src].")) + update_icon() + /obj/item/storage/pill_bottle/verb/set_maptext() set category = "Object" set name = "Set short label (on-sprite)" diff --git a/code/game/objects/items/tools/misc_tools.dm b/code/game/objects/items/tools/misc_tools.dm index 06f42aacd56c..b016f0e67b33 100644 --- a/code/game/objects/items/tools/misc_tools.dm +++ b/code/game/objects/items/tools/misc_tools.dm @@ -58,6 +58,10 @@ if(isturf(A)) to_chat(user, SPAN_WARNING("The label won't stick to that.")) return + if(istype(A, /obj/item/storage/pill_bottle)) + var/obj/item/storage/pill_bottle/target_pill_bottle = A + target_pill_bottle.choose_color(user) + if(!label || !length(label)) remove_label(A, user) return diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index a3febb11dddb..70dc5ff1786d 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -208,6 +208,9 @@ /obj/proc/hear_talk(mob/living/M as mob, msg, verb="says", datum/language/speaking, italics = 0) return +/obj/proc/see_emote(mob/living/M as mob, emote, audible = FALSE) + return + /obj/attack_hand(mob/user) if(can_buckle) manual_unbuckle(user) else . = ..() @@ -231,7 +234,7 @@ /obj/proc/afterbuckle(mob/M as mob) // Called after somebody buckled / unbuckled handle_rotation() // To be removed when we have full dir support in set_buckled - SEND_SIGNAL(src, COSMIG_OBJ_AFTER_BUCKLE, buckled_mob) + SEND_SIGNAL(src, COMSIG_OBJ_AFTER_BUCKLE, buckled_mob) if(!buckled_mob) UnregisterSignal(M, COMSIG_PARENT_QDELETING) else diff --git a/code/game/objects/structures/bookcase.dm b/code/game/objects/structures/bookcase.dm index b310bd00aa07..a6fc95fa0d73 100644 --- a/code/game/objects/structures/bookcase.dm +++ b/code/game/objects/structures/bookcase.dm @@ -7,6 +7,24 @@ density = TRUE opacity = TRUE +/obj/structure/bookcase/deconstruct(disassembled) + new /obj/item/stack/sheet/metal(loc) + return ..() + +/obj/structure/bookcase/attack_alien(mob/living/carbon/xenomorph/xeno) + if(xeno.a_intent == INTENT_HARM) + if(unslashable) + return + xeno.animation_attack_on(src) + playsound(loc, 'sound/effects/metalhit.ogg', 25, 1) + xeno.visible_message(SPAN_DANGER("[xeno] slices [src] apart!"), + SPAN_DANGER("We slice [src] apart!"), null, 5, CHAT_TYPE_XENO_COMBAT) + deconstruct(FALSE) + return XENO_ATTACK_ACTION + else + attack_hand(xeno) + return XENO_NONCOMBAT_ACTION + /obj/structure/bookcase/Initialize() . = ..() for(var/obj/item/I in loc) @@ -20,12 +38,18 @@ O.forceMove(src) update_icon() else if(HAS_TRAIT(O, TRAIT_TOOL_PEN)) - var/newname = stripped_input(usr, "What would you like to title this bookshelf?") + var/newname = stripped_input(user, "What would you like to title this bookshelf?") if(!newname) return else name = ("bookcase ([strip_html(newname)])") playsound(src, "paper_writing", 15, TRUE) + else if(HAS_TRAIT(O, TRAIT_TOOL_WRENCH)) + playsound(loc, 'sound/items/Ratchet.ogg', 25, 1) + if(do_after(user, 1 SECONDS, INTERRUPT_MOVED, BUSY_ICON_FRIENDLY, src)) + user.visible_message("[user] deconstructs [src].", \ + "You deconstruct [src].", "You hear a noise.") + deconstruct(FALSE) else ..() @@ -33,7 +57,7 @@ if(contents.len) var/obj/item/book/choice = input("Which book would you like to remove from the shelf?") as null|obj in contents if(choice) - if(usr.is_mob_incapacitated() || !in_range(loc, usr)) + if(user.is_mob_incapacitated() || !in_range(loc, user)) return if(ishuman(user)) if(!user.get_active_hand()) @@ -67,7 +91,7 @@ /obj/structure/bookcase/manuals/medical - name = "Medical Manuals bookcase" + name = "medical manuals bookcase" /obj/structure/bookcase/manuals/medical/Initialize() . = ..() @@ -78,7 +102,7 @@ /obj/structure/bookcase/manuals/engineering - name = "Engineering Manuals bookcase" + name = "engineering manuals bookcase" /obj/structure/bookcase/manuals/engineering/Initialize() . = ..() @@ -90,7 +114,7 @@ update_icon() /obj/structure/bookcase/manuals/research_and_development - name = "R&D Manuals bookcase" + name = "\improper R&D manuals bookcase" /obj/structure/bookcase/manuals/research_and_development/Initialize() . = ..() diff --git a/code/game/objects/structures/platforms.dm b/code/game/objects/structures/platforms.dm index cfffbc90fb7c..5510d319ee1e 100644 --- a/code/game/objects/structures/platforms.dm +++ b/code/game/objects/structures/platforms.dm @@ -142,7 +142,6 @@ icon_state = "kutjevo_platform" name = "raised metal edge" desc = "A raised level of metal, often used to elevate areas above others, or construct bridges. You could probably climb it." - climb_delay = 10 /obj/structure/platform_decoration/kutjevo name = "raised metal corner" diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 482139c03707..03c554af3426 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -412,6 +412,7 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) "Operations", "Weapons", "Vehicle Ammo", + "Vehicle Equipment", "Attachments", "Ammo", "Weapons Specialist Ammo", @@ -1367,6 +1368,13 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) name = "Barebones M577 Armored Personal Carrier" ordered_vehicle = /obj/effect/vehicle_spawner/apc/unarmed/broken +/datum/vehicle_order/arc + name = "M540-B Armored Recon Carrier" + ordered_vehicle = /obj/effect/vehicle_spawner/arc + +/datum/vehicle_order/arc/has_vehicle_lock() + return + /obj/structure/machinery/computer/supplycomp/vehicle/Initialize() . = ..() diff --git a/code/game/turfs/floor_types.dm b/code/game/turfs/floor_types.dm index 8a8698d0c047..0a1842134480 100644 --- a/code/game/turfs/floor_types.dm +++ b/code/game/turfs/floor_types.dm @@ -325,12 +325,21 @@ /turf/open/floor/almayer/aicore/glowing icon_state = "ai_floor2" light_color = "#d69c46" - light_range = 2 + light_range = 3 /turf/open/floor/almayer/aicore/glowing/Initialize(mapload, ...) . = ..() set_light_on(TRUE) + RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LOCKDOWN, PROC_REF(start_emergency_light_on)) + RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LIFT, PROC_REF(start_emergency_light_off)) + +/turf/open/floor/almayer/aicore/glowing/proc/start_emergency_light_on() + set_light(l_color = "#c70f0f") + +/turf/open/floor/almayer/aicore/glowing/proc/start_emergency_light_off() + set_light(l_color = "#d69c46") + /turf/open/floor/almayer/aicore/no_build allow_construction = FALSE hull_floor = TRUE diff --git a/code/game/turfs/walls/walls.dm b/code/game/turfs/walls/walls.dm index 251b23ad9c57..1781739176b7 100644 --- a/code/game/turfs/walls/walls.dm +++ b/code/game/turfs/walls/walls.dm @@ -9,7 +9,7 @@ var/hull = 0 var/walltype = WALL_METAL /// when walls smooth with one another, the type of junction each wall is. - var/junctiontype + var/junctiontype var/thermite = 0 var/melting = FALSE var/claws_minimum = CLAW_TYPE_SHARP @@ -24,7 +24,7 @@ var/damage = 0 /// Wall will break down to girders if damage reaches this point - var/damage_cap = HEALTH_WALL + var/damage_cap = HEALTH_WALL var/damage_overlay var/global/damage_overlays[8] @@ -38,7 +38,7 @@ var/d_state = 0 //Normal walls are now as difficult to remove as reinforced walls /// the acid hole inside the wall - var/obj/effect/acid_hole/acided_hole + var/obj/effect/acid_hole/acided_hole var/acided_hole_dir = SOUTH var/special_icon = 0 @@ -178,7 +178,7 @@ switch(d_state) if(WALL_STATE_WELD) - . += SPAN_INFO("The outer plating is intact. A blowtorch should slice it open.") + . += SPAN_INFO("The outer plating is intact. If you are not on help intent, a blowtorch should slice it open.") if(WALL_STATE_SCREW) . += SPAN_INFO("The outer plating has been sliced open. A screwdriver should remove the support lines.") if(WALL_STATE_WIRECUTTER) @@ -482,6 +482,8 @@ /turf/closed/wall/proc/try_weldingtool_usage(obj/item/W, mob/user) if(!damage || !iswelder(W)) return FALSE + if(user.a_intent != INTENT_HELP) + return FALSE var/obj/item/tool/weldingtool/WT = W if(WT.remove_fuel(0, user)) @@ -504,6 +506,8 @@ if(!(WT.remove_fuel(0, user))) to_chat(user, SPAN_WARNING("You need more welding fuel!")) return + if(user.a_intent == INTENT_HELP) + return playsound(src, 'sound/items/Welder.ogg', 25, 1) user.visible_message(SPAN_NOTICE("[user] begins slicing through the outer plating."), diff --git a/code/game/verbs/records.dm b/code/game/verbs/records.dm index 05506804790a..3810bf7e99cb 100644 --- a/code/game/verbs/records.dm +++ b/code/game/verbs/records.dm @@ -1,10 +1,8 @@ -//CO Whitelist is '1', Synthetic Whitelist is '2', Yautja Whitelist is '3'. - /client/verb/own_records() set name = "View Own Records" set category = "OOC.Records" - var/list/options = list("Admin", "Merit", "Commanding Officer", "Synthetic", "Yautja") + var/list/options = list("Admin", "Merit", "Whitelist") var/choice = tgui_input_list(usr, "What record do you wish to view?", "Record Choice", options) switch(choice) @@ -12,12 +10,8 @@ show_own_notes(NOTE_ADMIN, choice) if("Merit") show_own_notes(NOTE_MERIT, choice) - if("Commanding Officer") - show_own_notes(NOTE_COMMANDER, choice) - if("Synthetic") - show_own_notes(NOTE_SYNTHETIC, choice) - if("Yautja") - show_own_notes(NOTE_YAUTJA, choice) + if("Whitelist") + show_own_notes(NOTE_WHITELIST, choice) else return to_chat(usr, SPAN_NOTICE("Displaying your [choice] Record.")) @@ -46,12 +40,8 @@ switch(note_category) if(NOTE_MERIT) color = "#9e3dff" - if(NOTE_COMMANDER) + if(NOTE_WHITELIST) color = "#324da5" - if(NOTE_SYNTHETIC) - color = "#39e7a4" - if(NOTE_YAUTJA) - color = "#114e11" dat += "[N.text] by [admin_ckey] ([N.admin_rank]) on [N.date] [NOTE_ROUND_ID(N)] " dat += "

" @@ -69,16 +59,15 @@ //Contributions and suggestions are welcome. //Kindly, forest2001 -/client/verb/other_records() +/client/proc/other_records() set name = "View Target Records" set category = "OOC.Records" ///Management Access - var/MA + var/manager = FALSE ///Edit Access - var/edit_C = FALSE - var/edit_S = FALSE - var/edit_Y = FALSE + var/add_wl = FALSE + var/del_wl = FALSE ///Note category options var/list/options = list() @@ -86,7 +75,7 @@ if(CLIENT_IS_STAFF(src)) options = GLOB.note_categories.Copy() if(admin_holder.rights & R_PERMISSIONS) - MA = TRUE + manager = TRUE else if(!isCouncil(src)) to_chat(usr, SPAN_WARNING("Error: you are not authorised to view the records of another player!")) return @@ -97,15 +86,11 @@ return target = ckey(target) - if(check_whitelist_status(WHITELIST_COMMANDER_COUNCIL)) - options |= "Commanding Officer" - edit_C = TRUE - if(check_whitelist_status(WHITELIST_SYNTHETIC_COUNCIL)) - options |= "Synthetic" - edit_S = TRUE - if(check_whitelist_status(WHITELIST_YAUTJA_COUNCIL)) - options |= "Yautja" - edit_Y = TRUE + if(manager || isCouncil(src)) + options |= "Whitelist" + add_wl = TRUE + if(manager || isSenator(src)) + del_wl = TRUE var/choice = tgui_input_list(usr, "What record do you wish to view?", "Record Choice", options) if(!choice) @@ -115,21 +100,8 @@ show_other_record(NOTE_ADMIN, choice, target, TRUE) if("Merit") show_other_record(NOTE_MERIT, choice, target, TRUE) - if("Commanding Officer") - if(MA || check_whitelist_status(WHITELIST_COMMANDER_LEADER)) - show_other_record(NOTE_COMMANDER, choice, target, TRUE, TRUE) - else - show_other_record(NOTE_COMMANDER, choice, target, edit_C) - if("Synthetic") - if(MA || check_whitelist_status(WHITELIST_SYNTHETIC_LEADER)) - show_other_record(NOTE_SYNTHETIC, choice, target, TRUE, TRUE) - else - show_other_record(NOTE_SYNTHETIC, choice, target, edit_S) - if("Yautja") - if(MA || check_whitelist_status(WHITELIST_YAUTJA_LEADER)) - show_other_record(NOTE_YAUTJA, choice, target, TRUE, TRUE) - else - show_other_record(NOTE_YAUTJA, choice, target, edit_Y) + if("Whitelist") + show_other_record(NOTE_WHITELIST, choice, target, add_wl, del_wl) to_chat(usr, SPAN_NOTICE("Displaying [target]'s [choice] notes.")) @@ -148,15 +120,9 @@ if(NOTE_MERIT) color = "#9e3dff" add_dat = "Add Merit Note
" - if(NOTE_COMMANDER) + if(NOTE_WHITELIST) color = "#324da5" - add_dat = "Add Commander Note
" - if(NOTE_SYNTHETIC) - color = "#39e7a4" - add_dat = "Add Synthetic Note
" - if(NOTE_YAUTJA) - color = "#114e11" - add_dat = "Add Yautja Note
" + add_dat = "Add Whitelist Note
" var/list/datum/view_record/note_view/NL = DB_VIEW(/datum/view_record/note_view, DB_COMP("player_ckey", DB_EQUALS, target)) for(var/datum/view_record/note_view/N as anything in NL) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 4194627262a4..979217019f0c 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -95,12 +95,8 @@ color = "#AA0055" else if(N.note_category == NOTE_MERIT) color = "#9e3dff" - else if(N.note_category == NOTE_COMMANDER) + else if(N.note_category == NOTE_WHITELIST) color = "#324da5" - else if(N.note_category == NOTE_SYNTHETIC) - color = "#39e7a4" - else if(N.note_category == NOTE_YAUTJA) - color = "#114e11" dat += "[N.text] by [admin_ckey] ([N.admin_rank])[confidential_text] on [N.date] [NOTE_ROUND_ID(N)] " if(admin_ckey == usr.ckey || admin_ckey == "Adminbot" || check_for_rights(R_PERMISSIONS)) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 626758fc2a5a..aa87f157173c 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -72,6 +72,7 @@ GLOBAL_LIST_INIT(admin_verbs_default, list( /client/proc/cmd_admin_say, /*staff-only ooc chat*/ /client/proc/cmd_mod_say, /* alternate way of typing asay, no different than cmd_admin_say */ /client/proc/cmd_admin_tacmaps_panel, + /client/proc/other_records, )) GLOBAL_LIST_INIT(admin_verbs_admin, list( @@ -138,6 +139,7 @@ GLOBAL_LIST_INIT(admin_verbs_minor_event, list( /client/proc/adminpanelweapons, /client/proc/admin_general_quarters, /client/proc/admin_biohazard_alert, + /client/proc/admin_aicore_alert, /client/proc/toggle_hardcore_perma, /client/proc/toggle_bypass_joe_restriction, /client/proc/toggle_joe_respawns, diff --git a/code/modules/almayer/machinery.dm b/code/modules/almayer/machinery.dm index 74ce9a81eb88..9411c229d2f3 100644 --- a/code/modules/almayer/machinery.dm +++ b/code/modules/almayer/machinery.dm @@ -73,7 +73,7 @@ /obj/structure/machinery/prop/almayer/CICmap name = "map table" - desc = "A table that displays a map of the current target location" + desc = "A table that displays a map of the current operation location." icon = 'icons/obj/structures/machinery/computer.dmi' icon_state = "maptable" anchored = TRUE @@ -103,6 +103,11 @@ map.tgui_interact(user) +/obj/structure/machinery/prop/almayer/CICmap/computer + name = "map terminal" + desc = "A terminal that displays a map of the current operation location." + icon_state = "security" + /obj/structure/machinery/prop/almayer/CICmap/upp minimap_type = MINIMAP_FLAG_UPP faction = FACTION_UPP diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 213c54f0e201..6afbfa695db2 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -187,39 +187,21 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( var/datum/entity/player/P = get_player_from_key(key) P.add_note(add, FALSE, NOTE_MERIT) - if(href_list["add_wl_info_1"]) - var/key = href_list["add_wl_info_1"] - var/add = input("Add Commander Note") as null|message + if(href_list["add_wl_info"]) + var/key = href_list["add_wl_info"] + var/add = input("Add Whitelist Note") as null|message if(!add) return var/datum/entity/player/P = get_player_from_key(key) - P.add_note(add, FALSE, NOTE_COMMANDER) - - if(href_list["add_wl_info_2"]) - var/key = href_list["add_wl_info_2"] - var/add = input("Add Synthetic Note") as null|message - if(!add) - return - - var/datum/entity/player/P = get_player_from_key(key) - P.add_note(add, FALSE, NOTE_SYNTHETIC) - - if(href_list["add_wl_info_3"]) - var/key = href_list["add_wl_info_3"] - var/add = input("Add Yautja Note") as null|message - if(!add) - return - - var/datum/entity/player/P = get_player_from_key(key) - P.add_note(add, FALSE, NOTE_YAUTJA) + P.add_note(add, FALSE, NOTE_WHITELIST) if(href_list["remove_wl_info"]) var/key = href_list["remove_wl_info"] var/index = text2num(href_list["remove_index"]) var/datum/entity/player/P = get_player_from_key(key) - P.remove_note(index) + P.remove_note(index, whitelist = TRUE) switch(href_list["_src_"]) if("admin_holder") diff --git a/code/modules/cm_marines/dropship_equipment.dm b/code/modules/cm_marines/dropship_equipment.dm index bd40076ea500..af06f468adcd 100644 --- a/code/modules/cm_marines/dropship_equipment.dm +++ b/code/modules/cm_marines/dropship_equipment.dm @@ -524,12 +524,6 @@ if(light_on) set_light(0) -/obj/structure/dropship_equipment/electronics/spotlights/on_launch() - set_light(0) - -/obj/structure/dropship_equipment/electronics/spotlights/on_arrival() - set_light(brightness) - /obj/structure/dropship_equipment/electronics/spotlights/ui_data(mob/user) . = list() var/is_deployed = light_on diff --git a/code/modules/cm_marines/overwatch.dm b/code/modules/cm_marines/overwatch.dm index 70b2b82d8c86..500d575c053f 100644 --- a/code/modules/cm_marines/overwatch.dm +++ b/code/modules/cm_marines/overwatch.dm @@ -867,6 +867,9 @@ /obj/structure/machinery/computer/overwatch/almayer/broken name = "Broken Overwatch Console" +/obj/structure/machinery/computer/overwatch/almayer/small + icon_state = "engineering_terminal" + /obj/structure/machinery/computer/overwatch/clf faction = FACTION_CLF /obj/structure/machinery/computer/overwatch/upp diff --git a/code/modules/cm_tech/techs/marine/tier1/arc.dm b/code/modules/cm_tech/techs/marine/tier1/arc.dm new file mode 100644 index 000000000000..dc02762cc5f0 --- /dev/null +++ b/code/modules/cm_tech/techs/marine/tier1/arc.dm @@ -0,0 +1,40 @@ +/datum/tech/arc + name = "M540-B Armored Recon Carrier" + desc = "Purchase an M540-B Armored Recon Carrier, specialized in assisting groundside command. Able to be driven by Staff Officers, Executive Officers, and Commanding Officers." + icon_state = "upgrade" + + required_points = 5 + + tier = /datum/tier/one + + announce_name = "M540-B ARC ACQUIRED" + announce_message = "An M540-B Armored Recon Carrier has been authorized and will be delivered in the vehicle bay." + + flags = TREE_FLAG_MARINE + +/datum/tech/arc/on_unlock() + . = ..() + + var/obj/structure/machinery/computer/supplycomp/vehicle/comp = GLOB.VehicleElevatorConsole + var/obj/structure/machinery/cm_vending/gear/vehicle_crew/gearcomp = GLOB.VehicleGearConsole + + if(!comp || !gearcomp) + return FALSE + + comp.spent = FALSE + QDEL_NULL_LIST(comp.vehicles) + comp.vehicles = list( + new /datum/vehicle_order/arc() + ) + comp.allowed_roles = list(JOB_SYNTH, JOB_SEA, JOB_SO, JOB_XO, JOB_CO, JOB_GENERAL) + comp.req_access = list(ACCESS_MARINE_COMMAND) + comp.req_one_access = list() + comp.spent = FALSE + + gearcomp.req_access = list(ACCESS_MARINE_COMMAND) + gearcomp.req_one_access = list() + gearcomp.vendor_role = list() + gearcomp.selected_vehicle = "ARC" + gearcomp.available_categories = VEHICLE_ALL_AVAILABLE + + return TRUE diff --git a/code/modules/defenses/sentry.dm b/code/modules/defenses/sentry.dm index a02e4e7808c9..954e6adca7ec 100644 --- a/code/modules/defenses/sentry.dm +++ b/code/modules/defenses/sentry.dm @@ -365,7 +365,7 @@ targets.Remove(A) continue - if(M.get_target_lock(faction_group) || M.invisibility || HAS_TRAIT(M, TRAIT_ABILITY_BURROWED)) + if(M.get_target_lock(faction_group) || M.invisibility || HAS_TRAIT(M, TRAIT_ABILITY_BURROWED) || M.is_ventcrawling) if(M == target) target = null targets.Remove(M) diff --git a/code/modules/gear_presets/clf.dm b/code/modules/gear_presets/clf.dm index 143a2271f00e..bb168f22457b 100644 --- a/code/modules/gear_presets/clf.dm +++ b/code/modules/gear_presets/clf.dm @@ -71,6 +71,7 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/belt/shotgun/full/random(new_human), WEAR_WAIST) new_human.equip_to_slot_or_del(new /obj/item/weapon/gun/shotgun/pump/dual_tube/cmb(new_human), WEAR_BACK) + new_human.equip_to_slot_or_del(new /obj/item/attachable/bayonet/upp(new_human), WEAR_FACE) if(prob(50)) spawn_rebel_smg(new_human) else @@ -176,6 +177,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/head/welding, WEAR_HEAD) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/utility/full(new_human), WEAR_WAIST) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/CLF/cct, WEAR_L_EAR) + new_human.equip_to_slot_or_del(new /obj/item/attachable/bayonet/upp(new_human), WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/engineerpack/ert, WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/explosive/plastic/breaching_charge, WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/explosive/plastic/breaching_charge, WEAR_IN_BACK) @@ -300,6 +302,7 @@ new_human.equip_to_slot_or_del(new /obj/item/roller, WEAR_IN_BELT) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/CLF/medic(new_human), WEAR_L_EAR) + new_human.equip_to_slot_or_del(new /obj/item/attachable/bayonet/upp(new_human), WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/lightpack(new_human), WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/explosive/grenade/custom/ied(new_human), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/storage/firstaid/adv(new_human), WEAR_IN_BACK) @@ -455,6 +458,7 @@ //clothing new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/militia(new_human), WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(new_human), WEAR_HEAD) + new_human.equip_to_slot_or_del(new /obj/item/attachable/bayonet/upp(new_human), WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(new_human), WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/gun/m4a3/mod88(new_human), WEAR_WAIST) @@ -574,6 +578,7 @@ new_human.equip_to_slot_or_del(new /obj/item/clothing/under/colonist/clf(new_human), WEAR_BODY) new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/militia(new_human), WEAR_JACKET) new_human.equip_to_slot_or_del(new /obj/item/clothing/head/beret/sec/hos(new_human), WEAR_HEAD) + new_human.equip_to_slot_or_del(new /obj/item/attachable/bayonet/upp(new_human), WEAR_FACE) new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(new_human), WEAR_FEET) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(new_human), WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/storage/belt/marine(new_human), WEAR_WAIST) diff --git a/code/modules/gear_presets/wy_goons.dm b/code/modules/gear_presets/wy_goons.dm index a8f3a443311e..7867016491dc 100644 --- a/code/modules/gear_presets/wy_goons.dm +++ b/code/modules/gear_presets/wy_goons.dm @@ -62,7 +62,7 @@ assignment = JOB_WY_GOON rank = JOB_WY_GOON paygrade = PAY_SHORT_CPO - skills = /datum/skills/MP + skills = /datum/skills/wy_goon /datum/equipment_preset/goon/standard/load_gear(mob/living/carbon/human/new_human) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/WY, WEAR_L_EAR) @@ -88,6 +88,40 @@ new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/ap, WEAR_IN_BACK) +/datum/equipment_preset/goon/engineer + name = "Weyland-Yutani Corporate Security Technician (Goon Engineer)" + flags = EQUIPMENT_PRESET_EXTRA + + assignment = JOB_WY_GOON_TECH + rank = JOB_WY_GOON_TECH + paygrade = PAY_SHORT_CPO + skills = /datum/skills/wy_goon_tech + +/datum/equipment_preset/goon/engineer/load_gear(mob/living/carbon/human/new_human) + new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/distress/WY, WEAR_L_EAR) + new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/veteran/pmc/corporate, WEAR_BODY) + new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/marine/veteran/pmc/light/corporate, WEAR_JACKET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran, WEAR_HANDS) + new_human.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/marine/veteran/pmc/corporate, WEAR_HEAD) + new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/welding, WEAR_EYES) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/corporate, WEAR_FEET) + + new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/engineerpack/ert, WEAR_BACK) + new_human.equip_to_slot_or_del(new /obj/item/weapon/baton, WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/handcuffs/zip, WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle, WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle, WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle, WEAR_IN_BACK) + + new_human.equip_to_slot_or_del(new /obj/item/storage/belt/utility/full, WEAR_WAIST) + new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/firstaid/full, WEAR_R_STORE) + new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/construction/full, WEAR_L_STORE) + + new_human.equip_to_slot_or_del(new /obj/item/weapon/gun/rifle/m41a/corporate, WEAR_J_STORE) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/ap, WEAR_IN_JACKET) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/rifle/ap, WEAR_IN_JACKET) + + /datum/equipment_preset/goon/lead name = "Weyland-Yutani Corporate Security Lead (Goon Lead)" flags = EQUIPMENT_PRESET_EXTRA @@ -95,7 +129,7 @@ assignment = JOB_WY_GOON_LEAD rank = JOB_WY_GOON_LEAD paygrade = PAY_SHORT_CSPO - skills = /datum/skills/MP + skills = /datum/skills/wy_goon_lead /datum/equipment_preset/goon/lead/New() . = ..() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 4e71b178824d..bc7d11c25e1f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1687,3 +1687,11 @@ INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living/carbon/human, update_body), 1, 0) INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living/carbon/human, update_hair)) + +/mob/living/carbon/human/point_to_atom(atom/A, turf/T) + if(isitem(A)) + var/obj/item/item = A + if(item == get_active_hand() || item == get_inactive_hand()) + item.showoff(src) + return TRUE + return ..() diff --git a/code/modules/mob/living/carbon/human/human_abilities.dm b/code/modules/mob/living/carbon/human/human_abilities.dm index a568e93df5c0..2d7f472952cc 100644 --- a/code/modules/mob/living/carbon/human/human_abilities.dm +++ b/code/modules/mob/living/carbon/human/human_abilities.dm @@ -605,3 +605,26 @@ CULT var/mob/living/carbon/human/human_user = owner SEND_SIGNAL(human_user, COMSIG_MOB_MG_EXIT) + +/datum/action/human_action/toggle_arc_antenna + name = "Toggle Sensor Antenna" + action_icon_state = "recoil_compensation" + +/datum/action/human_action/toggle_arc_antenna/give_to(mob/user) + . = ..() + RegisterSignal(user, COMSIG_MOB_RESET_VIEW, PROC_REF(remove_from)) + +/datum/action/human_action/toggle_arc_antenna/remove_from(mob/user) + . = ..() + UnregisterSignal(user, COMSIG_MOB_RESET_VIEW) + +/datum/action/human_action/toggle_arc_antenna/action_activate() + if(!can_use_action()) + return + + var/mob/living/carbon/human/human_user = owner + if(istype(human_user.buckled, /obj/structure/bed/chair/comfy/vehicle)) + var/obj/structure/bed/chair/comfy/vehicle/vehicle_chair = human_user.buckled + if(istype(vehicle_chair.vehicle, /obj/vehicle/multitile/arc)) + var/obj/vehicle/multitile/arc/vehicle = vehicle_chair.vehicle + vehicle.toggle_antenna(human_user) diff --git a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm index 8aa3000092f5..9a87f10d74a3 100644 --- a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm +++ b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm @@ -281,7 +281,7 @@ if(isturf(human.loc)) forceMove(human.loc)//Just checkin - if(!human.handle_hugger_attachment(src)) + if(!human.handle_hugger_attachment(src, hugger)) return FALSE attached = TRUE @@ -413,9 +413,6 @@ M.stored_huggers++ qdel(src) return - // Tutorial facehuggers never time out - if(hivenumber == XENO_HIVE_TUTORIAL) - return die() /obj/item/clothing/mask/facehugger/proc/die() @@ -441,12 +438,15 @@ playsound(src.loc, 'sound/voice/alien_facehugger_dies.ogg', 25, 1) if(ismob(loc)) //Make it fall off the person so we can update their icons. Won't update if they're in containers thou - var/mob/M = loc - M.drop_inv_item_on_ground(src) + var/mob/holder_mob = loc + holder_mob.drop_inv_item_on_ground(src) layer = TURF_LAYER //so dead hugger appears below live hugger if stacked on same tile. (and below nested hosts) - addtimer(CALLBACK(src, PROC_REF(decay)), 3 MINUTES) + if(hivenumber == XENO_HIVE_TUTORIAL) + addtimer(CALLBACK(src, PROC_REF(decay)), 5 SECONDS) + else + addtimer(CALLBACK(src, PROC_REF(decay)), 3 MINUTES) /obj/item/clothing/mask/facehugger/proc/decay() visible_message("[icon2html(src, viewers(src))] \The [src] decays into a mass of acid and chitin.") @@ -491,15 +491,14 @@ /** * Human hugger handling */ - -/mob/living/carbon/human/proc/handle_hugger_attachment(obj/item/clothing/mask/facehugger/hugger) +/mob/living/carbon/human/proc/handle_hugger_attachment(obj/item/clothing/mask/facehugger/hugger, mob/living/carbon/xenomorph/facehugger/mob_hugger) var/can_infect = TRUE if(!has_limb("head")) hugger.visible_message(SPAN_WARNING("[hugger] looks for a face to hug on [src], but finds none!")) hugger.go_idle() return FALSE - if(species && !species.handle_hugger_attachment(src, hugger)) + if(species && !species.handle_hugger_attachment(src, hugger, mob_hugger)) return FALSE if(head && !(head.flags_item & NODROP)) @@ -546,10 +545,10 @@ return can_infect -/datum/species/proc/handle_hugger_attachment(mob/living/carbon/human/target, obj/item/clothing/mask/facehugger/hugger) +/datum/species/proc/handle_hugger_attachment(mob/living/carbon/human/target, obj/item/clothing/mask/facehugger/hugger, mob/living/carbon/xenomorph/facehugger/mob_hugger) return TRUE -/datum/species/yautja/handle_hugger_attachment(mob/living/carbon/human/target, obj/item/clothing/mask/facehugger/hugger) +/datum/species/yautja/handle_hugger_attachment(mob/living/carbon/human/target, obj/item/clothing/mask/facehugger/hugger, mob/living/carbon/xenomorph/facehugger/mob_hugger) var/catch_chance = 50 if(target.dir == GLOB.reverse_dir[hugger.dir]) catch_chance += 20 @@ -563,7 +562,10 @@ if(!target.stat && target.dir != hugger.dir && prob(catch_chance)) //Not facing away target.visible_message(SPAN_NOTICE("[target] snatches [hugger] out of the air and squashes it!")) - hugger.die() + if(mob_hugger) + mob_hugger.death(create_cause_data("squished")) + else + hugger.die() return FALSE return TRUE diff --git a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm index 0b0efbc0f34f..0da2b61142e8 100644 --- a/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm +++ b/code/modules/mob/living/carbon/xenomorph/XenoOverwatch.dm @@ -93,6 +93,10 @@ to_chat(src, SPAN_XENOWARNING("Our sister's psychic connection is cut off!")) return + if(HAS_TRAIT(src, TRAIT_ABILITY_BURROWED)) + to_chat(src, SPAN_XENOWARNING("We cannot do this in our current state!")) + return + if(observed_xeno && targetXeno && observed_xeno == targetXeno) if(istype(targetXeno, /obj/effect/alien/resin/marker)) to_chat(src, SPAN_XENOWARNING("We are already watching that mark!")) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm b/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm index 9bfc98a7091d..0990df678f61 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/ability_helper_procs.dm @@ -195,6 +195,10 @@ client.pixel_x = -viewoffset client.pixel_y = 0 + for (var/datum/action/xeno_action/onclick/toggle_long_range/action in actions) + action.on_zoom_in() + return + /mob/living/carbon/xenomorph/proc/zoom_out() if(!client) return diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm index f854272365d0..ee084e77a5a0 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_powers.dm @@ -126,7 +126,7 @@ return var/area/A = get_area(T) - if(A.flags_area & AREA_NOTUNNEL) + if(A.flags_area & AREA_NOTUNNEL || get_dist(src, T) > 15) to_chat(src, SPAN_XENOWARNING("There's no way to tunnel over there.")) return diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm index 98c0c19f68f7..d7a4f987623a 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/defender/defender_powers.dm @@ -17,7 +17,6 @@ if(xeno.crest_defense) to_chat(xeno, SPAN_XENOWARNING("We lower our crest.")) - xeno.balloon_alert(xeno, "crest lowered") xeno.ability_speed_modifier += speed_debuff xeno.armor_deflection_buff += armor_buff @@ -26,7 +25,6 @@ xeno.update_icons() else to_chat(xeno, SPAN_XENOWARNING("We raise our crest.")) - xeno.balloon_alert(xeno, "crest raised") xeno.ability_speed_modifier -= speed_debuff xeno.armor_deflection_buff -= armor_buff diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_abilities.dm index ee1fed3094a7..d60d292cba25 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_abilities.dm @@ -17,3 +17,8 @@ freeze_time = 5 freeze_play_sound = FALSE can_be_shield_blocked = TRUE + +/datum/action/xeno_action/onclick/toggle_long_range/facehugger + handles_movement = FALSE + should_delay = FALSE + ability_primacy = XENO_PRIMARY_ACTION_3 diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_powers.dm index 054762b3c7d4..6eef21c6d5af 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/facehugger/facehugger_powers.dm @@ -25,4 +25,22 @@ if(current_airlock.density) //if its CLOSED YOU'RE SCUTTLING AND CANNOT POUNCE!!! to_chat(owner, SPAN_WARNING("We cannot do that while squeezing and scuttling!")) return FALSE + + if(HAS_TRAIT(owner, TRAIT_IMMOBILIZED)) + to_chat(owner, SPAN_WARNING("We cannot do that while immobilized!")) + return FALSE + return ..() + +/datum/action/xeno_action/onclick/toggle_long_range/facehugger/on_zoom_out() + . = ..() + + var/mob/living/carbon/xenomorph/facehugger/facehugger = owner + REMOVE_TRAIT(facehugger, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Long-Range Sight")) + +/datum/action/xeno_action/onclick/toggle_long_range/facehugger/on_zoom_in() + . = ..() + + var/mob/living/carbon/xenomorph/facehugger/facehugger = owner + ADD_TRAIT(facehugger, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Long-Range Sight")) + diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm index f36e23394eef..39b05b964648 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm @@ -329,6 +329,9 @@ xeno.recalculate_speed() button.icon_state = "template" +/datum/action/xeno_action/onclick/toggle_long_range/proc/on_zoom_in() + return + /datum/action/xeno_action/onclick/toggle_long_range/proc/handle_mob_move_or_look(mob/living/carbon/xenomorph/xeno, actually_moving, direction, specific_direction) SIGNAL_HANDLER movement_buffer-- diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm index 8a829d8d6bc0..17677c8427af 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_abilities.dm @@ -18,8 +18,6 @@ macro_path = /datum/action/xeno_action/verb/verb_lurker_invisibility ability_primacy = XENO_PRIMARY_ACTION_2 action_type = XENO_ACTION_CLICK - xeno_cooldown = 1 // This ability never goes off cooldown 'naturally'. Cooldown is applied manually as a super-large value in the use_ability proc - // and reset by the behavior_delegate whenever the ability ends (because it can be ended by things like slashes, that we can't easily track here) plasma_cost = 20 var/duration = 30 SECONDS // 30 seconds base diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm index 0d1bcc99281a..51f23f22a09f 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/lurker/lurker_powers.dm @@ -1,8 +1,10 @@ -/datum/action/xeno_action/activable/pounce/lurker/additional_effects_always() +/datum/action/xeno_action/activable/pounce/lurker/additional_effects(mob/living/living_mob) var/mob/living/carbon/xenomorph/xeno = owner if(!istype(xeno)) return + RegisterSignal(xeno, COMSIG_XENO_SLASH_ADDITIONAL_EFFECTS_SELF, PROC_REF(remove_freeze), TRUE) // Suppresses runtime ever we pounce again before slashing + var/found = FALSE for(var/mob/living/carbon/human/human in get_turf(xeno)) if(human.stat == DEAD) @@ -12,14 +14,8 @@ if(found) var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis = get_xeno_action_by_type(xeno, /datum/action/xeno_action/onclick/lurker_invisibility) - lurker_invis.invisibility_off() - -/datum/action/xeno_action/activable/pounce/lurker/additional_effects(mob/living/living_mob) - var/mob/living/carbon/xenomorph/xeno = owner - if(!istype(xeno)) - return - - RegisterSignal(xeno, COMSIG_XENO_SLASH_ADDITIONAL_EFFECTS_SELF, PROC_REF(remove_freeze), TRUE) // Suppresses runtime ever we pounce again before slashing + if(lurker_invis) + lurker_invis.invisibility_off() // Full cooldown /datum/action/xeno_action/activable/pounce/lurker/proc/remove_freeze(mob/living/carbon/xenomorph/xeno) SIGNAL_HANDLER @@ -29,21 +25,33 @@ UnregisterSignal(xeno, COMSIG_XENO_SLASH_ADDITIONAL_EFFECTS_SELF) end_pounce_freeze() +/datum/action/xeno_action/onclick/lurker_invisibility/can_use_action() + if(!..()) + return FALSE + var/mob/living/carbon/xenomorph/xeno = owner + return xeno.deselect_timer < world.time // We clicked the same ability in a very short time + /datum/action/xeno_action/onclick/lurker_invisibility/use_ability(atom/targeted_atom) var/mob/living/carbon/xenomorph/xeno = owner - if (!istype(xeno)) + if(!istype(xeno)) return - - if (!action_cooldown_check()) + if(!action_cooldown_check()) return - - if (!check_and_use_plasma_owner()) + if(!check_and_use_plasma_owner()) return - animate(xeno, alpha = alpha_amount, time = 0.1 SECONDS, easing = QUAD_EASING) + xeno.deselect_timer = world.time + 5 // Half a second to prevent double clicks + + if(xeno.stealth) + invisibility_off(0.9) // Near full refund of remaining time + return ..() + + button.icon_state = "template_active" xeno.update_icons() // callback to make the icon_state indicate invisibility is in lurker/update_icon + animate(xeno, alpha = alpha_amount, time = 0.1 SECONDS, easing = QUAD_EASING) + xeno.speed_modifier -= speed_buff xeno.recalculate_speed() @@ -53,31 +61,44 @@ // if we go off early, this also works fine. invis_timer_id = addtimer(CALLBACK(src, PROC_REF(invisibility_off)), duration, TIMER_STOPPABLE) - // Only resets when invisibility ends - apply_cooldown_override(1000000000) return ..() -/datum/action/xeno_action/onclick/lurker_invisibility/proc/invisibility_off() - if(!owner || owner.alpha == initial(owner.alpha)) +/// Implementation for disabling invisibility. +/// (refund_multiplier) indicates how much cooldown to refund based on time remaining +/// 0 indicates full cooldown; 0.5 indicates 50% of remaining time is refunded +/datum/action/xeno_action/onclick/lurker_invisibility/proc/invisibility_off(refund_multiplier = 0.0) + var/mob/living/carbon/xenomorph/xeno = owner + + if(!istype(xeno)) + return + if(owner.alpha == initial(owner.alpha) && !xeno.stealth) return - if (invis_timer_id != TIMER_ID_NULL) + if(invis_timer_id != TIMER_ID_NULL) deltimer(invis_timer_id) invis_timer_id = TIMER_ID_NULL - var/mob/living/carbon/xenomorph/xeno = owner - if (istype(xeno)) - animate(xeno, alpha = initial(xeno.alpha), time = 0.1 SECONDS, easing = QUAD_EASING) - to_chat(xeno, SPAN_XENOHIGHDANGER("We feel our invisibility end!")) + animate(xeno, alpha = initial(xeno.alpha), time = 0.1 SECONDS, easing = QUAD_EASING) + to_chat(xeno, SPAN_XENOHIGHDANGER("We feel our invisibility end!")) - xeno.update_icons() + button.icon_state = "template" + xeno.update_icons() + + xeno.speed_modifier += speed_buff + xeno.recalculate_speed() + + var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate + if(!istype(behavior)) + CRASH("lurker_base behavior_delegate missing/invalid for [xeno]!") - xeno.speed_modifier += speed_buff - xeno.recalculate_speed() + var/recharge_time = behavior.invis_recharge_time + if(behavior.invis_start_time > 0) // Sanity + refund_multiplier = clamp(refund_multiplier, 0, 1) + var/remaining = 1 - (world.time - behavior.invis_start_time) / behavior.invis_duration + recharge_time = behavior.invis_recharge_time - remaining * refund_multiplier * behavior.invis_recharge_time + apply_cooldown_override(recharge_time) - var/datum/behavior_delegate/lurker_base/behavior = xeno.behavior_delegate - if (istype(behavior)) - behavior.on_invisibility_off() + behavior.on_invisibility_off() /datum/action/xeno_action/onclick/lurker_invisibility/ability_cooldown_over() to_chat(owner, SPAN_XENOHIGHDANGER("We are ready to use our invisibility again!")) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index 1f37651b2c8e..38e643e0d25c 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -371,10 +371,17 @@ xeno.use_plasma(plasma_cost_jelly) return /datum/action/xeno_action/onclick/manage_hive/use_ability(atom/Atom) - var/mob/living/carbon/xenomorph/queen/queenbanish = owner + var/mob/living/carbon/xenomorph/queen/queen_manager = owner plasma_cost = 0 - - var/choice = tgui_input_list(queenbanish, "Manage The Hive", "Hive Management", list("Banish (500)", "Re-Admit (100)", "De-evolve (500)", "Reward Jelly (500)", "Exchange larva for evolution (100)",), theme="hive_status") + var/list/options = list("Banish (500)", "Re-Admit (100)", "De-evolve (500)", "Reward Jelly (500)", "Exchange larva for evolution (100)",) + if(queen_manager.hive.hivenumber == XENO_HIVE_CORRUPTED) + var/datum/hive_status/corrupted/hive = queen_manager.hive + options += "Add Personal Ally" + if(length(hive.personal_allies)) + options += "Remove Personal Ally" + options += "Clear Personal Allies" + + var/choice = tgui_input_list(queen_manager, "Manage The Hive", "Hive Management", options, theme="hive_status") switch(choice) if("Banish (500)") banish() @@ -383,9 +390,118 @@ if("De-evolve (500)") de_evolve_other() if("Reward Jelly (500)") - give_jelly_reward(queenbanish.hive) + give_jelly_reward(queen_manager.hive) if("Exchange larva for evolution (100)") give_evo_points() + if("Add Personal Ally") + add_personal_ally() + if("Remove Personal Ally") + remove_personal_ally() + if("Clear Personal Allies") + clear_personal_allies() + +/datum/action/xeno_action/onclick/manage_hive/proc/add_personal_ally() + var/mob/living/carbon/xenomorph/queen/user_xeno = owner + if(user_xeno.hive.hivenumber != XENO_HIVE_CORRUPTED) + return + + if(!user_xeno.check_state()) + return + + var/datum/hive_status/corrupted/hive = user_xeno.hive + var/list/target_list = list() + if(!user_xeno.client) + return + for(var/mob/living/carbon/human/possible_target in range(7, user_xeno.client.eye)) + if(possible_target.stat == DEAD) + continue + if(possible_target.status_flags & CORRUPTED_ALLY) + continue + if(possible_target.hivenumber) + continue + target_list += possible_target + + if(!length(target_list)) + to_chat(user_xeno, SPAN_WARNING("No talls in view.")) + return + var/mob/living/target_mob = tgui_input_list(usr, "Target", "Set Up a Personal Alliance With...", target_list, theme="hive_status") + + if(!user_xeno.check_state(TRUE)) + return + + if(!target_mob) + return + + if(target_mob.hivenumber) + to_chat(user_xeno, SPAN_WARNING("We cannot set up a personal alliance with a hive cultist.")) + return + + hive.add_personal_ally(target_mob) + +/datum/action/xeno_action/onclick/manage_hive/proc/remove_personal_ally() + var/mob/living/carbon/xenomorph/queen/user_xeno = owner + if(user_xeno.hive.hivenumber != XENO_HIVE_CORRUPTED) + return + + if(!user_xeno.check_state()) + return + + var/datum/hive_status/corrupted/hive = user_xeno.hive + + if(!length(hive.personal_allies)) + to_chat(user_xeno, SPAN_WARNING("We don't have personal allies.")) + return + + var/list/mob/living/allies = list() + var/list/datum/weakref/dead_refs = list() + for(var/datum/weakref/ally_ref as anything in hive.personal_allies) + var/mob/living/ally = ally_ref.resolve() + if(ally) + allies += ally + continue + dead_refs += ally_ref + + hive.personal_allies -= dead_refs + + if(!length(allies)) + to_chat(user_xeno, SPAN_WARNING("We don't have personal allies.")) + return + + var/mob/living/target_mob = tgui_input_list(usr, "Target", "Break the Personal Alliance With...", allies, theme="hive_status") + + if(!target_mob) + return + + var/target_mob_ref = WEAKREF(target_mob) + + if(!(target_mob_ref in hive.personal_allies)) + return + + if(!user_xeno.check_state(TRUE)) + return + + hive.remove_personal_ally(target_mob_ref) + +/datum/action/xeno_action/onclick/manage_hive/proc/clear_personal_allies() + var/mob/living/carbon/xenomorph/queen/user_xeno = owner + if(user_xeno.hive.hivenumber != XENO_HIVE_CORRUPTED) + return + + if(!user_xeno.check_state()) + return + + var/datum/hive_status/corrupted/hive = user_xeno.hive + if(!length(hive.personal_allies)) + to_chat(user_xeno, SPAN_WARNING("We don't have personal allies.")) + return + + if(tgui_alert(user_xeno, "Are you sure you want to clear personal allies?", "Clear Personal Allies", list("No", "Yes"), 10 SECONDS) != "Yes") + return + + if(!length(hive.personal_allies)) + return + + hive.clear_personal_allies() /datum/action/xeno_action/onclick/manage_hive/proc/banish() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm index b9bde4c78992..5196be26f3d7 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Lurker.dm @@ -67,15 +67,14 @@ name = "Base Lurker Behavior Delegate" // Config - var/invis_recharge_time = 150 // 15 seconds to recharge invisibility. + var/invis_recharge_time = 20 SECONDS var/invis_start_time = -1 // Special value for when we're not invisible - var/invis_duration = 300 // so we can display how long the lurker is invisible to it + var/invis_duration = 30 SECONDS // so we can display how long the lurker is invisible to it var/buffed_slash_damage_ratio = 1.2 var/slash_slow_duration = 35 // State var/next_slash_buffed = FALSE - var/can_go_invisible = TRUE /datum/behavior_delegate/lurker_base/melee_attack_modify_damage(original_damage, mob/living/carbon/target_carbon) if (!isxeno_human(target_carbon)) @@ -116,55 +115,57 @@ var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if (lurker_invis_action) - lurker_invis_action.invisibility_off() + lurker_invis_action.invisibility_off() // Full cooldown /datum/behavior_delegate/lurker_base/proc/decloak_handler(mob/source) SIGNAL_HANDLER var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invis_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) if(istype(lurker_invis_action)) - lurker_invis_action.invisibility_off() + lurker_invis_action.invisibility_off(0.5) // Partial refund of remaining time -// What to do when we go invisible +/// Implementation for enabling invisibility. /datum/behavior_delegate/lurker_base/proc/on_invisibility() var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker) - if (lurker_pounce_action) + if(lurker_pounce_action) lurker_pounce_action.knockdown = TRUE // pounce knocks down lurker_pounce_action.freeze_self = TRUE ADD_TRAIT(bound_xeno, TRAIT_CLOAKED, TRAIT_SOURCE_ABILITY("cloak")) RegisterSignal(bound_xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(decloak_handler)) bound_xeno.stealth = TRUE - can_go_invisible = FALSE invis_start_time = world.time +/// Implementation for disabling invisibility. /datum/behavior_delegate/lurker_base/proc/on_invisibility_off() var/datum/action/xeno_action/activable/pounce/lurker/lurker_pounce_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/activable/pounce/lurker) - if (lurker_pounce_action) + if(lurker_pounce_action) lurker_pounce_action.knockdown = FALSE // pounce no longer knocks down lurker_pounce_action.freeze_self = FALSE bound_xeno.stealth = FALSE REMOVE_TRAIT(bound_xeno, TRAIT_CLOAKED, TRAIT_SOURCE_ABILITY("cloak")) UnregisterSignal(bound_xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL) + invis_start_time = -1 - // SLIGHTLY hacky because we need to maintain lots of other state on the lurker - // whenever invisibility is on/off CD and when it's active. - addtimer(CALLBACK(src, PROC_REF(regen_invisibility)), invis_recharge_time) +/datum/behavior_delegate/lurker_base/append_to_stat() + . = list() - invis_start_time = -1 + // Invisible + if(invis_start_time != -1) + var/time_left = (invis_duration-(world.time - invis_start_time)) / 10 + . += "Invisibility Remaining: [time_left] second\s." + return -/datum/behavior_delegate/lurker_base/proc/regen_invisibility() - if (can_go_invisible) + var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) + if(!lurker_invisibility_action) return - can_go_invisible = TRUE - if(bound_xeno) - var/datum/action/xeno_action/onclick/lurker_invisibility/lurker_invisibility_action = get_xeno_action_by_type(bound_xeno, /datum/action/xeno_action/onclick/lurker_invisibility) - if(lurker_invisibility_action) - lurker_invisibility_action.end_cooldown() + // Recharged + if(lurker_invisibility_action.cooldown_timer_id == TIMER_ID_NULL) + . += "Invisibility Recharge: Ready." + return -/datum/behavior_delegate/lurker_base/append_to_stat() - . = list() - var/invis_message = (invis_start_time == -1) ? "N/A" : "[(invis_duration-(world.time - invis_start_time))/10] seconds." - . += "Invisibility Time Left: [invis_message]" + // Recharging + var/time_left = timeleft(lurker_invisibility_action.cooldown_timer_id) / 10 + . += "Invisibility Recharge: [time_left] second\s." /datum/behavior_delegate/lurker_base/on_collide(atom/movable/movable_atom) . = ..() @@ -184,4 +185,4 @@ return to_chat(bound_xeno, SPAN_XENOHIGHDANGER("We bumped into someone and lost our invisibility!")) - lurker_invisibility_action.invisibility_off() + lurker_invisibility_action.invisibility_off(0.5) // partial refund of remaining time diff --git a/code/modules/mob/living/carbon/xenomorph/hive_status.dm b/code/modules/mob/living/carbon/xenomorph/hive_status.dm index 22b061715892..baa736382733 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_status.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_status.dm @@ -979,6 +979,7 @@ need_round_end_check = TRUE var/list/defectors = list() + var/list/datum/weakref/personal_allies = list() /datum/hive_status/corrupted/add_xeno(mob/living/carbon/xenomorph/xeno) . = ..() @@ -1253,9 +1254,9 @@ if(living_xeno_queen) if(allies[faction]) - xeno_message(SPAN_XENOANNOUNCE("Your Queen set up an alliance with [faction]!"), 3, hivenumber) + xeno_message(SPAN_XENOANNOUNCE("Our Queen set up an alliance with [faction]!"), 3, hivenumber) else - xeno_message(SPAN_XENOANNOUNCE("Your Queen broke the alliance with [faction]!"), 3, hivenumber) + xeno_message(SPAN_XENOANNOUNCE("Our Queen broke the alliance with [faction]!"), 3, hivenumber) for(var/number in GLOB.hive_datum) var/datum/hive_status/target_hive = GLOB.hive_datum[number] @@ -1291,14 +1292,14 @@ addtimer(CALLBACK(src, PROC_REF(handle_defectors), faction), 11 SECONDS) /datum/hive_status/corrupted/proc/give_defection_choice(mob/living/carbon/xenomorph/xeno, faction) - if(tgui_alert(xeno, "Your Queen has broken the alliance with the [faction]. The device inside your carapace begins to suppress your connection with the Hive. Do you remove it and stay loyal to her?", "Alliance broken!", list("Stay loyal", "Obey the talls"), 10 SECONDS) == "Obey the talls") + if(tgui_alert(xeno, "Our Queen has broken the alliance with the [faction]. The device inside our carapace begins to suppress our connection with the Hive. Do we remove it and stay loyal to her?", "Alliance broken!", list("Stay loyal", "Obey the talls"), 10 SECONDS) == "Obey the talls") if(!xeno.iff_tag) to_chat(xeno, SPAN_XENOWARNING("It's too late now. The device is gone and our service to the Queen continues.")) return defectors += xeno xeno.set_hive_and_update(XENO_HIVE_RENEGADE) to_chat(xeno, SPAN_XENOANNOUNCE("You lost the connection with your Hive. Now you have no Queen, only your masters.")) - to_chat(xeno, SPAN_NOTICE("Our instincts have changed, we seem compelled to protect [english_list(xeno.iff_tag.faction_groups, "no one")].")) + to_chat(xeno, SPAN_NOTICE("Your instincts have changed, you seem compelled to protect [english_list(xeno.iff_tag.faction_groups, "no one")].")) return xeno.visible_message(SPAN_XENOWARNING("[xeno] rips out [xeno.iff_tag]!"), SPAN_XENOWARNING("We rip out [xeno.iff_tag]! For the Hive!")) xeno.adjustBruteLoss(50) @@ -1313,20 +1314,58 @@ continue if(!(faction in xeno.iff_tag.faction_groups)) continue - xeno.visible_message(SPAN_XENOWARNING("[xeno] rips out [xeno.iff_tag]!"), SPAN_XENOWARNING("You rip out [xeno.iff_tag]! For the hive!")) + xeno.visible_message(SPAN_XENOWARNING("[xeno] rips out [xeno.iff_tag]!"), SPAN_XENOWARNING("We rip out [xeno.iff_tag]! For the hive!")) xeno.adjustBruteLoss(50) xeno.iff_tag.forceMove(get_turf(xeno)) xeno.iff_tag = null if(!length(defectors)) return - xeno_message(SPAN_XENOANNOUNCE("You sense that [english_list(defectors)] turned their backs against their sisters and the Queen in favor of their slavemasters!"), 3, hivenumber) + xeno_message(SPAN_XENOANNOUNCE("We sense that [english_list(defectors)] turned their backs against their sisters and the Queen in favor of their slavemasters!"), 3, hivenumber) defectors.Cut() +/datum/hive_status/corrupted/proc/add_personal_ally(mob/living/ally) + personal_allies += WEAKREF(ally) + ally.status_flags |= CORRUPTED_ALLY + ally.med_hud_set_status() + xeno_message(SPAN_XENOANNOUNCE("Our Queen proclaimed [ally] our ally! We must not harm them."), 3, hivenumber) + +/datum/hive_status/corrupted/proc/remove_personal_ally(datum/weakref/ally_ref) + personal_allies -= ally_ref + var/mob/living/ally = ally_ref.resolve() + if(ally) + ally.status_flags &= ~CORRUPTED_ALLY + ally.med_hud_set_status() + xeno_message(SPAN_XENOANNOUNCE("Our Queen has declared that [ally] is no longer our ally!"), 3, hivenumber) + +/datum/hive_status/corrupted/proc/clear_personal_allies(death = FALSE) + for(var/datum/weakref/ally_ref in personal_allies) + var/mob/living/ally = ally_ref.resolve() + if(!ally) + continue + ally.status_flags &= ~CORRUPTED_ALLY + ally.med_hud_set_status() + personal_allies.Cut() + if(!death) + xeno_message(SPAN_XENOANNOUNCE("Our Queen has broken all personal alliances with the talls! Favoritism is no more."), 3, hivenumber) + return + xeno_message(SPAN_XENOWARNING("With the death of the Queen, her friends no longer matter to us."), 3, hivenumber) + +/datum/hive_status/corrupted/is_ally(mob/living/living_mob) + if(living_mob.status_flags & CORRUPTED_ALLY) + return TRUE + return ..() + /datum/hive_status/proc/override_evilution(evil, override) if(SSxevolution) SSxevolution.override_power(hivenumber, evil, override) +/datum/hive_status/corrupted/on_queen_death() + ..() + if(!length(personal_allies)) + return + clear_personal_allies(TRUE) + //Xeno Resin Mark Shit, the very best place for it too :0) //Defines at the bottom of this list here will show up at the top in the mark menu /datum/xeno_mark_define diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm index e6c8061bd0fe..f64bfd6b500f 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/boiler/trapper.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/trapper name = BOILER_TRAPPER - description = "You trade your ability to bombard, lance, and dump your acid in order to gain some speed and the ability to create acid explosions and restrain talls within them. With your longer-range vision, set up traps that immobilize your opponents and place acid mines which deal damage to talls and barricades and reduce the cooldown of your trap deployment for every tall hit. Finally, hit talls with your Acid Shotgun ability which adds a stack of insight to empower the next trap you place once you reach a maximum of ten insight. A point-blank shot or a shot on a stunned target will instantly apply ten stacks." - flavor_description = "Hsss, I love the smell of burnin' tallhost flesh in the mornin'." + description = "You trade your ability to bombard, lance, and dump your acid in order to gain some speed and the ability to create acid explosions and restrain enemies within them. With your longer-range vision, set up traps that immobilize your opponents and place acid mines which deal damage to enemies and barricades and reduce the cooldown of your trap deployment for every enemy hit. Finally, hit enemies with your Acid Shotgun ability which adds a stack of insight to empower the next trap you place once you reach a maximum of ten insight. A point-blank shot or a shot on a stunned target will instantly apply ten stacks." + flavor_description = "The battlefield is my canvas, this one, my painter. Melt them where they stand." actions_to_remove = list( /datum/action/xeno_action/activable/xeno_spit/bombard, diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm index 84877b43571e..55e459cc6dde 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/crusher/charger.dm @@ -14,8 +14,8 @@ /datum/xeno_strain/charger name = CRUSHER_CHARGER - description = "In exchange for your shield, a little bit of your armor and damage, your slowdown resist from autospitters, your influence under frenzy pheromones, your stomp no longer knocking down talls, and your ability to lock your direction, you gain a considerable amount of health, some speed, your stomp does extra damage when stomping over a grounded tall, and your charge is now manually-controlled and momentum-based; the further you go, the more damage and speed you will gain until you achieve maximum momentum, indicated by your roar. In addition, your armor is now directional, being the toughest on the front, weaker on the sides, and weakest from the back. In return, you gain an ability to tumble to pass through talls and avoid enemy fire, and an ability to forcefully move enemies via ramming into them." - flavor_description = "We're just getting started. Nothing stops this train. Nothing." + description = "In exchange for your shield, a little bit of your armor and damage, your slowdown resist from turrets, your influence under frenzy pheromones, your stomp no longer knocking down talls, and your ability to lock your direction, you gain a considerable amount of health, some speed, your stomp does extra damage when stomping over a grounded tall, and your charge is now manually-controlled and momentum-based; the further you go, the more damage and speed you will gain until you achieve maximum momentum, indicated by your roar. In addition, your armor is now directional, being the toughest on the front, weaker on the sides, and weakest from the back. In return, you gain an ability to tumble to pass through enemies and avoid enemy fire, and an ability to forcefully move enemies via ramming into them." + flavor_description = "Nothing stops this hive. This one will become both the immovable object and the unstoppable force." actions_to_remove = list( /datum/action/xeno_action/activable/pounce/crusher_charge, diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm index f84566e9c841..cfbf85de299d 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/defender/steel_crest.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/steel_crest name = DEFENDER_STEELCREST description = "You trade your tail sweep and a small amount of your slash damage for slightly increased headbutt knockback and damage and the ability to slowly move and headbutt while fortified. Along with this, you gain a unique ability to accumulate damage, and use it to recover a slight amount of health and refresh your tail slam." - flavor_description = "To handle yourself, use your head. To handle others, use your head." + flavor_description = "This one, like my will, is indomitable. It will become my steel crest against all that defy me." icon_state_prefix = "Steelcrest" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm index 0fcbb2ecf09a..5ebafc88eaef 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/healer name = DRONE_HEALER - description = "You lose your choice of resin secretions, a chunk of your slash damage, and you will experience a slighty-increased difficulty in tackling tallhosts in exchange for strong pheromones, the ability to use a bit of your health to plant a maximum of three lesser resin fruits, and the ability to heal your sisters' wounds by secreting a regenerative resin salve by using your vital fluids and a fifth of your plasma. Be wary, this is a dangerous process; overexert yourself and you may exhaust yourself to unconsciousness, or die..." - flavor_description = "To the very last drop, your blood belongs to The Hive; share it with your sisters to keep them fighting." + description = "You lose your choice of resin secretions, a chunk of your slash damage, and you will experience a slighty-increased difficulty in tackling hosts in exchange for strong pheromones, the ability to use a bit of your health to plant a maximum of three lesser resin fruits, and the ability to heal your sisters' wounds by secreting a regenerative resin salve by using your vital fluids and a fifth of your plasma. Be wary, this is a dangerous process; overexert yourself and you may exhaust yourself to unconsciousness, or die..." + flavor_description = "Divided we fall, united we win. We live for the hive, we die for the hive." icon_state_prefix = "Healer" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/facehugger/watcher.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/facehugger/watcher.dm index 7fba30b6f352..c5e1cff29c63 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/facehugger/watcher.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/facehugger/watcher.dm @@ -1,13 +1,13 @@ /datum/xeno_strain/watcher name = FACEHUGGER_WATCHER - description = "You lose your ability to hide in exchange to see further and the ability to no longer take damage outside of weeds. This enables you to stalk your host from a distance and wait for the perfect oppertunity to strike." + description = "You lose your ability to hide in exchange to see further. This enables you to stalk your host from a distance and wait for the perfect oppertunity to strike." flavor_description = "No need to hide when you can see the danger." actions_to_remove = list( /datum/action/xeno_action/onclick/xenohide, ) actions_to_add = list( - /datum/action/xeno_action/onclick/toggle_long_range/runner, + /datum/action/xeno_action/onclick/toggle_long_range/facehugger, ) behavior_delegate_type = /datum/behavior_delegate/facehugger_watcher @@ -19,3 +19,13 @@ // This has no special effects, it's just here to skip `/datum/behavior_delegate/facehugger_base/on_life()`. /datum/behavior_delegate/facehugger_watcher name = "Watcher Facehugger Behavior Delegate" + +/datum/behavior_delegate/facehugger_watcher/on_life() + // Sap health if we're standing, not on weeds, and not zoomed out + if(bound_xeno.body_position != STANDING_UP) + return + if(bound_xeno.is_zoomed) + return + if(locate(/obj/effect/alien/weeds) in get_turf(bound_xeno)) + return + bound_xeno.adjustBruteLoss(1) diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm index cf1cafde9267..538aacc63722 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/hivelord/resin_whisperer.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/resin_whisperer name = HIVELORD_RESIN_WHISPERER description = "You lose your corrosive acid, your ability to secrete thick resin, your ability to reinforce resin secretions, sacrifice your ability to plant weed nodes outside of weeds, and you sacrifice a fifth of your plasma reserves to enhance your vision and gain a stronger connection to the resin. You can now remotely place resin secretions including weed nodes up to a distance of twelve paces!" - flavor_description = "Let the resin guide you. It whispers, so listen closely." + flavor_description = "We let the resin guide us. It whispers, so listen closely." icon_state_prefix = "Resin Whisperer" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm index f9a5dbedb614..7de4b93aad19 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/dancer.dm @@ -1,8 +1,8 @@ /datum/xeno_strain/dancer // My name is Cuban Pete, I'm the King of the Rumba Beat name = PRAETORIAN_DANCER - description = "You lose all of your acid-based abilities and a small amount of your armor in exchange for increased movement speed, evasion, and unparalleled agility that gives you an ability to move even more quickly, dodge bullets, and phase through tallhosts. By slashing tallhosts, you temporarily increase your movement speed and you also you apply a tag that changes how your two new tail abilities function. By tagging hosts, you will make Impale hit twice instead of once and make Tail Trip knock hosts down instead of stunning them." - flavor_description = "Demonstrate to the talls what 'there is beauty in death' truly symbolizes, then dance upon their graves!" + description = "You lose all of your acid-based abilities and a small amount of your armor in exchange for increased movement speed, evasion, and unparalleled agility that gives you an ability to move even more quickly, dodge bullets, and phase through enemies and allies alike. By slashing enemies, you temporarily increase your movement speed and you also you apply a tag that changes how your two new tail abilities function. By tagging enemies, you will make Impale hit twice instead of once and make Tail Trip knock enemies down instead of stunning them." + flavor_description = "A performance fit for a Queen, this one will become my instrument of death." icon_state_prefix = "Dancer" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm index 91ea59661462..b9541a13ca80 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/oppressor.dm @@ -1,8 +1,8 @@ /datum/xeno_strain/oppressor // Dread it, run from it, destiny still arrives... or should I say, I do name = PRAETORIAN_OPPRESSOR - description = "You abandon all of your acid-based abilities, your dash, some speed, and a bit of your slash damage for some resistance against small explosives, slashes that deal extra damage to prone targets, and a powerful hook ability that pulls up to three talls towards you, slows them, and has varying effects depending on how many talls you pull. You also gain a powerful punch that reduces your other abilities' cooldowns, pierces through armor, and does double damage in addition to rooting slowed targets. You can also knock talls back and slow them with your new Tail Lash and quickly grab a tall, slow it, and pull it towards you with your unique Tail Stab." - flavor_description = "Dread it. Run from it. The Hive arrives all the same, or, more accurately, you do." + description = "You abandon all of your acid-based abilities, your dash, some speed, and a bit of your slash damage for some resistance against small explosives, slashes that deal extra damage to prone targets, and a powerful hook ability that pulls up to three enemies towards you, slows them, and has varying effects depending on how many enemies you pull. You also gain a powerful punch that reduces your other abilities' cooldowns, pierces through armor, and does double damage in addition to rooting slowed targets. You can also knock enemies back and slow them with your new Tail Lash and quickly grab a tall, slow it, and pull it towards you with your unique Tail Stab." + flavor_description = "My reach is endless, this one will pull down the heavens." icon_state_prefix = "Oppressor" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm index 2a344523e974..310db35ab370 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/vanguard.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/vanguard name = PRAETORIAN_VANGUARD - description = "You forfeit all of your acid-based abilities and some health for some extra speed and a rechargable shield that can block one attack. Use your Pierce from up to three paces away to stab through talls, while stabbing through several will completely recharge your shield. Use your charge to plow through enemies and use it again to unleash a powerful AoE slash that reaches up to three paces. You also have a Cleave ability, amplified by your shield, which you can toggle to either immobilize or fling a target away." - flavor_description = "They are my bulwark against the tallhosts. They are my Vanguard and they shall know no fear." + description = "You forfeit all of your acid-based abilities and some health for some extra speed and a rechargable shield that can block one attack. Use your Pierce from up to three paces away to stab through talls, while stabbing through two or more will completely recharge your shield. Use your charge to plow through enemies and use it again to unleash a powerful AoE slash that reaches up to three paces. You also have a Cleave ability, amplified by your shield, which you can toggle to either immobilize or fling a target away." + flavor_description = "Fearless you are born, fearless you serve, fearless you die. This one will become my Vanguard" icon_state_prefix = "Vanguard" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/warden.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/warden.dm index 313778baf038..9dc9404ee498 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/warden.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/praetorian/warden.dm @@ -1,8 +1,8 @@ /datum/xeno_strain/warden // i mean so basically im braum name = PRAETORIAN_WARDEN - description = "You trade your acid ball, acid spray, dash, and a small bit of your slash damage and speed to become an effective medic. You gain the ability to emit strong pheromones, an ability that retrieves endangered, knocked-down or sitting allies and pulls them to your location, and you gain an internal hitpoint pool that fills with every slash against your enemies, which can be spent to aid your allies and yourself by healing them or curing their ailments." - flavor_description = "Only in death does your sisters' service to the Queen end. They will be untouched by plague or disease; no sickness will blight them." + description = "You trade your acid ball, acid spray, dash, and a small bit of your slash damage and speed to become an effective medic. You gain the ability to emit strong pheromones, an ability that retrieves endangered, knocked-down or resting allies and pulls them to your location, and you gain an internal hitpoint pool that fills with every slash against your enemies, which can be spent to aid your allies and yourself by healing them or curing their ailments." + flavor_description = "This one will deny her sisters' deaths until they earn it. Fight or be forgotten." icon_state_prefix = "Warden" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/berserker.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/berserker.dm index 365304259ac8..5b8981157bda 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/berserker.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/berserker.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/berserker name = RAVAGER_BERSERKER - description = "You lose your empower, charge, and scissor cut, decrease your health, and sacrifice a bit of your influence under frenzy pheromones to increase your movement speed, slightly increase your armor, and gain a new set of abilities that make you a terrifying melee monster. By slashing, you heal yourself and gain a stack of rage that increases your armor, movement speed, attack speed, and your heals per slash, to a maximum of six rage. Use your new Appehend ability to increase your movement speed and apply a slow on the next target you slash and use your Clothesline ability to fling your target to heal yourself, even more-so if you have a rage stack that will be used up. Finally, use your Eviscerate to unleash a devastating windmill attack that heals you for every host you hit after an immobilizing wind-up." - flavor_description = "They shall be my finest warriors. They will rend and tear, crush and butcher, and maim and rage until every tallhost falls." + description = "You lose your empower, charge, and scissor cut, decrease your health, and sacrifice a bit of your influence under frenzy pheromones to increase your movement speed, slightly increase your armor, and gain a new set of abilities that make you a terrifying melee monster. By slashing, you heal yourself and gain a stack of rage that increases your armor, movement speed, attack speed, and your heals per slash, to a maximum of six rage. Use your new Appehend ability to increase your movement speed and apply a slow on the next target you slash and use your Clothesline ability to fling your target to heal yourself, even more-so if you have a rage stack that will be used up. Finally, use your Eviscerate to unleash a devastating windmill attack that heals you for every enemy you hit after an immobilizing wind-up." + flavor_description = "Unbridled fury fills this one. You will become an extension of my rage." icon_state_prefix = "Berserker" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm index 5cb756d8889d..b88df4068cec 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/ravager/hedgehog.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/hedgehog name = RAVAGER_HEDGEHOG description = "You lose your empower, charge, scissor cut, and some slash damage in exchange for more explosive resistance. Your resistance scales with your shard count and at 50% grants you immunity to some explosive stuns. You accumulate shards over time and when taking damage. You can use these shards to power three new abilities: Spike Shield which gives you a temporary shield that spits bone shards around you when damaged; Fire Spikes which launches spikes at your target to slow them and deal damage when they move; and Spike Shed which launches all your spikes, grants a temporary speed boost, and disables shard generation for thirty seconds." - flavor_description = "They will be of iron will and steely muscle. In great armor shall they be clad, and with the mightiest spikes will they be armed." + flavor_description = "You will pierce them a million times, show them what it feels like. This one will become my shield." icon_state_prefix = "Hedgehog" actions_to_remove = list( diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acid.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acid.dm index 7b9bafadeb7b..f98263871707 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acid.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/runner/acid.dm @@ -1,7 +1,7 @@ /datum/xeno_strain/acider name = RUNNER_ACIDER description = "At the cost of a little bit of your speed and all of your current abilities, you gain a considerable amount of health, some armor, and a new organ that fills with volatile acid over time. Your Tail Stab and slashes apply acid to living lifeforms that slowly burns them, and slashes against targets with acid stacks fill your acid glands. You also gain Corrosive Acid equivalent to that of a boiler that you can deploy more quickly than any other caste, at the cost of a chunk of your acid reserves with each use. Finally, after a twenty second windup, you can force your body to explode, covering everything near you with acid. The more acid you have stored, the more devastating the explosion will be, but during those twenty seconds before detonation you are slowed and give off several warning signals which give talls an opportunity to end you before you can detonate. If you successfully explode, you will reincarnate as a larva again!" - flavor_description = "Burn their walls, maim their faces! Your life, for The Hive!" + flavor_description = "This one will be the last thing they hear. A martyr." icon_state_prefix = "Acider" actions_to_remove = list( diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index bd7370f4806f..b6f2871e0370 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -132,6 +132,7 @@ if(user.action_busy) to_chat(xeno, SPAN_WARNING("We are already busy with something.")) return + SEND_SIGNAL(xeno, COMSIG_MOB_EFFECT_CLOAK_CANCEL) xeno.visible_message(SPAN_DANGER("[xeno] starts to devour [pulled]!"), \ SPAN_DANGER("We start to devour [pulled]!"), null, 5) if(HAS_TRAIT(xeno, TRAIT_CLOAKED)) //cloaked don't show the visible message, so we gotta work around diff --git a/code/modules/objectives/data_retrieval.dm b/code/modules/objectives/data_retrieval.dm index f66c578f48fb..ee5053f26c4b 100644 --- a/code/modules/objectives/data_retrieval.dm +++ b/code/modules/objectives/data_retrieval.dm @@ -117,29 +117,14 @@ /datum/cm_objective/retrieve_data/disk/process() var/obj/structure/machinery/computer/disk_reader/reader = disk.loc if(!reader.powered()) - reader.visible_message(SPAN_WARNING("\The [reader] powers down mid-operation as the area looses power.")) - playsound(reader, 'sound/machines/terminal_shutdown.ogg', 25, 1) - SSobjectives.stop_processing_objective(src) - disk.forceMove(reader.loc) - reader.disk = null + SEND_SIGNAL(reader, COMSIG_INTEL_DISK_LOST_POWER) return ..() /datum/cm_objective/retrieve_data/disk/complete() state = OBJECTIVE_COMPLETE - var/obj/structure/machinery/computer/disk_reader/reader = disk.loc - reader.visible_message("\The [reader] pings softly as the upload finishes and ejects the disk.") - playsound(reader, 'sound/machines/screen_output1.ogg', 25, 1) - disk.forceMove(reader.loc) - disk.name = "[disk.name] (complete)" - reader.disk = null - award_points() - - // Now enable the objective to store this disk in the lab. - disk.retrieve_objective.state = OBJECTIVE_ACTIVE - disk.retrieve_objective.activate() - + SEND_SIGNAL(disk.loc, COMSIG_INTEL_DISK_COMPLETED) ..() /datum/cm_objective/retrieve_data/disk/get_tgui_data() @@ -295,34 +280,6 @@ unslashable = TRUE unacidable = TRUE -/obj/structure/machinery/computer/disk_reader/attack_hand(mob/living/user) - if(isxeno(user)) - return - if(disk) - to_chat(user, SPAN_NOTICE("[disk] is currently being uploaded to ARES.")) - -/obj/structure/machinery/computer/disk_reader/attackby(obj/item/W, mob/living/user) - if(istype(W, /obj/item/disk/objective)) - if(istype(disk)) - to_chat(user, SPAN_WARNING("There is a disk in the drive being uploaded already!")) - return FALSE - var/obj/item/disk/objective/newdisk = W - if(newdisk.objective.state == OBJECTIVE_COMPLETE) - to_chat(user, SPAN_WARNING("The reader displays a message stating this disk has already been read and refuses to accept it.")) - return FALSE - if(input(user,"Enter the encryption key","Decrypting [newdisk]","") != newdisk.objective.decryption_password) - to_chat(user, SPAN_WARNING("The reader asks for the encryption key for this disk, not having the correct key you eject the disk.")) - return FALSE - if(istype(disk)) - to_chat(user, SPAN_WARNING("There is a disk in the drive being uploaded already!")) - return FALSE - - if(!(newdisk in user.contents)) - return FALSE - - newdisk.objective.activate() - - user.drop_inv_item_to_loc(W, src) - disk = W - to_chat(user, SPAN_NOTICE("You insert \the [W] and enter the decryption key.")) - user.count_niche_stat(STATISTICS_NICHE_DISK) +/obj/structure/machinery/computer/disk_reader/Initialize() + . = ..() + AddComponent(/datum/component/disk_reader) diff --git a/code/modules/objectives/objective_memory_storage.dm b/code/modules/objectives/objective_memory_storage.dm index 161c78d4d1ba..de2ab30691cc 100644 --- a/code/modules/objectives/objective_memory_storage.dm +++ b/code/modules/objectives/objective_memory_storage.dm @@ -218,6 +218,15 @@ GLOBAL_DATUM_INIT(intel_system, /datum/intel_system, new()) GLOB.intel_system.store_single_objective(O) return 1 +/obj/structure/machinery/computer/intel/disk_reader // ARC computer to save on tile space + name = "\improper SIGINT terminal" + desc = "An USCM computer capable of uploading data to the intelligence database. It has a disk reader slot built into the bottom, as well." + icon_state = "terminal" + +/obj/structure/machinery/computer/intel/disk_reader/Initialize() + . = ..() + AddComponent(/datum/component/disk_reader) + // -------------------------------------------- // *** View objectives with the computer *** // -------------------------------------------- diff --git a/code/modules/organs/limbs.dm b/code/modules/organs/limbs.dm index 4c3954575245..3cf8dae2a2c6 100644 --- a/code/modules/organs/limbs.dm +++ b/code/modules/organs/limbs.dm @@ -1513,7 +1513,7 @@ treat_grafted var tells it to apply to grafted but unsalved wounds, for burn kit /obj/limb/head/limb_delimb(damage_source) var/obj/item/clothing/head/helmet/owner_helmet = owner.head - if(!istype(owner_helmet) || !owner.allow_gun_usage) + if(!istype(owner_helmet) || (issynth(owner) && !owner.allow_gun_usage)) droplimb(0, 0, damage_source) return diff --git a/code/modules/paperwork/desk_bell.dm b/code/modules/paperwork/desk_bell.dm index 6e7de1101ae7..ddd4a9dc5d58 100644 --- a/code/modules/paperwork/desk_bell.dm +++ b/code/modules/paperwork/desk_bell.dm @@ -93,3 +93,12 @@ flick("desk_bell_activate", src) times_rang++ return TRUE + +/obj/item/desk_bell/ares + name = "AI core reception bell" + +/obj/item/desk_bell/ares/ring_bell(mob/living/user) + if(broken_ringer) + return FALSE + ares_apollo_talk("Attendence requested at AI Core Reception.") + return ..() diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 5614a4ffe52b..df39248e343a 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -359,6 +359,12 @@ flags_equip_slot = NO_FLAGS //cannot be equiped var/obj/structure/machinery/camera/correspondent/linked_cam +/obj/item/device/camera/broadcasting/Initialize(mapload, ...) + . = ..() + linked_cam = new(loc, src) + linked_cam.status = FALSE + RegisterSignal(src, COMSIG_COMPONENT_ADDED, PROC_REF(handle_rename)) + /obj/item/device/camera/broadcasting/Destroy() clear_broadcast() return ..() @@ -367,13 +373,25 @@ . = ..() if(!.) return - linked_cam = new(loc, src) + flags_atom |= (USES_HEARING|USES_SEEING) + if(!linked_cam || QDELETED(linked_cam)) + linked_cam = new(loc, src) + else + linked_cam.status = TRUE + linked_cam.forceMove(loc) SEND_SIGNAL(src, COMSIG_BROADCAST_GO_LIVE) to_chat(user, SPAN_NOTICE("[src] begins to buzz softly as you go live.")) /obj/item/device/camera/broadcasting/unwield(mob/user) . = ..() - clear_broadcast() + flags_atom &= ~(USES_HEARING|USES_SEEING) + linked_cam.status = FALSE + +/obj/item/device/camera/broadcasting/proc/handle_rename(obj/item/camera, datum/component/label) + SIGNAL_HANDLER + if(!istype(label, /datum/component/label)) + return + linked_cam.c_tag = get_broadcast_name() /obj/item/device/camera/broadcasting/proc/clear_broadcast() if(!QDELETED(linked_cam)) @@ -385,6 +403,12 @@ return src_label_component.label_name return "Broadcast [serial_number]" +/obj/item/device/camera/broadcasting/hear_talk(mob/living/sourcemob, message, verb = "says", datum/language/language, italics = FALSE) + SEND_SIGNAL(src, COMSIG_BROADCAST_HEAR_TALK, sourcemob, message, verb, language, italics, get_dist(sourcemob, src) < 3) + +/obj/item/device/camera/broadcasting/see_emote(mob/living/sourcemob, emote, audible = FALSE) + SEND_SIGNAL(src, COMSIG_BROADCAST_SEE_EMOTE, sourcemob, emote, audible, get_dist(sourcemob, src) < 3 && audible) + /obj/item/photo/proc/construct(datum/picture/P) icon = P.fields["icon"] tiny = P.fields["tiny"] diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 76550fbe079b..8ec24526fc1e 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1372,3 +1372,7 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( crash_break_probability = 0 #undef APC_UPDATE_ICON_COOLDOWN + +// apc that start at zero charge. +/obj/structure/machinery/power/apc/nocharge + start_charge = 0 diff --git a/code/modules/projectiles/gun_attachables.dm b/code/modules/projectiles/gun_attachables.dm index a2801821349c..5e2fc8459377 100644 --- a/code/modules/projectiles/gun_attachables.dm +++ b/code/modules/projectiles/gun_attachables.dm @@ -1761,8 +1761,6 @@ Defined in conflicts.dm of the #defines folder. //but at the same time you are slow when 2 handed aim_speed_mod = CONFIG_GET(number/slowdown_med) - matter = list("wood" = 2000) - select_gamemode_skin(type) /obj/item/attachable/stock/double diff --git a/code/modules/projectiles/guns/specialist/launcher/rocket_launcher.dm b/code/modules/projectiles/guns/specialist/launcher/rocket_launcher.dm index 356d0e6c3b48..1f0ae4aed571 100644 --- a/code/modules/projectiles/guns/specialist/launcher/rocket_launcher.dm +++ b/code/modules/projectiles/guns/specialist/launcher/rocket_launcher.dm @@ -189,12 +189,18 @@ smoke.set_up(1, 0, backblast_loc, turn(user.dir, 180)) smoke.start() playsound(src, 'sound/weapons/gun_rocketlauncher.ogg', 100, TRUE, 10) - for(var/mob/living/carbon/C in backblast_loc) - if(C.body_position == STANDING_UP && !HAS_TRAIT(C, TRAIT_EAR_PROTECTION)) //Have to be standing up to get the fun stuff - C.apply_damage(15, BRUTE) //The shockwave hurts, quite a bit. It can knock unarmored targets unconscious in real life - C.apply_effect(4, STUN) //For good measure - C.apply_effect(6, STUTTER) - C.emote("pain") + for(var/mob/living/carbon/mob in backblast_loc) + if(mob.body_position != STANDING_UP || HAS_TRAIT(mob, TRAIT_EAR_PROTECTION)) //Have to be standing up to get the fun stuff + continue + to_chat(mob, SPAN_BOLDWARNING("You got hit by the backblast!")) + mob.apply_damage(15, BRUTE) //The shockwave hurts, quite a bit. It can knock unarmored targets unconscious in real life + var/knockdown_amount = 6 + if(isxeno(mob)) + var/mob/living/carbon/xenomorph/xeno = mob + knockdown_amount = knockdown_amount * (1 - xeno.caste?.xeno_explosion_resistance / 100) + mob.KnockDown(knockdown_amount) + mob.apply_effect(6, STUTTER) + mob.emote("pain") //------------------------------------------------------- //M5 RPG'S MEAN FUCKING COUSIN diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index edb565158185..cd69c1940aba 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -358,14 +358,7 @@ SEND_SIGNAL(src, COMSIG_BULLET_TERMINAL) // Check we can reach the turf at all based on pathed grid - var/proj_dir = get_dir(current_turf, next_turf) - if((proj_dir & (proj_dir - 1)) && !current_turf.Adjacent(next_turf)) - ammo.on_hit_turf(current_turf, src) - current_turf.bullet_act(src) - return TRUE - - // Check for hits that would occur when moving to turf, such as a blocking cade - if(scan_a_turf(next_turf, proj_dir)) + if(check_canhit(current_turf, next_turf)) return TRUE // Actually move @@ -533,7 +526,8 @@ else direct_hit = TRUE - SEND_SIGNAL(firer, COMSIG_BULLET_DIRECT_HIT, L) + if(firer) + SEND_SIGNAL(firer, COMSIG_BULLET_DIRECT_HIT, L) // At present, Xenos have no inherent effects or localized damage stemming from limb targeting // Therefore we exempt the shooter from direct hit accuracy penalties as well, @@ -600,6 +594,19 @@ if(SEND_SIGNAL(src, COMSIG_BULLET_POST_HANDLE_MOB, L, .) & COMPONENT_BULLET_PASS_THROUGH) return FALSE +/obj/projectile/proc/check_canhit(turf/current_turf, turf/next_turf) + var/proj_dir = get_dir(current_turf, next_turf) + if((proj_dir & (proj_dir - 1)) && !current_turf.Adjacent(next_turf)) + ammo.on_hit_turf(current_turf, src) + current_turf.bullet_act(src) + return TRUE + + // Check for hits that would occur when moving to turf, such as a blocking cade + if(scan_a_turf(next_turf, proj_dir)) + return TRUE + + return FALSE + //---------------------------------------------------------- // \\ // HITTING THE TARGET \\ diff --git a/code/modules/reagents/chemistry_machinery/chem_master.dm b/code/modules/reagents/chemistry_machinery/chem_master.dm index dc5206bb2df5..5b145f75940f 100644 --- a/code/modules/reagents/chemistry_machinery/chem_master.dm +++ b/code/modules/reagents/chemistry_machinery/chem_master.dm @@ -141,7 +141,15 @@ if(length(label) < 3) loaded_pill_bottle.maptext_label = label loaded_pill_bottle.update_icon() + else if(href_list["setcolor"]) + // Checking for state changes + if(!loaded_pill_bottle) + return + + if(!Adjacent(usr)) + return + loaded_pill_bottle.choose_color() else if(href_list["close"]) close_browser(user, "chemmaster") @@ -355,7 +363,8 @@ if(pill_maker) if(loaded_pill_bottle) dat += "Eject [loaded_pill_bottle] \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.max_storage_space]\]
" - dat += "Add label to [loaded_pill_bottle] \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.max_storage_space]\]

" + dat += "Add label to [loaded_pill_bottle] \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.max_storage_space]\]
" + dat += "Set color to [loaded_pill_bottle] \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.max_storage_space]\]

" dat += "Transfer [loaded_pill_bottle] \[[loaded_pill_bottle.contents.len]/[loaded_pill_bottle.max_storage_space]\] to the smartfridge

" else dat += "No pill bottle inserted.

" diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm index 0ec570ca9244..d826840dc495 100644 --- a/code/modules/tgui/states.dm +++ b/code/modules/tgui/states.dm @@ -105,3 +105,26 @@ return UI_DISABLED // Otherwise, we got nothing. return UI_CLOSE + +/** + * public + * + * Check if in view. Can interact only if adjacent, updates within max distance, otherwise closes + * + * required src_object atom/movable The object which owns the UI. + * + * return UI_state The state of the UI. + */ +/mob/living/proc/shared_living_ui_in_view(atom/movable/src_object, viewcheck = TRUE, max_distance = 7) + // If the object is obscured, close it. + if(viewcheck && !(src_object in view(src))) + return UI_CLOSE + var/dist = get_dist(src_object, src) + // Open and interact if 1-0 tiles away. + if(dist <= 1) + return UI_INTERACTIVE + // View only if within distance. + else if(dist <= max_distance) + return UI_UPDATE + // Otherwise, we got nothing. + return UI_CLOSE diff --git a/code/modules/tgui/states/in_view.dm b/code/modules/tgui/states/in_view.dm new file mode 100644 index 000000000000..76ab16e8c794 --- /dev/null +++ b/code/modules/tgui/states/in_view.dm @@ -0,0 +1,15 @@ +//If in view and within view distance +GLOBAL_DATUM_INIT(in_view, /datum/ui_state/in_view, new) +/datum/ui_state/in_view/can_use_topic(src_object, mob/user) + return user.in_view_can_use_topic(src_object) // Call the individual mob-overridden procs. + +/mob/proc/in_view_can_use_topic(src_object) + return UI_CLOSE // Don't allow interaction by default. + +/mob/ghost/in_view_can_use_topic(src_object) + return UI_UPDATE //ghost can just watch + +/mob/living/in_view_can_use_topic(src_object) + . = shared_ui_interaction(src_object) + if(. > UI_CLOSE && loc) //must not be in nullspace. + . = min(., shared_living_ui_in_view(src_object)) // Check the distance and view... diff --git a/code/modules/vehicles/apc/apc_command.dm b/code/modules/vehicles/apc/apc_command.dm index e0862ae4f2ab..54647279ec3b 100644 --- a/code/modules/vehicles/apc/apc_command.dm +++ b/code/modules/vehicles/apc/apc_command.dm @@ -43,8 +43,6 @@ return ..() /obj/vehicle/multitile/apc/command/process() - . = ..() - var/turf/apc_turf = get_turf(src) if(health == 0 || !visible_in_tacmap || !is_ground_level(apc_turf.z)) return diff --git a/code/modules/vehicles/arc/arc.dm b/code/modules/vehicles/arc/arc.dm new file mode 100644 index 000000000000..feee097c3638 --- /dev/null +++ b/code/modules/vehicles/arc/arc.dm @@ -0,0 +1,271 @@ +/obj/vehicle/multitile/arc + name = "\improper M540-B Armored Recon Carrier" + desc = "An M540-B Armored Recon Carrier. A lightly armored reconnaissance and intelligence vehicle. Entrances on the sides." + + icon = 'icons/obj/vehicles/arc.dmi' + icon_state = "arc_base" + pixel_x = -48 + pixel_y = -48 + + bound_width = 96 + bound_height = 96 + + bound_x = -32 + bound_y = -32 + + health = 800 + + interior_map = /datum/map_template/interior/arc + + passengers_slots = 3 + xenos_slots = 5 + + entrances = list( + "left" = list(2, 0), + "right" = list(-2, 0), + ) + + entrance_speed = 0.5 SECONDS + + required_skill = SKILL_VEHICLE_LARGE + + movement_sound = 'sound/vehicles/tank_driving.ogg' + + luminosity = 7 + + hardpoints_allowed = list( + /obj/item/hardpoint/locomotion/arc_wheels, + /obj/item/hardpoint/primary/arc_sentry, + /obj/item/hardpoint/support/arc_antenna, + ) + + seats = list( + VEHICLE_DRIVER = null, + ) + + active_hp = list( + VEHICLE_DRIVER = null, + ) + + vehicle_flags = VEHICLE_CLASS_LIGHT + + mob_size_required_to_hit = MOB_SIZE_XENO + + dmg_multipliers = list( + "all" = 1, + "acid" = 1.8, + "slash" = 1.1, + "bullet" = 0.6, + "explosive" = 0.8, + "blunt" = 0.8, + "abstract" = 1, + ) + + move_max_momentum = 2.2 + move_momentum_build_factor = 1.5 + move_turn_momentum_loss_factor = 0.8 + + vehicle_ram_multiplier = VEHICLE_TRAMPLE_DAMAGE_APC_REDUCTION + + /// If the ARC has its antenna up, making it unable to move but enabling the turret and sensor wallhack + var/antenna_deployed = FALSE + /// How long it takes to deploy or retract the antenna + var/antenna_toggle_time = 10 SECONDS + /// Range of the ARC's xenomorph wallhacks + var/sensor_radius = 45 + /// weakrefs of xenos temporarily added to the marine minimap + var/list/minimap_added = list() + +/obj/vehicle/multitile/arc/Initialize() + . = ..() + + var/turf/gotten_turf = get_turf(src) + if(gotten_turf?.z) + SSminimaps.add_marker(src, gotten_turf.z, MINIMAP_FLAG_USCM, "arc", 'icons/ui_icons/map_blips_large.dmi') + + RegisterSignal(src, COMSIG_ARC_ANTENNA_TOGGLED, PROC_REF(on_antenna_toggle)) + +/obj/vehicle/multitile/arc/crew_mousedown(datum/source, atom/object, turf/location, control, params) + var/list/modifiers = params2list(params) + if(modifiers[SHIFT_CLICK] || modifiers[MIDDLE_CLICK] || modifiers[RIGHT_CLICK]) //don't step on examine, point, etc + return + + switch(get_mob_seat(source)) + if(VEHICLE_DRIVER) + if(modifiers[LEFT_CLICK] && modifiers[CTRL_CLICK]) + activate_horn() + +/obj/vehicle/multitile/arc/get_examine_text(mob/user) + . = ..() + if(!isxeno(user)) + return + + if(health > 0) + . += SPAN_XENO("[src] can be crawled under once destroyed.") + else + . += SPAN_XENO("[src] can be crawled under by dragging our sprite to it.") + +/obj/vehicle/multitile/arc/proc/on_antenna_toggle(datum/source) + SIGNAL_HANDLER + + if(antenna_deployed) + START_PROCESSING(SSslowobj, src) + + else + STOP_PROCESSING(SSslowobj, src) + +/obj/vehicle/multitile/arc/process() + var/turf/arc_turf = get_turf(src) + if((health <= 0) || !visible_in_tacmap || !is_ground_level(arc_turf.z)) + return + + var/obj/item/hardpoint/support/arc_antenna/antenna = locate() in hardpoints + if(!antenna || (antenna.health <= 0)) + for(var/datum/weakref/xeno as anything in minimap_added) + SSminimaps.remove_marker(xeno.resolve()) + minimap_added.Remove(xeno) + return + + for(var/mob/living/carbon/xenomorph/current_xeno as anything in GLOB.living_xeno_list) + var/turf/xeno_turf = get_turf(current_xeno) + if(!is_ground_level(xeno_turf.z)) + continue + + var/datum/weakref/xeno_weakref = WEAKREF(current_xeno) + + if(get_dist(src, current_xeno) <= sensor_radius) + if(xeno_weakref in minimap_added) + continue + + SSminimaps.remove_marker(current_xeno) + current_xeno.add_minimap_marker(MINIMAP_FLAG_USCM|MINIMAP_FLAG_XENO) + minimap_added += xeno_weakref + else if(xeno_weakref in minimap_added) + SSminimaps.remove_marker(current_xeno) + current_xeno.add_minimap_marker() + minimap_added -= xeno_weakref + +/obj/vehicle/multitile/arc/relaymove(mob/user, direction) + if(antenna_deployed) + return FALSE + + return ..() + +/obj/vehicle/multitile/arc/load_role_reserved_slots() + var/datum/role_reserved_slots/RRS = new + RRS.category_name = "CIC Officer" + RRS.roles = list(JOB_SO, JOB_SEA, JOB_XO, JOB_CO, JOB_GENERAL) + RRS.total = 2 + role_reserved_slots += RRS + + RRS = new + RRS.category_name = "Intelligence Officer" + RRS.roles = list(JOB_INTEL) + RRS.total = 1 + role_reserved_slots += RRS + +/obj/vehicle/multitile/arc/set_seated_mob(seat, mob/living/M) + . = ..() + if(!.) + return + + give_action(M, /datum/action/human_action/toggle_arc_antenna) + +/obj/vehicle/multitile/arc/add_seated_verbs(mob/living/M, seat) + if(!M.client) + return + add_verb(M.client, list( + /obj/vehicle/multitile/proc/get_status_info, + /obj/vehicle/multitile/arc/proc/open_arc_controls_guide, + /obj/vehicle/multitile/proc/toggle_door_lock, + /obj/vehicle/multitile/proc/activate_horn, + /obj/vehicle/multitile/proc/name_vehicle, + /obj/vehicle/multitile/arc/proc/toggle_antenna, + )) + +/obj/vehicle/multitile/arc/remove_seated_verbs(mob/living/M, seat) + if(!M.client) + return + remove_verb(M.client, list( + /obj/vehicle/multitile/proc/get_status_info, + /obj/vehicle/multitile/arc/proc/open_arc_controls_guide, + /obj/vehicle/multitile/proc/toggle_door_lock, + /obj/vehicle/multitile/proc/activate_horn, + /obj/vehicle/multitile/proc/name_vehicle, + /obj/vehicle/multitile/arc/proc/toggle_antenna, + )) + SStgui.close_user_uis(M, src) + +/obj/vehicle/multitile/arc/initialize_cameras(change_tag = FALSE) + if(!camera) + camera = new /obj/structure/machinery/camera/vehicle(src) + if(change_tag) + camera.c_tag = "#[rand(1,100)] M540-B \"[nickname]\" ARC" + if(camera_int) + camera_int.c_tag = camera.c_tag + " interior" + else + camera.c_tag = "#[rand(1,100)] M540-B ARC" + if(camera_int) + camera_int.c_tag = camera.c_tag + " interior" + +/obj/vehicle/multitile/arc/MouseDrop_T(mob/M, mob/user) + . = ..() + if((M != user) || !isxeno(user)) + return + + if(health > 0) + to_chat(user, SPAN_XENO("We can't go under [src] until it is destroyed!")) + return + + var/turf/current_turf = get_turf(user) + var/dir_to_go = get_dir(current_turf, src) + for(var/i in 1 to 3) + current_turf = get_step(current_turf, dir_to_go) + if(!(current_turf in locs)) + break + + if(current_turf.density) + to_chat(user, SPAN_XENO("The path under [src] is obstructed!")) + return + + // Now we check to make sure the turf on the other side of the ARC isn't dense too + current_turf = get_step(current_turf, dir_to_go) + if(current_turf.density) + to_chat(user, SPAN_XENO("The path under [src] is obstructed!")) + return + + to_chat(user, SPAN_XENO("We begin to crawl under [src]...")) + if(!do_after(user, 3 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE)) + to_chat(user, SPAN_XENO("We stop crawling under [src].")) + return + + user.forceMove(current_turf) + to_chat(user, SPAN_XENO("We crawl to the other side of [src].")) + +/* +** PRESETS SPAWNERS +*/ +/obj/effect/vehicle_spawner/arc + name = "ARC Transport Spawner" + icon = 'icons/obj/vehicles/apc.dmi' + icon_state = "apc_base" + pixel_x = -48 + pixel_y = -48 + +/obj/effect/vehicle_spawner/arc/Initialize() + . = ..() + spawn_vehicle() + return INITIALIZE_HINT_QDEL + +/obj/effect/vehicle_spawner/arc/spawn_vehicle() + var/obj/vehicle/multitile/arc/ARC = new (loc) + + load_misc(ARC) + load_hardpoints(ARC) + handle_direction(ARC) + ARC.update_icon() + +/obj/effect/vehicle_spawner/arc/load_hardpoints(obj/vehicle/multitile/arc/vehicle) + vehicle.add_hardpoint(new /obj/item/hardpoint/locomotion/arc_wheels) + vehicle.add_hardpoint(new /obj/item/hardpoint/primary/arc_sentry) + vehicle.add_hardpoint(new /obj/item/hardpoint/support/arc_antenna) diff --git a/code/modules/vehicles/arc/verbs.dm b/code/modules/vehicles/arc/verbs.dm new file mode 100644 index 000000000000..3b866236e77d --- /dev/null +++ b/code/modules/vehicles/arc/verbs.dm @@ -0,0 +1,121 @@ +/obj/vehicle/multitile/arc/proc/toggle_antenna(mob/toggler) + set name = "Toggle Sensor Antenna" + set desc = "Raises or lowers the external sensor antenna. While raised, the ARC cannot move." + set category = "Vehicle" + + var/mob/user = toggler || usr + if(!user || !istype(user)) + return + + var/obj/vehicle/multitile/arc/vehicle = user.interactee + if(!istype(vehicle)) + return + + var/seat + for(var/vehicle_seat in vehicle.seats) + if(vehicle.seats[vehicle_seat] == user) + seat = vehicle_seat + break + + if(!seat) + return + + if(vehicle.health < initial(vehicle.health) * 0.5) + to_chat(user, SPAN_WARNING("[vehicle]'s hull is too damaged to operate!")) + return + + var/obj/item/hardpoint/support/arc_antenna/antenna = locate() in vehicle.hardpoints + if(!antenna) + to_chat(user, SPAN_WARNING("[vehicle] has no antenna mounted!")) + return + + if(antenna.deploying) + return + + if(antenna.health <= 0) + to_chat(user, SPAN_WARNING("[antenna] is broken!")) + return + + if(vehicle.antenna_deployed) + to_chat(user, SPAN_NOTICE("You begin to retract [antenna]...")) + antenna.deploying = TRUE + if(!do_after(user, max(vehicle.antenna_toggle_time - antenna.deploy_animation_time, 1 SECONDS), target = vehicle)) + to_chat(user, SPAN_NOTICE("You stop retracting [antenna].")) + antenna.deploying = FALSE + return + + antenna.retract_antenna() + addtimer(CALLBACK(vehicle, PROC_REF(finish_antenna_retract), user), antenna.deploy_animation_time) + + else + to_chat(user, SPAN_NOTICE("You begin to extend [antenna]...")) + antenna.deploying = TRUE + if(!do_after(user, max(vehicle.antenna_toggle_time - antenna.deploy_animation_time, 1 SECONDS), target = vehicle)) + to_chat(user, SPAN_NOTICE("You stop extending [antenna].")) + antenna.deploying = FALSE + return + + antenna.deploy_antenna() + addtimer(CALLBACK(vehicle, PROC_REF(finish_antenna_deploy), user), antenna.deploy_animation_time) + +/obj/vehicle/multitile/arc/proc/finish_antenna_retract(mob/user) + var/obj/item/hardpoint/support/arc_antenna/antenna = locate() in hardpoints + if(!antenna) + antenna.deploying = FALSE + return + + if(user) + to_chat(user, SPAN_NOTICE("You retract [antenna], enabling the ARC to move again.")) + playsound(user, 'sound/machines/hydraulics_2.ogg', 80, TRUE) + antenna_deployed = !antenna_deployed + antenna.deploying = FALSE + update_icon() + SEND_SIGNAL(src, COMSIG_ARC_ANTENNA_TOGGLED) + +/obj/vehicle/multitile/arc/proc/finish_antenna_deploy(mob/user) + var/obj/item/hardpoint/support/arc_antenna/antenna = locate() in hardpoints + if(!antenna) + antenna.deploying = FALSE + return + + if(user) + to_chat(user, SPAN_NOTICE("You extend [antenna], locking the ARC in place.")) + playsound(user, 'sound/machines/hydraulics_2.ogg', 80, TRUE) + antenna_deployed = !antenna_deployed + antenna.deploying = FALSE + update_icon() + SEND_SIGNAL(src, COMSIG_ARC_ANTENNA_TOGGLED) + +/obj/vehicle/multitile/arc/proc/open_arc_controls_guide() + set name = "Vehicle Controls Guide" + set desc = "MANDATORY FOR FIRST PLAY AS VEHICLE CREWMAN OR AFTER UPDATES." + set category = "Vehicle" + + var/mob/user = usr + if(!istype(user)) + return + + var/obj/vehicle/multitile/arc/vehicle = user.interactee + if(!istype(vehicle)) + return + + var/seat + for(var/vehicle_seat in vehicle.seats) + if(vehicle.seats[vehicle_seat] == user) + seat = vehicle_seat + break + + if(!seat) + return + + var/dat = "Common verbs:
\ + 1. \"G: Name Vehicle\" - used to add a custom name to the vehicle. Single use. 26 characters maximum.
\ + 2. \"I: Get Status Info\" - brings up \"Vehicle Status Info\" window with all available information about your vehicle.
\ + 3. \"G: Toggle Sensor Antenna\" - extend or retract the ARC's sensor antenna. While extended, all unknown lifeforms within a large range can be seen by all on the tacmap, but the ARC cannot move. Additionally enables the automated RE700 cannon.
\ + Driver verbs:
1. \"G: Activate Horn\" - activates vehicle horn. Keep in mind, that vehicle horn is very loud and can be heard from afar by both allies and foes.
\ + 2. \"G: Toggle Door Locks\" - toggles vehicle's access restrictions. Crewman, Brig and Command accesses bypass these restrictions.
\ + Driver shortcuts:
1. \"CTRL + Click\" - activates vehicle horn.
" + + show_browser(user, dat, "Vehicle Controls Guide", "vehicle_help", "size=900x500") + onclose(user, "vehicle_help") + return diff --git a/code/modules/vehicles/hardpoints/hardpoint.dm b/code/modules/vehicles/hardpoints/hardpoint.dm index 21e3e4b29f89..9b69308a47a0 100644 --- a/code/modules/vehicles/hardpoints/hardpoint.dm +++ b/code/modules/vehicles/hardpoints/hardpoint.dm @@ -125,6 +125,8 @@ /// Currently selected target to fire at. Set with set_target(). var/atom/target + /// The type of projectile to fire + var/projectile_type = /obj/projectile //----------------------------- //------GENERAL PROCS---------- @@ -149,7 +151,7 @@ if(owner || indestructible) return - health = max(0, health - severity / 2) + take_damage(severity / 2) if(health <= 0) visible_message(SPAN_WARNING("\The [src] disintegrates into useless pile of scrap under the damage it suffered.")) deconstruct(TRUE) @@ -159,7 +161,7 @@ return /obj/item/hardpoint/proc/generate_bullet(mob/user, turf/origin_turf) - var/obj/projectile/P = new(origin_turf, create_cause_data(initial(name), user)) + var/obj/projectile/P = new projectile_type(origin_turf, create_cause_data(initial(name), user)) P.generate_bullet(new ammo.default_ammo) // Apply bullet traits from gun for(var/entry in traits_to_give) @@ -180,7 +182,14 @@ return TRUE /obj/item/hardpoint/proc/take_damage(damage) + if(health <= 0) + return health = max(0, health - damage * damage_multiplier) + if(!health) + on_destroy() + +/obj/item/hardpoint/proc/on_destroy() + return /obj/item/hardpoint/proc/is_activatable() if(health <= 0) @@ -581,7 +590,6 @@ /// Wrapper proc for the autofire system to ensure the important args aren't null. /obj/item/hardpoint/proc/fire_wrapper(atom/target, mob/living/user, params) - SHOULD_NOT_OVERRIDE(TRUE) if(!target) target = src.target if(!user) @@ -717,7 +725,9 @@ var/is_broken = health <= 0 var/image/I = image(icon = disp_icon, icon_state = "[disp_icon_state]_[is_broken ? "1" : "0"]", pixel_x = x_offset, pixel_y = y_offset, dir = new_dir) switch(round((health / initial(health)) * 100)) - if(0 to 20) + if(0) + I.color = "#888888" + if(1 to 20) I.color = "#4e4e4e" if(21 to 40) I.color = "#6e6e6e" @@ -792,3 +802,11 @@ /obj/item/hardpoint/get_applying_acid_time() return 10 SECONDS //you are not supposed to be able to easily combat-melt irreplaceable things. + +/// Proc to be overridden if you want to have special conditions preventing the removal of the hardpoint. Add chat messages in this proc if you want to tell the player why +/obj/item/hardpoint/proc/can_be_removed(mob/remover) + SHOULD_CALL_PARENT(TRUE) + + if(remover.stat > CONSCIOUS) + return FALSE + return TRUE diff --git a/code/modules/vehicles/hardpoints/hardpoint_ammo/arc_sentry_ammo.dm b/code/modules/vehicles/hardpoints/hardpoint_ammo/arc_sentry_ammo.dm new file mode 100644 index 000000000000..f9c28e151514 --- /dev/null +++ b/code/modules/vehicles/hardpoints/hardpoint_ammo/arc_sentry_ammo.dm @@ -0,0 +1,16 @@ +/obj/item/ammo_magazine/hardpoint/arc_sentry + name = "\improper RE700 Rotary Cannon Magazine" + desc = "A magazine for RE700 Rotary Cannon filled with 20mm rounds. Supports IFF." + caliber = "20mm" + icon_state = "ace_autocannon" + w_class = SIZE_LARGE + default_ammo = /datum/ammo/bullet/re700 + max_rounds = 500 + gun_type = /obj/item/hardpoint/primary/arc_sentry + +/obj/item/ammo_magazine/hardpoint/arc_sentry/update_icon() + if(current_rounds > 0) + icon_state = "ace_autocannon" + else + icon_state = "ace_autocannon_empty" + diff --git a/code/modules/vehicles/hardpoints/primary/arc_sentry.dm b/code/modules/vehicles/hardpoints/primary/arc_sentry.dm new file mode 100644 index 000000000000..4b5087b2e608 --- /dev/null +++ b/code/modules/vehicles/hardpoints/primary/arc_sentry.dm @@ -0,0 +1,229 @@ +// APC cannons +/obj/item/hardpoint/primary/arc_sentry + name = "\improper RE700 Rotary Cannon" + desc = "A primary two-barrel cannon for the ARC that shoots 12.7mm IFF-compatible rounds." + icon = 'icons/obj/vehicles/hardpoints/arc.dmi' + + icon_state = "autocannon" + disp_icon = "arc" + disp_icon_state = "autocannon" + activation_sounds = list('sound/weapons/gun_m60.ogg') + + damage_multiplier = 0.1 + health = 125 + + origins = list(0, 0) + + ammo = new /obj/item/ammo_magazine/hardpoint/arc_sentry + max_clips = 2 + + use_muzzle_flash = TRUE + angle_muzzleflash = FALSE + muzzleflash_icon_state = "muzzle_flash_double" + + muzzle_flash_pos = list( + "1" = list(1, 4), + "2" = list(1, -29), + "4" = list(16, 3), + "8" = list(-16, 3) + ) + gun_firemode = GUN_FIREMODE_BURSTFIRE + gun_firemode_list = list( + GUN_FIREMODE_BURSTFIRE, + ) + burst_delay = 2 + burst_amount = 3 + projectile_type = /obj/projectile/arc_sentry + + /// Potential targets the turret can shoot at + var/list/targets = list() + /// The currently focused sentry target + var/atom/movable/sentry_target = null + /// The range that this turret can shoot at the furthest + var/turret_range = 5 + /// What factions this sentry is aligned with + var/faction_group = FACTION_LIST_MARINE + +/obj/item/hardpoint/primary/arc_sentry/on_install(obj/vehicle/multitile/vehicle) + . = ..() + RegisterSignal(owner, COMSIG_ARC_ANTENNA_TOGGLED, PROC_REF(toggle_processing)) + toggle_processing() // We can't know that the antenna is in the same position as when the gun was removed + +/obj/item/hardpoint/primary/arc_sentry/on_uninstall(obj/vehicle/multitile/vehicle) + . = ..() + UnregisterSignal(owner, COMSIG_ARC_ANTENNA_TOGGLED) + STOP_PROCESSING(SSfastobj, src) + +/obj/item/hardpoint/primary/arc_sentry/Destroy() + STOP_PROCESSING(SSfastobj, src) + sentry_target = null + return ..() + +/obj/item/hardpoint/primary/arc_sentry/proc/toggle_processing() + SIGNAL_HANDLER + if(!owner) + return + + var/obj/vehicle/multitile/arc/vehicle = owner + if(vehicle.antenna_deployed) + START_PROCESSING(SSfastobj, src) + + else + STOP_PROCESSING(SSfastobj, src) + +/obj/item/hardpoint/primary/arc_sentry/process() + for(var/mob/living/in_range_mob in range(turret_range, owner)) + targets |= in_range_mob + + if(!length(targets)) + return FALSE + + if(!sentry_target) + sentry_target = pick(targets) + + get_target(sentry_target) + return TRUE + +/obj/item/hardpoint/primary/arc_sentry/set_bullet_traits() + LAZYADD(traits_to_give, list( + BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_iff, faction_group) + )) + +/obj/item/hardpoint/primary/arc_sentry/fire_wrapper(atom/target, mob/living/user, params) + if(!target) + target = src.target + if(!target) + return NONE + + return try_fire(target, null, params) + + +/obj/item/hardpoint/primary/arc_sentry/generate_bullet(mob/user, turf/origin_turf) + var/obj/projectile/arc_sentry/made_projectile = ..() + made_projectile.permutated += owner + return made_projectile + +/obj/item/hardpoint/primary/arc_sentry/start_fire(datum/source, atom/object, turf/location, control, params) + if(QDELETED(object)) + return + if(!COOLDOWN_FINISHED(src, fire_cooldown)) + return + + set_target(object) + SEND_SIGNAL(src, COMSIG_GUN_FIRE) + +/obj/item/hardpoint/primary/arc_sentry/proc/get_target(atom/movable/new_target) + if(QDELETED(new_target)) + sentry_target = null + return + + if(!targets.Find(new_target)) + targets.Add(new_target) + + if(!length(targets)) + return + + var/list/conscious_targets = list() + var/list/unconscious_targets = list() + + for(var/mob/living/living_mob as anything in targets) // orange allows sentry to fire through gas and darkness + if(living_mob.stat == DEAD) + purge_target(living_mob) + continue + + if(living_mob.get_target_lock(faction_group) || living_mob.invisibility || HAS_TRAIT(living_mob, TRAIT_ABILITY_BURROWED)) + purge_target(living_mob) + continue + + var/list/turf/path = get_line(get_turf(src), living_mob) + if(!length(path) || get_dist(get_turf(src), living_mob) > turret_range) + purge_target(living_mob) + continue + + var/blocked = FALSE + for(var/turf/tile as anything in path) + if(tile.density || tile.opacity) + blocked = TRUE + break + + for(var/obj/structure/struct in tile) + if(struct.opacity) + blocked = TRUE + break + + for(var/obj/vehicle/multitile/vehicle in tile) + if(vehicle == owner) // Some of the tiles will inevitably be the ARC itself + continue + blocked = TRUE + break + + if(locate(/obj/effect/particle_effect/smoke) in tile) + blocked = TRUE + break + + if(blocked) + purge_target(living_mob) + continue + + if(living_mob.stat & UNCONSCIOUS) + unconscious_targets += living_mob + else + conscious_targets += living_mob + + if((sentry_target in conscious_targets) || (sentry_target in unconscious_targets)) + sentry_target = sentry_target + + else if(length(conscious_targets)) + sentry_target = pick(conscious_targets) + + else if(length(unconscious_targets)) + sentry_target = pick(unconscious_targets) + + if(!sentry_target) //No targets, don't bother firing + return + + start_fire(object = sentry_target) + +/obj/item/hardpoint/primary/arc_sentry/proc/purge_target(mob/target) + if(target == sentry_target) + sentry_target = null + targets.Remove(target) + +/obj/item/hardpoint/primary/arc_sentry/can_be_removed(mob/remover) + var/obj/vehicle/multitile/arc/arc_owner = owner + if(!istype(arc_owner)) + return TRUE + + if(arc_owner.antenna_deployed) + to_chat(remover, SPAN_WARNING("[src] cannot be removed from [owner] while its antenna is deployed.")) + return FALSE + + return ..() + +/obj/projectile/arc_sentry/Initialize(mapload, datum/cause_data/cause_data) + . = ..() + RegisterSignal(src, COMSIG_BULLET_POST_HANDLE_OBJ, PROC_REF(check_passthrough)) + +/obj/projectile/arc_sentry/check_canhit(turf/current_turf, turf/next_turf) + var/proj_dir = get_dir(current_turf, next_turf) + var/obj/item/hardpoint/arc_sentry = shot_from + if(!(arc_sentry.owner in current_turf) && !(arc_sentry.owner in next_turf) && (proj_dir & (proj_dir - 1)) && !current_turf.Adjacent(next_turf)) + ammo.on_hit_turf(current_turf, src) + current_turf.bullet_act(src) + return TRUE + + // Check for hits that would occur when moving to turf, such as a blocking cade + if(scan_a_turf(next_turf, proj_dir)) + return TRUE + + return FALSE + +/obj/projectile/arc_sentry/proc/check_passthrough(datum/source, obj/hit_obj, bool) + SIGNAL_HANDLER + + if(!istype(shot_from, /obj/item/hardpoint)) + return + + var/obj/item/hardpoint/sentry = shot_from + if(sentry.owner == hit_obj) + return COMPONENT_BULLET_PASS_THROUGH diff --git a/code/modules/vehicles/hardpoints/support/antenna.dm b/code/modules/vehicles/hardpoints/support/antenna.dm new file mode 100644 index 000000000000..11fd50a9506e --- /dev/null +++ b/code/modules/vehicles/hardpoints/support/antenna.dm @@ -0,0 +1,94 @@ +/obj/item/hardpoint/support/arc_antenna + name = "\improper U-56 Radar Antenna" + desc = "A heavy-duty antenna built for the ARC." + icon = 'icons/obj/vehicles/hardpoints/arc.dmi' + + icon_state = "antenna" + disp_icon = "arc" + disp_icon_state = "antenna" + + damage_multiplier = 0.1 + + health = 500 + + /// How long the antenna deploy/retract animation is, keep accurate to the sprite in the dmi + var/deploy_animation_time = 1.2 SECONDS + /// If the antenna is already deploying + var/deploying = FALSE + +/obj/item/hardpoint/support/arc_antenna/proc/deploy_antenna() + set waitfor = FALSE + + disp_icon_state = "" + if(owner) + owner.update_icon() + var/obj/dummy_obj = new() + dummy_obj.icon = 'icons/obj/vehicles/arc.dmi' + dummy_obj.icon_state = "antenna_cover_0" + dummy_obj.dir = owner.dir + dummy_obj.vis_flags = VIS_INHERIT_ID | VIS_INHERIT_LAYER | VIS_INHERIT_PLANE + owner.vis_contents += dummy_obj + flick("antenna_extending", dummy_obj) + sleep(deploy_animation_time) + qdel(dummy_obj) + disp_icon_state = initial(disp_icon_state) + +/obj/item/hardpoint/support/arc_antenna/proc/retract_antenna() + set waitfor = FALSE + + disp_icon_state = "" + if(owner) + owner.update_icon() + var/obj/dummy_obj = new() + dummy_obj.icon = 'icons/obj/vehicles/arc.dmi' + dummy_obj.icon_state = "antenna_cover_0" + dummy_obj.dir = owner.dir + dummy_obj.vis_flags = VIS_INHERIT_ID | VIS_INHERIT_LAYER | VIS_INHERIT_PLANE + owner.vis_contents += dummy_obj + flick("antenna_retracting", dummy_obj) + sleep(deploy_animation_time) + qdel(dummy_obj) + disp_icon_state = initial(disp_icon_state) + +/obj/item/hardpoint/support/arc_antenna/get_icon_image(x_offset, y_offset, new_dir) + var/is_broken = health <= 0 + var/antenna_extended = FALSE + if(istype(owner, /obj/vehicle/multitile/arc)) + var/obj/vehicle/multitile/arc/arc_owner = owner + antenna_extended = arc_owner.antenna_deployed + + var/image/antenna_img = image(icon = disp_icon, icon_state = "[disp_icon_state]_[antenna_extended ? "extended" : "cover"]_[is_broken ? "1" : "0"]", pixel_x = x_offset, pixel_y = y_offset, dir = new_dir) + switch(round((health / initial(health)) * 100)) + if(0) + antenna_img.color = "#888888" + if(1 to 20) + antenna_img.color = "#4e4e4e" + if(21 to 40) + antenna_img.color = "#6e6e6e" + if(41 to 60) + antenna_img.color = "#8b8b8b" + if(61 to 80) + antenna_img.color = "#bebebe" + else + antenna_img.color = null + return antenna_img + +/obj/item/hardpoint/support/arc_antenna/can_be_removed(mob/remover) + var/obj/vehicle/multitile/arc/arc_owner = owner + if(!istype(arc_owner)) + return TRUE + + if(arc_owner.antenna_deployed) + to_chat(remover, SPAN_WARNING("[src] cannot be removed from [owner] while it is deployed.")) + return FALSE + + return ..() + +/obj/item/hardpoint/support/arc_antenna/on_destroy() + var/obj/vehicle/multitile/arc/arc_owner = owner + if(!istype(arc_owner)) + return + + if(arc_owner.antenna_deployed) + retract_antenna() + addtimer(CALLBACK(arc_owner, TYPE_PROC_REF(/obj/vehicle/multitile/arc, finish_antenna_retract)), deploy_animation_time) diff --git a/code/modules/vehicles/hardpoints/wheels/arc_wheels.dm b/code/modules/vehicles/hardpoints/wheels/arc_wheels.dm new file mode 100644 index 000000000000..9bb6c31746e0 --- /dev/null +++ b/code/modules/vehicles/hardpoints/wheels/arc_wheels.dm @@ -0,0 +1,17 @@ +/obj/item/hardpoint/locomotion/arc_wheels + name = "ARC Wheels" + desc = "Integral to the movement of the ARC." + icon = 'icons/obj/vehicles/hardpoints/arc.dmi' + + damage_multiplier = 0.15 + + icon_state = "tires" + disp_icon = "arc" + disp_icon_state = "arc_wheels" + + health = 500 + + move_delay = VEHICLE_SPEED_SUPERFAST + move_max_momentum = 2 + move_momentum_build_factor = 1.5 + move_turn_momentum_loss_factor = 0.5 diff --git a/code/modules/vehicles/interior/areas.dm b/code/modules/vehicles/interior/areas.dm index 254bcb6b26ea..399e55e11450 100644 --- a/code/modules/vehicles/interior/areas.dm +++ b/code/modules/vehicles/interior/areas.dm @@ -29,5 +29,9 @@ name = "van interior" icon_state = "van" +/area/interior/vehicle/arc + name = "\improper ARC interior" + icon_state = "arc" + /area/interior/fancylocker name = "closet interior" diff --git a/code/modules/vehicles/interior/interior_landmarks.dm b/code/modules/vehicles/interior/interior_landmarks.dm index 90284682d2d4..fa1eee8651ac 100644 --- a/code/modules/vehicles/interior/interior_landmarks.dm +++ b/code/modules/vehicles/interior/interior_landmarks.dm @@ -227,7 +227,7 @@ Phone.pixel_x = pixel_x Phone.pixel_y = pixel_y Phone.phone_category = "Vehicles" - Phone.phone_id = I.exterior.name + Phone.phone_id = replacetext(Phone.phone_id, "\improper", "") // this has to be done because phone IDs need to be the same as their display name (\improper doesn't display, obviously) qdel(src) diff --git a/code/modules/vehicles/multitile/multitile.dm b/code/modules/vehicles/multitile/multitile.dm index f3b7be510b08..18dade67b834 100644 --- a/code/modules/vehicles/multitile/multitile.dm +++ b/code/modules/vehicles/multitile/multitile.dm @@ -334,11 +334,12 @@ // Checked here because we want to be able to null the mob in a seat if(!istype(M)) - return + return FALSE M.set_interaction(src) M.reset_view(src) give_action(M, /datum/action/human_action/vehicle_unbuckle) + return TRUE /// Get crewmember of seat. /obj/vehicle/multitile/proc/get_seat_mob(seat) diff --git a/code/modules/vehicles/multitile/multitile_hardpoints.dm b/code/modules/vehicles/multitile/multitile_hardpoints.dm index 2a6f97dda06f..b94b8459890f 100644 --- a/code/modules/vehicles/multitile/multitile_hardpoints.dm +++ b/code/modules/vehicles/multitile/multitile_hardpoints.dm @@ -149,7 +149,7 @@ hps += H var/chosen_hp = tgui_input_list(usr, "Select a hardpoint to remove", "Hardpoint Removal", (hps + "Cancel")) - if(chosen_hp == "Cancel" || !chosen_hp || !in_range(src, user)) + if(chosen_hp == "Cancel" || !chosen_hp || (get_dist(src, user) > 2)) //get_dist uses 2 because the vehicle is 3x3 return var/obj/item/hardpoint/old = chosen_hp @@ -158,6 +158,9 @@ to_chat(user, SPAN_WARNING("There is nothing installed there.")) return + if(!old.can_be_removed(user)) + return + // It's in a holder if(!(old in hardpoints)) for(var/obj/item/hardpoint/holder/H in hardpoints) diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index 8632159b4f6d..c78be6fa57ec 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -159,10 +159,11 @@ // Checked here because we want to be able to null the mob in a seat if(!istype(M)) - return + return FALSE M.forceMove(src) M.set_interaction(src) + return TRUE /obj/vehicle/proc/turn_on() if(stat) diff --git a/colonialmarines.dme b/colonialmarines.dme index b69a03136b78..11902f619cad 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -382,6 +382,7 @@ #include "code\datums\ammo\rocket.dm" #include "code\datums\ammo\shrapnel.dm" #include "code\datums\ammo\xeno.dm" +#include "code\datums\ammo\bullet\arc.dm" #include "code\datums\ammo\bullet\bullet.dm" #include "code\datums\ammo\bullet\lever_action.dm" #include "code\datums\ammo\bullet\pistol.dm" @@ -404,6 +405,7 @@ #include "code\datums\components\cluster_stack.dm" #include "code\datums\components\connect_mob_behalf.dm" #include "code\datums\components\crate_tag.dm" +#include "code\datums\components\disk_reader.dm" #include "code\datums\components\footstep.dm" #include "code\datums\components\healing_reduction.dm" #include "code\datums\components\id_lock.dm" @@ -631,6 +633,7 @@ #include "code\datums\skills\synthetic.dm" #include "code\datums\skills\upp.dm" #include "code\datums\skills\uscm.dm" +#include "code\datums\skills\wygoons.dm" #include "code\datums\stamina\_stamina.dm" #include "code\datums\stamina\none.dm" #include "code\datums\statistics\cause_data.dm" @@ -676,6 +679,7 @@ #include "code\datums\supply_packs\restricted_equipment.dm" #include "code\datums\supply_packs\spec_ammo.dm" #include "code\datums\supply_packs\vehicle_ammo.dm" +#include "code\datums\supply_packs\vehicle_equipment.dm" #include "code\datums\supply_packs\weapons.dm" #include "code\datums\tutorial\_tutorial.dm" #include "code\datums\tutorial\_tutorial_menu.dm" @@ -822,6 +826,7 @@ #include "code\game\jobs\job\special\provost.dm" #include "code\game\jobs\job\special\uaac.dm" #include "code\game\jobs\job\special\uscm.dm" +#include "code\game\machinery\aicore_lockdown.dm" #include "code\game\machinery\air_alarm.dm" #include "code\game\machinery\air_sensor.dm" #include "code\game\machinery\autolathe.dm" @@ -1688,6 +1693,7 @@ #include "code\modules\cm_tech\resources\resource.dm" #include "code\modules\cm_tech\techs\abstract\repeatable.dm" #include "code\modules\cm_tech\techs\abstract\transitory.dm" +#include "code\modules\cm_tech\techs\marine\tier1\arc.dm" #include "code\modules\cm_tech\techs\marine\tier1\points.dm" #include "code\modules\cm_tech\techs\marine\tier2\orbital_ammo.dm" #include "code\modules\cm_tech\techs\marine\tier3\cryo_spec.dm" @@ -2362,6 +2368,7 @@ #include "code\modules\tgui\states\default.dm" #include "code\modules\tgui\states\hands.dm" #include "code\modules\tgui\states\human_adjacent.dm" +#include "code\modules\tgui\states\in_view.dm" #include "code\modules\tgui\states\inventory.dm" #include "code\modules\tgui\states\never.dm" #include "code\modules\tgui\states\new_player.dm" @@ -2397,6 +2404,8 @@ #include "code\modules\vehicles\apc\apc_command.dm" #include "code\modules\vehicles\apc\apc_medical.dm" #include "code\modules\vehicles\apc\interior.dm" +#include "code\modules\vehicles\arc\arc.dm" +#include "code\modules\vehicles\arc\verbs.dm" #include "code\modules\vehicles\hardpoints\hardpoint.dm" #include "code\modules\vehicles\hardpoints\armor\armor.dm" #include "code\modules\vehicles\hardpoints\armor\ballistic.dm" @@ -2404,6 +2413,7 @@ #include "code\modules\vehicles\hardpoints\armor\concussive.dm" #include "code\modules\vehicles\hardpoints\armor\paladin.dm" #include "code\modules\vehicles\hardpoints\armor\snowplow.dm" +#include "code\modules\vehicles\hardpoints\hardpoint_ammo\arc_sentry_ammo.dm" #include "code\modules\vehicles\hardpoints\hardpoint_ammo\autocannon_ammo.dm" #include "code\modules\vehicles\hardpoints\hardpoint_ammo\cupola_ammo.dm" #include "code\modules\vehicles\hardpoints\hardpoint_ammo\dualcannon_ammo.dm" @@ -2419,6 +2429,7 @@ #include "code\modules\vehicles\hardpoints\hardpoint_ammo\tow_ammo.dm" #include "code\modules\vehicles\hardpoints\holder\holder.dm" #include "code\modules\vehicles\hardpoints\holder\tank_turret.dm" +#include "code\modules\vehicles\hardpoints\primary\arc_sentry.dm" #include "code\modules\vehicles\hardpoints\primary\autocannon.dm" #include "code\modules\vehicles\hardpoints\primary\dual_cannon.dm" #include "code\modules\vehicles\hardpoints\primary\flamer.dm" @@ -2433,12 +2444,14 @@ #include "code\modules\vehicles\hardpoints\secondary\tow.dm" #include "code\modules\vehicles\hardpoints\special\firing_port_weapon.dm" #include "code\modules\vehicles\hardpoints\special\special.dm" +#include "code\modules\vehicles\hardpoints\support\antenna.dm" #include "code\modules\vehicles\hardpoints\support\artillery.dm" #include "code\modules\vehicles\hardpoints\support\flare.dm" #include "code\modules\vehicles\hardpoints\support\iwsa.dm" #include "code\modules\vehicles\hardpoints\support\overdrive.dm" #include "code\modules\vehicles\hardpoints\support\support.dm" #include "code\modules\vehicles\hardpoints\wheels\apc_wheels.dm" +#include "code\modules\vehicles\hardpoints\wheels\arc_wheels.dm" #include "code\modules\vehicles\hardpoints\wheels\locomotion.dm" #include "code\modules\vehicles\hardpoints\wheels\treads.dm" #include "code\modules\vehicles\hardpoints\wheels\van_wheels.dm" diff --git a/html/changelogs/AutoChangeLog-pr-6183.yml b/html/changelogs/AutoChangeLog-pr-6183.yml deleted file mode 100644 index 5971ec8dae32..000000000000 --- a/html/changelogs/AutoChangeLog-pr-6183.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Steelpoint" -delete-after: True -changes: - - rscadd: "UPP and CLF Combat Synthetic preset is now available for admins to spawn them in." \ No newline at end of file diff --git a/html/changelogs/archive/2024-04.yml b/html/changelogs/archive/2024-04.yml index efa0f73ad350..bf3a3c8de208 100644 --- a/html/changelogs/archive/2024-04.yml +++ b/html/changelogs/archive/2024-04.yml @@ -329,3 +329,27 @@ - bugfix: Fixes boilers slowing themselves by using long range sight while resting. iloveloopers: - qol: Alt clicking a reagent tank will now toggle whether its dispensing or filling +2024-04-25: + Drathek: + - bugfix: 'Fixed hugger handling in drone tutorial: Now the hugger dying will put + another hugger into the tutorial morpher.' + Steelpoint: + - rscadd: UPP and CLF Combat Synthetic preset is now available for admins to spawn + them in. + ihatethisengine: + - bugfix: spotlight no longer breaks after every flight + - rscadd: Combat Correspondent can broadcast speech and emotes. + - rscadd: Speech close enough to the camera will be shown above connected TVs as + abovehead messages + realforest2001: + - bugfix: You can delete flight logs from ARES Interface again as intended. +2024-04-26: + Git-Nivrak: + - qol: You can now change the color of pill bottles in the chem master or with a + hand labeler. + realforest2001: + - spellcheck: Fixes a typo for M4RA AP Ammo in the ASRS menu. +2024-04-27: + Lagomorphica: + - balance: The spotter laser designators, scout laser designators, and scout cloak + are now unmeltable and indestructible to explosions. diff --git a/html/changelogs/archive/2024-05.yml b/html/changelogs/archive/2024-05.yml new file mode 100644 index 000000000000..af586d5033c1 --- /dev/null +++ b/html/changelogs/archive/2024-05.yml @@ -0,0 +1,92 @@ +2024-05-02: + Drathek: + - balance: Lurker invisibility recharge time is now 20s (up from 15s) + - balance: Lurker invisibility now ends when devouring but refunds 50% of time unused + - balance: Lurker invisibility bump now refunds 50% of time unused + - balance: Lurker invisibility can now be toggled refunding 90% of time unused (with + dbl click prevention) + - rscdel: Removed defender crest toggle balloon alerts + - bugfix: Lurker invisibility code is refactored to properly use cooldowns and now + doesn't incorrectly get interrupted by bump code + - rscadd: Lurker invisibility recharge time is now displayed in status tab + - maptweak: Added medlinks to WO + - maptweak: Added a medlink to each ground map + Git-Nivrak: + - rscadd: Survivors can now receive command announcements with IFF and a marine + headset. + Huffie56: + - maptweak: Officer cafeteria added back missing emergency shutters and move the + pipes from bellow the windows. + - maptweak: Starboard aft hull removed the two walls. + - maptweak: Upper engi area around lobby remove pipping going bellow window also + rework the area to better fit aestetic of almayer. + - maptweak: some apc are a bit moved around to avoid them having a small light on + them. + HumiliatedGoblin: + - qol: Now needs help intent to repair walls + - qol: Now needs disarm, grab and harm intent to deconstruct walls + cuberound: + - balance: FM sound is 4 seconds before CAS open fire from 5 + - balance: FM direction warning is 1 seconds before CAS open fire from 1.5 + ihatethisengine: + - rscadd: Corrupted Queen can set up personal alliances with humans + realforest2001: + - rscadd: Changed the AI Core Lockdown to the same system as Research Lockdown. + - rscadd: Added a subtype of desk bell for the AI Core reception desk that sends + an alert over APOLLO Link. + - imageadd: Added directional blast door sprites from Thwomper for blended black + shutters. + - code_imp: Renamed operator var in apollo console code to user. +2024-05-03: + InsaneRed: + - spellcheck: New flavor text and better strain information + realforest2001: + - rscadd: Added the name of an announcement sender, if one exists, to ARES logs. +2024-05-04: + AndroBetel: + - qol: Pointing at an item in your hands shows it off. + BasilHerb: + - rscadd: 'Type 80 bayonet to the mouths of the following mobs: CLF Soldier, CLF + Specialist, CLF Medic, CLF Engineer, CLF Leader.' + Drathek: + - bugfix: Fixed weeded corpses staying weeded if they were transported by shuttle + Git-Nivrak: + - bugfix: Synths no longer get affected by boiler's neurotoxin + coldironwarrior: + - rscadd: Added eyewear options, more glove options to the SEA vendor + - rscadd: SEAs now get full versions of the utility holster belt + - rscdel: Removed the CPR dummy from the SEA vendor + iloveloopers: + - qol: Bookcases can now be wrenched or slashed to be deconstructed + - balance: Kutjevo ledges now take only 0.2 seconds to climb instead of 1 whole + second + kivts: + - bugfix: Infinite metal oversight fix. + realforest2001: + - bugfix: Whitelist notes now work properly. Council can add notes to players regarding + whitelist issues. + - rscadd: Changing whitelist flags with the Whitelist Panel now automatically adds + a note with the reason. + - rscadd: Added skillsets specific to WY Goons. + - rscadd: Added a WY Goon Engineer preset. + vero5123: + - bugfix: Fixes microwave food duplication + - bugfix: Fixes scout being able to be decapitated with a helmet on while cloaked. + - bugfix: Fixes sentries firing at xenos while vent crawling. + - bugfix: fixes hugger not dying when squished by predator + - bugfix: Burrower can no longer tunnel across the map. +2024-05-06: + Git-Nivrak: + - balance: Watcher is now immobilized when zoomed out and loses health off weeds + when not zoomed out + ihatethisengine: + - balance: SADAR backblast now knockdowns and is reduced by xeno explosion resistance + s5nt: + - rscadd: Added more materials to pred ship including more sandstone, wood, table + parts, etc for lodge construction, along with more pred specific food to the + pred kitchen. + - maptweak: Slightly expanded pred ship material storage area by moving bracer storage + over to the left side of the ship. +2024-05-07: + Zonespace, d.1.n.a. (original sprites), esselnek (new sprites): + - rscadd: Added the M540-B Armored Recon Carrier as a t1 intel purchase. diff --git a/icons/mob/hud/hud.dmi b/icons/mob/hud/hud.dmi index 507ec0dd485b..8d89fb781264 100644 Binary files a/icons/mob/hud/hud.dmi and b/icons/mob/hud/hud.dmi differ diff --git a/icons/obj/structures/doors/blastdoors_shutters.dmi b/icons/obj/structures/doors/blastdoors_shutters.dmi index 8c63d0580922..1fe1df44b23a 100644 Binary files a/icons/obj/structures/doors/blastdoors_shutters.dmi and b/icons/obj/structures/doors/blastdoors_shutters.dmi differ diff --git a/icons/obj/vehicles/arc.dmi b/icons/obj/vehicles/arc.dmi new file mode 100644 index 000000000000..f662d5475ac0 Binary files /dev/null and b/icons/obj/vehicles/arc.dmi differ diff --git a/icons/obj/vehicles/hardpoints/arc.dmi b/icons/obj/vehicles/hardpoints/arc.dmi new file mode 100644 index 000000000000..b971efecff5e Binary files /dev/null and b/icons/obj/vehicles/hardpoints/arc.dmi differ diff --git a/icons/turf/areas_interiors.dmi b/icons/turf/areas_interiors.dmi index 47a95da322ea..6fc30badd763 100644 Binary files a/icons/turf/areas_interiors.dmi and b/icons/turf/areas_interiors.dmi differ diff --git a/icons/ui_icons/map_blips_large.dmi b/icons/ui_icons/map_blips_large.dmi index 0cf41b52a4dc..f03433c8c8ef 100644 Binary files a/icons/ui_icons/map_blips_large.dmi and b/icons/ui_icons/map_blips_large.dmi differ diff --git a/maps/interiors/arc.dmm b/maps/interiors/arc.dmm new file mode 100644 index 000000000000..4da63cbff383 --- /dev/null +++ b/maps/interiors/arc.dmm @@ -0,0 +1,296 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aD" = ( +/obj/effect/landmark/interior/spawn/weapons_loader, +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_12" + }, +/area/interior/vehicle/arc) +"be" = ( +/obj/structure/interior_wall/apc{ + icon_state = "door_back" + }, +/turf/open/void/vehicle, +/area/space) +"cJ" = ( +/obj/structure/interior_wall/apc{ + icon_state = "rear_1" + }, +/turf/open/void/vehicle, +/area/space) +"dM" = ( +/obj/structure/interior_wall/apc{ + icon_state = "rear_2" + }, +/turf/open/void/vehicle, +/area/space) +"dU" = ( +/obj/effect/landmark/interior/spawn/vehicle_driver_seat/armor{ + dir = 4 + }, +/obj/structure/machinery/cm_vending/sorted/medical/wall_med/vehicle{ + pixel_x = 6; + pixel_y = 28 + }, +/obj/item/device/megaphone, +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_9_1" + }, +/area/interior/vehicle/arc) +"jb" = ( +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_11" + }, +/area/interior/vehicle/arc) +"ml" = ( +/obj/structure/interior_wall/apc{ + icon_state = "wall" + }, +/obj/effect/landmark/interior/spawn/telephone, +/turf/open/void/vehicle, +/area/space) +"mR" = ( +/obj/structure/interior_wall/apc{ + icon_state = "front_wheel_R" + }, +/turf/open/void/vehicle, +/area/space) +"ro" = ( +/obj/structure/interior_wall/apc{ + alpha = 100; + icon_state = "wall_door_front"; + layer = 5.2; + pixel_y = 32 + }, +/turf/open/void/vehicle, +/area/space) +"ru" = ( +/turf/open/shuttle/vehicle{ + icon_state = "floor_1_6" + }, +/area/interior/vehicle/arc) +"tD" = ( +/obj/structure/interior_wall/apc{ + icon_state = "rear_6" + }, +/turf/open/void/vehicle, +/area/space) +"vt" = ( +/obj/structure/interior_wall/apc{ + icon_state = "rear_wheel_L" + }, +/turf/open/void/vehicle, +/area/space) +"we" = ( +/obj/structure/interior_wall/apc{ + alpha = 100; + icon_state = "door_front"; + layer = 5.2; + pixel_y = 32 + }, +/turf/open/void/vehicle, +/area/space) +"wK" = ( +/obj/structure/interior_wall/apc{ + icon_state = "wheel_front_top_1"; + pixel_x = 1; + pixel_y = -4 + }, +/turf/open/void/vehicle, +/area/space) +"ym" = ( +/obj/structure/interior_wall/apc{ + icon_state = "rear_wheel_R"; + opacity = 0 + }, +/turf/open/void/vehicle, +/area/space) +"yX" = ( +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_8_1" + }, +/area/interior/vehicle/arc) +"CB" = ( +/obj/structure/interior_wall/apc{ + icon_state = "wall"; + opacity = 0 + }, +/turf/open/void/vehicle, +/area/space) +"Dn" = ( +/obj/structure/machinery/prop/almayer/CICmap/computer{ + dir = 4; + pixel_y = 8 + }, +/obj/structure/surface/table/reinforced/prison{ + pixel_y = -3 + }, +/obj/structure/machinery/computer/overwatch/almayer/small{ + dir = 4; + layer = 3.01; + pixel_y = -5 + }, +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_10_1" + }, +/area/interior/vehicle/arc) +"Gy" = ( +/obj/structure/interior_wall/apc{ + icon_state = "front_1" + }, +/turf/open/void/vehicle, +/area/space) +"HB" = ( +/obj/structure/interior_wall/apc{ + icon_state = "corner_small_L" + }, +/obj/structure/interior_wall/apc{ + icon_state = "rear_5" + }, +/turf/open/void/vehicle, +/area/space) +"HJ" = ( +/obj/structure/interior_wall/apc{ + icon_state = "front_6" + }, +/turf/open/void/vehicle, +/area/space) +"Jc" = ( +/obj/structure/interior_wall/apc{ + icon_state = "corner_small_R" + }, +/obj/structure/interior_wall/apc{ + icon_state = "front_5" + }, +/turf/open/void/vehicle, +/area/space) +"Ng" = ( +/obj/structure/interior_wall/apc{ + icon_state = "wall" + }, +/turf/open/void/vehicle, +/area/space) +"NS" = ( +/obj/structure/bed/chair/comfy{ + dir = 8 + }, +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_5" + }, +/area/interior/vehicle/arc) +"Ol" = ( +/obj/effect/landmark/interior/spawn/entrance{ + alpha = 50; + exit_type = /obj/structure/interior_exit/vehicle/apc; + name = "Right APC door"; + tag = "right" + }, +/obj/effect/landmark/interior/spawn/interior_viewport{ + dir = 8; + pixel_x = 5; + pixel_y = 1 + }, +/turf/open/shuttle/vehicle{ + icon_state = "floor_1_12" + }, +/area/interior/vehicle/arc) +"Po" = ( +/obj/structure/surface/table/reinforced/prison{ + pixel_y = -3 + }, +/obj/structure/machinery/computer/intel/disk_reader{ + dir = 4; + pixel_y = 6 + }, +/obj/structure/machinery/computer/groundside_operations{ + dir = 4; + pixel_y = -7 + }, +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_8_1" + }, +/area/interior/vehicle/arc) +"Rb" = ( +/turf/open/void/vehicle, +/area/space) +"Rf" = ( +/obj/structure/interior_wall/apc{ + icon_state = "front_2" + }, +/turf/open/void/vehicle, +/area/space) +"Zs" = ( +/obj/structure/bed/chair/comfy{ + dir = 8 + }, +/turf/open/shuttle/vehicle{ + icon_state = "floor_3_8_1" + }, +/area/interior/vehicle/arc) +"ZF" = ( +/obj/effect/landmark/interior/spawn/interior_viewport{ + dir = 8; + pixel_x = 5; + pixel_y = 8 + }, +/obj/effect/landmark/interior/spawn/entrance{ + alpha = 50; + dir = 1; + exit_type = /obj/structure/interior_exit/vehicle/apc; + name = "Left APC door"; + pixel_y = 32; + tag = "left" + }, +/turf/open/shuttle/vehicle{ + icon_state = "floor_1_11" + }, +/area/interior/vehicle/arc) + +(1,1,1) = {" +tD +HB +dM +cJ +Rb +"} +(2,1,1) = {" +Ng +Po +Dn +vt +Rb +"} +(3,1,1) = {" +ml +Zs +NS +ym +Rb +"} +(4,1,1) = {" +Ng +jb +yX +aD +ro +"} +(5,1,1) = {" +be +ZF +ru +Ol +we +"} +(6,1,1) = {" +wK +CB +dU +mR +Rb +"} +(7,1,1) = {" +HJ +Jc +Rf +Gy +Rb +"} diff --git a/maps/map_files/BigRed/BigRed.dmm b/maps/map_files/BigRed/BigRed.dmm index dbcf22e2e586..82e04ca58330 100644 --- a/maps/map_files/BigRed/BigRed.dmm +++ b/maps/map_files/BigRed/BigRed.dmm @@ -27889,6 +27889,14 @@ icon_state = "wood" }, /area/bigredv2/outside/library) +"efh" = ( +/obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link, +/turf/open/floor{ + dir = 1; + icon_state = "darkyellow2" + }, +/area/bigredv2/caves/eta/research) "efK" = ( /obj/structure/machinery/computer/crew{ density = 0; @@ -66550,7 +66558,7 @@ bvY kdr kdr aBv -bwZ +efh bxo bxz bxo diff --git a/maps/map_files/CORSAT/Corsat.dmm b/maps/map_files/CORSAT/Corsat.dmm index 9c09a95e9f94..6c179dbc8b2c 100644 --- a/maps/map_files/CORSAT/Corsat.dmm +++ b/maps/map_files/CORSAT/Corsat.dmm @@ -179,7 +179,6 @@ "aaF" = ( /obj/structure/machinery/door/airlock/almayer/security/glass/colony{ dir = 1; - locked = 0; name = "CORSAT Armory"; req_access_txt = "101" }, @@ -2354,7 +2353,6 @@ /obj/structure/machinery/door/airlock/almayer/maint/colony{ damage_cap = 4000; dir = 1; - locked = 0; name = "\improper Emergency Access"; req_access_txt = "100"; req_one_access = null @@ -5915,7 +5913,6 @@ "arv" = ( /obj/structure/machinery/door/airlock/almayer/maint/colony{ damage_cap = 4000; - locked = 0; name = "\improper Emergency Access"; req_access_txt = "100"; req_one_access = null @@ -21812,8 +21809,7 @@ /area/corsat/gamma/engineering) "bij" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0 + name = "Floodlight" }, /turf/open/auto_turf/snow/layer3, /area/corsat/gamma/biodome) @@ -27730,6 +27726,7 @@ /area/corsat/gamma/medbay) "bAg" = ( /obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link, /turf/open/floor/corsat{ dir = 5; icon_state = "greenwhite" @@ -28919,7 +28916,6 @@ /area/corsat/omega/checkpoint) "bDv" = ( /obj/structure/machinery/door/airlock/almayer/security/glass/colony{ - locked = 0; name = "Security Armory"; req_access_txt = "101" }, @@ -30377,8 +30373,7 @@ /area/corsat/gamma/airlock/control) "bJE" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0 + name = "Floodlight" }, /turf/open/mars, /area/corsat/sigma/biodome) @@ -34143,8 +34138,7 @@ /area/corsat/sigma/airlock/control) "bVD" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0 + name = "Floodlight" }, /turf/open/floor{ dir = 1; @@ -35393,7 +35387,6 @@ /obj/structure/machinery/door/airlock/almayer/research/glass/colony{ dir = 1; name = "Weapons Development"; - req_access = null; req_one_access_txt = "103" }, /obj/structure/pipes/standard/simple/hidden/green, @@ -35720,8 +35713,7 @@ /area/corsat/omega/control) "caS" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0 + name = "Floodlight" }, /turf/open/floor/plating, /area/corsat/sigma/biodome/testgrounds) @@ -37793,8 +37785,7 @@ /area/corsat/omega/hallways) "dFb" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0 + name = "Floodlight" }, /turf/open/auto_turf/snow/layer0, /area/corsat/gamma/biodome) @@ -48442,7 +48433,6 @@ /obj/structure/machinery/door/airlock/almayer/research/glass/colony{ dir = 1; name = "Teleportation Lab"; - req_access = null; req_one_access_txt = "103" }, /obj/structure/pipes/standard/simple/hidden/green, @@ -49076,8 +49066,7 @@ /area/corsat/omega/airlocknorth/id) "lUY" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0 + name = "Floodlight" }, /obj/structure/pipes/standard/simple/hidden/green, /turf/open/auto_turf/snow/layer3, @@ -50944,7 +50933,6 @@ /obj/structure/machinery/door/airlock/almayer/research/glass/colony{ dir = 1; name = "Teleportation Chamber"; - req_access = null; req_one_access_txt = "101;103" }, /turf/open/floor/corsat{ @@ -61779,7 +61767,6 @@ "vqF" = ( /obj/structure/machinery/door/airlock/almayer/maint/colony{ damage_cap = 4000; - locked = 0; name = "\improper Emergency Access"; req_access_txt = "100"; req_one_access = null diff --git a/maps/map_files/DesertDam/Desert_Dam.dmm b/maps/map_files/DesertDam/Desert_Dam.dmm index a86fb326152d..fff406145a3a 100644 --- a/maps/map_files/DesertDam/Desert_Dam.dmm +++ b/maps/map_files/DesertDam/Desert_Dam.dmm @@ -64959,6 +64959,14 @@ /obj/structure/machinery/camera/autoname/lz_camera, /turf/open/floor/plating, /area/desert_dam/exterior/landing_pad_one) +"uIC" = ( +/obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link/green, +/turf/open/floor/prison{ + dir = 10; + icon_state = "whitegreenfull" + }, +/area/desert_dam/building/medical/treatment_room) "uKo" = ( /obj/structure/platform/mineral/sandstone/runed{ dir = 4 @@ -102788,7 +102796,7 @@ cvU cvU cCn ctW -cEy +uIC cEB cGg cHc diff --git a/maps/map_files/FOP_v2_Cellblocks/Prison_Station_FOP.dmm b/maps/map_files/FOP_v2_Cellblocks/Prison_Station_FOP.dmm index 97f0248ff6e8..a03946d3c6cf 100644 --- a/maps/map_files/FOP_v2_Cellblocks/Prison_Station_FOP.dmm +++ b/maps/map_files/FOP_v2_Cellblocks/Prison_Station_FOP.dmm @@ -1378,8 +1378,7 @@ /obj/structure/machinery/door/airlock/almayer/security/glass/colony{ density = 0; icon_state = "door_open"; - name = "Cell Access"; - req_access = null + name = "Cell Access" }, /turf/open/floor/prison{ dir = 10; @@ -1574,8 +1573,7 @@ density = 0; icon_state = "door_open"; name = "Cell"; - opacity = 0; - req_access = null + opacity = 0 }, /obj/structure/disposalpipe/segment{ dir = 4 @@ -1621,8 +1619,7 @@ dir = 2; icon_state = "door_open"; name = "Cell"; - opacity = 0; - req_access = null + opacity = 0 }, /obj/structure/disposalpipe/segment, /turf/open/floor/prison{ @@ -3915,8 +3912,7 @@ /obj/structure/machinery/door/airlock/almayer/security/glass/colony{ density = 0; icon_state = "door_open"; - name = "Cell Access"; - req_access = null + name = "Cell Access" }, /obj/structure/pipes/standard/simple/hidden/supply{ dir = 4 @@ -8229,13 +8225,6 @@ icon_state = "bright_clean" }, /area/prison/chapel) -"awd" = ( -/obj/structure/machinery/door/airlock/almayer/security/colony{ - locked = 0; - name = "Research Containment Locker" - }, -/turf/open/floor/prison, -/area/prison/research/secret) "awe" = ( /obj/structure/window/framed/prison/reinforced/hull, /turf/open/floor/plating, @@ -28265,8 +28254,7 @@ /area/prison/hallway/east) "bDU" = ( /obj/structure/machinery/door/airlock/multi_tile/almayer/comdoor/colony{ - dir = 2; - req_access = null + dir = 2 }, /turf/open/floor/prison{ dir = 10; @@ -31414,9 +31402,7 @@ /turf/open/floor/wood, /area/prison/residential/south) "bNt" = ( -/obj/structure/machinery/door/airlock/multi_tile/almayer/generic{ - locked = 0 - }, +/obj/structure/machinery/door/airlock/multi_tile/almayer/generic, /turf/open/floor/prison{ icon_state = "damaged3" }, @@ -47865,6 +47851,14 @@ icon_state = "yellowfull" }, /area/prison/cellblock/protective) +"rmb" = ( +/obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link/green, +/turf/open/floor/prison{ + dir = 10; + icon_state = "whitegreenfull" + }, +/area/prison/medbay) "rpB" = ( /obj/structure/flora/bush/ausbushes/var3/brflowers, /obj/structure/machinery/light{ @@ -82696,7 +82690,7 @@ arx apK asp asT -att +rmb att avj avn @@ -87123,7 +87117,7 @@ aeZ aeZ aiN aiN -awd +atK aiN aiN aiN diff --git a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm index f81f67e45a80..f6e85338a637 100644 --- a/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm +++ b/maps/map_files/FOP_v3_Sciannex/Fiorina_SciAnnex.dmm @@ -22085,6 +22085,7 @@ dir = 8; health = 80 }, +/obj/structure/medical_supply_link, /turf/open/floor/prison{ dir = 10; icon_state = "sterile_white" diff --git a/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm b/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm index 7ff89252a916..1514e8023b99 100644 --- a/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm +++ b/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm @@ -11583,6 +11583,7 @@ /area/shiva/exterior/junkyard) "gHh" = ( /obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link, /turf/open/floor/shiva{ dir = 9; icon_state = "wred" diff --git a/maps/map_files/Kutjevo/Kutjevo.dmm b/maps/map_files/Kutjevo/Kutjevo.dmm index e29ebb9280b9..b1beb0dfc2b1 100644 --- a/maps/map_files/Kutjevo/Kutjevo.dmm +++ b/maps/map_files/Kutjevo/Kutjevo.dmm @@ -13120,6 +13120,7 @@ /area/kutjevo/exterior/lz_dunes) "rQa" = ( /obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link/green, /turf/open/floor/kutjevo/colors/cyan/inner_corner{ dir = 1 }, diff --git a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm index 3b8e72bf2cee..bdf58d54fb34 100644 --- a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm +++ b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm @@ -44755,6 +44755,7 @@ /obj/structure/machinery/light{ dir = 4 }, +/obj/structure/medical_supply_link/green, /turf/open/floor/strata{ dir = 4; icon_state = "white_cyan3" diff --git a/maps/map_files/LV624/LV624.dmm b/maps/map_files/LV624/LV624.dmm index 6f03ce4c2cba..46f5a179a50e 100644 --- a/maps/map_files/LV624/LV624.dmm +++ b/maps/map_files/LV624/LV624.dmm @@ -2125,8 +2125,7 @@ "akh" = ( /obj/item/trash/candy, /obj/structure/machinery/power/apc{ - dir = 1; - name = "Corporate Lobby APC" + dir = 1 }, /obj/structure/machinery/door_control{ id = "secure_outer_blast"; @@ -3238,11 +3237,8 @@ }, /area/lv624/lazarus/hydroponics) "aru" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Hydroponics APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ dir = 9; @@ -4413,11 +4409,8 @@ }, /area/lv624/lazarus/fitness) "aww" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Fitness APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ dir = 4; @@ -5132,11 +5125,8 @@ }, /area/lv624/lazarus/robotics) "azc" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Robotics Lab APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ icon_state = "vault" @@ -5625,33 +5615,27 @@ }, /area/lv624/lazarus/sleep_male) "aAR" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Research APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/machinery/light/small{ dir = 1 }, /obj/structure/surface/table, /obj/effect/landmark/item_pool_spawner/survivor_ammo/buckshot, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ dir = 5; icon_state = "whitepurple" }, /area/lv624/lazarus/research) "aAS" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Men's Dorms APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/surface/table, /obj/item/toy/deck, /obj/item/storage/fancy/cigarettes/wypacket, /obj/effect/landmark/item_pool_spawner/survivor_ammo/buckshot, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ icon_state = "bluecorner" }, @@ -6068,12 +6052,6 @@ /obj/structure/machinery/light/small{ dir = 4 }, -/obj/structure/machinery/power/apc{ - dir = 4; - name = "Women's Dorms APC"; - pixel_x = 30; - start_charge = 0 - }, /turf/open/floor{ dir = 9; icon_state = "purple" @@ -6498,11 +6476,8 @@ }, /area/lv624/lazarus/sleep_female) "aDE" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Storage Pods APC"; - pixel_x = -30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor/vault, /area/lv624/lazarus/quartstorage) @@ -6682,11 +6657,8 @@ /obj/structure/machinery/light/small{ dir = 1 }, -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Unisex Bathrooms APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor{ icon_state = "freezerfloor" @@ -6779,15 +6751,12 @@ }, /area/lv624/ground/caves/north_central_caves) "aEK" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Chapel APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/pipes/standard/simple/hidden/cyan{ dir = 4 }, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ dir = 1; icon_state = "chapel" @@ -6915,16 +6884,13 @@ }, /area/lv624/lazarus/quart) "aEZ" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Quartermaster APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/largecrate/random, /obj/structure/pipes/standard/simple/hidden/cyan{ dir = 4 }, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ dir = 4; icon_state = "whiteyellowfull" @@ -7756,15 +7722,12 @@ }, /area/lv624/lazarus/main_hall) "aIh" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Central Hallway APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/surface/table, /obj/effect/landmark/crap_item, /obj/effect/landmark/item_pool_spawner/survivor_ammo/buckshot, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ icon_state = "white" }, @@ -8313,9 +8276,8 @@ /area/lv624/lazarus/yggdrasil) "aKq" = ( /obj/structure/flora/jungle/vines/light_1, -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Atmospherics Processing APC" +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/gm/grass/grass2, /area/lv624/lazarus/yggdrasil) @@ -9003,9 +8965,8 @@ }, /area/lv624/lazarus/security) "aNR" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Security Office APC" +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ icon_state = "red" @@ -9148,11 +9109,8 @@ /turf/open/gm/dirt, /area/lv624/ground/jungle/east_central_jungle) "aOy" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Secure Vault APC"; - pixel_x = -28; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor{ icon_state = "cult" @@ -9775,11 +9733,8 @@ }, /area/lv624/lazarus/kitchen) "aQQ" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Cafeteria APC"; - pixel_x = -28; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor{ icon_state = "bar" @@ -10128,11 +10083,8 @@ }, /area/lv624/ground/caves/south_east_caves) "aSq" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Commandant's Quarters APC"; - pixel_x = -28; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor{ icon_state = "grimy" @@ -10483,7 +10435,6 @@ "aTJ" = ( /obj/structure/machinery/power/apc{ dir = 1; - name = "Telecomms APC"; start_charge = 15 }, /turf/open/floor{ @@ -10594,8 +10545,7 @@ "aUc" = ( /obj/structure/surface/rack, /obj/structure/machinery/power/apc{ - dir = 1; - name = "Kitchen APC" + dir = 1 }, /turf/open/floor{ icon_state = "freezerfloor" @@ -10748,18 +10698,6 @@ icon_state = "grimy" }, /area/lv624/lazarus/hop) -"aUF" = ( -/obj/structure/pipes/standard/simple/hidden/cyan{ - dir = 4 - }, -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Research Director's APC" - }, -/turf/open/floor{ - icon_state = "grimy" - }, -/area/lv624/lazarus/hop) "aUG" = ( /obj/structure/pipes/standard/simple/hidden/cyan{ dir = 4 @@ -10823,8 +10761,6 @@ "aUR" = ( /obj/structure/machinery/power/apc{ dir = 1; - name = "Secure Vault APC"; - pixel_y = 30; start_charge = 200 }, /turf/open/floor/greengrid, @@ -11562,10 +11498,8 @@ /area/lv624/ground/jungle/east_central_jungle) "aXs" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Geothermal APC"; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ icon_state = "delivery" @@ -14779,9 +14713,7 @@ /turf/open/gm/dirt, /area/lv624/ground/caves/south_central_caves) "fqM" = ( -/obj/structure/machinery/power/apc{ - start_charge = 0 - }, +/obj/structure/machinery/power/apc/nocharge, /turf/open/floor{ dir = 4; icon_state = "asteroidwarning" @@ -14881,6 +14813,7 @@ /area/lv624/lazarus/engineering) "fAz" = ( /obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link, /turf/open/floor{ icon_state = "whitebluefull" }, @@ -14951,9 +14884,7 @@ /turf/open/floor/plating, /area/lv624/lazarus/engineering) "fFZ" = ( -/obj/structure/machinery/power/apc{ - start_charge = 0 - }, +/obj/structure/machinery/power/apc/nocharge, /turf/open/floor{ dir = 1; icon_state = "asteroidfloor" @@ -16668,6 +16599,15 @@ }, /turf/open/gm/grass/grass1, /area/lv624/ground/jungle/north_jungle) +"jcb" = ( +/obj/structure/machinery/power/apc/nocharge{ + dir = 4 + }, +/turf/open/floor{ + dir = 9; + icon_state = "purple" + }, +/area/lv624/lazarus/sleep_female) "jcn" = ( /obj/effect/decal/grass_overlay/grass1{ dir = 8 @@ -17096,6 +17036,17 @@ /obj/effect/landmark/objective_landmark/far, /turf/open/gm/dirt, /area/lv624/ground/caves/sand_temple) +"jQX" = ( +/obj/structure/pipes/standard/simple/hidden/cyan{ + dir = 4 + }, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, +/turf/open/floor{ + icon_state = "grimy" + }, +/area/lv624/lazarus/hop) "jRm" = ( /turf/open/gm/dirt, /area/lv624/ground/colony/north_nexus_road) @@ -20098,11 +20049,8 @@ /turf/open/auto_turf/strata_grass/layer1, /area/lv624/ground/barrens/north_east_barrens) "pgf" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Medbay APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ dir = 1; @@ -51067,7 +51015,7 @@ aSA aSA aTC aQM -aUF +jQX aVq aVM aSB @@ -54914,7 +54862,7 @@ azw aBg azR aCd -aBC +jcb aDb aOo aDY diff --git a/maps/map_files/LV624/armory/10.cheese.dmm b/maps/map_files/LV624/armory/10.cheese.dmm index cee714b1c170..0864030e130b 100644 --- a/maps/map_files/LV624/armory/10.cheese.dmm +++ b/maps/map_files/LV624/armory/10.cheese.dmm @@ -151,12 +151,6 @@ }, /area/lv624/lazarus/security) "u" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Secure Vault APC"; - pixel_x = -28; - start_charge = 0 - }, /obj/structure/surface/rack, /obj/item/reagent_container/food/snacks/cheesewedge/verymature{ pixel_x = -7; @@ -169,6 +163,9 @@ /obj/item/reagent_container/food/snacks/cheesewedge/verymature{ pixel_y = 6 }, +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 + }, /turf/open/floor{ icon_state = "cult" }, diff --git a/maps/map_files/LV624/armory/10.extra.dmm b/maps/map_files/LV624/armory/10.extra.dmm index 7086e945d1ad..3e6fa0c0d68b 100644 --- a/maps/map_files/LV624/armory/10.extra.dmm +++ b/maps/map_files/LV624/armory/10.extra.dmm @@ -168,11 +168,8 @@ }, /area/lv624/lazarus/security) "u" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Secure Vault APC"; - pixel_x = -28; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor{ icon_state = "cult" diff --git a/maps/map_files/LV624/armory/10.looted.dmm b/maps/map_files/LV624/armory/10.looted.dmm index b81e0660816d..1c619fad1678 100644 --- a/maps/map_files/LV624/armory/10.looted.dmm +++ b/maps/map_files/LV624/armory/10.looted.dmm @@ -135,11 +135,8 @@ }, /area/lv624/lazarus/security) "u" = ( -/obj/structure/machinery/power/apc{ - dir = 8; - name = "Secure Vault APC"; - pixel_x = -28; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 8 }, /turf/open/floor{ icon_state = "cult" diff --git a/maps/map_files/LV624/gym/20.pool.dmm b/maps/map_files/LV624/gym/20.pool.dmm index be863f49c556..ab5a1afe46bb 100644 --- a/maps/map_files/LV624/gym/20.pool.dmm +++ b/maps/map_files/LV624/gym/20.pool.dmm @@ -221,13 +221,10 @@ }, /area/lv624/lazarus/fitness) "Be" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Fitness APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/effect/decal/remains/human, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ dir = 4; icon_state = "whitepurplecorner" diff --git a/maps/map_files/LV624/gym/30.alternate.dmm b/maps/map_files/LV624/gym/30.alternate.dmm index 79d0887c2219..466c996ef91d 100644 --- a/maps/map_files/LV624/gym/30.alternate.dmm +++ b/maps/map_files/LV624/gym/30.alternate.dmm @@ -658,11 +658,8 @@ /turf/open/floor/plating, /area/lv624/lazarus/fitness) "Wy" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Fitness APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ dir = 4; diff --git a/maps/map_files/LV624/medbay/10.destroyed.dmm b/maps/map_files/LV624/medbay/10.destroyed.dmm index 88e17a3aeee0..b33c4c28d8c2 100644 --- a/maps/map_files/LV624/medbay/10.destroyed.dmm +++ b/maps/map_files/LV624/medbay/10.destroyed.dmm @@ -48,11 +48,8 @@ }, /area/lv624/lazarus/medbay) "hW" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Medbay APC"; - pixel_y = 30; - start_charge = 0 +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 }, /turf/open/floor{ icon_state = "white" diff --git a/maps/map_files/LV624/medbay/30.larvasurgery.dmm b/maps/map_files/LV624/medbay/30.larvasurgery.dmm index b67b5e7bf1c5..4f0bf7a041ec 100644 --- a/maps/map_files/LV624/medbay/30.larvasurgery.dmm +++ b/maps/map_files/LV624/medbay/30.larvasurgery.dmm @@ -363,14 +363,11 @@ /turf/open/gm/grass/grass1, /area/lv624/ground/jungle/north_west_jungle) "qP" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Medbay APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/effect/landmark/corpsespawner/colonist/random/burst, /obj/effect/decal/cleanable/blood, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, /turf/open/floor{ dir = 1; icon_state = "whiteblue" diff --git a/maps/map_files/LV624/science/10.yautja.dmm b/maps/map_files/LV624/science/10.yautja.dmm index 04e671be3259..3d70df608c1f 100644 --- a/maps/map_files/LV624/science/10.yautja.dmm +++ b/maps/map_files/LV624/science/10.yautja.dmm @@ -266,12 +266,6 @@ }, /area/lv624/lazarus/research) "aL" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Research APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/machinery/light/small{ dir = 1 }, @@ -516,6 +510,16 @@ icon_state = "freezerfloor" }, /area/lv624/lazarus/research) +"Hj" = ( +/obj/effect/landmark/crap_item, +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, +/turf/open/floor{ + dir = 5; + icon_state = "whitepurple" + }, +/area/lv624/lazarus/research) "Lo" = ( /obj/effect/decal/cleanable/blood/splatter, /obj/effect/decal/remains/human, @@ -724,7 +728,7 @@ Zw al aE ab -ec +Hj ak al ab diff --git a/maps/map_files/LV624/science/40.fullylocked.dmm b/maps/map_files/LV624/science/40.fullylocked.dmm index 933de359a481..ae7fffe8efd9 100644 --- a/maps/map_files/LV624/science/40.fullylocked.dmm +++ b/maps/map_files/LV624/science/40.fullylocked.dmm @@ -310,12 +310,6 @@ }, /area/lv624/lazarus/research) "aS" = ( -/obj/structure/machinery/power/apc{ - dir = 1; - name = "Research APC"; - pixel_y = 30; - start_charge = 0 - }, /obj/structure/machinery/light/small{ dir = 1 }, @@ -455,6 +449,15 @@ icon_state = "whitepurple" }, /area/lv624/lazarus/research) +"Fm" = ( +/obj/structure/machinery/power/apc/nocharge{ + dir = 1 + }, +/turf/open/floor{ + dir = 5; + icon_state = "whitepurple" + }, +/area/lv624/lazarus/research) "Jv" = ( /obj/effect/landmark/corpsespawner/scientist, /obj/effect/decal/cleanable/blood/splatter, @@ -663,7 +666,7 @@ Mu ay aJ ab -ay +Fm ak ay ab diff --git a/maps/map_files/LV624/standalone/clfship.dmm b/maps/map_files/LV624/standalone/clfship.dmm index c24a511cfc29..34032943b1c1 100644 --- a/maps/map_files/LV624/standalone/clfship.dmm +++ b/maps/map_files/LV624/standalone/clfship.dmm @@ -1601,12 +1601,10 @@ }, /area/lv624/lazarus/crashed_ship) "Px" = ( +/obj/structure/machinery/autolathe, /obj/structure/machinery/power/apc{ - dir = 1; - name = "Crashed Ship APC"; - pixel_y = 25 + dir = 1 }, -/obj/structure/machinery/autolathe, /turf/open/floor/almayer{ dir = 9; icon_state = "orange" diff --git a/maps/map_files/New_Varadero/New_Varadero.dmm b/maps/map_files/New_Varadero/New_Varadero.dmm index fbcba0174790..1450edbbd180 100644 --- a/maps/map_files/New_Varadero/New_Varadero.dmm +++ b/maps/map_files/New_Varadero/New_Varadero.dmm @@ -1890,9 +1890,7 @@ /area/varadero/interior/hall_N) "bhU" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0; - wrenchable = 1 + name = "Floodlight" }, /obj/structure/platform_decoration/kutjevo{ dir = 8 @@ -10659,9 +10657,7 @@ /area/varadero/interior/security) "gRU" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0; - wrenchable = 1 + name = "Floodlight" }, /turf/open/auto_turf/sand_white/layer1, /area/varadero/interior_protected/caves/digsite) @@ -13796,9 +13792,7 @@ /area/varadero/interior/administration) "iWX" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0; - wrenchable = 1 + name = "Floodlight" }, /turf/open/auto_turf/sand_white/layer1, /area/varadero/exterior/eastbeach) @@ -19282,9 +19276,7 @@ /area/varadero/interior/cargo) "mtp" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0; - wrenchable = 1 + name = "Floodlight" }, /turf/open/floor/plating/icefloor{ icon_state = "asteroidplating" @@ -19372,9 +19364,7 @@ /area/varadero/interior/hall_SE) "mvO" = ( /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0; - wrenchable = 1 + name = "Floodlight" }, /turf/open/floor/shiva{ dir = 1; @@ -19887,9 +19877,7 @@ dir = 1 }, /obj/structure/machinery/floodlight{ - name = "Floodlight"; - unacidable = 0; - wrenchable = 1 + name = "Floodlight" }, /turf/open/floor/shiva{ dir = 1; @@ -27273,6 +27261,7 @@ /area/varadero/interior/caves/east) "rsh" = ( /obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link, /turf/open/floor/shiva{ dir = 9; icon_state = "wred" diff --git a/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm b/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm index c781fdff23cc..6b8b6b82e284 100644 --- a/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm +++ b/maps/map_files/Sorokyne_Strata/Sorokyne_Strata.dmm @@ -33534,6 +33534,7 @@ /area/strata/ag/interior/outpost/med) "jsd" = ( /obj/structure/machinery/cm_vending/sorted/medical/no_access, +/obj/structure/medical_supply_link, /turf/open/floor/strata{ icon_state = "floor2" }, diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 6bc6bfeb4a22..c87ab7b4c09a 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -1475,6 +1475,9 @@ name = "\improper Officer's Cafeteria" }, /obj/structure/machinery/door/firedoor/border_only/almayer, +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 4 + }, /turf/open/floor/almayer{ icon_state = "test_floor4" }, @@ -1494,7 +1497,7 @@ /area/almayer/living/cafeteria_officer) "ain" = ( /obj/structure/pipes/standard/simple/hidden/supply{ - dir = 5 + dir = 9 }, /turf/open/floor/almayer{ icon_state = "plate" @@ -1650,10 +1653,6 @@ icon_state = "mono" }, /area/almayer/lifeboat_pumps/north1) -"ajJ" = ( -/obj/structure/window/framed/almayer, -/turf/open/floor/plating, -/area/almayer/living/cafeteria_officer) "ajM" = ( /obj/structure/window/framed/almayer, /obj/structure/machinery/door/poddoor/almayer/open{ @@ -2670,18 +2669,6 @@ icon_state = "tcomms" }, /area/almayer/command/telecomms) -"aqe" = ( -/obj/structure/disposalpipe/segment{ - dir = 1; - icon_state = "pipe-c" - }, -/obj/structure/machinery/door/firedoor/border_only/almayer{ - dir = 1 - }, -/turf/open/floor/almayer{ - icon_state = "test_floor4" - }, -/area/almayer/engineering/upper_engineering) "aqf" = ( /obj/structure/pipes/vents/pump{ dir = 4 @@ -2690,19 +2677,15 @@ /area/almayer/engineering/upper_engineering) "aqg" = ( /obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/disposalpipe/junction, /obj/structure/machinery/door/firedoor/border_only/almayer{ dir = 1 }, +/obj/structure/disposalpipe/segment, /turf/open/floor/almayer{ icon_state = "test_floor4" }, /area/almayer/engineering/upper_engineering) "aqh" = ( -/obj/structure/pipes/standard/manifold/hidden/supply{ - dir = 4 - }, -/obj/structure/disposalpipe/segment, /obj/structure/flora/pottedplant{ icon_state = "pottedplant_21" }, @@ -2714,15 +2697,6 @@ icon_state = "orange" }, /area/almayer/engineering/upper_engineering) -"aqj" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/window/framed/almayer, -/obj/structure/machinery/door/firedoor/border_only/almayer{ - dir = 1 - }, -/turf/open/floor/plating, -/area/almayer/engineering/upper_engineering) "aqm" = ( /obj/item/bedsheet/brown, /obj/structure/bed, @@ -3018,15 +2992,8 @@ name = "General Listening Channel"; pixel_y = 28 }, -/turf/open/floor/almayer{ - dir = 1; - icon_state = "orange" - }, -/area/almayer/engineering/upper_engineering) -"arw" = ( -/obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/disposalpipe/junction{ - dir = 1 +/obj/structure/disposalpipe/segment{ + dir = 4 }, /turf/open/floor/almayer{ dir = 1; @@ -4443,27 +4410,8 @@ icon_state = "red" }, /area/almayer/lifeboat_pumps/north2) -"ayd" = ( -/obj/structure/disposalpipe/segment{ - dir = 1; - icon_state = "pipe-c" - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 5 - }, -/turf/open/floor/almayer{ - dir = 4; - icon_state = "orangecorner" - }, -/area/almayer/engineering/upper_engineering) "aye" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, /obj/structure/bed/chair, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 4 - }, /turf/open/floor/almayer{ dir = 1; icon_state = "orange" @@ -5227,12 +5175,11 @@ /turf/open/floor/plating/plating_catwalk, /area/almayer/engineering/upper_engineering) "aBl" = ( -/obj/structure/disposalpipe/segment{ - dir = 4; - icon_state = "pipe-c" +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 4 }, -/obj/structure/pipes/standard/manifold/hidden/supply{ - dir = 1 +/obj/structure/disposalpipe/segment{ + dir = 4 }, /turf/open/floor/almayer, /area/almayer/engineering/upper_engineering) @@ -5624,8 +5571,6 @@ }, /area/almayer/engineering/upper_engineering) "aDh" = ( -/obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/disposalpipe/segment, /turf/open/floor/almayer{ icon_state = "cargo" }, @@ -6073,11 +6018,9 @@ /turf/open/floor/plating/plating_catwalk, /area/almayer/command/telecomms) "aFl" = ( -/obj/structure/disposalpipe/segment, /obj/structure/machinery/door/firedoor/border_only/almayer{ dir = 2 }, -/obj/structure/pipes/standard/simple/hidden/supply, /turf/open/floor/almayer{ icon_state = "test_floor4" }, @@ -6461,19 +6404,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/command/telecomms) -"aHt" = ( -/obj/structure/disposalpipe/segment{ - dir = 8; - icon_state = "pipe-c" - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 9 - }, -/turf/open/floor/almayer{ - dir = 5; - icon_state = "orange" - }, -/area/almayer/engineering/upper_engineering) "aHu" = ( /obj/structure/pipes/standard/simple/hidden/supply, /obj/effect/decal/warning_stripes{ @@ -14160,6 +14090,15 @@ icon_state = "red" }, /area/almayer/shipboard/weapon_room) +"bFg" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "W"; + layer = 3.3 + }, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, +/area/almayer/command/airoom) "bFj" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 4 @@ -14601,15 +14540,7 @@ name = "\improper ARES Mainframe Shutters"; plane = -7 }, -/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{ - closed_layer = 3.2; - id = "ARES Emergency"; - layer = 3.2; - name = "ARES Emergency Lockdown"; - needs_power = 0; - open_layer = 1.9; - plane = -7 - }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -18391,14 +18322,6 @@ icon_state = "test_floor4" }, /area/almayer/engineering/lower/engine_core) -"cla" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/aft_hallway) "cle" = ( /turf/open/floor/almayer{ dir = 4; @@ -20167,15 +20090,15 @@ /obj/structure/disposalpipe/trunk{ dir = 1 }, -/obj/structure/disposaloutlet{ +/obj/structure/machinery/disposal/delivery{ density = 0; - desc = "An outlet for the pneumatic delivery system."; - icon_state = "delivery_outlet"; - name = "take-ins"; - pixel_x = -1; + desc = "A pneumatic delivery unit."; + icon_state = "delivery_engi"; + name = "Returns"; pixel_y = 28; - range = 0 + pixel_x = 25 }, +/obj/structure/surface/rack, /turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) "cJK" = ( @@ -21427,6 +21350,9 @@ dir = 4 }, /obj/structure/machinery/door/firedoor/border_only/almayer, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/almayer{ icon_state = "test_floor4" }, @@ -21546,6 +21472,14 @@ icon_state = "red" }, /area/almayer/shipboard/brig/chief_mp_office) +"dgI" = ( +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 4 + }, +/turf/open/floor/prison{ + icon_state = "kitchen" + }, +/area/almayer/living/cafeteria_officer) "dha" = ( /turf/open/floor/almayer{ icon_state = "plate" @@ -22464,7 +22398,9 @@ autoname = 0; c_tag = "AI - Secondary Processors" }, -/turf/open/floor/almayer/aicore/glowing/no_build, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, /area/almayer/command/airoom) "dzG" = ( /obj/structure/reagent_dispensers/peppertank{ @@ -22881,13 +22817,6 @@ icon_state = "red" }, /area/almayer/shipboard/brig/starboard_hallway) -"dFB" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/machinery/light, -/turf/open/floor/plating/plating_catwalk, -/area/almayer/hallways/upper/aft_hallway) "dFF" = ( /obj/structure/flora/pottedplant{ icon_state = "pottedplant_21" @@ -22911,6 +22840,16 @@ icon_state = "plate" }, /area/almayer/hallways/lower/vehiclehangar) +"dFN" = ( +/obj/structure/pipes/standard/manifold/hidden/supply{ + dir = 8 + }, +/obj/structure/disposalpipe/junction{ + dir = 2; + icon_state = "pipe-j2" + }, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/engineering/upper_engineering) "dFR" = ( /turf/open/floor/almayer{ dir = 9; @@ -23379,19 +23318,6 @@ }, /turf/open/floor/plating, /area/almayer/maint/lower/constr) -"dPB" = ( -/obj/structure/disposalpipe/segment{ - dir = 2; - icon_state = "pipe-c" - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 10 - }, -/turf/open/floor/almayer{ - dir = 8; - icon_state = "orange" - }, -/area/almayer/hallways/upper/midship_hallway) "dPC" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 9 @@ -23951,18 +23877,6 @@ icon_state = "test_floor4" }, /area/almayer/living/briefing) -"dZr" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 4 - }, -/turf/open/floor/almayer{ - dir = 1; - icon_state = "orange" - }, -/area/almayer/engineering/upper_engineering) "dZu" = ( /obj/structure/machinery/light{ dir = 1 @@ -24586,6 +24500,13 @@ /obj/structure/window/framed/almayer, /turf/open/floor/plating, /area/almayer/living/grunt_rnr) +"ejx" = ( +/obj/structure/pipes/standard/simple/hidden/supply, +/turf/open/floor/almayer{ + dir = 1; + icon_state = "silver" + }, +/area/almayer/hallways/upper/midship_hallway) "ejV" = ( /obj/structure/closet, /obj/item/device/flashlight/pen, @@ -24773,10 +24694,6 @@ /area/almayer/medical/medical_science) "emL" = ( /obj/structure/machinery/light, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/pipes/standard/manifold/hidden/supply, /turf/open/floor/almayer{ icon_state = "orange" }, @@ -24824,17 +24741,6 @@ icon_state = "test_floor4" }, /area/almayer/maint/hull/lower/l_m_s) -"eol" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 9 - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/midship_hallway) "eox" = ( /obj/structure/machinery/light/small, /turf/open/floor/plating/plating_catwalk, @@ -25241,6 +25147,19 @@ icon_state = "plate" }, /area/almayer/shipboard/starboard_point_defense) +"etM" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "S"; + layer = 3.3 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "NE-out"; + pixel_y = 1 + }, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, +/area/almayer/command/airoom) "etN" = ( /obj/effect/landmark/yautja_teleport, /turf/open/floor/plating/plating_catwalk, @@ -25776,6 +25695,15 @@ }, /turf/open/floor/almayer, /area/almayer/living/bridgebunks) +"eDT" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/almayer{ + dir = 1; + icon_state = "orange" + }, +/area/almayer/engineering/upper_engineering) "eEc" = ( /obj/structure/machinery/light, /obj/effect/decal/warning_stripes{ @@ -26175,17 +26103,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/maint/hull/lower/l_m_s) -"eLV" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 4 - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/aft_hallway) "eLX" = ( /obj/structure/bed/chair{ dir = 4 @@ -26358,7 +26275,7 @@ /obj/structure/machinery/door_control{ id = "ARES StairsUpper"; name = "ARES Core Access"; - pixel_x = -10; + pixel_x = -5; pixel_y = -24; req_one_access_txt = "91;92" }, @@ -26366,20 +26283,14 @@ id = "ARES StairsLock"; name = "ARES Exterior Lockdown"; pixel_y = -24; - req_one_access_txt = "91;92" + req_one_access_txt = "91;92"; + pixel_x = 6 }, /obj/structure/surface/table/reinforced/almayer_B{ indestructible = 1; unacidable = 1; unslashable = 1 }, -/obj/structure/machinery/door_control{ - id = "ARES Emergency"; - name = "ARES Emergency Lockdown"; - pixel_x = 10; - pixel_y = -24; - req_one_access_txt = "91;92" - }, /obj/structure/machinery/computer/cameras/almayer{ dir = 4; pixel_y = 12 @@ -26769,18 +26680,19 @@ /turf/open/floor/almayer, /area/almayer/living/offices) "eXy" = ( -/obj/effect/step_trigger/teleporter_vector{ +/obj/effect/projector{ name = "Almayer_AresDown"; vector_x = 96; vector_y = -65 }, -/obj/structure/machinery/light{ - dir = 1 - }, /obj/structure/stairs{ - dir = 1 + dir = 1; + icon_state = "ramptop" + }, +/turf/open/floor/almayer/aicore/glowing/no_build{ + icon_state = "ai_floor3"; + light_range = 3 }, -/turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) "eXD" = ( /obj/structure/prop/invuln/lattice_prop{ @@ -28784,7 +28696,9 @@ /obj/effect/decal/warning_stripes{ icon_state = "SW-out" }, -/turf/open/floor/almayer/aicore/glowing/no_build, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, /area/almayer/command/airoom) "fKh" = ( /obj/structure/window/framed/almayer, @@ -28951,15 +28865,6 @@ plane = -7 }, /obj/effect/step_trigger/ares_alert/core, -/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{ - closed_layer = 3.2; - id = "ARES Emergency"; - layer = 3.2; - name = "ARES Emergency Lockdown"; - needs_power = 0; - open_layer = 1.9; - plane = -7 - }, /obj/structure/sign/safety/laser{ pixel_x = 32; pixel_y = -8 @@ -28968,6 +28873,7 @@ pixel_x = 32; pixel_y = 6 }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -29053,13 +28959,6 @@ icon_state = "plating" }, /area/almayer/shipboard/sea_office) -"fOJ" = ( -/obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/disposalpipe/segment, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/engineering/upper_engineering) "fOK" = ( /obj/structure/surface/table/almayer, /obj/item/device/camera, @@ -31207,6 +31106,9 @@ req_one_access_txt = "91;92"; dir = 1 }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore{ + plane = -6 + }, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -35495,6 +35397,18 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/engineering/upper_engineering/port) +"iav" = ( +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 9 + }, +/obj/structure/disposalpipe/segment{ + dir = 8; + icon_state = "pipe-c" + }, +/turf/open/floor/almayer{ + icon_state = "orangecorner" + }, +/area/almayer/engineering/upper_engineering) "iaF" = ( /obj/structure/pipes/standard/manifold/hidden/supply{ dir = 4 @@ -35739,7 +35653,9 @@ /obj/effect/decal/warning_stripes{ icon_state = "SE-out" }, -/turf/open/floor/almayer/aicore/glowing/no_build, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, /area/almayer/command/airoom) "igs" = ( /obj/structure/surface/table/almayer, @@ -35763,13 +35679,6 @@ icon_state = "plate" }, /area/almayer/maint/hull/lower/l_m_s) -"igC" = ( -/obj/structure/disposalpipe/segment{ - dir = 2; - icon_state = "pipe-c" - }, -/turf/open/floor/almayer, -/area/almayer/hallways/upper/aft_hallway) "igS" = ( /obj/effect/decal/warning_stripes{ icon_state = "SE-out" @@ -36051,17 +35960,12 @@ name = "\improper ARES Core Shutters"; plane = -7 }, -/obj/structure/machinery/door/poddoor/almayer/blended/open{ - id = "ARES Emergency"; - name = "ARES Emergency Lockdown"; - open_layer = 1.9; - plane = -7 - }, /obj/structure/disposalpipe/up/almayer{ id = "ares_vault_in"; name = "aicore"; dir = 2 }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -36683,9 +36587,9 @@ }, /area/almayer/squads/delta) "izf" = ( -/obj/structure/disposalpipe/down/almayer{ +/obj/structure/disposalpipe/up/almayer{ dir = 4; - id = "ares_vault_in"; + id = "ares_vault_out"; name = "aicore" }, /turf/closed/wall/almayer/aicore/hull, @@ -37126,6 +37030,11 @@ icon_state = "plate" }, /area/almayer/maint/upper/u_a_s) +"iJs" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/pipes/standard/simple/hidden/supply, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/engineering/upper_engineering) "iJB" = ( /obj/structure/sign/safety/galley{ pixel_x = 8; @@ -38339,15 +38248,14 @@ pixel_x = -2; pixel_y = 26 }, -/obj/structure/machinery/door_control/brbutton{ - id = "ARES Emergency"; - name = "ARES Emergency Lockdown Override"; - pixel_x = 8; - pixel_y = 26 - }, /obj/structure/machinery/computer/cameras/almayer/ares{ dir = 4 }, +/obj/structure/machinery/aicore_lockdown{ + icon_state = "big_red_button_wallv"; + pixel_x = 8; + pixel_y = 26 + }, /turf/open/floor/wood/ship, /area/almayer/living/commandbunks) "jbX" = ( @@ -39300,15 +39208,7 @@ plane = -7 }, /obj/effect/step_trigger/ares_alert/core, -/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{ - closed_layer = 3.2; - id = "ARES Emergency"; - layer = 3.2; - name = "ARES Emergency Lockdown"; - needs_power = 0; - open_layer = 1.9; - plane = -7 - }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -39319,12 +39219,6 @@ }, /turf/open/floor/almayer, /area/almayer/shipboard/brig/execution) -"jrc" = ( -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 4 - }, -/turf/open/floor/plating/plating_catwalk, -/area/almayer/hallways/upper/midship_hallway) "jre" = ( /obj/structure/closet/secure_closet/cargotech, /obj/item/clothing/accessory/storage/webbing, @@ -40217,6 +40111,13 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/medical/morgue) +"jIs" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/pipes/standard/manifold/hidden/supply, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/hallways/upper/midship_hallway) "jIC" = ( /obj/structure/machinery/computer/working_joe{ dir = 4; @@ -42908,6 +42809,16 @@ icon_state = "dark_sterile" }, /area/almayer/medical/containment) +"kDH" = ( +/obj/structure/pipes/standard/manifold/hidden/supply{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4; + icon_state = "pipe-c" + }, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/engineering/upper_engineering) "kDK" = ( /obj/structure/pipes/vents/scrubber, /turf/open/floor/wood/ship, @@ -43432,6 +43343,14 @@ }, /turf/open/floor/wood/ship, /area/almayer/living/basketball) +"kNV" = ( +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 4 + }, +/turf/open/floor/almayer{ + icon_state = "mono" + }, +/area/almayer/hallways/upper/starboard) "kNX" = ( /obj/structure/bed/chair/comfy/charlie{ dir = 1 @@ -44015,12 +43934,6 @@ icon_state = "sterile_green_side" }, /area/almayer/medical/medical_science) -"kXD" = ( -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 6 - }, -/turf/open/floor/almayer, -/area/almayer/hallways/upper/midship_hallway) "kXN" = ( /obj/item/clothing/glasses/sunglasses/aviator{ pixel_x = -1; @@ -44200,6 +44113,8 @@ /obj/structure/machinery/door/airlock/multi_tile/almayer/engidoor/glass{ name = "\improper Engineering Reception" }, +/obj/structure/disposalpipe/segment, +/obj/structure/pipes/standard/simple/hidden/supply, /turf/open/floor/almayer{ icon_state = "test_floor4" }, @@ -45761,10 +45676,6 @@ }, /turf/open/floor/plating, /area/almayer/maint/lower/constr) -"lDH" = ( -/obj/structure/pipes/standard/simple/hidden/supply, -/turf/open/floor/almayer, -/area/almayer/hallways/upper/midship_hallway) "lDL" = ( /obj/structure/machinery/light{ dir = 4 @@ -46207,6 +46118,15 @@ icon_state = "orangecorner" }, /area/almayer/hallways/upper/midship_hallway) +"lLA" = ( +/obj/structure/machinery/door/firedoor/border_only/almayer{ + dir = 2 + }, +/obj/structure/pipes/standard/simple/hidden/supply, +/turf/open/floor/almayer{ + icon_state = "test_floor4" + }, +/area/almayer/hallways/upper/midship_hallway) "lLC" = ( /obj/structure/surface/table/almayer, /turf/open/floor/almayer, @@ -47705,6 +47625,15 @@ icon_state = "test_floor4" }, /area/almayer/hallways/lower/starboard_umbilical) +"mpZ" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 4 + }, +/turf/open/floor/almayer, +/area/almayer/engineering/upper_engineering) "mqb" = ( /obj/structure/pipes/standard/manifold/hidden/supply{ dir = 8 @@ -47798,19 +47727,6 @@ icon_state = "green" }, /area/almayer/squads/req) -"mrO" = ( -/obj/structure/disposalpipe/segment{ - dir = 1; - icon_state = "pipe-c" - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 5 - }, -/turf/open/floor/almayer{ - dir = 10; - icon_state = "orange" - }, -/area/almayer/hallways/upper/midship_hallway) "msg" = ( /obj/structure/machinery/light, /obj/structure/sign/safety/waterhazard{ @@ -47960,8 +47876,6 @@ /turf/open/floor/almayer, /area/almayer/lifeboat_pumps/north1) "mux" = ( -/obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/disposalpipe/segment, /obj/structure/machinery/camera/autoname/almayer{ dir = 8; name = "ship-grade camera" @@ -48270,6 +48184,10 @@ /area/almayer/living/port_emb) "mAe" = ( /obj/structure/window/framed/almayer/aicore/hull/black/hijack_bustable, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown{ + plane = -6; + dir = 4 + }, /turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) "mAp" = ( @@ -48607,15 +48525,7 @@ name = "\improper ARES Mainframe Shutters"; plane = -7 }, -/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{ - closed_layer = 3.2; - id = "ARES Emergency"; - layer = 3.2; - name = "ARES Emergency Lockdown"; - needs_power = 0; - open_layer = 1.9; - plane = -7 - }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -48663,12 +48573,6 @@ icon_state = "silver" }, /area/almayer/command/securestorage) -"mGL" = ( -/turf/open/floor/almayer{ - dir = 4; - icon_state = "orange" - }, -/area/almayer/hallways/upper/midship_hallway) "mGT" = ( /obj/structure/machinery/status_display{ pixel_y = 30 @@ -49291,15 +49195,6 @@ plane = -7 }, /obj/effect/step_trigger/ares_alert/core, -/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{ - closed_layer = 3.2; - id = "ARES Emergency"; - layer = 3.2; - name = "ARES Emergency Lockdown"; - needs_power = 0; - open_layer = 1.9; - plane = -7 - }, /obj/structure/sign/safety/terminal{ pixel_x = -18; pixel_y = -8 @@ -49308,6 +49203,7 @@ pixel_x = -18; pixel_y = 6 }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -50866,9 +50762,9 @@ /turf/open/floor/plating, /area/almayer/engineering/starboard_atmos) "npq" = ( -/obj/structure/disposalpipe/up/almayer{ +/obj/structure/disposalpipe/down/almayer{ dir = 8; - id = "ares_vault_out"; + id = "ares_vault_in"; name = "aicore" }, /turf/closed/wall/almayer/aicore/hull, @@ -51959,16 +51855,18 @@ }, /area/almayer/command/lifeboat) "nKO" = ( -/obj/structure/machinery/disposal/delivery{ - density = 0; - desc = "A pneumatic delivery unit."; - icon_state = "delivery_engi"; - name = "Returns"; - pixel_y = 28 - }, /obj/structure/disposalpipe/trunk{ dir = 1 }, +/obj/structure/disposaloutlet{ + density = 0; + desc = "An outlet for the pneumatic delivery system."; + icon_state = "delivery_outlet"; + name = "take-ins"; + pixel_x = 7; + pixel_y = 28; + range = 0 + }, /turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) "nKP" = ( @@ -52089,6 +51987,19 @@ icon_state = "red" }, /area/almayer/hallways/upper/port) +"nNA" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "N"; + pixel_y = 1 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "S"; + layer = 3.3 + }, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, +/area/almayer/command/airoom) "nNH" = ( /turf/open/floor/almayer{ dir = 1; @@ -52718,6 +52629,19 @@ }, /turf/open/floor/wood/ship, /area/almayer/shipboard/brig/cells) +"nYg" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "S"; + layer = 3.3 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "NW-out"; + pixel_y = 1 + }, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, +/area/almayer/command/airoom) "nYi" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/almayer{ @@ -54204,12 +54128,6 @@ }, /turf/open/floor/almayer, /area/almayer/hallways/lower/starboard_aft_hallway) -"oxi" = ( -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 10 - }, -/turf/open/floor/almayer, -/area/almayer/living/cafeteria_officer) "oxl" = ( /obj/structure/window/reinforced{ dir = 8; @@ -55281,6 +55199,17 @@ icon_state = "plate" }, /area/almayer/command/lifeboat) +"oOW" = ( +/obj/structure/pipes/standard/simple/hidden/supply, +/obj/structure/disposalpipe/junction{ + dir = 2; + icon_state = "pipe-j2" + }, +/turf/open/floor/almayer{ + dir = 1; + icon_state = "orange" + }, +/area/almayer/engineering/upper_engineering) "oOZ" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 4 @@ -55818,17 +55747,6 @@ icon_state = "orange" }, /area/almayer/engineering/lower) -"oXP" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 4 - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/midship_hallway) "oXY" = ( /obj/structure/machinery/camera/autoname/almayer{ dir = 8; @@ -55897,6 +55815,20 @@ icon_state = "silver" }, /area/almayer/hallways/lower/repair_bay) +"oYZ" = ( +/obj/effect/step_trigger/teleporter_vector{ + name = "Almayer_AresDown"; + vector_x = 96; + vector_y = -65 + }, +/obj/structure/stairs{ + dir = 1 + }, +/turf/open/floor/almayer/aicore/glowing/no_build{ + icon_state = "ai_floor3"; + light_range = 3 + }, +/area/almayer/command/airoom) "oZp" = ( /obj/structure/surface/table/almayer, /obj/structure/machinery/light, @@ -57370,6 +57302,12 @@ "pzW" = ( /turf/closed/wall/almayer/reinforced, /area/almayer/hallways/lower/vehiclehangar) +"pzX" = ( +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 9 + }, +/turf/open/floor/almayer, +/area/almayer/engineering/upper_engineering) "pAm" = ( /turf/open/floor/almayer, /area/almayer/engineering/lower/engine_core) @@ -59755,6 +59693,13 @@ icon_state = "plating_striped" }, /area/almayer/squads/req) +"qsG" = ( +/obj/structure/pipes/standard/manifold/hidden/supply, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/almayer, +/area/almayer/hallways/upper/aft_hallway) "qsL" = ( /obj/structure/pipes/standard/simple/hidden/supply, /turf/open/floor/almayer, @@ -60632,11 +60577,14 @@ }, /area/almayer/powered) "qHD" = ( -/obj/structure/disposalpipe/segment, /obj/structure/pipes/standard/simple/hidden/supply{ dir = 4 }, -/turf/open/floor/almayer, +/obj/structure/disposalpipe/segment{ + dir = 8; + icon_state = "pipe-c" + }, +/turf/open/floor/plating/plating_catwalk, /area/almayer/hallways/upper/aft_hallway) "qHG" = ( /obj/structure/machinery/light/small{ @@ -60984,6 +60932,16 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/shipboard/brig/armory) +"qMI" = ( +/obj/structure/pipes/standard/manifold/hidden/supply{ + dir = 1 + }, +/obj/structure/disposalpipe/junction{ + dir = 2; + icon_state = "pipe-y" + }, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/hallways/upper/aft_hallway) "qMP" = ( /obj/structure/bed/chair/comfy{ dir = 8 @@ -61258,15 +61216,6 @@ }, /turf/open/floor/almayer, /area/almayer/shipboard/port_point_defense) -"qSp" = ( -/obj/structure/disposalpipe/segment{ - dir = 8; - icon_state = "pipe-c" - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/aft_hallway) "qSE" = ( /obj/structure/surface/table/almayer, /obj/item/reagent_container/food/condiment/hotsauce/cholula, @@ -61525,18 +61474,6 @@ dir = 4 }, /area/almayer/medical/containment/cell/cl) -"qXh" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 4 - }, -/turf/open/floor/almayer{ - dir = 6; - icon_state = "orange" - }, -/area/almayer/hallways/upper/midship_hallway) "qXk" = ( /turf/open/floor/almayer{ icon_state = "plate" @@ -64093,6 +64030,15 @@ icon_state = "silver" }, /area/almayer/hallways/lower/repair_bay) +"rOz" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "S"; + layer = 3.3 + }, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, +/area/almayer/command/airoom) "rOC" = ( /obj/structure/machinery/light{ dir = 1 @@ -65707,8 +65653,6 @@ }, /area/almayer/shipboard/brig/perma) "sqo" = ( -/obj/structure/pipes/standard/simple/hidden/supply, -/obj/structure/disposalpipe/segment, /obj/structure/bed/chair{ dir = 8 }, @@ -66197,6 +66141,13 @@ icon_state = "blue" }, /area/almayer/squads/delta) +"sAw" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/pipes/standard/manifold/hidden/supply{ + dir = 8 + }, +/turf/open/floor/almayer, +/area/almayer/engineering/upper_engineering) "sAz" = ( /obj/effect/decal/warning_stripes{ icon_state = "W" @@ -66705,12 +66656,6 @@ icon_state = "cargo" }, /area/almayer/engineering/lower/workshop/hangar) -"sJN" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plating/plating_catwalk, -/area/almayer/hallways/upper/aft_hallway) "sJY" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 4 @@ -67030,23 +66975,6 @@ icon_state = "plate" }, /area/almayer/command/lifeboat) -"sRC" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/machinery/door/firedoor/border_only/almayer, -/turf/open/floor/almayer{ - icon_state = "test_floor4" - }, -/area/almayer/hallways/upper/aft_hallway) -"sRM" = ( -/obj/structure/machinery/power/apc/almayer{ - dir = 1 - }, -/turf/open/floor/almayer{ - icon_state = "plate" - }, -/area/almayer/maint/hull/lower/l_a_s) "sRZ" = ( /obj/effect/projector{ name = "Almayer_Down2"; @@ -69482,12 +69410,7 @@ name = "\improper ARES Core Shutters"; plane = -7 }, -/obj/structure/machinery/door/poddoor/almayer/blended/open{ - id = "ARES Emergency"; - name = "ARES Emergency Lockdown"; - open_layer = 1.9; - plane = -7 - }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -70375,6 +70298,14 @@ icon_state = "test_floor4" }, /area/almayer/squads/req) +"tXn" = ( +/obj/structure/machinery/power/apc/almayer{ + dir = 8 + }, +/turf/open/floor/almayer{ + icon_state = "plate" + }, +/area/almayer/maint/hull/lower/l_a_s) "tXo" = ( /turf/open/floor/almayer{ icon_state = "redcorner" @@ -70798,6 +70729,10 @@ icon_state = "sterile_green_side" }, /area/almayer/medical/lockerroom) +"uez" = ( +/obj/structure/pipes/standard/manifold/hidden/supply, +/turf/open/floor/almayer, +/area/almayer/hallways/upper/aft_hallway) "ueG" = ( /obj/item/bedsheet/orange, /obj/structure/bed{ @@ -71028,6 +70963,14 @@ icon_state = "test_floor4" }, /area/almayer/command/cichallway) +"ujn" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "E" + }, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, +/area/almayer/command/airoom) "ujz" = ( /obj/structure/disposalpipe/segment, /obj/structure/pipes/standard/simple/hidden/supply, @@ -72977,9 +72920,16 @@ unslashable = 1 }, /obj/item/paper_bin/uscm{ - pixel_y = 6 + pixel_y = 6; + pixel_x = -12 + }, +/obj/item/tool/pen{ + pixel_x = -14 + }, +/obj/structure/machinery/aicore_lockdown{ + pixel_y = 4; + pixel_x = 3 }, -/obj/item/tool/pen, /turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) "uVc" = ( @@ -74165,6 +74115,12 @@ icon_state = "plate" }, /area/almayer/living/gym) +"vnM" = ( +/obj/structure/pipes/standard/simple/hidden/supply{ + dir = 6 + }, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/hallways/upper/starboard) "vnY" = ( /turf/open/floor/almayer, /area/almayer/hallways/lower/repair_bay) @@ -74300,15 +74256,15 @@ unacidable = 1; unslashable = 1 }, -/obj/item/desk_bell{ - pixel_y = 14; - pixel_x = -5; - anchored = 1 - }, /obj/structure/machinery/computer/working_joe{ layer = 3.3; dir = 8 }, +/obj/item/desk_bell/ares{ + pixel_y = 14; + pixel_x = -5; + anchored = 1 + }, /turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) "vpI" = ( @@ -75229,7 +75185,9 @@ c_tag = "AI - Primary Processors"; autoname = 0 }, -/turf/open/floor/almayer/aicore/glowing/no_build, +/turf/open/floor/almayer/aicore/no_build{ + icon_state = "ai_floor2" + }, /area/almayer/command/airoom) "vCO" = ( /obj/effect/landmark/start/bridge, @@ -75403,16 +75361,6 @@ icon_state = "plate" }, /area/almayer/maint/hull/lower/l_f_p) -"vGi" = ( -/obj/structure/pipes/standard/manifold/hidden/supply{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ - dir = 4; - icon_state = "pipe-c" - }, -/turf/open/floor/almayer, -/area/almayer/hallways/upper/aft_hallway) "vGn" = ( /turf/open/floor/almayer{ dir = 1; @@ -77002,14 +76950,6 @@ /obj/effect/landmark/late_join/charlie, /turf/open/floor/plating/plating_catwalk, /area/almayer/squads/charlie) -"wdE" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/midship_hallway) "wdF" = ( /turf/open/floor/almayer{ allow_construction = 0 @@ -77454,15 +77394,7 @@ alert_message = "Caution: Movement detected in ARES Core."; cooldown_duration = 1200 }, -/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{ - closed_layer = 3.2; - id = "ARES Emergency"; - layer = 3.2; - name = "ARES Emergency Lockdown"; - needs_power = 0; - open_layer = 1.9; - plane = -7 - }, +/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore, /turf/open/floor/almayer/no_build{ icon_state = "test_floor4" }, @@ -78331,12 +78263,7 @@ /area/almayer/maint/hull/lower/l_m_s) "wyQ" = ( /obj/structure/surface/table/reinforced/almayer_B, -/obj/structure/machinery/door_control{ - id = "ARES Emergency"; - indestructible = 1; - name = "ARES Emergency Lockdown"; - req_one_access_txt = "91;92" - }, +/obj/structure/machinery/aicore_lockdown, /turf/open/floor/almayer/no_build{ icon_state = "plating" }, @@ -80106,8 +80033,10 @@ }, /area/almayer/engineering/laundry) "xfm" = ( -/obj/structure/pipes/standard/simple/hidden/supply, /obj/structure/window/framed/almayer, +/obj/structure/machinery/door/firedoor/border_only/almayer{ + dir = 2 + }, /turf/open/floor/plating, /area/almayer/living/cafeteria_officer) "xfq" = ( @@ -82713,7 +82642,7 @@ /obj/structure/pipes/standard/simple/hidden/supply/no_boom{ dir = 4 }, -/turf/open/floor/plating/plating_catwalk, +/turf/open/floor/almayer, /area/almayer/engineering/upper_engineering) "xZk" = ( /obj/item/prop/helmetgarb/gunoil{ @@ -82959,18 +82888,6 @@ icon_state = "plate" }, /area/almayer/living/briefing) -"ycA" = ( -/obj/structure/disposalpipe/junction{ - dir = 8; - icon_state = "pipe-j2" - }, -/obj/structure/pipes/standard/simple/hidden/supply{ - dir = 10 - }, -/turf/open/floor/almayer{ - icon_state = "orangecorner" - }, -/area/almayer/hallways/upper/aft_hallway) "ycH" = ( /obj/structure/surface/table/almayer, /obj/item/pizzabox/margherita{ @@ -120242,10 +120159,10 @@ sVV sVV sVV sVV -sVV -wNC -sfz -lGh +vnM +lLA +ejx +jIs xLw vOy woh @@ -120445,7 +120362,7 @@ xMz lIY gxn aMy -aMy +kNV wNC wlr xyp @@ -120851,7 +120768,7 @@ lzt ael afE agT -agT +dgI ael ogT yiu @@ -121257,10 +121174,10 @@ qTi ael afI agY -oxi +aiq xfm -lDH -vIZ +xIj +qdJ iCg mOi mOi @@ -121461,7 +121378,7 @@ ael afJ agY aiq -ajJ +xfm xIj qdJ xIj @@ -121669,10 +121586,10 @@ sgH qdJ xIj mOi -eXy vRA +oYZ ezq -ezq +eXy tFe xQV pax @@ -124305,8 +124222,8 @@ fjo opu hlj iso -dPB -mrO +ceV +nsH alL alL alL @@ -124508,7 +124425,7 @@ asA msS nZf rho -lDH +jIs emL jvY jvY @@ -124711,8 +124628,8 @@ nBK wYa hlj giW -mGL -qXh +puP +tfF jvY arg atf @@ -124914,8 +124831,8 @@ aeC beN mdm lLt -xIj -oXP +qdJ +vCv jvY arh atm @@ -125117,8 +125034,8 @@ ggQ aME aep lLt -kXD -eol +lGh +vCv jvY ari aoP @@ -125320,8 +125237,8 @@ afk agM aep lLt -jrc -wdE +yiu +vCv jvY arj atm @@ -125523,8 +125440,8 @@ afk afk aep lLt -jrc -wdE +poD +vCv jvY ark atm @@ -125727,7 +125644,7 @@ aep aep umI ddO -sRC +umI jvY alL atk @@ -125929,8 +125846,8 @@ aep aep aep sHI -cNC -cla +jao +qhT jvY arl atm @@ -126132,8 +126049,8 @@ cMx cMx cMx sHI -cNC -cla +jao +qhT jvY abF atm @@ -126335,8 +126252,8 @@ oVo oVo cMx nSw -pqY -cla +qsG +qhT jvY jvY jvY @@ -126538,8 +126455,8 @@ fIK fIK wuS tzF -pqY -cla +qsG +qhT alL urM dBG @@ -126741,9 +126658,9 @@ oVo oVo cMx nWf -cNC -igC -aqe +lOn +acQ +kwd amw anO arq @@ -126944,20 +126861,20 @@ oVo rYU cMx nXV -wHr -vGi +qMI +rUN aqg -arr -atn +oOW atn atn atn +sAw anP aBh anP -atn -atn -atn +anP +iJs +dFN atn aOB aRj @@ -127147,21 +127064,21 @@ iVz rAS cMx sHI -tof -jao +lOn +acQ kwd -amA -atq -atq +eDT amx amx amx -atq +awy amx amx amx -atq -atq +amx +amx +mpZ +amx aoT kwd acQ @@ -127350,20 +127267,20 @@ cMx cMx cMx sHI -tof -eLV +jao +qhT alO ars amx amx aqf +pzX amx amx -atq -amx amx amx amx +mpZ amx aOC alO @@ -127553,20 +127470,20 @@ oaP jhQ cMx kYb -tof -eLV +jao +qhT inw -amA +eDT amx amx -awy amx amx amx amx amx amx -atq +amx +aBo amx aoT inw @@ -127756,21 +127673,21 @@ oVo oVo cMx sHI -tof -ycA -aqj -arw -anP -fOJ +jao +qhT +inw +eDT +amx +auB aqh sqo sqo aDh aDh mux -ayd -atq -atq +aya +aBo +amx wwJ inw sHI @@ -127959,8 +127876,8 @@ oVo oVo cMx nWf -tof -cla +jao +qhT inw qHM emn @@ -127972,7 +127889,7 @@ aBi aDi alO aye -amx +aBo amx aBs inw @@ -128162,8 +128079,8 @@ qbw qbw vTE kGS -tof -dFB +lOn +wCe alO alO alO @@ -128175,8 +128092,8 @@ anO aDj inw aye -atq -atq +mpZ +amx aBs alO sHI @@ -128365,21 +128282,21 @@ oVo oVo btb sHI -tof -sJN +lOn +qhT alO gKZ vTv auL alO axy -amA -atq +azh +aBk aoT inw aye -atq -atq +mpZ +amx aBs alO uSk @@ -128568,20 +128485,20 @@ pVh mSl btb sHI -tof -sJN +jao +qhT alO arz atq aoT alO aOG -azh -aBk -aoT +amA +kDH +aOB laQ -dZr -auB +arr +iav atc aOF alO @@ -128771,8 +128688,8 @@ cMx cMx cMx sHI -tof -sJN +jao +qhT alO arz atq @@ -128781,9 +128698,9 @@ alO axA amA aBl -aOB +aoT aFl -aHt +arm aIU aMq aOG @@ -128974,8 +128891,8 @@ yfn nkc cMx sHI -tof -sJN +jao +qhT alO arz atq @@ -129177,8 +129094,8 @@ oVo iIU cMx uSk -tof -sJN +jao +kGS xHt arm ats @@ -129381,7 +129298,7 @@ whO bYL dlT qHD -qSp +qhT alO arA att @@ -129583,7 +129500,7 @@ cMx cMx cMx nWf -tof +cNC qhT wDM wDM @@ -129989,7 +129906,7 @@ jhx dnH gpc tzF -pqY +uez qhT wDM uto @@ -130192,7 +130109,7 @@ owg owg ptK sHI -cNC +tof qhT wDM aOQ @@ -130598,7 +130515,7 @@ wiG nWN eNi sHI -cNC +tof qhT wDM wDM @@ -131701,7 +131618,7 @@ emA emA emA ikT -oBr +jEM aQL qDq qDq @@ -132724,8 +132641,8 @@ jEM gCu jEM jEM -oBr -sRM +tXn +jEM jEM jEM oBr @@ -140207,7 +140124,7 @@ qQS bIp fKe dDp -dDp +bFg frM lcg daz @@ -140409,9 +140326,9 @@ dIn rby bIp euN +ujn sEK -sEK -mlb +etM lcg daz lmz @@ -140611,10 +140528,10 @@ lnS uVv flf ebN -cxc +rOz kBy kBy -gfu +nNA fPB daz lmz @@ -142033,9 +141950,9 @@ yaQ vLz mFN kSy +bFg dDp -dDp -frM +nYg lcg daz lmz @@ -142237,7 +142154,7 @@ qQS mFN igr sEK -sEK +ujn mlb lcg daz diff --git a/maps/map_files/Whiskey_Outpost_v2/Whiskey_Outpost_v2.dmm b/maps/map_files/Whiskey_Outpost_v2/Whiskey_Outpost_v2.dmm index 5a4ce7045021..46200d9f79e4 100644 --- a/maps/map_files/Whiskey_Outpost_v2/Whiskey_Outpost_v2.dmm +++ b/maps/map_files/Whiskey_Outpost_v2/Whiskey_Outpost_v2.dmm @@ -2413,6 +2413,7 @@ /area/whiskey_outpost/inside/bunker/bunker/front) "iJ" = ( /obj/structure/machinery/cm_vending/sorted/medical, +/obj/structure/medical_supply_link/green, /turf/open/floor{ dir = 10; icon_state = "whitegreen" @@ -2446,6 +2447,7 @@ /area/whiskey_outpost/outside/mortar_pit) "iN" = ( /obj/structure/machinery/cm_vending/sorted/medical, +/obj/structure/medical_supply_link/green, /turf/open/floor{ icon_state = "whitegreen" }, @@ -3686,16 +3688,6 @@ icon_state = "whitegreencorner" }, /area/whiskey_outpost/inside/hospital/triage) -"ne" = ( -/obj/effect/decal/medical_decals{ - icon_state = "docstripingdir" - }, -/obj/structure/machinery/cm_vending/gear/medic, -/turf/open/floor{ - dir = 1; - icon_state = "asteroidfloor" - }, -/area/whiskey_outpost) "nf" = ( /obj/structure/disposalpipe/segment, /obj/effect/decal/medical_decals{ @@ -3713,12 +3705,10 @@ /area/whiskey_outpost/outside/south/very_far) "ni" = ( /obj/structure/machinery/cm_vending/sorted/medical/marinemed, -/obj/effect/decal/medical_decals{ - icon_state = "docstripingdir" - }, /obj/structure/machinery/light{ dir = 1 }, +/obj/structure/medical_supply_link, /turf/open/floor{ dir = 1; icon_state = "asteroidfloor" @@ -3911,9 +3901,7 @@ /area/whiskey_outpost) "nR" = ( /obj/structure/machinery/cm_vending/sorted/medical/marinemed, -/obj/effect/decal/medical_decals{ - icon_state = "docstripingdir" - }, +/obj/structure/medical_supply_link, /turf/open/floor{ dir = 1; icon_state = "asteroidfloor" @@ -13296,6 +13284,7 @@ /area/whiskey_outpost/outside/south) "Zm" = ( /obj/structure/machinery/cm_vending/sorted/medical/chemistry, +/obj/structure/medical_supply_link, /turf/open/floor{ icon_state = "white" }, @@ -23638,7 +23627,7 @@ lG iV qz qz -ne +kh kj oW OX diff --git a/maps/predship/huntership.dmm b/maps/predship/huntership.dmm index 7c5d633286f0..113f6448d3a8 100644 --- a/maps/predship/huntership.dmm +++ b/maps/predship/huntership.dmm @@ -525,6 +525,11 @@ /obj/item/stack/sheet/mineral/sandstone/large_stack, /obj/item/stack/sheet/mineral/sandstone/large_stack, /obj/item/stack/sheet/mineral/sandstone/large_stack, +/obj/item/stack/sheet/mineral/sandstone/large_stack, +/obj/item/stack/sheet/mineral/sandstone/large_stack, +/obj/item/stack/sheet/mineral/sandstone/large_stack, +/obj/item/stack/sheet/mineral/sandstone/large_stack, +/obj/item/stack/sheet/mineral/sandstone/large_stack, /turf/open/floor/corsat{ dir = 1; icon_state = "squareswood" @@ -844,6 +849,13 @@ icon_state = "squareswood" }, /area/yautja) +"bZ" = ( +/obj/item/storage/fancy/candle_box, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) "ca" = ( /obj/structure/barricade/handrail/strata{ dir = 1 @@ -1029,6 +1041,18 @@ /obj/structure/closet/secure_closet/freezer/fridge{ locked = 0 }, +/obj/item/reagent_container/food/snacks/xemeatpie{ + name = "Elite Hunter's Xenopie" + }, +/obj/item/reagent_container/food/snacks/xemeatpie{ + name = "Elite Hunter's Xenopie" + }, +/obj/item/reagent_container/food/snacks/xemeatpie{ + name = "Elite Hunter's Xenopie" + }, +/obj/item/reagent_container/food/snacks/xemeatpie{ + name = "Elite Hunter's Xenopie" + }, /turf/open/floor{ dir = 10; icon_state = "darkred2" @@ -1343,6 +1367,29 @@ /obj/item/stack/sheet/mineral/sandstone/runed/large_stack, /obj/item/stack/sheet/mineral/sandstone/runed/large_stack, /obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, +/obj/item/stack/sheet/mineral/sandstone/runed/large_stack, /turf/open/floor/corsat{ dir = 1; icon_state = "squareswood" @@ -1547,6 +1594,12 @@ /obj/structure/closet/secure_closet/freezer/fridge{ locked = 0 }, +/obj/item/reagent_container/food/snacks/xemeatpie{ + name = "Elite Hunter's Xenopie" + }, +/obj/item/reagent_container/food/snacks/xemeatpie{ + name = "Elite Hunter's Xenopie" + }, /turf/open/floor{ dir = 1; icon_state = "darkred2" @@ -1734,6 +1787,30 @@ }, /turf/open/shuttle/predship, /area/yautja) +"fI" = ( +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 + }, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/obj/item/device/flashlight/lamp, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) "fS" = ( /obj/structure/barricade/handrail/strata, /turf/open/gm/dirtgrassborder/weedable{ @@ -1807,8 +1884,32 @@ name = "Armory Shutters"; needs_power = 0; pixel_x = 24; - req_one_access_txt = "392"; - needs_power = 0 + req_one_access_txt = "392" + }, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) +"gN" = ( +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 + }, +/obj/item/stack/tile/carpet{ + amount = 50 + }, +/obj/item/stack/tile/carpet{ + amount = 50 + }, +/obj/item/stack/tile/carpet{ + amount = 50 + }, +/obj/item/stack/tile/carpet{ + amount = 50 + }, +/obj/item/stack/tile/carpet{ + amount = 50 }, /turf/open/floor/corsat{ dir = 1; @@ -1859,6 +1960,11 @@ /obj/structure/kitchenspike, /obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, /obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, +/obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, +/obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, +/obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, +/obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, +/obj/item/reagent_container/food/snacks/sliceable/xenomeatbread, /turf/open/floor{ dir = 8; icon_state = "darkred2" @@ -1950,6 +2056,60 @@ icon_state = "desert1" }, /area/yautja) +"mn" = ( +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/obj/item/device/flashlight/lantern{ + pixel_x = 1; + pixel_y = 9 + }, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) "mv" = ( /obj/structure/surface/table/reinforced/prison{ color = "#6b675e" @@ -2151,6 +2311,37 @@ icon_state = "multi_tiles" }, /area/yautja) +"sS" = ( +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/obj/item/stack/sheet/wood{ + amount = 50 + }, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) "sV" = ( /obj/structure/machinery/door/airlock/yautja{ dir = 1; @@ -2210,18 +2401,22 @@ }, /area/yautja) "tR" = ( -/obj/structure/surface/table/reinforced/prison{ - color = "#6b675e" - }, -/obj/structure/window/reinforced{ - dir = 8; - health = 80 - }, -/obj/structure/window/reinforced{ - dir = 4; - health = 80 +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 }, -/obj/item/storage/box/bracer, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, +/obj/item/frame/table/wood/poor, /turf/open/floor/corsat{ dir = 1; icon_state = "squareswood" @@ -2233,6 +2428,54 @@ }, /turf/open/gm/dirtgrassborder/west, /area/yautja) +"uj" = ( +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 + }, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/obj/item/frame/table/gambling, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) +"um" = ( +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 + }, +/obj/item/storage/fancy/candle_box, +/obj/item/storage/fancy/candle_box, +/obj/item/storage/fancy/candle_box, +/obj/item/storage/fancy/candle_box, +/obj/item/storage/fancy/candle_box, +/obj/item/storage/fancy/candle_box, +/obj/item/storage/fancy/candle_box, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) "uO" = ( /obj/structure/bed/chair/hunter{ dir = 4 @@ -2358,6 +2601,24 @@ icon_state = "squareswood" }, /area/yautja) +"yr" = ( +/obj/structure/window/reinforced{ + dir = 8; + health = 80 + }, +/obj/structure/window/reinforced{ + dir = 4; + health = 80 + }, +/obj/structure/surface/table/reinforced/prison{ + color = "#6b675e" + }, +/obj/item/storage/box/bracer, +/turf/open/floor/corsat{ + dir = 1; + icon_state = "squareswood" + }, +/area/yautja) "yH" = ( /obj/structure/closet/secure_closet/freezer/fridge/groceries, /turf/open/floor{ @@ -2394,18 +2655,28 @@ }, /area/yautja) "zZ" = ( -/obj/structure/surface/table/reinforced/prison{ - color = "#6b675e" - }, -/obj/structure/window/reinforced{ - dir = 8; - health = 80 - }, -/obj/structure/window/reinforced{ - dir = 1; - health = 80; - pixel_y = 16 +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 }, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, +/obj/item/frame/table/wood/fancy, /turf/open/floor/corsat{ dir = 1; icon_state = "squareswood" @@ -2845,6 +3116,21 @@ /obj/item/stack/sheet/metal{ amount = 50 }, +/obj/item/stack/sheet/metal{ + amount = 50 + }, +/obj/item/stack/sheet/metal{ + amount = 50 + }, +/obj/item/stack/sheet/metal{ + amount = 50 + }, +/obj/item/stack/sheet/metal{ + amount = 50 + }, +/obj/item/stack/sheet/metal{ + amount = 50 + }, /turf/open/floor/corsat{ dir = 1; icon_state = "squareswood" @@ -3109,17 +3395,32 @@ /turf/open/shuttle/predship, /area/yautja) "Ut" = ( -/obj/structure/surface/table/reinforced/prison{ - color = "#6b675e" - }, -/obj/structure/window/reinforced{ - dir = 8; - health = 80 - }, -/obj/structure/window/reinforced{ - dir = 4; - health = 80 +/obj/structure/surface/rack{ + color = "#6b675e"; + layer = 2.79 }, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, +/obj/item/frame/table/wood, /turf/open/floor/corsat{ dir = 1; icon_state = "squareswood" @@ -5403,7 +5704,7 @@ JH JH JH bL -bL +yr bj bj bj @@ -5475,7 +5776,7 @@ bL bL JH JH -bL +yr bj bM da @@ -5545,9 +5846,9 @@ cP bL bL bL -bL +bZ JH -bL +yr bj cv cP @@ -5619,7 +5920,7 @@ bL mv xO JH -bL +yr bj cP cP @@ -5691,7 +5992,7 @@ cP cP Dk JH -bL +yr bj cP cP @@ -6479,7 +6780,7 @@ cH ti bd ti -Ut +uj bL cP tR @@ -6554,7 +6855,7 @@ bj Ut cP cP -tR +fI bj bj bj @@ -6621,12 +6922,12 @@ cP cP Pm ov -nh -ZM +sS +gN zZ cP cP -tR +mn bj bj bj @@ -6698,7 +6999,7 @@ cP cP cP cP -tR +um bj bj aa diff --git a/strings/xenotips.txt b/strings/xenotips.txt index d5bc61e7cf79..414d0883e576 100644 --- a/strings/xenotips.txt +++ b/strings/xenotips.txt @@ -37,6 +37,8 @@ You can filter out the Xenomorphs displayed in hive status by health, allowing y Each xeno has their own ‘tackle counter’ on a marine. The range to successfully tackle can be anywhere from two to six tackles based on caste. If a marine gets stunned or knocked over by other means it will reset everyone's tackle counters and they may get up! As a Xenomorph, the list of available tunnels is sorted by their distance to the player! As a Xenomorph, pay attention to what a marine is wearing. If they have no helmet, aiming for the head will be significantly more damaging, if they aren't wearing gloves, then think about going for their hands. +The M540-A Armored Recon Carrier can be crawled under as a xenomorph when destroyed. +The M540-A Armored Recon Carrier is very vulnerable to acid damage. Applying acid to flares makes them burn faster. Melting weapons, ammo or other valuables owned by marines is a good way to debilitate them. The secrete acid shortcut is (by default) Shift + C. diff --git a/tgui/.swcrc b/tgui/.swcrc new file mode 100644 index 000000000000..c0402a41f0bf --- /dev/null +++ b/tgui/.swcrc @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "loose": true, + "parser": { + "syntax": "typescript", + "tsx": true + }, + "transform": { + "react": { + "runtime": "automatic" + } + } + } +} diff --git a/tgui/babel.config.js b/tgui/babel.config.js deleted file mode 100644 index 69a5a401cc77..000000000000 --- a/tgui/babel.config.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ - -const createBabelConfig = (options) => { - const { presets = [], plugins = [], removeConsole } = options; - return { - presets: [ - [ - require.resolve('@babel/preset-typescript'), - { - allowDeclareFields: true, - }, - ], - [ - require.resolve('@babel/preset-env'), - { - modules: 'commonjs', - useBuiltIns: 'entry', - corejs: '3.3.2', - spec: false, - loose: true, - targets: [], - }, - ], - [require.resolve('@babel/preset-react'), { runtime: 'automatic' }], - ...presets, - ].filter(Boolean), - plugins: [ - [ - require.resolve('@babel/plugin-transform-class-properties'), - { - loose: true, - }, - ], - require.resolve('@babel/plugin-transform-jscript'), - removeConsole && require.resolve('babel-plugin-transform-remove-console'), - require.resolve('common/string.babel-plugin.cjs'), - ...plugins, - ].filter(Boolean), - }; -}; - -module.exports = (api) => { - api.cache(true); - const mode = process.env.NODE_ENV; - return createBabelConfig({ mode }); -}; - -module.exports.createBabelConfig = createBabelConfig; diff --git a/tgui/jest.config.js b/tgui/jest.config.js index 8b78818004be..d8b4ac3e41a8 100644 --- a/tgui/jest.config.js +++ b/tgui/jest.config.js @@ -8,7 +8,7 @@ module.exports = { testEnvironment: 'jsdom', testRunner: require.resolve('jest-circus/runner'), transform: { - '^.+\\.(js|cjs|ts|tsx)$': require.resolve('babel-jest'), + '^.+\\.(js|cjs|ts|tsx)$': require.resolve('@swc/jest'), }, moduleFileExtensions: ['js', 'cjs', 'ts', 'tsx', 'json'], resetMocks: true, diff --git a/tgui/package.json b/tgui/package.json index 77ff3be9b01f..1187ab904451 100644 --- a/tgui/package.json +++ b/tgui/package.json @@ -20,24 +20,16 @@ "tgui:tsc": "tsc" }, "dependencies": { - "@babel/core": "^7.15.0", - "@babel/eslint-parser": "^7.15.0", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-jscript": "^7.14.5", - "@babel/preset-env": "^7.15.0", - "@babel/preset-react": "^7.23.3", - "@babel/preset-typescript": "^7.15.0", + "@swc/core": "^1.5.0", + "@swc/jest": "^0.2.36", "@types/jest": "^27.0.1", "@types/jsdom": "^16.2.13", "@types/node": "^14.17.9", "@types/webpack": "^5.28.0", "@types/webpack-env": "^1.16.2", "@typescript-eslint/parser": "^4.29.1", - "babel-jest": "^27.0.6", - "babel-loader": "^8.2.2", - "babel-plugin-transform-remove-console": "^6.9.4", - "common": "workspace:*", "css-loader": "^5.2.7", + "esbuild-loader": "^4.1.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-radar": "^0.2.1", @@ -52,7 +44,7 @@ "sass": "^1.37.5", "sass-loader": "^11.1.1", "style-loader": "^2.0.0", - "terser-webpack-plugin": "^5.1.4", + "swc-loader": "^0.2.6", "typescript": "^4.9.4", "url-loader": "^4.1.1", "webpack": "^5.75.0", diff --git a/tgui/packages/tgui/components/Button.jsx b/tgui/packages/tgui/components/Button.jsx index dbffb6a72c95..826ba3309676 100644 --- a/tgui/packages/tgui/components/Button.jsx +++ b/tgui/packages/tgui/components/Button.jsx @@ -5,7 +5,7 @@ */ import { KEY_ENTER, KEY_ESCAPE, KEY_SPACE } from 'common/keycodes'; -import { classes, pureComponentHooks } from 'common/react'; +import { classes } from 'common/react'; import { Component, createRef } from 'react'; import { createLogger } from '../logging'; import { Box, computeBoxClassName, computeBoxProps } from './Box'; @@ -134,8 +134,6 @@ export const Button = (props) => { return buttonContent; }; -Button.defaultHooks = pureComponentHooks; - export const ButtonCheckbox = (props) => { const { checked, ...rest } = props; return ( diff --git a/tgui/packages/tgui/components/Chart.jsx b/tgui/packages/tgui/components/Chart.jsx index b8a9c62f8929..87eacff1e35f 100644 --- a/tgui/packages/tgui/components/Chart.jsx +++ b/tgui/packages/tgui/components/Chart.jsx @@ -5,7 +5,6 @@ */ import { map, zipWith } from 'common/collections'; -import { pureComponentHooks } from 'common/react'; import { Component, createRef } from 'react'; import { Box } from './Box'; @@ -117,8 +116,6 @@ class LineChart extends Component { } } -LineChart.defaultHooks = pureComponentHooks; - const Stub = (props) => null; // IE8: No inline svg support diff --git a/tgui/packages/tgui/components/ColorBox.jsx b/tgui/packages/tgui/components/ColorBox.jsx index a6203ca4694c..ce3c202d8cd6 100644 --- a/tgui/packages/tgui/components/ColorBox.jsx +++ b/tgui/packages/tgui/components/ColorBox.jsx @@ -4,7 +4,7 @@ * @license MIT */ -import { classes, pureComponentHooks } from 'common/react'; +import { classes } from 'common/react'; import { computeBoxClassName, computeBoxProps } from './Box'; export const ColorBox = (props) => { @@ -27,5 +27,3 @@ export const ColorBox = (props) => { ); }; - -ColorBox.defaultHooks = pureComponentHooks; diff --git a/tgui/packages/tgui/components/DraggableControl.jsx b/tgui/packages/tgui/components/DraggableControl.jsx index 018118dd7966..3b4b5380ccb4 100644 --- a/tgui/packages/tgui/components/DraggableControl.jsx +++ b/tgui/packages/tgui/components/DraggableControl.jsx @@ -5,7 +5,6 @@ */ import { clamp } from 'common/math'; -import { pureComponentHooks } from 'common/react'; import { Component, createRef } from 'react'; import { AnimatedNumber } from './AnimatedNumber'; @@ -276,7 +275,6 @@ export class DraggableControl extends Component { } } -DraggableControl.defaultHooks = pureComponentHooks; DraggableControl.defaultProps = { minValue: -Infinity, maxValue: +Infinity, diff --git a/tgui/packages/tgui/components/Grid.jsx b/tgui/packages/tgui/components/Grid.jsx index 7ad3fd1dfdbf..f5593c9e00a5 100644 --- a/tgui/packages/tgui/components/Grid.jsx +++ b/tgui/packages/tgui/components/Grid.jsx @@ -5,7 +5,6 @@ */ import { Table } from './Table'; -import { pureComponentHooks } from 'common/react'; /** @deprecated */ export const Grid = (props) => { @@ -17,8 +16,6 @@ export const Grid = (props) => { ); }; -Grid.defaultHooks = pureComponentHooks; - /** @deprecated */ export const GridColumn = (props) => { const { size = 1, style, ...rest } = props; @@ -33,6 +30,4 @@ export const GridColumn = (props) => { ); }; -Grid.defaultHooks = pureComponentHooks; - Grid.Column = GridColumn; diff --git a/tgui/packages/tgui/components/Icon.jsx b/tgui/packages/tgui/components/Icon.jsx index e9a4d7fd7ba9..5d63782fa72c 100644 --- a/tgui/packages/tgui/components/Icon.jsx +++ b/tgui/packages/tgui/components/Icon.jsx @@ -6,7 +6,7 @@ * @license MIT */ -import { classes, pureComponentHooks } from 'common/react'; +import { classes } from 'common/react'; import { computeBoxClassName, computeBoxProps } from './Box'; const FA_OUTLINE_REGEX = /-o$/; @@ -55,8 +55,6 @@ export const Icon = (props) => { ); }; -Icon.defaultHooks = pureComponentHooks; - export const IconStack = (props) => { const { className, children, ...rest } = props; return ( diff --git a/tgui/packages/tgui/components/NoticeBox.jsx b/tgui/packages/tgui/components/NoticeBox.jsx index 1c3b49b16a53..09e205b46bef 100644 --- a/tgui/packages/tgui/components/NoticeBox.jsx +++ b/tgui/packages/tgui/components/NoticeBox.jsx @@ -4,7 +4,7 @@ * @license MIT */ -import { classes, pureComponentHooks } from 'common/react'; +import { classes } from 'common/react'; import { Box } from './Box'; export const NoticeBox = (props) => { @@ -23,5 +23,3 @@ export const NoticeBox = (props) => { /> ); }; - -NoticeBox.defaultHooks = pureComponentHooks; diff --git a/tgui/packages/tgui/components/Table.jsx b/tgui/packages/tgui/components/Table.jsx index e936b9144808..60e7ea1cd227 100644 --- a/tgui/packages/tgui/components/Table.jsx +++ b/tgui/packages/tgui/components/Table.jsx @@ -4,7 +4,7 @@ * @license MIT */ -import { classes, pureComponentHooks } from 'common/react'; +import { classes } from 'common/react'; import { computeBoxClassName, computeBoxProps } from './Box'; export const Table = (props) => { @@ -23,8 +23,6 @@ export const Table = (props) => { ); }; -Table.defaultHooks = pureComponentHooks; - export const TableRow = (props) => { const { className, header, ...rest } = props; return ( @@ -40,8 +38,6 @@ export const TableRow = (props) => { ); }; -TableRow.defaultHooks = pureComponentHooks; - export const TableCell = (props) => { const { className, collapsing, header, ...rest } = props; return ( @@ -58,7 +54,5 @@ export const TableCell = (props) => { ); }; -TableCell.defaultHooks = pureComponentHooks; - Table.Row = TableRow; Table.Cell = TableCell; diff --git a/tgui/packages/tgui/interfaces/AresInterface.jsx b/tgui/packages/tgui/interfaces/AresInterface.jsx index be9106e31c25..115a5fd1e74f 100644 --- a/tgui/packages/tgui/interfaces/AresInterface.jsx +++ b/tgui/packages/tgui/interfaces/AresInterface.jsx @@ -66,7 +66,7 @@ const Login = (props) => { WY-DOS Executive - Version 8.2.3 + Version 8.3.4 Copyright © 2182, Weyland Yutani Corp.