diff --git a/code/__DEFINES/__game.dm b/code/__DEFINES/__game.dm index f1424f5560ec..765603df629c 100644 --- a/code/__DEFINES/__game.dm +++ b/code/__DEFINES/__game.dm @@ -103,7 +103,7 @@ block( \ #define SOUND_MIDI (1<<1) #define SOUND_AMBIENCE (1<<2) #define SOUND_LOBBY (1<<3) -#define SOUND_INTERNET (1<<4) +#define SOUND_INTERNET (1<<4) // Unused currently. Kept for default prefs compat only #define SOUND_REBOOT (1<<5) #define SOUND_ADMIN_MEME (1<<6) #define SOUND_ADMIN_ATMOSPHERIC (1<<7) diff --git a/code/__DEFINES/assert.dm b/code/__DEFINES/assert.dm new file mode 100644 index 000000000000..cff78107714c --- /dev/null +++ b/code/__DEFINES/assert.dm @@ -0,0 +1,13 @@ +#undef ASSERT + +/// Override BYOND's native ASSERT to optionally specify a message +#define ASSERT(condition, message...) \ + if (!(condition)) { \ + CRASH(assertion_message(__FILE__, __LINE__, #condition, ##message)) \ + } + +/proc/assertion_message(file, line, condition, message) + if (!isnull(message)) + message = " - [message]" + + return "[file]:[line]:Assertion failed: [condition][message]" diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 3abd79708f7a..de7eb672e87b 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -23,6 +23,8 @@ #define T0C 273.15 // 0degC #define T20C 293.15 // 20degC +#define T90C 363.15 // 90degC +#define T120C 393.15 // 120degC #define TCMB 2.7 // -270.3degC #define ICE_COLONY_TEMPERATURE 223 //-50degC #define SOROKYNE_TEMPERATURE 223 // Same as Ice for now diff --git a/code/__DEFINES/conflict.dm b/code/__DEFINES/conflict.dm index 0820c709cdae..d69f0891ffa0 100644 --- a/code/__DEFINES/conflict.dm +++ b/code/__DEFINES/conflict.dm @@ -109,6 +109,7 @@ #define SHOES_SLOWDOWN -1 #define SLOWDOWN_ARMOR_NONE 0 +#define SLOWDOWN_ARMOR_SUPER_LIGHT 0.10 #define SLOWDOWN_ARMOR_VERY_LIGHT 0.20 #define SLOWDOWN_ARMOR_LIGHT 0.35 #define SLOWDOWN_ARMOR_MEDIUM 0.55 diff --git a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm index bab6064cfdbf..32717a2115f2 100644 --- a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm +++ b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm @@ -1,3 +1,5 @@ +///from base of mob/set_stat(): (new_stat, old_stat) +#define COMSIG_MOB_STATCHANGE "mob_statchange" /// From /obj/structure/machinery/door/airlock/proc/take_damage #define COMSIG_MOB_DESTROY_AIRLOCK "mob_destroy_airlock" @@ -128,3 +130,6 @@ /// From /obj/item/proc/pickup() : (obj/item/picked_up) #define COMSIG_MOB_PICKUP_ITEM "mob_pickup_item" + +/// Cancels all running cloaking effects on target +#define COMSIG_MOB_EFFECT_CLOAK_CANCEL "mob_effect_cloak_cancel" diff --git a/code/__DEFINES/dcs/signals/atom/signals_atom.dm b/code/__DEFINES/dcs/signals/atom/signals_atom.dm index cac9861d09cb..d9bd1202c159 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_atom.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_atom.dm @@ -51,3 +51,6 @@ /// Called when an atom is mouse dropped on another atom, from /client/MouseDrop: (atom/dropped_onto) #define COMSIG_ATOM_DROP_ON "atom_drop_on" + +/// Called when an atom has emp_act called on it, from /atom/emp_act: (severity) +#define COMSIG_ATOM_EMP_ACT "atom_emp_act" diff --git a/code/__DEFINES/dcs/signals/atom/signals_cell.dm b/code/__DEFINES/dcs/signals/atom/signals_cell.dm new file mode 100644 index 000000000000..75e13d8bfdfc --- /dev/null +++ b/code/__DEFINES/dcs/signals/atom/signals_cell.dm @@ -0,0 +1,26 @@ +/// (charge_amount) +#define COMSIG_CELL_USE_CHARGE "cell_use_charge" + #define COMPONENT_CELL_NO_USE_CHARGE (1<<0) + +/// (charge_amount) +#define COMSIG_CELL_ADD_CHARGE "cell_add_charge" + +#define COMSIG_CELL_START_TICK_DRAIN "cell_start_tick_drain" + +#define COMSIG_CELL_STOP_TICK_DRAIN "cell_stop_tick_drain" + +/// (mob/living/user) +#define COMSIG_CELL_TRY_RECHARGING "cell_try_recharging" + #define COMPONENT_CELL_NO_RECHARGE (1<<0) + +#define COMSIG_CELL_OUT_OF_CHARGE "cell_out_of_charge" + +/// (charge_amount) +#define COMSIG_CELL_CHECK_CHARGE "cell_check_charge" + #define COMPONENT_CELL_CHARGE_INSUFFICIENT (1<<0) + +#define COMSIG_CELL_TRY_INSERT_CELL "cell_try_insert_cell" + #define COMPONENT_CANCEL_CELL_INSERT (1<<0) + +/// (mob/living/user) +#define COMSIG_CELL_REMOVE_CELL "cell_remove_cell" diff --git a/code/__DEFINES/dcs/signals/atom/signals_item.dm b/code/__DEFINES/dcs/signals/atom/signals_item.dm index 6c31b77f76a4..6024c0524992 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_item.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_item.dm @@ -65,3 +65,6 @@ /// from /obj/item/weapon/gun/proc/load_into_chamber() : () #define COMSIG_GUN_INTERRUPT_FIRE "gun_interrupt_fire" + +//from /datum/authority/branch/role/proc/equip_role() +#define COMSIG_POST_SPAWN_UPDATE "post_spawn_update" diff --git a/code/__DEFINES/dcs/signals/atom/signals_obj.dm b/code/__DEFINES/dcs/signals/atom/signals_obj.dm index aebd0d09d0d2..93579e068ec7 100644 --- a/code/__DEFINES/dcs/signals/atom/signals_obj.dm +++ b/code/__DEFINES/dcs/signals/atom/signals_obj.dm @@ -29,3 +29,5 @@ /// from /obj/proc/afterbuckle() #define COSMIG_OBJ_AFTER_BUCKLE "signal_obj_after_buckle" + +#define COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED "structure_crate_squad_launched" diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index 032a1891a808..dc5e70fcd5ec 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -60,8 +60,11 @@ #define COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING "!groundside_forsaken_handling" /// From -#define COMSIG_GLOB_YAUTJA_ARMORY_OPENED "yautja_armory_opened" +#define COMSIG_GLOB_YAUTJA_ARMORY_OPENED "!yautja_armory_opened" /// From /proc/biohazard_lockdown() -#define COMSIG_GLOB_RESEARCH_LOCKDOWN "research_lockdown_closed" -#define COMSIG_GLOB_RESEARCH_LIFT "research_lockdown_opened" +#define COMSIG_GLOB_RESEARCH_LOCKDOWN "!research_lockdown_closed" +#define COMSIG_GLOB_RESEARCH_LIFT "!research_lockdown_opened" + +/// From /obj/structure/machinery/power/fusion_engine/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 5f8f27a65711..6628a5c925c2 100644 --- a/code/__DEFINES/equipment.dm +++ b/code/__DEFINES/equipment.dm @@ -80,10 +80,8 @@ #define CAN_DIG_SHRAPNEL (1<<11) /// whether it has an animated icon state of "[icon_state]_on" to be used during surgeries. #define ANIMATED_SURGICAL_TOOL (1<<12) -/// The item goes on top of tables, instead of into them with the overlay system -#define NOTABLEMERGE (1<<13) /// Has heat source but isn't 'on fire' and thus can be stored -#define IGNITING_ITEM (1<<14) +#define IGNITING_ITEM (1<<13) //========================================================================================== diff --git a/code/__DEFINES/hijack.dm b/code/__DEFINES/hijack.dm new file mode 100644 index 000000000000..85d4c227ae70 --- /dev/null +++ b/code/__DEFINES/hijack.dm @@ -0,0 +1,13 @@ +#define EVACUATION_TYPE_NONE 0 +#define EVACUATION_TYPE_ADDITIVE 1 +#define EVACUATION_TYPE_MULTIPLICATIVE 2 + +#define HIJACK_ANNOUNCE "ARES Emergency Procedures" +#define XENO_HIJACK_ANNOUNCE "You sense something unusual..." + +#define EVACUATION_STATUS_NOT_INITIATED 0 +#define EVACUATION_STATUS_INITIATED 1 + +#define HIJACK_OBJECTIVES_NOT_STARTED 0 +#define HIJACK_OBJECTIVES_STARTED 1 +#define HIJACK_OBJECTIVES_COMPLETE 2 diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 38e5693dcbe5..deee80c7a91d 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -23,3 +23,5 @@ #define NOTIFY_ATTACK "attack" #define NOTIFY_ORBIT "orbit" #define NOTIFY_JOIN_XENO "join_xeno" +#define NOTIFY_XENO_TACMAP "xeno_tacmap" +#define NOTIFY_USCM_TACMAP "uscm_tacmap" diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm index 89b88f67c038..56062cb0213b 100644 --- a/code/__DEFINES/job.dm +++ b/code/__DEFINES/job.dm @@ -11,6 +11,7 @@ #define SQUAD_MARINE_CRYO "Foxtrot" #define SQUAD_MARINE_INTEL "Intel" #define SQUAD_SOF "SOF" +#define SQUAD_CBRN "CBRN" // Job name defines #define JOB_SQUAD_MARINE "Rifleman" diff --git a/code/__DEFINES/keybinding.dm b/code/__DEFINES/keybinding.dm index 88f194bb33df..764282d59765 100644 --- a/code/__DEFINES/keybinding.dm +++ b/code/__DEFINES/keybinding.dm @@ -14,6 +14,7 @@ #define COMSIG_KB_ADMIN_INVISIMINTOGGLE_DOWN "keybinding_admin_invisimintoggle_down" #define COMSIG_KB_ADMIN_DEADMIN_DOWN "keybinding_admin_deadmin_down" #define COMSIG_KB_ADMIN_READMIN_DOWN "keybinding_admin_readmin_down" +#define COMSIG_KB_ADMIN_MENTORSAY_DOWN "keybinding_admin_mentorsay_down" //Carbon #define COMSIG_KB_CARBON_HOLDRUNMOVEINTENT_DOWN "keybinding_carbon_holdrunmoveintent_down" @@ -87,6 +88,7 @@ #define COMSIG_KB_HUMAN_WEAPON_UNLOAD "keybinding_human_weapon_unload" #define COMSIG_KB_HUMAN_WEAPON_ATTACHMENT "keybinding_human_weapon_attachment" #define COMSIG_KB_HUMAN_WEAPON_ATTACHMENT_RAIL "keybinding_human_weapon_attachment_rail" +#define COMSIG_KB_HUMAN_WEAPON_SHOTGUN_TUBE "keybinding_human_weapon_shotgun_tube" #define COMSIG_KB_HUMAN_WEAPON_TOGGLE_IFF "keybinding_human_weapon_toggle_iff" diff --git a/code/__DEFINES/minimap.dm b/code/__DEFINES/minimap.dm index 71d0ed8e7445..003d723600c4 100644 --- a/code/__DEFINES/minimap.dm +++ b/code/__DEFINES/minimap.dm @@ -5,7 +5,17 @@ #define MINIMAP_FLAG_UPP (1<<3) #define MINIMAP_FLAG_CLF (1<<4) #define MINIMAP_FLAG_YAUTJA (1<<5) -#define MINIMAP_FLAG_ALL (1<<6) - 1 +#define MINIMAP_FLAG_XENO_CORRUPTED (1<<6) +#define MINIMAP_FLAG_XENO_ALPHA (1<<7) +#define MINIMAP_FLAG_XENO_BRAVO (1<<8) +#define MINIMAP_FLAG_XENO_CHARLIE (1<<9) +#define MINIMAP_FLAG_XENO_DELTA (1<<10) +#define MINIMAP_FLAG_XENO_FERAL (1<<11) +#define MINIMAP_FLAG_XENO_TAMED (1<<12) +#define MINIMAP_FLAG_XENO_MUTATED (1<<13) +#define MINIMAP_FLAG_XENO_FORSAKEN (1<<14) +#define MINIMAP_FLAG_XENO_RENEGADE (1<<15) +#define MINIMAP_FLAG_ALL (1<<16) - 1 ///Converts the overworld x and y to minimap x and y values #define MINIMAP_SCALE 2 @@ -77,9 +87,3 @@ GLOBAL_LIST_INIT(all_minimap_flags, bitfield2list(MINIMAP_FLAG_ALL)) #define TACMAP_BASE_OCCLUDED "Occluded" #define TACMAP_BASE_OPEN "Open" - -#define TACMAP_DEFAULT "Default" -#define TACMAP_XENO "Xeno" -#define TACMAP_YAUTJA "Yautja" -#define TACMAP_FACTION "Faction" - diff --git a/code/__DEFINES/sounds.dm b/code/__DEFINES/sounds.dm index a6bb381100e7..541d95d28189 100644 --- a/code/__DEFINES/sounds.dm +++ b/code/__DEFINES/sounds.dm @@ -27,7 +27,7 @@ #define SOUND_CHANNEL_AMBIENCE 1019 #define SOUND_CHANNEL_WALKMAN 1020 #define SOUND_CHANNEL_SOUNDSCAPE 1021 -#define SOUND_CHANNEL_ADMIN_MIDI 1022 +//#define SOUND_CHANNEL_ADMIN_MIDI 1022 #define SOUND_CHANNEL_LOBBY 1023 #define SOUND_CHANNEL_Z 1024 diff --git a/code/__DEFINES/speech_channels.dm b/code/__DEFINES/speech_channels.dm index 3f6e4720bde9..5a9a74af8ad0 100644 --- a/code/__DEFINES/speech_channels.dm +++ b/code/__DEFINES/speech_channels.dm @@ -1,6 +1,7 @@ // Used to direct channels to speak into. #define SAY_CHANNEL "Say" #define COMMS_CHANNEL "Comms" +#define WHISPER_CHANNEL "Whisper" #define ME_CHANNEL "Me" #define OOC_CHANNEL "OOC" #define LOOC_CHANNEL "LOOC" diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 158c59aff327..6af4a3585e29 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -109,36 +109,24 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. -#define SS_INIT_TICKER_SPAWN 999 +#define SS_INIT_PROFILER 86 #define SS_INIT_INPUT 85 -#define SS_INIT_FAIL_TO_TOPIC 84 #define SS_INIT_TOPIC 83 #define SS_INIT_LOBBYART 82 -#define SS_INIT_RUST 30 #define SS_INIT_INFLUXDRIVER 28 -#define SS_INIT_SUPPLY_SHUTTLE 25 #define SS_INIT_GARBAGE 24 #define SS_INIT_EVENTS 23.5 -#define SS_INIT_JOB 23 +#define SS_INIT_HIJACK 22.6 #define SS_INIT_REDIS 22.5 #define SS_INIT_REAGENTS 22.1 #define SS_INIT_MAPPING 22 #define SS_INIT_NIGHTMARE 21.5 #define SS_INIT_TIMETRACK 21.1 #define SS_INIT_HUMANS 21 -#define SS_INIT_MAP 20 -#define SS_INIT_COMPONENT 19.5 #define SS_INIT_POWER 19 -#define SS_INIT_OBJECT 18 -#define SS_INIT_PIPENET 17.5 -#define SS_INIT_XENOARCH 17 -#define SS_INIT_MORE_INIT 16 -#define SS_INIT_AIR 15 -#define SS_INIT_TELEPORTER 13 #define SS_INIT_INFLUXMCSTATS 12 #define SS_INIT_INFLUXSTATS 11 #define SS_INIT_LIGHTING 10 -#define SS_INIT_DEFCON 9 #define SS_INIT_LAW 6 #define SS_INIT_FZ_TRANSITIONS 5 #define SS_INIT_PROJECTILES 4.1 @@ -152,12 +140,9 @@ #define SS_INIT_RADIO 2 #define SS_INIT_TIMER 100 #define SS_INIT_UNSPECIFIED 0 -#define SS_INIT_EMERGENCY_SHUTTLE -19 #define SS_INIT_ASSETS -20 #define SS_INIT_TICKER -21 #define SS_INIT_VOTE -23 -#define SS_INIT_FINISH -24 -#define SS_INIT_ADMIN -26 #define SS_INIT_DATABASE -27 #define SS_INIT_ENTITYMANAGER -28 #define SS_INIT_PLAYTIME -29 @@ -176,7 +161,6 @@ #define SS_PRIORITY_SOUND 250 #define SS_PRIORITY_TICKER 200 #define SS_PRIORITY_NIGHTMARE 180 -#define SS_PRIORITY_MAPVIEW 170 #define SS_PRIORITY_QUADTREE 160 #define SS_PRIORITY_CHAT 155 #define SS_PRIORITY_STATPANEL 154 @@ -194,20 +178,17 @@ #define SS_PRIORITY_VOTE 110 #define SS_PRIORITY_FAST_OBJECTS 105 #define SS_PRIORITY_OBJECTS 104 -#define SS_PRIORITY_FACEHUGGERS 100 #define SS_PRIORITY_DECORATOR 99 +#define SS_PRIORITY_HIJACK 97 #define SS_PRIORITY_POWER 95 #define SS_PRIORITY_EFFECTS 92 #define SS_PRIORITY_MACHINERY 90 #define SS_PRIORITY_FZ_TRANSITIONS 88 -#define SS_PRIORITY_PIPENET 85 #define SS_PRIORITY_ROUND_RECORDING 83 #define SS_PRIORITY_SHUTTLE 80 -#define SS_PRIORITY_TELEPORTER 75 #define SS_PRIORITY_EVENT 65 #define SS_PRIORITY_DISEASE 60 -#define SS_PRIORITY_FAST_MACHINERY 55 -#define SS_PRIORITY_MIDI 40 +#define SS_PRIORITY_DEFENSES 55 #define SS_PRIORITY_ENTITY 37 #define SS_PRIORITY_DEFCON 35 #define SS_PRIORITY_ACID_PILLAR 34 @@ -226,7 +207,6 @@ #define SS_PRIORITY_INFLUXSTATS 8 #define SS_PRIORITY_PLAYTIME 5 #define SS_PRIORITY_PERFLOGGING 4 -#define SS_PRIORITY_CORPSESPAWNER 3 #define SS_PRIORITY_GARBAGE 2 #define SS_PRIORITY_INACTIVITY 1 #define SS_PRIORITY_ADMIN 0 diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm index 1bdf2318d250..9257172eeee5 100644 --- a/code/__DEFINES/surgery.dm +++ b/code/__DEFINES/surgery.dm @@ -149,7 +149,7 @@ See also /datum/surgery_step/saw_off_limb/failure var/list/cannot_hack, listing #define SURGERY_TOOLS_SEVER_BONE list(\ /obj/item/tool/surgery/circular_saw = SURGERY_TOOL_MULT_IDEAL,\ /obj/item/weapon/twohanded/fireaxe = SURGERY_TOOL_MULT_SUBOPTIMAL,\ - /obj/item/weapon/claymore/mercsword/machete = SURGERY_TOOL_MULT_SUBOPTIMAL,\ + /obj/item/weapon/sword/machete = SURGERY_TOOL_MULT_SUBOPTIMAL,\ /obj/item/tool/hatchet = SURGERY_TOOL_MULT_SUBSTITUTE,\ /obj/item/tool/kitchen/knife/butcher = SURGERY_TOOL_MULT_SUBSTITUTE,\ /obj/item/attachable/bayonet = SURGERY_TOOL_MULT_BAD_SUBSTITUTE\ diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index d468d6044196..b0e97e05e9b2 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,6 +1,6 @@ // tgstation-server DMAPI -#define TGS_DMAPI_VERSION "6.6.1" +#define TGS_DMAPI_VERSION "6.7.0" // All functions and datums outside this document are subject to change with any version and should not be relied on. diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index ef500b6af9f8..7f69a4acc4d6 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -1,22 +1,20 @@ -//shamelessly ripped from TG #define SIGNAL_ADDTRAIT(trait_ref) "addtrait [trait_ref]" #define SIGNAL_REMOVETRAIT(trait_ref) "removetrait [trait_ref]" // trait accessor defines -//here be dragons #define ADD_TRAIT(target, trait, source) \ do { \ var/list/_L; \ - if (!target.status_traits) { \ - target.status_traits = list(); \ - _L = target.status_traits; \ + if (!target._status_traits) { \ + target._status_traits = list(); \ + _L = target._status_traits; \ _L[trait] = list(source); \ SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \ if(trait in GLOB.traits_with_elements){ \ target.AddElement(GLOB.traits_with_elements[trait]); \ } \ } else { \ - _L = target.status_traits; \ + _L = target._status_traits; \ if (_L[trait]) { \ _L[trait] |= list(source); \ } else { \ @@ -30,16 +28,16 @@ } while (0) #define REMOVE_TRAIT(target, trait, sources) \ do { \ - var/list/_L = target.status_traits; \ + var/list/_L = target._status_traits; \ var/list/_S; \ if (sources && !islist(sources)) { \ _S = list(sources); \ } else { \ _S = sources\ }; \ - if (_L && _L[trait]) { \ + if (_L?[trait]) { \ for (var/_T in _L[trait]) { \ - if ((!_S && (_T != TRAIT_SOURCE_QUIRK)) || (_T in _S)) { \ + if ((!_S && (_T != ROUNDSTART_TRAIT)) || (_T in _S)) { \ _L[trait] -= _T \ } \ };\ @@ -51,13 +49,40 @@ } \ }; \ if (!length(_L)) { \ - target.status_traits = null \ + target._status_traits = null \ + }; \ + } \ + } while (0) +#define REMOVE_TRAIT_NOT_FROM(target, trait, sources) \ + do { \ + var/list/_traits_list = target._status_traits; \ + var/list/_sources_list; \ + if (sources && !islist(sources)) { \ + _sources_list = list(sources); \ + } else { \ + _sources_list = sources\ + }; \ + if (_traits_list?[trait]) { \ + for (var/_trait_source in _traits_list[trait]) { \ + if (!(_trait_source in _sources_list)) { \ + _traits_list[trait] -= _trait_source \ + } \ + };\ + if (!length(_traits_list[trait])) { \ + _traits_list -= trait; \ + SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \ + if(trait in GLOB.traits_with_elements) { \ + target.RemoveElement(GLOB.traits_with_elements[trait]); \ + } \ + }; \ + if (!length(_traits_list)) { \ + target._status_traits = null \ }; \ } \ } while (0) #define REMOVE_TRAITS_NOT_IN(target, sources) \ do { \ - var/list/_L = target.status_traits; \ + var/list/_L = target._status_traits; \ var/list/_S = sources; \ if (_L) { \ for (var/_T in _L) { \ @@ -65,20 +90,20 @@ if (!length(_L[_T])) { \ _L -= _T; \ SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T), _T); \ - if(_T in GLOB.traits_with_elements) { \ - target.RemoveElement(GLOB.traits_with_elements[_T]); \ + if(trait in GLOB.traits_with_elements) { \ + target.RemoveElement(GLOB.traits_with_elements[trait]); \ }; \ };\ };\ if (!length(_L)) { \ - target.status_traits = null\ + target._status_traits = null\ };\ }\ } while (0) #define REMOVE_TRAITS_IN(target, sources) \ do { \ - var/list/_L = target.status_traits; \ + var/list/_L = target._status_traits; \ var/list/_S = sources; \ if (sources && !islist(sources)) { \ _S = list(sources); \ @@ -97,40 +122,34 @@ };\ };\ if (!length(_L)) { \ - target.status_traits = null\ + target._status_traits = null\ };\ }\ } while (0) -/// Will 100% nuke a trait regardless of source. Preferably use this as little as possible -#define REMOVE_TRAIT_ALLSOURCES(target, trait) \ - do { \ - var/list/_L = target.status_traits; \ - if (_L?[trait]) { \ - if (length(_L)) { \ - _L -= trait; \ - SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \ - }; \ - else { \ - target.status_traits = null \ - }; \ - } \ - } while (0) - -#define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE) -#define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE) -#define HAS_TRAIT_FROM_ONLY(target, trait, source) (\ - target.status_traits ?\ - (target.status_traits[trait] ?\ - ((source in target.status_traits[trait]) && (length(target.status_traits) == 1))\ - : FALSE)\ - : FALSE) -#define HAS_TRAIT_NOT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (length(target.status_traits[trait] - source) > 0) : FALSE) : FALSE) - +#define HAS_TRAIT(target, trait) (target._status_traits?[trait] ? TRUE : FALSE) +#define HAS_TRAIT_FROM(target, trait, source) (HAS_TRAIT(target, trait) && (source in target._status_traits[trait])) +#define HAS_TRAIT_FROM_ONLY(target, trait, source) (HAS_TRAIT(target, trait) && (source in target._status_traits[trait]) && (length(target._status_traits[trait]) == 1)) +#define HAS_TRAIT_NOT_FROM(target, trait, source) (HAS_TRAIT(target, trait) && (length(target._status_traits[trait] - source) > 0)) +/// Returns a list of trait sources for this trait. Only useful for wacko cases and internal futzing +/// You should not be using this +#define GET_TRAIT_SOURCES(target, trait) (target._status_traits?[trait] || list()) +/// Returns the amount of sources for a trait. useful if you don't want to have a "thing counter" stuck around all the time +#define COUNT_TRAIT_SOURCES(target, trait) length(GET_TRAIT_SOURCES(target, trait)) +/// A simple helper for checking traits in a mob's mind +#define HAS_MIND_TRAIT(target, trait) (HAS_TRAIT(target, trait) || (target.mind ? HAS_TRAIT(target.mind, trait) : FALSE)) /// Example trait // #define TRAIT_X "t_x" + //-- mob traits -- +/// Prevents voluntary movement. +#define TRAIT_IMMOBILIZED "immobilized" +/// Apply this to make a mob not dense, and remove it when you want it to no longer make them undense, other sorces of undesity will still apply. Always define a unique source when adding a new instance of this! +#define TRAIT_UNDENSE "undense" +/// Apply this to identify a mob as merged with weeds +#define TRAIT_MERGED_WITH_WEEDS "merged_with_weeds" + // SPECIES TRAITS /// Knowledge of Yautja technology #define TRAIT_YAUTJA_TECH "t_yautja_tech" @@ -279,6 +298,8 @@ GLOBAL_LIST_INIT(mob_traits, list( */ GLOBAL_LIST_INIT(traits_by_type, list( /mob = list( + "TRAIT_IMMOBILIZED" = TRAIT_IMMOBILIZED, + "TRAIT_UNDENSE" = TRAIT_UNDENSE, "TRAIT_YAUTJA_TECH" = TRAIT_YAUTJA_TECH, "TRAIT_SUPER_STRONG" = TRAIT_SUPER_STRONG, "TRAIT_FOREIGN_BIO" = TRAIT_FOREIGN_BIO, @@ -354,15 +375,17 @@ GLOBAL_LIST(trait_name_map) /// Example trait source // #define TRAIT_SOURCE_Y "t_s_y" #define TRAIT_SOURCE_INHERENT "t_s_inherent" +/// cannot be removed without admin intervention +#define ROUNDSTART_TRAIT "roundstart" //-- mob traits -- +///Status trait coming from lying down through update_canmove() +#define LYING_TRAIT "lying" ///Status trait coming from species. .human/species_gain() #define TRAIT_SOURCE_SPECIES "t_s_species" ///Status trait coming from the hive. #define TRAIT_SOURCE_HIVE "t_s_hive" ///Status trait coming from being buckled. #define TRAIT_SOURCE_BUCKLE "t_s_buckle" -///Status trait coming from roundstart quirks (that don't exist yet). Unremovable by REMOVE_TRAIT -#define TRAIT_SOURCE_QUIRK "t_s_quirk" ///Status trait coming from being assigned as [acting] squad leader. #define TRAIT_SOURCE_SQUAD_LEADER "t_s_squad_leader" ///Status trait coming from their job @@ -379,6 +402,8 @@ GLOBAL_LIST(trait_name_map) #define TRAIT_SOURCE_ABILITY(ability) "t_s_ability_[ability]" ///Status trait forced by the xeno action charge #define TRAIT_SOURCE_XENO_ACTION_CHARGE "t_s_xeno_action_charge" +///Status trait coming from a xeno nest +#define XENO_NEST_TRAIT "xeno_nest" //-- structure traits -- ///Status trait coming from being flipped or unflipped. #define TRAIT_SOURCE_FLIP_TABLE "t_s_flip_table" @@ -390,3 +415,14 @@ GLOBAL_LIST(trait_name_map) //Status trait coming from clothing. #define TRAIT_SOURCE_CLOTHING "t_s_clothing" + +/// traits associated with actively interacted machinery +#define INTERACTION_TRAIT "interaction" +/// trait effect related to active specialist gear +#define SPECIALIST_GEAR_TRAIT "specialist_gear" +/// traits associated with usage of snowflake dropship double seats +#define DOUBLE_SEATS_TRAIT "double_seats" +/// traits associated with xeno on-ground weeds +#define XENO_WEED_TRAIT "xeno_weed" +/// traits from chloroform usage +#define CHLOROFORM_TRAIT "chloroform" diff --git a/code/__DEFINES/urls.dm b/code/__DEFINES/urls.dm index 137095327a2c..5d3fca1a2032 100644 --- a/code/__DEFINES/urls.dm +++ b/code/__DEFINES/urls.dm @@ -1,3 +1,7 @@ +// placeholder strings to be replaced +#define WIKI_PLACEHOLDER "%WIKIURL%" +#define LAW_PLACEHOLDER "%LAWURL%" + // ------ MISC WIKI LINKS ------ // #define URL_WIKI_LAW "Marine_Law" #define URL_WIKI_XENO_QUICKSTART "Xeno_Quickstart_Guide" diff --git a/code/__DEFINES/vehicle.dm b/code/__DEFINES/vehicle.dm index 9c6685085788..8a1617229926 100644 --- a/code/__DEFINES/vehicle.dm +++ b/code/__DEFINES/vehicle.dm @@ -53,5 +53,6 @@ #define VEHICLE_CLASS_LIGHT (1<<2) //light class armor (APC, tank) #define VEHICLE_CLASS_MEDIUM (1<<3) //medium class armor (tank) #define VEHICLE_CLASS_HEAVY (1<<4) //heavy class armor (tank) - -#define TANK_POPLOCK 90 +// Other vehicle flags +/// Vehicle can bypass vehicle blockers, typically going further into maps than intended +#define VEHICLE_BYPASS_BLOCKERS (1<<5) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 1116f1acb2a8..24e39ff16c89 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -682,8 +682,9 @@ world * * moving - whether or not to use a moving state for the given icon * * sourceonly - if TRUE, only generate the asset and send back the asset url, instead of tags that display the icon to players * * extra_clases - string of extra css classes to use when returning the icon string + * * keyonly - if TRUE, only returns the asset key to use get_asset_url manually. Overrides sourceonly. */ -/proc/icon2html(atom/thing, client/target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE, extra_classes = null) +/proc/icon2html(atom/thing, client/target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE, extra_classes = null, keyonly = FALSE) if (!thing) return @@ -714,6 +715,8 @@ world SSassets.transport.register_asset(name, thing) for (var/thing2 in targets) SSassets.transport.send_assets(thing2, name) + if(keyonly) + return name if(sourceonly) return SSassets.transport.get_asset_url(name) return "" @@ -756,6 +759,8 @@ world SSassets.transport.register_asset(key, rsc_ref, file_hash, icon_path) for (var/client_target in targets) SSassets.transport.send_assets(client_target, key) + if(keyonly) + return key if(sourceonly) return SSassets.transport.get_asset_url(key) return "" diff --git a/code/__HELPERS/job.dm b/code/__HELPERS/job.dm index 43902b07cfd9..220236c6f7e3 100644 --- a/code/__HELPERS/job.dm +++ b/code/__HELPERS/job.dm @@ -14,39 +14,10 @@ all_jobs += new jobtype return all_jobs - /proc/get_all_centcom_jobs() return list() -//gets the actual job rank (ignoring alt titles) -//this is used solely for sechuds -/obj/proc/GetJobRealName() - if (!istype(src,/obj/item/card/id)) return - var/obj/item/card/id/I = src - if(I.rank in GLOB.joblist) return I.rank - if(I.assignment in GLOB.joblist) return I.assignment - return "Unknown" - -/proc/FindNameFromID(mob/living/carbon/human/H) - ASSERT(istype(H)) - var/obj/item/card/id/I = H.wear_id - if(istype(I)) return I.registered_name - I = H.get_active_hand() - if(istype(I)) return I.registered_name - /proc/get_all_job_icons() return GLOB.joblist + list("Prisoner")//For all existing HUD icons -/obj/proc/GetJobName() //Used in secHUD icon generation - var/obj/item/card/id/I = src - if(istype(I)) - var/job_icons = get_all_job_icons() - var/centcom = get_all_centcom_jobs() - - if(I.assignment in job_icons) return I.assignment//Check if the job has a hud icon - if(I.rank in job_icons) return I.rank - if(I.assignment in centcom) return "Centcom"//Return with the NT logo if it is a Centcom job - if(I.rank in centcom) return "Centcom" - return "Unknown" //Return unknown if none of the above apply - /proc/get_actual_job_name(mob/M) if(!M) return null diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm new file mode 100644 index 000000000000..ba99b2e1e7ff --- /dev/null +++ b/code/__HELPERS/traits.dm @@ -0,0 +1,43 @@ +#define TRAIT_CALLBACK_ADD(target, trait, source) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___TraitAdd), ##target, ##trait, ##source) +#define TRAIT_CALLBACK_REMOVE(target, trait, source) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___TraitRemove), ##target, ##trait, ##source) + +///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback. +/proc/___TraitAdd(target,trait,source) + if(!target || !trait || !source) + return + if(islist(target)) + for(var/i in target) + if(!isatom(i)) + continue + var/atom/the_atom = i + ADD_TRAIT(the_atom,trait,source) + else if(isatom(target)) + var/atom/the_atom2 = target + ADD_TRAIT(the_atom2,trait,source) + +///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback. +/proc/___TraitRemove(target,trait,source) + if(!target || !trait || !source) + return + if(islist(target)) + for(var/i in target) + if(!isatom(i)) + continue + var/atom/the_atom = i + REMOVE_TRAIT(the_atom,trait,source) + else if(isatom(target)) + var/atom/the_atom2 = target + REMOVE_TRAIT(the_atom2,trait,source) + + +/// Proc that handles adding multiple traits to a target via a list. Must have a common source and target. +/datum/proc/add_traits(list/list_of_traits, source) + ASSERT(islist(list_of_traits), "Invalid arguments passed to add_traits! Invoked on [src] with [list_of_traits], source being [source].") + for(var/trait in list_of_traits) + ADD_TRAIT(src, trait, source) + +/// Proc that handles removing multiple traits from a target via a list. Must have a common source and target. +/datum/proc/remove_traits(list/list_of_traits, source) + ASSERT(islist(list_of_traits), "Invalid arguments passed to remove_traits! Invoked on [src] with [list_of_traits], source being [source].") + for(var/trait in list_of_traits) + REMOVE_TRAIT(src, trait, source) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 9a6ee4362088..38c02e776735 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -21,16 +21,16 @@ #define between(low, middle, high) (max(min(middle, high), low)) //Offuscate x for coord system -#define obfuscate_x(x) (x + obfs_x) +#define obfuscate_x(x) (x + GLOB.obfs_x) //Offuscate y for coord system -#define obfuscate_y(y) (y + obfs_y) +#define obfuscate_y(y) (y + GLOB.obfs_y) //Deoffuscate x for coord system -#define deobfuscate_x(x) (x - obfs_x) +#define deobfuscate_x(x) (x - GLOB.obfs_x) //Deoffuscate y for coord system -#define deobfuscate_y(y) (y - obfs_y) +#define deobfuscate_y(y) (y - GLOB.obfs_y) #define can_xeno_build(T) (!T.density && !(locate(/obj/structure/fence) in T) && !(locate(/obj/structure/tunnel) in T) && (locate(/obj/effect/alien/weeds) in T)) diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 53dd40ff6035..b85aa18fdb6b 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -166,7 +166,6 @@ DEFINE_BITFIELD(flags_item, list( "ITEM_OVERRIDE_NORTHFACE" = ITEM_OVERRIDE_NORTHFACE, "CAN_DIG_SHRAPNEL" = CAN_DIG_SHRAPNEL, "ANIMATED_SURGICAL_TOOL" = ANIMATED_SURGICAL_TOOL, - "NOTABLEMERGE" = NOTABLEMERGE, "IGNITING_ITEM" = IGNITING_ITEM, )) @@ -462,3 +461,11 @@ DEFINE_BITFIELD(vend_flags, list( "VEND_FACTION_THEMES" = VEND_FACTION_THEMES, "VEND_USE_VENDOR_FLAGS" = VEND_USE_VENDOR_FLAGS, )) + +DEFINE_BITFIELD(vehicle_flags, list( + "VEHICLE_CLASS_WEAK" = VEHICLE_CLASS_WEAK, + "VEHICLE_CLASS_LIGHT" = VEHICLE_CLASS_LIGHT, + "VEHICLE_CLASS_MEDIUM" = VEHICLE_CLASS_MEDIUM, + "VEHICLE_CLASS_HEAVY" = VEHICLE_CLASS_HEAVY, + "VEHICLE_BYPASS_BLOCKERS" = VEHICLE_BYPASS_BLOCKERS, +)) diff --git a/code/_globalvars/global_lists.dm b/code/_globalvars/global_lists.dm index 36058a44fc37..3ba92a7c4d0c 100644 --- a/code/_globalvars/global_lists.dm +++ b/code/_globalvars/global_lists.dm @@ -1,6 +1,3 @@ - -var/list/unansweredAhelps = list() //This feels inefficient, but I can't think of a better way. Stores the message indexed by CID - GLOBAL_LIST_EMPTY(PressFaxes) GLOBAL_LIST_EMPTY(WYFaxes) //Departmental faxes GLOBAL_LIST_EMPTY(USCMFaxes) @@ -9,6 +6,14 @@ GLOBAL_LIST_EMPTY(CMBFaxes) GLOBAL_LIST_EMPTY(GeneralFaxes) //Inter-machine faxes GLOBAL_LIST_EMPTY(fax_contents) //List of fax contents to maintain it even if source paper is deleted +//datum containing a reference to the flattend map png url, the actual png is stored in the user's cache. +GLOBAL_LIST_EMPTY(uscm_flat_tacmap_data) +GLOBAL_LIST_EMPTY(xeno_flat_tacmap_data) + +//datum containing the svg overlay coords in array format. +GLOBAL_LIST_EMPTY(uscm_svg_tacmap_data) +GLOBAL_LIST_EMPTY(xeno_svg_tacmap_data) + GLOBAL_LIST_EMPTY(failed_fultons) //A list of fultoned items which weren't collected and fell back down GLOBAL_LIST_EMPTY(larva_burst_by_hive) diff --git a/code/_globalvars/lists/object_lists.dm b/code/_globalvars/lists/object_lists.dm index 3a417625538b..3db9bd28cbfe 100644 --- a/code/_globalvars/lists/object_lists.dm +++ b/code/_globalvars/lists/object_lists.dm @@ -31,3 +31,6 @@ GLOBAL_LIST_EMPTY_TYPED(all_multi_vehicles, /obj/vehicle/multitile) GLOBAL_LIST_EMPTY_TYPED(lifeboat_almayer_docks, /obj/docking_port/stationary/lifeboat_dock) GLOBAL_LIST_EMPTY_TYPED(lifeboat_doors, /obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/lifeboat/blastdoor) + +GLOBAL_LIST_EMPTY_TYPED(teleporters, /datum/teleporter) +GLOBAL_LIST_EMPTY(teleporters_by_id) diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index 646b8ec2c854..cd6708198eae 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -14,6 +14,22 @@ GLOBAL_LIST_INIT(pill_icon_mappings, map_pill_icons()) /// In-round override to default OOC color GLOBAL_VAR(ooc_color_override) +// tacmap cooldown for xenos and marines +GLOBAL_VAR_INIT(uscm_canvas_cooldown, 0) +GLOBAL_VAR_INIT(xeno_canvas_cooldown, 0) + +// getFlatIcon cooldown for xenos and marines +GLOBAL_VAR_INIT(uscm_flatten_map_icon_cooldown, 0) +GLOBAL_VAR_INIT(xeno_flatten_map_icon_cooldown, 0) + +// latest unannounced flat tacmap for xenos and marines +GLOBAL_VAR(uscm_unannounced_map) +GLOBAL_VAR(xeno_unannounced_map) + +//global tacmaps for action button access +GLOBAL_DATUM_INIT(uscm_tacmap_status, /datum/tacmap/drawing/status_tab_view, new) +GLOBAL_DATUM_INIT(xeno_tacmap_status, /datum/tacmap/drawing/status_tab_view/xeno, new) + /// List of roles that can be setup for each gamemode GLOBAL_LIST_INIT(gamemode_roles, list()) @@ -30,3 +46,10 @@ GLOBAL_VAR_INIT(time_offset, setup_offset()) /// The last count of possible candidates in the xeno larva queue (updated via get_alien_candidates) GLOBAL_VAR(xeno_queue_candidate_count) + +//Coordinate obsfucator +//Used by the rangefinders and linked systems to prevent coords collection/prefiring +/// A number between -500 and 500. +GLOBAL_VAR(obfs_x) +/// A number between -500 and 500. +GLOBAL_VAR(obfs_y) diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm index a6754747a019..a99129d09bcd 100644 --- a/code/_onclick/hud/ghost.dm +++ b/code/_onclick/hud/ghost.dm @@ -48,6 +48,14 @@ var/mob/dead/observer/G = usr G.reenter_corpse() +/atom/movable/screen/ghost/toggle_huds + name = "Toggle HUDs" + icon_state = "ghost_hud_toggle" + +/atom/movable/screen/ghost/toggle_huds/Click() + var/client/client = usr.client + client.toggle_ghost_hud() + /datum/hud/ghost/New(mob/owner, ui_style='icons/mob/hud/human_white.dmi', ui_color, ui_alpha = 230) . = ..() var/atom/movable/screen/using @@ -68,6 +76,9 @@ using.screen_loc = ui_ghost_slot4 static_inventory += using + using = new /atom/movable/screen/ghost/toggle_huds() + using.screen_loc = ui_ghost_slot5 + static_inventory += using /datum/hud/ghost/show_hud(version = 0, mob/viewmob) // don't show this HUD if observing; show the HUD of the observee diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index cfc6c4d034fb..4a23ebd882d3 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -34,6 +34,12 @@ GLOBAL_LIST_EMPTY(radial_menus) /atom/movable/screen/radial/slice/clicked(mob/user) + if(QDELETED(src)) + return + + if(!parent) + CRASH("clicked() called on a radial slice with a null parent while not deleted/deleting") + if(user.client == parent.current_user) if(next_page) parent.next_page() diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index b49bce4111f0..d114aff6b7cb 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -535,7 +535,7 @@ if(!user.hive.living_xeno_queen) to_chat(user, SPAN_WARNING("Without a queen your psychic link is broken!")) return FALSE - if(user.burrow || user.is_mob_incapacitated() || user.buckled) + if(HAS_TRAIT(user, TRAIT_ABILITY_BURROWED) || user.is_mob_incapacitated() || user.buckled) return FALSE user.hive.mark_ui.update_all_data() user.hive.mark_ui.open_mark_menu(user) @@ -583,7 +583,7 @@ if(!user.hive.living_xeno_queen) to_chat(user, SPAN_WARNING("Your hive doesn't have a living queen!")) return FALSE - if(user.burrow || user.is_mob_incapacitated() || user.buckled) + if(HAS_TRAIT(user, TRAIT_ABILITY_BURROWED) || user.is_mob_incapacitated() || user.buckled) return FALSE user.overwatch(user.hive.living_xeno_queen) diff --git a/code/_onclick/human.dm b/code/_onclick/human.dm index cb71e27f9d1a..8f329656ef6c 100644 --- a/code/_onclick/human.dm +++ b/code/_onclick/human.dm @@ -99,7 +99,7 @@ if(xeno.stat != DEAD) // If the Xeno is alive, fight back var/mob/living/carbon/carbon_user = user if(!carbon_user || !carbon_user.ally_of_hivenumber(xeno.hivenumber)) - user.KnockDown(rand(xeno.caste.tacklestrength_min, xeno.caste.tacklestrength_max)) + carbon_user.KnockDown(rand(xeno.caste.tacklestrength_min, xeno.caste.tacklestrength_max)) playsound(user.loc, 'sound/weapons/pierce.ogg', 25, TRUE) user.visible_message(SPAN_WARNING("\The [user] tried to unstrap \the [back_item] from [xeno] but instead gets a tail swipe to the head!")) return diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 9c9784286d09..0bfa0a759287 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -13,7 +13,7 @@ var/obj/structure/S = A S.do_climb(src, mods) return TRUE - else if(!(isitem(A) && get_dist(src, A) <= 1) && client.prefs.toggle_prefs & TOGGLE_MIDDLE_MOUSE_SWAP_HANDS) + else if(!(isitem(A) && get_dist(src, A) <= 1) && (client && (client.prefs.toggle_prefs & TOGGLE_MIDDLE_MOUSE_SWAP_HANDS))) swap_hand() return TRUE diff --git a/code/_onclick/xeno.dm b/code/_onclick/xeno.dm index 62d612790930..adb637dfe8fa 100644 --- a/code/_onclick/xeno.dm +++ b/code/_onclick/xeno.dm @@ -3,7 +3,7 @@ */ /mob/living/carbon/xenomorph/UnarmedAttack(atom/target, proximity, click_parameters, tile_attack = FALSE, ignores_resin = FALSE) - if(lying || burrow) //No attacks while laying down + if(lying || HAS_TRAIT(src, TRAIT_ABILITY_BURROWED)) //No attacks while laying down return FALSE var/mob/alt diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index e8b010669c0e..147f57fcb1aa 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -20,7 +20,8 @@ var/policy var/static/regex/ic_filter_regex - var/list/fail_to_topic_whitelisted_ips + + var/is_loaded = FALSE /datum/controller/configuration/proc/admin_reload() if(IsAdminAdvancedProcCall()) @@ -53,7 +54,8 @@ loadmaplist(CONFIG_GROUND_MAPS_FILE, GROUND_MAP) loadmaplist(CONFIG_SHIP_MAPS_FILE, SHIP_MAP) LoadChatFilter() - LoadTopicRateWhitelist() + + is_loaded = TRUE if(Master) Master.OnConfigLoad() @@ -333,18 +335,3 @@ /datum/controller/configuration/proc/DelayedMessageAdmins(text) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(message_admins), text), 0) -/datum/controller/configuration/proc/LoadTopicRateWhitelist() - LAZYINITLIST(fail_to_topic_whitelisted_ips) - if(!fexists("[directory]/topic_rate_limit_whitelist.txt")) - log_config("Error 404: topic_rate_limit_whitelist.txt not found!") - return - - log_config("Loading config file topic_rate_limit_whitelist.txt...") - - for(var/line in file2list("[directory]/topic_rate_limit_whitelist.txt")) - if(!line) - continue - if(findtextEx(line, "#", 1, 2)) - continue - - fail_to_topic_whitelisted_ips[line] = 1 diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index cc3d00fd951b..385cbcb8d446 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -627,3 +627,5 @@ This maintains a list of ip addresses that are able to bypass topic filtering. protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED /datum/config_entry/flag/guest_ban + +/datum/config_entry/flag/auto_profile diff --git a/code/controllers/subsystem/admin.dm b/code/controllers/subsystem/admin.dm deleted file mode 100644 index 8aab64b04881..000000000000 --- a/code/controllers/subsystem/admin.dm +++ /dev/null @@ -1,40 +0,0 @@ -SUBSYSTEM_DEF(admin) - name = "Admin" - wait = 5 MINUTES - flags = SS_NO_INIT | SS_KEEP_TIMING - runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY - var/list/currentrun = list() - var/times_repeated = 0 - -/datum/controller/subsystem/admin/stat_entry(msg) - msg = "P:[unansweredAhelps.len]" - return ..() - -/datum/controller/subsystem/admin/fire(resumed = FALSE) - if (!resumed) - currentrun = unansweredAhelps.Copy() - - if(!currentrun.len) - times_repeated = 0 - return - - var/msg = "Unheard Ahelps (Repeated [times_repeated] times):" - - while (currentrun.len) - var/ahelp_msg = currentrun[currentrun.len] - currentrun.len-- - - if (!ahelp_msg) - continue - - msg += unansweredAhelps[ahelp_msg] + "\n" - - if (MC_TICK_CHECK) - return - - for(var/client/C in GLOB.admins) - if(C && C.admin_holder && (C.admin_holder.rights & R_MOD)) - if(C.prefs.toggles_sound & SOUND_ADMINHELP) - sound_to(C, 'sound/effects/adminhelp_new.ogg') - to_chat(C, msg) - times_repeated++ diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm index a5c5271c8d7d..8458436a53e5 100644 --- a/code/controllers/subsystem/communications.dm +++ b/code/controllers/subsystem/communications.dm @@ -107,6 +107,7 @@ var/const/MAX_FREQ = 1468 // --------------------------------------------------- var/const/HC_FREQ = 1471 var/const/SOF_FREQ = 1472 var/const/PVST_FREQ = 1473 +var/const/CBRN_FREQ = 1474 //Ship department channels var/const/SENTRY_FREQ = 1480 @@ -162,6 +163,7 @@ var/list/radiochannels = list( SQUAD_MARINE_5 = ECHO_FREQ, SQUAD_MARINE_CRYO = CRYO_FREQ, SQUAD_SOF = SOF_FREQ, + SQUAD_CBRN = CBRN_FREQ, RADIO_CHANNEL_ALAMO = DS1_FREQ, RADIO_CHANNEL_NORMANDY = DS2_FREQ, @@ -262,6 +264,7 @@ SUBSYSTEM_DEF(radio) "[DELTA_FREQ]" = "deltaradio", "[ECHO_FREQ]" = "echoradio", "[CRYO_FREQ]" = "cryoradio", + "[CBRN_FREQ]" = "hcradio", "[SOF_FREQ]" = "hcradio", "[HC_FREQ]" = "hcradio", "[PVST_FREQ]" = "pvstradio", diff --git a/code/controllers/subsystem/disease.dm b/code/controllers/subsystem/disease.dm index 25200cce11ed..b98187ca252c 100644 --- a/code/controllers/subsystem/disease.dm +++ b/code/controllers/subsystem/disease.dm @@ -1,22 +1,19 @@ -var/list/active_diseases = list() - - SUBSYSTEM_DEF(disease) name = "Disease" wait = 2 SECONDS flags = SS_NO_INIT | SS_KEEP_TIMING priority = SS_PRIORITY_DISEASE - var/list/currentrun = list() + var/list/datum/disease/all_diseases = list() + var/list/datum/disease/currentrun = list() /datum/controller/subsystem/disease/stat_entry(msg) - msg = "P:[active_diseases.len]" + msg = "P:[all_diseases.len]" return ..() - /datum/controller/subsystem/disease/fire(resumed = FALSE) if (!resumed) - currentrun = active_diseases.Copy() + currentrun = all_diseases.Copy() while (currentrun.len) var/datum/disease/D = currentrun[currentrun.len] diff --git a/code/controllers/subsystem/fail_to_topic.dm b/code/controllers/subsystem/fail_to_topic.dm deleted file mode 100644 index 45674683a443..000000000000 --- a/code/controllers/subsystem/fail_to_topic.dm +++ /dev/null @@ -1,81 +0,0 @@ -SUBSYSTEM_DEF(fail_to_topic) - name = "Fail to Topic" - init_order = SS_INIT_FAIL_TO_TOPIC - flags = SS_BACKGROUND - runlevels = ALL - - var/list/rate_limiting = list() - var/list/fail_counts = list() - var/list/active_bans = list() - var/list/currentrun = list() - - var/rate_limit - var/max_fails - var/enabled = FALSE - -/datum/controller/subsystem/fail_to_topic/Initialize(timeofday) - rate_limit = ((CONFIG_GET(number/topic_rate_limit)) SECONDS) - max_fails = CONFIG_GET(number/topic_max_fails) - enabled = CONFIG_GET(flag/topic_enabled) - - if (world.system_type == UNIX && enabled) - enabled = FALSE - WARNING("fail_to_topic subsystem disabled. UNIX is not supported.") - return SS_INIT_NO_NEED - - if (!enabled) - can_fire = FALSE - return SS_INIT_NO_NEED - - return SS_INIT_SUCCESS - -/datum/controller/subsystem/fail_to_topic/fire(resumed = FALSE) - if(!resumed) - currentrun = rate_limiting.Copy() - //cache for sanic speed (lists are references anyways) - var/list/current_run = currentrun - - while(current_run.len) - var/ip = current_run[current_run.len] - var/last_attempt = current_run[ip] - current_run.len-- - - // last_attempt list housekeeping - if(world.time - last_attempt > rate_limit) - rate_limiting -= ip - fail_counts -= ip - - if(MC_TICK_CHECK) - return - -/datum/controller/subsystem/fail_to_topic/proc/IsRateLimited(ip) - if(!enabled) - return FALSE - - var/last_attempt = rate_limiting[ip] - - if (config.fail_to_topic_whitelisted_ips[ip]) - return FALSE - - if (active_bans[ip]) - return TRUE - - rate_limiting[ip] = world.time - - if (isnull(last_attempt)) - return FALSE - - if (world.time - last_attempt > rate_limit) - fail_counts -= ip - return FALSE - else - var/failures = fail_counts[ip] - - if (isnull(failures)) - fail_counts[ip] = 1 - return TRUE - else if (failures > max_fails) - return TRUE - else - fail_counts[ip] = failures + 1 - return TRUE diff --git a/code/controllers/subsystem/fast_machinery.dm b/code/controllers/subsystem/fast_machinery.dm deleted file mode 100644 index 8211b3b5e310..000000000000 --- a/code/controllers/subsystem/fast_machinery.dm +++ /dev/null @@ -1,27 +0,0 @@ -var/list/fast_machines = list() - - -SUBSYSTEM_DEF(fast_machinery) - name = "Fast Machinery" - wait = 0.7 SECONDS - priority = SS_PRIORITY_FAST_MACHINERY - flags = SS_NO_INIT - var/list/currentrun = list() - -/datum/controller/subsystem/fast_machinery/stat_entry(msg) - msg = "FP:[fast_machines.len]" - return ..() - -/datum/controller/subsystem/fast_machinery/fire(resumed = FALSE) - if(!resumed) - currentrun = fast_machines.Copy() - while(currentrun.len) - var/obj/structure/machinery/M = currentrun[currentrun.len] - currentrun.len-- - - if(QDELETED(M)) - continue - - M.process() - if(MC_TICK_CHECK) - return diff --git a/code/controllers/subsystem/game_decorator.dm b/code/controllers/subsystem/game_decorator.dm new file mode 100644 index 000000000000..dd53b647d1a8 --- /dev/null +++ b/code/controllers/subsystem/game_decorator.dm @@ -0,0 +1,35 @@ +// Essentially the same as decorators but that apply to the whole game state instead of individual atoms +SUBSYSTEM_DEF(game_decorator) + name = "Game Decorator" + init_order = SS_INIT_DECORATOR + flags = SS_NO_FIRE + +/datum/controller/subsystem/game_decorator/Initialize() + . = ..() + for(var/decorator_type in subtypesof(/datum/game_decorator)) + var/datum/game_decorator/decorator = new decorator_type() + if(!decorator.is_active_decor()) + continue + if(!decorator.defer_decoration) + decorator.decorate() + CHECK_TICK + + return SS_INIT_SUCCESS + +/datum/game_decorator + var/defer_decoration = TRUE //! So map decoration is done post-setup after nightmare and spawners + +/datum/game_decorator/New() + if(defer_decoration && is_active_decor()) + RegisterSignal(SSdcs, COMSIG_GLOB_MODE_POSTSETUP, PROC_REF(defered_decoration)) + +/datum/game_decorator/proc/is_active_decor() + return FALSE + +/datum/game_decorator/proc/defered_decoration(dcs) + SIGNAL_HANDLER + decorate() + +/datum/game_decorator/proc/decorate() + set waitfor = FALSE + return diff --git a/code/controllers/subsystem/hijack.dm b/code/controllers/subsystem/hijack.dm new file mode 100644 index 000000000000..a256a7f2a8b2 --- /dev/null +++ b/code/controllers/subsystem/hijack.dm @@ -0,0 +1,429 @@ +SUBSYSTEM_DEF(hijack) + name = "Hijack" + wait = 2 SECONDS + flags = SS_KEEP_TIMING + priority = SS_PRIORITY_HIJACK + init_order = SS_INIT_HIJACK + + ///Required progress to evacuate safely via lifeboats + var/required_progress = 100 + + ///Current progress towards evacuating safely via lifeboats + var/current_progress = 0 + + /// How much progress is required to early launch + var/early_launch_required_progress = 25 + + ///The estimated time left to get to the safe evacuation point + var/estimated_time_left = 0 + + ///Areas that are marked as having progress, assoc list that is progress_area = boolean, the boolean indicating if it was progressing or not on the last fire() + var/list/area/progress_areas = list() + + ///The areas that need cycled through currently + var/list/area/current_run = list() + + ///The progress of the current run that needs to be added at the end of the current run + var/current_run_progress_additive = 0 + + ///Holds what the current_run_progress_additive should be multiplied by at the end of the current run + var/current_run_progress_multiplicative = 1 + + ///Holds the progress change from last run + var/last_run_progress_change = 0 + + ///Holds the next % point progress should be announced, increments on itself + var/announce_checkpoint = 25 + + ///What stage of evacuation we are currently on + var/evac_status = EVACUATION_STATUS_NOT_INITIATED + + ///What stage of hijack are we currently on + var/hijack_status = HIJACK_OBJECTIVES_NOT_STARTED + + ///Whether or not evacuation has been disabled by admins + var/evac_admin_denied = FALSE + + /// If TRUE, self destruct has been unlocked and is possible with a hold of reactor + var/sd_unlocked = FALSE + + /// Admin var to manually prevent self destruct from occurring + var/admin_sd_blocked = FALSE + + /// Maximum amount of fusion generators that can be overloaded at once for a time benefit + var/maximum_overload_generators = 18 + + /// How many generators are currently overloaded + var/overloaded_generators = 0 + + /// How long the manual self destruct will take on the high end + var/sd_max_time = 15 MINUTES + + /// How long the manual self destruct will take on the low end + var/sd_min_time = 5 MINUTES + + /// How much time left until SD detonates + var/sd_time_remaining = 0 + + /// Roughly what % of the SD countdown remains + var/percent_completion_remaining = 100 + + /// If the engine room has been heated, occurs at 33% SD completion + var/engine_room_heated = FALSE + + /// If the engine room has been superheated, occurs at 66% SD completion + var/engine_room_superheated = FALSE + + /// If the self destruct has/is detonating + var/sd_detonated = FALSE + + /// If a generator has ever been overloaded in the past this round + var/generator_ever_overloaded = FALSE + + /// If ARES has announced the 50% point yet for SD + var/ares_sd_announced = FALSE + +/datum/controller/subsystem/hijack/Initialize(timeofday) + RegisterSignal(SSdcs, COMSIG_GLOB_GENERATOR_SET_OVERLOADING, PROC_REF(on_generator_overload)) + return SS_INIT_SUCCESS + +/datum/controller/subsystem/hijack/stat_entry(msg) + if(!SSticker?.mode?.is_in_endgame) + msg = " Not Hijack" + return ..() + + if(current_progress >= required_progress) + msg = " Complete" + return ..() + + msg = " Progress: [current_progress]% | Last run: [last_run_progress_change]" + return ..() + +/datum/controller/subsystem/hijack/fire(resumed = FALSE) + if(!SSticker?.mode?.is_in_endgame) + return + + if(hijack_status < HIJACK_OBJECTIVES_STARTED) + hijack_status = HIJACK_OBJECTIVES_STARTED + + if(current_progress >= required_progress) + if(hijack_status < HIJACK_OBJECTIVES_COMPLETE) + hijack_status = HIJACK_OBJECTIVES_COMPLETE + + if(sd_unlocked && overloaded_generators) + sd_time_remaining -= wait + if(!engine_room_heated && (sd_time_remaining <= (max((1 - round(overloaded_generators / maximum_overload_generators, 0.01)) * sd_max_time, sd_min_time) * 0.66))) + heat_engine_room() + + if(!ares_sd_announced && (sd_time_remaining <= (max((1 - round(overloaded_generators / maximum_overload_generators, 0.01)) * sd_max_time, sd_min_time) * 0.5))) + announce_sd_halfway() + + if(!engine_room_superheated && (sd_time_remaining <= (max((1 - round(overloaded_generators / maximum_overload_generators, 0.01)) * sd_max_time, sd_min_time) * 0.33))) + superheat_engine_room() + + if((sd_time_remaining <= 0) && !sd_detonated) + detonate_sd() + + return + + if(!resumed) + current_run = progress_areas.Copy() + + for(var/area/almayer/cycled_area as anything in current_run) + current_run -= cycled_area + + if(progress_areas[cycled_area] != cycled_area.power_equip) + progress_areas[cycled_area] = !progress_areas[cycled_area] + announce_area_power_change(cycled_area) + + if(progress_areas[cycled_area]) + switch(cycled_area.hijack_evacuation_type) + if(EVACUATION_TYPE_ADDITIVE) + current_run_progress_additive += cycled_area.hijack_evacuation_weight + if(EVACUATION_TYPE_MULTIPLICATIVE) + current_run_progress_multiplicative *= cycled_area.hijack_evacuation_weight + + if (MC_TICK_CHECK) + return + + last_run_progress_change = current_run_progress_additive * current_run_progress_multiplicative + current_progress += last_run_progress_change + + if(last_run_progress_change) + estimated_time_left = ((required_progress - current_progress) / last_run_progress_change) * wait + else + estimated_time_left = INFINITY + + if(current_progress >= announce_checkpoint) + announce_progress() + announce_checkpoint += initial(announce_checkpoint) + + current_run_progress_additive = 0 + current_run_progress_multiplicative = 1 + +///Called when the xeno dropship crashes into the Almayer and announces the current status of various objectives to marines +/datum/controller/subsystem/hijack/proc/announce_status_on_crash() + var/message = "" + + for(var/area/cycled_area as anything in progress_areas) + message += "[cycled_area] - [cycled_area.power_equip ? "Online" : "Offline"]\n" + progress_areas[cycled_area] = cycled_area.power_equip + + message += "\nDue to low orbit, extra fuel is required for non-surface evacuations.\nMaintain fueling functionality for optimal evacuation conditions." + + marine_announcement(message, HIJACK_ANNOUNCE) + +///Called when an area power status is changed to announce that it has been changed +/datum/controller/subsystem/hijack/proc/announce_area_power_change(area/changed_area) + var/message = "[changed_area] - [changed_area.power_equip ? "Online" : "Offline"]" + + marine_announcement(message, HIJACK_ANNOUNCE) + +///Called to announce to xenos the state of evacuation progression +/datum/controller/subsystem/hijack/proc/announce_progress() + var/announce = announce_checkpoint / initial(announce_checkpoint) + + var/marine_warning_areas = "" + var/xeno_warning_areas = "" + + for(var/area/cycled_area as anything in progress_areas) + if(cycled_area.power_equip) + xeno_warning_areas += "[cycled_area], " + continue + marine_warning_areas += "[cycled_area], " + + if(xeno_warning_areas) + xeno_warning_areas = copytext(xeno_warning_areas, 1, -2) + + if(marine_warning_areas) + marine_warning_areas = copytext(marine_warning_areas, 1, -2) + + var/datum/hive_status/hive + for(var/hivenumber in GLOB.hive_datum) + hive = GLOB.hive_datum[hivenumber] + if(!length(hive.totalXenos)) + continue + + switch(announce) + if(1) + xeno_announcement(SPAN_XENOANNOUNCE("The talls are a quarter of the way towards their goals. Disable the following areas: [xeno_warning_areas]"), hive.hivenumber, XENO_HIJACK_ANNOUNCE) + if(2) + xeno_announcement(SPAN_XENOANNOUNCE("The talls are half way towards their goals. Disable the following areas: [xeno_warning_areas]"), hive.hivenumber, XENO_HIJACK_ANNOUNCE) + if(3) + xeno_announcement(SPAN_XENOANNOUNCE("The talls are three quarters of the way towards their goals. Disable the following areas: [xeno_warning_areas]"), hive.hivenumber, XENO_HIJACK_ANNOUNCE) + if(4) + xeno_announcement(SPAN_XENOANNOUNCE("The talls have completed their goals!"), hive.hivenumber, XENO_HIJACK_ANNOUNCE) + + switch(announce) + if(1) + marine_announcement("Emergency fuel replenishment is at 25 percent. Lifeboat emergency early launch is now available.[marine_warning_areas ? "\nTo increase speed, restore power to the following areas: [marine_warning_areas]" : " All fueling areas operational."]", HIJACK_ANNOUNCE) + if(2) + marine_announcement("Emergency fuel replenishment is at 50 percent.[marine_warning_areas ? "\nTo increase speed, restore power to the following areas: [marine_warning_areas]" : " All fueling areas operational."]", HIJACK_ANNOUNCE) + if(3) + marine_announcement("Emergency fuel replenishment is at 75 percent.[marine_warning_areas ? "\nTo increase speed, restore power to the following areas: [marine_warning_areas]" : " All fueling areas operational."]", HIJACK_ANNOUNCE) + if(4) + marine_announcement("Emergency fuel replenishment is at 100 percent. Safe utilization of lifeboats and pods is now possible.", HIJACK_ANNOUNCE) + if(!admin_sd_blocked) + addtimer(CALLBACK(src, PROC_REF(unlock_self_destruct)), 8 SECONDS) + +/// Passes the ETA for status panels +/datum/controller/subsystem/hijack/proc/get_evac_eta() + switch(hijack_status) + if(HIJACK_OBJECTIVES_STARTED) + if(estimated_time_left == INFINITY) + return "Never" + return "[duration2text_sec(estimated_time_left)]" + + if(HIJACK_OBJECTIVES_COMPLETE) + return "Complete" + +/datum/controller/subsystem/hijack/proc/get_sd_eta() + if(!sd_time_remaining) + return "Complete" + + if(overloaded_generators <= 0) + return "Never" + + return "[duration2text_sec(sd_time_remaining)]" + +//~~~~~~~~~~~~~~~~~~~~~~~~ EVAC STUFF ~~~~~~~~~~~~~~~~~~~~~~~~// + +/// Initiates evacuation by announcing and then prepping all lifepods/lifeboats +/datum/controller/subsystem/hijack/proc/initiate_evacuation() + if(evac_status == EVACUATION_STATUS_NOT_INITIATED && !(evac_admin_denied & FLAGS_EVACUATION_DENY)) + evac_status = EVACUATION_STATUS_INITIATED + ai_announcement("Attention. Emergency. All personnel must evacuate immediately.", 'sound/AI/evacuate.ogg') + + for(var/obj/structure/machinery/status_display/cycled_status_display in machines) + if(is_mainship_level(cycled_status_display.z)) + cycled_status_display.set_picture("evac") + for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile) + shuttle.prepare_evac() + activate_lifeboats() + return TRUE + +/// Cancels evacuation, tells lifepods/lifeboats and status_displays +/datum/controller/subsystem/hijack/proc/cancel_evacuation() + if(evac_status == EVACUATION_STATUS_INITIATED) + evac_status = EVACUATION_STATUS_NOT_INITIATED + deactivate_lifeboats() + ai_announcement("Evacuation has been cancelled.", 'sound/AI/evacuate_cancelled.ogg') + + for(var/obj/structure/machinery/status_display/cycled_status_display in machines) + if(is_mainship_level(cycled_status_display.z)) + cycled_status_display.set_sec_level_picture() + + for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile) + shuttle.cancel_evac() + return TRUE + +/// Opens the lifeboat doors and gets them ready to launch +/datum/controller/subsystem/hijack/proc/activate_lifeboats() + for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks) + var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked() + if(lifeboat && lifeboat.available) + lifeboat.status = LIFEBOAT_ACTIVE + lifeboat_dock.open_dock() + +/// Turns off ability to manually take off lifeboats +/datum/controller/subsystem/hijack/proc/deactivate_lifeboats() + for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks) + var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked() + if(lifeboat && lifeboat.available) + lifeboat.status = LIFEBOAT_INACTIVE + + +/// Once refueling is done, marines can optionally hold SD for a time for a stalemate instead of a xeno minor +/datum/controller/subsystem/hijack/proc/unlock_self_destruct() + sd_time_remaining = sd_max_time + sd_unlocked = TRUE + marine_announcement("Fuel reserves full. Manual detonation of fuel reserves by overloading the on-board fusion reactors now possible.", HIJACK_ANNOUNCE) + +/datum/controller/subsystem/hijack/proc/on_generator_overload(obj/structure/machinery/power/fusion_engine/source, new_overloading) + SIGNAL_HANDLER + + if(!generator_ever_overloaded) + generator_ever_overloaded = TRUE + var/datum/hive_status/hive + for(var/hivenumber in GLOB.hive_datum) + hive = GLOB.hive_datum[hivenumber] + if(!length(hive.totalXenos)) + continue + + xeno_announcement(SPAN_XENOANNOUNCE("The talls may be attempting to take their ship down with them in Engineering, stop them!"), hive.hivenumber, XENO_HIJACK_ANNOUNCE) + + adjust_generator_overload_count(new_overloading ? 1 : -1) + +/datum/controller/subsystem/hijack/proc/adjust_generator_overload_count(amount = 1) + var/generator_overload_percent = round(overloaded_generators / maximum_overload_generators, 0.01) + var/old_required_time = sd_min_time + ((1 - generator_overload_percent) * (sd_max_time - sd_min_time)) + percent_completion_remaining = sd_time_remaining / old_required_time + overloaded_generators = clamp(overloaded_generators + amount, 0, maximum_overload_generators) + generator_overload_percent = round(overloaded_generators / maximum_overload_generators, 0.01) + var/new_required_time = sd_min_time + ((1 - generator_overload_percent) * (sd_max_time - sd_min_time)) + sd_time_remaining = percent_completion_remaining * new_required_time + +/datum/controller/subsystem/hijack/proc/heat_engine_room() + engine_room_heated = TRUE + var/area/engine_room = GLOB.areas_by_type[/area/almayer/engineering/engine_core] + engine_room.firealert() + engine_room.temperature = T90C + for(var/mob/current_mob as anything in GLOB.mob_list) + var/area/mob_area = get_area(current_mob) + if(istype(mob_area, /area/almayer/engineering/engine_core)) + to_chat(current_mob, SPAN_BOLDWARNING("You feel the heat of the room increase as the fusion engines whirr louder.")) + +/datum/controller/subsystem/hijack/proc/superheat_engine_room() + engine_room_superheated = TRUE + var/area/engine_room = GLOB.areas_by_type[/area/almayer/engineering/engine_core] + engine_room.firealert() + engine_room.temperature = T120C //slowly deals burn at this temp + for(var/mob/current_mob as anything in GLOB.mob_list) + var/area/mob_area = get_area(current_mob) + if(istype(mob_area, /area/almayer/engineering/engine_core)) + to_chat(current_mob, SPAN_BOLDWARNING("The room feels incredibly hot, you can't take much more of this!")) + +/datum/controller/subsystem/hijack/proc/announce_sd_halfway() + ares_sd_announced = TRUE + marine_announcement("ALERT: Fusion reactor meltdown has reached fifty percent.", HIJACK_ANNOUNCE) + +/datum/controller/subsystem/hijack/proc/detonate_sd() + set waitfor = FALSE + sd_detonated = TRUE + var/creak_picked = pick('sound/effects/creak1.ogg', 'sound/effects/creak2.ogg', 'sound/effects/creak3.ogg') + for(var/mob/current_mob as anything in GLOB.mob_list) + var/turf/current_turf = get_turf(current_mob) + if(!current_mob?.loc || !current_mob.client || !current_turf || !is_mainship_level(current_turf.z)) + continue + + to_chat(current_mob, SPAN_BOLDWARNING("The ship's deck worryingly creaks underneath you.")) + playsound_client(current_mob.client, creak_picked, vol = 50) + + sleep(7 SECONDS) + shakeship(2, 10, TRUE) + + marine_announcement("ALERT: Fusion reactors dangerously overloaded. Runaway meltdown in reactor core imminent.", HIJACK_ANNOUNCE) + sleep(5 SECONDS) + + var/sound_picked = pick('sound/theme/nuclear_detonation1.ogg','sound/theme/nuclear_detonation2.ogg') + for(var/client/player as anything in GLOB.clients) + playsound_client(player, sound_picked, 90) + + var/list/alive_mobs = list() //Everyone who will be destroyed on the zlevel(s). + var/list/dead_mobs = list() //Everyone who only needs to see the cinematic. + for(var/mob/current_mob as anything in GLOB.mob_list) //This only does something cool for the people about to die, but should prove pretty interesting. + var/turf/current_turf = get_turf(current_mob) + if(!current_mob?.loc || !current_turf) + continue + + if(current_mob.stat == DEAD) + dead_mobs |= current_mob + continue + + if(is_mainship_level(current_turf.z)) + alive_mobs |= current_mob + shake_camera(current_mob, 110, 4) + + + sleep(10 SECONDS) + /*Hardcoded for now, since this was never really used for anything else. + Would ideally use a better system for showing cutscenes.*/ + var/atom/movable/screen/cinematic/explosion/explosive_cinematic = new() + + for(var/mob/current_mob as anything in (alive_mobs + dead_mobs)) + if(current_mob?.loc && current_mob.client) + current_mob.client.add_to_screen(explosive_cinematic) //They may have disconnected in the mean time. + + sleep(1.5 SECONDS) //Extra 1.5 seconds to look at the ship. + flick("intro_nuke", explosive_cinematic) + + sleep(3.5 SECONDS) + for(var/mob/current_mob as anything in alive_mobs) + var/turf/current_mob_turf = get_turf(current_mob) + if(!current_mob?.loc || !current_mob_turf) //Who knows, maybe they escaped, or don't exist anymore. + continue + + if(is_mainship_level(current_mob_turf.z)) + if(istype(current_mob.loc, /obj/structure/closet/secure_closet/freezer/fridge)) + continue + + current_mob.death(create_cause_data("nuclear explosion")) + else + current_mob.client.remove_from_screen(explosive_cinematic) //those who managed to escape the z level at last second shouldn't have their view obstructed. + + flick("ship_destroyed", explosive_cinematic) + explosive_cinematic.icon_state = "summary_destroyed" + + for(var/client/player as anything in GLOB.clients) + playsound_client(player, 'sound/effects/explosionfar.ogg', 90) + + + sleep(0.5 SECONDS) + if(SSticker.mode) + SSticker.mode.check_win() + + if(!SSticker.mode) //Just a safety, just in case a mode isn't running, somehow. + to_world(SPAN_ROUNDBODY("Resetting in 30 seconds!")) + sleep(30 SECONDS) + log_game("Rebooting due to nuclear detonation.") + world.Reboot() diff --git a/code/controllers/subsystem/htmlui.dm b/code/controllers/subsystem/htmlui.dm deleted file mode 100644 index 5dc885abc625..000000000000 --- a/code/controllers/subsystem/htmlui.dm +++ /dev/null @@ -1,57 +0,0 @@ -// What in the name of god is this? -// You'd think it'd be some form of process for the HTML interface module. -// But it isn't? -// It's some form of proc queue but ??? -// Does anything even *use* this? - -SUBSYSTEM_DEF(html_ui) - name = "HTMLUI" - wait = 1.7 SECONDS - flags = SS_NO_INIT - runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY - var/list/update = list() - -/datum/controller/subsystem/html_ui/fire(resumed = FALSE) - if (update.len) - var/list/L = list() - var/key - - for (var/datum/procqueue_item/item in update) - key = "[item.ref]_[item.procname]" - - if (item.args) - key += "(" - var/first = 1 - for (var/a in item.args) - if (!first) - key += "," - key += "[a]" - first = 0 - key += ")" - - if (!(key in L)) - if (item.args) - call(item.ref, item.procname)(arglist(item.args)) - else - call(item.ref, item.procname)() - - L.Add(key) - - update.Cut() - - -/datum/controller/subsystem/html_ui/proc/queue(ref, procname, ...) - var/datum/procqueue_item/item = new - item.ref = ref - item.procname = procname - - if (args.len > 2) - item.args = args.Copy(3) - - update.Insert(1, item) - - -/datum/procqueue_item - var/ref - var/procname - var/list/args diff --git a/code/controllers/subsystem/inactivity.dm b/code/controllers/subsystem/inactivity.dm index 5edd4e8c5294..6b8542444040 100644 --- a/code/controllers/subsystem/inactivity.dm +++ b/code/controllers/subsystem/inactivity.dm @@ -17,7 +17,7 @@ SUBSYSTEM_DEF(inactivity) return for(var/client/current as anything in GLOB.clients) - if(current.admin_holder && current.admin_holder.rights & R_ADMIN) //Skip admins. + if(current.admin_holder && current.admin_holder.rights & R_MOD) //Skip admins. continue if(current.is_afk(INACTIVITY_KICK)) if(!istype(current.mob, /mob/dead)) diff --git a/code/controllers/subsystem/interior.dm b/code/controllers/subsystem/interior.dm index 389e95fe6022..8fb7ffbfeee7 100644 --- a/code/controllers/subsystem/interior.dm +++ b/code/controllers/subsystem/interior.dm @@ -42,7 +42,7 @@ SUBSYSTEM_DEF(interior) continue if(x >= bounds[1].x && x <= bounds[2].x && y >= bounds[1].y && y <= bounds[2].y) return current_interior - return FALSE + return /// Checks if an atom is in an interior /datum/controller/subsystem/interior/proc/in_interior(loc) @@ -51,7 +51,7 @@ SUBSYSTEM_DEF(interior) if(!isturf(loc)) loc = get_turf(loc) - var/datum/turf_reservation/interior/reservation = SSmapping.used_turfs[loc] + var/datum/weakref/reservation = SSmapping.used_turfs[loc] if(!istype(reservation)) return FALSE diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 6f0f060305b2..913e5dcd50d3 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -6,10 +6,13 @@ SUBSYSTEM_DEF(mapping) var/list/datum/map_config/configs var/list/datum/map_config/next_map_configs + ///Name of all maps var/list/map_templates = list() - + ///Name of all shuttles var/list/shuttle_templates = list() var/list/all_shuttle_templates = list() + ///map_id of all tents + var/list/tent_type_templates = list() var/list/areas_in_z = list() @@ -201,6 +204,7 @@ SUBSYSTEM_DEF(mapping) map_templates[T.name] = T preloadShuttleTemplates() + preload_tent_templates() /proc/generateMapList(filename) . = list() @@ -242,6 +246,11 @@ SUBSYSTEM_DEF(mapping) all_shuttle_templates[item] = S map_templates[S.shuttle_id] = S +/datum/controller/subsystem/mapping/proc/preload_tent_templates() + for(var/template in subtypesof(/datum/map_template/tent)) + var/datum/map_template/tent/new_tent = new template() + tent_type_templates[new_tent.map_id] = new_tent + /datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override) UNTIL(initialized && !clearing_reserved_turfs) var/datum/turf_reservation/reserve = new type diff --git a/code/controllers/subsystem/midi.dm b/code/controllers/subsystem/midi.dm deleted file mode 100644 index 158d67cf25ac..000000000000 --- a/code/controllers/subsystem/midi.dm +++ /dev/null @@ -1,45 +0,0 @@ -/datum/midi_record - var/target - var/midi - -SUBSYSTEM_DEF(midi) - name = "Midi" - wait = 2 SECONDS - flags = SS_NO_INIT|SS_BACKGROUND - runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY - priority = SS_PRIORITY_MIDI - - var/list/datum/midi_record/prepped_midis = list() - - var/list/datum/midi_record/currentrun = list() - - -/datum/controller/subsystem/midi/stat_entry(msg) - msg = "MR:[prepped_midis.len]" - return ..() - - -/datum/controller/subsystem/midi/fire(resumed = FALSE) - if (!resumed) - currentrun = prepped_midis - prepped_midis = list() - - while (currentrun.len) - var/datum/midi_record/E = currentrun[currentrun.len] - currentrun.len-- - - if (!E) - continue - - E.target << E.midi - - if (MC_TICK_CHECK) - return - -/datum/controller/subsystem/midi/proc/queue(target, midi) - if(!prepped_midis) - prepped_midis = list() - var/datum/midi_record/MR = new() - MR.target = target - MR.midi = midi - prepped_midis.Add(MR) diff --git a/code/controllers/subsystem/minimap.dm b/code/controllers/subsystem/minimap.dm index 6f5b9303a91f..d28fe916291a 100644 --- a/code/controllers/subsystem/minimap.dm +++ b/code/controllers/subsystem/minimap.dm @@ -256,8 +256,6 @@ SUBSYSTEM_DEF(minimaps) removal_cbs[target] = CALLBACK(src, PROC_REF(removeimage), blip, target) RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(remove_marker)) - - /** * removes an image from raw tracked lists, invoked by callback */ @@ -322,7 +320,7 @@ SUBSYSTEM_DEF(minimaps) minimaps_by_z["[z_level]"].images_assoc["[flag]"] -= source /** - * Fetches a /atom/movable/screen/minimap instance or creates on if none exists + * Fetches a /atom/movable/screen/minimap instance or creates one if none exists * Note this does not destroy them when the map is unused, might be a potential thing to do? * Arguments: * * zlevel: zlevel to fetch map for @@ -338,6 +336,170 @@ SUBSYSTEM_DEF(minimaps) hashed_minimaps[hash] = map return map +/** + * Fetches the datum containing an announced flattend map png reference. + * + * Arguments: + * * faction: FACTION_MARINE or XENO_HIVE_NORMAL + */ +/proc/get_tacmap_data_png(faction) + var/list/map_list + + if(faction == FACTION_MARINE) + map_list = GLOB.uscm_flat_tacmap_data + else if(faction == XENO_HIVE_NORMAL) + map_list = GLOB.xeno_flat_tacmap_data + else + return null + + var/map_length = length(map_list) + + if(map_length == 0) + return null + + return map_list[map_length] + +/** + * Fetches the datum containing the latest unannounced flattend map png reference. + * + * Arguments: + * * faction: FACTION_MARINE or XENO_HIVE_NORMAL + */ +/proc/get_unannounced_tacmap_data_png(faction) + if(faction == FACTION_MARINE) + return GLOB.uscm_unannounced_map + else if(faction == XENO_HIVE_NORMAL) + return GLOB.xeno_unannounced_map + + return null + +/** + * Fetches the last set of svg coordinates for the tacmap drawing. + * + * Arguments: + * * faction: which faction get the map for: FACTION_MARINE or XENO_HIVE_NORMAL + */ +/proc/get_tacmap_data_svg(faction) + var/list/map_list + + if(faction == FACTION_MARINE) + map_list = GLOB.uscm_svg_tacmap_data + else if(faction == XENO_HIVE_NORMAL) + map_list = GLOB.xeno_svg_tacmap_data + else + return null + + var/map_length = length(map_list) + + if(map_length == 0) + return null + + return map_list[map_length] + +/** + * Re-sends relevant flattened tacmaps to a single client. + * + * Arguments: + * * user: The mob that is either an observer, marine, or xeno + */ +/proc/resend_current_map_png(mob/user) + if(!user.client) + return + + var/is_observer = user.faction == FACTION_NEUTRAL && isobserver(user) + if(is_observer || user.faction == FACTION_MARINE) + // Send marine maps + var/datum/flattened_tacmap/latest = get_tacmap_data_png(FACTION_MARINE) + if(latest) + SSassets.transport.send_assets(user.client, latest.asset_key) + var/datum/flattened_tacmap/unannounced = get_unannounced_tacmap_data_png(FACTION_MARINE) + if(unannounced && (!latest || latest.asset_key != unannounced.asset_key)) + SSassets.transport.send_assets(user.client, unannounced.asset_key) + + var/mob/living/carbon/xenomorph/xeno = user + if(is_observer || istype(xeno) && xeno.hivenumber == XENO_HIVE_NORMAL) + // Send xeno maps + var/datum/flattened_tacmap/latest = get_tacmap_data_png(XENO_HIVE_NORMAL) + if(latest) + SSassets.transport.send_assets(user.client, latest.asset_key) + var/datum/flattened_tacmap/unannounced = get_unannounced_tacmap_data_png(XENO_HIVE_NORMAL) + if(unannounced && (!latest || latest.asset_key != unannounced.asset_key)) + SSassets.transport.send_assets(user.client, unannounced.asset_key) + +/** + * Flattens the current map and then distributes it for the specified faction as an unannounced map. + * + * Arguments: + * * faction: Which faction to distribute the map to: FACTION_MARINE or XENO_HIVE_NORMAL + * Return: + * * Returns a boolean value, TRUE if the operation was successful, FALSE if it was not (on cooldown generally). + */ +/datum/tacmap/drawing/proc/distribute_current_map_png(faction) + if(faction == FACTION_MARINE) + if(!COOLDOWN_FINISHED(GLOB, uscm_flatten_map_icon_cooldown)) + return FALSE + COOLDOWN_START(GLOB, uscm_flatten_map_icon_cooldown, flatten_map_cooldown_time) + else if(faction == XENO_HIVE_NORMAL) + if(!COOLDOWN_FINISHED(GLOB, xeno_flatten_map_icon_cooldown)) + return FALSE + COOLDOWN_START(GLOB, xeno_flatten_map_icon_cooldown, flatten_map_cooldown_time) + else + return FALSE + + var/icon/flat_map = getFlatIcon(map_holder.map, appearance_flags = TRUE) + if(!flat_map) + to_chat(usr, SPAN_WARNING("A critical error has occurred! Contact a coder.")) // tf2heavy: "Oh, this is bad!" + return FALSE + + // Send to only relevant clients + var/list/faction_clients = list() + for(var/client/client as anything in GLOB.clients) + if(!client || !client.mob) + continue + var/mob/client_mob = client.mob + if(client_mob.faction == faction) + faction_clients += client + else if(client_mob.faction == FACTION_NEUTRAL && isobserver(client_mob)) + faction_clients += client + else if(isxeno(client_mob)) + var/mob/living/carbon/xenomorph/xeno = client_mob + if(xeno.hivenumber == faction) + faction_clients += client + + // This may be unnecessary to do this way if the asset url is always the same as the lookup key + var/flat_tacmap_key = icon2html(flat_map, faction_clients, keyonly = TRUE) + if(!flat_tacmap_key) + to_chat(usr, SPAN_WARNING("A critical error has occurred! Contact a coder.")) + return FALSE + var/flat_tacmap_png = SSassets.transport.get_asset_url(flat_tacmap_key) + var/datum/flattened_tacmap/new_flat = new(flat_tacmap_png, flat_tacmap_key) + + if(faction == FACTION_MARINE) + GLOB.uscm_unannounced_map = new_flat + else //if(faction == XENO_HIVE_NORMAL) + GLOB.xeno_unannounced_map = new_flat + + return TRUE + +/** + * Globally stores svg coords for a given faction. + * + * Arguments: + * * faction: which faction to save the data for: FACTION_MARINE or XENO_HIVE_NORMAL + * * svg_coords: an array of coordinates corresponding to an svg. + * * ckey: the ckey of the user who submitted this + */ +/datum/tacmap/drawing/proc/store_current_svg_coords(faction, svg_coords, ckey) + var/datum/svg_overlay/svg_store_overlay = new(svg_coords, ckey) + + if(faction == FACTION_MARINE) + GLOB.uscm_svg_tacmap_data += svg_store_overlay + else if(faction == XENO_HIVE_NORMAL) + GLOB.xeno_svg_tacmap_data += svg_store_overlay + else + qdel(svg_store_overlay) + debug_log("SVG coordinates for [faction] are not implemented!") + /datum/controller/subsystem/minimaps/proc/fetch_tacmap_datum(zlevel, flags) var/hash = "[zlevel]-[flags]" if(hashed_tacmaps[hash]) @@ -442,7 +604,7 @@ SUBSYSTEM_DEF(minimaps) marker_flags = MINIMAP_FLAG_USCM /datum/action/minimap/observer - minimap_flags = MINIMAP_FLAG_XENO|MINIMAP_FLAG_USCM|MINIMAP_FLAG_UPP|MINIMAP_FLAG_CLF|MINIMAP_FLAG_UPP + minimap_flags = MINIMAP_FLAG_ALL marker_flags = NONE hidden = TRUE @@ -452,17 +614,61 @@ SUBSYSTEM_DEF(minimaps) var/targeted_ztrait = ZTRAIT_GROUND var/atom/owner + /// tacmap holder for holding the minimap var/datum/tacmap_holder/map_holder +/datum/tacmap/drawing + /// A url that will point to the wiki map for the current map as a fall back image + var/static/wiki_map_fallback + + /// color selection for the tactical map canvas, defaults to black. + var/toolbar_color_selection = "black" + var/toolbar_updated_selection = "black" + + var/canvas_cooldown_time = 4 MINUTES + var/flatten_map_cooldown_time = 3 MINUTES + + /// boolean value to keep track if the canvas has been updated or not, the value is used in tgui state. + var/updated_canvas = FALSE + /// current flattend map + var/datum/flattened_tacmap/new_current_map + /// previous flattened map + var/datum/flattened_tacmap/old_map + /// current svg + var/datum/svg_overlay/current_svg + + var/action_queue_change = 0 + + /// The last time the map has been flattened - used as a key to trick react into updating the canvas + var/last_update_time = 0 + /// A temporary lock out time before we can open the new canvas tab to allow the tacmap time to fire + var/tacmap_ready_time = 0 + /datum/tacmap/New(atom/source, minimap_type) allowed_flags = minimap_type owner = source +/datum/tacmap/drawing/status_tab_view/New() + var/datum/tacmap/drawing/status_tab_view/uscm_tacmap + allowed_flags = MINIMAP_FLAG_USCM + owner = uscm_tacmap + +/datum/tacmap/drawing/status_tab_view/xeno/New() + var/datum/tacmap/drawing/status_tab_view/xeno/xeno_tacmap + allowed_flags = MINIMAP_FLAG_XENO + owner = xeno_tacmap + /datum/tacmap/Destroy() map_holder = null owner = null return ..() +/datum/tacmap/drawing/Destroy() + new_current_map = null + old_map = null + current_svg = null + return ..() + /datum/tacmap/tgui_interact(mob/user, datum/tgui/ui) if(!map_holder) var/level = SSmapping.levels_by_trait(targeted_ztrait) @@ -476,11 +682,216 @@ SUBSYSTEM_DEF(minimaps) ui = new(user, src, "TacticalMap") ui.open() +/datum/tacmap/drawing/tgui_interact(mob/user, datum/tgui/ui) + var/mob/living/carbon/xenomorph/xeno = user + var/is_xeno = istype(xeno) + var/faction = is_xeno ? xeno.hivenumber : user.faction + if(faction == FACTION_NEUTRAL && isobserver(user)) + faction = allowed_flags == MINIMAP_FLAG_XENO ? XENO_HIVE_NORMAL : FACTION_MARINE + + new_current_map = get_unannounced_tacmap_data_png(faction) + old_map = get_tacmap_data_png(faction) + current_svg = get_tacmap_data_svg(faction) + + var/use_live_map = faction == FACTION_MARINE && skillcheck(user, SKILL_LEADERSHIP, SKILL_LEAD_EXPERT) || is_xeno + + if(use_live_map && !map_holder) + var/level = SSmapping.levels_by_trait(targeted_ztrait) + if(!level[1]) + return + map_holder = SSminimaps.fetch_tacmap_datum(level[1], allowed_flags) + + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + if(!wiki_map_fallback) + var/wiki_url = CONFIG_GET(string/wikiurl) + var/obj/item/map/current_map/new_map = new + if(wiki_url && new_map.html_link) + wiki_map_fallback ="[wiki_url]/[new_map.html_link]" + else + debug_log("Failed to determine fallback wiki map! Attempted '[wiki_url]/[new_map.html_link]'") + qdel(new_map) + + // Ensure we actually have the map image sent + resend_current_map_png(user) + + if(use_live_map) + tacmap_ready_time = SSminimaps.next_fire + 2 SECONDS + addtimer(CALLBACK(src, PROC_REF(on_tacmap_fire), faction), SSminimaps.next_fire - world.time + 1 SECONDS) + user.client.register_map_obj(map_holder.map) + + ui = new(user, src, "TacticalMap") + ui.open() + +/datum/tacmap/drawing/ui_data(mob/user) + var/list/data = list() + + data["newCanvasFlatImage"] = new_current_map?.flat_tacmap + data["oldCanvasFlatImage"] = old_map?.flat_tacmap + data["svgData"] = current_svg?.svg_data + + data["actionQueueChange"] = action_queue_change + + data["toolbarColorSelection"] = toolbar_color_selection + data["toolbarUpdatedSelection"] = toolbar_updated_selection + + if(isxeno(user)) + data["canvasCooldown"] = max(GLOB.xeno_canvas_cooldown - world.time, 0) + else + data["canvasCooldown"] = max(GLOB.uscm_canvas_cooldown - world.time, 0) + + data["nextCanvasTime"] = canvas_cooldown_time + data["updatedCanvas"] = updated_canvas + + data["lastUpdateTime"] = last_update_time + data["tacmapReady"] = world.time > tacmap_ready_time + + return data + /datum/tacmap/ui_static_data(mob/user) var/list/data = list() - data["mapRef"] = map_holder.map_ref + data["mapRef"] = map_holder?.map_ref + data["canDraw"] = FALSE + data["canViewTacmap"] = TRUE + data["canViewCanvas"] = FALSE + data["isXeno"] = FALSE + return data +/datum/tacmap/drawing/ui_static_data(mob/user) + var/list/data = list() + + data["mapRef"] = map_holder?.map_ref + data["canDraw"] = FALSE + data["mapFallback"] = wiki_map_fallback + + var/mob/living/carbon/xenomorph/xeno = user + var/is_xeno = istype(xeno) + var/faction = is_xeno ? xeno.hivenumber : user.faction + + data["isXeno"] = is_xeno + data["canViewTacmap"] = is_xeno + data["canViewCanvas"] = faction == FACTION_MARINE || faction == XENO_HIVE_NORMAL + + if(faction == FACTION_MARINE && skillcheck(user, SKILL_LEADERSHIP, SKILL_LEAD_EXPERT) || faction == XENO_HIVE_NORMAL && isqueen(user)) + data["canDraw"] = TRUE + data["canViewTacmap"] = TRUE + + return data + +/datum/tacmap/drawing/status_tab_view/ui_static_data(mob/user) + var/list/data = list() + data["mapFallback"] = wiki_map_fallback + data["canDraw"] = FALSE + data["canViewTacmap"] = FALSE + data["canViewCanvas"] = TRUE + data["isXeno"] = FALSE + + return data + +/datum/tacmap/drawing/status_tab_view/xeno/ui_static_data(mob/user) + var/list/data = list() + data["mapFallback"] = wiki_map_fallback + data["canDraw"] = FALSE + data["canViewTacmap"] = FALSE + data["canViewCanvas"] = TRUE + data["isXeno"] = TRUE + + return data + +/datum/tacmap/drawing/ui_close(mob/user) + . = ..() + action_queue_change = 0 + updated_canvas = FALSE + toolbar_color_selection = "black" + toolbar_updated_selection = "black" + +/datum/tacmap/drawing/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + var/mob/user = ui.user + var/mob/living/carbon/xenomorph/xeno = user + var/faction = istype(xeno) ? xeno.hivenumber : user.faction + if(faction == FACTION_NEUTRAL && isobserver(user)) + faction = allowed_flags == MINIMAP_FLAG_XENO ? XENO_HIVE_NORMAL : FACTION_MARINE + + switch (action) + if ("menuSelect") + if(params["selection"] != "new canvas") + if(updated_canvas) + updated_canvas = FALSE + toolbar_updated_selection = toolbar_color_selection // doing this if it == canvas can cause a latency issue with the stroke. + else + distribute_current_map_png(faction) + last_update_time = world.time + // An attempt to get the image to load on first try in the interface, but doesn't seem always reliable + + new_current_map = get_unannounced_tacmap_data_png(faction) + old_map = get_tacmap_data_png(faction) + current_svg = get_tacmap_data_svg(faction) + + if ("updateCanvas") + // forces state change, this will export the svg. + toolbar_updated_selection = "export" + updated_canvas = TRUE + action_queue_change += 1 + + if ("clearCanvas") + toolbar_updated_selection = "clear" + updated_canvas = FALSE + action_queue_change += 1 + + if ("undoChange") + toolbar_updated_selection = "undo" + updated_canvas = FALSE + action_queue_change += 1 + + if ("selectColor") + var/newColor = params["color"] + if(newColor) + toolbar_color_selection = newColor + toolbar_updated_selection = newColor + action_queue_change += 1 + + if ("onDraw") + updated_canvas = FALSE + + if ("selectAnnouncement") + if(!istype(params["image"], /list)) // potentially very serious? + return FALSE + + if(faction == FACTION_MARINE) + GLOB.uscm_flat_tacmap_data += new_current_map + else if(faction == XENO_HIVE_NORMAL) + GLOB.xeno_flat_tacmap_data += new_current_map + + store_current_svg_coords(faction, params["image"], user) + current_svg = get_tacmap_data_svg(faction) + old_map = get_tacmap_data_png(faction) + + if(faction == FACTION_MARINE) + COOLDOWN_START(GLOB, uscm_canvas_cooldown, canvas_cooldown_time) + var/mob/living/carbon/human/human_leader = user + for(var/datum/squad/current_squad in RoleAuthority.squads) + current_squad.send_maptext("Tactical map update in progress...", "Tactical Map:") + human_leader.visible_message(SPAN_BOLDNOTICE("Tactical map update in progress...")) + playsound_client(human_leader.client, "sound/effects/sos-morse-code.ogg") + notify_ghosts(header = "Tactical Map", message = "The USCM tactical map has been updated.", ghost_sound = "sound/effects/sos-morse-code.ogg", notify_volume = 80, action = NOTIFY_USCM_TACMAP, enter_link = "uscm_tacmap=1", enter_text = "View", source = owner) + + else if(faction == XENO_HIVE_NORMAL) + var/mutable_appearance/appearance = mutable_appearance(icon('icons/mob/hud/actions_xeno.dmi'), "toggle_queen_zoom") + COOLDOWN_START(GLOB, xeno_canvas_cooldown, canvas_cooldown_time) + xeno_maptext("The Queen has updated your hive mind map", "You sense something unusual...", faction) + notify_ghosts(header = "Tactical Map", message = "The Xenomorph tactical map has been updated.", ghost_sound = "sound/voice/alien_distantroar_3.ogg", notify_volume = 50, action = NOTIFY_XENO_TACMAP, enter_link = "xeno_tacmap=1", enter_text = "View", source = user, alert_overlay = appearance) + + toolbar_updated_selection = toolbar_color_selection + message_admins("[key_name(user)] has updated the tactical map for [faction].") + updated_canvas = FALSE + + return TRUE + /datum/tacmap/ui_status(mob/user) if(!(isatom(owner))) return UI_INTERACTIVE @@ -493,7 +904,7 @@ SUBSYSTEM_DEF(minimaps) else return UI_CLOSE -/datum/tacmap/xeno/ui_status(mob/user) +/datum/tacmap/drawing/xeno/ui_status(mob/user) if(!isxeno(user)) return UI_CLOSE @@ -516,3 +927,71 @@ SUBSYSTEM_DEF(minimaps) /datum/tacmap_holder/Destroy() map = null return ..() + +/datum/flattened_tacmap + var/flat_tacmap + var/asset_key + var/time + +/datum/flattened_tacmap/New(flat_tacmap, asset_key) + src.flat_tacmap = flat_tacmap + src.asset_key = asset_key + src.time = time_stamp() + +/datum/svg_overlay + var/svg_data + var/ckey + var/name + var/time + +/datum/svg_overlay/New(svg_data, mob/user) + src.svg_data = svg_data + src.ckey = user?.persistent_ckey + src.name = user?.real_name + src.time = time_stamp() + +/// Callback when timer indicates the tacmap is flattenable now +/datum/tacmap/drawing/proc/on_tacmap_fire(faction) + distribute_current_map_png(faction) + last_update_time = world.time + +/// Gets the MINIMAP_FLAG for the provided faction or hivenumber if one exists +/proc/get_minimap_flag_for_faction(faction) + switch(faction) + if(XENO_HIVE_NORMAL) + return MINIMAP_FLAG_XENO + if(FACTION_MARINE) + return MINIMAP_FLAG_USCM + if(FACTION_UPP) + return MINIMAP_FLAG_UPP + if(FACTION_WY) + return MINIMAP_FLAG_USCM + if(FACTION_CLF) + return MINIMAP_FLAG_CLF + if(FACTION_PMC) + return MINIMAP_FLAG_PMC + if(FACTION_YAUTJA) + return MINIMAP_FLAG_YAUTJA + if(XENO_HIVE_CORRUPTED) + return MINIMAP_FLAG_XENO_CORRUPTED + if(XENO_HIVE_ALPHA) + return MINIMAP_FLAG_XENO_ALPHA + if(XENO_HIVE_BRAVO) + return MINIMAP_FLAG_XENO_BRAVO + if(XENO_HIVE_CHARLIE) + return MINIMAP_FLAG_XENO_CHARLIE + if(XENO_HIVE_DELTA) + return MINIMAP_FLAG_XENO_DELTA + if(XENO_HIVE_FERAL) + return MINIMAP_FLAG_XENO_FERAL + if(XENO_HIVE_TAMED) + return MINIMAP_FLAG_XENO_TAMED + if(XENO_HIVE_MUTATED) + return MINIMAP_FLAG_XENO_MUTATED + if(XENO_HIVE_FORSAKEN) + return MINIMAP_FLAG_XENO_FORSAKEN + if(XENO_HIVE_YAUTJA) + return MINIMAP_FLAG_YAUTJA + if(XENO_HIVE_RENEGADE) + return MINIMAP_FLAG_XENO_RENEGADE + return 0 diff --git a/code/controllers/subsystem/processing/defprocess.dm b/code/controllers/subsystem/processing/defprocess.dm new file mode 100644 index 000000000000..3701a0617a7a --- /dev/null +++ b/code/controllers/subsystem/processing/defprocess.dm @@ -0,0 +1,5 @@ +PROCESSING_SUBSYSTEM_DEF(defprocess) + name = "Defenses Processing" + priority = SS_PRIORITY_DEFENSES + flags = SS_NO_INIT + wait = 0.7 SECONDS diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm new file mode 100644 index 000000000000..f9ba79046c2c --- /dev/null +++ b/code/controllers/subsystem/profiler.dm @@ -0,0 +1,74 @@ +#define PROFILER_FILENAME "profiler.json" +#define SENDMAPS_FILENAME "sendmaps.json" + +SUBSYSTEM_DEF(profiler) + name = "Profiler" + init_order = SS_INIT_PROFILER + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + wait = 300 SECONDS + var/fetch_cost = 0 + var/write_cost = 0 + +/datum/controller/subsystem/profiler/stat_entry(msg) + msg += "F:[round(fetch_cost,1)]ms" + msg += "|W:[round(write_cost,1)]ms" + return msg + +/datum/controller/subsystem/profiler/Initialize() + if(CONFIG_GET(flag/auto_profile)) + StartProfiling() + else + StopProfiling() //Stop the early start profiler + return SS_INIT_SUCCESS + +/datum/controller/subsystem/profiler/OnConfigLoad() + if(CONFIG_GET(flag/auto_profile)) + StartProfiling() + can_fire = TRUE + else + StopProfiling() + can_fire = FALSE + +/datum/controller/subsystem/profiler/fire() + DumpFile() + +/datum/controller/subsystem/profiler/Shutdown() + if(CONFIG_GET(flag/auto_profile)) + DumpFile(allow_yield = FALSE) + world.Profile(PROFILE_CLEAR, type = "sendmaps") + return ..() + +/datum/controller/subsystem/profiler/proc/StartProfiling() + world.Profile(PROFILE_START) + world.Profile(PROFILE_START, type = "sendmaps") + +/datum/controller/subsystem/profiler/proc/StopProfiling() + world.Profile(PROFILE_STOP) + world.Profile(PROFILE_STOP, type = "sendmaps") + +/datum/controller/subsystem/profiler/proc/DumpFile(allow_yield = TRUE) + var/timer = TICK_USAGE_REAL + var/current_profile_data = world.Profile(PROFILE_REFRESH, format = "json") + var/current_sendmaps_data = world.Profile(PROFILE_REFRESH, type = "sendmaps", format="json") + fetch_cost = MC_AVERAGE(fetch_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + if(allow_yield) + CHECK_TICK + + if(!length(current_profile_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, profiling stopped manually before dump.") + var/prof_file = file("[GLOB.log_directory]/[PROFILER_FILENAME]") + if(fexists(prof_file)) + fdel(prof_file) + if(!length(current_sendmaps_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, sendmaps profiling stopped manually before dump.") + var/sendmaps_file = file("[GLOB.log_directory]/[SENDMAPS_FILENAME]") + if(fexists(sendmaps_file)) + fdel(sendmaps_file) + + timer = TICK_USAGE_REAL + WRITE_FILE(prof_file, current_profile_data) + WRITE_FILE(sendmaps_file, current_sendmaps_data) + write_cost = MC_AVERAGE(write_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + +#undef PROFILER_FILENAME +#undef SENDMAPS_FILENAME diff --git a/code/controllers/subsystem/smoke_system.dm b/code/controllers/subsystem/smoke_system.dm deleted file mode 100644 index 2010687fcba2..000000000000 --- a/code/controllers/subsystem/smoke_system.dm +++ /dev/null @@ -1,31 +0,0 @@ -var/list/active_smoke_effects = list() - - -SUBSYSTEM_DEF(smoke_effects) - name = "Smoke Effects" - wait = 1 SECONDS - flags = SS_NO_INIT | SS_KEEP_TIMING - priority = SS_PRIORITY_OBJECTS - - var/list/currentrun = list() - -/datum/controller/subsystem/smoke_effects/stat_entry(msg) - msg = "P:[active_smoke_effects.len]" - return ..() - - -/datum/controller/subsystem/smoke_effects/fire(resumed = FALSE) - if(!resumed) - currentrun = active_smoke_effects.Copy() - - while(currentrun.len) - var/obj/effect/particle_effect/smoke/E = currentrun[currentrun.len] - currentrun.len-- - - if(!E || QDELETED(E)) - continue - - E.process() - - if(MC_TICK_CHECK) - return diff --git a/code/controllers/subsystem/sound.dm b/code/controllers/subsystem/sound.dm index 1935294394e7..4fdfd7935349 100644 --- a/code/controllers/subsystem/sound.dm +++ b/code/controllers/subsystem/sound.dm @@ -41,5 +41,5 @@ SUBSYSTEM_DEF(sound) if(VI?.ready) var/list/bounds = VI.get_middle_coords() if(bounds.len >= 2) - hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], VI.map_template.height, VI.map_template.width), bounds[3]) + hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], VI.map_template.width, VI.map_template.height), bounds[3]) template_queue[template] = hearers diff --git a/code/controllers/subsystem/stamina.dm b/code/controllers/subsystem/stamina.dm deleted file mode 100644 index 84d5b4038cd0..000000000000 --- a/code/controllers/subsystem/stamina.dm +++ /dev/null @@ -1,25 +0,0 @@ -var/global/list/active_staminas = list() - -SUBSYSTEM_DEF(stamina) - name = "Stamina" - wait = 2 SECONDS - priority = SS_PRIORITY_STAMINA - flags = SS_NO_INIT - var/list/currentrun = list() - - -/datum/controller/subsystem/stamina/fire(resumed = FALSE) - if (!resumed) - currentrun = active_staminas.Copy() - - while (currentrun.len) - var/datum/stamina/S = currentrun[currentrun.len] - currentrun.len-- - - if (!S || QDELETED(S)) - continue - - S.process() - - if (MC_TICK_CHECK) - return diff --git a/code/controllers/subsystem/stats_collector.dm b/code/controllers/subsystem/stats_collector.dm deleted file mode 100644 index de66e3b2c6b1..000000000000 --- a/code/controllers/subsystem/stats_collector.dm +++ /dev/null @@ -1,17 +0,0 @@ -/// Collects simple round statistics periodically -SUBSYSTEM_DEF(stats_collector) - name = "Round Stats" - wait = 30 SECONDS - priority = SS_PRIORITY_PAGER_STATUS - runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY - flags = SS_KEEP_TIMING | SS_NO_INIT - - var/stat_ticks = 0 - var/players_counter = 0 - -/datum/controller/subsystem/stats_collector/fire(resumed = FALSE) - players_counter += length(GLOB.clients) - stat_ticks++ - -/datum/controller/subsystem/stats_collector/proc/get_avg_players() - return players_counter / stat_ticks diff --git a/code/controllers/subsystem/teleporter.dm b/code/controllers/subsystem/teleporter.dm deleted file mode 100644 index b753bdb0d519..000000000000 --- a/code/controllers/subsystem/teleporter.dm +++ /dev/null @@ -1,10 +0,0 @@ -// Master teleporter controller. -SUBSYSTEM_DEF(teleporter) - name = "Teleporter" - wait = 5 SECONDS - init_order = SS_INIT_TELEPORTER - priority = SS_PRIORITY_TELEPORTER - flags = SS_NO_FIRE|SS_NO_INIT - - var/list/teleporters_by_id = list() // Associative list of teleporters by ID, master list of teleporters to process - var/list/teleporters = list() // Process list (identical contents to teleporters_by_id) diff --git a/code/controllers/subsystem/xenocon.dm b/code/controllers/subsystem/xenocon.dm deleted file mode 100644 index d16e59bd9813..000000000000 --- a/code/controllers/subsystem/xenocon.dm +++ /dev/null @@ -1,18 +0,0 @@ -SUBSYSTEM_DEF(xenocon) - name = "XENOCON" - wait = 5 SECONDS - priority = SS_PRIORITY_INACTIVITY - flags = SS_NO_INIT - var/rewarded = FALSE - -/datum/controller/subsystem/xenocon/fire(resumed = FALSE) - if(rewarded) - return - - var/datum/hive_status/hive - for(var/hivenumber in GLOB.hive_datum) - hive = GLOB.hive_datum[hivenumber] - if(hive.xenocon_points >= XENOCON_THRESHOLD) - var/datum/emergency_call/em_call = new /datum/emergency_call/xenos/platoon() - em_call.activate() - rewarded = TRUE diff --git a/code/datums/agents/tools/chloroform.dm b/code/datums/agents/tools/chloroform.dm index 464533309bcc..c6e3320688eb 100644 --- a/code/datums/agents/tools/chloroform.dm +++ b/code/datums/agents/tools/chloroform.dm @@ -47,8 +47,8 @@ /obj/item/weapon/chloroform/proc/grab_stun(mob/living/M, mob/living/user) M.anchored = TRUE - M.frozen = TRUE - M.density = FALSE + ADD_TRAIT(M, TRAIT_IMMOBILIZED, CHLOROFORM_TRAIT) + ADD_TRAIT(M, TRAIT_UNDENSE, CHLOROFORM_TRAIT) M.able_to_speak = FALSE M.update_canmove() @@ -82,7 +82,8 @@ M.density = TRUE M.able_to_speak = TRUE M.layer = MOB_LAYER - M.unfreeze() + REMOVE_TRAIT(M, TRAIT_IMMOBILIZED, CHLOROFORM_TRAIT) + REMOVE_TRAIT(M, TRAIT_UNDENSE, CHLOROFORM_TRAIT) QDEL_NULL(mask_item) diff --git a/code/datums/agents/tools/tracker.dm b/code/datums/agents/tools/tracker.dm index 1d6d6d4801b4..508db286b970 100644 --- a/code/datums/agents/tools/tracker.dm +++ b/code/datums/agents/tools/tracker.dm @@ -12,7 +12,7 @@ overlays.Cut() if(active && tracked_object) - overlays += icon(icon, "+tracker_arrow", get_dir(src, tracked_object)) + overlays += icon(icon, "+tracker_arrow", Get_Compass_Dir(src, tracked_object)) /obj/item/device/tracker/attack_self(mob/user) if(!skillcheckexplicit(user, SKILL_ANTAG, SKILL_ANTAG_AGENT)) diff --git a/code/datums/ammo/xeno.dm b/code/datums/ammo/xeno.dm index 9d91920ac6f8..75c78298fe4f 100644 --- a/code/datums/ammo/xeno.dm +++ b/code/datums/ammo/xeno.dm @@ -37,7 +37,7 @@ neuro_callback = CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(apply_neuro)) -/proc/apply_neuro(mob/M, power, insta_neuro) +/proc/apply_neuro(mob/living/M, power, insta_neuro) if(skillcheck(M, SKILL_ENDURANCE, SKILL_ENDURANCE_MAX) && !insta_neuro) M.visible_message(SPAN_DANGER("[M] withstands the neurotoxin!")) return //endurance 5 makes you immune to weak neurotoxin @@ -69,7 +69,7 @@ M.adjust_effect(1 * power, WEAKEN) // KD them a bit more M.visible_message(SPAN_DANGER("[M] falls prone.")) -/proc/apply_scatter_neuro(mob/M) +/proc/apply_scatter_neuro(mob/living/M) if(ishuman(M)) var/mob/living/carbon/human/H = M if(skillcheck(M, SKILL_ENDURANCE, SKILL_ENDURANCE_MAX)) @@ -317,7 +317,7 @@ shrapnel_type = /obj/item/shard/shrapnel/bone_chips shrapnel_chance = 60 -/datum/ammo/xeno/bone_chips/on_hit_mob(mob/M, obj/projectile/P) +/datum/ammo/xeno/bone_chips/on_hit_mob(mob/living/M, obj/projectile/P) if(iscarbon(M)) var/mob/living/carbon/C = M if((HAS_FLAG(C.status_flags, XENO_HOST) && HAS_TRAIT(C, TRAIT_NESTED)) || C.stat == DEAD) @@ -347,7 +347,7 @@ damage = 10 shrapnel_chance = 0 -/datum/ammo/xeno/bone_chips/spread/runner/on_hit_mob(mob/M, obj/projectile/P) +/datum/ammo/xeno/bone_chips/spread/runner/on_hit_mob(mob/living/M, obj/projectile/P) if(iscarbon(M)) var/mob/living/carbon/C = M if((HAS_FLAG(C.status_flags, XENO_HOST) && HAS_TRAIT(C, TRAIT_NESTED)) || C.stat == DEAD) diff --git a/code/datums/components/autofire/autofire.dm b/code/datums/components/autofire/autofire.dm index 2b9401e8d346..455fb70a9fa1 100644 --- a/code/datums/components/autofire/autofire.dm +++ b/code/datums/components/autofire/autofire.dm @@ -82,6 +82,8 @@ /datum/component/automatedfire/autofire/proc/initiate_shot() SIGNAL_HANDLER if(shooting)//if we are already shooting, it means the shooter is still on cooldown + if(bursting && (world.time > (next_fire + (burstfire_shot_delay * burst_shots_to_fire)))) + hard_reset() return shooting = TRUE process_shot() @@ -123,19 +125,19 @@ if(GUN_FIREMODE_BURSTFIRE) shots_fired++ if(shots_fired == burst_shots_to_fire) - callback_bursting.Invoke(FALSE) - callback_display_ammo.Invoke() + callback_bursting?.Invoke(FALSE) + callback_display_ammo?.Invoke() bursting = FALSE stop_firing() if(have_to_reset_at_burst_end)//We failed to reset because we were bursting, we do it now - callback_reset_fire.Invoke() + callback_reset_fire?.Invoke() have_to_reset_at_burst_end = FALSE return - callback_bursting.Invoke(TRUE) + callback_bursting?.Invoke(TRUE) bursting = TRUE next_fire = world.time + burstfire_shot_delay if(GUN_FIREMODE_AUTOMATIC) - callback_set_firing.Invoke(TRUE) + callback_set_firing?.Invoke(TRUE) next_fire = world.time + (auto_fire_shot_delay * automatic_delay_mult) if(GUN_FIREMODE_SEMIAUTO) return diff --git a/code/datums/components/cell.dm b/code/datums/components/cell.dm new file mode 100644 index 000000000000..81ef3733e2e2 --- /dev/null +++ b/code/datums/components/cell.dm @@ -0,0 +1,202 @@ +#define UNLIMITED_CHARGE -1 +#define UNLIMITED_DISTANCE -1 + +/datum/component/cell + dupe_mode = COMPONENT_DUPE_UNIQUE + /// Maximum charge of the power cell, set to -1 for infinite charge + var/max_charge = 10000 + /// Initial max charge of the power cell + var/initial_max_charge + /// Current charge of power cell + var/charge = 10000 + /// If the component can be recharged by hitting its parent with a cell + var/hit_charge = FALSE + /// The maximum amount that can be recharged per tick when using a cell to recharge this component + var/max_recharge_tick = 400 + /// If draining charge on process(), how much to drain per process call + var/charge_drain = 10 + /// If the parent should show cell charge on examine + var/display_charge = TRUE + /// From how many tiles at the highest someone can examine the parent to see the charge + var/charge_examine_range = 1 + /// If the component requires a cell to be inserted to work instead of having an integrated one + var/cell_insert = FALSE + /// Ref to an inserted cell. Should only be null if cell_insert is false + var/obj/item/cell/inserted_cell + + +/datum/component/cell/Initialize( + max_charge = 10000, + hit_charge = FALSE, + max_recharge_tick = 400, + charge_drain = 10, + display_charge = TRUE, + charge_examine_range = 1, + cell_insert = FALSE, + ) + + . = ..() + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + src.max_charge = max_charge + charge = max_charge + src.hit_charge = hit_charge + src.max_recharge_tick = max_recharge_tick + src.charge_drain = charge_drain + src.display_charge = display_charge + src.charge_examine_range = charge_examine_range + src.cell_insert = cell_insert + +/datum/component/cell/Destroy(force, silent) + QDEL_NULL(inserted_cell) + return ..() + + +/datum/component/cell/RegisterWithParent() + ..() + RegisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_ITEM_ATTACKED), PROC_REF(on_object_hit)) + RegisterSignal(parent, COMSIG_CELL_ADD_CHARGE, PROC_REF(add_charge)) + RegisterSignal(parent, COMSIG_CELL_USE_CHARGE, PROC_REF(use_charge)) + RegisterSignal(parent, COMSIG_CELL_CHECK_CHARGE, PROC_REF(has_charge)) + RegisterSignal(parent, COMSIG_CELL_START_TICK_DRAIN, PROC_REF(start_drain)) + RegisterSignal(parent, COMSIG_CELL_STOP_TICK_DRAIN, PROC_REF(stop_drain)) + RegisterSignal(parent, COMSIG_CELL_REMOVE_CELL, PROC_REF(remove_cell)) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) + RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp)) + +/datum/component/cell/process() + use_charge(null, charge_drain) + +/datum/component/cell/proc/on_emp(datum/source, severity) + SIGNAL_HANDLER + + use_charge(null, round(max_charge / severity)) + +/datum/component/cell/proc/start_drain(datum/source) + SIGNAL_HANDLER + + START_PROCESSING(SSobj, src) + +/datum/component/cell/proc/stop_drain(datum/source) + SIGNAL_HANDLER + + STOP_PROCESSING(SSobj, src) + +/datum/component/cell/proc/on_examine(datum/source, mob/examiner, list/examine_text) + SIGNAL_HANDLER + + if(!display_charge) + return + + if((charge_examine_range != UNLIMITED_DISTANCE) && get_dist(examiner, parent) > charge_examine_range) + return + + examine_text += "A small gauge in the corner reads \"Power: [round(100 * charge / max_charge)]%\"." + +/datum/component/cell/proc/on_object_hit(datum/source, obj/item/cell/attack_obj, mob/living/attacker, params) + SIGNAL_HANDLER + + if(!hit_charge || !istype(attack_obj)) + return + + if(!cell_insert) + INVOKE_ASYNC(src, PROC_REF(charge_from_cell), attack_obj, attacker) + + else + insert_cell(attack_obj, attacker) + + return COMPONENT_NO_AFTERATTACK|COMPONENT_CANCEL_ITEM_ATTACK + +/datum/component/cell/proc/insert_cell(obj/item/cell/power_cell, mob/living/user) + if(inserted_cell) + to_chat(user, SPAN_WARNING("There's already a power cell in [parent]!")) + return + + if(SEND_SIGNAL(parent, COMSIG_CELL_TRY_INSERT_CELL) & COMPONENT_CANCEL_CELL_INSERT) + return + + power_cell.drop_to_floor(user) + power_cell.forceMove(parent) + inserted_cell = power_cell + charge = power_cell.charge + max_charge = power_cell.maxcharge + +/datum/component/cell/proc/remove_cell(mob/living/user) + SIGNAL_HANDLER + + user.put_in_hands(inserted_cell, TRUE) + to_chat(user, SPAN_NOTICE("You remove [inserted_cell] from [parent].")) + inserted_cell = null + max_charge = initial_max_charge + charge = 0 + +/datum/component/cell/proc/charge_from_cell(obj/item/cell/power_cell, mob/living/user) + if(max_charge == UNLIMITED_CHARGE) + to_chat(user, SPAN_WARNING("[parent] doesn't need more power.")) + return + + while(charge < max_charge) + if(SEND_SIGNAL(parent, COMSIG_CELL_TRY_RECHARGING, user) & COMPONENT_CELL_NO_RECHARGE) + return + + if(power_cell.charge <= 0) + to_chat(user, SPAN_WARNING("[power_cell] is completely dry.")) + return + + if(!do_after(user, 1 SECONDS, (INTERRUPT_ALL & (~INTERRUPT_MOVED)), BUSY_ICON_BUILD, power_cell, INTERRUPT_DIFF_LOC)) + to_chat(user, SPAN_WARNING("You were interrupted.")) + return + + if(power_cell.charge <= 0) + return + + var/to_transfer = min(max_recharge_tick, power_cell.charge, (max_charge - charge)) + if(power_cell.use(to_transfer)) + add_charge(null, to_transfer) + to_chat(user, "You transfer some power between [power_cell] and [parent]. The gauge now reads: [round(100 * charge / max_charge)]%.") + +/datum/component/cell/proc/add_charge(datum/source, charge_add = 0) + SIGNAL_HANDLER + + if(max_charge == UNLIMITED_CHARGE) + return + + if(!charge_add) + return + + charge = clamp(charge + charge_add, 0, max_charge) + +/datum/component/cell/proc/use_charge(datum/source, charge_use = 0) + SIGNAL_HANDLER + + if(max_charge == UNLIMITED_CHARGE) + return + + if(!charge_use) + return + + if(!charge) + return COMPONENT_CELL_NO_USE_CHARGE + + charge = clamp(charge - charge_use, 0, max_charge) + + if(!charge) + on_charge_empty() + return + +/datum/component/cell/proc/has_charge(datum/source, charge_amount = 0) + SIGNAL_HANDLER + + if(!charge) + return COMPONENT_CELL_CHARGE_INSUFFICIENT + + if(charge < charge_amount) + return COMPONENT_CELL_CHARGE_INSUFFICIENT + +/datum/component/cell/proc/on_charge_empty() + stop_drain() + SEND_SIGNAL(parent, COMSIG_CELL_OUT_OF_CHARGE) + +#undef UNLIMITED_CHARGE +#undef UNLIMITED_DISTANCE diff --git a/code/datums/components/crate_tag.dm b/code/datums/components/crate_tag.dm new file mode 100644 index 000000000000..379df82a2084 --- /dev/null +++ b/code/datums/components/crate_tag.dm @@ -0,0 +1,36 @@ +/datum/component/crate_tag + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The crate tag used for notifications and as label + var/name + +/datum/component/crate_tag/Initialize(name, obj/structure/closet/crate/masquarade_type) + var/obj/structure/closet/crate/crate = parent + if(!istype(crate)) + return COMPONENT_INCOMPATIBLE + setup(name, masquarade_type) + RegisterSignal(parent, COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED, PROC_REF(notify_squad)) + +/datum/component/crate_tag/InheritComponent(datum/component/C, i_am_original, name, obj/structure/closet/crate/masquarade_type) + . = ..() + setup(name, masquarade_type) + +/datum/component/crate_tag/proc/setup(name, obj/structure/closet/crate/masquarade_type) + var/obj/structure/closet/crate/crate = parent + if(masquarade_type) + crate.name = initial(masquarade_type.name) + crate.desc = initial(masquarade_type.desc) + crate.icon_opened = initial(masquarade_type.icon_opened) + crate.icon_closed = initial(masquarade_type.icon_closed) + if(crate.opened) + crate.icon_state = crate.icon_opened + else + crate.icon_state = crate.icon_closed + if(name) + parent.AddComponent(/datum/component/label, name) + src.name = name // Keep it around additionally for notifications + +/// Handler to notify an overwatched squad that this crate has been dropped for them +/datum/component/crate_tag/proc/notify_squad(datum/source, datum/squad/squad) + SIGNAL_HANDLER + squad.send_message("'[name]' supply drop incoming. Heads up!") + squad.send_maptext(name, "Incoming Supply Drop:") diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index ce6c17e0af95..648478aa6140 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -259,7 +259,8 @@ active = FALSE merged = TRUE - parent_mob.density = FALSE + ADD_TRAIT(parent_mob, TRAIT_UNDENSE, XENO_WEED_TRAIT) + ADD_TRAIT(parent_mob, TRAIT_MERGED_WITH_WEEDS, XENO_WEED_TRAIT) parent_mob.anchored = TRUE parent_mob.mouse_opacity = MOUSE_OPACITY_TRANSPARENT parent_mob.plane = FLOOR_PLANE @@ -288,6 +289,7 @@ UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) absorbing_weeds = null + REMOVE_TRAIT(parent_mob, TRAIT_MERGED_WITH_WEEDS, XENO_WEED_TRAIT) parent_mob.anchored = FALSE parent_mob.mouse_opacity = MOUSE_OPACITY_ICON parent_mob.plane = GAME_PLANE diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index b60b20bc9026..213a959296fb 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -133,6 +133,9 @@ GLOBAL_DATUM_INIT(data_core, /datum/datacore, new) continue dept_flags |= FLAG_SHOW_MARINES squad_sublists[squad_name] = TRUE + ///If it is a real squad in the USCM squad list to prevent the crew manifest from breaking + if(!(squad_name in ROLES_SQUAD_ALL)) + continue LAZYSET(marines_by_squad[squad_name][real_rank], name, rank) //here we fill manifest diff --git a/code/datums/datum.dm b/code/datums/datum.dm index b26c6afe4d91..7d497785a72a 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -19,8 +19,8 @@ /// Active timers with this datum as the target var/list/active_timers - /// Status traits attached. - var/list/status_traits + /// Status traits attached to this datum. associative list of the form: list(trait name (string) = list(source1, source2, source3,...)) + var/list/_status_traits /** * Components attached to this datum diff --git a/code/datums/disease.dm b/code/datums/disease.dm index 92986b668b47..d2f466ebeb39 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -131,7 +131,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease /datum/disease/process() if(!holder) - active_diseases -= src + SSdisease.all_diseases -= src return if(prob(65)) spread(holder) @@ -176,7 +176,7 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease /datum/disease/New(process=TRUE)//process = 1 - adding the object to global list. List is processed by master controller. cure_list = list(cure_id) // to add more cures, add more vars to this list in the actual disease's New() if(process) // Viruses in list are considered active. - active_diseases += src + SSdisease.all_diseases += src initial_spread = spread /datum/disease/proc/IsSame(datum/disease/D) @@ -191,5 +191,5 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease /datum/disease/Destroy() affected_mob = null holder = null - active_diseases -= src + SSdisease.all_diseases -= src . = ..() diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index 6440c9734374..ad4703ba65fe 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -391,7 +391,7 @@ var/list/advance_cures = list( D.AssignName(new_name) D.Refresh() - for(var/datum/disease/advance/AD in active_diseases) + for(var/datum/disease/advance/AD in SSdisease.all_diseases) AD.Refresh() for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list.Copy())) @@ -409,7 +409,7 @@ var/list/advance_cures = list( /* /mob/verb/test() - for(var/datum/disease/D in active_diseases) + for(var/datum/disease/D in SSdisease.all_diseases) to_chat(src, "[D.name] - [D.holder]") */ diff --git a/code/datums/diseases/black_goo.dm b/code/datums/diseases/black_goo.dm index 38a26f3648c7..d4d9b6f50996 100644 --- a/code/datums/diseases/black_goo.dm +++ b/code/datums/diseases/black_goo.dm @@ -211,6 +211,15 @@ . = ..() reagents.add_reagent("antiZed", 30) +/obj/item/reagent_container/glass/bottle/labeled_black_goo_cure + name = "\"Pathogen\" cure bottle" + desc = "The bottle has a biohazard symbol on the front, and has a label, designating its use against Agent A0-3959X.91–15, colloquially known as the \"Black Goo\"." + icon_state = "bottle20" + +/obj/item/reagent_container/glass/bottle/labeled_black_goo_cure/Initialize() + . = ..() + reagents.add_reagent("antiZed", 60) + /datum/language/zombie name = "Zombie" desc = "A growling, guttural method of communication, only Zombies seem to be capable of producing these sounds." diff --git a/code/datums/effects/xeno_strains/boiler_trap.dm b/code/datums/effects/xeno_strains/boiler_trap.dm index 61451391e816..1833b9641a9a 100644 --- a/code/datums/effects/xeno_strains/boiler_trap.dm +++ b/code/datums/effects/xeno_strains/boiler_trap.dm @@ -4,19 +4,17 @@ effect_name = "boiler trap" duration = null flags = INF_DURATION - /// Ghetto flag indicating whether we actually placed the freeze or not, until we have an actual effects system - var/freezer = FALSE /datum/effects/boiler_trap/New(atom/A, mob/from, last_dmg_source, zone) . = ..() if(!QDELETED(src)) var/mob/M = affected_atom - freezer = M.freeze() + ADD_TRAIT(M, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY(effect_name)) /datum/effects/boiler_trap/Destroy(force) - if(ismob(affected_atom) && freezer) + if(ismob(affected_atom)) var/mob/M = affected_atom - M.unfreeze() + REMOVE_TRAIT(M, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY(effect_name)) return ..() /datum/effects/boiler_trap/validate_atom(atom/A) @@ -29,7 +27,5 @@ . = ..() if(!.) return FALSE var/mob/M = affected_atom - if(M.frozen) return TRUE - if(!freezer) - freezer = M.freeze() + ADD_TRAIT(M, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY(effect_name)) return TRUE diff --git a/code/datums/emergency_calls/cbrn.dm b/code/datums/emergency_calls/cbrn.dm new file mode 100644 index 000000000000..3a6b1c640632 --- /dev/null +++ b/code/datums/emergency_calls/cbrn.dm @@ -0,0 +1,80 @@ +/datum/emergency_call/cbrn + name = "CBRN (Squad)" + arrival_message = "A CBRN squad has been dispatched to your ship. Stand by." + objectives = "Handle the chemical, biological, radiological, or nuclear threat. Further orders may be provided." + mob_min = 3 + mob_max = 5 + max_heavies = 0 + max_smartgunners = 0 + +/datum/emergency_call/cbrn/create_member(datum/mind/new_mind, turf/override_spawn_loc) + var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/mob = new(spawn_loc) + new_mind.transfer_to(mob, TRUE) + + if(!leader && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(mob.client, JOB_SQUAD_LEADER, time_required_for_job)) + leader = mob + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/leader, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Fireteam Leader!")) + + else if(medics < max_medics && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(mob.client, JOB_SQUAD_MEDIC, time_required_for_job)) + medics++ + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/medic, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Squad Medic!")) + + else if(engineers < max_engineers && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_ENGINEER) && check_timelock(mob.client, JOB_SQUAD_ENGI, time_required_for_job)) + engineers++ + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/engineer, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Squad Engineer!")) + + else + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/standard, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are a CBRN Squad Rifleman!")) + + to_chat(mob, SPAN_ROLE_BODY("You are a member of the USCM's CBRN. The CBRN is a force that specializes in handling chemical, biological, radiological, and nuclear threats.")) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + +/datum/emergency_call/cbrn/ert + name = "CBRN (Distress)" + arrival_message = "Your distress signal has been received and we are dispatching the nearest CBRN squad to board with you now. Stand by." + probability = 10 + +/datum/emergency_call/cbrn/ert/New() + ..() + objectives = "Investigate the distress signal aboard the [MAIN_SHIP_NAME]." + +/datum/emergency_call/cbrn/specialists + name = "CBRN (Specialists)" + mob_min = 2 + mob_max = 5 + max_engineers = 0 + max_medics = 0 + +/datum/emergency_call/cbrn/specialists/New() + var/cbrn_ship_name = "Unit [pick(nato_phonetic_alphabet)]-[rand(1, 99)]" + arrival_message = "[MAIN_SHIP_NAME], CBRN [cbrn_ship_name] has been dispatched. Follow all orders provided by [cbrn_ship_name]." + objectives = "You are a specialist team in [cbrn_ship_name] dispatched to quell a threat to [MAIN_SHIP_NAME]. Further orders may be provided." + +/datum/emergency_call/cbrn/specialists/create_member(datum/mind/new_mind, turf/override_spawn_loc) + var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/mob = new(spawn_loc) + new_mind.transfer_to(mob, TRUE) + + if(!leader && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(mob.client, JOB_SQUAD_LEADER, time_required_for_job)) + leader = mob + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/specialist/lead, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are the CBRN Specialist Squad Leader!")) + else + arm_equipment(mob, /datum/equipment_preset/uscm/cbrn/specialist, TRUE, TRUE) + to_chat(mob, SPAN_ROLE_HEADER("You are a CBRN Specialist!")) + + to_chat(mob, SPAN_ROLE_BODY("You are a member of the USCM's CBRN. The CBRN is a force that specializes in handling chemical, biological, radiological, and nuclear threats.")) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) diff --git a/code/datums/emergency_calls/deathsquad.dm b/code/datums/emergency_calls/deathsquad.dm index 0bfab8fbf2b7..1cd5bdef6713 100644 --- a/code/datums/emergency_calls/deathsquad.dm +++ b/code/datums/emergency_calls/deathsquad.dm @@ -3,7 +3,7 @@ //Weyland-Yutani Deathsquad - W-Y Deathsquad. Event only /datum/emergency_call/death - name = "Weyland Whiteout Operators" + name = "Weyland Whiteout Operators (!DEATHSQUAD!)" mob_max = 8 mob_min = 5 arrival_message = "'!`2*%slau#*jer t*h$em a!l%. le&*ve n(o^ w&*nes%6es.*v$e %#d ou^'" @@ -18,41 +18,76 @@ // DEATH SQUAD-------------------------------------------------------------------------------- -/datum/emergency_call/death/create_member(datum/mind/M, turf/override_spawn_loc) +/datum/emergency_call/death/create_member(datum/mind/player, turf/override_spawn_loc) var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() if(!istype(spawn_loc)) return //Didn't find a useable spawn point. - var/mob/living/carbon/human/H = new(spawn_loc) - M.transfer_to(H, TRUE) + var/mob/living/carbon/human/person = new(spawn_loc) + player.transfer_to(person, TRUE) - if(!leader && HAS_FLAG(H.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(H.client, JOB_SQUAD_LEADER, time_required_for_job)) - leader = H - to_chat(H, SPAN_ROLE_HEADER("You are the Whiteout Team Leader!")) - to_chat(H, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) - arm_equipment(H, /datum/equipment_preset/pmc/w_y_whiteout/leader, TRUE, TRUE) - else if(medics < max_medics && HAS_FLAG(H.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(H.client, JOB_SQUAD_MEDIC, time_required_for_job)) + if(!leader && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(person.client, JOB_SQUAD_LEADER, time_required_for_job)) + leader = person + to_chat(person, SPAN_ROLE_HEADER("You are the Whiteout Team Leader!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/leader, TRUE, TRUE) + else if(medics < max_medics && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(person.client, JOB_SQUAD_MEDIC, time_required_for_job)) medics++ - to_chat(H, SPAN_ROLE_HEADER("You are a Whiteout Team Medic!")) - to_chat(H, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) - arm_equipment(H, /datum/equipment_preset/pmc/w_y_whiteout/medic, TRUE, TRUE) - else if(heavies < max_heavies && HAS_FLAG(H.client.prefs.toggles_ert, PLAY_SMARTGUNNER) && check_timelock(H.client, list(JOB_SQUAD_SPECIALIST, JOB_SQUAD_SMARTGUN), time_required_for_job)) + to_chat(person, SPAN_ROLE_HEADER("You are a Whiteout Team Medic!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/medic, TRUE, TRUE) + else if(heavies < max_heavies && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_SMARTGUNNER) && check_timelock(person.client, list(JOB_SQUAD_SPECIALIST, JOB_SQUAD_SMARTGUN), time_required_for_job)) heavies++ - to_chat(H, SPAN_ROLE_HEADER("You are a Whiteout Team Terminator!")) - to_chat(H, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) - arm_equipment(H, /datum/equipment_preset/pmc/w_y_whiteout/terminator, TRUE, TRUE) + to_chat(person, SPAN_ROLE_HEADER("You are a Whiteout Team Terminator!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/terminator, TRUE, TRUE) else - to_chat(H, SPAN_ROLE_HEADER("You are a Whiteout Team Operative!")) - to_chat(H, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) - arm_equipment(H, /datum/equipment_preset/pmc/w_y_whiteout, TRUE, TRUE) + to_chat(person, SPAN_ROLE_HEADER("You are a Whiteout Team Operative!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout, TRUE, TRUE) - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), person, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + +/datum/emergency_call/death/low_threat + name = "Weyland Whiteout Operators" + +// DEATH SQUAD-------------------------------------------------------------------------------- +/datum/emergency_call/death/low_threat/create_member(datum/mind/player, turf/override_spawn_loc) + var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/person = new(spawn_loc) + player.transfer_to(person, TRUE) + + if(!leader && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(person.client, JOB_SQUAD_LEADER, time_required_for_job)) + leader = person + to_chat(person, SPAN_ROLE_HEADER("You are the Whiteout Team Leader!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/low_threat/leader, TRUE, TRUE) + else if(medics < max_medics && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(person.client, JOB_SQUAD_MEDIC, time_required_for_job)) + medics++ + to_chat(person, SPAN_ROLE_HEADER("You are a Whiteout Team Medic!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/low_threat/medic, TRUE, TRUE) + else if(heavies < max_heavies && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_SMARTGUNNER) && check_timelock(person.client, list(JOB_SQUAD_SPECIALIST, JOB_SQUAD_SMARTGUN), time_required_for_job)) + heavies++ + to_chat(person, SPAN_ROLE_HEADER("You are a Whiteout Team Terminator!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/low_threat/terminator, TRUE, TRUE) + else + to_chat(person, SPAN_ROLE_HEADER("You are a Whiteout Team Operative!")) + to_chat(person, SPAN_ROLE_BODY("Whiteout protocol is in effect for the target, all assets onboard are to be liquidated with expediency unless otherwise instructed by Weyland Yutani personnel holding the position of Director or above.")) + arm_equipment(person, /datum/equipment_preset/pmc/w_y_whiteout/low_threat, TRUE, TRUE) + + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), person, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) //################################################################################################ // Marine commandos - USCM Deathsquad. Event only /datum/emergency_call/marsoc - name = "Marine Raider Strike Team" + name = "Marine Raider Strike Team (!DEATHSQUAD!)" mob_max = 8 mob_min = 5 probability = 0 @@ -81,7 +116,7 @@ return /datum/emergency_call/marsoc_covert - name = "Marine Raider Operatives (Covert)" + name = "Marine Raider Operatives (!DEATHSQUAD! Covert)" mob_max = 8 mob_min = 5 probability = 0 @@ -107,3 +142,27 @@ to_chat(H, SPAN_BOLDNOTICE("You are absolutely loyal to High Command and must follow their directives.")) to_chat(H, SPAN_BOLDNOTICE("Execute the mission assigned to you with extreme prejudice!")) return + + +/datum/emergency_call/marsoc/low_threat + name = "Marine Raider Operatives" + +/datum/emergency_call/marsoc/low_threat/create_member(datum/mind/MIND) + + var/turf/spawn_loc = get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/player = new(spawn_loc) + MIND.transfer_to(player, TRUE) + if(!leader && HAS_FLAG(player.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(player.client, JOB_SQUAD_LEADER, time_required_for_job)) //First one spawned is always the leader. + leader = player + to_chat(player, SPAN_WARNING(FONT_SIZE_BIG("You are a Marine Raider Team Leader, better than all the rest."))) + arm_equipment(player, /datum/equipment_preset/uscm/marsoc/low_threat/sl, TRUE, TRUE) + else + to_chat(player, SPAN_WARNING(FONT_SIZE_BIG("You are an elite Marine Raider, the best of the best."))) + arm_equipment(player, /datum/equipment_preset/uscm/marsoc/low_threat, TRUE, TRUE) + to_chat(player, SPAN_BOLDNOTICE("You are absolutely loyal to High Command and must follow their directives.")) + to_chat(player, SPAN_BOLDNOTICE("Execute the mission assigned to you with extreme prejudice!")) + return diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm index 4c3dfbbfac2b..9db46955a5ea 100644 --- a/code/datums/emergency_calls/emergency_call.dm +++ b/code/datums/emergency_calls/emergency_call.dm @@ -305,7 +305,7 @@ candidates = list() if(arrival_message && announce_incoming) - marine_announcement(arrival_message, "Intercepted Tranmission:") + marine_announcement(arrival_message, "Intercepted Transmission:") /datum/emergency_call/proc/add_candidate(mob/M) if(!M.client || (M.mind && (M.mind in candidates)) || istype(M, /mob/living/carbon/xenomorph)) diff --git a/code/datums/emergency_calls/upp_commando.dm b/code/datums/emergency_calls/upp_commando.dm index 14c4af46c27b..1bc2b59ba08c 100644 --- a/code/datums/emergency_calls/upp_commando.dm +++ b/code/datums/emergency_calls/upp_commando.dm @@ -1,7 +1,7 @@ //UPP COMMANDOS /datum/emergency_call/upp_commando - name = "UPP Commandos" + name = "UPP Commandos (!DEATHSQUAD!)" mob_max = 6 probability = 0 objectives = "Stealthily assault the ship. Use your silenced weapons, tranquilizers, and night vision to get the advantage on the enemy. Take out the power systems, comms and engine. Stick together and keep a low profile." @@ -51,3 +51,29 @@ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) +/datum/emergency_call/upp_commando/low_threat + name = "UPP Commandos" + +/datum/emergency_call/upp_commando/create_member(datum/mind/mind, turf/override_spawn_loc) + var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point() + + if(!istype(spawn_loc)) + return //Didn't find a useable spawn point. + + var/mob/living/carbon/human/person = new(spawn_loc) + mind.transfer_to(person, TRUE) + + if(!leader && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(person.client, JOB_SQUAD_LEADER, time_required_for_job)) //First one spawned is always the leader. + leader = person + arm_equipment(person, /datum/equipment_preset/upp/commando/leader/low_threat, TRUE, TRUE) + to_chat(person, SPAN_ROLE_HEADER("You are a Commando Team Leader of the Union of Progressive People, a powerful socialist state that rivals the United Americas!")) + else if(medics < max_medics && HAS_FLAG(person.client.prefs.toggles_ert, PLAY_MEDIC) && check_timelock(person.client, JOB_SQUAD_MEDIC, time_required_for_job)) + medics++ + to_chat(person, SPAN_ROLE_HEADER("You are a Commando Medic of the Union of Progressive People, a powerful socialist state that rivals the United Americas!")) + arm_equipment(person, /datum/equipment_preset/upp/commando/medic/low_threat, TRUE, TRUE) + else + to_chat(person, SPAN_ROLE_HEADER("You are a Commando of the Union of Progressive People, a powerful socialist state that rivals the United Americas!")) + arm_equipment(person, /datum/equipment_preset/upp/commando/low_threat, TRUE, TRUE) + print_backstory(person) + + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), person, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) diff --git a/code/datums/factions/uscm.dm b/code/datums/factions/uscm.dm index cf77142ce5d6..0a9b0cff40b9 100644 --- a/code/datums/factions/uscm.dm +++ b/code/datums/factions/uscm.dm @@ -189,6 +189,19 @@ if(JOB_CMB_OBS) marine_rk = "obs" icon_prefix = "cmb_" + // Check squad marines here too, for the unique ones + if(JOB_SQUAD_ENGI) + marine_rk = "engi" + if(JOB_SQUAD_MEDIC) + marine_rk = "med" + if(JOB_SQUAD_SPECIALIST) + marine_rk = "spec" + if(JOB_SQUAD_SMARTGUN) + marine_rk = "gun" + if(JOB_SQUAD_TEAM_LEADER) + marine_rk = "tl" + if(JOB_SQUAD_LEADER) + marine_rk = "leader" if(marine_rk) var/image/I = image('icons/mob/hud/marine_hud.dmi', current_human, "hudsquad") diff --git a/code/datums/keybinding/communication.dm b/code/datums/keybinding/communication.dm index 4164198d4818..e1ba0ab5a31e 100644 --- a/code/datums/keybinding/communication.dm +++ b/code/datums/keybinding/communication.dm @@ -32,7 +32,7 @@ /datum/keybinding/client/communication/whisper hotkey_keys = list("Unbound") classic_keys = list("Unbound") - name = "Whisper" + name = WHISPER_CHANNEL full_name = "IC Whisper" keybind_signal = COMSIG_KB_CLIENT_WHISPER_DOWN @@ -56,4 +56,4 @@ name = MENTOR_CHANNEL full_name = "Mentor Say" description = "Talk with other mentors." - keybind_signal = COMSIG_KB_ADMIN_ASAY_DOWN + keybind_signal = COMSIG_KB_ADMIN_MENTORSAY_DOWN diff --git a/code/datums/keybinding/human_combat.dm b/code/datums/keybinding/human_combat.dm index 2f37efc61438..d30414d68563 100644 --- a/code/datums/keybinding/human_combat.dm +++ b/code/datums/keybinding/human_combat.dm @@ -190,3 +190,20 @@ var/obj/item/weapon/gun/rifle/m46c/COgun = held_item COgun.toggle_iff(human) return TRUE + +/datum/keybinding/human/combat/toggle_shotgun_tube + hotkey_keys = list("Unbound") + classic_keys = list("Unbound") + name = "toggle_shotgun_tube" + full_name = "Toggle Shotgun Tube" + keybind_signal = COMSIG_KB_HUMAN_WEAPON_SHOTGUN_TUBE + +/datum/keybinding/human/combat/toggle_shotgun_tube/down(client/user) + . = ..() + if(.) + return + var/mob/living/carbon/human/human = user.mob + var/obj/item/weapon/gun/shotgun/pump/dual_tube/held_item = human.get_held_item() + if(istype(held_item)) + held_item.toggle_tube() + return TRUE diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index c6fc23c68eba..11ba15146430 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -37,6 +37,15 @@ /// Has the looping started yet? var/loop_started = FALSE + /** + * Let's you make a "loud" sound that "projects." IE you can hear this sound from a further distance away. + * Think of like an air raid siren. They're loud if you're close yeah... but you can hear them from mad far away, bruv + * with a longer "falloff distance." Fixes the extra_range stuff + */ + var/is_sound_projecting = FALSE + ///only applicable to is_sound_projecting: max range till sound volume starts dropping as distance increases + var/falloff_distance = 50 + /* // as of yet unused varen \\ /// How much the sound will be affected by falloff per tile. @@ -130,19 +139,18 @@ sound_to_play.channel = get_free_channel() sound_to_play.volume = volume_override || volume //Use volume as fallback if theres no override SEND_SOUND(parent, sound_to_play) - else - playsound( - parent, - sound_to_play, - volume, - vary, - extra_range//, - // falloff_exponent = falloff_exponent, - // pressure_affected = pressure_affected, - // ignore_walls = ignore_walls, - // falloff_distance = falloff_distance, - // use_reverb = use_reverb - ) + return + if (is_sound_projecting) + playsound(parent, sound_to_play, volume, vary, extra_range, VOLUME_SFX, 0, 0, falloff_distance) + return + + playsound( + parent, + sound_to_play, + volume, + vary, + extra_range + ) /// Returns the sound we should now be playing. /datum/looping_sound/proc/get_sound(_mid_sounds) diff --git a/code/datums/looping_sounds/misc_sounds.dm b/code/datums/looping_sounds/misc_sounds.dm new file mode 100644 index 000000000000..6411b3f51f4a --- /dev/null +++ b/code/datums/looping_sounds/misc_sounds.dm @@ -0,0 +1,3 @@ +/datum/looping_sound/looping_launch_announcement_alarm + mid_sounds = list('sound/vehicles/Dropships/single_alarm_brr_dropship_1.ogg' = 1) + start_sound = list('sound/vehicles/Dropships/single_alarm_brr_dropship_1.ogg' = 1) diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm index 1f3c265ead76..3bf5c601cec9 100644 --- a/code/datums/map_config.dm +++ b/code/datums/map_config.dm @@ -87,12 +87,14 @@ /datum/equipment_preset/synth/survivor/janitor_synth, /datum/equipment_preset/synth/survivor/chef_synth, /datum/equipment_preset/synth/survivor/teacher_synth, + /datum/equipment_preset/synth/survivor/freelancer_synth, + /datum/equipment_preset/synth/survivor/trucker_synth, /datum/equipment_preset/synth/survivor/bartender_synth, /datum/equipment_preset/synth/survivor/detective_synth, /datum/equipment_preset/synth/survivor/cmb_synth, - /datum/equipment_preset/synth/survivor/security_synth, - /datum/equipment_preset/synth/survivor/protection_synth, - /datum/equipment_preset/synth/survivor/corporate_synth, + /datum/equipment_preset/synth/survivor/wy/security_synth, + /datum/equipment_preset/synth/survivor/wy/protection_synth, + /datum/equipment_preset/synth/survivor/wy/corporate_synth, /datum/equipment_preset/synth/survivor/radiation_synth, ) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 2e56b963e88f..9e8279a843a4 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -29,9 +29,14 @@ research_objective_interface = new() /datum/mind/Destroy() + QDEL_NULL(initial_account) QDEL_NULL(objective_memory) QDEL_NULL(objective_interface) QDEL_NULL(research_objective_interface) + current = null + original = null + ghost_mob = null + player_entity = null return ..() /datum/mind/proc/transfer_to(mob/living/new_character, force = FALSE) diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm index 65c5a47896fa..ff1263510761 100644 --- a/code/datums/mob_hud.dm +++ b/code/datums/mob_hud.dm @@ -283,6 +283,12 @@ var/list/datum/mob_hud/huds = list( return /mob/living/carbon/xenomorph/med_hud_set_health() + if(QDELETED(src)) + return + + if(!(HEALTH_HUD_XENO in hud_list)) + CRASH("hud_list lacks HEALTH_HUD_XENO despite not being deleted in med_hud_set_health()") + var/image/holder = hud_list[HEALTH_HUD_XENO] var/health_hud_type = "xenohealth" @@ -798,7 +804,7 @@ var/global/image/hud_icon_hudfocus tag_holder.overlays += image('icons/mob/hud/hud.dmi', src, "prae_tag") // Hacky, but works. Currently effects are hard to make with precise timings - var/freeze_found = frozen + var/freeze_found = HAS_TRAIT(src, TRAIT_IMMOBILIZED) && !buckled && !lying if (freeze_found) freeze_holder.overlays += image('icons/mob/hud/hud.dmi', src, "xeno_freeze") diff --git a/code/datums/soundOutput.dm b/code/datums/soundOutput.dm index bc5ffd8efcfb..1f4512b28d59 100644 --- a/code/datums/soundOutput.dm +++ b/code/datums/soundOutput.dm @@ -152,11 +152,6 @@ adjust_volume_prefs(VOLUME_AMB, "Set the volume for ambience and soundscapes", 0) soundOutput.update_ambience(null, null, TRUE) -/client/verb/adjust_volume_admin_music() - set name = "Adjust Volume Admin MIDIs" - set category = "Preferences.Sound" - adjust_volume_prefs(VOLUME_ADM, "Set the volume for admin MIDIs", SOUND_CHANNEL_ADMIN_MIDI) - /client/verb/adjust_volume_lobby_music() set name = "Adjust Volume LobbyMusic" set category = "Preferences.Sound" diff --git a/code/datums/stamina/_stamina.dm b/code/datums/stamina/_stamina.dm index 36705e3be300..e233aaa81676 100644 --- a/code/datums/stamina/_stamina.dm +++ b/code/datums/stamina/_stamina.dm @@ -37,13 +37,11 @@ current_stamina = Clamp(current_stamina - amount, 0, max_stamina) if(current_stamina < max_stamina) - if(!(src in active_staminas)) - active_staminas.Add(src) - + START_PROCESSING(SSobj, src) if(amount > 0) apply_rest_period(STAMINA_REST_PERIOD) else - active_staminas.Remove(src) + STOP_PROCESSING(SSobj, src) update_stamina_level() diff --git a/code/datums/statistics/entities/caste_stats.dm b/code/datums/statistics/entities/caste_stats.dm index 639e1b4a05f5..6bfc18d124b7 100644 --- a/code/datums/statistics/entities/caste_stats.dm +++ b/code/datums/statistics/entities/caste_stats.dm @@ -3,6 +3,10 @@ var/total_hits = 0 var/list/abilities_used = list() // types of /datum/entity/statistic, "tail sweep" = 10, "screech" = 2 +/datum/entity/player_stats/caste/Destroy(force) + . = ..() + QDEL_LIST_ASSOC_VAL(abilities_used) + /datum/entity/player_stats/caste/proc/setup_ability(ability) if(!ability) return diff --git a/code/datums/statistics/entities/death_stats.dm b/code/datums/statistics/entities/death_stats.dm index cb3053a33442..35ff1769b925 100644 --- a/code/datums/statistics/entities/death_stats.dm +++ b/code/datums/statistics/entities/death_stats.dm @@ -140,16 +140,16 @@ new_death.detach() return new_death -/mob/living/carbon/human/track_mob_death(cause, cause_mob) - . = ..(cause, cause_mob, job) +/mob/living/carbon/human/track_mob_death(datum/cause_data/cause_data, turf/death_loc) + . = ..() if(statistic_exempt || !mind) return var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() if(human_stats && human_stats.death_list) human_stats.death_list.Insert(1, .) -/mob/living/carbon/xenomorph/track_mob_death(cause, cause_mob) - var/datum/entity/statistic/death/new_death = ..(cause, cause_mob, caste_type) +/mob/living/carbon/xenomorph/track_mob_death(datum/cause_data/cause_data, turf/death_loc) + var/datum/entity/statistic/death/new_death = ..() if(!new_death) return new_death.is_xeno = TRUE // this was placed beneath the if below, which meant gibbing as a xeno wouldn't track properly in stats diff --git a/code/datums/statistics/entities/human_stats.dm b/code/datums/statistics/entities/human_stats.dm index 51b07867dfd3..1e15aa1d161b 100644 --- a/code/datums/statistics/entities/human_stats.dm +++ b/code/datums/statistics/entities/human_stats.dm @@ -5,10 +5,17 @@ var/total_shots = 0 var/total_shots_hit = 0 var/total_screams = 0 - var/datum/entity/weapon_stats/top_weapon = null // reference to /datum/entity/weapon_stats (like tac-shotty) - var/list/weapon_stats_list = list() // list of types /datum/entity/weapon_stats - var/list/job_stats_list = list() // list of types /datum/entity/job_stats - var/list/datum/entity/statistic/medal/medal_list = list() // list of all medals earned + var/list/weapon_stats_list = list() //! indexed list of types /datum/entity/weapon_stats + var/list/job_stats_list = list() //! indexed list of types /datum/entity/job_stats + var/datum/entity/weapon_stats/top_weapon //! reference to /datum/entity/weapon_stats (like tac-shotty) + var/list/datum/entity/statistic/medal/medal_list = list() //! list of all medals earned + +/datum/entity/player_stats/human/Destroy(force) + . = ..() + QDEL_LIST_ASSOC_VAL(weapon_stats_list) + QDEL_LIST_ASSOC_VAL(job_stats_list) + QDEL_NULL(top_weapon) + QDEL_LIST(medal_list) /datum/entity/player_stats/human/get_playtime(type) if(!type) diff --git a/code/datums/statistics/entities/job_stats.dm b/code/datums/statistics/entities/job_stats.dm index ecde1c942082..199c2adb3160 100644 --- a/code/datums/statistics/entities/job_stats.dm +++ b/code/datums/statistics/entities/job_stats.dm @@ -1,8 +1,8 @@ /datum/entity/player_stats/job - var/name = null - var/total_friendly_fire = null - var/total_revives = null - var/total_lives_saved = null - var/total_shots = null - var/total_shots_hit = null - var/total_screams = null + var/name + var/total_friendly_fire + var/total_revives + var/total_lives_saved + var/total_shots + var/total_shots_hit + var/total_screams diff --git a/code/datums/statistics/entities/panel_stats.dm b/code/datums/statistics/entities/panel_stats.dm index d6e391e1731f..e507d5d81a8b 100644 --- a/code/datums/statistics/entities/panel_stats.dm +++ b/code/datums/statistics/entities/panel_stats.dm @@ -8,7 +8,7 @@ update_panel_data(round_statistics) ui_interact(user) -/datum/entity/player_entity/proc/ui_interact(mob/user, ui_key = "statistics", datum/nanoui/ui = null, force_open = 1) +/datum/entity/player_entity/proc/ui_interact(mob/user, ui_key = "statistics", datum/nanoui/ui, force_open = 1) data["menu"] = menu data["subMenu"] = subMenu data["dataMenu"] = dataMenu diff --git a/code/datums/statistics/entities/player_entity.dm b/code/datums/statistics/entities/player_entity.dm index 72f4d95d7aa3..f0b3d37ede7e 100644 --- a/code/datums/statistics/entities/player_entity.dm +++ b/code/datums/statistics/entities/player_entity.dm @@ -8,8 +8,8 @@ /datum/entity/player_entity var/name var/ckey // "cakey" - var/list/datum/entity/player_stats = list() - var/list/datum/entity/statistic/death/death_stats = list() + var/list/player_stats = list() //! Indeed list of /datum/entity/player_stats + var/list/death_stats = list() //! Indexed list of /datum/entity/statistic/death var/menu = 0 var/subMenu = 0 var/dataMenu = 0 @@ -18,6 +18,11 @@ var/savefile_version var/save_loaded = FALSE +/datum/entity/player_entity/Destroy(force) + QDEL_LIST_ASSOC_VAL(player_stats) + QDEL_LIST_ASSOC_VAL(death_stats) + return ..() + /datum/entity/player_entity/proc/get_playtime(branch, type) var/playtime = 0 if(player_stats["[branch]"]) diff --git a/code/datums/statistics/entities/player_stats.dm b/code/datums/statistics/entities/player_stats.dm index b378d7c2ea24..d9fbd3b11e03 100644 --- a/code/datums/statistics/entities/player_stats.dm +++ b/code/datums/statistics/entities/player_stats.dm @@ -6,13 +6,21 @@ var/total_rounds_played = 0 var/steps_walked = 0 var/round_played = FALSE - var/datum/entity/statistic/nemesis = null // "runner" = 3 + var/datum/entity/statistic/nemesis // "runner" = 3 var/list/niche_stats = list() // list of type /datum/entity/statistic, "Total Executions" = number var/list/humans_killed = list() // list of type /datum/entity/statistic, "jobname2" = number var/list/xenos_killed = list() // list of type /datum/entity/statistic, "caste" = number var/list/death_list = list() // list of type /datum/entity/death_stats var/display_stat = TRUE +/datum/entity/player_stats/Destroy(force) + QDEL_NULL(nemesis) + QDEL_LIST_ASSOC_VAL(niche_stats) + QDEL_LIST_ASSOC_VAL(humans_killed) + QDEL_LIST_ASSOC_VAL(xenos_killed) + QDEL_LIST_ASSOC_VAL(death_list) + return ..() + /datum/entity/player_stats/proc/get_playtime() return total_playtime diff --git a/code/datums/statistics/entities/round_stats.dm b/code/datums/statistics/entities/round_stats.dm index 0e1fb6e387db..baed6befa912 100644 --- a/code/datums/statistics/entities/round_stats.dm +++ b/code/datums/statistics/entities/round_stats.dm @@ -23,7 +23,7 @@ var/total_slashes = 0 // untracked data - var/datum/entity/statistic/map/current_map = null // reference to current map + var/datum/entity/statistic/map/current_map // reference to current map var/list/datum/entity/statistic/death/death_stats_list = list() var/list/abilities_used = list() // types of /datum/entity/statistic, "tail sweep" = 10, "screech" = 2 @@ -37,8 +37,20 @@ var/list/job_stats_list = list() // list of types /datum/entity/job_stats // nanoui data - var/round_data[0] - var/death_data[0] + var/list/round_data = list() + var/list/death_data = list() + +/datum/entity/statistic/round/Destroy(force) + . = ..() + QDEL_NULL(current_map) + QDEL_LIST(death_stats_list) + QDEL_LIST_ASSOC_VAL(abilities_used) + QDEL_LIST_ASSOC_VAL(final_participants) + QDEL_LIST_ASSOC_VAL(hijack_participants) + QDEL_LIST_ASSOC_VAL(total_deaths) + QDEL_LIST_ASSOC_VAL(caste_stats_list) + QDEL_LIST_ASSOC_VAL(weapon_stats_list) + QDEL_LIST_ASSOC_VAL(job_stats_list) /datum/entity_meta/statistic_round entity_type = /datum/entity/statistic/round diff --git a/code/datums/statistics/entities/weapon_stats.dm b/code/datums/statistics/entities/weapon_stats.dm index 0d8458c20de2..9fff5c514458 100644 --- a/code/datums/statistics/entities/weapon_stats.dm +++ b/code/datums/statistics/entities/weapon_stats.dm @@ -1,16 +1,23 @@ /datum/entity/weapon_stats - var/datum/entity/player = null // "deanthelis" - var/list/niche_stats = list() // list of type /datum/entity/statistic, "Total Reloads" = number - var/list/humans_killed = list() // list of type /datum/entity/statistic, "jobname2" = number - var/list/xenos_killed = list() // list of type /datum/entity/statistic, "caste" = number - var/name = null + var/datum/entity/player + var/list/niche_stats = list() //! Indexed list of /datum/entity/statistic, "Total Reloads" = number + var/list/humans_killed = list() //! Indexed list of /datum/entity/statistic, "jobname2" = number + var/list/xenos_killed = list() //! Indexed list of /datum/entity/statistic, "caste" = number + var/name var/total_kills = 0 - var/total_hits = null - var/total_shots = null - var/total_shots_hit = null - var/total_friendly_fire = null + var/total_hits + var/total_shots + var/total_shots_hit + var/total_friendly_fire var/display_stat = TRUE +/datum/entity/weapon_stats/Destroy(force) + player = null + QDEL_LIST_ASSOC_VAL(niche_stats) + QDEL_LIST_ASSOC_VAL(humans_killed) + QDEL_LIST_ASSOC_VAL(xenos_killed) + return ..() + /datum/entity/weapon_stats/proc/count_human_kill(job_name) if(!job_name) return diff --git a/code/datums/statistics/entities/xeno_stats.dm b/code/datums/statistics/entities/xeno_stats.dm index 9ed327258258..8fff4a2e5dd3 100644 --- a/code/datums/statistics/entities/xeno_stats.dm +++ b/code/datums/statistics/entities/xeno_stats.dm @@ -4,6 +4,12 @@ var/list/caste_stats_list = list() // list of types /datum/entity/player_stats/caste var/list/datum/entity/statistic/medal/medal_list = list() // list of all royal jelly earned +/datum/entity/player_stats/xeno/Destroy(force) + . = ..() + QDEL_NULL(top_caste) + QDEL_LIST_ASSOC_VAL(caste_stats_list) + QDEL_LIST(medal_list) + /datum/entity/player_stats/xeno/get_playtime(type) if(!type || type == FACTION_XENOMORPH) return ..() diff --git a/code/datums/supply_packs/black_market.dm b/code/datums/supply_packs/black_market.dm index 1b8464820bb6..36d890e2b3d5 100644 --- a/code/datums/supply_packs/black_market.dm +++ b/code/datums/supply_packs/black_market.dm @@ -585,7 +585,7 @@ Primarily made up of things that would be best utilized, well, shipside. Recreat /obj/item/storage/box/packet/hefa/toy, /obj/item/toy/inflatable_duck, /obj/item/toy/beach_ball, - /obj/item/toy/farwadoll, + /obj/item/toy/plush/farwa, /obj/item/toy/waterflower, /obj/item/toy/spinningtoy, /obj/item/storage/box/snappops, @@ -749,8 +749,8 @@ This is where the RO can reclaim their lost honor and purchase the M44 custom, t dollar_cost = 10 containertype = /obj/structure/largecrate/black_market -/datum/supply_packs/contraband/deep_storage/xm42b_pipe - name = "10x99mm XM42B casing" +/datum/supply_packs/contraband/deep_storage/xm43e1_pipe + name = "10x99mm XM43E1 casing" contains = list(/obj/item/prop/helmetgarb/bullet_pipe) dollar_cost = 10 containertype = /obj/structure/largecrate/black_market diff --git a/code/datums/supply_packs/spec_ammo.dm b/code/datums/supply_packs/spec_ammo.dm index 7931a4d40204..e20a5de865a3 100644 --- a/code/datums/supply_packs/spec_ammo.dm +++ b/code/datums/supply_packs/spec_ammo.dm @@ -109,10 +109,10 @@ containername = "M42A Incendiary Magazine Crate" group = "Weapons Specialist Ammo" -//XM42B - Disabled during testing per request. +//XM43E1 - Disabled during testing per request. /* /datum/supply_packs/ammo_amr_marksman - name = "XM42B anti-materiel rifle marksman magazines crate (x5)" + name = "XM43E1 anti-materiel rifle marksman magazines crate (x5)" contains = list( /obj/item/ammo_magazine/sniper/anti_materiel, /obj/item/ammo_magazine/sniper/anti_materiel, @@ -122,7 +122,7 @@ ) cost = 30 containertype = /obj/structure/closet/crate/ammo - containername = "XM42B Anti-Materiel Magazine Crate" + containername = "XM43E1 Anti-Materiel Magazine Crate" group = "Specialist Ammo" */ //M4RA diff --git a/code/game/area/WhiskeyOutpost.dm b/code/game/area/WhiskeyOutpost.dm index 02d94dc942da..aef72d1a9941 100644 --- a/code/game/area/WhiskeyOutpost.dm +++ b/code/game/area/WhiskeyOutpost.dm @@ -65,7 +65,7 @@ icon_state = "livingspace" /area/whiskey_outpost/inside/supply - name = "\improper Supply Depo" + name = "\improper Supply Depot" icon_state = "req" /* diff --git a/code/game/area/almayer.dm b/code/game/area/almayer.dm index 6ced81a22b15..d9ff42f4f55c 100644 --- a/code/game/area/almayer.dm +++ b/code/game/area/almayer.dm @@ -13,13 +13,28 @@ ambience_exterior = AMBIENCE_ALMAYER ceiling_muffle = FALSE + ///Whether this area is used for hijack evacuation progress + var/hijack_evacuation_area = FALSE + + ///The weight this area gives towards hijack evacuation progress + var/hijack_evacuation_weight = 0 + + ///Whether this area is additive or multiplicative towards evacuation progress + var/hijack_evacuation_type = EVACUATION_TYPE_NONE + +/area/almayer/Initialize(mapload, ...) + . = ..() + + if(hijack_evacuation_area) + SShijack.progress_areas[src] = power_equip + /area/shuttle/almayer/elevator_maintenance/upperdeck - name = "\improper Maintenance Elevator" + name = "\improper Upper Deck Maintenance Elevator" icon_state = "shuttle" fake_zlevel = 1 /area/shuttle/almayer/elevator_maintenance/lowerdeck - name = "\improper Maintenance Elevator" + name = "\improper Lower Deck Maintenance Elevator" icon_state = "shuttle" fake_zlevel = 2 @@ -83,23 +98,23 @@ resin_construction_allowed = FALSE /area/almayer/command/securestorage - name = "\improper Secure Storage" + name = "\improper Upper Deck Secure Storage" icon_state = "corporatespace" - fake_zlevel = 2 // lowerdeck + fake_zlevel = 1 // upperdeck /area/almayer/command/computerlab - name = "\improper Computer Lab" + name = "\improper Upper Deck Computer Lab" icon_state = "ceroom" - fake_zlevel = 2 // lowerdeck + fake_zlevel = 1 // upperdeck /area/almayer/command/telecomms - name = "\improper Telecommunications" + name = "\improper Upper Deck Telecommunications" icon_state = "tcomms" fake_zlevel = 1 // upperdeck flags_area = AREA_NOTUNNEL /area/almayer/command/self_destruct - name = "\improper Self-Destruct Core Room" + name = "\improper Upper Deck Self-Destruct Core Room" icon_state = "selfdestruct" fake_zlevel = 1 // upperdeck flags_area = AREA_NOTUNNEL @@ -110,7 +125,7 @@ fake_zlevel = 1 // upperdeck /area/almayer/command/combat_correspondent - name = "\improper Combat Correspondent Office" + name = "\improper Upper Deck Combat Correspondent Office" icon_state = "selfdestruct" fake_zlevel = 1 // upperdeck @@ -118,36 +133,36 @@ minimap_color = MINIMAP_AREA_ENGI /area/almayer/engineering/upper_engineering - name = "\improper Upper Engineering" + name = "\improper Upper Deck Engineering" icon_state = "upperengineering" fake_zlevel = 1 // upperdeck /area/almayer/engineering/upper_engineering/starboard - name = "\improper Starboard Upper Engineering" + name = "\improper Upper Deck Starboard Engineering" /area/almayer/engineering/upper_engineering/port - name = "\improper Port Upper Engineering" + name = "\improper Upper Deck Port Engineering" /area/almayer/engineering/upper_engineering/notunnel flags_area = AREA_NOTUNNEL /area/almayer/engineering/ce_room - name = "\improper Chief Engineer Office" + name = "\improper Upper Deck Chief Engineer Office" icon_state = "ceroom" fake_zlevel = 1 // upperdeck /area/almayer/engineering/lower_engine_monitoring - name = "\improper Engine Reactor Monitoring" + name = "\improper Lower Deck Engine Reactor Monitoring" icon_state = "lowermonitoring" fake_zlevel = 2 // lowerdeck /area/almayer/engineering/lower_engineering - name = "\improper Engineering Lower" + name = "\improper Lower Deck Engineering" icon_state = "lowerengineering" fake_zlevel = 2 // lowerdeck /area/almayer/engineering/engineering_workshop - name = "\improper Engineering Workshop" + name = "\improper Lower Deck Engineering Workshop" icon_state = "workshop" fake_zlevel = 2 // lowerdeck @@ -160,19 +175,22 @@ fake_zlevel = 2 // lowerdeck soundscape_playlist = SCAPE_PL_ENG soundscape_interval = 15 + hijack_evacuation_area = TRUE + hijack_evacuation_weight = 0.2 + hijack_evacuation_type = EVACUATION_TYPE_ADDITIVE /area/almayer/engineering/starboard_atmos - name = "\improper Atmospherics Starboard" + name = "\improper Upper Deck Starboard Atmospherics" icon_state = "starboardatmos" fake_zlevel = 1 // upperdeck /area/almayer/engineering/port_atmos - name = "\improper Atmospherics Port" + name = "\improper Upper Deck Port Atmospherics" icon_state = "portatmos" fake_zlevel = 1 // upperdeck /area/almayer/engineering/laundry - name = "\improper Laundry Room" + name = "\improper Upper Deck Laundry Room" icon_state = "laundry" fake_zlevel = 1 // upperdeck @@ -183,6 +201,9 @@ name = "\improper Astronavigational Deck" icon_state = "astronavigation" fake_zlevel = 2 // lowerdeck + hijack_evacuation_area = TRUE + hijack_evacuation_weight = 1.1 + hijack_evacuation_type = EVACUATION_TYPE_MULTIPLICATIVE /area/almayer/shipboard/panic name = "\improper Hangar Panic Room" @@ -190,17 +211,17 @@ fake_zlevel = 2 // lowerdeck /area/almayer/shipboard/starboard_missiles - name = "\improper Missile Tubes Starboard" + name = "\improper Upper Deck Starboard Missile Tubes" icon_state = "starboardmissile" fake_zlevel = 1 // upperdeck /area/almayer/shipboard/port_missiles - name = "\improper Missile Tubes Port" + name = "\improper Upper Deck Port Missile Tubes" icon_state = "portmissile" fake_zlevel = 1 // upperdeck /area/almayer/shipboard/weapon_room - name = "\improper Weapon Control Room" + name = "\improper Lower Deck Weapon Control" icon_state = "weaponroom" fake_zlevel = 2 // lowerdeck @@ -208,12 +229,12 @@ flags_area = AREA_NOTUNNEL /area/almayer/shipboard/starboard_point_defense - name = "\improper Point Defense Starboard" + name = "\improper Lower Deck Starboard Point Defense" icon_state = "starboardpd" fake_zlevel = 2 // lowerdeck /area/almayer/shipboard/port_point_defense - name = "\improper Point Defense Port" + name = "\improper Lower Deck Port Point Defense" icon_state = "portpd" fake_zlevel = 2 // lowerdeck @@ -279,7 +300,7 @@ icon_state = "chiefmpoffice" /area/almayer/shipboard/sea_office - name = "\improper Senior Enlisted Advisor Office" + name = "\improper Lower Deck Senior Enlisted Advisor Office" icon_state = "chiefmpoffice" fake_zlevel = 2 // lowerdeck @@ -305,7 +326,7 @@ soundscape_interval = 50 /area/almayer/hallways/vehiclehangar - name = "\improper Vehicle Storage" + name = "\improper Lower Deck Vehicle Storage" icon_state = "exoarmor" fake_zlevel = 2 @@ -313,135 +334,136 @@ minimap_color = MINIMAP_AREA_COLONY /area/almayer/living/tankerbunks - name = "\improper Vehicle Crew Bunks" + name = "\improper Lower Deck Vehicle Crew Bunks" icon_state = "livingspace" fake_zlevel = 2 /area/almayer/living/auxiliary_officer_office - name = "\improper Auxiliary Support Officer office" + name = "\improper Lower Deck Auxiliary Support Officer office" icon_state = "livingspace" fake_zlevel = 2 /area/almayer/squads/tankdeliveries - name = "\improper Vehicle ASRS" + name = "\improper Lower Deck Vehicle ASRS" icon_state = "req" fake_zlevel = 2 /area/almayer/hallways/exoarmor - name = "\improper Vehicle Armor Storage" + name = "\improper Lower Deck Vehicle Armor Storage" icon_state = "exoarmor" fake_zlevel = 2 // lowerdeck /area/almayer/hallways/repair_bay - name = "\improper Deployment Workshop" + name = "\improper Lower Deck Deployment Workshop" icon_state = "dropshiprepair" fake_zlevel = 2 // lowerdeck /area/almayer/hallways/mission_planner - name = "\improper Dropship Central Computer Room" + name = "\improper Lower Deck Dropship Central Computer Room" icon_state = "missionplanner" fake_zlevel = 2 // lowerdeck /area/almayer/hallways/starboard_umbilical - name = "\improper Umbilical Starboard" + name = "\improper Lower Deck Starboard Umbilical Hallway" icon_state = "starboardumbilical" fake_zlevel = 2 // lowerdeck /area/almayer/hallways/port_umbilical - name = "\improper Umbilical Port" + name = "\improper Lower Deck Port Umbilical Hallway" icon_state = "portumbilical" fake_zlevel = 2 // lowerdeck /area/almayer/hallways/aft_hallway - name = "\improper Hallway Aft" + name = "\improper Upper Deck Aft Hallway" icon_state = "aft" fake_zlevel = 1 // upperdeck /area/almayer/hallways/stern_hallway - name = "\improper Hallway Stern" + name = "\improper Upper Deck Stern Hallway" icon_state = "stern" fake_zlevel = 1 // upperdeck /area/almayer/hallways/port_hallway - name = "\improper Hallway Port" + name = "\improper Lower Deck Port Hallway" icon_state = "port" fake_zlevel = 2 // lowerdeck /area/almayer/hallways/starboard_hallway - name = "\improper Hallway Starboard" + name = "\improper Lower Deck Starboard Hallway" icon_state = "starboard" fake_zlevel = 2 // lowerdeck /area/almayer/stair_clone - name = "\improper Stairs" + name = "\improper Lower Deck Stairs" icon_state = "stairs_lowerdeck" fake_zlevel = 2 // lowerdeck resin_construction_allowed = FALSE /area/almayer/stair_clone/upper + name = "\improper Upper Deck Stairs" icon_state = "stairs_upperdeck" fake_zlevel = 1 // upperdeck /area/almayer/hull/lower_hull - name = "\improper Hull Lower" + name = "\improper Lower Deck Hull" icon_state = "lowerhull" fake_zlevel = 2 // lowerdeck /area/almayer/hull/upper_hull - name = "\improper Hull Upper" + name = "\improper Upper Deck Hull" icon_state = "upperhull" fake_zlevel = 1 // upperdeck /area/almayer/hull/upper_hull/u_f_s - name = "\improper Upper Fore-Starboard Hull" + name = "\improper Upper Deck Fore-Starboard Hull" icon_state = "upperhull" /area/almayer/hull/upper_hull/u_m_s - name = "\improper Upper Midship-Starboard Hull" + name = "\improper Upper Deck Starboard-Midship Hull" icon_state = "upperhull" /area/almayer/hull/upper_hull/u_a_s - name = "\improper Upper Aft-Starboard Hull" + name = "\improper Upper Deck Starboard-Aft Hull" icon_state = "upperhull" /area/almayer/hull/upper_hull/u_f_p - name = "\improper Upper Fore-Port Hull" + name = "\improper Upper Deck Port-Fore Hull" icon_state = "upperhull" /area/almayer/hull/upper_hull/u_m_p - name = "\improper Upper Midship-Port Hull" + name = "\improper Upper Deck Port-Midship Hull" icon_state = "upperhull" /area/almayer/hull/upper_hull/u_a_p - name = "\improper Upper Aft-Port Hull" + name = "\improper Upper Deck Port-Aft Hull" icon_state = "upperhull" /area/almayer/hull/lower_hull/l_f_s - name = "\improper Lower Fore-Starboard Hull" + name = "\improper Lower Deck Starboard-Fore Hull" icon_state = "upperhull" /area/almayer/hull/lower_hull/l_m_s - name = "\improper Lower Midship-Starboard Hull" + name = "\improper Lower Deck Starboard-Midship Hull" icon_state = "upperhull" /area/almayer/hull/lower_hull/l_a_s - name = "\improper Lower Aft-Starboard Hull" + name = "\improper Lower Deck Starboard Hull" icon_state = "upperhull" /area/almayer/hull/lower_hull/l_f_p - name = "\improper Lower Fore-Port Hull" + name = "\improper Lower Deck Port-Fore Hull" icon_state = "upperhull" /area/almayer/hull/lower_hull/l_m_p - name = "\improper Lower Midship-Port Hull" + name = "\improper Lower Deck Port-Midship Hull" icon_state = "upperhull" /area/almayer/hull/lower_hull/l_a_p - name = "\improper Lower Aft-Port Hull" + name = "\improper Lower Deck Port-Aft Hull" icon_state = "upperhull" /area/almayer/living/cryo_cells - name = "\improper Cryo Cells" + name = "\improper Lower Deck Cryo Cells" icon_state = "cryo" fake_zlevel = 2 // lowerdeck @@ -451,22 +473,22 @@ fake_zlevel = 2 // lowerdeck /area/almayer/living/port_emb - name = "\improper Extended Mission Bunks" + name = "\improper Lower Deck Port Extended Mission Bunks" icon_state = "portemb" fake_zlevel = 2 // lowerdeck /area/almayer/living/starboard_emb - name = "\improper Extended Mission Bunks" + name = "\improper Lower Deck Starboard Extended Mission Bunks" icon_state = "starboardemb" fake_zlevel = 2 // lowerdeck /area/almayer/living/port_garden - name = "\improper Garden" + name = "\improper Port Garden" icon_state = "portemb" fake_zlevel = 1 // upperdeck /area/almayer/living/starboard_garden - name = "\improper Garden" + name = "\improper Starboard Garden" icon_state = "starboardemb" fake_zlevel = 1 // upperdeck @@ -481,12 +503,12 @@ fake_zlevel = 2 // lowerdeck /area/almayer/living/officer_rnr - name = "\improper Officer's Lounge" + name = "\improper Upper Deck Officer's Lounge" icon_state = "officerrnr" fake_zlevel = 1 // upperdeck /area/almayer/living/officer_study - name = "\improper Officer's Study" + name = "\improper Upper Deck Officer's Study" icon_state = "officerstudy" fake_zlevel = 1 // upperdeck @@ -501,17 +523,17 @@ fake_zlevel = 2 // lowerdeck /area/almayer/living/gym - name = "\improper Gym" + name = "\improper Lower Deck Gym" icon_state = "officerrnr" fake_zlevel = 2 // lowerdeck /area/almayer/living/cafeteria_officer - name = "\improper Officer Cafeteria" + name = "\improper Upper Deck Officer Cafeteria" icon_state = "food" fake_zlevel = 1 // upperdeck /area/almayer/living/offices - name = "\improper Conference Office" + name = "\improper Lower Deck Conference Office" icon_state = "briefing" fake_zlevel = 2 // lowerdeck @@ -539,7 +561,7 @@ fake_zlevel = 1 // upperdeck /area/almayer/living/synthcloset - name = "\improper Synthetic Storage Closet" + name = "\improper Upper Deck Synthetic Storage Closet" icon_state = "livingspace" fake_zlevel = 1 // upperdeck @@ -712,18 +734,21 @@ icon_state = "lifeboat_pump" requires_power = 1 fake_zlevel = 1 + hijack_evacuation_area = TRUE + hijack_evacuation_weight = 0.1 + hijack_evacuation_type = EVACUATION_TYPE_ADDITIVE /area/almayer/lifeboat_pumps/north1 - name = "North West Lifeboat Fuel Pump" + name = "Starboard Fore Lifeboat Fuel Pump" /area/almayer/lifeboat_pumps/north2 - name = "North East Lifeboat Fuel Pump" + name = "Starboard Aft Lifeboat Fuel Pump" /area/almayer/lifeboat_pumps/south1 - name = "South West Lifeboat Fuel Pump" + name = "Port Fore Lifeboat Fuel Pump" /area/almayer/lifeboat_pumps/south2 - name = "South East Lifeboat Fuel Pump" + name = "Port Aft Lifeboat Fuel Pump" /area/almayer/command/lifeboat name = "\improper Lifeboat Docking Port" @@ -736,7 +761,7 @@ flags_area = AREA_NOTUNNEL /area/space/almayer/lifeboat_dock - name = "\improper Lifeboat Docking Port" + name = "\improper Port Lifeboat Docking" icon_state = "lifeboat" fake_zlevel = 1 // upperdeck flags_area = AREA_NOTUNNEL diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e1541f8368b8..e0590265840c 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -33,8 +33,11 @@ var/list/filter_data //For handling persistent filters - // Base transform matrix - var/matrix/base_transform = null + /// Base transform matrix, edited by admin tooling and such + var/matrix/base_transform + /// Last transform used before being compound with base_transform + /// This allows us to re-create transform if only base_transform changes + var/matrix/raw_transform ///Chemistry. var/datum/reagents/reagents = null @@ -116,7 +119,14 @@ directive is properly returned. //=========================================================================== - +// TODO make all atoms use set_density, do not rely on it at present +///Setter for the `density` variable to append behavior related to its changing. +/atom/proc/set_density(new_value) + SHOULD_CALL_PARENT(TRUE) + if(density == new_value) + return + . = density + density = new_value //atmos procs @@ -141,15 +151,27 @@ directive is properly returned. if(loc) return loc.return_gas() -// Updates the atom's transform -/atom/proc/apply_transform(matrix/M) - if(!base_transform) - transform = M - return +/// Updates the atom's transform compounding it with [/atom/var/base_transform] +/atom/proc/apply_transform(matrix/new_transform, time = 0, easing = (EASE_IN|EASE_OUT)) + var/matrix/base_copy + if(base_transform) + base_copy = matrix(base_transform) + else + base_copy = matrix() + raw_transform = matrix(new_transform) // Keep a copy to replay if needed - var/matrix/base_copy = matrix(base_transform) // Compose the base and applied transform in that order - transform = base_copy.Multiply(M) + var/matrix/complete = base_copy.Multiply(raw_transform) + + if(!time) + transform = complete + return + animate(src, transform = complete, time = time, easing = easing) + +/// Upates the base_transform which will be compounded with other transforms +/atom/proc/update_base_transform(matrix/new_transform, time = 0) + base_transform = matrix(new_transform) + apply_transform(raw_transform, time) /atom/proc/on_reagent_change() return @@ -183,7 +205,9 @@ directive is properly returned. return /atom/proc/emp_act(severity) - return + SHOULD_CALL_PARENT(TRUE) + + SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity) /atom/proc/in_contents_of(container)//can take class or object instance as argument if(ispath(container)) @@ -223,8 +247,8 @@ directive is properly returned. if(!examine_strings) log_debug("Attempted to create an examine block with no strings! Atom : [src], user : [user]") return - to_chat(user, examine_block(examine_strings.Join("\n"))) SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, examine_strings) + to_chat(user, examine_block(examine_strings.Join("\n"))) /atom/proc/get_examine_text(mob/user) . = list() @@ -699,10 +723,9 @@ Parameters are passed from New. usr.client.cmd_admin_emp(src) if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT)) - var/result = tgui_input_list(usr, "Choose the transformation to apply","Transform Mod", list("Scale","Translate","Rotate")) + var/result = tgui_input_list(usr, "Choose the transformation to apply","Transform Mod", list("Scale","Translate","Rotate", "Reflect X Axis", "Reflect Y Axis")) if(!result) return - var/matrix/M = transform if(!result) return switch(result) @@ -711,19 +734,37 @@ Parameters are passed from New. var/y = tgui_input_real_number(usr, "Choose y mod","Transform Mod") if(isnull(x) || isnull(y)) return - transform = M.Scale(x,y) + var/matrix/base_matrix = matrix(base_transform) + update_base_transform(base_matrix.Scale(x,y)) if("Translate") var/x = tgui_input_real_number(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") var/y = tgui_input_real_number(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") if(isnull(x) || isnull(y)) return - transform = M.Translate(x,y) + var/matrix/base_matrix = matrix(base_transform) + update_base_transform(base_matrix.Translate(x,y)) if("Rotate") var/angle = tgui_input_real_number(usr, "Choose angle to rotate","Transform Mod") if(isnull(angle)) return - transform = M.Turn(angle) - + var/matrix/base_matrix = matrix(base_transform) + update_base_transform(base_matrix.Turn(angle)) + if("Reflect X Axis") + var/matrix/current = matrix(base_transform) + var/matrix/reflector = matrix() + reflector.a = -1 + reflector.d = 0 + reflector.b = 0 + reflector.e = 1 + update_base_transform(current * reflector) + if("Reflect Y Axis") + var/matrix/current = matrix(base_transform) + var/matrix/reflector = matrix() + reflector.a = 1 + reflector.d = 0 + reflector.b = 0 + reflector.e = -1 + update_base_transform(current * reflector) SEND_SIGNAL(src, COMSIG_ATOM_VV_MODIFY_TRANSFORM) if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT)) diff --git a/code/game/cas_manager/datums/cas_fire_mission.dm b/code/game/cas_manager/datums/cas_fire_mission.dm index 0a04876414e7..cb43caec30bb 100644 --- a/code/game/cas_manager/datums/cas_fire_mission.dm +++ b/code/game/cas_manager/datums/cas_fire_mission.dm @@ -114,7 +114,7 @@ if(get_turf(M) == initial_turf) relative_dir = 0 else - relative_dir = get_dir(M, initial_turf) + relative_dir = Get_Compass_Dir(M, initial_turf) var/ds_identifier = "LARGE BIRD" if (M.mob_flags & KNOWS_TECHNOLOGY) @@ -132,7 +132,7 @@ if(get_turf(M) == initial_turf) relative_dir = 0 else - relative_dir = get_dir(M, initial_turf) + relative_dir = Get_Compass_Dir(M, initial_turf) var/ds_identifier = "LARGE BIRD" if (M.mob_flags & KNOWS_TECHNOLOGY) diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index effd3325f887..f047c4a5bf57 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -356,21 +356,27 @@ Additional game mode variables. else available_xenos_non_ssd += cur_xeno - // Only offer buried larva if there is no queue: - // This basically means this block of code will almost never execute, because we are instead relying on the hive cores/larva pops to handle their larva - // Technically this should be after a get_alien_candidates() call to be accurate, but we are intentionally trying to not call that proc as much as possible - if(GLOB.xeno_queue_candidate_count < 1) - var/datum/hive_status/hive - for(var/hivenumber in GLOB.hive_datum) - hive = GLOB.hive_datum[hivenumber] - if(!hive.hardcore && hive.stored_larva && (hive.hive_location || (world.time < XENO_BURIED_LARVA_TIME_LIMIT + SSticker.round_start_time))) - if(SSticker.mode && (SSticker.mode.flags_round_type & MODE_RANDOM_HIVE)) - available_xenos |= "any buried larva" - LAZYADD(available_xenos["any buried larva"], hive) - else - var/larva_option = "buried larva ([hive])" - available_xenos += larva_option - available_xenos[larva_option] = list(hive) + var/datum/hive_status/hive + for(var/hivenumber in GLOB.hive_datum) + hive = GLOB.hive_datum[hivenumber] + if(hive.hardcore) + continue + if(!hive.stored_larva) + continue + // Only offer buried larva if there is no queue because we are instead relying on the hive cores/larva pops to handle their larva: + // Technically this should be after a get_alien_candidates() call to be accurate, but we are intentionally trying to not call that proc as much as possible + if(hive.hive_location && GLOB.xeno_queue_candidate_count > 0) + continue + if(!hive.hive_location && (world.time > XENO_BURIED_LARVA_TIME_LIMIT + SSticker.round_start_time)) + continue + + if(SSticker.mode && (SSticker.mode.flags_round_type & MODE_RANDOM_HIVE)) + available_xenos |= "any buried larva" + LAZYADD(available_xenos["any buried larva"], hive) + else + var/larva_option = "buried larva ([hive])" + available_xenos += larva_option + available_xenos[larva_option] = list(hive) if(!available_xenos.len || (instant_join && !available_xenos_non_ssd.len)) if(!xeno_candidate.client || !xeno_candidate.client.prefs || !(xeno_candidate.client.prefs.be_special & BE_ALIEN_AFTER_DEATH)) @@ -423,7 +429,7 @@ Additional game mode variables. for(var/mob_name in picked_hive.banished_ckeys) if(picked_hive.banished_ckeys[mob_name] == xeno_candidate.ckey) to_chat(xeno_candidate, SPAN_WARNING("You are banished from the [picked_hive], you may not rejoin unless the Queen re-admits you or dies.")) - return + return FALSE if(isnewplayer(xeno_candidate)) var/mob/new_player/noob = xeno_candidate noob.close_spawn_windows() @@ -443,9 +449,6 @@ Additional game mode variables. return FALSE new_xeno = userInput - if(!xeno_candidate) - return FALSE - if(!(new_xeno in GLOB.living_xeno_list) || new_xeno.stat == DEAD) to_chat(xeno_candidate, SPAN_WARNING("You cannot join if the xenomorph is dead.")) return FALSE @@ -479,14 +482,14 @@ Additional game mode variables. else new_xeno = pick(available_xenos_non_ssd) //Just picks something at random. if(istype(new_xeno) && xeno_candidate && xeno_candidate.client) if(isnewplayer(xeno_candidate)) - var/mob/new_player/N = xeno_candidate - N.close_spawn_windows() + var/mob/new_player/noob = xeno_candidate + noob.close_spawn_windows() for(var/mob_name in new_xeno.hive.banished_ckeys) if(new_xeno.hive.banished_ckeys[mob_name] == xeno_candidate.ckey) to_chat(xeno_candidate, SPAN_WARNING("You are banished from this hive, You may not rejoin unless the Queen re-admits you or dies.")) - return + return FALSE if(transfer_xeno(xeno_candidate, new_xeno)) - return 1 + return TRUE to_chat(xeno_candidate, "JAS01: Something went wrong, tell a coder.") /datum/game_mode/proc/attempt_to_join_as_facehugger(mob/xeno_candidate) @@ -594,7 +597,14 @@ Additional game mode variables. for(var/obj/effect/alien/resin/special/pylon/cycled_pylon as anything in hive.hive_structures[XENO_STRUCTURE_PYLON]) if(cycled_pylon.lesser_drone_spawns >= 1) - selection_list += "[cycled_pylon.name] at [get_area(cycled_pylon)]" + var/pylon_number = 1 + var/pylon_name = "[cycled_pylon.name] at [get_area(cycled_pylon)]" + //For renaming the pylon if we have duplicates + var/pylon_selection_name = pylon_name + while(pylon_selection_name in selection_list) + pylon_selection_name = "[pylon_name] ([pylon_number])" + pylon_number ++ + selection_list += pylon_selection_name selection_list_structure += cycled_pylon if(!length(selection_list)) @@ -614,20 +624,21 @@ Additional game mode variables. /datum/game_mode/proc/transfer_xeno(xeno_candidate, mob/living/new_xeno) if(!xeno_candidate || !isxeno(new_xeno) || QDELETED(new_xeno)) return FALSE + var/datum/mind/xeno_candidate_mind if(ismind(xeno_candidate)) xeno_candidate_mind = xeno_candidate else if(ismob(xeno_candidate)) - var/mob/M = xeno_candidate - if(M.mind) - xeno_candidate_mind = M.mind + var/mob/xeno_candidate_mob = xeno_candidate + if(xeno_candidate_mob.mind) + xeno_candidate_mind = xeno_candidate_mob.mind else - xeno_candidate_mind = new /datum/mind(M.key, M.ckey) + xeno_candidate_mind = new /datum/mind(xeno_candidate_mob.key, xeno_candidate_mob.ckey) xeno_candidate_mind.active = TRUE xeno_candidate_mind.current = new_xeno else if(isclient(xeno_candidate)) - var/client/C = xeno_candidate - xeno_candidate_mind = new /datum/mind(C.key, C.ckey) + var/client/xeno_candidate_client = xeno_candidate + xeno_candidate_mind = new /datum/mind(xeno_candidate_client.key, xeno_candidate_client.ckey) xeno_candidate_mind.active = TRUE xeno_candidate_mind.current = new_xeno else diff --git a/code/game/gamemodes/cm_self_destruct.dm b/code/game/gamemodes/cm_self_destruct.dm deleted file mode 100644 index 07c9c43a4768..000000000000 --- a/code/game/gamemodes/cm_self_destruct.dm +++ /dev/null @@ -1,478 +0,0 @@ -/* -TODO -Look into animation screen not showing on self-destruct and other weirdness -Intergrate distress into this controller. -Finish nanoui conversion for comm console. -Make sure people who get nuked and wake up from SSD don't live. -Add flashing lights to evac. //DEFERRED TO BETTER LIGHTING -Finish the game mode announcement thing. -Fix escape doors to work properly. -*/ - -/* -How this works: - -First: All of the linking is done automatically on world start, so nothing needs to be done on that end other than making -sure that objects are actually placed in the game world. If not, the game will error and let you know about it. But you -don't need to modify variables or worry about area placement. It's all done for you. -The rods, for example, configure the time per activation based on their number. Shuttles link their own machines via area. -Nothing in this controller is linked to game mode, so it's stand alone, more or less, but it's best used during a game mode. -Admins have a lot of tools in their disposal via the check antagonist panel, and devs can access the VV of this controller -through that panel. - -Second: The communication console handles most of the IC triggers for activating these functions, the rest is handled elsewhere. -Check communications.dm for that. shuttle_controller.dm handles the set up for the escape pods. escape_pods.dm handles most of the -functions of the escape pods themselves. This file would likely need to be broken down into individual parts at some point in the -future. - -Evacuation takes place when sufficient alert level is reaised and a distress beacon was launched. All of the evac pods come online -and open their doors to allow entry inside. Characters may then get inside of the cryo units to before the shuttles automatically launch. -If wanted, a nearby controller object may launch each individual shuttle early. Only three people may ride on a shuttle to escape, -otherwise the launch will fail and the shuttle will become inoperable. -Any launched shuttles are taken out of the game. If the evacuation is canceled, any persons inside of the cryo tubes will be ejected. -They may temporarily open the door to exit if they are stuck inside after evac is canceled. - -When the self-destruct is enabled, the console comes online. This usually happens during an evacuation. Once the console is -interacted with, it fires up the self-destruct sequence. Several rods rise and must be interacted with in order to arm the system. -Once that happens, the console must be interacted with again to trigger the self-destruct. The self-destruct may also be -canceled from the console. - -The self-destruct may also happen if a nuke is detonated on the ship's zlevel; if it is detonated elsewhere, the ship will not blow up. -Regardless of where it's detonated, or how, a successful detonation will end the round or automatically restart the game. - -All of the necessary difines are stored under mode.dm in defines. -*/ - -var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initited elsewhere so that the world has a chance to load in. - -/datum/authority/branch/evacuation - var/name = "Evacuation Authority" - var/evac_time //Time the evacuation was initiated. - var/evac_status = EVACUATION_STATUS_STANDING_BY //What it's doing now? It can be standing by, getting ready to launch, or finished. - - var/obj/structure/machinery/self_destruct/console/dest_master //The main console that does the brunt of the work. - var/dest_rods[] //Slave devices to make the explosion work. - var/dest_cooldown //How long it takes between rods, determined by the amount of total rods present. - var/dest_index = 1 //What rod the thing is currently on. - var/dest_status = NUKE_EXPLOSION_INACTIVE - var/dest_started_at = 0 - - var/flags_scuttle = NO_FLAGS - -/datum/authority/branch/evacuation/New() - ..() - dest_master = locate() - if(!dest_master) - log_debug("ERROR CODE SD1: could not find master self-destruct console") - to_world(SPAN_DEBUG("ERROR CODE SD1: could not find master self-destruct console")) - return FALSE - dest_rods = new - for(var/obj/structure/machinery/self_destruct/rod/I in dest_master.loc.loc) dest_rods += I - if(!dest_rods.len) - log_debug("ERROR CODE SD2: could not find any self-destruct rods") - to_world(SPAN_DEBUG("ERROR CODE SD2: could not find any self-destruct rods")) - QDEL_NULL(dest_master) - return FALSE - dest_cooldown = SELF_DESTRUCT_ROD_STARTUP_TIME / dest_rods.len - dest_master.desc = "The main operating panel for a self-destruct system. It requires very little user input, but the final safety mechanism is manually unlocked.\nAfter the initial start-up sequence, [dest_rods.len] control rods must be armed, followed by manually flipping the detonation switch." - -/** - * This proc returns the ship's z level list (or whatever specified), - * when an evac/self-destruct happens. - */ -/datum/authority/branch/evacuation/proc/get_affected_zlevels() - //Nuke is not in progress, end the round on ship only. - if(dest_status < NUKE_EXPLOSION_IN_PROGRESS && SSticker?.mode.is_in_endgame) - . = SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP)) - return - -//========================================================================================= -//========================================================================================= -//=====================================EVACUATION========================================== -//========================================================================================= -//========================================================================================= - - -/datum/authority/branch/evacuation/proc/initiate_evacuation(force=0) //Begins the evacuation procedure. - if(force || (evac_status == EVACUATION_STATUS_STANDING_BY && !(flags_scuttle & FLAGS_EVACUATION_DENY))) - evac_time = world.time - evac_status = EVACUATION_STATUS_INITIATING - ai_announcement("Attention. Emergency. All personnel must evacuate immediately. You have [round(EVACUATION_ESTIMATE_DEPARTURE/60,1)] minute\s until departure.", 'sound/AI/evacuate.ogg') - xeno_message_all("A wave of adrenaline ripples through the hive. The fleshy creatures are trying to escape!") - - for(var/obj/structure/machinery/status_display/SD in machines) - if(is_mainship_level(SD.z)) - SD.set_picture("evac") - for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile) - shuttle.prepare_evac() - activate_lifeboats() - process_evacuation() - return TRUE - -/datum/authority/branch/evacuation/proc/cancel_evacuation() //Cancels the evac procedure. Useful if admins do not want the marines leaving. - if(evac_status == EVACUATION_STATUS_INITIATING) - evac_time = null - evac_status = EVACUATION_STATUS_STANDING_BY - deactivate_lifeboats() - ai_announcement("Evacuation has been cancelled.", 'sound/AI/evacuate_cancelled.ogg') - - if(get_security_level() == "red") - for(var/obj/structure/machinery/status_display/SD in machines) - if(is_mainship_level(SD.z)) - SD.set_picture("redalert") - - for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile) - shuttle.cancel_evac() - return TRUE - -/datum/authority/branch/evacuation/proc/begin_launch() //Launches the pods. - if(evac_status == EVACUATION_STATUS_INITIATING) - evac_status = EVACUATION_STATUS_IN_PROGRESS //Cannot cancel at this point. All shuttles are off. - spawn() //One of the few times spawn() is appropriate. No need for a new proc. - ai_announcement("WARNING: Evacuation order confirmed. Launching escape pods.", 'sound/AI/evacuation_confirmed.ogg') - addtimer(CALLBACK(src, PROC_REF(launch_lifeboats)), 10 SECONDS) // giving some time to board lifeboats - - for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile) - shuttle.evac_launch() - sleep(50) - - sleep(300) //Sleep 30 more seconds to make sure everyone had a chance to leave. - var/lifesigns = 0 - // lifesigns += P.passengers - var/obj/docking_port/mobile/crashable/lifeboat/lifeboat1 = SSshuttle.getShuttle(MOBILE_SHUTTLE_LIFEBOAT_PORT) - lifeboat1.check_for_survivors() - lifesigns += lifeboat1.survivors - var/obj/docking_port/mobile/crashable/lifeboat/lifeboat2 = SSshuttle.getShuttle(MOBILE_SHUTTLE_LIFEBOAT_STARBOARD) - lifeboat2.check_for_survivors() - lifesigns += lifeboat2.survivors - ai_announcement("ATTENTION: Evacuation complete. Outbound lifesigns detected: [lifesigns ? lifesigns : "none"].", 'sound/AI/evacuation_complete.ogg') - evac_status = EVACUATION_STATUS_COMPLETE - return TRUE - -/datum/authority/branch/evacuation/proc/process_evacuation() //Process the timer. - set background = 1 - - spawn while(evac_status == EVACUATION_STATUS_INITIATING) //If it's not departing, no need to process. - if(world.time >= evac_time + EVACUATION_AUTOMATIC_DEPARTURE) begin_launch() - sleep(10) //One second. - -/datum/authority/branch/evacuation/proc/get_status_panel_eta() - switch(evac_status) - if(EVACUATION_STATUS_INITIATING) - var/eta = EVACUATION_ESTIMATE_DEPARTURE - . = "[(eta / 60) % 60]:[add_zero(num2text(eta % 60), 2)]" - if(EVACUATION_STATUS_IN_PROGRESS) . = "NOW" - -// LIFEBOATS CORNER -/datum/authority/branch/evacuation/proc/activate_lifeboats() - for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks) - var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked() - if(lifeboat && lifeboat.available) - lifeboat.status = LIFEBOAT_ACTIVE - lifeboat_dock.open_dock() - - -/datum/authority/branch/evacuation/proc/deactivate_lifeboats() - for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks) - var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked() - if(lifeboat && lifeboat.available) - lifeboat.status = LIFEBOAT_INACTIVE - -/datum/authority/branch/evacuation/proc/launch_lifeboats() - for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks) - var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked() - if(lifeboat && lifeboat.available) - lifeboat.evac_launch() - -//========================================================================================= -//========================================================================================= -//=====================================SELF DETRUCT======================================== -//========================================================================================= -//========================================================================================= - -/datum/authority/branch/evacuation/proc/enable_self_destruct(force=0) - if(force || (dest_status == NUKE_EXPLOSION_INACTIVE && !(flags_scuttle & FLAGS_SELF_DESTRUCT_DENY))) - dest_status = NUKE_EXPLOSION_ACTIVE - dest_master.lock_or_unlock() - dest_started_at = world.time - set_security_level(SEC_LEVEL_DELTA) //also activate Delta alert, to open the SD shutters. - spawn(0) - for(var/obj/structure/machinery/door/poddoor/shutters/almayer/D in machines) - if(D.id == "sd_lockdown") - D.open() - return TRUE - -//Override is for admins bypassing normal player restrictions. -/datum/authority/branch/evacuation/proc/cancel_self_destruct(override) - if(dest_status == NUKE_EXPLOSION_ACTIVE) - var/obj/structure/machinery/self_destruct/rod/I - var/i - for(i in EvacuationAuthority.dest_rods) - I = i - if(I.active_state == SELF_DESTRUCT_MACHINE_ARMED && !override) - dest_master.state(SPAN_WARNING("WARNING: Unable to cancel detonation. Please disarm all control rods.")) - return FALSE - - dest_status = NUKE_EXPLOSION_INACTIVE - dest_master.in_progress = 1 - dest_started_at = 0 - for(i in dest_rods) - I = i - if(I.active_state == SELF_DESTRUCT_MACHINE_ACTIVE || (I.active_state == SELF_DESTRUCT_MACHINE_ARMED && override)) I.lock_or_unlock(1) - dest_master.lock_or_unlock(1) - dest_index = 1 - ai_announcement("The emergency destruct system has been deactivated.", 'sound/AI/selfdestruct_deactivated.ogg') - if(evac_status == EVACUATION_STATUS_STANDING_BY) //the evac has also been cancelled or was never started. - set_security_level(SEC_LEVEL_RED, TRUE) //both SD and evac are inactive, lowering the security level. - return TRUE - -/datum/authority/branch/evacuation/proc/initiate_self_destruct(override) - if(dest_status < NUKE_EXPLOSION_IN_PROGRESS) - var/obj/structure/machinery/self_destruct/rod/I - var/i - for(i in dest_rods) - I = i - if(I.active_state != SELF_DESTRUCT_MACHINE_ARMED && !override) - dest_master.state(SPAN_WARNING("WARNING: Unable to trigger detonation. Please arm all control rods.")) - return FALSE - dest_master.in_progress = !dest_master.in_progress - for(i in EvacuationAuthority.dest_rods) - I = i - I.in_progress = 1 - ai_announcement("DANGER. DANGER. Self-destruct system activated. DANGER. DANGER. Self-destruct in progress. DANGER. DANGER.") - trigger_self_destruct(,,override) - return TRUE - -/datum/authority/branch/evacuation/proc/trigger_self_destruct(list/z_levels = SSmapping.levels_by_trait(ZTRAIT_MARINE_MAIN_SHIP), origin = dest_master, override = FALSE, end_type = NUKE_EXPLOSION_FINISHED, play_anim = TRUE, end_round = TRUE) - set waitfor = 0 - if(dest_status < NUKE_EXPLOSION_IN_PROGRESS) //One more check for good measure, in case it's triggered through a bomb instead of the destruct mechanism/admin panel. - dest_status = NUKE_EXPLOSION_IN_PROGRESS - playsound(origin, 'sound/machines/Alarm.ogg', 75, 0, 30) - world << pick('sound/theme/nuclear_detonation1.ogg','sound/theme/nuclear_detonation2.ogg') - - var/ship_status = 1 - for(var/i in z_levels) - if(is_mainship_level(i)) - ship_status = 0 //Destroyed. - break - - var/list/alive_mobs = list() //Everyone who will be destroyed on the zlevel(s). - var/list/dead_mobs = list() //Everyone who only needs to see the cinematic. - for(var/mob/current_mob as anything in GLOB.mob_list) //This only does something cool for the people about to die, but should prove pretty interesting. - var/turf/current_turf = get_turf(current_mob) - if(!current_mob || !current_mob.loc || !current_turf) - continue //In case something changes when we sleep(). - if(current_mob.stat == DEAD) - dead_mobs |= current_mob - continue - if(current_turf.z in z_levels) - alive_mobs |= current_mob - shake_camera(current_mob, 110, 4) - - - sleep(100) - /*Hardcoded for now, since this was never really used for anything else. - Would ideally use a better system for showing cutscenes.*/ - var/atom/movable/screen/cinematic/explosion/C = new - - if(play_anim) - for(var/mob/current_mob as anything in alive_mobs + dead_mobs) - if(current_mob && current_mob.loc && current_mob.client) - current_mob.client.add_to_screen(C) //They may have disconnected in the mean time. - - sleep(15) //Extra 1.5 seconds to look at the ship. - flick(override ? "intro_override" : "intro_nuke", C) - sleep(35) - for(var/mob/current_mob in alive_mobs) - if(current_mob && current_mob.loc) //Who knows, maybe they escaped, or don't exist anymore. - var/turf/current_mob_turf = get_turf(current_mob) - if(!current_mob_turf) - continue - if(current_mob_turf.z in z_levels) - if(istype(current_mob.loc, /obj/structure/closet/secure_closet/freezer/fridge)) - continue - current_mob.death(create_cause_data("nuclear explosion")) - else - if(play_anim) - current_mob.client.remove_from_screen(C) //those who managed to escape the z level at last second shouldn't have their view obstructed. - if(play_anim) - flick(ship_status ? "ship_spared" : "ship_destroyed", C) - C.icon_state = ship_status ? "summary_spared" : "summary_destroyed" - world << sound('sound/effects/explosionfar.ogg') - - if(end_round) - dest_status = end_type - - sleep(5) - if(SSticker.mode) - SSticker.mode.check_win() - - if(!SSticker.mode) //Just a safety, just in case a mode isn't running, somehow. - to_world(SPAN_ROUNDBODY("Resetting in 30 seconds!")) - sleep(300) - log_game("Rebooting due to nuclear detonation.") - world.Reboot() - return TRUE - -/datum/authority/branch/evacuation/proc/process_self_destruct() - set background = 1 - - spawn while(dest_master && dest_master.loc && dest_master.active_state == SELF_DESTRUCT_MACHINE_ARMED && dest_status == NUKE_EXPLOSION_ACTIVE && dest_index <= dest_rods.len) - var/obj/structure/machinery/self_destruct/rod/I = dest_rods[dest_index] - if(world.time >= dest_cooldown + I.activate_time) - I.lock_or_unlock() //Unlock it. - if(++dest_index <= dest_rods.len) - I = dest_rods[dest_index]//Start the next sequence. - I.activate_time = world.time - sleep(10) //Checks every second. Could integrate into another controller for better tracking. - -//Generic parent base for the self_destruct items. -/obj/structure/machinery/self_destruct - icon = 'icons/obj/structures/machinery/self_destruct.dmi' - icon_state = "console_1" - var/base_icon_state = "console" - use_power = USE_POWER_NONE //Runs unpowered, may need to change later. - density = FALSE - anchored = TRUE //So it doesn't go anywhere. - unslashable = TRUE - unacidable = TRUE //Cannot C4 it either. - mouse_opacity = FALSE //No need to click or interact with this initially. - var/in_progress = 0 //Cannot interact with while it's doing something, like an animation. - var/active_state = SELF_DESTRUCT_MACHINE_INACTIVE //What step of the process it's on. - -/obj/structure/machinery/self_destruct/Initialize(mapload, ...) - . = ..() - icon_state = "[base_icon_state]_1" - -/obj/structure/machinery/self_destruct/Destroy() - . = ..() - machines -= src - operator = null - -/obj/structure/machinery/self_destruct/ex_act(severity) - return FALSE - -/obj/structure/machinery/self_destruct/attack_hand() - if(..() || in_progress) - return FALSE //This check is backward, ugh. - return TRUE - -//Add sounds. -/obj/structure/machinery/self_destruct/proc/lock_or_unlock(lock) - set waitfor = 0 - in_progress = 1 - flick("[base_icon_state]" + (lock? "_5" : "_2"),src) - sleep(9) - mouse_opacity = !mouse_opacity - icon_state = "[base_icon_state]" + (lock? "_1" : "_3") - in_progress = 0 - active_state = active_state > SELF_DESTRUCT_MACHINE_INACTIVE ? SELF_DESTRUCT_MACHINE_INACTIVE : SELF_DESTRUCT_MACHINE_ACTIVE - -/obj/structure/machinery/self_destruct/console - name = "self-destruct control panel" - icon_state = "console_1" - base_icon_state = "console" - req_one_access = list(ACCESS_MARINE_CO, ACCESS_MARINE_SENIOR) - -/obj/structure/machinery/self_destruct/console/Destroy() - . = ..() - EvacuationAuthority.dest_master = null - EvacuationAuthority.dest_rods = null - -/obj/structure/machinery/self_destruct/console/lock_or_unlock(lock) - playsound(src, 'sound/machines/hydraulics_1.ogg', 25, 1) - ..() - -//TODO: Add sounds. -/obj/structure/machinery/self_destruct/console/attack_hand(mob/user) - if(inoperable()) - return - - tgui_interact(user) - -/obj/structure/machinery/self_destruct/console/tgui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "SelfDestructConsole", name) - ui.open() - -/obj/structure/machinery/sleep_console/ui_status(mob/user, datum/ui_state/state) - . = ..() - if(inoperable()) - return UI_CLOSE - - -/obj/structure/machinery/self_destruct/console/ui_data(mob/user) - var/list/data = list() - - data["dest_status"] = active_state - - return data - -/obj/structure/machinery/self_destruct/console/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) - . = ..() - if(.) - return - - switch(action) - if("dest_start") - to_chat(usr, SPAN_NOTICE("You press a few keys on the panel.")) - to_chat(usr, SPAN_NOTICE("The system must be booting up the self-destruct sequence now.")) - playsound(src.loc, 'sound/items/rped.ogg', 25, TRUE) - sleep(2 SECONDS) - ai_announcement("Danger. The emergency destruct system is now activated. The ship will detonate in T-minus 20 minutes. Automatic detonation is unavailable. Manual detonation is required.", 'sound/AI/selfdestruct.ogg') - active_state = SELF_DESTRUCT_MACHINE_ARMED //Arm it here so the process can execute it later. - var/obj/structure/machinery/self_destruct/rod/I = EvacuationAuthority.dest_rods[EvacuationAuthority.dest_index] - I.activate_time = world.time - EvacuationAuthority.process_self_destruct() - . = TRUE - - if("dest_trigger") - EvacuationAuthority.initiate_self_destruct() - . = TRUE - - if("dest_cancel") - if(!allowed(usr)) - to_chat(usr, SPAN_WARNING("You don't have the necessary clearance to cancel the emergency destruct system!")) - return - EvacuationAuthority.cancel_self_destruct() - . = TRUE - -/obj/structure/machinery/self_destruct/rod - name = "self-destruct control rod" - desc = "It is part of a complicated self-destruct sequence, but relatively simple to operate. Twist to arm or disarm." - icon_state = "rod_1" - base_icon_state = "rod" - layer = BELOW_OBJ_LAYER - var/activate_time - -/obj/structure/machinery/self_destruct/rod/Destroy() - . = ..() - if(EvacuationAuthority && EvacuationAuthority.dest_rods) - EvacuationAuthority.dest_rods -= src - -/obj/structure/machinery/self_destruct/rod/lock_or_unlock(lock) - playsound(src, 'sound/machines/hydraulics_2.ogg', 25, 1) - ..() - if(lock) - activate_time = null - density = FALSE - layer = initial(layer) - else - density = TRUE - layer = ABOVE_OBJ_LAYER - -/obj/structure/machinery/self_destruct/rod/attack_hand(mob/user) - if(..()) - switch(active_state) - if(SELF_DESTRUCT_MACHINE_ACTIVE) - to_chat(user, SPAN_NOTICE("You twist and release the control rod, arming it.")) - playsound(src, 'sound/machines/switch.ogg', 25, 1) - icon_state = "rod_4" - active_state = SELF_DESTRUCT_MACHINE_ARMED - if(SELF_DESTRUCT_MACHINE_ARMED) - to_chat(user, SPAN_NOTICE("You twist and release the control rod, disarming it.")) - playsound(src, 'sound/machines/switch.ogg', 25, 1) - icon_state = "rod_3" - active_state = SELF_DESTRUCT_MACHINE_ACTIVE - else to_chat(user, SPAN_WARNING("The control rod is not ready.")) diff --git a/code/game/gamemodes/colonialmarines/colonialmarines.dm b/code/game/gamemodes/colonialmarines/colonialmarines.dm index df04873ac140..7b1c695ade2b 100644 --- a/code/game/gamemodes/colonialmarines/colonialmarines.dm +++ b/code/game/gamemodes/colonialmarines/colonialmarines.dm @@ -297,29 +297,25 @@ if(SSticker.current_state != GAME_STATE_PLAYING) return - var/living_player_list[] = count_humans_and_xenos(EvacuationAuthority.get_affected_zlevels()) + var/living_player_list[] = count_humans_and_xenos(get_affected_zlevels()) var/num_humans = living_player_list[1] var/num_xenos = living_player_list[2] if(force_end_at && world.time > force_end_at) round_finished = MODE_INFESTATION_X_MINOR - if(EvacuationAuthority.dest_status == NUKE_EXPLOSION_FINISHED) - round_finished = MODE_GENERIC_DRAW_NUKE //Nuke went off, ending the round. - if(EvacuationAuthority.dest_status == NUKE_EXPLOSION_GROUND_FINISHED) - round_finished = MODE_INFESTATION_M_MINOR //Nuke went off, ending the round. - if(EvacuationAuthority.dest_status < NUKE_EXPLOSION_IN_PROGRESS) //If the nuke ISN'T in progress. We do not want to end the round before it detonates. - if(!num_humans && num_xenos) //No humans remain alive. - round_finished = MODE_INFESTATION_X_MAJOR //Evacuation did not take place. Everyone died. - else if(num_humans && !num_xenos) - if(SSticker.mode && SSticker.mode.is_in_endgame) - round_finished = MODE_INFESTATION_X_MINOR //Evacuation successfully took place. - else - SSticker.roundend_check_paused = TRUE - round_finished = MODE_INFESTATION_M_MAJOR //Humans destroyed the xenomorphs. - ares_conclude() - addtimer(VARSET_CALLBACK(SSticker, roundend_check_paused, FALSE), MARINE_MAJOR_ROUND_END_DELAY) - else if(!num_humans && !num_xenos) - round_finished = MODE_INFESTATION_DRAW_DEATH //Both were somehow destroyed. + + if(!num_humans && num_xenos) //No humans remain alive. + round_finished = MODE_INFESTATION_X_MAJOR //Evacuation did not take place. Everyone died. + else if(num_humans && !num_xenos) + if(SSticker.mode && SSticker.mode.is_in_endgame) + round_finished = MODE_INFESTATION_X_MINOR //Evacuation successfully took place. + else + SSticker.roundend_check_paused = TRUE + round_finished = MODE_INFESTATION_M_MAJOR //Humans destroyed the xenomorphs. + ares_conclude() + addtimer(VARSET_CALLBACK(SSticker, roundend_check_paused, FALSE), MARINE_MAJOR_ROUND_END_DELAY) + else if(!num_humans && !num_xenos) + round_finished = MODE_INFESTATION_DRAW_DEATH //Both were somehow destroyed. /datum/game_mode/colonialmarines/check_queen_status(hivenumber) set waitfor = 0 @@ -367,7 +363,7 @@ round_statistics.current_map.total_marine_victories++ round_statistics.current_map.total_marine_majors++ if(MODE_INFESTATION_X_MINOR) - var/list/living_player_list = count_humans_and_xenos(EvacuationAuthority.get_affected_zlevels()) + var/list/living_player_list = count_humans_and_xenos(get_affected_zlevels()) if(living_player_list[1] && !living_player_list[2]) // If Xeno Minor but Xenos are dead and Humans are alive, see which faction is the last standing var/headcount = count_per_faction() var/living = headcount["total_headcount"] diff --git a/code/game/gamemodes/colonialmarines/huntergames.dm b/code/game/gamemodes/colonialmarines/huntergames.dm index c8c90fa51c0c..bd5302bf7ec0 100644 --- a/code/game/gamemodes/colonialmarines/huntergames.dm +++ b/code/game/gamemodes/colonialmarines/huntergames.dm @@ -11,11 +11,11 @@ #define HUNTER_GOOD_ITEM pick(\ 50; /obj/item/weapon/shield/riot, \ - 100; /obj/item/weapon/claymore, \ - 100; /obj/item/weapon/katana, \ + 100; /obj/item/weapon/sword, \ + 100; /obj/item/weapon/sword/katana, \ 100; /obj/item/weapon/harpoon/yautja, \ - 150; /obj/item/weapon/claymore/mercsword, \ - 200; /obj/item/weapon/claymore/mercsword/machete, \ + 150; /obj/item/weapon/sword, \ + 200; /obj/item/weapon/sword/machete, \ 125; /obj/item/weapon/twohanded/fireaxe, \ \ 100; /obj/item/device/binoculars, \ @@ -51,7 +51,7 @@ 300; /obj/item/tool/hatchet, \ 100; /obj/item/tool/scythe, \ 100; /obj/item/tool/kitchen/knife/butcher, \ - 50; /obj/item/weapon/katana/replica, \ + 50; /obj/item/weapon/sword/katana/replica, \ 100; /obj/item/weapon/harpoon, \ 75; /obj/item/attachable/bayonet, \ 200; /obj/item/weapon/throwing_knife, \ diff --git a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm index e7d7b7a67edf..9b3ef1df4c15 100644 --- a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm +++ b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm @@ -152,9 +152,6 @@ spawn(0) //Deleting Almayer, for performance! SSitem_cleanup.delete_almayer() - if(SSxenocon) - //Don't need XENOCON - SSxenocon.wait = 30 MINUTES //PROCCESS @@ -322,9 +319,9 @@ OT = "sup" //no breaking anything. else if (OT == "sup") - randpick = rand(0,50) + randpick = rand(0,90) switch(randpick) - if(0 to 5)//Marine Gear 10% Chance. + if(0 to 3)//Marine Gear 3% Chance. crate = new /obj/structure/closet/crate/secure/gear(T) choosemax = rand(5,10) randomitems = list(/obj/item/clothing/head/helmet/marine, @@ -340,19 +337,19 @@ /obj/effect/landmark/wo_supplies/storage/webbing, /obj/item/device/binoculars) - if(6 to 10)//Lights and shiet 10% + if(4 to 6)//Lights and shiet 2% new /obj/structure/largecrate/supply/floodlights(T) new /obj/structure/largecrate/supply/supplies/flares(T) - if(11 to 13) //6% Chance to drop this !FUN! junk. + if(7 to 10) //3% Chance to drop this !FUN! junk. crate = new /obj/structure/closet/crate/secure/gear(T) spawnitems = list(/obj/item/storage/belt/utility/full, /obj/item/storage/belt/utility/full, /obj/item/storage/belt/utility/full, /obj/item/storage/belt/utility/full) - if(14 to 18)//Materials 10% Chance. + if(11 to 22)//Materials 12% Chance. crate = new /obj/structure/closet/crate/secure/gear(T) choosemax = rand(3,8) randomitems = list(/obj/item/stack/sheet/metal, @@ -363,7 +360,7 @@ /obj/item/stack/sandbags_empty/half, /obj/item/stack/sandbags_empty/half) - if(19 to 20)//Blood Crate 4% chance + if(23 to 25)//Blood Crate 2% chance crate = new /obj/structure/closet/crate/medical(T) spawnitems = list(/obj/item/reagent_container/blood/OMinus, /obj/item/reagent_container/blood/OMinus, @@ -371,7 +368,7 @@ /obj/item/reagent_container/blood/OMinus, /obj/item/reagent_container/blood/OMinus) - if(21 to 25)//Advanced meds Crate 10% + if(26 to 30)//Advanced meds Crate 5% crate = new /obj/structure/closet/crate/medical(T) spawnitems = list(/obj/item/storage/firstaid/fire, /obj/item/storage/firstaid/regular, @@ -386,7 +383,7 @@ /obj/item/clothing/glasses/hud/health, /obj/item/device/defibrillator) - if(26 to 30)//Random Medical Items 10% as well. Made the list have less small junk + if(31 to 34)//Random Medical Items 4%. Made the list have less small junk crate = new /obj/structure/closet/crate/medical(T) spawnitems = list(/obj/item/storage/belt/medical/lifesaver/full, /obj/item/storage/belt/medical/lifesaver/full, @@ -394,7 +391,7 @@ /obj/item/storage/belt/medical/lifesaver/full, /obj/item/storage/belt/medical/lifesaver/full) - if(31 to 35)//Random explosives Crate 10% because the lord commeth and said let there be explosives. + if(35 to 40)//Random explosives Crate 5% because the lord commeth and said let there be explosives. crate = new /obj/structure/closet/crate/ammo(T) choosemax = rand(1,5) randomitems = list(/obj/item/storage/box/explosive_mines, @@ -404,7 +401,7 @@ /obj/item/explosive/grenade/high_explosive, /obj/item/storage/box/nade_box ) - if(36 to 40) // Junk + if(41 to 44) crate = new /obj/structure/closet/crate/ammo(T) spawnitems = list( /obj/item/attachable/heavy_barrel, @@ -412,20 +409,75 @@ /obj/item/attachable/heavy_barrel, /obj/item/attachable/heavy_barrel) - if(40 to 48)//Weapon + supply beacon drop. 6% + if(45 to 50)//Weapon + supply beacon drop. 5% crate = new /obj/structure/closet/crate/ammo(T) spawnitems = list(/obj/item/device/whiskey_supply_beacon, /obj/item/device/whiskey_supply_beacon, /obj/item/device/whiskey_supply_beacon, /obj/item/device/whiskey_supply_beacon) - if(49 to 50)//Rare weapons. Around 4% + if(51 to 57)//Rare weapons. Around 6% crate = new /obj/structure/closet/crate/ammo(T) spawnitems = list(/obj/effect/landmark/wo_supplies/ammo/box/rare/m41aap, /obj/effect/landmark/wo_supplies/ammo/box/rare/m41aapmag, /obj/effect/landmark/wo_supplies/ammo/box/rare/m41aextend, /obj/effect/landmark/wo_supplies/ammo/box/rare/smgap, /obj/effect/landmark/wo_supplies/ammo/box/rare/smgextend) + + if(58 to 65) // Sandbags kit + crate = new /obj/structure/closet/crate(T) + spawnitems = list(/obj/item/tool/shovel/etool, + /obj/item/stack/sandbags_empty/half, + /obj/item/stack/sandbags_empty/half, + /obj/item/stack/sandbags_empty/half) + + if(66 to 70) // Mortar shells. Pew Pew! + crate = new /obj/structure/closet/crate/secure/mortar_ammo(T) + choosemax = rand(6,10) + randomitems = list(/obj/item/mortar_shell/he, + /obj/item/mortar_shell/incendiary, + /obj/item/mortar_shell/flare, + /obj/item/mortar_shell/frag) + + if(71 to 79) + crate = new /obj/structure/closet/crate/ammo(T) + choosemax = rand(2, 3) + randomitems = list(/obj/item/ammo_box/rounds, + /obj/item/ammo_box/rounds/ap, + /obj/item/ammo_box/rounds/smg, + /obj/item/ammo_box/rounds/smg/ap, + /obj/item/ammo_box/magazine/ap, + /obj/item/ammo_box/magazine/ext, + /obj/item/ammo_box/magazine/m4ra/ap, + /obj/item/ammo_box/magazine/m4ra/ap, + /obj/item/ammo_box/magazine/m39/ap, + /obj/item/ammo_box/magazine/m39/ext, + ) + + if(80 to 82) + crate = new /obj/structure/closet/crate/ammo(T) + choosemax = rand(2, 3) + randomitems = list(/obj/item/ammo_magazine/rifle/lmg/holo_target, + /obj/item/ammo_magazine/rifle/lmg/holo_target, + /obj/item/ammo_magazine/rifle/lmg, + /obj/item/ammo_magazine/rifle/lmg, + ) + + if(83 to 86) + crate = new /obj/structure/closet/crate/ammo(T) + spawnitems = list( + /obj/item/attachable/magnetic_harness, + /obj/item/attachable/magnetic_harness, + /obj/item/attachable/magnetic_harness, + /obj/item/attachable/magnetic_harness) + + if(86 to 90) + crate = new /obj/structure/closet/crate/secure/gear(T) + spawnitems = list( + /obj/item/device/binoculars/range, + /obj/item/device/binoculars/range, + ) + if(crate) crate.storage_capacity = 60 diff --git a/code/game/gamemodes/colonialmarines/xenovsxeno.dm b/code/game/gamemodes/colonialmarines/xenovsxeno.dm index 5623295f1915..a19c3e3582c1 100644 --- a/code/game/gamemodes/colonialmarines/xenovsxeno.dm +++ b/code/game/gamemodes/colonialmarines/xenovsxeno.dm @@ -79,9 +79,6 @@ spawn(0) //Deleting Almayer, for performance! SSitem_cleanup.delete_almayer() - if(SSxenocon) - //Don't need XENOCON - SSxenocon.wait = 30 MINUTES //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// diff --git a/code/game/gamemodes/extended/infection.dm b/code/game/gamemodes/extended/infection.dm index 04e0545361aa..a6b909022aef 100644 --- a/code/game/gamemodes/extended/infection.dm +++ b/code/game/gamemodes/extended/infection.dm @@ -95,7 +95,7 @@ possible_survivors -= new_survivor //either we drafted a survivor, or we're skipping over someone, either or - remove them /datum/game_mode/infection/check_win() - var/living_player_list[] = count_humans_and_xenos(EvacuationAuthority.get_affected_zlevels()) + var/list/living_player_list = count_humans_and_xenos(get_affected_zlevels()) var/num_humans = living_player_list[1] var/zed = living_player_list[2] diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 5382d80f37a2..e467631c915e 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -111,6 +111,10 @@ var/global/cas_tracking_id_increment = 0 //this var used to assign unique tracki log_game("Server IP: [world.internet_address]:[world.port]") return TRUE +/datum/game_mode/proc/get_affected_zlevels() + if(is_in_endgame) + . = SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP)) + return ///process() ///Called by the gameticker @@ -119,8 +123,7 @@ var/global/cas_tracking_id_increment = 0 //this var used to assign unique tracki /datum/game_mode/proc/check_finished() //to be called by ticker - if(EvacuationAuthority.dest_status == NUKE_EXPLOSION_FINISHED || EvacuationAuthority.dest_status == NUKE_EXPLOSION_GROUND_FINISHED ) - return TRUE + return /datum/game_mode/proc/cleanup() //This is called when the round has ended but not the game, if any cleanup would be necessary in that case. return diff --git a/code/game/jobs/job/civilians/other/liaison.dm b/code/game/jobs/job/civilians/other/liaison.dm index 7f73376a05dd..cbbb87124957 100644 --- a/code/game/jobs/job/civilians/other/liaison.dm +++ b/code/game/jobs/job/civilians/other/liaison.dm @@ -6,7 +6,7 @@ selection_class = "job_cl" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/liaison - entry_message_body = "As a representative of Weyland-Yutani Corporation, your job requires you to stay in character at all times. You are not required to follow military orders; however, you cannot give military orders. Your primary job is to observe and report back your findings to Weyland-Yutani. Follow regular game rules unless told otherwise by your superiors. Use your office fax machine to communicate with corporate headquarters or to acquire new directives. You may not receive anything back, and this is normal." + entry_message_body = "As a representative of Weyland-Yutani Corporation, your job requires you to stay in character at all times. You are not required to follow military orders; however, you cannot give military orders. Your primary job is to observe and report back your findings to Weyland-Yutani. Follow regular game rules unless told otherwise by your superiors. Use your office fax machine to communicate with corporate headquarters or to acquire new directives. You may not receive anything back, and this is normal." var/mob/living/carbon/human/active_liaison /datum/job/civilian/liaison/generate_entry_conditions(mob/living/liaison, whitelist_status) diff --git a/code/game/jobs/job/civilians/other/mess_seargent.dm b/code/game/jobs/job/civilians/other/mess_seargent.dm index 4b1975015a95..fb4f5ee14d7c 100644 --- a/code/game/jobs/job/civilians/other/mess_seargent.dm +++ b/code/game/jobs/job/civilians/other/mess_seargent.dm @@ -1,12 +1,30 @@ /datum/job/civilian/chef title = JOB_MESS_SERGEANT - total_positions = 1 + total_positions = 2 spawn_positions = 1 + allow_additional = TRUE + scaled = TRUE selection_class = "job_ot" flags_startup_parameters = ROLE_ADD_TO_DEFAULT supervisors = "the auxiliary support officer" gear_preset = /datum/equipment_preset/uscm_ship/chef - entry_message_body = "Your job is to service the marines with excellent food, drinks and entertaining the shipside crew when needed. You have a lot of freedom and it is up to you, to decide what to do with it. Good luck!" + entry_message_body = "Your job is to service the marines with excellent food, drinks and entertaining the shipside crew when needed. You have a lot of freedom and it is up to you, to decide what to do with it. Good luck!" + +/datum/job/civilian/chef/set_spawn_positions(count) + spawn_positions = mess_sergeant_slot_formula(count) + +/datum/job/civilian/chef/get_total_positions(latejoin = FALSE) + var/positions = spawn_positions + if(latejoin) + positions = mess_sergeant_slot_formula(get_total_marines()) + if(positions <= total_positions_so_far) + positions = total_positions_so_far + else + total_positions_so_far = positions + else + total_positions_so_far = positions + + return positions /obj/effect/landmark/start/chef name = JOB_MESS_SERGEANT diff --git a/code/game/jobs/job/civilians/other/survivors.dm b/code/game/jobs/job/civilians/other/survivors.dm index 5c82241c47de..23097e139eda 100644 --- a/code/game/jobs/job/civilians/other/survivors.dm +++ b/code/game/jobs/job/civilians/other/survivors.dm @@ -10,6 +10,8 @@ job_options = SURVIVOR_VARIANT_LIST var/intro_text var/story_text + /// Whether or not the survivor is an inherently hostile to marines. + var/hostile = FALSE /datum/job/civilian/survivor/set_spawn_positions(count) spawn_positions = Clamp((round(count * SURVIVOR_TO_TOTAL_SPAWN_RATIO)), 2, 8) @@ -59,23 +61,32 @@ if(picked_spawner.story_text) story_text = picked_spawner.story_text + + if(picked_spawner.hostile) + hostile = TRUE + new /datum/cm_objective/move_mob/almayer/survivor(H) -/datum/job/civilian/survivor/generate_entry_message(mob/living/carbon/human/H) +/datum/job/civilian/survivor/generate_entry_message(mob/living/carbon/human/survivor) if(intro_text) for(var/line in intro_text) - to_chat(H, line) + to_chat(survivor, line) else - to_chat(H, "

You are a survivor!

") - to_chat(H, SPAN_NOTICE(SSmapping.configs[GROUND_MAP].survivor_message)) - to_chat(H, SPAN_NOTICE("You are fully aware of the xenomorph threat and are able to use this knowledge as you see fit.")) - to_chat(H, SPAN_NOTICE("You are NOT aware of the marines or their intentions. ")) + to_chat(survivor, "

You are a survivor!

") + to_chat(survivor, SPAN_NOTICE(SSmapping.configs[GROUND_MAP].survivor_message)) + to_chat(survivor, SPAN_NOTICE("You are fully aware of the xenomorph threat and are able to use this knowledge as you see fit.")) + to_chat(survivor, SPAN_NOTICE("You are NOT aware of the marines or their intentions. ")) if(story_text) - to_chat(H, story_text) - H.mind.memory += story_text + to_chat(survivor, story_text) + survivor.mind.memory += story_text + else + tell_survivor_story(survivor) + + if(hostile) + to_chat(survivor, SPAN_HIGHDANGER("You are HOSTILE to the USCM!")) else - tell_survivor_story(H) + to_chat(survivor, SPAN_XENOHIGHDANGER("You are NON-HOSTILE to the USCM!")) /datum/job/civilian/survivor/proc/tell_survivor_story(mob/living/carbon/human/H) var/list/survivor_story = list( diff --git a/code/game/jobs/job/civilians/support/cmo.dm b/code/game/jobs/job/civilians/support/cmo.dm index 8c4690ea2057..835f16f7d814 100644 --- a/code/game/jobs/job/civilians/support/cmo.dm +++ b/code/game/jobs/job/civilians/support/cmo.dm @@ -6,7 +6,7 @@ selection_class = "job_cmo" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/uscm_medical/cmo - entry_message_body = "You're a commissioned officer of the USCM. You have authority over everything related to Medbay and Research, only able to be overriden by the XO and CO. You are in charge of medical staff, surgery, chemistry, stimulants and keeping the marines healthy overall." + entry_message_body = "You're a commissioned officer of the USCM. You have authority over everything related to Medbay and Research, only able to be overriden by the XO and CO. You are in charge of medical staff, surgery, chemistry, stimulants and keeping the marines healthy overall." AddTimelock(/datum/job/civilian/professor, list( JOB_MEDIC_ROLES = 10 HOURS diff --git a/code/game/jobs/job/civilians/support/nurse.dm b/code/game/jobs/job/civilians/support/nurse.dm index 7a0cab16f559..8912011298dc 100644 --- a/code/game/jobs/job/civilians/support/nurse.dm +++ b/code/game/jobs/job/civilians/support/nurse.dm @@ -6,7 +6,7 @@ selection_class = "job_doctor" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/uscm_medical/nurse - entry_message_body = "You are tasked with keeping the Marines healthy and strong. You are also an expert when it comes to medication and treatment, and can do minor surgical procedures. Focus on assisting doctors and triaging wounded marines." + entry_message_body = "You are tasked with keeping the Marines healthy and strong. You are also an expert when it comes to medication and treatment, and can do minor surgical procedures. Focus on assisting doctors and triaging wounded marines." /obj/effect/landmark/start/nurse name = JOB_NURSE diff --git a/code/game/jobs/job/civilians/support/researcher.dm b/code/game/jobs/job/civilians/support/researcher.dm index 61245c8164ab..21163f27959d 100644 --- a/code/game/jobs/job/civilians/support/researcher.dm +++ b/code/game/jobs/job/civilians/support/researcher.dm @@ -10,7 +10,7 @@ selection_class = "job_researcher" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/uscm_medical/researcher - entry_message_body = "You're a commissioned officer of the USCM, though you are not in the ship's chain of command. You are tasked with researching and developing new medical treatments, helping your fellow doctors, and generally learning new things. Your role involves a lot of roleplaying, but you can perform the function of a regular doctor. Do not hand out things to Marines without getting permission from your supervisor." + entry_message_body = "You're a commissioned officer of the USCM, though you are not in the ship's chain of command. You are tasked with researching and developing new medical treatments, helping your fellow doctors, and generally learning new things. Your role involves a lot of roleplaying, but you can perform the function of a regular doctor. Do not hand out things to Marines without getting permission from your supervisor." /datum/job/civilian/researcher/set_spawn_positions(count) spawn_positions = rsc_slot_formula(count) diff --git a/code/game/jobs/job/civilians/support/synthetic.dm b/code/game/jobs/job/civilians/support/synthetic.dm index 3e02385bc96c..70060fb36a15 100644 --- a/code/game/jobs/job/civilians/support/synthetic.dm +++ b/code/game/jobs/job/civilians/support/synthetic.dm @@ -9,7 +9,7 @@ flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADMIN_NOTIFY|ROLE_WHITELISTED|ROLE_CUSTOM_SPAWN flags_whitelist = WHITELIST_SYNTHETIC gear_preset = /datum/equipment_preset/synth/uscm - entry_message_body = "You are a Synthetic! You are held to a higher standard and are required to obey not only the Server Rules but Marine Law and Synthetic Rules. Failure to do so may result in your White-list Removal. Your primary job is to support and assist all USCM Departments and Personnel on-board. In addition, being a Synthetic gives you knowledge in every field and specialization possible on-board the ship. As a Synthetic you answer to the acting commanding officer. Special circumstances may change this!" + entry_message_body = "You are a Synthetic! You are held to a higher standard and are required to obey not only the Server Rules but Marine Law and Synthetic Rules. Failure to do so may result in your White-list Removal. Your primary job is to support and assist all USCM Departments and Personnel on-board. In addition, being a Synthetic gives you knowledge in every field and specialization possible on-board the ship. As a Synthetic you answer to the acting commanding officer. Special circumstances may change this!" /datum/job/civilian/synthetic/New() . = ..() diff --git a/code/game/jobs/job/command/auxiliary/auxiliary_support_officer.dm b/code/game/jobs/job/command/auxiliary/auxiliary_support_officer.dm index e5155c949a32..5f6293000365 100644 --- a/code/game/jobs/job/command/auxiliary/auxiliary_support_officer.dm +++ b/code/game/jobs/job/command/auxiliary/auxiliary_support_officer.dm @@ -5,7 +5,7 @@ allow_additional = TRUE flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/auxiliary_officer - entry_message_body = "Your job is to oversee the hangar crew, the intel officers, the engineering department, and requisition department. You have many responsibilities and a few plates to keep spinning but your subordinates are mostly self-reliant. Assist where you can and make sure command personnel are confident the auxiliary departments are operating at peak efficiency." + entry_message_body = "Your job is to oversee the hangar crew, the intel officers, the engineering department, and requisition department. You have many responsibilities and a few plates to keep spinning but your subordinates are mostly self-reliant. Assist where you can and make sure command personnel are confident the auxiliary departments are operating at peak efficiency." AddTimelock(/datum/job/command/auxiliary_officer, list( JOB_SQUAD_ROLES = 5 HOURS, diff --git a/code/game/jobs/job/command/auxiliary/crew_chief.dm b/code/game/jobs/job/command/auxiliary/crew_chief.dm index c8dfe2a8eb37..0770bcd60ffa 100644 --- a/code/game/jobs/job/command/auxiliary/crew_chief.dm +++ b/code/game/jobs/job/command/auxiliary/crew_chief.dm @@ -7,7 +7,7 @@ supervisors = "the pilot officers" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/dcc - entry_message_body = "Your job is to assist the pilot officer maintain the ship's dropship. You have authority only on the dropship, but you are expected to maintain order, as not to disrupt the pilot." + entry_message_body = "Your job is to assist the pilot officer maintain the ship's dropship. You have authority only on the dropship, but you are expected to maintain order, as not to disrupt the pilot." AddTimelock(/datum/job/command/crew_chief, list( JOB_SQUAD_ROLES = 5 HOURS diff --git a/code/game/jobs/job/command/auxiliary/intel.dm b/code/game/jobs/job/command/auxiliary/intel.dm index 8d83d49ed143..9905bc9d3747 100644 --- a/code/game/jobs/job/command/auxiliary/intel.dm +++ b/code/game/jobs/job/command/auxiliary/intel.dm @@ -8,7 +8,7 @@ supervisors = "the auxiliary support officer" flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = "USCM Intelligence Officer (IO) (Cryo)" - entry_message_body = "Your job is to assist the marines in collecting intelligence related to the current operation to better inform command of their opposition. You are in charge of gathering any data disks, folders, and notes you may find on the operational grounds and decrypt them to grant the USCM additional resources." + entry_message_body = "Your job is to assist the marines in collecting intelligence related to the current operation to better inform command of their opposition. You are in charge of gathering any data disks, folders, and notes you may find on the operational grounds and decrypt them to grant the USCM additional resources." /datum/job/command/intel/set_spawn_positions(count) spawn_positions = int_slot_formula(count) diff --git a/code/game/jobs/job/command/auxiliary/pilot.dm b/code/game/jobs/job/command/auxiliary/pilot.dm index a75846f92919..1a7a7c21d5a0 100644 --- a/code/game/jobs/job/command/auxiliary/pilot.dm +++ b/code/game/jobs/job/command/auxiliary/pilot.dm @@ -7,7 +7,7 @@ supervisors = "the auxiliary support officer" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/po - entry_message_body = "Your job is to fly, protect, and maintain the ship's dropship. While you are an officer, your authority is limited to the dropship, where you have authority over the enlisted personnel. If you are not piloting, there is an autopilot fallback for command, but don't leave the dropship without reason." + entry_message_body = "Your job is to fly, protect, and maintain the ship's dropship. While you are an officer, your authority is limited to the dropship, where you have authority over the enlisted personnel. If you are not piloting, there is an autopilot fallback for command, but don't leave the dropship without reason." // Dropship Roles is both PO and DCC combined to not force people to backtrack AddTimelock(/datum/job/command/pilot, list( diff --git a/code/game/jobs/job/command/auxiliary/senior.dm b/code/game/jobs/job/command/auxiliary/senior.dm index 5e9b7caf1f10..014db9569b2a 100644 --- a/code/game/jobs/job/command/auxiliary/senior.dm +++ b/code/game/jobs/job/command/auxiliary/senior.dm @@ -7,7 +7,7 @@ job_options = list("Gunnery Sergeant" = "GySGT", "Master Sergeant" = "MSgt", "First Sergeant" = "1Sgt", "Master Gunnery Sergeant" = "MGySgt", "Sergeant Major" = "SgtMaj") /datum/job/command/senior/on_config_load() - entry_message_body = "You are held to a higher standard and are required to obey not only the Server Rules but Marine Law and Standard Operating Procedure. Failure to do so may result in your Mentorship Removal. Your primary job is to teach others the game and its mechanics, and offer advice to all USCM Departments and Personnel on-board." + entry_message_body = "You are held to a higher standard and are required to obey not only the Server Rules but Marine Law and Standard Operating Procedure. Failure to do so may result in your Mentorship Removal. Your primary job is to teach others the game and its mechanics, and offer advice to all USCM Departments and Personnel on-board." return ..() /datum/job/command/senior/announce_entry_message(mob/living/carbon/human/H) diff --git a/code/game/jobs/job/command/cic/captain.dm b/code/game/jobs/job/command/cic/captain.dm index 98db585e1d07..72f861351912 100644 --- a/code/game/jobs/job/command/cic/captain.dm +++ b/code/game/jobs/job/command/cic/captain.dm @@ -16,7 +16,7 @@ ) /datum/job/command/commander/generate_entry_message() - entry_message_body = "You are the Commanding Officer of the [MAIN_SHIP_NAME] as well as the operation. Your goal is to lead the Marines on their mission as well as protect and command the ship and her crew. Your job involves heavy roleplay and requires you to behave like a high-ranking officer and to stay in character at all times. As the Commanding Officer your only superior is High Command itself. You must abide by the Commanding Officer Code of Conduct. Failure to do so may result in punitive action against you. Godspeed." + entry_message_body = "You are the Commanding Officer of the [MAIN_SHIP_NAME] as well as the operation. Your goal is to lead the Marines on their mission as well as protect and command the ship and her crew. Your job involves heavy roleplay and requires you to behave like a high-ranking officer and to stay in character at all times. As the Commanding Officer your only superior is High Command itself. You must abide by the Commanding Officer Code of Conduct. Failure to do so may result in punitive action against you. Godspeed." return ..() /datum/job/command/commander/get_whitelist_status(list/roles_whitelist, client/player) diff --git a/code/game/jobs/job/command/cic/staffofficer.dm b/code/game/jobs/job/command/cic/staffofficer.dm index fff51624aa4b..94769de2158f 100644 --- a/code/game/jobs/job/command/cic/staffofficer.dm +++ b/code/game/jobs/job/command/cic/staffofficer.dm @@ -6,7 +6,7 @@ scaled = FALSE flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/so - entry_message_body = "Your job is to monitor the Marines, man the CIC, and listen to your superior officers. You are in charge of logistics and the overwatch system. You are also in line to take command after other eligible superior commissioned officers." + entry_message_body = "Your job is to monitor the Marines, man the CIC, and listen to your superior officers. You are in charge of logistics and the overwatch system. You are also in line to take command after other eligible superior commissioned officers." /datum/job/command/bridge/set_spawn_positions(count) spawn_positions = so_slot_formula(count) diff --git a/code/game/jobs/job/command/police/chief_police.dm b/code/game/jobs/job/command/police/chief_police.dm index b76943c4d0ac..63e6d8023f17 100644 --- a/code/game/jobs/job/command/police/chief_police.dm +++ b/code/game/jobs/job/command/police/chief_police.dm @@ -4,7 +4,7 @@ selection_class = "job_cmp" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/uscm_police/cmp - entry_message_body = "You are held by a higher standard and are required to obey not only the server rules but the Marine Law. Failure to do so may result in a job ban or server ban. You lead the Military Police, ensure your officers maintain peace and stability aboard the ship. Marines can get rowdy after a few weeks of cryosleep! In addition, you are tasked with the security of high-ranking personnel, including the command staff. Keep them safe!" + entry_message_body = "You are held by a higher standard and are required to obey not only the server rules but the Marine Law. Failure to do so may result in a job ban or server ban. You lead the Military Police, ensure your officers maintain peace and stability aboard the ship. Marines can get rowdy after a few weeks of cryosleep! In addition, you are tasked with the security of high-ranking personnel, including the command staff. Keep them safe!" AddTimelock(/datum/job/command/warrant, list( JOB_POLICE_ROLES = 15 HOURS, diff --git a/code/game/jobs/job/command/police/police.dm b/code/game/jobs/job/command/police/police.dm index 7285c5b278b1..e05bc2e96256 100644 --- a/code/game/jobs/job/command/police/police.dm +++ b/code/game/jobs/job/command/police/police.dm @@ -8,7 +8,7 @@ selection_class = "job_mp" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/uscm_police/mp - entry_message_body = "You are held by a higher standard and are required to obey not only the server rules but the Marine Law. Failure to do so may result in a job ban or server ban. Your primary job is to maintain peace and stability aboard the ship. Marines can get rowdy after a few weeks of cryosleep! In addition, you are tasked with the security of high-ranking personnel, including the command staff. Keep them safe!" + entry_message_body = "You are held by a higher standard and are required to obey not only the server rules but the Marine Law. Failure to do so may result in a job ban or server ban. Your primary job is to maintain peace and stability aboard the ship. Marines can get rowdy after a few weeks of cryosleep! In addition, you are tasked with the security of high-ranking personnel, including the command staff. Keep them safe!" /datum/job/command/police/set_spawn_positions(count) spawn_positions = mp_slot_formula(count) diff --git a/code/game/jobs/job/command/police/warden.dm b/code/game/jobs/job/command/police/warden.dm index 55cbea975401..d2775e197537 100644 --- a/code/game/jobs/job/command/police/warden.dm +++ b/code/game/jobs/job/command/police/warden.dm @@ -5,7 +5,7 @@ flags_startup_parameters = ROLE_ADD_TO_DEFAULT supervisors = "the Chief MP" gear_preset = /datum/equipment_preset/uscm_ship/uscm_police/warden - entry_message_body = "You are held by a higher standard and are required to obey not only the server rules but the Marine Law. Failure to do so may result in a job ban or server ban. Your primary job is to maintain peace and stability aboard the ship. Marines can get rowdy after a few weeks of cryosleep! In addition, you are tasked with the mainting security records and overwatching any prisoners in Brig." + entry_message_body = "You are held by a higher standard and are required to obey not only the server rules but the Marine Law. Failure to do so may result in a job ban or server ban. Your primary job is to maintain peace and stability aboard the ship. Marines can get rowdy after a few weeks of cryosleep! In addition, you are tasked with the mainting security records and overwatching any prisoners in Brig." AddTimelock(/datum/job/command/warden, list( JOB_POLICE_ROLES = 10 HOURS diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 0d68d23e5524..48ad372e1f33 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -49,13 +49,16 @@ if(!disp_title) disp_title = title + if(global.config.is_loaded) + on_config_load() + /datum/job/proc/on_config_load() if(entry_message_body) entry_message_body = replace_placeholders(entry_message_body) /datum/job/proc/replace_placeholders(replacement_string) - replacement_string = replacetextEx(replacement_string, "%WIKIURL%", generate_wiki_link()) - replacement_string = replacetextEx(replacement_string, "%LAWURL%", "[CONFIG_GET(string/wikiarticleurl)]/[URL_WIKI_LAW]") + replacement_string = replacetextEx(replacement_string, WIKI_PLACEHOLDER, generate_wiki_link()) + replacement_string = replacetextEx(replacement_string, LAW_PLACEHOLDER, "[CONFIG_GET(string/wikiarticleurl)]/[URL_WIKI_LAW]") return replacement_string /datum/job/proc/generate_wiki_link() diff --git a/code/game/jobs/job/logistics/cargo/cargo_tech.dm b/code/game/jobs/job/logistics/cargo/cargo_tech.dm index 3b588022bd97..c4725289c3ff 100644 --- a/code/game/jobs/job/logistics/cargo/cargo_tech.dm +++ b/code/game/jobs/job/logistics/cargo/cargo_tech.dm @@ -8,7 +8,7 @@ selection_class = "job_ct" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/cargo - entry_message_body = "Your job is to dispense supplies to the marines, including weapon attachments. Stay in your department when possible to ensure the marines have full access to the supplies they may require. Listen to the radio in case someone requests a supply drop via the overwatch system." + entry_message_body = "Your job is to dispense supplies to the marines, including weapon attachments. Stay in your department when possible to ensure the marines have full access to the supplies they may require. Listen to the radio in case someone requests a supply drop via the overwatch system." /datum/job/logistics/cargo/set_spawn_positions(count) spawn_positions = ct_slot_formula(count) diff --git a/code/game/jobs/job/logistics/cargo/chief_req.dm b/code/game/jobs/job/logistics/cargo/chief_req.dm index 76b7e98f2db8..5d5123e687ed 100644 --- a/code/game/jobs/job/logistics/cargo/chief_req.dm +++ b/code/game/jobs/job/logistics/cargo/chief_req.dm @@ -3,7 +3,7 @@ selection_class = "job_qm" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/qm - entry_message_body = "Your job is to dispense supplies to the marines, including weapon attachments. Your cargo techs can help you out, but you have final say in your department. Make sure they're not goofing off. While you may request paperwork for supplies, do not go out of your way to screw with marines, unless you want to get deposed. A happy ship is a well-functioning ship." + entry_message_body = "Your job is to dispense supplies to the marines, including weapon attachments. Your cargo techs can help you out, but you have final say in your department. Make sure they're not goofing off. While you may request paperwork for supplies, do not go out of your way to screw with marines, unless you want to get deposed. A happy ship is a well-functioning ship." AddTimelock(/datum/job/logistics/requisition, list( JOB_REQUISITION_ROLES = 10 HOURS, diff --git a/code/game/jobs/job/logistics/engi/chief_engineer.dm b/code/game/jobs/job/logistics/engi/chief_engineer.dm index 3a15c8632953..b6aa23f9c4a6 100644 --- a/code/game/jobs/job/logistics/engi/chief_engineer.dm +++ b/code/game/jobs/job/logistics/engi/chief_engineer.dm @@ -3,7 +3,7 @@ selection_class = "job_ce" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/chief_engineer - entry_message_body = "Your job is to maintain your department and keep your technicians in check. You are responsible for engineering, power, ordnance, and the orbital cannon. Should the commanding and executive officer be unavailable, you are next in the chain of command." + entry_message_body = "Your job is to maintain your department and keep your technicians in check. You are responsible for engineering, power, ordnance, and the orbital cannon. Should the commanding and executive officer be unavailable, you are next in the chain of command." AddTimelock(/datum/job/logistics/engineering, list( JOB_ENGINEER_ROLES = 10 HOURS, diff --git a/code/game/jobs/job/logistics/engi/maint_tech.dm b/code/game/jobs/job/logistics/engi/maint_tech.dm index 8562408360d7..b13062127a12 100644 --- a/code/game/jobs/job/logistics/engi/maint_tech.dm +++ b/code/game/jobs/job/logistics/engi/maint_tech.dm @@ -6,7 +6,7 @@ selection_class = "job_ot" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/maint - entry_message_body = "Your job is to maintain the integrity of the ship, including the orbital cannon. You remain one of the more flexible roles on the ship and as such may receive other menial tasks from your superiors." + entry_message_body = "Your job is to maintain the integrity of the ship, including the orbital cannon. You remain one of the more flexible roles on the ship and as such may receive other menial tasks from your superiors." /obj/effect/landmark/start/maint name = JOB_MAINT_TECH diff --git a/code/game/jobs/job/logistics/engi/ordnance_tech.dm b/code/game/jobs/job/logistics/engi/ordnance_tech.dm index bed0acf15887..43a8a7122a8f 100644 --- a/code/game/jobs/job/logistics/engi/ordnance_tech.dm +++ b/code/game/jobs/job/logistics/engi/ordnance_tech.dm @@ -9,7 +9,7 @@ selection_class = "job_ot" flags_startup_parameters = ROLE_ADD_TO_DEFAULT gear_preset = /datum/equipment_preset/uscm_ship/ordn - entry_message_body = "Your job is to maintain the integrity of the USCM weapons, munitions and equipment, including the orbital cannon. You can use the workshop in the portside hangar to construct new armaments for the marines. However you remain one of the more flexible roles on the ship and as such may receive other menial tasks from your superiors." + entry_message_body = "Your job is to maintain the integrity of the USCM weapons, munitions and equipment, including the orbital cannon. You can use the workshop in the portside hangar to construct new armaments for the marines. However you remain one of the more flexible roles on the ship and as such may receive other menial tasks from your superiors." /datum/job/logistics/otech/set_spawn_positions(count) spawn_positions = ot_slot_formula(count) diff --git a/code/game/jobs/job/marine/squad/engineer.dm b/code/game/jobs/job/marine/squad/engineer.dm index 00a6b91dcffd..1910248a61a2 100644 --- a/code/game/jobs/job/marine/squad/engineer.dm +++ b/code/game/jobs/job/marine/squad/engineer.dm @@ -5,7 +5,7 @@ allow_additional = 1 flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/engineer - entry_message_body = "You have the equipment and skill to build fortifications, reroute power lines, and bunker down. Your squaddies will look to you when it comes to construction in the field of battle." + entry_message_body = "You have the equipment and skill to build fortifications, reroute power lines, and bunker down. Your squaddies will look to you when it comes to construction in the field of battle." /datum/job/marine/engineer/set_spawn_positions(count) for(var/datum/squad/sq in RoleAuthority.squads) diff --git a/code/game/jobs/job/marine/squad/leader.dm b/code/game/jobs/job/marine/squad/leader.dm index 960a80d5f659..be78438db3d6 100644 --- a/code/game/jobs/job/marine/squad/leader.dm +++ b/code/game/jobs/job/marine/squad/leader.dm @@ -5,7 +5,7 @@ supervisors = "the acting commanding officer" flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/leader - entry_message_body = "You are responsible for the men and women of your squad. Make sure they are on task, working together, and communicating. You are also in charge of communicating with command and letting them know about the situation first hand. Keep out of harm's way." + entry_message_body = "You are responsible for the men and women of your squad. Make sure they are on task, working together, and communicating. You are also in charge of communicating with command and letting them know about the situation first hand. Keep out of harm's way." /datum/job/marine/leader/whiskey title = JOB_WO_SQUAD_LEADER diff --git a/code/game/jobs/job/marine/squad/medic.dm b/code/game/jobs/job/marine/squad/medic.dm index cdbd74acefde..3df0a3793ca5 100644 --- a/code/game/jobs/job/marine/squad/medic.dm +++ b/code/game/jobs/job/marine/squad/medic.dm @@ -5,7 +5,7 @@ allow_additional = 1 flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/medic - entry_message_body = "You tend the wounds of your squad mates and make sure they are healthy and active. You may not be a fully-fledged doctor, but you stand between life and death when it matters." + entry_message_body = "You tend the wounds of your squad mates and make sure they are healthy and active. You may not be a fully-fledged doctor, but you stand between life and death when it matters." /datum/job/marine/medic/set_spawn_positions(count) for(var/datum/squad/sq in RoleAuthority.squads) diff --git a/code/game/jobs/job/marine/squad/smartgunner.dm b/code/game/jobs/job/marine/squad/smartgunner.dm index aacc562f921b..1a89abf5d3be 100644 --- a/code/game/jobs/job/marine/squad/smartgunner.dm +++ b/code/game/jobs/job/marine/squad/smartgunner.dm @@ -6,7 +6,7 @@ scaled = 1 flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/sg - entry_message_body = "You are the smartgunner. Your task is to provide heavy weapons support." + entry_message_body = "You are the smartgunner. Your task is to provide heavy weapons support." /datum/job/marine/smartgunner/set_spawn_positions(count) spawn_positions = sg_slot_formula(count) diff --git a/code/game/jobs/job/marine/squad/specialist.dm b/code/game/jobs/job/marine/squad/specialist.dm index 42ee69ef2d5c..e69241cdc70b 100644 --- a/code/game/jobs/job/marine/squad/specialist.dm +++ b/code/game/jobs/job/marine/squad/specialist.dm @@ -6,7 +6,7 @@ scaled = 1 flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/spec - entry_message_body = "You are the very rare and valuable weapon expert, trained to use special equipment. You can serve a variety of roles, so choose carefully." + entry_message_body = "You are the very rare and valuable weapon expert, trained to use special equipment. You can serve a variety of roles, so choose carefully." /datum/job/marine/specialist/set_spawn_positions(count) spawn_positions = spec_slot_formula(count) diff --git a/code/game/jobs/job/marine/squad/standard.dm b/code/game/jobs/job/marine/squad/standard.dm index e2502576e5ea..2fcd8a3cdd28 100644 --- a/code/game/jobs/job/marine/squad/standard.dm +++ b/code/game/jobs/job/marine/squad/standard.dm @@ -6,7 +6,10 @@ spawn_positions = -1 flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/pfc - entry_message_body = "You are a rank-and-file Marine of the USCM, and that is your strength. What you lack alone, you gain standing shoulder to shoulder with the men and women of the corps. Ooh-rah!" + +/datum/job/marine/standard/on_config_load() + entry_message_body = "You are a rank-and-file Marine of the USCM, and that is your strength. What you lack alone, you gain standing shoulder to shoulder with the men and women of the corps. Ooh-rah!" + return ..() /datum/job/marine/standard/set_spawn_positions(count) spawn_positions = max((round(count * STANDARD_MARINE_TO_TOTAL_SPAWN_RATIO)), 8) diff --git a/code/game/jobs/job/marine/squad/tl.dm b/code/game/jobs/job/marine/squad/tl.dm index ebebf360e830..2b0cff3ea3ed 100644 --- a/code/game/jobs/job/marine/squad/tl.dm +++ b/code/game/jobs/job/marine/squad/tl.dm @@ -5,7 +5,7 @@ allow_additional = 1 flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADD_TO_SQUAD gear_preset = /datum/equipment_preset/uscm/tl - entry_message_body = "You are the Team Leader.Your task is to assist the squad leader in leading the squad as well as utilize ordnance such as orbital bombardments, CAS, and mortar as well as coordinating resupply with Requisitions and CIC. If the squad leader dies, you are expected to lead in their place." + entry_message_body = "You are the Team Leader.Your task is to assist the squad leader in leading the squad as well as utilize ordnance such as orbital bombardments, CAS, and mortar as well as coordinating resupply with Requisitions and CIC. If the squad leader dies, you are expected to lead in their place." /datum/job/marine/tl/generate_entry_conditions(mob/living/carbon/human/spawning_human) . = ..() diff --git a/code/game/jobs/job/marine/squads.dm b/code/game/jobs/job/marine/squads.dm index d984aaa72c8a..d1c2640a81aa 100644 --- a/code/game/jobs/job/marine/squads.dm +++ b/code/game/jobs/job/marine/squads.dm @@ -210,6 +210,17 @@ roundstart = FALSE locked = TRUE +/datum/squad/marine/cbrn + name = SQUAD_CBRN + equipment_color = "#3B2A7B" //Chemical Corps Purple + chat_color = "#553EB2" + radio_freq = CBRN_FREQ + minimap_color = "#3B2A7B" + + active = FALSE + roundstart = FALSE + locked = TRUE + //############################### UPP Squads /datum/squad/upp name = "Root" diff --git a/code/game/jobs/role_authority.dm b/code/game/jobs/role_authority.dm index c147807f004e..dc9865f8d6e6 100644 --- a/code/game/jobs/role_authority.dm +++ b/code/game/jobs/role_authority.dm @@ -501,85 +501,86 @@ I hope it's easier to tell what the heck this proc is even doing, unlike previou M.job = null -/datum/authority/branch/role/proc/equip_role(mob/living/M, datum/job/J, turf/late_join) - if(!istype(M) || !istype(J)) +/datum/authority/branch/role/proc/equip_role(mob/living/new_mob, datum/job/new_job, turf/late_join) + if(!istype(new_mob) || !istype(new_job)) return . = TRUE - if(!ishuman(M)) + if(!ishuman(new_mob)) return - var/mob/living/carbon/human/H = M + var/mob/living/carbon/human/new_human = new_mob - if(J.job_options && H?.client?.prefs?.pref_special_job_options[J.title]) - J.handle_job_options(H.client.prefs.pref_special_job_options[J.title]) + if(new_job.job_options && new_human?.client?.prefs?.pref_special_job_options[new_job.title]) + new_job.handle_job_options(new_human.client.prefs.pref_special_job_options[new_job.title]) - var/job_whitelist = J.title - var/whitelist_status = J.get_whitelist_status(roles_whitelist, H.client) + var/job_whitelist = new_job.title + var/whitelist_status = new_job.get_whitelist_status(roles_whitelist, new_human.client) if(whitelist_status) - job_whitelist = "[J.title][whitelist_status]" + job_whitelist = "[new_job.title][whitelist_status]" - H.job = J.title //TODO Why is this a mob variable at all? + new_human.job = new_job.title //TODO Why is this a mob variable at all? - if(J.gear_preset_whitelist[job_whitelist]) - arm_equipment(H, J.gear_preset_whitelist[job_whitelist], FALSE, TRUE) - var/generated_account = J.generate_money_account(H) - J.announce_entry_message(H, generated_account, whitelist_status) //Tell them their spawn info. - J.generate_entry_conditions(H, whitelist_status) //Do any other thing that relates to their spawn. + if(new_job.gear_preset_whitelist[job_whitelist]) + arm_equipment(new_human, new_job.gear_preset_whitelist[job_whitelist], FALSE, TRUE) + var/generated_account = new_job.generate_money_account(new_human) + new_job.announce_entry_message(new_human, generated_account, whitelist_status) //Tell them their spawn info. + new_job.generate_entry_conditions(new_human, whitelist_status) //Do any other thing that relates to their spawn. else - arm_equipment(H, J.gear_preset, FALSE, TRUE) //After we move them, we want to equip anything else they should have. - var/generated_account = J.generate_money_account(H) - J.announce_entry_message(H, generated_account) //Tell them their spawn info. - J.generate_entry_conditions(H) //Do any other thing that relates to their spawn. + arm_equipment(new_human, new_job.gear_preset, FALSE, TRUE) //After we move them, we want to equip anything else they should have. + var/generated_account = new_job.generate_money_account(new_human) + new_job.announce_entry_message(new_human, generated_account) //Tell them their spawn info. + new_job.generate_entry_conditions(new_human) //Do any other thing that relates to their spawn. - if(J.flags_startup_parameters & ROLE_ADD_TO_SQUAD) //Are we a muhreen? Randomize our squad. This should go AFTER IDs. //TODO Robust this later. - randomize_squad(H) + if(new_job.flags_startup_parameters & ROLE_ADD_TO_SQUAD) //Are we a muhreen? Randomize our squad. This should go AFTER IDs. //TODO Robust this later. + randomize_squad(new_human) - if(Check_WO() && job_squad_roles.Find(GET_DEFAULT_ROLE(H.job))) //activates self setting proc for marine headsets for WO + if(Check_WO() && job_squad_roles.Find(GET_DEFAULT_ROLE(new_human.job))) //activates self setting proc for marine headsets for WO var/datum/game_mode/whiskey_outpost/WO = SSticker.mode - WO.self_set_headset(H) + WO.self_set_headset(new_human) var/assigned_squad - if(ishuman(H)) - var/mob/living/carbon/human/human = H + if(ishuman(new_human)) + var/mob/living/carbon/human/human = new_human if(human.assigned_squad) assigned_squad = human.assigned_squad.name if(isturf(late_join)) - H.forceMove(late_join) + new_human.forceMove(late_join) else if(late_join) var/turf/late_join_turf if(GLOB.latejoin_by_squad[assigned_squad]) late_join_turf = get_turf(pick(GLOB.latejoin_by_squad[assigned_squad])) - else if(GLOB.latejoin_by_job[J.title]) - late_join_turf = get_turf(pick(GLOB.latejoin_by_job[J.title])) + else if(GLOB.latejoin_by_job[new_job.title]) + late_join_turf = get_turf(pick(GLOB.latejoin_by_job[new_job.title])) else late_join_turf = get_turf(pick(GLOB.latejoin)) - H.forceMove(late_join_turf) + new_human.forceMove(late_join_turf) else var/turf/join_turf - if(assigned_squad && GLOB.spawns_by_squad_and_job[assigned_squad] && GLOB.spawns_by_squad_and_job[assigned_squad][J.type]) - join_turf = get_turf(pick(GLOB.spawns_by_squad_and_job[assigned_squad][J.type])) - else if(GLOB.spawns_by_job[J.type]) - join_turf = get_turf(pick(GLOB.spawns_by_job[J.type])) + if(assigned_squad && GLOB.spawns_by_squad_and_job[assigned_squad] && GLOB.spawns_by_squad_and_job[assigned_squad][new_job.type]) + join_turf = get_turf(pick(GLOB.spawns_by_squad_and_job[assigned_squad][new_job.type])) + else if(GLOB.spawns_by_job[new_job.type]) + join_turf = get_turf(pick(GLOB.spawns_by_job[new_job.type])) else if(assigned_squad && GLOB.latejoin_by_squad[assigned_squad]) join_turf = get_turf(pick(GLOB.latejoin_by_squad[assigned_squad])) else join_turf = get_turf(pick(GLOB.latejoin)) - H.forceMove(join_turf) + new_human.forceMove(join_turf) for(var/cardinal in GLOB.cardinals) - var/obj/structure/machinery/cryopod/pod = locate() in get_step(H, cardinal) + var/obj/structure/machinery/cryopod/pod = locate() in get_step(new_human, cardinal) if(pod) - pod.go_in_cryopod(H, silent = TRUE) + pod.go_in_cryopod(new_human, silent = TRUE) break - H.sec_hud_set_ID() - H.hud_set_squad() + new_human.sec_hud_set_ID() + new_human.hud_set_squad() - SSround_recording.recorder.track_player(H) + SEND_SIGNAL(new_human, COMSIG_POST_SPAWN_UPDATE) + SSround_recording.recorder.track_player(new_human) //Find which squad has the least population. If all 4 squads are equal it should just use a random one /datum/authority/branch/role/proc/get_lowest_squad(mob/living/carbon/human/H) diff --git a/code/game/jobs/slot_scaling.dm b/code/game/jobs/slot_scaling.dm index 7230f57eb745..2d444d06e5ab 100644 --- a/code/game/jobs/slot_scaling.dm +++ b/code/game/jobs/slot_scaling.dm @@ -50,3 +50,6 @@ /proc/working_joe_slot_formula(playercount) return job_slot_formula(playercount,30,1,3,6) + +/proc/mess_sergeant_slot_formula(playercount) + return job_slot_formula(playercount, 70, 1, 1, 2) diff --git a/code/game/machinery/ARES/ARES_interface.dm b/code/game/machinery/ARES/ARES_interface.dm index 64755897bc8e..0e45d5ee171b 100644 --- a/code/game/machinery/ARES/ARES_interface.dm +++ b/code/game/machinery/ARES/ARES_interface.dm @@ -79,7 +79,7 @@ data["access_level"] = authentication data["alert_level"] = security_level - data["evac_status"] = EvacuationAuthority.evac_status + data["evac_status"] = SShijack.evac_status data["worldtime"] = world.time data["access_log"] = datacore.interface_access_list @@ -397,12 +397,12 @@ playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE - if(EvacuationAuthority.flags_scuttle & FLAGS_EVACUATION_DENY) + if(SShijack.evac_admin_denied) to_chat(usr, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE - if(!EvacuationAuthority.initiate_evacuation()) + if(!SShijack.initiate_evacuation()) to_chat(usr, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) return FALSE diff --git a/code/game/machinery/ARES/ARES_interface_apollo.dm b/code/game/machinery/ARES/ARES_interface_apollo.dm index ad4df31c35a8..3bbc6065a88a 100644 --- a/code/game/machinery/ARES/ARES_interface_apollo.dm +++ b/code/game/machinery/ARES/ARES_interface_apollo.dm @@ -14,7 +14,7 @@ var/current_menu = "login" var/last_menu = "" - var/authentication = ARES_ACCESS_BASIC + var/authentication = APOLLO_ACCESS_LOGOUT /// The last person to login. var/last_login diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm index 4dbcf794f7be..831f76e48930 100644 --- a/code/game/machinery/ARES/ARES_procs.dm +++ b/code/game/machinery/ARES/ARES_procs.dm @@ -258,3 +258,37 @@ GLOBAL_LIST_INIT(maintenance_categories, list( return "Working Joe" if(APOLLO_ACCESS_DEBUG)//6 return "AI Service Technician" + +/obj/item/device/working_joe_pda/proc/get_ares_access(obj/item/card/id/card) + if(ACCESS_ARES_DEBUG in card.access) + return APOLLO_ACCESS_DEBUG + switch(card.assignment) + if(JOB_WORKING_JOE) + return APOLLO_ACCESS_JOE + if(JOB_CHIEF_ENGINEER, JOB_SYNTH, JOB_CO) + return APOLLO_ACCESS_AUTHED + if(ACCESS_MARINE_AI in card.access) + return APOLLO_ACCESS_AUTHED + if(ACCESS_MARINE_AI_TEMP in card.access) + return APOLLO_ACCESS_TEMP + if((ACCESS_MARINE_SENIOR in card.access ) || (ACCESS_MARINE_ENGINEERING in card.access) || (ACCESS_WY_GENERAL in card.access)) + return APOLLO_ACCESS_REPORTER + else + return APOLLO_ACCESS_REQUEST + +/obj/item/device/working_joe_pda/proc/ares_auth_to_text(access_level) + switch(access_level) + if(APOLLO_ACCESS_LOGOUT)//0 + return "Logged Out" + if(APOLLO_ACCESS_REQUEST)//1 + return "Unauthorized Personnel" + if(APOLLO_ACCESS_REPORTER)//2 + return "Validated Incident Reporter" + if(APOLLO_ACCESS_TEMP)//3 + return "Authorized Visitor" + if(APOLLO_ACCESS_AUTHED)//4 + return "Certified Personnel" + if(APOLLO_ACCESS_JOE)//5 + return "Working Joe" + if(APOLLO_ACCESS_DEBUG)//6 + return "AI Service Technician" diff --git a/code/game/machinery/ARES/apollo_pda.dm b/code/game/machinery/ARES/apollo_pda.dm new file mode 100644 index 000000000000..26ec9d5120bd --- /dev/null +++ b/code/game/machinery/ARES/apollo_pda.dm @@ -0,0 +1,419 @@ +/obj/item/device/working_joe_pda + icon = 'icons/obj/items/synth/wj_pda.dmi' + name = "KN5500 PDA" + desc = "A portable interface used by Working-Joes, capable of connecting to the local command AI to relay tasking information. Built to withstand a nuclear bomb." + icon_state = "karnak_off" + unacidable = TRUE + indestructible = TRUE + req_one_access = list(ACCESS_MARINE_AI_TEMP, ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) + + /// The ID used to link all devices. + var/datum/ares_link/link + /// The datacore storing all the information. + var/datum/ares_datacore/datacore + + var/current_menu = "login" + var/last_menu = "off" + + var/authentication = APOLLO_ACCESS_LOGOUT + /// The last person to login. + var/last_login + + +/obj/item/device/working_joe_pda/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + if(link && !override) + return FALSE + if(new_link) + new_link.ticket_computers += src + link = new_link + new_link.linked_systems += src + if(!datacore) + datacore = GLOB.ares_datacore + return TRUE + +/obj/item/device/working_joe_pda/Initialize(mapload, ...) + link_systems(override = FALSE) + . = ..() + +/obj/item/device/working_joe_pda/proc/delink() + if(link) + link.ticket_computers -= src + link.linked_systems -= src + link = null + datacore = null + +/obj/item/device/working_joe_pda/Destroy() + delink() + return ..() + +/obj/item/device/working_joe_pda/update_icon() + . = ..() + if(last_menu == "off") + icon_state = "karnak_off" + else if(current_menu == "login") + icon_state = "karnak_login_anim" + else + icon_state = "karnak_on_anim" + +// ------ Maintenance Controller UI ------ // +/obj/item/device/working_joe_pda/attack_self(mob/user) + if(..() || !allowed(usr)) + return FALSE + + if((last_menu == "off") && (current_menu == "login")) + last_menu = "main" + update_icon() + + tgui_interact(user) + return TRUE + +/obj/item/device/working_joe_pda/tgui_interact(mob/user, datum/tgui/ui, datum/ui_state/state) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "WorkingJoe", name) + ui.open() + +/obj/item/device/working_joe_pda/ui_close(mob/user) + . = ..() + + current_menu = "login" + last_menu = "off" + if(last_login) + datacore.apollo_login_list += "[last_login] logged out at [worldtime2text()]." + last_login = null + update_icon() + +/obj/item/device/working_joe_pda/ui_data(mob/user) + var/list/data = list() + + data["current_menu"] = current_menu + data["last_page"] = last_menu + + data["logged_in"] = last_login + + data["access_text"] = "access level [authentication], [ares_auth_to_text(authentication)]." + data["access_level"] = authentication + + data["alert_level"] = security_level + data["worldtime"] = world.time + + data["access_log"] = list() + data["access_log"] += datacore.apollo_login_list + + data["apollo_log"] = list() + data["apollo_log"] += datacore.apollo_log + + var/list/logged_maintenance = list() + for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance) + if(!istype(maint_ticket)) + continue + var/lock_status = TICKET_OPEN + switch(maint_ticket.ticket_status) + if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) + lock_status = TICKET_CLOSED + + var/list/current_maint = list() + current_maint["id"] = maint_ticket.ticket_id + current_maint["time"] = maint_ticket.ticket_time + current_maint["priority_status"] = maint_ticket.ticket_priority + current_maint["category"] = maint_ticket.ticket_name + current_maint["details"] = maint_ticket.ticket_details + current_maint["status"] = maint_ticket.ticket_status + current_maint["submitter"] = maint_ticket.ticket_submitter + current_maint["assignee"] = maint_ticket.ticket_assignee + current_maint["lock_status"] = lock_status + current_maint["ref"] = "\ref[maint_ticket]" + logged_maintenance += list(current_maint) + data["maintenance_tickets"] = logged_maintenance + + var/list/logged_access = list() + var/list/requesting_access = list() + for(var/datum/ares_ticket/access/access_ticket as anything in link.tickets_access) + var/lock_status = TICKET_OPEN + switch(access_ticket.ticket_status) + if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_REVOKED) + lock_status = TICKET_CLOSED + + var/list/current_ticket = list() + current_ticket["id"] = access_ticket.ticket_id + current_ticket["time"] = access_ticket.ticket_time + current_ticket["priority_status"] = access_ticket.ticket_priority + current_ticket["title"] = access_ticket.ticket_name + current_ticket["details"] = access_ticket.ticket_details + current_ticket["status"] = access_ticket.ticket_status + current_ticket["submitter"] = access_ticket.ticket_submitter + current_ticket["assignee"] = access_ticket.ticket_assignee + current_ticket["lock_status"] = lock_status + current_ticket["ref"] = "\ref[access_ticket]" + logged_access += list(current_ticket) + + if(lock_status == TICKET_OPEN) + requesting_access += access_ticket.ticket_name + data["access_tickets"] = logged_access + + return data + +/obj/item/device/working_joe_pda/ui_status(mob/user, datum/ui_state/state) + . = ..() + if(!allowed(user)) + return UI_UPDATE + +/obj/item/device/working_joe_pda/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + + var/playsound = TRUE + var/mob/living/carbon/human/operator = usr + + switch (action) + if("go_back") + if(!last_menu) + return to_chat(usr, 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() + if(istype(idcard)) + authentication = get_ares_access(idcard) + last_login = idcard.registered_name + else if(operator.wear_id) + idcard = operator.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!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(authentication) + datacore.apollo_login_list += "[last_login] at [worldtime2text()], Access Level [authentication] - [ares_auth_to_text(authentication)]." + current_menu = "main" + last_menu = "main" + update_icon() + + if("logout") + last_menu = current_menu + current_menu = "login" + datacore.apollo_login_list += "[last_login] logged out at [worldtime2text()]." + update_icon() + + if("home") + last_menu = current_menu + current_menu = "main" + if("page_logins") + last_menu = current_menu + current_menu = "login_records" + if("page_apollo") + last_menu = current_menu + current_menu = "apollo" + if("page_request") + last_menu = current_menu + current_menu = "access_requests" + if("page_report") + last_menu = current_menu + current_menu = "maint_reports" + if("page_tickets") + last_menu = current_menu + current_menu = "access_tickets" + if("page_maintenance") + last_menu = current_menu + current_menu = "maint_claim" + + 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) + 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) + 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")) + if(is_priority == "Yes") + priority_report = TRUE + + var/confirm = alert(operator, "Please confirm the submission of your maintenance report. \n\n Priority: [priority_report ? "Yes" : "No"]\n Category: '[maint_type]'\n Details: '[details]'\n\n Is this correct?", "Confirmation", "Yes", "No") + if(confirm == "Yes") + if(link) + var/datum/ares_ticket/maintenance/maint_ticket = new(last_login, maint_type, details, priority_report) + link.tickets_maintenance += maint_ticket + if(priority_report) + ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.") + log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(operator)] as [last_login] with Category '[maint_type]' and Details of '[details]'.") + return TRUE + return FALSE + + if("claim_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + var/claim = TRUE + var/assigned = ticket.ticket_assignee + if(assigned) + if(assigned == last_login) + var/prompt = tgui_alert(usr, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No")) + if(prompt != "Yes") + return FALSE + /// set ticket back to pending + ticket.ticket_assignee = null + ticket.ticket_status = TICKET_PENDING + return claim + var/choice = tgui_alert(usr, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No")) + if(choice != "Yes") + claim = FALSE + if(claim) + ticket.ticket_assignee = last_login + ticket.ticket_status = TICKET_ASSIGNED + return claim + + if("cancel_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + if(ticket.ticket_submitter != last_login) + to_chat(usr, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!")) + return FALSE + to_chat(usr, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled.")) + ticket.ticket_status = TICKET_CANCELLED + if(ticket.ticket_priority) + ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been cancelled.") + return TRUE + + if("mark_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + if(ticket.ticket_assignee != last_login && ticket.ticket_assignee) //must be claimed by you or unclaimed.) + to_chat(usr, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + return FALSE + var/choice = tgui_alert(usr, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS) + switch(choice) + if(TICKET_COMPLETED) + ticket.ticket_status = TICKET_COMPLETED + if(TICKET_REJECTED) + ticket.ticket_status = TICKET_REJECTED + else + return FALSE + if(ticket.ticket_priority) + ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by [last_login].") + to_chat(usr, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) + return TRUE + + if("new_access") + var/obj/item/card/id/idcard = operator.get_active_hand() + var/has_id = FALSE + if(istype(idcard)) + has_id = TRUE + else if(operator.wear_id) + idcard = operator.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!")) + 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!")) + 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) + 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") + 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) + ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] requesting access for '[details].") + return TRUE + + if("return_access") + playsound = FALSE + var/datum/ares_ticket/access/access_ticket + for(var/datum/ares_ticket/access/possible_ticket in link.tickets_access) + if(possible_ticket.ticket_status != TICKET_GRANTED) + continue + if(possible_ticket.ticket_name != last_login) + continue + access_ticket = possible_ticket + break + + for(var/obj/item/card/id/identification in link.active_ids) + if(!istype(identification)) + continue + if(identification.registered_gid != access_ticket.user_id_num) + continue + + access_ticket.ticket_status = TICKET_RETURNED + identification.access -= ACCESS_MARINE_AI_TEMP + identification.modification_log += "Temporary AI Access self-returned by [key_name(operator)]." + + to_chat(operator, 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.") + + authentication = get_ares_access(identification) + if(authentication) + 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!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + if("auth_access") + playsound = FALSE + var/datum/ares_ticket/access/access_ticket = locate(params["ticket"]) + if(!access_ticket) + return FALSE + for(var/obj/item/card/id/identification in link.waiting_ids) + if(!istype(identification)) + continue + if(identification.registered_gid != access_ticket.user_id_num) + continue + identification.handle_ares_access(last_login, operator) + 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].") + return TRUE + for(var/obj/item/card/id/identification in link.active_ids) + if(!istype(identification)) + continue + if(identification.registered_gid != access_ticket.user_id_num) + continue + identification.handle_ares_access(last_login, operator) + 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].") + return TRUE + return FALSE + + if("reject_access") + var/datum/ares_ticket/access/access_ticket = locate(params["ticket"]) + 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(usr, SPAN_WARNING("You cannot update a ticket that is not assigned to you!")) + return FALSE + access_ticket.ticket_status = TICKET_REJECTED + to_chat(usr, 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].") + return TRUE + + if(playsound) + var/sound = pick('sound/machines/pda_button1.ogg', 'sound/machines/pda_button2.ogg') + playsound(src, sound, 15, TRUE) diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 0af38cacd75e..1c240fb05dfb 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -18,16 +18,14 @@ PF.flags_can_pass_all = PASS_OVER|PASS_AROUND|PASS_UNDER /obj/structure/machinery/portable_atmospherics/powered/scrubber/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(prob(50/severity)) on = !on update_icon() - ..(severity) - /obj/structure/machinery/portable_atmospherics/powered/scrubber/update_icon() src.overlays = 0 diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 116753093fe5..912a6070328a 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -114,6 +114,7 @@ /obj/structure/machinery/bot/emp_act(severity) + . = ..() var/was_on = on stat |= EMPED new /obj/effect/overlay/temp/emp_sparks (loc) diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index d82591994e7b..b88f8249566b 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -916,11 +916,11 @@ post_signal_multiple(control_freq, kv) /obj/structure/machinery/bot/mulebot/emp_act(severity) + . = ..() if (cell) cell.emp_act(severity) if(load) load.emp_act(severity) - ..() /obj/structure/machinery/bot/mulebot/explode() diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index ee83c430c2db..8d4b27778c69 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -1,15 +1,3 @@ -/obj/structure/machinery/driver_button - name = "mass driver button" - icon = 'icons/obj/objects.dmi' - icon_state = "launcherbtt" - desc = "A remote control switch for a mass driver." - var/id = null - var/active = 0 - anchored = TRUE - use_power = USE_POWER_IDLE - idle_power_usage = 2 - active_power_usage = 4 - /obj/structure/machinery/ignition_switch name = "ignition switch" icon = 'icons/obj/objects.dmi' diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index d416c561fcd3..3b2a91eea314 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -35,6 +35,9 @@ var/colony_camera_mapload = TRUE + /// If this camera should have innate EMP-proofing + var/emp_proof = FALSE + /obj/structure/machinery/camera/Initialize(mapload, ...) . = ..() WireColorToFlag = randomCameraWires() @@ -72,6 +75,7 @@ if(WEST) pixel_x = 27 /obj/structure/machinery/camera/emp_act(severity) + . = ..() if(!isEmpProof()) if(prob(100/severity)) icon_state = "[initial(icon_state)]emp" @@ -89,7 +93,6 @@ if(can_use()) cameranet.addCamera(src) kick_viewers() - ..() /obj/structure/machinery/camera/ex_act(severity) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index a8735cbc06a8..e5ab520cbee8 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -30,6 +30,7 @@ network = list(CAMERA_NET_LASER_TARGETS) unslashable = TRUE unacidable = TRUE + emp_proof = TRUE /obj/structure/machinery/camera/laser_cam/Initialize(mapload, laser_name) . = ..() @@ -37,8 +38,6 @@ var/area/A = get_area(src) c_tag = "[laser_name] ([A.name])" -/obj/structure/machinery/camera/laser_cam/emp_act(severity) - return //immune to EMPs, just in case /obj/structure/machinery/camera/laser_cam/ex_act() return @@ -125,9 +124,7 @@ invisibility = 101 //fuck you init() colony_camera_mapload = FALSE - -/obj/structure/machinery/camera/autoname/lz_camera/emp_act(severity) - return //immune to EMPs, just in case + emp_proof = TRUE /obj/structure/machinery/camera/autoname/lz_camera/ex_act() return @@ -137,7 +134,7 @@ /obj/structure/machinery/camera/proc/isEmpProof() var/O = locate(/obj/item/stack/sheet/mineral/osmium) in assembly.upgrades - return O + return O || emp_proof /obj/structure/machinery/camera/proc/isXRay() var/obj/item/stock_parts/scanning_module/O = locate(/obj/item/stock_parts/scanning_module) in assembly.upgrades diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index fcd8c65e93ca..eb7a501fa078 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -80,11 +80,11 @@ return /obj/structure/machinery/cell_charger/emp_act(severity) + . = ..() if(inoperable()) return if(charging) charging.emp_act(severity) - ..(severity) /obj/structure/machinery/cell_charger/process() diff --git a/code/game/machinery/computer/almayer_control.dm b/code/game/machinery/computer/almayer_control.dm index 145d0d278cb6..fb9f7a0375d9 100644 --- a/code/game/machinery/computer/almayer_control.dm +++ b/code/game/machinery/computer/almayer_control.dm @@ -81,9 +81,9 @@ data["worldtime"] = world.time - data["evac_status"] = EvacuationAuthority.evac_status - if(EvacuationAuthority.evac_status == EVACUATION_STATUS_INITIATING) - data["evac_eta"] = EvacuationAuthority.get_status_panel_eta() + data["evac_status"] = SShijack.evac_status + if(SShijack.evac_status == EVACUATION_STATUS_INITIATED) + data["evac_eta"] = SShijack.get_evac_eta() if(!messagetitle.len) data["messages"] = null @@ -120,11 +120,11 @@ to_chat(usr, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) return FALSE - if(EvacuationAuthority.flags_scuttle & FLAGS_EVACUATION_DENY) + if(SShijack.evac_admin_denied) to_chat(usr, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) return FALSE - if(!EvacuationAuthority.initiate_evacuation()) + if(!SShijack.initiate_evacuation()) to_chat(usr, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) return FALSE @@ -134,12 +134,10 @@ . = TRUE if("evacuation_cancel") - if(!EvacuationAuthority.cancel_evacuation()) + if(!SShijack.cancel_evacuation()) to_chat(usr, SPAN_WARNING("You are unable to cancel the evacuation right now!")) return FALSE - addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/structure/machinery/computer/almayer_control, cancel_evac)), 4 SECONDS) - 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.") @@ -276,10 +274,3 @@ // end tgui interact \\ // end tgui \\ - -/obj/structure/machinery/computer/almayer_control/proc/cancel_evac() - if(EvacuationAuthority.evac_status == EVACUATION_STATUS_STANDING_BY)//nothing changed during the wait - //if the self_destruct is active we try to cancel it (which includes lowering alert level to red) - if(!EvacuationAuthority.cancel_self_destruct(1)) - //if SD wasn't active (likely canceled manually in the SD room), then we lower the alert level manually. - set_security_level(SEC_LEVEL_RED, TRUE) //both SD and evac are inactive, lowering the security level. diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 8d35dd1b6aff..1ac5a06738d5 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -165,8 +165,8 @@ return /obj/structure/machinery/computer/arcade/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return var/empprize = null var/num_of_prizes = 0 @@ -178,5 +178,3 @@ for(num_of_prizes; num_of_prizes > 0; num_of_prizes--) empprize = pickweight(prizes) new empprize(src.loc) - - ..(severity) diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm index 281c548227b0..0fd487e2ef7c 100644 --- a/code/game/machinery/computer/camera_console.dm +++ b/code/game/machinery/computer/camera_console.dm @@ -354,8 +354,8 @@ exproof = TRUE colony_camera_mapload = FALSE -/obj/structure/machinery/computer/cameras/mortar/emp_act(severity) - return FALSE +/obj/structure/machinery/computer/cameras/mortar/set_broken() + return /obj/structure/machinery/computer/cameras/dropship name = "abstract dropship camera computer" diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index d4d45de8db4e..b39f59530adc 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -43,7 +43,7 @@ var/stat_msg1 var/stat_msg2 - var/datum/tacmap/tacmap + var/datum/tacmap/drawing/tacmap var/minimap_type = MINIMAP_FLAG_USCM processing = TRUE @@ -138,11 +138,11 @@ to_chat(usr, SPAN_WARNING("The ship must be under delta alert in order to enact evacuation procedures.")) return FALSE - if(EvacuationAuthority.flags_scuttle & FLAGS_EVACUATION_DENY) + if(SShijack.evac_admin_denied) to_chat(usr, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) return FALSE - if(!EvacuationAuthority.initiate_evacuation()) + if(!SShijack.initiate_evacuation()) to_chat(usr, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) return FALSE @@ -155,17 +155,10 @@ if("evacuation_cancel") if(state == STATE_EVACUATION_CANCEL) - if(!EvacuationAuthority.cancel_evacuation()) + if(!SShijack.cancel_evacuation()) to_chat(usr, SPAN_WARNING("You are unable to cancel the evacuation right now!")) return FALSE - spawn(35)//some time between AI announcements for evac cancel and SD cancel. - if(EvacuationAuthority.evac_status == EVACUATION_STATUS_STANDING_BY)//nothing changed during the wait - //if the self_destruct is active we try to cancel it (which includes lowering alert level to red) - if(!EvacuationAuthority.cancel_self_destruct(1)) - //if SD wasn't active (likely canceled manually in the SD room), then we lower the alert level manually. - set_security_level(SEC_LEVEL_RED, TRUE) //both SD and evac are inactive, lowering the security level. - 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.") @@ -327,8 +320,8 @@ user.set_interaction(src) var/dat = "Communications Console" - if(EvacuationAuthority.evac_status == EVACUATION_STATUS_INITIATING) - dat += "Evacuation in Progress\n
\nETA: [EvacuationAuthority.get_status_panel_eta()]
" + if(SShijack.evac_status == EVACUATION_STATUS_INITIATED) + dat += "Evacuation in Progress\n
\nETA: [SShijack.get_evac_eta()]
" switch(state) if(STATE_DEFAULT) if(authenticated) @@ -351,9 +344,11 @@ dat += "
Award a medal" dat += "
Send Distress Beacon" dat += "
Activate Self-Destruct" - switch(EvacuationAuthority.evac_status) - if(EVACUATION_STATUS_STANDING_BY) dat += "
Initiate emergency evacuation" - if(EVACUATION_STATUS_INITIATING) dat += "
Cancel emergency evacuation" + switch(SShijack.evac_status) + if(EVACUATION_STATUS_NOT_INITIATED) + dat += "
Initiate emergency evacuation" + if(EVACUATION_STATUS_INITIATED) + dat += "
Cancel emergency evacuation" else dat += "
LOG IN" @@ -408,20 +403,8 @@ if(STATE_ALERT_LEVEL) dat += "Current alert level: [get_security_level()]
" - if(security_level == SEC_LEVEL_DELTA) - if(EvacuationAuthority.dest_status >= NUKE_EXPLOSION_ACTIVE) - dat += SET_CLASS("The self-destruct mechanism is active. [EvacuationAuthority.evac_status != EVACUATION_STATUS_INITIATING ? "You have to manually deactivate the self-destruct mechanism." : ""]", INTERFACE_RED) - dat += "
" - switch(EvacuationAuthority.evac_status) - if(EVACUATION_STATUS_INITIATING) - dat += SET_CLASS("Evacuation initiated. Evacuate or rescind evacuation orders.", INTERFACE_RED) - if(EVACUATION_STATUS_IN_PROGRESS) - dat += SET_CLASS("Evacuation in progress.", INTERFACE_RED) - if(EVACUATION_STATUS_COMPLETE) - dat += SET_CLASS("Evacuation complete.", INTERFACE_RED) - else - dat += "Blue
" - dat += "Green" + dat += "Blue
" + dat += "Green" if(STATE_CONFIRM_LEVEL) dat += "Current alert level: [get_security_level()]
" diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 304b24a14f04..c33517796271 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -31,8 +31,9 @@ return 1 /obj/structure/machinery/computer/emp_act(severity) - if(prob(20/severity)) set_broken() - ..() + . = ..() + if(prob(20/severity)) + set_broken() /obj/structure/machinery/computer/ex_act(severity) diff --git a/code/game/machinery/computer/groundside_operations.dm b/code/game/machinery/computer/groundside_operations.dm index 9856ae8f970e..f2b36276c8eb 100644 --- a/code/game/machinery/computer/groundside_operations.dm +++ b/code/game/machinery/computer/groundside_operations.dm @@ -25,7 +25,11 @@ add_pmcs = FALSE else if(SSticker.current_state < GAME_STATE_PLAYING) RegisterSignal(SSdcs, COMSIG_GLOB_MODE_PRESETUP, PROC_REF(disable_pmc)) - tacmap = new(src, minimap_type) + if(announcement_faction == FACTION_MARINE) + tacmap = new /datum/tacmap/drawing(src, minimap_type) + else + tacmap = new(src, minimap_type) // Non-drawing version + return ..() /obj/structure/machinery/computer/groundside_operations/Destroy() diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index fe85599018ae..53efad3da877 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -483,8 +483,8 @@ return /obj/structure/machinery/computer/med_data/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return for(var/datum/data/record/R as anything in GLOB.data_core.medical) @@ -509,8 +509,6 @@ qdel(R) continue - ..(severity) - /obj/structure/machinery/computer/med_data/laptop name = "Medical Laptop" diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index f6adaa8edd4e..7ec97874bb7f 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -1,158 +1,8 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -/obj/structure/machinery/computer/pod - name = "Pod Launch Control" - desc = "A control for launching pods. Some people prefer firing Mechas." +// Legacy SS13 machinery turned into props +/obj/structure/machinery/computer/pod/old + name = "DoorMex Control Computer" + desc = "A control for launching pods." icon_state = "computer_generic" density = TRUE - circuit = /obj/item/circuitboard/computer/pod - var/id = 1 - var/obj/structure/machinery/mass_driver/connected = null - var/timing = 0 - var/time = 30 - var/title = "Mass Driver Controls" + circuit = /obj/item/circuitboard/computer/pod/old processing = TRUE - - -/obj/structure/machinery/computer/pod/New() - ..() - spawn( 5 ) - for(var/obj/structure/machinery/mass_driver/M in machines) - if(M.id == id) - connected = M - return - return - - -/obj/structure/machinery/computer/pod/proc/alarm() - if(inoperable()) - return - - if(!( connected )) - to_chat(viewers(null, null), "Cannot locate mass driver connector. Cancelling firing sequence!") - return - - for(var/obj/structure/machinery/door/poddoor/M in machines) - if(M.id == id) - M.open() - - sleep(20) - - for(var/obj/structure/machinery/mass_driver/M in machines) - if(M.id == id) - M.power = connected.power - M.drive() - - sleep(50) - for(var/obj/structure/machinery/door/poddoor/M in machines) - if(M.id == id) - M.close() - return - return - -/obj/structure/machinery/computer/pod/attack_remote(mob/user as mob) - return attack_hand(user) - -/obj/structure/machinery/computer/pod/attack_hand(mob/user as mob) - if(..()) - return - - var/dat = "[title]" - user.set_interaction(src) - if(connected) - var/d2 - if(timing) //door controls do not need timers. - d2 = "Stop Time Launch" - else - d2 = "Initiate Time Launch" - var/second = time % 60 - var/minute = (time - second) / 60 - dat += "
\nTimer System: [d2]\nTime Left: [minute ? "[minute]:" : null][second] - - + +" - var/temp = "" - var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 ) - for(var/t in L) - if(t == connected.power) - temp += "[t] " - else - temp += "[t] " - dat += "
\nPower Level: [temp]
\nFiring Sequence
\nTest Fire Driver
\nToggle Outer Door
" - else - dat += "
\nToggle Outer Door
" - dat += "

Close
" - show_browser(user, dat, "computer", "size=400x500") - add_fingerprint(usr) - return - - -/obj/structure/machinery/computer/pod/process() - if(!..()) - return - if(timing) - if(time > 0) - time = round(time) - 1 - else - alarm() - time = 0 - timing = 0 - updateDialog() - return - - -/obj/structure/machinery/computer/pod/Topic(href, href_list) - if(..()) - return - if((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (isRemoteControlling(usr))) - usr.set_interaction(src) - if(href_list["power"]) - var/t = text2num(href_list["power"]) - t = min(max(0.25, t), 16) - if(connected) - connected.power = t - if(href_list["alarm"]) - alarm() - if(href_list["drive"]) - for(var/obj/structure/machinery/mass_driver/M in machines) - if(M.id == id) - M.power = connected.power - M.drive() - - if(href_list["time"]) - timing = text2num(href_list["time"]) - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 120) - if(href_list["door"]) - for(var/obj/structure/machinery/door/poddoor/M in machines) - if(M.id == id) - if(M.density) - M.open() - else - M.close() - updateUsrDialog() - return - - - -/obj/structure/machinery/computer/pod/old - name = "DoorMex Control Computer" - title = "Door Controls" - -/obj/structure/machinery/computer/pod/old/syndicate - name = "ProComp Executive IIc" - desc = "The Syndicate operate on a tight budget. Operates external airlocks." - icon_state = "syndicomp" - title = "External Airlock Controls" - req_access = list(ACCESS_ILLEGAL_PIRATE) - -/obj/structure/machinery/computer/pod/old/syndicate/attack_hand(mob/user as mob) - if(!allowed(user)) - to_chat(user, SPAN_DANGER("Access Denied")) - return - else - ..() - -/obj/structure/machinery/computer/pod/old/swf - name = "Magix System IV" - icon_state = "wizard" - desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorceror's Edition" diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 857118937910..2d9a4a1dbea4 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -524,8 +524,8 @@ What a mess.*/ return selection.fields["img"] /obj/structure/machinery/computer/secure_data/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return for(var/datum/data/record/R in GLOB.data_core.security) @@ -550,8 +550,6 @@ What a mess.*/ qdel(R) continue - ..(severity) - /obj/structure/machinery/computer/secure_data/detective_computer icon = 'icons/obj/structures/machinery/computer.dmi' icon_state = "messyfiles" diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index a20d344b53a9..60b5aa232940 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -347,8 +347,8 @@ What a mess.*/ return /obj/structure/machinery/computer/skills/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return for(var/datum/data/record/R in GLOB.data_core.security) @@ -373,4 +373,3 @@ What a mess.*/ qdel(R) continue - ..(severity) diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 99996bea8978..687882d9d7ae 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -65,6 +65,7 @@ return /obj/structure/machinery/deployable/barrier/emp_act(severity) + . = ..() if(inoperable()) return if(prob(50/severity)) diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index 8be8609d6008..5d6c66309d48 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -64,7 +64,7 @@ if(is_mainship_level(z)) // on the almayer return - shuttle.control_doors("lock", "all", force=FALSE) + shuttle.control_doors("force-lock", "all", force=FALSE) /obj/structure/machinery/door_control/proc/handle_door() for(var/obj/structure/machinery/door/airlock/D in range(range)) @@ -150,47 +150,6 @@ else icon_state = initial(icon_state) + "0" -/obj/structure/machinery/driver_button/attack_remote(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/machinery/driver_button/attackby(obj/item/W, mob/user as mob) - return src.attack_hand(user) - -/obj/structure/machinery/driver_button/attack_hand(mob/user as mob) - - src.add_fingerprint(usr) - if(inoperable()) - return - if(active) - return - add_fingerprint(user) - - use_power(5) - - active = 1 - icon_state = "launcheract" - - for(var/obj/structure/machinery/door/poddoor/M in machines) - if(M.id == src.id) - INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/structure/machinery/door, open)) - - sleep(20) - - for(var/obj/structure/machinery/mass_driver/M in machines) - if(M.id == src.id) - M.drive() - - sleep(50) - - for(var/obj/structure/machinery/door/poddoor/M in machines) - if(M.id == src.id) - INVOKE_ASYNC(M, TYPE_PROC_REF(/obj/structure/machinery/door, close)) - - icon_state = "launcherbtt" - active = 0 - - return - // Controls elevator railings /obj/structure/machinery/door_control/railings name = "railing controls" diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index b7257ff4e7d3..c6d9ddf3efbd 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -866,3 +866,8 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list( var/damage = xeno.melee_damage_upper * TAILSTAB_AIRLOCK_DAMAGE_MULTIPLIER take_damage(damage, xeno) return TAILSTAB_COOLDOWN_NORMAL + +/obj/structure/machinery/door/airlock/autoclose() + if(locked) + return + ..() diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index f4d09796194c..feb699fd245e 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -138,7 +138,6 @@ opacity = 0 assembly_type = /obj/structure/airlock_assembly/airlock_assembly_research glass = 1 - heat_proof = 1 req_one_access = list(ACCESS_CIVILIAN_RESEARCH, ACCESS_CIVILIAN_COMMAND, ACCESS_WY_COLONIAL) /obj/structure/machinery/door/airlock/glass_mining/colony diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 578ef368f5d9..021cb60769f9 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -1,4 +1,3 @@ - /obj/structure/machinery/door name = "\improper Door" desc = "It opens and closes." @@ -7,50 +6,43 @@ anchored = TRUE opacity = TRUE density = TRUE - throwpass = 0 + throwpass = FALSE layer = DOOR_OPEN_LAYER minimap_color = MINIMAP_DOOR var/open_layer = DOOR_OPEN_LAYER var/closed_layer = DOOR_CLOSED_LAYER var/id = "" + var/width = 1 var/secondsElectrified = 0 - var/visible = 1 + var/visible = TRUE var/panel_open = FALSE - var/operating = 0 - var/autoclose = 0 - var/glass = 0 - var/normalspeed = 1 - var/openspeed = 10 //How many seconds does it take to open it? Default 1 second. Use only if you have long door opening animations - var/heat_proof = 0 // For glass airlocks/opacity firedoors - var/air_properties_vary_with_direction = 0 - var/turf/filler //Fixes double door opacity issue + var/operating = FALSE + var/autoclose = FALSE + var/glass = FALSE + /// If FALSE it speeds up the autoclosing timing. + var/normalspeed = TRUE + /// Time to open/close airlock, default is 1 second. + var/openspeed = 1 SECONDS + /// Fixes multi_tile doors opacity issues. + var/list/filler_turfs = list() //Previously this was just var, because no one had forseen someone creating doors more than 2 tiles wide /// Stops it being forced open through normal means (Hunters/Zombies/Aliens). var/heavy = FALSE /// Resistance to masterkey var/masterkey_resist = FALSE var/masterkey_mod = 0.1 - - - //Multi-tile doors - dir = EAST - var/width = 1 + dir = EAST //So multitile doors are directioned properly /obj/structure/machinery/door/Initialize(mapload, ...) . = ..() - if(density) - layer = closed_layer - update_flags_heat_protection(get_turf(src)) - else - layer = open_layer - + layer = density ? closed_layer : open_layer handle_multidoor() /obj/structure/machinery/door/Destroy() . = ..() - if(filler && width > 1) - filler.set_opacity(0)// Ehh... let's hope there are no walls there. Must fix this - filler = null + if(length(filler_turfs) && width > 1) + change_filler_opacity(0) // It still doesn't check for walls, might want to add checking that in the future + filler_turfs = null density = FALSE /obj/structure/machinery/door/initialize_pass_flags(datum/pass_flags_container/PF) @@ -58,21 +50,41 @@ if (PF) PF.flags_can_pass_all = NONE +/// Also refreshes filler_turfs list. +/obj/structure/machinery/door/proc/change_filler_opacity(new_opacity) + // I have no idea why do we null opacity first before... changing it + for(var/turf/filler_turf as anything in filler_turfs) + filler_turf.set_opacity(null) + + filler_turfs = list() + for(var/turf/filler as anything in locate_filler_turfs()) + filler.set_opacity(new_opacity) + filler_turfs += filler + +/// Updates collision box and opacity of multi_tile airlocks. /obj/structure/machinery/door/proc/handle_multidoor() if(width > 1) if(dir in list(EAST, WEST)) bound_width = width * world.icon_size bound_height = world.icon_size - filler = get_step(src,EAST) - filler.set_opacity(opacity) else bound_width = world.icon_size bound_height = width * world.icon_size - filler = get_step(src,NORTH) - filler.set_opacity(opacity) + change_filler_opacity(opacity) + +/// Finds turfs which should be filler ones. +/obj/structure/machinery/door/proc/locate_filler_turfs() + var/turf/filler_temp + var/list/located_turfs = list() -//process() - //return + for(var/i in 1 to width - 1) + if (dir in list(EAST, WEST)) + filler_temp = locate(x + i, y, z) + else + filler_temp = locate(x, y + i, z) + if (filler_temp) + located_turfs += filler_temp + return located_turfs /obj/structure/machinery/door/proc/borders_space() for(var/turf/target in range(1, src)) @@ -81,7 +93,8 @@ return FALSE /obj/structure/machinery/door/Collided(atom/movable/AM) - if(panel_open || operating) return + if(panel_open || operating) + return if(ismob(AM)) var/mob/M = AM if(world.time - M.last_bumped <= openspeed) return //Can bump-open one airlock per second. This is to prevent shock spam. @@ -89,12 +102,10 @@ if(!M.is_mob_restrained() && M.mob_size > MOB_SIZE_SMALL) bumpopen(M) return - if(istype(AM, /obj)) var/obj/O = AM if(O.buckled_mob) Collided(O.buckled_mob) - if(istype(AM, /obj/structure/machinery/bot)) var/obj/structure/machinery/bot/bot = AM if(src.check_access(bot.botcard)) @@ -102,16 +113,17 @@ open() return - /obj/structure/machinery/door/proc/bumpopen(mob/user as mob) - if(operating) return - src.add_fingerprint(user) - if(!src.requiresID()) + if(operating) + return + add_fingerprint(user) + if(!requiresID()) user = null - if(density) - if(allowed(user)) open() - else flick("door_deny", src) + if(allowed(user)) + open() + else + flick("door_deny", src) return /obj/structure/machinery/door/attack_remote(mob/user) @@ -124,9 +136,7 @@ add_fingerprint(user) if(operating) return - if(!Adjacent(user)) - user = null //so allowed(user) always succeeds - if(!requiresID()) + if(!Adjacent(user) || !requiresID()) user = null //so allowed(user) always succeeds if(allowed(user)) if(density) @@ -137,64 +147,56 @@ if(density) flick("door_deny", src) - /obj/structure/machinery/door/attackby(obj/item/I, mob/user) if(!(I.flags_item & NOBLUDGEON)) try_to_activate_door(user) - return 1 + return TRUE /obj/structure/machinery/door/emp_act(severity) - if(prob(20/severity) && (istype(src,/obj/structure/machinery/door/airlock) || istype(src,/obj/structure/machinery/door/window)) ) + . = ..() + if(prob(20/severity) && use_power) open() if(prob(40/severity)) if(secondsElectrified == 0) secondsElectrified = -1 spawn(30 SECONDS) secondsElectrified = 0 - ..() - /obj/structure/machinery/door/ex_act(severity) - if(unacidable) return + if(unacidable) + return if(density) switch(severity) if(0 to EXPLOSION_THRESHOLD_LOW) if(prob(80)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(2, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(2, 1, src) + spark.start() if(EXPLOSION_THRESHOLD_LOW to INFINITY) qdel(src) else switch(severity) if(0 to EXPLOSION_THRESHOLD_MEDIUM) if(prob(80)) - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(2, 1, src) - s.start() + var/datum/effect_system/spark_spread/spark = new /datum/effect_system/spark_spread + spark.set_up(2, 1, src) + spark.start() else qdel(src) return - /obj/structure/machinery/door/get_explosion_resistance() if(density) if(unacidable) - return 1000000 + return 1000000 //Used for negation of explosions, should probably be made into define in the future else return EXPLOSION_THRESHOLD_LOW //this should exactly match the amount of damage needed to destroy the door else return 0 - /obj/structure/machinery/door/update_icon() - if(density) - icon_state = "door1" - else - icon_state = "door0" - return - + icon_state = density ? "door1" : "door0" /obj/structure/machinery/door/proc/do_animate(animation) switch(animation) @@ -212,7 +214,6 @@ flick("door_deny", src) return - /obj/structure/machinery/door/proc/open(forced=0) if(!density) return TRUE @@ -223,8 +224,8 @@ do_animate("opening") icon_state = "door0" set_opacity(FALSE) - if(filler) - filler.set_opacity(opacity) + if(length(filler_turfs)) + change_filler_opacity(opacity) addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed) return TRUE @@ -235,11 +236,9 @@ if(operating) operating = FALSE - if(autoclose) addtimer(CALLBACK(src, PROC_REF(autoclose)), normalspeed ? 150 + openspeed : 5) - /obj/structure/machinery/door/proc/close() if(density) return TRUE @@ -256,22 +255,19 @@ update_icon() if(visible && !glass) set_opacity(TRUE) - if(filler) - filler.set_opacity(opacity) + if(length(filler_turfs)) + change_filler_opacity(opacity) operating = FALSE /obj/structure/machinery/door/proc/requiresID() return TRUE - -/obj/structure/machinery/door/proc/update_flags_heat_protection(turf/source) - - +/// Used for overriding in airlocks /obj/structure/machinery/door/proc/autoclose() - var/obj/structure/machinery/door/airlock/A = src - if(!A.density && !A.operating && !A.locked && !A.welded && A.autoclose) + if(!autoclose) + return + if(!density && !operating) close() - return /obj/structure/machinery/door/Move(new_loc, new_dir) . = ..() @@ -279,16 +275,15 @@ if(dir in list(EAST, WEST)) bound_width = width * world.icon_size bound_height = world.icon_size - filler.set_opacity(0) - filler = (get_step(src,EAST)) //Find new turf - filler.set_opacity(opacity) else bound_width = world.icon_size bound_height = width * world.icon_size - filler.set_opacity(0) - filler = (get_step(src,NORTH)) //Find new turf - filler.set_opacity(opacity) + change_filler_opacity(opacity) +/obj/structure/machinery/door/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) + . = ..() + // Yes, for a split second after departure you can see through rear dropship airlocks, but it's the simplest solution I could've think of + handle_multidoor() /obj/structure/machinery/door/morgue icon = 'icons/obj/structures/doors/doormorgue.dmi' diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index 65ecd67a438e..0a179af27803 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -13,7 +13,6 @@ /obj/structure/machinery/door/airlock/multi_tile/Initialize() . = ..() - handle_multidoor() update_icon() /obj/structure/machinery/door/airlock/multi_tile/glass @@ -137,7 +136,6 @@ /obj/structure/window/framed/almayer, /obj/structure/machinery/door/airlock, ) - var/multi_filler = list() /obj/structure/machinery/door/airlock/multi_tile/almayer/Initialize() . = ..() @@ -233,42 +231,6 @@ req_access = null req_one_access = list(ACCESS_CIVILIAN_BRIG, ACCESS_CIVILIAN_COMMAND, ACCESS_WY_COLONIAL) -/obj/structure/machinery/door/airlock/multi_tile/almayer/handle_multidoor() - . = ..() - if(!(width > 1)) return //Bubblewrap - - update_filler_turfs() - -//We have to find these again since these doors are used on shuttles a lot so the turfs changes -/obj/structure/machinery/door/airlock/multi_tile/almayer/proc/update_filler_turfs() - for(var/turf/T in multi_filler) - T.set_opacity(null) - - multi_filler = list() - for(var/turf/T in get_filler_turfs()) - T.set_opacity(opacity) - multi_filler += list(T) - -/obj/structure/machinery/door/airlock/multi_tile/proc/get_filler_turfs() - . = list() - for(var/i = 1, i < width, i++) - if(dir in list(NORTH, SOUTH)) - var/turf/T = locate(x, y + i, z) - if(T) - . += list(T) - else if(dir in list(EAST, WEST)) - var/turf/T = locate(x + i, y, z) - if(T) - . += list(T) - -/obj/structure/machinery/door/airlock/multi_tile/almayer/open() - . = ..() - update_filler_turfs() - -/obj/structure/machinery/door/airlock/multi_tile/almayer/close() - . = ..() - update_filler_turfs() - //------Dropship Cargo Doors -----// /obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear @@ -313,6 +275,17 @@ name = "\improper Normandy cargo door" icon = 'icons/obj/structures/doors/dropship2_cargo.dmi' +/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/dropshipside + width = 2 + +/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/dropshipside/ds1 + name = "\improper Alamo crew hatch" + icon = 'icons/obj/structures/doors/dropship1_side2.dmi' + +/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/dropshipside/ds2 + name = "\improper Normandy crew hatch" + icon = 'icons/obj/structures/doors/dropship2_side2.dmi' + /obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/blastdoor name = "bulkhead blast door" icon = 'icons/obj/structures/doors/almayerblastdoor.dmi' diff --git a/code/game/machinery/doors/runed_sandstone.dm b/code/game/machinery/doors/runed_sandstone.dm index 4bf66dfdc8d8..a6de7348dd7f 100644 --- a/code/game/machinery/doors/runed_sandstone.dm +++ b/code/game/machinery/doors/runed_sandstone.dm @@ -110,8 +110,8 @@ density = FALSE update_icon() set_opacity(0) - if(filler) - filler.set_opacity(opacity) + if(length(filler_turfs)) + change_filler_opacity(opacity) if(operating) operating = FALSE diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 2b57fbd0a44d..bd544c5c3f5a 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -11,7 +11,6 @@ flags_atom = ON_BORDER opacity = FALSE var/obj/item/circuitboard/airlock/electronics = null - air_properties_vary_with_direction = 1 /obj/structure/machinery/door/window/Initialize() . = ..() diff --git a/code/game/machinery/fax_machine.dm b/code/game/machinery/fax_machine.dm index 7bbc86681eb1..ff21671ed758 100644 --- a/code/game/machinery/fax_machine.dm +++ b/code/game/machinery/fax_machine.dm @@ -6,6 +6,7 @@ var/list/alldepartments = list() #define DEPARTMENT_CMB "CMB Incident Command Center, Local Operations" #define DEPARTMENT_PROVOST "USCM Provost Office" #define DEPARTMENT_PRESS "Various Press Organizations" +#define HIGHCOM_DEPARTMENTS list(DEPARTMENT_WY, DEPARTMENT_HC, DEPARTMENT_CMB, DEPARTMENT_PROVOST, DEPARTMENT_PRESS) /obj/structure/machinery/faxmachine // why not fax_machine? name = "\improper General Purpose Fax Machine" @@ -319,10 +320,14 @@ var/list/alldepartments = list() GLOB.fax_contents += faxcontents + var/scan_department = target_department + if(department in HIGHCOM_DEPARTMENTS) + scan_department = department + var/msg_admin = SPAN_STAFF_IC("[target_department]: [key_name(user, 1)] ") msg_admin += "[CC_MARK(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_JMP_USER(user)] " - switch(target_department) + switch(scan_department) if(DEPARTMENT_HC) GLOB.USCMFaxes.Add("\['[original_fax.name]' from [key_name(usr)], [scan] at [time2text(world.timeofday, "hh:mm:ss")]\] REPLY") msg_admin += "(RPLY): " diff --git a/code/game/machinery/fire_alarm.dm b/code/game/machinery/fire_alarm.dm index fe1f80646c4f..dd7e0ee70150 100644 --- a/code/game/machinery/fire_alarm.dm +++ b/code/game/machinery/fire_alarm.dm @@ -63,8 +63,9 @@ FIRE ALARM return src.alarm() /obj/structure/machinery/firealarm/emp_act(severity) - if(prob(50/severity)) alarm() - ..() + . = ..() + if(prob(50/severity)) + alarm() /obj/structure/machinery/firealarm/attackby(obj/item/held_object as obj, mob/user as mob) src.add_fingerprint(user) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index 75d0de56dec0..cd59862a2e13 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -84,12 +84,11 @@ /obj/structure/machinery/flasher/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(prob(75/severity)) flash() - ..(severity) /obj/structure/machinery/flasher/portable/HasProximity(atom/movable/AM as mob|obj) if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150)) diff --git a/code/game/machinery/fusion_engine.dm b/code/game/machinery/fusion_engine.dm index 4158727e3745..8e3097ef52d1 100644 --- a/code/game/machinery/fusion_engine.dm +++ b/code/game/machinery/fusion_engine.dm @@ -15,6 +15,7 @@ unacidable = TRUE //NOPE.jpg anchored = TRUE density = TRUE + power_machine = TRUE var/power_gen_percent = 0 //50,000W at full capacity var/buildstate = 0 //What state of building it are we on, 0-3, 1 is "broken", the default @@ -24,7 +25,8 @@ var/obj/item/fuelCell/fusion_cell = new //Starts with a fuel cell loaded in. Maybe replace with the plasma tanks in the future and have it consume plasma? Possibly remove this later if it's irrelevent... var/fuel_rate = 0 //Rate at which fuel is used. Based mostly on how long the generator has been running. - power_machine = TRUE + /// If the generator is overloaded. Only possible during hijack once fuel is at 100%. + var/overloaded = FALSE /obj/structure/machinery/power/fusion_engine/Initialize(mapload, ...) . = ..() @@ -35,11 +37,25 @@ /obj/structure/machinery/power/fusion_engine/Destroy() QDEL_NULL(fusion_cell) - . = ..() + return ..() +/obj/structure/machinery/power/fusion_engine/attack_alien(mob/living/carbon/xenomorph/xeno) + if(!overloaded) + to_chat(xeno, SPAN_WARNING("You see no reason to attack [src].")) + return XENO_NO_DELAY_ACTION + + xeno.animation_attack_on(src) + playsound(src, 'sound/effects/metalhit.ogg', 25, 1) + xeno.visible_message(SPAN_DANGER("[xeno] [xeno.slashes_verb] [src], stopping its overload process!"), \ + SPAN_DANGER("You [xeno.slash_verb] [src], stopping its overload process!"), null, 5, CHAT_TYPE_XENO_COMBAT) + set_overloading(FALSE) + return XENO_ATTACK_ACTION /obj/structure/machinery/power/fusion_engine/power_change() - return + . = ..() + if(overloaded) + set_overloading(FALSE) + visible_message("[icon2html(src, viewers(src))] [src]'s overload suddenly ceases as primary power is lost.") /obj/structure/machinery/power/fusion_engine/process() if(!is_on || buildstate || !anchored || !powernet || !fusion_cell) //Default logic checking @@ -60,9 +76,18 @@ stop_processing() return FALSE - if(!check_failure()) + if(overloaded && prob(1)) // up to 18 generators at 1% every 3.5 seconds means that every ~21 seconds or so, one generator will make noise assuming all are overloaded + switch(rand(1, 2)) + if(1) + visible_message("[icon2html(src, viewers(src))] [SPAN_NOTICE("[src] loudly hums.")]") + playsound(src, 'sound/machines/resource_node/node_idle.ogg', 60, TRUE) + if(2) + visible_message("[icon2html(src, viewers(src))] [SPAN_NOTICE("[src] makes a worrying hiss.")]") + playsound(src, 'sound/machines/hiss.ogg', 60, TRUE) - if(power_gen_percent < 100) power_gen_percent++ + if(!check_failure()) + if(power_gen_percent < 100) + power_gen_percent++ switch(power_gen_percent) //Flavor text! if(10) @@ -96,6 +121,10 @@ to_chat(user, SPAN_NOTICE("Use a wrench to repair it.")) return FALSE if(is_on) + if(overloaded) + to_chat(user, SPAN_WARNING("You can't shut off [src] while it's overloaded!")) + return + visible_message("[icon2html(src, viewers(src))] [SPAN_WARNING("[src] beeps softly and the humming stops as [usr] shuts off the generator.")]") is_on = 0 power_gen_percent = 0 @@ -208,11 +237,18 @@ if(buildstate) to_chat(user, SPAN_WARNING("You must repair the generator before working with its fuel cell.")) return + + if(overloaded) + to_chat(user, SPAN_WARNING("You must restore the safeties on the generator before working with its fuel cell.")) + return + if(is_on) to_chat(user, SPAN_WARNING("You must turn off the generator before working with its fuel cell.")) return + if(!fusion_cell) to_chat(user, SPAN_WARNING("There is no cell to remove.")) + else if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI)) user.visible_message(SPAN_WARNING("[user] fumbles around figuring out [src]'s fuel receptacle."), @@ -232,23 +268,73 @@ fusion_cell = null update_icon() return TRUE + + else if(HAS_TRAIT(O, TRAIT_TOOL_MULTITOOL)) + if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI)) + to_chat(user, SPAN_WARNING("You have no idea what to do with [src].")) + return + + if(!overloaded) + if(!SShijack.sd_unlocked) + to_chat(user, SPAN_WARNING("You consider overloading [src]'s safeties, but you decide against it.")) + return + + if(inoperable()) + to_chat(user, SPAN_WARNING("[src] needs to be working and have external power in order to overload it!")) + return + + to_chat(user, SPAN_WARNING("You start overloading the safeties on [src]...")) + if(!do_after(user, 1.5 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) + return + + if(inoperable()) + return + + to_chat(user, SPAN_WARNING("You finish overloading the safeties on [src].")) + set_overloading(TRUE) + log_game("[key_name(user)] has overloaded a generator.") + + else + to_chat(user, SPAN_WARNING("You start restoring the safeties on [src]...")) + if(!do_after(user, 1.5 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) + return + + if(inoperable()) + return + + to_chat(user, SPAN_WARNING("You finish restoring the safeties on [src].")) + log_game("[key_name(user)] has restored the safeties of a generator.") + set_overloading(FALSE) + + return TRUE + else return ..() /obj/structure/machinery/power/fusion_engine/get_examine_text(mob/user) . = ..() - if(ishuman(user)) + if(isxeno(user)) + if(overloaded) + . += SPAN_INFO("You could attack this to stop the overload process.") + + else if(ishuman(user)) if(buildstate) . += SPAN_INFO("It's broken.") switch(buildstate) if(1) - . += SPAN_INFO("Use a blowtorch, then wirecutters, then wrench to repair it.") + . += SPAN_INFO("Use a blowtorch, then wirecutters, then wrench to repair it.") if(2) - . += SPAN_INFO("Use a wirecutters, then wrench to repair it.") + . += SPAN_INFO("Use a wirecutters, then wrench to repair it.") if(3) - . += SPAN_INFO("Use a wrench to repair it.") + . += SPAN_INFO("Use a wrench to repair it.") return FALSE + if(SShijack.sd_unlocked && skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI)) + if(!overloaded) + . += SPAN_INFO("You could overload this with a multitool.") + else + . += SPAN_INFO("You could restore its safeties with a multitool.") + if(!is_on) . += SPAN_INFO("It looks offline.") else @@ -274,18 +360,21 @@ switch(buildstate) if(0) if(fusion_cell) - var/pstatus = is_on ? "on" : "off" - switch(fusion_cell.get_fuel_percent()) - if(0 to 10) - icon_state = "[pstatus]-10" - if(10 to 25) - icon_state = "[pstatus]-25" - if(25 to 50) - icon_state = "[pstatus]-50" - if(50 to 75) - icon_state = "[pstatus]-75" - if(75 to INFINITY) - icon_state = "[pstatus]-100" + if(overloaded) + icon_state = "overloaded" + else + var/pstatus = is_on ? "on" : "off" + switch(fusion_cell.get_fuel_percent()) + if(0 to 10) + icon_state = "[pstatus]-10" + if(10 to 25) + icon_state = "[pstatus]-25" + if(25 to 50) + icon_state = "[pstatus]-50" + if(50 to 75) + icon_state = "[pstatus]-75" + if(75 to INFINITY) + icon_state = "[pstatus]-100" else icon_state = "off" @@ -317,9 +406,13 @@ else return 0 +/obj/structure/machinery/power/fusion_engine/proc/set_overloading(new_overloading) + if(overloaded == new_overloading) + return - - + overloaded = new_overloading + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_GENERATOR_SET_OVERLOADING, overloaded) + update_icon() diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 33f75c50e341..d5a0505fca17 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -105,11 +105,10 @@ return 1 /obj/structure/machinery/sparker/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return ignite() - ..(severity) /obj/structure/machinery/ignition_switch/attack_remote(mob/user as mob) return attack_hand(user) diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 66eb0386713f..de61830c2501 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -62,8 +62,7 @@ updateicon() /obj/structure/machinery/light_switch/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return power_change() - ..(severity) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index f4ad7a63ba77..66bf08afba8e 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -105,7 +105,7 @@ Class Procs: var/list/component_parts //list of all the parts used to build it, if made from certain kinds of frames. var/manual = 0 layer = OBJ_LAYER - var/machine_processing = 0 // whether the machine is busy and requires process() calls in scheduler. + var/machine_processing = 0 // whether the machine is busy and requires process() calls in scheduler. // Please replace this by DF_ISPROCESSING in another refactor --fira throwpass = 1 projectile_coverage = PROJECTILE_COVERAGE_MEDIUM var/power_machine = FALSE //Whether the machine should process on power, or normal processor @@ -175,10 +175,10 @@ Class Procs: . += SPAN_WARNING("[msg]") /obj/structure/machinery/emp_act(severity) + . = ..() if(use_power && stat == 0) use_power(7500/severity) new /obj/effect/overlay/temp/emp_sparks (loc) - ..() /obj/structure/machinery/ex_act(severity) diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm deleted file mode 100644 index 591cec1f5baa..000000000000 --- a/code/game/machinery/magnet.dm +++ /dev/null @@ -1,421 +0,0 @@ -// Magnetic attractor, creates variable magnetic fields and attraction. -// Can also be used to emit electron/proton beams to create a center of magnetism on another tile - -// tl;dr: it's magnets lol -// This was created for firing ranges, but I suppose this could have other applications - Doohl - -/obj/structure/machinery/magnetic_module - - icon = 'icons/obj/objects.dmi' - icon_state = "floor_magnet-f" - name = "Electromagnetic Generator" - desc = "A device that uses station power to create points of magnetic energy." - level = 1 // underfloor - layer = UNDERFLOOR_OBJ_LAYER - anchored = TRUE - use_power = USE_POWER_IDLE - idle_power_usage = 50 - - var/freq = 1449 // radio frequency - var/electricity_level = 1 // intensity of the magnetic pull - var/magnetic_field = 1 // the range of magnetic attraction - var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something - var/turf/center // the center of magnetic attraction - var/on = 0 - var/pulling = 0 - - // x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down - var/center_x = 0 - var/center_y = 0 - var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer - -/obj/structure/machinery/magnetic_module/Initialize(mapload, ...) - . = ..() - - var/turf/T = loc - hide(T.intact_tile) - center = T - - SSradio.add_object(src, freq, RADIO_MAGNETS) - - INVOKE_ASYNC(src, PROC_REF(magnetic_process)) - -/obj/structure/machinery/magnetic_module/Destroy() - center = null - SSradio.remove_object(src, freq) - . = ..() - - - // update the invisibility and icon -/obj/structure/machinery/magnetic_module/hide(intact) - invisibility = intact ? 101 : 0 - updateicon() - - // update the icon_state -/obj/structure/machinery/magnetic_module/proc/updateicon() - var/state="floor_magnet" - var/onstate="" - if(!on) - onstate="0" - - if(invisibility) - icon_state = "[state][onstate]-f" // if invisible, set icon to faded version - // in case of being revealed by T-scanner - else - icon_state = "[state][onstate]" - -/obj/structure/machinery/magnetic_module/receive_signal(datum/signal/signal) - - var/command = signal.data["command"] - var/modifier = signal.data["modifier"] - var/signal_code = signal.data["code"] - if(command && (signal_code == code)) - - Cmd(command, modifier) - - - -/obj/structure/machinery/magnetic_module/proc/Cmd(command, modifier) - - if(command) - switch(command) - if("set-electriclevel") - if(modifier) electricity_level = modifier - if("set-magneticfield") - if(modifier) magnetic_field = modifier - - if("add-elec") - electricity_level++ - if(electricity_level > 12) - electricity_level = 12 - if("sub-elec") - electricity_level-- - if(electricity_level <= 0) - electricity_level = 1 - if("add-mag") - magnetic_field++ - if(magnetic_field > 4) - magnetic_field = 4 - if("sub-mag") - magnetic_field-- - if(magnetic_field <= 0) - magnetic_field = 1 - - if("set-x") - if(modifier) center_x = modifier - if("set-y") - if(modifier) center_y = modifier - - if("N") // NORTH - center_y++ - if("S") // SOUTH - center_y-- - if("E") // EAST - center_x++ - if("W") // WEST - center_x-- - if("C") // CENTER - center_x = 0 - center_y = 0 - if("R") // RANDOM - center_x = rand(-max_dist, max_dist) - center_y = rand(-max_dist, max_dist) - - if("set-code") - if(modifier) code = modifier - if("toggle-power") - on = !on - - if(on) - INVOKE_ASYNC(src, PROC_REF(magnetic_process)) - - -/obj/structure/machinery/magnetic_module/process() - if(stat & NOPOWER) - on = 0 - - // Sanity checks: - if(electricity_level <= 0) - electricity_level = 1 - if(magnetic_field <= 0) - magnetic_field = 1 - - - // Limitations: - if(abs(center_x) > max_dist) - center_x = max_dist - if(abs(center_y) > max_dist) - center_y = max_dist - if(magnetic_field > 4) - magnetic_field = 4 - if(electricity_level > 12) - electricity_level = 12 - - // Update power usage: - if(on) - use_power = USE_POWER_ACTIVE - active_power_usage = electricity_level*15 - else - use_power = USE_POWER_NONE - - - // Overload conditions: - /* // Eeeehhh kinda stupid - if(on) - if(electricity_level > 11) - if(prob(electricity_level)) - explosion(loc, 0, 1, 2, 3) // ooo dat shit EXPLODES son - spawn(2) - qdel(src) - */ - - updateicon() - - -/obj/structure/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the pulling - if(pulling) return - while(on) - - pulling = 1 - center = locate(x+center_x, y+center_y, z) - if(center) - for(var/obj/M in orange(magnetic_field, center)) - if(!M.anchored && (M.flags_atom & CONDUCT)) - step_towards(M, center) - - for(var/mob/living/silicon/S in orange(magnetic_field, center)) - if(isAI(S)) continue - step_towards(S, center) - - use_power(electricity_level * 5) - sleep(13 - electricity_level) - - pulling = 0 - -/obj/structure/machinery/magnetic_controller - name = "Magnetic Control Console" - icon = 'icons/obj/structures/machinery/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING! - icon_state = "airlock_control_standby" - density = TRUE - anchored = TRUE - use_power = USE_POWER_IDLE - idle_power_usage = 45 - var/frequency = 1449 - var/code = 0 - var/list/magnets = list() - var/title = "Magnetic Control Console" - var/autolink = 0 // if set to 1, can't probe for other magnets! - - var/pathpos = 1 // position in the path - var/path = "NULL" // text path of the magnet - var/speed = 1 // lowest = 1, highest = 10 - var/list/rpath = list() // real path of the magnet, used in iterator - - var/moving = 0 // 1 if scheduled to loop - var/looping = 0 // 1 if looping - - var/datum/radio_frequency/radio_connection - -/obj/structure/machinery/magnetic_controller/Initialize(mapload, ...) - . = ..() - if(autolink) - for(var/obj/structure/machinery/magnetic_module/M in machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - - SSradio.add_object(src, frequency, RADIO_MAGNETS) - - if(path) // check for default path - filter_path() // renders rpath - -/obj/structure/machinery/magnetic_controller/Destroy() - QDEL_NULL_LIST(magnets) - SSradio.remove_object(src, frequency) - . = ..() - - -/obj/structure/machinery/magnetic_controller/process() - if(magnets.len == 0 && autolink) - for(var/obj/structure/machinery/magnetic_module/M in machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - -/obj/structure/machinery/magnetic_controller/attack_remote(mob/user as mob) - return src.attack_hand(user) - -/obj/structure/machinery/magnetic_controller/attack_hand(mob/user as mob) - if(inoperable()) - return - user.set_interaction(src) - var/dat = "Magnetic Control Console

" - if(!autolink) - dat += {" - Frequency: [frequency]
- Code: [code]
- Probe Generators
- "} - - if(magnets.len >= 1) - - dat += "Magnets confirmed:
" - var/i = 0 - for(var/obj/structure/machinery/magnetic_module/M in magnets) - i++ - dat += "     < \[[i]\] ([M.on ? "On":"Off"])|Electricity level: - [M.electricity_level] +; Magnetic field: - [M.magnetic_field] +
" - - dat += "
Speed: - [speed] +
" - dat += "Path: {[path]}
" - dat += "Moving: [moving ? "Enabled":"Disabled"]" - - - show_browser(user, dat, name, "magnet", "size=400x500") - -/obj/structure/machinery/magnetic_controller/Topic(href, href_list) - . = ..() - if(.) - return - if(inoperable()) - return - usr.set_interaction(src) - src.add_fingerprint(usr) - - if(href_list["radio-op"]) - - // Prepare signal beforehand, because this is a radio operation - var/datum/signal/signal = new - signal.transmission_method = 1 // radio transmission - signal.source = src - signal.frequency = frequency - signal.data["code"] = code - - // Apply any necessary commands - switch(href_list["radio-op"]) - if("togglepower") - signal.data["command"] = "toggle-power" - - if("minuselec") - signal.data["command"] = "sub-elec" - if("pluselec") - signal.data["command"] = "add-elec" - - if("minusmag") - signal.data["command"] = "sub-mag" - if("plusmag") - signal.data["command"] = "add-mag" - - - // Broadcast the signal - - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) - - addtimer(CALLBACK(src, PROC_REF(updateUsrDialog)), 1) - - if(href_list["operation"]) - switch(href_list["operation"]) - if("plusspeed") - speed ++ - if(speed > 10) - speed = 10 - if("minusspeed") - speed -- - if(speed <= 0) - speed = 1 - if("setpath") - var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) - if(newpath && newpath != "") - moving = 0 // stop moving - path = newpath - pathpos = 1 // reset position - filter_path() // renders rpath - - if("togglemoving") - moving = !moving - if(moving) - INVOKE_ASYNC(src, PROC_REF(MagnetMove)) - - - updateUsrDialog() - -/obj/structure/machinery/magnetic_controller/proc/MagnetMove() - if(looping) return - - while(moving && rpath.len >= 1) - - if(inoperable()) - break - - looping = 1 - - // Prepare the radio signal - var/datum/signal/signal = new - signal.transmission_method = 1 // radio transmission - signal.source = src - signal.frequency = frequency - signal.data["code"] = code - - if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list! - pathpos = 1 - - var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive - - if(!(nextmove in list("N","S","E","W","C","R"))) - // N, S, E, W are directional - // C is center - // R is random (in magnetic field's bounds) - qdel(signal) - break // break the loop if the character located is invalid - - signal.data["command"] = nextmove - - - pathpos++ // increase iterator - - // Broadcast the signal - spawn() - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) - - if(speed == 10) - sleep(1) - else - sleep(12-speed) - - looping = 0 - - -/obj/structure/machinery/magnetic_controller/proc/filter_path() - // Generates the rpath variable using the path string, think of this as "string2list" - // Doesn't use params2list() because of the akward way it stacks entities - rpath = list() // clear rpath - var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length - - for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path - - var/nextchar = copytext(path, i, i+1) // find next character - - if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore - rpath += copytext(path, i, i+1) // else, add to list - - // there doesn't HAVE to be separators but it makes paths syntatically visible - - - - - - - - - - - - - - - - - - - - - - - diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index d1e2fecce20f..f1b0081e3a39 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -1,5 +1,4 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - +// Legacy SS13 machinery turned into a prop /obj/structure/machinery/mass_driver name = "mass driver" desc = "Shoots things into space." @@ -9,32 +8,3 @@ use_power = USE_POWER_IDLE idle_power_usage = 2 active_power_usage = 50 - - var/power = 1 - var/code = 1 - var/id = 1 - var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. - - -/obj/structure/machinery/mass_driver/proc/drive(amount) - if(inoperable()) - return - use_power(500) - var/O_limit - var/atom/target = get_edge_target_turf(src, dir) - for(var/atom/movable/O in loc) - if(!O.anchored) - if(O_limit >= 20) - for(var/mob/M in hearers(src, null)) - to_chat(M, SPAN_NOTICE(" The mass driver lets out a screech, it mustn't be able to handle any more items.")) - break - use_power(500) - INVOKE_ASYNC(O, TYPE_PROC_REF(/atom/movable, throw_atom), target, drive_range * power, 100/power) - flick("mass_driver1", src) - return - -/obj/structure/machinery/mass_driver/emp_act(severity) - if(inoperable()) - return - drive() - ..(severity) diff --git a/code/game/machinery/medical_pod/sleeper.dm b/code/game/machinery/medical_pod/sleeper.dm index 35d9a44863d2..bf2abe246c35 100644 --- a/code/game/machinery/medical_pod/sleeper.dm +++ b/code/game/machinery/medical_pod/sleeper.dm @@ -332,14 +332,13 @@ /obj/structure/machinery/medical_pod/sleeper/emp_act(severity) + . = ..() if(filtering) toggle_filter() if(inoperable()) - ..(severity) return if(occupant) go_out() - ..() /obj/structure/machinery/medical_pod/sleeper/proc/toggle_filter() if(!occupant) diff --git a/code/game/machinery/nuclearbomb.dm b/code/game/machinery/nuclearbomb.dm index 743f53e4f03b..28ebbecc7552 100644 --- a/code/game/machinery/nuclearbomb.dm +++ b/code/game/machinery/nuclearbomb.dm @@ -394,7 +394,38 @@ var/bomb_set = FALSE update_icon() safety = TRUE - EvacuationAuthority.trigger_self_destruct(list(z), src, FALSE, NUKE_EXPLOSION_GROUND_FINISHED, FALSE, end_round) + playsound(src, 'sound/machines/Alarm.ogg', 75, 0, 30) + world << pick('sound/theme/nuclear_detonation1.ogg','sound/theme/nuclear_detonation2.ogg') + + var/list/alive_mobs = list() //Everyone who will be destroyed on the zlevel(s). + var/list/dead_mobs = list() //Everyone who only needs to see the cinematic. + for(var/mob/current_mob as anything in GLOB.mob_list) + if(!current_mob?.loc) + continue + if(current_mob.stat == DEAD) + dead_mobs |= current_mob + continue + var/turf/current_turf = get_turf(current_mob) + if(z == current_turf.z) + alive_mobs |= current_mob + shake_camera(current_mob, 110, 4) + + for(var/mob/current_mob in alive_mobs) + if(current_mob && current_mob.loc) + var/turf/current_mob_turf = get_turf(current_mob) + if(z == current_mob_turf.z) + if(istype(current_mob.loc, /obj/structure/closet/secure_closet/freezer/fridge)) + continue + current_mob.death(create_cause_data("nuclear explosion")) + + for(var/mob/current_mob in (alive_mobs + dead_mobs)) + if(current_mob && current_mob.loc) + var/turf/current_mob_turf = get_turf(current_mob) + if(z == current_mob_turf.z) + if(istype(current_mob.loc, /obj/structure/closet/secure_closet/freezer/fridge)) + continue + for(var/obj/item/alien_embryo/embryo in current_mob) + qdel(embryo) sleep(100) cell_explosion(loc, 500, 150, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, create_cause_data(initial(name))) diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index c75360e07568..72e311c6d8ff 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -218,20 +218,14 @@ update_icon() /obj/structure/machinery/recharger/emp_act(severity) + . = ..() if(inoperable() || !anchored) - ..(severity) return -/* - if(istype(charging, /obj/item/weapon/gun/energy)) - var/obj/item/weapon/gun/energy/E = charging - if(E.power_supply) - E.power_supply.emp_act(severity) -*/ + if(istype(charging, /obj/item/weapon/baton)) var/obj/item/weapon/baton/B = charging if(B.bcell) B.bcell.charge = 0 - ..(severity) /obj/structure/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier. src.overlays = 0 diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 644402128852..56b782cd77a4 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -109,13 +109,12 @@ return /obj/structure/machinery/recharge_station/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(occupant) occupant.emp_act(severity) go_out() - ..(severity) /obj/structure/machinery/recharge_station/update_icon() ..() diff --git a/code/game/machinery/sentry_holder.dm b/code/game/machinery/sentry_holder.dm index 61f87251282d..fe676e9103d2 100644 --- a/code/game/machinery/sentry_holder.dm +++ b/code/game/machinery/sentry_holder.dm @@ -10,13 +10,12 @@ idle_power_usage = 1000 power_channel = 1 use_power = USE_POWER_IDLE - machine_processing = 1 var/deployment_cooldown var/turret_path = /obj/structure/machinery/defenses/sentry/premade/deployable // Path of the turret used var/obj/structure/machinery/defenses/sentry/premade/deployable/deployed_turret var/ox = 0 var/oy = 0 - var/ind = FALSE + var/require_red_alert = FALSE /obj/structure/machinery/sentry_holder/Initialize() . = ..() @@ -36,34 +35,38 @@ . += "It's offline." /obj/structure/machinery/sentry_holder/attack_hand(mob/user) - if(deployed_turret) - if(deployment_cooldown > world.time) - to_chat(user, SPAN_WARNING("[src] is busy.")) - return //prevents spamming deployment/undeployment - if(deployed_turret.loc == src) //not deployed - if(stat & NOPOWER) - to_chat(user, SPAN_WARNING("[src] is non-functional.")) - else - to_chat(user, SPAN_NOTICE("You deploy [src].")) - deploy_sentry() - else - to_chat(user, SPAN_NOTICE("You retract [src].")) - undeploy_sentry() - else + if(!deployed_turret) to_chat(user, SPAN_WARNING("[src] is unresponsive.")) + return -/obj/structure/machinery/sentry_holder/process() - if(stat & NOPOWER) - if(deployed_turret) - undeploy_sentry() - ind = FALSE - else - icon_state = "sentry_system_destroyed" - else - update_use_power(USE_POWER_IDLE) - if(!ind) - deploy_sentry() - ind = TRUE + if(deployment_cooldown > world.time) + to_chat(user, SPAN_WARNING("[src] is busy.")) + return + + if(deployed_turret.loc == src) //not deployed + if(stat & NOPOWER) + to_chat(user, SPAN_WARNING("[src] is non-functional.")) + return + + if(require_red_alert && (seclevel2num(get_security_level()) < SEC_LEVEL_RED)) + to_chat(user, SPAN_WARNING("[src] can only be activated in emergencies.")) + return + + to_chat(user, SPAN_NOTICE("You deploy [src].")) + deploy_sentry() + return + + to_chat(user, SPAN_NOTICE("You retract [src].")) + undeploy_sentry() + return + +/obj/structure/machinery/sentry_holder/update_use_power(new_use_power) + ..() + + if(!(stat & NOPOWER)) + return + + undeploy_sentry() /obj/structure/machinery/sentry_holder/proc/deploy_sentry() if(!deployed_turret) @@ -111,3 +114,6 @@ desc = "A box that deploys a sentry turret for protection of the residents in the area." turret_path = /obj/structure/machinery/defenses/sentry/premade/deployable/colony +/obj/structure/machinery/sentry_holder/almayer + turret_path = /obj/structure/machinery/defenses/sentry/premade/deployable/almayer + require_red_alert = TRUE diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index aa51201ae18b..dd45ad597800 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -40,12 +40,11 @@ /obj/structure/machinery/space_heater/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return if(cell) cell.emp_act(severity) - ..(severity) /obj/structure/machinery/space_heater/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/cell)) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 6c6d2bda8b07..79ead6321502 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -78,7 +78,7 @@ return 1 if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) //emergency shuttle timer message1 = "EVAC" - message2 = EvacuationAuthority.get_status_panel_eta() + message2 = SShijack.get_evac_eta() if(message2) if(length(message2) > CHARS_PER_LINE) message2 = "Error" update_display(message1, message2) @@ -163,6 +163,15 @@ if(maptext) maptext = "" +/obj/structure/machinery/status_display/proc/set_sec_level_picture() + switch(security_level) + if(SEC_LEVEL_GREEN) + set_picture("default") + if(SEC_LEVEL_BLUE) + set_picture("bluealert") + if(SEC_LEVEL_RED, SEC_LEVEL_DELTA) + set_picture("redalert") + /obj/structure/machinery/ai_status_display icon = 'icons/obj/structures/machinery/status_display.dmi' icon_state = "frame" @@ -179,11 +188,10 @@ var/emotion = "Neutral" /obj/structure/machinery/ai_status_display/emp_act(severity) + . = ..() if(inoperable()) - ..(severity) return set_picture("ai_bsod") - ..(severity) /obj/structure/machinery/ai_status_display/proc/update() if(mode==0) //Blank diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 5f26e9d5ed25..a9c7c61bc00d 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -449,8 +449,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) id = "CentComm Receiver" network = "tcommsat" autolinkers = list("receiverCent") - freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) - + freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) //Buses @@ -469,7 +468,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/bus/preset_three id = "Bus 3" network = "tcommsat" - freq_listening = list(SEC_FREQ, COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(SEC_FREQ, COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("processor3", "security", "command", "JTAC") /obj/structure/machinery/telecomms/bus/preset_four @@ -485,7 +484,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/bus/preset_cent id = "CentComm Bus" network = "tcommsat" - freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("processorCent", "centcomm") //Processors @@ -550,7 +549,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/server/presets/command id = "Command Server" - freq_listening = list(COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("command") /obj/structure/machinery/telecomms/server/presets/engineering @@ -565,10 +564,9 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers) /obj/structure/machinery/telecomms/server/presets/centcomm id = "CentComm Server" - freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ) + freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ, CBRN_FREQ) autolinkers = list("centcomm") - //Broadcasters //--PRESET LEFT--// diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index 255d70f45870..8b8b12dfd170 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -93,13 +93,13 @@ GLOBAL_LIST_EMPTY_TYPED(telecomms_list, /obj/structure/machinery/telecomms) update_state() /obj/structure/machinery/telecomms/emp_act(severity) + . = ..() if(prob(100/severity)) if(!(stat & EMPED)) stat |= EMPED var/duration = (300 * 10)/severity spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. stat &= ~EMPED - ..() /* The receiver idles and receives messages from subspace-compatible radio equipment; diff --git a/code/game/machinery/vending/cm_vending.dm b/code/game/machinery/vending/cm_vending.dm index 861f5b37ebca..f2eff1c23e56 100644 --- a/code/game/machinery/vending/cm_vending.dm +++ b/code/game/machinery/vending/cm_vending.dm @@ -37,8 +37,14 @@ var/vend_delay = 0 //delaying vending of an item (for drinks machines animation, for example). Make sure to synchronize this with animation duration var/vend_sound //use with caution. Potential spam + /// X Offset to vend to var/vend_x_offset = 0 + /// Y Offset to vend to var/vend_y_offset = 0 + /// Vending direction from adjacent users, if not using vend_x_offset or vend_y_offset + var/vend_dir + /// Direction to adjacent user from which we're allowed to do offset vending + var/list/vend_dir_whitelist var/list/listed_products = list() @@ -125,11 +131,20 @@ GLOBAL_LIST_EMPTY(vending_products) GLOB.vending_products[typepath] = 1 //get which turf the vendor will dispense its products on. -/obj/structure/machinery/cm_vending/proc/get_appropriate_vend_turf() - var/turf/T = loc +/obj/structure/machinery/cm_vending/proc/get_appropriate_vend_turf(mob/living/carbon/human/user) + var/turf/turf = loc if(vend_x_offset != 0 || vend_y_offset != 0) //this check should be more less expensive than using locate to locate your own tile every vending. - T = locate(x + vend_x_offset, y + vend_y_offset, z) - return T + turf = locate(x + vend_x_offset, y + vend_y_offset, z) + return turf + if(vend_dir) + if(vend_dir_whitelist) + var/user_dir = get_dir(loc, user) + if(!(user_dir in vend_dir_whitelist)) + return get_turf(user) + var/turf/relative_turf = get_step(user, vend_dir) + if(relative_turf) + return relative_turf + return turf /obj/structure/machinery/cm_vending/get_examine_text(mob/living/carbon/human/user) . = ..() @@ -245,7 +260,7 @@ GLOBAL_LIST_EMPTY(vending_products) return //Machete holsters handling else if(istype(item_to_stock, /obj/item/storage/large_holster/machete)) - var/obj/item/weapon/claymore/mercsword/machete/mac = locate(/obj/item/weapon/claymore/mercsword/machete) in item_to_stock + var/obj/item/weapon/sword/machete/mac = locate(/obj/item/weapon/sword/machete) in item_to_stock if(!mac) if(user) to_chat(user, SPAN_WARNING("\The [item_to_stock] is empty.")) @@ -428,7 +443,44 @@ GLOBAL_LIST_EMPTY(vending_products) //------------TGUI PROCS--------------- /obj/structure/machinery/cm_vending/ui_data(mob/user) - return vendor_user_ui_data(src, user) + if(vend_flags & VEND_LIMITED_INVENTORY) + return vendor_inventory_ui_data(user) + + . = list() + var/list/ui_listed_products = get_listed_products(user) + // list format + // ( + // name: str + // cost + // item reference + // allowed to buy flag + // item priority (mandatory/recommended/regular) + // ) + + var/list/stock_values = list() + + var/mob/living/carbon/human/marine = user + var/points = 0 + + if(instanced_vendor_points) + points = available_points_to_display + else + if(use_snowflake_points) + points = marine.marine_snowflake_points + else if(use_points) + points = marine.marine_points + + for (var/i in 1 to length(ui_listed_products)) + var/list/myprod = ui_listed_products[i] //we take one list from listed_products + var/prod_available = FALSE + var/p_cost = myprod[2] + var/category = myprod[4] + if(points >= p_cost && (!category || ((category in marine.marine_buyable_categories) && (marine.marine_buyable_categories[category])))) + prod_available = TRUE + stock_values += list(prod_available) + + .["stock_listing"] = stock_values + .["current_m_points"] = points /obj/structure/machinery/cm_vending/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() @@ -515,7 +567,7 @@ GLOBAL_LIST_EMPTY(vending_products) vend_fail() return FALSE - if(!handle_vend(src, itemspec, user)) + if(!handle_vend(itemspec, user)) to_chat(user, SPAN_WARNING("You can't buy things from this category anymore.")) vend_fail() return FALSE @@ -533,7 +585,7 @@ GLOBAL_LIST_EMPTY(vending_products) vend_fail() return TRUE // one left and the player spam click during a lagspike. - vendor_successful_vend(src, itemspec, user) + vendor_successful_vend(itemspec, user) return TRUE add_fingerprint(user) @@ -764,7 +816,7 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/structure/machinery/cm_vending/gear/ui_static_data(mob/user) . = ..(user) .["vendor_type"] = "gear" - .["displayed_categories"] = vendor_user_inventory_list(src, user) + .["displayed_categories"] = vendor_user_inventory_list(user) //------------CLOTHING VENDORS--------------- //clothing vendors automatically put item on user. QoL at it's finest. @@ -781,7 +833,7 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/structure/machinery/cm_vending/clothing/ui_static_data(mob/user) . = ..(user) .["vendor_type"] = "clothing" - .["displayed_categories"] = vendor_user_inventory_list(src, user) + .["displayed_categories"] = vendor_user_inventory_list(user) //------------SORTED VENDORS--------------- //22.06.2019 Modified ex-"marine_selector" system that doesn't use points by Jeser. In theory, should replace all vendors. @@ -840,7 +892,7 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/structure/machinery/cm_vending/sorted/ui_static_data(mob/user) . = ..(user) .["vendor_type"] = "sorted" - .["displayed_categories"] = vendor_user_inventory_list(src, user, null, 4) + .["displayed_categories"] = vendor_user_inventory_list(user, null, 4) /obj/structure/machinery/cm_vending/sorted/MouseDrop_T(atom/movable/A, mob/user) @@ -919,7 +971,7 @@ GLOBAL_LIST_EMPTY(vending_products) /obj/structure/machinery/cm_vending/own_points/ui_static_data(mob/user) . = ..(user) .["vendor_type"] = "gear" - .["displayed_categories"] = vendor_user_inventory_list(src, user) + .["displayed_categories"] = vendor_user_inventory_list(user) //------------ESSENTIALS SETS AND RANDOM GEAR SPAWNER--------------- @@ -1045,7 +1097,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( //---helper procs -/proc/vendor_user_inventory_list(vendor, mob/user, cost_index=2, priority_index=5) +/obj/structure/machinery/cm_vending/proc/vendor_user_inventory_list(mob/user, cost_index=2, priority_index=5) . = list() // default list format // ( @@ -1055,8 +1107,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( // allowed to buy flag // item priority (mandatory/recommended/regular) // ) - var/obj/structure/machinery/cm_vending/vending_machine = vendor - var/list/ui_listed_products = vending_machine.get_listed_products(user) + var/list/ui_listed_products = get_listed_products(user) for (var/i in 1 to length(ui_listed_products)) var/list/myprod = ui_listed_products[i] //we take one list from listed_products @@ -1098,10 +1149,9 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( var/last_category = .[last_index] last_category["items"] += list(display_item) -/proc/vendor_inventory_ui_data(vendor, mob/user) +/obj/structure/machinery/cm_vending/proc/vendor_inventory_ui_data(mob/user) . = list() - var/obj/structure/machinery/cm_vending/vending_machine = vendor - var/list/ui_listed_products = vending_machine.get_listed_products(user) + var/list/ui_listed_products = get_listed_products(user) var/list/ui_categories = list() for (var/i in 1 to length(ui_listed_products)) @@ -1110,92 +1160,50 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( ui_categories += list(p_amount) .["stock_listing"] = ui_categories -/proc/vendor_user_ui_data(obj/structure/machinery/cm_vending/vending_machine, mob/user) - if(vending_machine.vend_flags & VEND_LIMITED_INVENTORY) - return vendor_inventory_ui_data(vending_machine, user) - - . = list() - var/list/ui_listed_products = vending_machine.get_listed_products(user) - // list format - // ( - // name: str - // cost - // item reference - // allowed to buy flag - // item priority (mandatory/recommended/regular) - // ) - - var/list/stock_values = list() - - var/mob/living/carbon/human/marine = user - var/points = 0 - - if(vending_machine.instanced_vendor_points) - points = vending_machine.available_points_to_display - else - if(vending_machine.use_snowflake_points) - points = marine.marine_snowflake_points - else if(vending_machine.use_points) - points = marine.marine_points - - for (var/i in 1 to length(ui_listed_products)) - var/list/myprod = ui_listed_products[i] //we take one list from listed_products - var/prod_available = FALSE - var/p_cost = myprod[2] - var/category = myprod[4] - if(points >= p_cost && (!category || ((category in marine.marine_buyable_categories) && (marine.marine_buyable_categories[category])))) - prod_available = TRUE - stock_values += list(prod_available) - - .["stock_listing"] = stock_values - .["current_m_points"] = points - -/proc/vendor_successful_vend(obj/structure/machinery/cm_vending/vendor, list/itemspec, mob/living/carbon/human/user) - if(vendor.stat & IN_USE) +/obj/structure/machinery/cm_vending/proc/vendor_successful_vend(list/itemspec, mob/living/carbon/human/user) + if(stat & IN_USE) return - vendor.stat |= IN_USE + stat |= IN_USE - var/vend_flags = vendor.vend_flags - var/turf/target_turf = vendor.get_appropriate_vend_turf(user) + var/turf/target_turf = get_appropriate_vend_turf(user) if(LAZYLEN(itemspec)) //making sure it's not empty - if(vendor.vend_delay) - vendor.overlays.Cut() - vendor.icon_state = "[initial(vendor.icon_state)]_vend" - if(vendor.vend_sound) - playsound(vendor.loc, vendor.vend_sound, 25, 1, 2) //heard only near vendor - sleep(vendor.vend_delay) + if(vend_delay) + overlays.Cut() + icon_state = "[initial(icon_state)]_vend" + if(vend_sound) + playsound(loc, vend_sound, 25, 1, 2) //heard only near vendor + sleep(vend_delay) var/prod_type = itemspec[3] if(islist(prod_type)) for(var/each_type in prod_type) - vendor_successful_vend_one(vendor, each_type, user, target_turf, itemspec[4] == MARINE_CAN_BUY_UNIFORM) + vendor_successful_vend_one(each_type, user, target_turf, itemspec[4] == MARINE_CAN_BUY_UNIFORM) else - vendor_successful_vend_one(vendor, prod_type, user, target_turf, itemspec[4] == MARINE_CAN_BUY_UNIFORM) + vendor_successful_vend_one(prod_type, user, target_turf, itemspec[4] == MARINE_CAN_BUY_UNIFORM) if(vend_flags & VEND_LIMITED_INVENTORY) itemspec[2]-- if(vend_flags & VEND_LOAD_AMMO_BOXES) - vendor.update_derived_ammo_and_boxes(itemspec) + update_derived_ammo_and_boxes(itemspec) else to_chat(user, SPAN_WARNING("ERROR: itemspec is missing. Please report this to admins.")) sleep(15) - vendor.stat &= ~IN_USE - vendor.icon_state = initial(vendor.icon_state) - vendor.update_icon() + stat &= ~IN_USE + icon_state = initial(icon_state) + update_icon() -/proc/vendor_successful_vend_one(obj/structure/machinery/cm_vending/vendor, prod_type, mob/living/carbon/human/user, turf/target_turf, insignas_override) +/obj/structure/machinery/cm_vending/proc/vendor_successful_vend_one(prod_type, mob/living/carbon/human/user, turf/target_turf, insignas_override) var/obj/item/new_item - var/vend_flags = vendor.vend_flags if(ispath(prod_type, /obj/item)) if(ispath(prod_type, /obj/item/weapon/gun)) new_item = new prod_type(target_turf, TRUE) else if(prod_type == /obj/item/device/radio/headset/almayer/marine) - prod_type = vendor.headset_type + prod_type = headset_type else if(prod_type == /obj/item/clothing/gloves/marine) - prod_type = vendor.gloves_type + prod_type = gloves_type new_item = new prod_type(target_turf) new_item.add_fingerprint(user) else @@ -1224,13 +1232,13 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( if(vend_flags & VEND_TO_HAND) if(user.client?.prefs && (user.client?.prefs?.toggle_prefs & TOGGLE_VEND_ITEM_TO_HAND)) - if(vendor.Adjacent(user)) + if(Adjacent(user)) user.put_in_any_hand_if_possible(new_item, disable_warning = TRUE) new_item.post_vendor_spawn_hook(user) -/proc/handle_vend(obj/structure/machinery/cm_vending/vendor, list/listed_products, mob/living/carbon/human/vending_human) - if(vendor.vend_flags & VEND_USE_VENDOR_FLAGS) +/obj/structure/machinery/cm_vending/proc/handle_vend(list/listed_products, mob/living/carbon/human/vending_human) + if(vend_flags & VEND_USE_VENDOR_FLAGS) return TRUE var/buying_category = listed_products[4] if(buying_category) @@ -1266,62 +1274,3 @@ GLOBAL_LIST_INIT(cm_vending_gear_corresponding_types_list, list( stat &= ~IN_USE if(destroy) qdel(src) - -//------------HACKING--------------- - -//Hacking code from old vendors, in case someone will actually would like to add complex hacking in future. For now, simple access hacking I believe sufficient. -/* -/obj/structure/machinery/vending/proc/get_wire_descriptions() - return list( - VENDING_WIRE_EXTEND = "Inventory control computer", - VENDING_WIRE_IDSCAN = "ID scanner", - VENDING_WIRE_SHOCK = "Ground safety", - VENDING_WIRE_SHOOT_INV = "Dispenser motor control" - ) - -/obj/structure/machinery/vending/proc/isWireCut(wire) - return !(wires & getWireFlag(wire)) - -/obj/structure/machinery/vending/proc/cut(wire) - wires ^= getWireFlag(wire) - - switch(wire) - if(VENDING_WIRE_EXTEND) - src.extended_inventory = 0 - visible_message(SPAN_NOTICE("A weak yellow light turns off underneath \the [src].")) - if(VENDING_WIRE_SHOCK) - src.seconds_electrified = -1 - visible_message(SPAN_DANGER("Electric arcs shoot off from \the [src]!")) - if (VENDING_WIRE_SHOOT_INV) - if(!src.shoot_inventory) - src.shoot_inventory = TRUE - visible_message(SPAN_WARNING("\The [src] begins whirring noisily.")) - -/obj/structure/machinery/vending/proc/mend(wire) - wires |= getWireFlag(wire) - - switch(wire) - if(VENDING_WIRE_EXTEND) - src.extended_inventory = 1 - visible_message(SPAN_NOTICE("A weak yellow light turns on underneath \the [src].")) - if(VENDING_WIRE_SHOCK) - src.seconds_electrified = 0 - if (VENDING_WIRE_SHOOT_INV) - src.shoot_inventory = FALSE - visible_message(SPAN_NOTICE("\The [src] stops whirring.")) - -/obj/structure/machinery/vending/proc/pulse(wire) - switch(wire) - if(VENDING_WIRE_EXTEND) - src.extended_inventory = !src.extended_inventory - visible_message(SPAN_NOTICE("A weak yellow light turns [extended_inventory ? "on" : "off"] underneath \the [src].")) - if (VENDING_WIRE_SHOCK) - src.seconds_electrified = 30 - visible_message(SPAN_DANGER("Electric arcs shoot off from \the [src]!")) - if (VENDING_WIRE_SHOOT_INV) - src.shoot_inventory = !src.shoot_inventory - if(shoot_inventory) - visible_message(SPAN_WARNING("\The [src] begins whirring noisily.")) - else - visible_message(SPAN_NOTICE("\The [src] stops whirring.")) -*/ diff --git a/code/game/machinery/vending/vending_types.dm b/code/game/machinery/vending/vending_types.dm index a61934324491..a57bbfe7d29f 100644 --- a/code/game/machinery/vending/vending_types.dm +++ b/code/game/machinery/vending/vending_types.dm @@ -411,6 +411,13 @@ /obj/item/device/camera = 5, /obj/item/device/camera_film = 10, /obj/item/notepad = 5, + /obj/item/device/toner = 5, + /obj/item/paper/colonial_grunts = 15, + /obj/item/toy/dice/d20 = 10, + /obj/item/tool/pen = 10, + /obj/item/tool/pen/blue = 10, + /obj/item/tool/pen/red = 10, + /obj/item/tool/pen/fountain = 3, ) contraband = list(/obj/item/toy/sword = 2) @@ -431,5 +438,12 @@ /obj/item/toy/deck = 20, /obj/item/toy/deck/uno = 15, /obj/item/device/camera = 30, + /obj/item/device/toner = 15, + /obj/item/paper/colonial_grunts = 5, + /obj/item/toy/dice/d20 = 1, + /obj/item/tool/pen = 2, + /obj/item/tool/pen/blue = 2, + /obj/item/tool/pen/red = 2, + /obj/item/tool/pen/fountain = 30, ) product_type = VENDOR_PRODUCT_TYPE_RECREATIONAL diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm index 472db608c0f8..b489dbab16a4 100644 --- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm +++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm @@ -104,7 +104,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth, list( list("Surgical Drop Pouch", 0, /obj/item/clothing/accessory/storage/surg_vest/drop_green, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Surgical Drop Pouch (Blue)", 0, /obj/item/clothing/accessory/storage/surg_vest/drop_blue, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Surgical Drop Pouch (Black)", 0, /obj/item/clothing/accessory/storage/surg_vest/drop_black, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), - list("Tool Webbing", 0, /obj/item/clothing/accessory/storage/black_vest/tool_webbing, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Tool Webbing", 0, /obj/item/clothing/accessory/storage/tool_webbing/equipped, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("Drop Pouch", 0, /obj/item/clothing/accessory/storage/droppouch, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("SHOES (CHOOSE 1)", 0, null, null, null), 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 891a2a907b39..d352936b5434 100644 --- a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm +++ b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm @@ -55,8 +55,10 @@ SIGNAL_HANDLER UnregisterSignal(SSdcs, COMSIG_GLOB_VEHICLE_ORDERED) - selected_vehicle = "APC" - available_categories &= ~(VEHICLE_ARMOR_AVAILABLE|VEHICLE_INTEGRAL_AVAILABLE) //APC lacks these, so we need to remove these flags to be able to access spare parts section + if(!selected_vehicle) + selected_vehicle = "APC" // The whole thing seems to be based upon the assumption you unlock tank as an override, defaulting to APC + if(selected_vehicle == "APC") + available_categories &= ~(VEHICLE_ARMOR_AVAILABLE|VEHICLE_INTEGRAL_AVAILABLE) //APC lacks these, so we need to remove these flags to be able to access spare parts section /obj/structure/machinery/cm_vending/gear/vehicle_crew/get_listed_products(mob/user) var/list/display_list = list() diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index 8558019839f7..93680fb93d2c 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -175,22 +175,8 @@ //Special cargo-specific vendor with vending offsets /obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY | VEND_LOAD_AMMO_BOXES //We want to vend to turf not hand, since we are in requisitions - -/obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/get_appropriate_vend_turf(mob/living/carbon/human/H) - var/turf/turf_to_vent_to - if(vend_x_offset != 0 || vend_y_offset != 0) //this will allow to avoid code below that suits only Almayer. - turf_to_vent_to = locate(x + vend_x_offset, y + vend_y_offset, z) - else - turf_to_vent_to = get_turf(get_step(src, NORTH)) - if(H.loc == turf_to_vent_to) - turf_to_vent_to = get_turf(get_step(H.loc, WEST)) - else - turf_to_vent_to = get_turf(get_step(src, SOUTH)) - if(H.loc == turf_to_vent_to) - turf_to_vent_to = get_turf(get_step(H.loc, WEST)) - else - turf_to_vent_to = H.loc - return turf_to_vent_to + vend_dir = WEST + vend_dir_whitelist = list(NORTH, SOUTH) /obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/blend icon_state = "req_guns_wall" @@ -209,6 +195,8 @@ req_access = list(ACCESS_MARINE_CARGO) vendor_theme = VENDOR_THEME_USCM vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY | VEND_TO_HAND | VEND_LOAD_AMMO_BOXES + vend_dir = WEST + vend_dir_whitelist = list(SOUTHWEST, NORTHWEST) /obj/structure/machinery/cm_vending/sorted/cargo_ammo/vend_fail() return @@ -307,22 +295,6 @@ /obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY | VEND_LOAD_AMMO_BOXES //We want to vend to turf not hand, since we are in requisitions -/obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo/get_appropriate_vend_turf(mob/living/carbon/human/H) - var/turf/turf_to_vent_to - if(vend_x_offset != 0 || vend_y_offset != 0) //this will allow to avoid code below that suits only Almayer. - turf_to_vent_to = locate(x + vend_x_offset, y + vend_y_offset, z) - else - turf_to_vent_to = get_turf(get_step(src, NORTHWEST)) - if(H.loc == turf_to_vent_to) - turf_to_vent_to = get_turf(get_step(H.loc, WEST)) - else - turf_to_vent_to = get_turf(get_step(src, SOUTHWEST)) - if(H.loc == turf_to_vent_to) - turf_to_vent_to = get_turf(get_step(H.loc, WEST)) - else - turf_to_vent_to = H.loc - return turf_to_vent_to - //------------ATTACHMENTS VENDOR--------------- /obj/structure/machinery/cm_vending/sorted/attachments @@ -331,6 +303,9 @@ req_access = list(ACCESS_MARINE_CARGO) vendor_theme = VENDOR_THEME_USCM icon_state = "req_attach" + vend_dir = WEST + vend_dir_whitelist = list(SOUTHEAST, NORTHEAST) + vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY //We want to vend to turf not hand, since we are in requisitions /obj/structure/machinery/cm_vending/sorted/attachments/vend_fail() return @@ -379,22 +354,6 @@ list("M44 Magnum Sharpshooter Stock", round(scale * 4.5), /obj/item/attachable/stock/revolver, VENDOR_ITEM_REGULAR) ) -/obj/structure/machinery/cm_vending/sorted/attachments/get_appropriate_vend_turf(mob/living/carbon/human/H) - var/turf/turf_to_vent_to - if(vend_x_offset != 0 || vend_y_offset != 0) //this will allow to avoid code below that suits only Almayer. - turf_to_vent_to = locate(x + vend_x_offset, y + vend_y_offset, z) - else - turf_to_vent_to = get_turf(get_step(src, NORTHEAST)) - if(H.loc == turf_to_vent_to) - turf_to_vent_to = get_turf(get_step(H.loc, WEST)) - else - turf_to_vent_to = get_turf(get_step(src, SOUTHEAST)) - if(H.loc == turf_to_vent_to) - turf_to_vent_to = get_turf(get_step(H.loc, WEST)) - else - turf_to_vent_to = loc - return turf_to_vent_to - /obj/structure/machinery/cm_vending/sorted/attachments/blend icon_state = "req_attach_wall" tiles_with = list( @@ -402,7 +361,6 @@ /obj/structure/machinery/door/airlock, /turf/closed/wall/almayer, ) - vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY //We want to vend to turf not hand, since we are in requisitions //------------UNIFORM VENDOR--------------- @@ -455,6 +413,9 @@ list("MASKS", -1, null, null, null), list("Gas Mask", 20, /obj/item/clothing/mask/gas, VENDOR_ITEM_REGULAR), list("Heat Absorbent Coif", 10, /obj/item/clothing/mask/rebreather/scarf, VENDOR_ITEM_REGULAR), + + list("MISCELLANEOUS", -1, null, null), + list("Bedroll", 30, /obj/item/roller/bedroll, VENDOR_ITEM_REGULAR), ) /obj/structure/machinery/cm_vending/sorted/uniform_supply/ui_state(mob/user) diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm index 65397570511c..f11d1fd48b87 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm @@ -20,8 +20,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_engi, list( list("Plasteel x10", 7, /obj/item/stack/sheet/plasteel/small_stack, null, VENDOR_ITEM_RECOMMENDED), list("Plastic Explosive", 3, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR), list("Breaching Charge", 5, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_RECOMMENDED), - list("Range Finder", 10, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), - list("Laser Designator", 15, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), list("Sandbags x25", 10, /obj/item/stack/sandbags_empty/half, null, VENDOR_ITEM_RECOMMENDED), list("Super-Capacity Power Cell", 10, /obj/item/cell/super, null, VENDOR_ITEM_REGULAR), list("ES-11 Mobile Fuel Canister", 4, /obj/item/tool/weldpack/minitank, null, VENDOR_ITEM_REGULAR), @@ -72,6 +70,10 @@ GLOBAL_LIST_INIT(cm_vending_gear_engi, list( list("Motion Detector", 8, /obj/item/device/motiondetector, null, VENDOR_ITEM_REGULAR), list("Whistle", 3, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR), + list("BINOCULARS", 0, null, null, null), + list("Range Finder", 10, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), + list("Laser Designator", 15, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), + list("HELMET OPTICS", 0, null, null, null), list("Medical Helmet Optic", 12, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm index 81c1941c3423..fc9813f9b172 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm @@ -23,18 +23,21 @@ GLOBAL_LIST_INIT(cm_vending_gear_leader, list( list("Machete Pouch (Full)", 4, /obj/item/storage/pouch/machete/full, null, VENDOR_ITEM_REGULAR), list("USCM Radio Telephone Pack", 5, /obj/item/storage/backpack/marine/satchel/rto, null, VENDOR_ITEM_REGULAR), list("M276 Pattern Combat Toolbelt Rig", 15, /obj/item/storage/belt/gun/utility, null, VENDOR_ITEM_REGULAR), - list("Night Vision Optic", 20, /obj/item/device/helmet_visor/night_vision, null, VENDOR_ITEM_RECOMMENDED), list("UTILITIES", 0, null, null, null), list("Whistle", 3, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR), - list("Range Finder", 3, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), - list("Laser Designator", 5, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), list("Fire Extinguisher (Portable)", 3, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR), list("Motion Detector", 5, /obj/item/device/motiondetector, null, VENDOR_ITEM_REGULAR), list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR), + list("BINOCULARS", 0, null, null, null), + list("Range Finder", 3, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), + list("Laser Designator", 5, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), + list("HELMET OPTICS", 0, null, null, null), list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR), + list("Medical Helmet Optic", 4, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_RECOMMENDED), + list("Night Vision Optic", 20, /obj/item/device/helmet_visor/night_vision, null, VENDOR_ITEM_RECOMMENDED), list("ENGINEERING SUPPLIES", 0, null, null, null), list("Insulated Gloves", 3, /obj/item/clothing/gloves/yellow, null, VENDOR_ITEM_REGULAR), @@ -74,7 +77,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_leader, list( list("Injector (Tricord)", 1, /obj/item/reagent_container/hypospray/autoinjector/tricord, null, VENDOR_ITEM_REGULAR), list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR), - list("Medical Helmet Optic", 4, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_RECOMMENDED), list("Roller Bed", 2, /obj/item/roller, null, VENDOR_ITEM_REGULAR), list("SPECIAL AMMUNITION", 0, null, null, null), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm index 69399cfb1eb5..21485f10c50f 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm @@ -81,12 +81,14 @@ GLOBAL_LIST_INIT(cm_vending_gear_medic, list( list("Welding Goggles", 3, /obj/item/clothing/glasses/welding, null, VENDOR_ITEM_REGULAR), list("UTILITIES", 0, null, null, null), - list("Range Finder", 6, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), - list("Laser Designator", 8, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), list("Fire Extinguisher (Portable)", 3, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR), list("Motion Detector", 8, /obj/item/device/motiondetector, null, VENDOR_ITEM_REGULAR), list("Whistle", 3, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR), + list("BINOCULARS", 0, null, null, null), + list("Range Finder", 6, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), + list("Laser Designator", 8, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), + list("HELMET OPTICS", 0, null, null, null), list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR), @@ -117,6 +119,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_medic, list( GLOBAL_LIST_INIT(cm_vending_clothing_medic, list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), list("Standard Marine Apparel", 0, list(/obj/item/clothing/under/marine/medic, /obj/item/clothing/shoes/marine/knife, /obj/item/clothing/gloves/marine, /obj/item/device/radio/headset/almayer/marine, /obj/item/clothing/head/helmet/marine/medic), MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), + list("Combat Sterile Gloves", 0, /obj/item/clothing/gloves/marine/medical, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY), list("Map", 0, /obj/item/map/current_map, MARINE_CAN_BUY_KIT, VENDOR_ITEM_MANDATORY), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm index 222cd4693cd2..94325b09e9eb 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm @@ -158,6 +158,7 @@ list("USCM Flair", round(scale * 15), /obj/item/prop/helmetgarb/flair_uscm, VENDOR_ITEM_REGULAR), list("Falling Falcons Shoulder Patch", round(scale * 15), /obj/item/clothing/accessory/patch/falcon, VENDOR_ITEM_REGULAR), list("USCM Shoulder Patch", round(scale * 15), /obj/item/clothing/accessory/patch, VENDOR_ITEM_REGULAR), + list("Bedroll", round(scale * 20), /obj/item/roller/bedroll, VENDOR_ITEM_REGULAR), ) //--------------SQUAD SPECIFIC VERSIONS-------------- diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm index 6a569638984b..2e6f78f068f5 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm @@ -92,13 +92,15 @@ GLOBAL_LIST_INIT(cm_vending_clothing_marine, list( list("Sandbags", 20, /obj/item/stack/sandbags_empty/half, null, VENDOR_ITEM_REGULAR), list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR), list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR), - list("Range Finder", 10, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), - list("Laser Designator", 15, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), list("Fire Extinguisher (Portable)", 5, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR), list("Motion Detector", 15, /obj/item/device/motiondetector, null, VENDOR_ITEM_REGULAR), list("Data Detector", 15, /obj/item/device/motiondetector/intel, null, VENDOR_ITEM_REGULAR), list("Whistle", 5, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR), + list("BINOCULARS", 0, null, null, null), + list("Range Finder", 10, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), + list("Laser Designator", 15, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), + list("HELMET OPTICS", 0, null, null, null), list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR), list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm index 41710b477769..b67d11b3f487 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm @@ -29,13 +29,15 @@ GLOBAL_LIST_INIT(cm_vending_gear_smartgun, list( list("Large General Pouch", 6, /obj/item/storage/pouch/general/large, null, VENDOR_ITEM_REGULAR), list("UTILITIES", 0, null, null, null), - list("Range Finder", 10, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), - list("Laser Designator", 15, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), list("Fire Extinguisher (Portable)", 5, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR), list("Whistle", 5, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR), list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR), list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR), + list("BINOCULARS", 0, null, null, null), + list("Range Finder", 10, /obj/item/device/binoculars/range, null, VENDOR_ITEM_REGULAR), + list("Laser Designator", 15, /obj/item/device/binoculars/range/designator, null, VENDOR_ITEM_REGULAR), + list("HELMET OPTICS", 0, null, null, null), list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR), list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm index 7bd45cb46a60..1c86a293772e 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm @@ -43,7 +43,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list( list("Night Vision Optic", 30, /obj/item/device/helmet_visor/night_vision, null, VENDOR_ITEM_RECOMMENDED), list("UTILITIES", 0, null, null, null), - list("Binoculars", 5, /obj/item/device/binoculars, null, VENDOR_ITEM_REGULAR), list("Motion Detector", 15, /obj/item/device/motiondetector, null, VENDOR_ITEM_RECOMMENDED), list("Plastic Explosive", 10, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR), list("Breaching Charge", 10, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_REGULAR), @@ -52,6 +51,9 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list( list("Fire Extinguisher (Portable)", 5, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR), list("Whistle", 5, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR), + list("BINOCULARS", 0, null, null, null), + list("Binoculars", 5, /obj/item/device/binoculars, null, VENDOR_ITEM_REGULAR), + list("HELMET OPTICS", 0, null, null, null), list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR), list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR), diff --git a/code/game/machinery/vending/vendor_types/wo_vendors.dm b/code/game/machinery/vending/vendor_types/wo_vendors.dm index 645640f9dc84..557933754f07 100644 --- a/code/game/machinery/vending/vendor_types/wo_vendors.dm +++ b/code/game/machinery/vending/vendor_types/wo_vendors.dm @@ -110,52 +110,13 @@ ) //------------REQ AMMUNITION VENDOR--------------- -/obj/structure/machinery/cm_vending/sorted/cargo_ammo/wo +/obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo/wo req_access = list(ACCESS_MARINE_CARGO) req_one_access = list() -/obj/structure/machinery/cm_vending/sorted/cargo_ammo/wo/populate_product_list(scale) - listed_products = list( - list("REGULAR AMMUNITION", -1, null, null), - list("Box Of Buckshot Shells", round(scale * 5), /obj/item/ammo_magazine/shotgun/buckshot, VENDOR_ITEM_REGULAR), - list("Box Of Flechette Shells", round(scale * 5), /obj/item/ammo_magazine/shotgun/flechette, VENDOR_ITEM_REGULAR), - list("Box Of Shotgun Slugs", round(scale * 5), /obj/item/ammo_magazine/shotgun/slugs, VENDOR_ITEM_REGULAR), - list("M4RA magazine (10x24mm)", round(scale * 10), /obj/item/ammo_magazine/rifle/m4ra, VENDOR_ITEM_REGULAR), - list("M39 HV Magazine (10x20mm)", round(scale * 10), /obj/item/ammo_magazine/smg/m39, VENDOR_ITEM_REGULAR), - list("M41A MK1 Magazine (10x24mm)", round(scale * 10), /obj/item/ammo_magazine/rifle/m41aMK1, VENDOR_ITEM_REGULAR), - list("M41A MK2 Magazine (10x24mm)", round(scale * 10), /obj/item/ammo_magazine/rifle, VENDOR_ITEM_REGULAR), - list("M44 Speed Loader (.44)", round(scale * 10), /obj/item/ammo_magazine/revolver, VENDOR_ITEM_REGULAR), - list("M4A3 Magazine (9mm)", round(scale * 10), /obj/item/ammo_magazine/pistol, VENDOR_ITEM_REGULAR), - - list("ARMOR-PIERCING AMMUNITION", -1, null, null), - list("88 Mod 4 AP Magazine (9mm)", round(scale * 5), /obj/item/ammo_magazine/pistol/mod88, VENDOR_ITEM_REGULAR), - list("M4RA AP Magazine (10x24mm)", round(scale * 10), /obj/item/ammo_magazine/rifle/m4ra/ap, VENDOR_ITEM_REGULAR), - list("M39 AP Magazine (10x20mm)", round(scale * 5), /obj/item/ammo_magazine/smg/m39/ap, VENDOR_ITEM_REGULAR), - list("M41A MK1 AP Magazine (10x24mm)", round(scale * 10), /obj/item/ammo_magazine/rifle/m41aMK1/ap, VENDOR_ITEM_REGULAR), - list("M41A MK2 AP Magazine (10x24mm)", round(scale * 10), /obj/item/ammo_magazine/rifle/ap, VENDOR_ITEM_REGULAR), - list("M4A3 AP Magazine (9mm)", round(scale * 5), /obj/item/ammo_magazine/pistol/ap, VENDOR_ITEM_REGULAR), - - list("EXTENDED AMMUNITION", -1, null, null), - list("M39 Extended Magazine (10x20mm)", round(scale * 1), /obj/item/ammo_magazine/smg/m39/extended, VENDOR_ITEM_REGULAR), - list("M41A MK2 Extended Magazine (10x24mm)", round(scale * 3), /obj/item/ammo_magazine/rifle/extended, VENDOR_ITEM_REGULAR), - - list("INCENDIARY AMMUNITION", -1, null, null), - list("M4RA Incendiary Magazine (10x24mm)", round(scale * 3), /obj/item/ammo_magazine/rifle/m4ra/incendiary, VENDOR_ITEM_REGULAR), - list("M39 Incendiary Magazine (10x20mm)", round(scale * 2), /obj/item/ammo_magazine/smg/m39/incendiary, VENDOR_ITEM_REGULAR), - list("M41A MK2 Incendiary Magazine (10x24mm)", round(scale * 3), /obj/item/ammo_magazine/rifle/incendiary, VENDOR_ITEM_REGULAR), - list("M4A3 Incendiary Magazine (9mm)", round(scale * 1), /obj/item/ammo_magazine/pistol/incendiary, VENDOR_ITEM_REGULAR), - - list("SPECIAL AMMUNITION", -1, null, null), - list("Incinerator Tank", round(scale * 2.5), /obj/item/ammo_magazine/flamer_tank, VENDOR_ITEM_REGULAR), - list("M41AE2 Ammo Box (10x24mm)", round(scale * 5), /obj/item/ammo_magazine/rifle/lmg, VENDOR_ITEM_REGULAR), - list("M44 Heavy Speed Loader (.44)", round(scale * 2), /obj/item/ammo_magazine/revolver/heavy, VENDOR_ITEM_REGULAR), - list("M44 Marksman Speed Loader (.44)", round(scale * 2), /obj/item/ammo_magazine/revolver/marksman, VENDOR_ITEM_REGULAR), - list("M4A3 HP Magazine (9mm)", round(scale * 5), /obj/item/ammo_magazine/pistol/hp, VENDOR_ITEM_REGULAR), - list("M56 Battery", round(scale * 5), /obj/item/smartgun_battery, VENDOR_ITEM_REGULAR), - list("M56 Smartgun Drum", round(scale * 2), /obj/item/ammo_magazine/smartgun, VENDOR_ITEM_REGULAR), - list("SU-6 Smartpistol Magazine (.45)", round(scale * 6), /obj/item/ammo_magazine/pistol/smart, VENDOR_ITEM_REGULAR), - list("VP78 Magazine", round(scale * 6), /obj/item/ammo_magazine/pistol/vp78, VENDOR_ITEM_REGULAR), - +/obj/structure/machinery/cm_vending/sorted/cargo_ammo/cargo/wo/populate_product_list(scale) + ..() + listed_products += list( list("EXTRA SCOUT AMMUNITION", -1, null, null, null), list("A19 High Velocity Impact Magazine (10x24mm)", round(scale * 1), /obj/item/ammo_magazine/rifle/m4ra/custom/impact, VENDOR_ITEM_REGULAR), list("A19 High Velocity Incendiary Magazine (10x24mm)", round(scale * 1), /obj/item/ammo_magazine/rifle/m4ra/custom/incendiary, VENDOR_ITEM_REGULAR), @@ -181,96 +142,17 @@ list("Large Incinerator Tank", round(scale * 1), /obj/item/ammo_magazine/flamer_tank/large, VENDOR_ITEM_REGULAR), list("Large Incinerator Tank (B) (Green Flame)", round(scale * 1), /obj/item/ammo_magazine/flamer_tank/large/B, VENDOR_ITEM_REGULAR), list("Large Incinerator Tank (X) (Blue Flame)", round(scale * 1), /obj/item/ammo_magazine/flamer_tank/large/X, VENDOR_ITEM_REGULAR), - - list("AMMUNITION BOXES", -1, null, null), - list("Rifle Ammunition Box (10x24mm)", round(scale * 0.9), /obj/item/ammo_box/rounds, VENDOR_ITEM_REGULAR), - list("Rifle Ammunition Box (10x24mm AP)", round(scale * 0.75), /obj/item/ammo_box/rounds/ap, VENDOR_ITEM_REGULAR), - list("SMG Ammunition Box (10x20mm HV)", round(scale * 0.9), /obj/item/ammo_box/rounds/smg, VENDOR_ITEM_REGULAR), - list("SMG Ammunition Box (10x20mm AP)", round(scale * 0.75), /obj/item/ammo_box/rounds/smg/ap, VENDOR_ITEM_REGULAR), ) //------------ARMAMENTS VENDOR--------------- -/obj/structure/machinery/cm_vending/sorted/cargo_guns/wo +/obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/wo req_access = list(ACCESS_MARINE_CARGO) + vend_dir = NORTH + vend_dir_whitelist = list(EAST, WEST) -/obj/structure/machinery/cm_vending/sorted/cargo_guns/wo/populate_product_list(scale) - listed_products = list( - list("PRIMARY FIREARMS", -1, null, null), - list("M4RA Battle Rifle", round(scale * 20), /obj/item/weapon/gun/rifle/m4ra, VENDOR_ITEM_REGULAR), - list("M37A2 Pump Shotgun", round(scale * 10), /obj/item/weapon/gun/shotgun/pump, VENDOR_ITEM_REGULAR), - list("M39 Submachinegun", round(scale * 15), /obj/item/weapon/gun/smg/m39, VENDOR_ITEM_REGULAR), - list("M41A Pulse Rifle MK1", round(scale * 20), /obj/item/weapon/gun/rifle/m41aMK1, VENDOR_ITEM_REGULAR), - list("M41A Pulse Rifle MK2", round(scale * 20), /obj/item/weapon/gun/rifle/m41a, VENDOR_ITEM_REGULAR), - list("MK221 Tactical Shotgun", round(scale * 3), /obj/item/weapon/gun/shotgun/combat, VENDOR_ITEM_REGULAR), - - list("SIDEARMS", -1, null, null), - list("88 Mod 4 Combat Pistol", round(scale * 15), /obj/item/weapon/gun/pistol/mod88, VENDOR_ITEM_REGULAR), - list("M44 Combat Revolver", round(scale * 10), /obj/item/weapon/gun/revolver/m44, VENDOR_ITEM_REGULAR), - list("M4A3 Service Pistol", round(scale * 20), /obj/item/weapon/gun/pistol/m4a3, VENDOR_ITEM_REGULAR), - list("SU-6 Smartpistol", round(scale * 2), /obj/item/weapon/gun/pistol/smart, VENDOR_ITEM_REGULAR), - list("M82F Flare Gun", round(scale * 5), /obj/item/weapon/gun/flare, VENDOR_ITEM_REGULAR), - - list("RESTRICTED FIREARMS", -1, null, null), - list("VP78 Pistol", round(scale * 4), /obj/item/storage/box/guncase/vp78, VENDOR_ITEM_REGULAR), - list("SU-6 Smart Pistol", round(scale * 3), /obj/item/storage/box/guncase/smartpistol, VENDOR_ITEM_REGULAR), - list("M41AE2 Heavy Pulse Rifle", round(scale * 2), /obj/item/storage/box/guncase/lmg, VENDOR_ITEM_REGULAR), - list("M56D Heavy Machine Gun", round(scale * 2), /obj/item/storage/box/guncase/m56d, VENDOR_ITEM_REGULAR), - list("M2C Heavy Machine Gun", round(scale * 2), /obj/item/storage/box/guncase/m2c, VENDOR_ITEM_REGULAR), - list("M240 Incinerator Unit", round(scale * 2), /obj/item/storage/box/guncase/flamer, VENDOR_ITEM_REGULAR), - - list("EXPLOSIVES", -1, null, null), - list("M15 Fragmentation Grenade", round(scale * 2), /obj/item/explosive/grenade/high_explosive/m15, VENDOR_ITEM_REGULAR), - list("M20 Claymore Anti-Personnel Mine", round(scale * 5), /obj/item/explosive/mine, VENDOR_ITEM_REGULAR), - list("M40 HEDP Grenade Box", round(scale * 1), /obj/item/storage/box/nade_box, VENDOR_ITEM_REGULAR), - list("M40 HIDP Incendiary Grenade", round(scale * 3), /obj/item/explosive/grenade/incendiary, VENDOR_ITEM_REGULAR), - list("M40 HSDP Smoke Grenade", round(scale * 5), /obj/item/explosive/grenade/smokebomb, VENDOR_ITEM_REGULAR), - - list("BACKPACKS", -1, null, null), - list("Lightweight IMP Backpack", round(scale * 15), /obj/item/storage/backpack/marine, VENDOR_ITEM_REGULAR), - list("Shotgun Scabbard", round(scale * 10), /obj/item/storage/large_holster/m37, VENDOR_ITEM_REGULAR), - list("USCM Pyrotechnician G4-1 Fueltank", round(scale * 2), /obj/item/storage/backpack/marine/engineerpack/flamethrower/kit, VENDOR_ITEM_REGULAR), - list("USCM Technician Welderpack", round(scale * 2), /obj/item/storage/backpack/marine/engineerpack, VENDOR_ITEM_REGULAR), - - list("BELTS", -1, null, null), - list("G8-A General Utility Pouch", round(scale * 3), /obj/item/storage/backpack/general_belt, VENDOR_ITEM_REGULAR), - list("M276 Pattern Ammo Load Rig", round(scale * 15), /obj/item/storage/belt/marine, VENDOR_ITEM_REGULAR), - list("M276 Pattern General Pistol Holster Rig", round(scale * 10), /obj/item/storage/belt/gun/m4a3, VENDOR_ITEM_REGULAR), - list("M276 Pattern M39 Holster Rig", round(scale * 5), /obj/item/storage/belt/gun/m39, VENDOR_ITEM_REGULAR), - list("M276 Pattern M44 Holster Rig", round(scale * 5), /obj/item/storage/belt/gun/m44, VENDOR_ITEM_REGULAR), - list("M276 M82F Holster Rig", round(scale * 2), /obj/item/storage/belt/gun/flaregun, VENDOR_ITEM_REGULAR), - list("M276 Pattern Shotgun Shell Loading Rig", round(scale * 10), /obj/item/storage/belt/shotgun, VENDOR_ITEM_REGULAR), - - list("WEBBINGS", -1, null, null), - list("Black Webbing Vest", round(scale * 5), /obj/item/clothing/accessory/storage/black_vest, VENDOR_ITEM_REGULAR), - list("Brown Webbing Vest", round(scale * 5), /obj/item/clothing/accessory/storage/black_vest/brown_vest, VENDOR_ITEM_REGULAR), - list("Shoulder Holster", round(scale * 5), /obj/item/clothing/accessory/storage/holster, VENDOR_ITEM_REGULAR), - list("Webbing", round(scale * 5), /obj/item/clothing/accessory/storage/webbing, VENDOR_ITEM_REGULAR), - list("Knife Webbing", round(scale * 3), /obj/item/clothing/accessory/storage/knifeharness, VENDOR_ITEM_REGULAR), - list("Drop Pouch", round(scale * 5), /obj/item/clothing/accessory/storage/droppouch, VENDOR_ITEM_REGULAR), - - list("POUCHES", -1, null, null), - list("Construction Pouch", round(scale * 2), /obj/item/storage/pouch/construction, VENDOR_ITEM_REGULAR), - list("Explosive Pouch", round(scale * 2), /obj/item/storage/pouch/explosive, VENDOR_ITEM_REGULAR), - list("First-Aid Pouch (Full)", round(scale * 5), /obj/item/storage/pouch/firstaid/full, VENDOR_ITEM_REGULAR), - list("First Responder Pouch", round(scale * 2), /obj/item/storage/pouch/first_responder, VENDOR_ITEM_REGULAR), - list("Flare Pouch (Full)", round(scale * 5), /obj/item/storage/pouch/flare/full, VENDOR_ITEM_REGULAR), - list("Fuel Tank Strap Pouch", round(scale * 4), /obj/item/storage/pouch/flamertank, VENDOR_ITEM_REGULAR), - list("Large Pistol Magazine Pouch", round(scale * 5), /obj/item/storage/pouch/magazine/pistol/large, VENDOR_ITEM_REGULAR), - list("Magazine Pouch", round(scale * 5), /obj/item/storage/pouch/magazine, VENDOR_ITEM_REGULAR), - list("Medical Pouch", round(scale * 2), /obj/item/storage/pouch/medical, VENDOR_ITEM_REGULAR), - list("Medium General Pouch", round(scale * 2), /obj/item/storage/pouch/general/medium, VENDOR_ITEM_REGULAR), - list("Medkit Pouch", round(scale * 2), /obj/item/storage/pouch/medkit, VENDOR_ITEM_REGULAR), - list("Sidearm Pouch", round(scale * 15), /obj/item/storage/pouch/pistol, VENDOR_ITEM_REGULAR), - list("Syringe Pouch", round(scale * 2), /obj/item/storage/pouch/syringe, VENDOR_ITEM_REGULAR), - list("Tools Pouch (Full)", round(scale * 2), /obj/item/storage/pouch/tools/full, VENDOR_ITEM_REGULAR), - - list("MISCELLANEOUS", -1, null, null), - list("Combat Flashlight", round(scale * 5), /obj/item/device/flashlight/combat, VENDOR_ITEM_REGULAR), - list("Entrenching Tool (ET)", round(scale * 4), /obj/item/tool/shovel/etool, VENDOR_ITEM_REGULAR), - list("Gas Mask", round(scale * 10), /obj/item/clothing/mask/gas, VENDOR_ITEM_REGULAR), - list("M89-S Signal Flare Pack", round(scale * 2), /obj/item/storage/box/m94/signal, VENDOR_ITEM_REGULAR), - list("M94 Marking Flare Pack", round(scale * 10), /obj/item/storage/box/m94, VENDOR_ITEM_REGULAR), - list("Machete Scabbard (Full)", round(scale * 20), /obj/item/storage/large_holster/machete/full, VENDOR_ITEM_REGULAR), - list("MB-6 Folding Barricades (x3)", round(scale * 1), /obj/item/stack/folding_barricade/three, VENDOR_ITEM_REGULAR) - ) +//---- ATTACHIES +/obj/structure/machinery/cm_vending/sorted/attachments/wo + req_access = list(ACCESS_MARINE_CARGO) + vend_dir = NORTH + vend_dir_whitelist = list(SOUTHWEST, SOUTHEAST) diff --git a/code/game/objects/effects/decals/posters.dm b/code/game/objects/effects/decals/posters.dm index c688c4e6fb67..7a8054efce1a 100644 --- a/code/game/objects/effects/decals/posters.dm +++ b/code/game/objects/effects/decals/posters.dm @@ -184,6 +184,12 @@ serial_number = pick(27,28,30,31) .=..() +/obj/structure/sign/poster/io + icon_state = "poster14" + +/obj/structure/sign/poster/io/Initialize() + serial_number = 14 + . = ..() //////////////// //Hero Posters// //////////////// diff --git a/code/game/objects/effects/decals/warning_stripes.dm b/code/game/objects/effects/decals/warning_stripes.dm index ce0802d72d8e..20c96c2ac737 100644 --- a/code/game/objects/effects/decals/warning_stripes.dm +++ b/code/game/objects/effects/decals/warning_stripes.dm @@ -91,6 +91,20 @@ /obj/effect/decal/sand_overlay/sand2/corner2 icon_state = "sand2_c" +/obj/effect/decal/grass_overlay + name = "grass edge" + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + unacidable = TRUE + icon = 'icons/turf/floors/auto_strata_grass.dmi' + layer = TURF_LAYER + +/obj/effect/decal/grass_overlay/grass1 + icon_state = "grass_outercorner" + +/obj/effect/decal/grass_overlay/grass1/inner + name = "grass edge" + icon_state = "grass_innercorner" + /obj/effect/decal/siding name = "siding" icon = 'icons/turf/floors/floors.dmi' diff --git a/code/game/objects/effects/effect_system/smoke.dm b/code/game/objects/effects/effect_system/smoke.dm index 78aa01b5dacb..b80f53b14d2e 100644 --- a/code/game/objects/effects/effect_system/smoke.dm +++ b/code/game/objects/effects/effect_system/smoke.dm @@ -31,13 +31,13 @@ amount = oldamount - 1 cause_data = new_cause_data time_to_live += rand(-1,1) - active_smoke_effects += src + START_PROCESSING(SSeffects, src) /obj/effect/particle_effect/smoke/Destroy() . = ..() if(opacity) set_opacity(0) - active_smoke_effects -= src + STOP_PROCESSING(SSeffects, src) cause_data = null /obj/effect/particle_effect/smoke/initialize_pass_flags(datum/pass_flags_container/PF) diff --git a/code/game/objects/effects/landmarks/corpsespawner.dm b/code/game/objects/effects/landmarks/corpsespawner.dm index fe338bceabfe..27a717f58ba8 100644 --- a/code/game/objects/effects/landmarks/corpsespawner.dm +++ b/code/game/objects/effects/landmarks/corpsespawner.dm @@ -135,7 +135,7 @@ /obj/effect/landmark/corpsespawner/wy/manager/burst name = "Burst Corporate Supervisor" - equip_path = /datum/equipment_preset/corpse/ua_riot/burst + equip_path = /datum/equipment_preset/corpse/wy/manager/burst ///////////Faction Specific Corpses////////////////////// diff --git a/code/game/objects/effects/landmarks/survivor_spawner.dm b/code/game/objects/effects/landmarks/survivor_spawner.dm index fe4254982d57..a53fead0d3bf 100644 --- a/code/game/objects/effects/landmarks/survivor_spawner.dm +++ b/code/game/objects/effects/landmarks/survivor_spawner.dm @@ -8,6 +8,8 @@ var/roundstart_damage_min = 0 var/roundstart_damage_max = 0 var/roundstart_damage_times = 1 + /// Whether or not the spawner is for an inherently hostile survivor subtype. + var/hostile = FALSE var/spawn_priority = LOWEST_SPAWN_PRIORITY @@ -27,6 +29,7 @@ return TRUE /obj/effect/landmark/survivor_spawner/lv624_crashed_clf + hostile = TRUE equipment = /datum/equipment_preset/survivor/clf synth_equipment = /datum/equipment_preset/clf/synth intro_text = list("

You are a survivor of a crash landing!

",\ @@ -40,6 +43,7 @@ spawn_priority = SPAWN_PRIORITY_HIGH /obj/effect/landmark/survivor_spawner/lv624_crashed_clf_engineer + hostile = TRUE equipment = /datum/equipment_preset/clf/engineer synth_equipment = /datum/equipment_preset/clf/synth intro_text = list("

You are a survivor of a crash landing!

",\ @@ -53,6 +57,7 @@ spawn_priority = SPAWN_PRIORITY_VERY_HIGH /obj/effect/landmark/survivor_spawner/lv624_crashed_clf_medic + hostile = TRUE equipment = /datum/equipment_preset/clf/medic synth_equipment = /datum/equipment_preset/clf/synth intro_text = list("

You are a survivor of a crash landing!

",\ diff --git a/code/game/objects/effects/spawners/random.dm b/code/game/objects/effects/spawners/random.dm index a70fb5588f84..d302e7794f8b 100644 --- a/code/game/objects/effects/spawners/random.dm +++ b/code/game/objects/effects/spawners/random.dm @@ -351,8 +351,7 @@ /obj/effect/spawner/random/gun/proc/spawn_weapon_on_floor(gunpath, ammopath, ammo_amount = 1) - var/atom/spawnloc = src - spawnloc = get_turf(spawnloc) + var/turf/spawnloc = get_turf(src) var/obj/gun var/obj/ammo @@ -360,20 +359,20 @@ gun = new gunpath(spawnloc) if(scatter) var/direction = pick(alldirs) - var/turf/T = get_step(gun, direction) - if(!T || T.density) + var/turf/turf = get_step(gun, direction) + if(!turf || turf.density) return - gun.loc = T + gun.forceMove(turf) if(ammopath) for(var/i in 0 to ammo_amount-1) ammo = new ammopath(spawnloc) if(scatter) for(i=0, i 1) to_chat(user, SPAN_BOLDNOTICE("The display on \the [src] lights up: [dist]-[direction]")) else diff --git a/code/game/objects/items/devices/pinpointer.dm b/code/game/objects/items/devices/pinpointer.dm index 7ec3118ef96b..8a624d616d5b 100644 --- a/code/game/objects/items/devices/pinpointer.dm +++ b/code/game/objects/items/devices/pinpointer.dm @@ -31,7 +31,7 @@ if(!the_disk) icon_state = "pinonnull" return - setDir(get_dir(src,the_disk)) + setDir(Get_Compass_Dir(src,the_disk)) switch(get_dist(src,the_disk)) if(0) icon_state = "pinondirect" @@ -80,7 +80,7 @@ if(!location) icon_state = "pinonnull" return - setDir(get_dir(src,location)) + setDir(Get_Compass_Dir(src,location)) switch(get_dist(src,location)) if(0) icon_state = "pinondirect" @@ -99,7 +99,7 @@ if(!target) icon_state = "pinonnull" return - setDir(get_dir(src,target)) + setDir(Get_Compass_Dir(src,target)) switch(get_dist(src,target)) if(0) icon_state = "pinondirect" diff --git a/code/game/objects/items/devices/portable_vendor.dm b/code/game/objects/items/devices/portable_vendor.dm index 65e2128a02c0..29e1d06018ae 100644 --- a/code/game/objects/items/devices/portable_vendor.dm +++ b/code/game/objects/items/devices/portable_vendor.dm @@ -210,6 +210,7 @@ s.start() /obj/item/device/portable_vendor/emp_act(severity) + . = ..() if (broken) return if (prob(40*severity)) diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 21aa96e971a1..fb8640eeaa71 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -849,6 +849,14 @@ "Corporate Liaison" = TRACKER_CL ) +/obj/item/device/radio/headset/distress/cbrn + name = "\improper CBRN headset" + desc = "A headset given to CBRN marines. Channels are as follows: :g - public, :v - marine command, :a - alpha squad, :b - bravo squad, :c - charlie squad, :d - delta squad, :n - engineering, :m - medbay, :u - requisitions, :j - JTAC, :t - intel" + frequency = CBRN_FREQ + initial_keys = list(/obj/item/device/encryptionkey/public, /obj/item/device/encryptionkey/mcom) + ignore_z = TRUE + has_hud = TRUE + /obj/item/device/radio/headset/distress/pmc/hvh desc = "A special headset used by corporate personnel. Channels are as follows: :o - colony." initial_keys = list(/obj/item/device/encryptionkey/colony, /obj/item/device/encryptionkey/WY) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 2092ffa108c6..c503edc8f94f 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -425,11 +425,11 @@ else return /obj/item/device/radio/emp_act(severity) + . = ..() broadcasting = FALSE listening = FALSE for (var/ch_name in channels) channels[ch_name] = 0 - ..() /////////////////////////////// //////////Borg Radios////////// diff --git a/code/game/objects/items/explosives/mine.dm b/code/game/objects/items/explosives/mine.dm index 742a5f314c4a..57dd23bf4e96 100644 --- a/code/game/objects/items/explosives/mine.dm +++ b/code/game/objects/items/explosives/mine.dm @@ -42,6 +42,7 @@ prime() //We don't care about how strong the explosion was. /obj/item/explosive/mine/emp_act() + . = ..() prime() //Same here. Don't care about the effect strength. diff --git a/code/game/objects/items/explosives/plastic.dm b/code/game/objects/items/explosives/plastic.dm index 830df9659070..ac0a2263cd5c 100644 --- a/code/game/objects/items/explosives/plastic.dm +++ b/code/game/objects/items/explosives/plastic.dm @@ -26,7 +26,7 @@ /obj/item/explosive/plastic/Destroy() disarm() - . = ..() + return ..() /obj/item/explosive/plastic/explosion_throw(severity, direction, scatter_multiplier) if(active) @@ -156,7 +156,9 @@ plant_target.overlays -= overlay qdel(overlay) plant_target.contents -= src - forceMove(get_turf(plant_target)) + var/turf/plant_turf = get_turf(plant_target) + if(plant_turf) + forceMove(plant_turf) plant_target = null if(customizable) if(active) //deactivate diff --git a/code/game/objects/items/fulton.dm b/code/game/objects/items/fulton.dm index 98987d1cd2b3..6a0e0f933144 100644 --- a/code/game/objects/items/fulton.dm +++ b/code/game/objects/items/fulton.dm @@ -90,7 +90,7 @@ var/global/list/deployed_fultons = list() var/mob/living/carbon/human/H = target_atom if(isyautja(H) && H.stat == DEAD) can_attach = TRUE - else if((H.stat != DEAD || H.mind && H.check_tod() && H.is_revivable())) + else if((H.stat != DEAD || H.check_tod() && H.is_revivable())) to_chat(user, SPAN_WARNING("You can't attach [src] to [target_atom], they still have a chance!")) return else diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 71fb02cf3f07..2137b41d86bf 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -29,20 +29,6 @@ if(!C.handcuffed) place_handcuffs(C, user) -/obj/item/handcuffs/obj/structure/MouseDrop(mob/living/carbon/human/H) - var/mob/living/carbon/human/user = usr - if (!istype(user)) - return - if (user.stat || get_dist(user, src) > 1 || get_dist(user, H) > 1 || H.lying) - return - if (!istype(H)) - return - - if(!do_after(user, cuff_delay, INTERRUPT_ALL, BUSY_ICON_HOSTILE, H, INTERRUPT_MOVED, BUSY_ICON_GENERIC)) - return - - // TODO: apply handcuffs - /obj/item/handcuffs/get_mob_overlay(mob/user_mob, slot) var/image/ret = ..() diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index d39b7e675452..e7ebe0391fae 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -82,6 +82,7 @@ Implant Specifics:
"} return dat /obj/item/implant/tracking/emp_act(severity) + . = ..() if (malfunction) //no, dawg, you can't malfunction while you are malfunctioning return malfunction = MALFUNCTION_TEMPORARY @@ -216,6 +217,7 @@ Implant Specifics:
"} return 1 /obj/item/implant/explosive/emp_act(severity) + . = ..() if (malfunction) return malfunction = MALFUNCTION_TEMPORARY @@ -307,6 +309,7 @@ the implant may become unstable and either pre-maturely inject the subject or si return /obj/item/implant/chem/emp_act(severity) + . = ..() if (malfunction) return malfunction = MALFUNCTION_TEMPORARY @@ -432,6 +435,7 @@ the implant may become unstable and either pre-maturely inject the subject or si STOP_PROCESSING(SSobj, src) /obj/item/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this + . = ..() if (malfunction) //so I'm just going to add a meltdown chance here return malfunction = MALFUNCTION_TEMPORARY diff --git a/code/game/objects/items/implants/implantneurostim.dm b/code/game/objects/items/implants/implantneurostim.dm index a46cc31a2ca4..544cf70147e2 100644 --- a/code/game/objects/items/implants/implantneurostim.dm +++ b/code/game/objects/items/implants/implantneurostim.dm @@ -105,6 +105,7 @@ /obj/item/implant/neurostim/emp_act(severity) + . = ..() if (malfunction) return if (prob(80)) diff --git a/code/game/objects/items/misc.dm b/code/game/objects/items/misc.dm index abd8404d6e25..50c5cd75551b 100644 --- a/code/game/objects/items/misc.dm +++ b/code/game/objects/items/misc.dm @@ -141,13 +141,13 @@ . = ..() /obj/item/weapon/pole/fancy_cane/this_is_a_knife/machete - stored_item = new /obj/item/weapon/claymore/mercsword/machete + stored_item = new /obj/item/weapon/sword/machete /obj/item/weapon/pole/fancy_cane/this_is_a_knife/ceremonial_sword - stored_item = new /obj/item/weapon/claymore/mercsword/ceremonial + stored_item = new /obj/item/weapon/sword/ceremonial /obj/item/weapon/pole/fancy_cane/this_is_a_knife/katana - stored_item = new /obj/item/weapon/katana + stored_item = new /obj/item/weapon/sword/katana // IN SHOTGUNS.DM!! diff --git a/code/game/objects/items/props/helmetgarb.dm b/code/game/objects/items/props/helmetgarb.dm index 661c8d422316..7860236d5d51 100644 --- a/code/game/objects/items/props/helmetgarb.dm +++ b/code/game/objects/items/props/helmetgarb.dm @@ -37,6 +37,11 @@ desc = "The more you fire these, the more you're reminded that a fragmentation grenade is probably more effective at fulfilling the same purpose. Say, aren't these supposed to eject from your gun?" icon_state = "spent_flech" +/obj/item/prop/helmetgarb/cartridge + name = "cartridge" + desc = "This is the bullet from a Type 71 Pulse Rifle. It is deformed from impact against an armored surface. It's been reduced to a lucky keepsake now." + icon_state = "cartridge" + /obj/item/prop/helmetgarb/prescription_bottle name = "prescription medication" desc = "Anti-anxiety meds? Amphetamines? The cure for Sudden Sleep Disorder? The label can't be read, leaving the now absent contents forever a mystery. The cap is screwed on tighter than any ID lock." @@ -94,10 +99,8 @@ var/nvg_maxhealth = 125 var/nvg_health = 125 - var/nvg_maxcharge = 2500 - var/nvg_charge = 2500 - var/nvg_drain = 8 // has a 5 minute duration but byond may give it a couple of irl time due to lag - var/infinite_charge = FALSE + /// How much charge the cell should have at most. -1 is infinite + var/cell_max_charge = 2500 var/activated = FALSE var/nightvision = FALSE @@ -112,6 +115,13 @@ var/mob/living/attached_mob var/lighting_alpha = 100 +/obj/item/prop/helmetgarb/helmet_nvg/Initialize(mapload, ...) + . = ..() + if(shape != NVG_SHAPE_COSMETIC) + AddComponent(/datum/component/cell, cell_max_charge, TRUE, charge_drain = 8) + RegisterSignal(src, COMSIG_CELL_TRY_RECHARGING, PROC_REF(cell_try_recharge)) + RegisterSignal(src, COMSIG_CELL_OUT_OF_CHARGE, PROC_REF(on_power_out)) + /obj/item/prop/helmetgarb/helmet_nvg/on_enter_storage(obj/item/storage/internal/S) ..() @@ -134,42 +144,30 @@ /obj/item/prop/helmetgarb/helmet_nvg/attackby(obj/item/A as obj, mob/user as mob) - if(istype(A,/obj/item/cell)) - recharge(A, user) - if(HAS_TRAIT(A, TRAIT_TOOL_SCREWDRIVER)) repair(user) else ..() -/obj/item/prop/helmetgarb/helmet_nvg/proc/recharge(obj/item/cell/C, mob/user as mob) +/obj/item/prop/helmetgarb/helmet_nvg/proc/cell_try_recharge(datum/source, mob/living/user) + SIGNAL_HANDLER + if(user.action_busy) - return + return COMPONENT_CELL_NO_RECHARGE + if(src != user.get_inactive_hand()) - to_chat(user, SPAN_WARNING("You need to hold \the [src] in hand in order to recharge them.")) - return + to_chat(user, SPAN_WARNING("You need to hold [src] in hand in order to recharge them.")) + return COMPONENT_CELL_NO_RECHARGE + if(shape == NVG_SHAPE_COSMETIC) - to_chat(user, SPAN_WARNING("There is no connector for the power cell inside \the [src].")) - return + to_chat(user, SPAN_WARNING("There is no connector for the power cell inside [src].")) + return COMPONENT_CELL_NO_RECHARGE + if(shape == NVG_SHAPE_BROKEN) - to_chat(user, SPAN_WARNING("You need to repair \the [src] first.")) - return - if(nvg_charge == nvg_maxcharge) - to_chat(user, SPAN_WARNING("\The [src] are already fully charged.")) - return + to_chat(user, SPAN_WARNING("You need to repair [src] first.")) + return COMPONENT_CELL_NO_RECHARGE - while(nvg_charge < nvg_maxcharge) - if(C.charge <= 0) - to_chat(user, SPAN_WARNING("\The [C] is completely dry.")) - break - if(!do_after(user, 1 SECONDS, (INTERRUPT_ALL & (~INTERRUPT_MOVED)), BUSY_ICON_BUILD, C, INTERRUPT_DIFF_LOC)) - to_chat(user, SPAN_WARNING("You were interrupted.")) - break - var/to_transfer = min(400, C.charge, (nvg_maxcharge - nvg_charge)) - if(C.use(to_transfer)) - nvg_charge += to_transfer - to_chat(user, "You transfer some power between \the [C] and \the [src]. The gauge now reads: [round(100.0*nvg_charge/nvg_maxcharge) ]%.") /obj/item/prop/helmetgarb/helmet_nvg/proc/repair(mob/user as mob) if(user.action_busy) @@ -197,7 +195,6 @@ to_chat(user, "You successfully patch \the [src].") nvg_maxhealth = 65 nvg_health = 65 - nvg_drain = initial(nvg_drain) * 2 return else if(nvg_health == nvg_maxhealth) @@ -239,9 +236,6 @@ else if(nvg_health_procent >= 0) . += "They are falling apart." - if (get_dist(user, src) <= 1 && (shape == NVG_SHAPE_FINE || shape == NVG_SHAPE_PATCHED)) - . += "A small gauge in the corner reads: Power: [round(100.0*nvg_charge/nvg_maxcharge) ]%." - /obj/item/prop/helmetgarb/helmet_nvg/on_exit_storage(obj/item/storage/S) remove_attached_item() return ..() @@ -291,7 +285,7 @@ if(attached_mob != user && slot == WEAR_HEAD) set_attached_mob(user) - if(slot == WEAR_HEAD && !nightvision && activated && nvg_charge > 0 && shape > NVG_SHAPE_BROKEN) + if(slot == WEAR_HEAD && !nightvision && activated && !SEND_SIGNAL(src, COMSIG_CELL_CHECK_CHARGE) && shape > NVG_SHAPE_BROKEN) enable_nvg(user) else remove_nvg() @@ -314,7 +308,7 @@ attached_item.update_icon() activation.update_button_icon() - START_PROCESSING(SSobj, src) + SEND_SIGNAL(src, COMSIG_CELL_START_TICK_DRAIN) /obj/item/prop/helmetgarb/helmet_nvg/proc/update_sight(mob/M) @@ -348,20 +342,15 @@ attached_mob.update_sight() - STOP_PROCESSING(SSobj, src) + SEND_SIGNAL(src, COMSIG_CELL_STOP_TICK_DRAIN) /obj/item/prop/helmetgarb/helmet_nvg/process(delta_time) - if(nvg_charge > 0 && !infinite_charge) - nvg_charge = max(0, nvg_charge - nvg_drain * delta_time) - if(!attached_mob) return PROCESS_KILL - if(!activated || !attached_item || nvg_charge <= 0 || attached_mob.is_dead()) - if(activated && !attached_mob.is_dead()) - to_chat(attached_mob, SPAN_WARNING("\The [src] emit a low power warning and immediately shut down!")) - remove_nvg() + if(!activated || !attached_item || attached_mob.is_dead()) + on_power_out() return if(!attached_item.has_garb_overlay()) @@ -370,6 +359,13 @@ return +/obj/item/prop/helmetgarb/helmet_nvg/proc/on_power_out(datum/source) + SIGNAL_HANDLER + + if(activated && !attached_mob.is_dead()) + to_chat(attached_mob, SPAN_WARNING("[src] emit a low power warning and immediately shut down!")) + remove_nvg() + /obj/item/prop/helmetgarb/helmet_nvg/ui_action_click(mob/owner, obj/item/holder) toggle_nods(owner) @@ -405,7 +401,7 @@ if(activated) to_chat(user, SPAN_NOTICE("You flip the goggles down.")) icon_state = active_icon_state - if(nvg_charge > 0 && user.head == attached_item && shape > NVG_SHAPE_BROKEN) + if(!SEND_SIGNAL(src, COMSIG_CELL_CHECK_CHARGE) && user.head == attached_item && shape > NVG_SHAPE_BROKEN) enable_nvg(user) else icon_state = active_icon_state @@ -457,7 +453,7 @@ /obj/item/prop/helmetgarb/helmet_nvg/marsoc //for Marine Raiders name = "\improper Tactical M3 night vision goggles" desc = "With an integrated self-recharging battery, nothing can stop you. Put them on your helmet and press the button and it's go-time." - infinite_charge = TRUE + cell_max_charge = -1 #undef NVG_SHAPE_COSMETIC #undef NVG_SHAPE_BROKEN @@ -506,8 +502,8 @@ icon_state = "trimmed_wire" /obj/item/prop/helmetgarb/bullet_pipe - name = "10x99mm XM42B casing pipe" - desc = "The XM42B was an experimental weapons platform briefly fielded by the USCM and Wey-Yu PMC teams. It was manufactured by ARMAT systems at the Atlas weapons facility. Unfortunately the project had its funding pulled alongside the M5 integrated gasmask program. This spent casing has been converted into a pipe, but there is too much tar in the mouthpiece for it to be useable." + name = "10x99mm XM43E1 casing pipe" + desc = "The XM43E1 was an experimental weapons platform briefly fielded by the USCM and Wey-Yu PMC teams. It was manufactured by ARMAT systems at the Atlas weapons facility. Unfortunately the project had its funding pulled alongside the M5 integrated gasmask program. This spent casing has been converted into a pipe, but there is too much tar in the mouthpiece for it to be useable." icon_state = "bullet_pipe" /obj/item/prop/helmetgarb/chaplain_patch @@ -515,3 +511,76 @@ desc = "This patch is all that remains of the Chaplaincy of the USS Almayer, along with the Chaplains themselves. Both no longer exist as a result of losses suffered during Operation Tychon Tackle." icon_state = "chaplain_patch" flags_obj = OBJ_NO_HELMET_BAND + +/obj/item/prop/helmetgarb/family_photo + name = "family photo" + desc = "" + icon = 'icons/obj/items/items.dmi' + icon_state = "photo" + ///The human who spawns with the photo + var/datum/weakref/owner + ///The belonging human name + var/owner_name + ///The belonging human faction + var/owner_faction + ///Text written on the back + var/scribble + +/obj/item/prop/helmetgarb/family_photo/pickup(mob/user, silent) + . = ..() + if(!owner) + RegisterSignal(user, COMSIG_POST_SPAWN_UPDATE, PROC_REF(set_owner), override = TRUE) + + +///Sets the owner of the family photo to the human it spawns with, needs var/source for signals +/obj/item/prop/helmetgarb/family_photo/proc/set_owner(datum/source) + SIGNAL_HANDLER + UnregisterSignal(source, COMSIG_POST_SPAWN_UPDATE) + var/mob/living/carbon/human/user = source + owner = WEAKREF(user) + owner_name = user.name + owner_faction = user.faction + +/obj/item/prop/helmetgarb/family_photo/get_examine_text(mob/user) + . = ..() + if(scribble) + . += "\"[scribble]\" is written on the back of the photo." + if(user.weak_reference == owner) + . += "A photo of you and your family." + return + if(user.faction == owner_faction) + . += "A photo of [owner_name] and their family." + return + . += "A photo of a family you do not know." + +/obj/item/prop/helmetgarb/family_photo/attackby(obj/item/attacking_item, mob/user) + . = ..() + if(HAS_TRAIT(attacking_item, TRAIT_TOOL_PEN) || istype(attacking_item, /obj/item/toy/crayon)) + if(scribble) + to_chat(user, SPAN_NOTICE("[src] has already been written on.")) + return + var/new_text = copytext(strip_html(tgui_input_text(user, "What would you like to write on the back of [src]?", "Photo Writing")), 1, 128) + + if(!loc == user) + to_chat(user, SPAN_NOTICE("You need to be holding [src] to write on it.")) + return + if(!user.stat == CONSCIOUS) + to_chat(user, SPAN_NOTICE("You cannot write on [src] in this state.")) + return + scribble = new_text + playsound(src, "paper_writing", 15, TRUE) + return TRUE + +/obj/item/prop/helmetgarb/compass + name = "compass" + desc = "It always faces north. Are you sure it is not broken?" + icon = 'icons/obj/items/items.dmi' + icon_state = "compass" + w_class = SIZE_SMALL + +/obj/item/prop/helmetgarb/bug_spray + name = "insect repellent" + desc = "A store-brand insect repellent, to keep any variety of pest or mosquito away from you." + icon = 'icons/obj/items/spray.dmi' + icon_state = "pestspray" + w_class = SIZE_SMALL diff --git a/code/game/objects/items/reagent_containers/food/fortunecookie.dm b/code/game/objects/items/reagent_containers/food/fortunecookie.dm index a878ff589dc8..270bd4d7c44a 100644 --- a/code/game/objects/items/reagent_containers/food/fortunecookie.dm +++ b/code/game/objects/items/reagent_containers/food/fortunecookie.dm @@ -93,7 +93,7 @@ user.put_in_hands(cookiefortune) cookiefortune = null else - to_chat(SPAN_WARNING("You break open the fortune cookie, but there's no fortune inside! Oh no!")) + to_chat(user, SPAN_WARNING("You break open the fortune cookie, but there's no fortune inside! Oh no!")) else . = ..() @@ -109,7 +109,7 @@ user.put_in_hands(cookiefortune) cookiefortune = null else - to_chat(SPAN_WARNING("You break open the fortune cookie, but there's no fortune inside! Oh no!")) + to_chat(user, SPAN_WARNING("You break open the fortune cookie, but there's no fortune inside! Oh no!")) else . = ..() diff --git a/code/game/objects/items/reagent_containers/glass/bottle.dm b/code/game/objects/items/reagent_containers/glass/bottle.dm index dd857d391b52..01eb751774e1 100644 --- a/code/game/objects/items/reagent_containers/glass/bottle.dm +++ b/code/game/objects/items/reagent_containers/glass/bottle.dm @@ -30,7 +30,7 @@ /obj/item/reagent_container/glass/bottle/Initialize() . = ..() if(!icon_state) - icon_state = "bottle-[rand(1.4)]" + icon_state = "bottle-[rand(1,4)]" /obj/item/reagent_container/glass/bottle/update_icon() overlays.Cut() diff --git a/code/game/objects/items/reagent_containers/reagent_container.dm b/code/game/objects/items/reagent_containers/reagent_container.dm index e0561d5a7e3d..327f6ba1ce1c 100644 --- a/code/game/objects/items/reagent_containers/reagent_container.dm +++ b/code/game/objects/items/reagent_containers/reagent_container.dm @@ -67,12 +67,6 @@ if (N) R.amount_per_transfer_from_this = N -/obj/item/reagent_container/Initialize() - . = ..() - if (!possible_transfer_amounts) - verbs -= /obj/item/reagent_container/verb/set_APTFT //which objects actually uses it? - create_reagents(volume) - /obj/item/reagent_container/Destroy() possible_transfer_amounts = null return ..() diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 972898e6449b..6d0736f8aeb2 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -189,6 +189,13 @@ is_reinforced = 1 construction_options = list("One Direction", "Full Window", "Windoor") +/obj/item/stack/sheet/glass/reinforced/medium_stack + amount = 25 + +/obj/item/stack/sheet/glass/reinforced/large_stack + amount = 50 + + /obj/item/stack/sheet/glass/reinforced/cyborg matter = null diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index d85e615bc1c8..82e091be9008 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -182,6 +182,11 @@ Also change the icon to reflect the amount of sheets, if possible.*/ to_chat(usr, SPAN_WARNING("The [R.title] cannot be built here!")) //might cause some friendly fire regarding other items like barbed wire, shouldn't be a problem? return + var/obj/structure/tunnel/tunnel = locate(/obj/structure/tunnel) in usr.loc + if(tunnel) + to_chat(usr, SPAN_WARNING("The [R.title] cannot be constructed on a tunnel!")) + return + if((R.flags & RESULT_REQUIRES_SNOW) && !(istype(usr.loc, /turf/open/snow) || istype(usr.loc, /turf/open/auto_turf/snow))) to_chat(usr, SPAN_WARNING("The [R.title] must be built on snow!")) return @@ -308,6 +313,8 @@ Also change the icon to reflect the amount of sheets, if possible.*/ if(mods["alt"]) if(!CAN_PICKUP(user, src)) return + if(amount <= 1) + return var/desired = tgui_input_number(user, "How much would you like to split off from this stack?", "How much?", 1, amount-1, 1) if(!desired) return diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 3b65811b05b3..966b18fc494b 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -72,9 +72,9 @@ return FALSE // Create their vis object if needed - if(!xeno.backpack_icon_carrier) - xeno.backpack_icon_carrier = new(null, xeno) - xeno.vis_contents += xeno.backpack_icon_carrier + if(!xeno.backpack_icon_holder) + xeno.backpack_icon_holder = new(null, xeno) + xeno.vis_contents += xeno.backpack_icon_holder target_mob.put_in_back(src) return FALSE @@ -566,6 +566,18 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r /obj/item/storage/backpack/marine/satchel/rto/pickup(mob/user) . = ..() + autoset_phone_id(user) + +/obj/item/storage/backpack/marine/satchel/rto/equipped(mob/user, slot) + . = ..() + autoset_phone_id(user) + +/// Automatically sets the phone_id based on the current or updated user +/obj/item/storage/backpack/marine/satchel/rto/proc/autoset_phone_id(mob/user) + if(!user) + internal_transmitter.phone_id = "[src]" + internal_transmitter.enabled = FALSE + return if(ishuman(user)) var/mob/living/carbon/human/H = user if(H.comm_title) @@ -579,13 +591,11 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r internal_transmitter.phone_id += " ([H.assigned_squad.name])" else internal_transmitter.phone_id = "[user]" - internal_transmitter.enabled = TRUE /obj/item/storage/backpack/marine/satchel/rto/dropped(mob/user) . = ..() - internal_transmitter.phone_id = "[src]" - internal_transmitter.enabled = FALSE + autoset_phone_id(null) // Disable phone when dropped /obj/item/storage/backpack/marine/satchel/rto/proc/use_phone(mob/user) internal_transmitter.attack_hand(user) @@ -745,6 +755,7 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r RegisterSignal(H, COMSIG_GRENADE_PRE_PRIME, PROC_REF(cloak_grenade_callback)) RegisterSignal(H, COMSIG_HUMAN_EXTINGUISH, PROC_REF(wrapper_fizzle_camouflage)) + RegisterSignal(H, COMSIG_MOB_EFFECT_CLOAK_CANCEL, PROC_REF(deactivate_camouflage)) camo_active = TRUE ADD_TRAIT(H, TRAIT_CLOAKED, TRAIT_SOURCE_EQUIPMENT(WEAR_BACK)) @@ -774,12 +785,14 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r deactivate_camouflage(wearer, TRUE, TRUE) /obj/item/storage/backpack/marine/satchel/scout_cloak/proc/deactivate_camouflage(mob/living/carbon/human/H, anim = TRUE, forced) + SIGNAL_HANDLER if(!istype(H)) return FALSE UnregisterSignal(H, list( COMSIG_GRENADE_PRE_PRIME, - COMSIG_HUMAN_EXTINGUISH + COMSIG_HUMAN_EXTINGUISH, + COMSIG_MOB_EFFECT_CLOAK_CANCEL, )) if(forced) @@ -1114,6 +1127,10 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r max_storage_space = 21 camo_alpha = 10 +/obj/item/storage/backpack/marine/satchel/scout_cloak/upp/weak + desc = "A thermo-optic camouflage cloak commonly used by UPP commando units. This one is less effective than normal." + actions_types = null + //----------TWE SECTION---------- /obj/item/storage/backpack/rmc has_gamemode_skin = FALSE diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index 6266f0eef77d..4a3afa00f368 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -151,6 +151,7 @@ RegisterSignal(SSdcs, COMSIG_GLOB_MODE_PRESETUP, PROC_REF(handle_delete_clash_contents)) /obj/item/storage/box/flashbangs/proc/handle_delete_clash_contents() + SIGNAL_HANDLER if(MODE_HAS_FLAG(MODE_FACTION_CLASH)) var/grenade_count = 0 var/grenades_desired = 4 diff --git a/code/game/objects/items/storage/large_holster.dm b/code/game/objects/items/storage/large_holster.dm index b4a6c3a8c1af..27026165fc31 100644 --- a/code/game/objects/items/storage/large_holster.dm +++ b/code/game/objects/items/storage/large_holster.dm @@ -75,20 +75,20 @@ desc = "A large leather scabbard used to carry a M2132 machete. It can be strapped to the back or the armor." icon_state = "machete_holster" flags_equip_slot = SLOT_WAIST|SLOT_BACK - can_hold = list(/obj/item/weapon/claymore/mercsword/machete) + can_hold = list(/obj/item/weapon/sword/machete) /obj/item/storage/large_holster/machete/full/fill_preset_inventory() - new /obj/item/weapon/claymore/mercsword/machete(src) + new /obj/item/weapon/sword/machete(src) /obj/item/storage/large_holster/machete/arnold name = "\improper QH20 pattern M2100 custom machete scabbard" desc = "A large leather scabbard used to carry a M2100 \"Ngájhe\" machete. It can be strapped to the back or the armor." icon_state = "arnold-machete-pouch" flags_equip_slot = SLOT_WAIST|SLOT_BACK - can_hold = list(/obj/item/weapon/claymore/mercsword/machete) + can_hold = list(/obj/item/weapon/sword/machete) /obj/item/storage/large_holster/machete/arnold/full/fill_preset_inventory() - new /obj/item/weapon/claymore/mercsword/machete/arnold(src) + new /obj/item/weapon/sword/machete/arnold(src) /obj/item/storage/large_holster/katana name = "\improper katana scabbard" @@ -97,10 +97,10 @@ force = 12 attack_verb = list("bludgeoned", "struck", "cracked") flags_equip_slot = SLOT_WAIST|SLOT_BACK - can_hold = list(/obj/item/weapon/katana) + can_hold = list(/obj/item/weapon/sword/katana) /obj/item/storage/large_holster/katana/full/fill_preset_inventory() - new /obj/item/weapon/katana(src) + new /obj/item/weapon/sword/katana(src) /obj/item/storage/large_holster/ceremonial_sword name = "ceremonial sword scabbard" @@ -108,10 +108,10 @@ icon_state = "ceremonial_sword_holster"//object icon is duplicate of katana holster, needs new icon at some point. force = 12 flags_equip_slot = SLOT_WAIST - can_hold = list(/obj/item/weapon/claymore/mercsword/ceremonial) + can_hold = list(/obj/item/weapon/sword/ceremonial) /obj/item/storage/large_holster/ceremonial_sword/full/fill_preset_inventory() - new /obj/item/weapon/claymore/mercsword/ceremonial(src) + new /obj/item/weapon/sword/ceremonial(src) /obj/item/storage/large_holster/m39 name = "\improper M276 pattern M39 holster rig" @@ -249,9 +249,13 @@ if(!ishuman(user) || user.is_mob_incapacitated()) return FALSE - var/obj/item/weapon/gun/flamer/M240T/F = user.get_active_hand() - if(!istype(F)) - to_chat(usr, "You must be holding the M240-T incinerator unit to use [src]") + if(user.back != src) + to_chat(user, "The [src] must be equipped before you can switch types") + return + + var/obj/item/weapon/gun/flamer/M240T/flamer = user.get_active_hand() + if(!istype(flamer)) + to_chat(user, "You must be holding the M240-T incinerator unit to use [src]") return if(!active_fuel) @@ -267,14 +271,13 @@ else active_fuel = fuelB - for(var/X in actions) - var/datum/action/A = X - A.update_button_icon() + for(var/datum/action/action_added as anything in actions) + action_added.update_button_icon() to_chat(user, "You switch the fuel tank to [active_fuel.caliber]") playsound(src, 'sound/machines/click.ogg', 25, TRUE) - F.current_mag = active_fuel - F.update_icon() + flamer.current_mag = active_fuel + flamer.update_icon() return TRUE diff --git a/code/game/objects/items/storage/pouch.dm b/code/game/objects/items/storage/pouch.dm index 48eb322f2093..acb87e988879 100644 --- a/code/game/objects/items/storage/pouch.dm +++ b/code/game/objects/items/storage/pouch.dm @@ -683,6 +683,18 @@ new /obj/item/reagent_container/hypospray/autoinjector/stimulant/redemption_stimulant(src) new /obj/item/reagent_container/hypospray/autoinjector/stimulant/speed_stimulant(src) +/obj/item/storage/pouch/medical/socmed/not_op/fill_preset_inventory() + new /obj/item/device/healthanalyzer(src) + new /obj/item/stack/medical/splint(src) + new /obj/item/stack/medical/advanced/bruise_pack(src) + new /obj/item/stack/medical/advanced/ointment(src) + new /obj/item/reagent_container/hypospray/autoinjector/bicaridine(src) + new /obj/item/reagent_container/hypospray/autoinjector/kelotane(src) + new /obj/item/reagent_container/hypospray/autoinjector/oxycodone(src) + new /obj/item/reagent_container/hypospray/autoinjector/emergency(src) + new /obj/item/reagent_container/hypospray/autoinjector/emergency(src) + new /obj/item/tool/extinguisher/mini(src) + /obj/item/storage/pouch/medical/socmed/dutch name = "\improper Dutch's Medical Pouch" desc = "A pouch bought from a black market trader by Dutch quite a few years ago. Rumoured to be stolen from secret USCM assets. Its contents have been slowly used up and replaced over the years." @@ -833,6 +845,15 @@ new /obj/item/stack/medical/advanced/ointment(src) new /obj/item/stack/medical/splint(src) +/obj/item/storage/pouch/medkit/full/toxin/fill_preset_inventory() + new /obj/item/device/healthanalyzer(src) + new /obj/item/storage/pill_bottle/antitox(src) + new /obj/item/storage/pill_bottle/antitox(src) + new /obj/item/roller(src) + new /obj/item/stack/medical/splint(src) + new /obj/item/stack/medical/advanced/bruise_pack(src) + new /obj/item/stack/medical/advanced/ointment(src) + /obj/item/storage/pouch/pressurized_reagent_canister name = "Pressurized Reagent Canister Pouch" max_w_class = SIZE_SMALL @@ -1372,7 +1393,7 @@ item_state = "machete_holster" max_w_class = SIZE_LARGE storage_flags = STORAGE_FLAGS_POUCH|STORAGE_USING_DRAWING_METHOD|STORAGE_ALLOW_QUICKDRAW - can_hold = list(/obj/item/weapon/claymore/mercsword/machete) + can_hold = list(/obj/item/weapon/sword/machete) var/sheathe_sound = 'sound/weapons/gun_rifle_draw.ogg' var/draw_sound = 'sound/weapons/gun_rifle_draw.ogg' @@ -1392,4 +1413,4 @@ playsound(src, draw_sound, vol = 15, vary = TRUE) /obj/item/storage/pouch/machete/full/fill_preset_inventory() - new /obj/item/weapon/claymore/mercsword/machete(src) + new /obj/item/weapon/sword/machete(src) diff --git a/code/game/objects/items/storage/smartpack.dm b/code/game/objects/items/storage/smartpack.dm index 8df079c92ca4..0b0fd05eac17 100644 --- a/code/game/objects/items/storage/smartpack.dm +++ b/code/game/objects/items/storage/smartpack.dm @@ -144,7 +144,7 @@ immobile_form = FALSE M.status_flags |= CANPUSH M.anchored = FALSE - M.unfreeze() + REMOVE_TRAIT(M, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_BACK)) ..() /obj/item/storage/backpack/marine/smartpack/attack_self(mob/user) @@ -236,7 +236,7 @@ battery_charge -= IMMOBILE_COST user.status_flags &= ~CANPUSH user.anchored = TRUE - user.frozen = TRUE + ADD_TRAIT(user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_BACK)) to_chat(user, SPAN_DANGER("[name] beeps, \"You are anchored in place and cannot be moved.\"")) to_chat(user, SPAN_INFO("The current charge reads [battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) @@ -248,7 +248,7 @@ else user.status_flags |= CANPUSH user.anchored = FALSE - user.unfreeze() + REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_BACK)) to_chat(user, SPAN_DANGER("[name] beeps, \"You can now move again.\"")) user.remove_filter("synth_immobile_form") diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index e3fbe86c0e3b..6e7e891d6ba8 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -22,7 +22,7 @@ var/atom/movable/screen/storage/storage_start = null //storage UI var/atom/movable/screen/storage/storage_continue = null var/atom/movable/screen/storage/storage_end = null - var/datum/item_storage_box/stored_ISB = null // This contains what previously was known as stored_start, stored_continue, and stored_end + var/datum/item_storage_box/stored_ISB //! This contains what previously was known as stored_start, stored_continue, and stored_end var/atom/movable/screen/close/closer = null var/foldable = null var/use_sound = "rustle" //sound played when used. null for no sound. @@ -212,16 +212,17 @@ if (storage_flags & STORAGE_SHOW_FULLNESS) boxes.update_fullness(src) -var/list/global/item_storage_box_cache = list() +GLOBAL_LIST_EMPTY_TYPED(item_storage_box_cache, /datum/item_storage_box) /datum/item_storage_box - var/atom/movable/screen/storage/start = null - var/atom/movable/screen/storage/continued = null - var/atom/movable/screen/storage/end = null - /// The index that indentifies me inside item_storage_box_cache + var/atom/movable/screen/storage/start + var/atom/movable/screen/storage/continued + var/atom/movable/screen/storage/end + /// The index that indentifies me inside GLOB.item_storage_box_cache var/index /datum/item_storage_box/New() + . = ..() start = new() start.icon_state = "stored_start" continued = new() @@ -233,7 +234,7 @@ var/list/global/item_storage_box_cache = list() QDEL_NULL(start) QDEL_NULL(continued) QDEL_NULL(end) - item_storage_box_cache[index] = null // Or would it be better to -= src? + GLOB.item_storage_box_cache -= index return ..() /obj/item/storage/proc/space_orient_objs(list/obj/item/display_contents) @@ -271,7 +272,7 @@ var/list/global/item_storage_box_cache = list() click_border_start.Add(startpoint) click_border_end.Add(endpoint) - if(!item_storage_box_cache[isb_index]) + if(!GLOB.item_storage_box_cache[isb_index]) var/datum/item_storage_box/box = new() var/matrix/M_start = matrix() var/matrix/M_continue = matrix() @@ -284,9 +285,9 @@ var/list/global/item_storage_box_cache = list() box.continued.apply_transform(M_continue) box.end.apply_transform(M_end) box.index = isb_index - item_storage_box_cache[isb_index] = box + GLOB.item_storage_box_cache[isb_index] = box - var/datum/item_storage_box/ISB = item_storage_box_cache[isb_index] + var/datum/item_storage_box/ISB = GLOB.item_storage_box_cache[isb_index] stored_ISB = ISB storage_start.overlays += ISB.start @@ -851,6 +852,7 @@ W is always an item. stop_warning prevents messaging. user may be null.**/ return ..() /obj/item/storage/emp_act(severity) + . = ..() if(!istype(src.loc, /mob/living)) for(var/obj/O in contents) O.emp_act(severity) diff --git a/code/game/objects/items/tools/flame_tools.dm b/code/game/objects/items/tools/flame_tools.dm index 130bd567098b..7681e74a1d88 100644 --- a/code/game/objects/items/tools/flame_tools.dm +++ b/code/game/objects/items/tools/flame_tools.dm @@ -642,7 +642,39 @@ CIGARETTE PACKETS ARE IN FANCY.DM icon_off = "cobpipeoff" smoketime = 800 SECONDS +/obj/item/clothing/mask/electronic_cigarette + name = "electronic cigarette" + desc = "An electronic cigarette by The American Tobacco Company, who also made Lucky Strikes." + icon_state = "cigoff" + item_state = "cigoff" + w_class = SIZE_SMALL + flags_equip_slot = SLOT_EAR|SLOT_FACE + var/icon_on = "cigon" + var/icon_off = "cigoff" + var/enabled = FALSE +/obj/item/clothing/mask/electronic_cigarette/update_icon() + . = ..() + if(enabled) + icon_state = icon_on + item_state = icon_on + return + icon_state = icon_off + item_state = icon_off + +/obj/item/clothing/mask/electronic_cigarette/attack_self(mob/user) + . = ..() + to_chat(user, SPAN_NOTICE("You [enabled ? "disable" : "enable"] [src].")) + enabled = !enabled + update_icon() + +/obj/item/clothing/mask/electronic_cigarette/cigar + name = "electronic cigar" + desc = "A luxury electronic cigar, with its labels scratched off. Where could this be from?" + icon_state = "cigar_off" + item_state = "cigar_off" + icon_on = "cigar_on" + icon_off = "cigar_off" ///////// //ZIPPO// diff --git a/code/game/objects/items/tools/misc_tools.dm b/code/game/objects/items/tools/misc_tools.dm index b5be55eed540..f70f93497021 100644 --- a/code/game/objects/items/tools/misc_tools.dm +++ b/code/game/objects/items/tools/misc_tools.dm @@ -173,7 +173,7 @@ playsound(user.loc, "sound/items/pen_click_[on? "on": "off"].ogg", 100, 1, 5) update_pen_state() -/obj/item/tool/pen/Initialize() +/obj/item/tool/pen/Initialize(mapload, ...) . = ..() update_pen_state() @@ -284,21 +284,24 @@ matter = list("metal" = 20, "gold" = 10) var/static/list/colour_list = list("red", "blue", "green", "yellow", "purple", "pink", "brown", "black", "orange") // Can add more colors as required var/current_colour_index = 1 - var/owner = "hard to read text" + var/owner_name -/obj/item/tool/pen/fountain/Initialize(mapload, mob/living/carbon/human/user) +/obj/item/tool/pen/fountain/pickup(mob/user, silent) . = ..() - var/turf/current_turf = get_turf(src) - var/mob/living/carbon/human/new_owner = locate() in current_turf - if(new_owner) - owner = new_owner.real_name - var/obj/structure/machinery/cryopod/new_owners_pod = locate() in current_turf - if(new_owners_pod) - owner = new_owners_pod.occupant?.real_name + if(!owner_name) + RegisterSignal(user, COMSIG_POST_SPAWN_UPDATE, PROC_REF(set_owner), override = TRUE) + +///Sets the owner of the pen to who it spawns with, requires var/source for signals +/obj/item/tool/pen/fountain/proc/set_owner(datum/source) + SIGNAL_HANDLER + UnregisterSignal(source, COMSIG_POST_SPAWN_UPDATE) + var/mob/living/carbon/human/user = source + owner_name = user.name /obj/item/tool/pen/fountain/get_examine_text(mob/user) . = ..() - . += "There's a laser engraving of [owner] on it." + if(owner_name) + . += "There's a laser engraving of [owner_name] on it." /obj/item/tool/pen/fountain/attack_self(mob/living/carbon/human/user) if(on) diff --git a/code/game/objects/items/toys/cards.dm b/code/game/objects/items/toys/cards.dm index b6e3bb558ec4..2debd83f9bab 100644 --- a/code/game/objects/items/toys/cards.dm +++ b/code/game/objects/items/toys/cards.dm @@ -21,7 +21,6 @@ icon = 'icons/obj/items/playing_cards.dmi' icon_state = "deck" w_class = SIZE_TINY - flags_item = NOTABLEMERGE var/base_icon = "deck" var/max_cards = 52 @@ -262,7 +261,6 @@ icon = 'icons/obj/items/playing_cards.dmi' icon_state = "empty" w_class = SIZE_TINY - flags_item = NOTABLEMERGE var/concealed = FALSE var/pile_state = FALSE diff --git a/code/game/objects/items/toys/toys.dm b/code/game/objects/items/toys/toys.dm index b2a66becd869..88946f5fa446 100644 --- a/code/game/objects/items/toys/toys.dm +++ b/code/game/objects/items/toys/toys.dm @@ -318,56 +318,6 @@ desc = "Mini-Mecha action figure! Collect them all! 11/11." icon_state = "phazonprize" - -/obj/item/toy/therapy_red - name = "red therapy doll" - desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles. This one is red." - icon = 'icons/obj/items/toy.dmi' - icon_state = "therapyred" - item_state = "egg4" // It's the red egg in items_left/righthand - w_class = SIZE_TINY - -/obj/item/toy/therapy_purple - name = "purple therapy doll" - desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles. This one is purple." - icon = 'icons/obj/items/toy.dmi' - icon_state = "therapypurple" - item_state = "egg1" // It's the magenta egg in items_left/righthand - w_class = SIZE_TINY - -/obj/item/toy/therapy_blue - name = "blue therapy doll" - desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles. This one is blue." - icon = 'icons/obj/items/toy.dmi' - icon_state = "therapyblue" - item_state = "egg2" // It's the blue egg in items_left/righthand - w_class = SIZE_TINY - -/obj/item/toy/therapy_yellow - name = "yellow therapy doll" - desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles. This one is yellow." - icon = 'icons/obj/items/toy.dmi' - icon_state = "therapyyellow" - item_state = "egg5" // It's the yellow egg in items_left/righthand - w_class = SIZE_TINY - -/obj/item/toy/therapy_orange - name = "orange therapy doll" - desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles. This one is orange." - icon = 'icons/obj/items/toy.dmi' - icon_state = "therapyorange" - item_state = "egg4" // It's the red one again, lacking an orange item_state and making a new one is pointless - w_class = SIZE_TINY - -/obj/item/toy/therapy_green - name = "green therapy doll" - desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles. This one is green." - icon = 'icons/obj/items/toy.dmi' - icon_state = "therapygreen" - item_state = "egg3" // It's the green egg in items_left/righthand - w_class = SIZE_TINY - - /obj/item/toy/inflatable_duck name = "inflatable duck" desc = "No bother to sink or swim when you can just float!" @@ -377,7 +327,6 @@ flags_equip_slot = SLOT_WAIST black_market_value = 20 - /obj/item/toy/beach_ball name = "beach ball" icon_state = "beachball" @@ -394,7 +343,6 @@ user.drop_held_item() throw_atom(target, throw_range, throw_speed, user) - /obj/item/toy/dice name = "d6" desc = "A die with six sides." @@ -427,10 +375,6 @@ SPAN_NOTICE("You throw [src]. It lands on a [result]. [comment]"), \ SPAN_NOTICE("You hear [src] landing on a [result]. [comment]")) - - - - /obj/item/toy/bikehorn name = "bike horn" desc = "A horn off of a bicycle." @@ -455,47 +399,6 @@ src.add_fingerprint(user) addtimer(VARSET_CALLBACK(src, spam_flag, FALSE), 2 SECONDS) - - -/obj/item/toy/farwadoll - name = "Farwa plush doll" - desc = "A Farwa plush doll. It's soft and comforting!" - w_class = SIZE_TINY - icon_state = "farwaplush" - black_market_value = 25 - COOLDOWN_DECLARE(last_hug_time) - -/obj/item/toy/farwadoll/attack_self(mob/user) - ..() - - if(COOLDOWN_FINISHED(src, last_hug_time)) - user.visible_message(SPAN_NOTICE("[user] hugs [src]! How cute! "), \ - SPAN_NOTICE("You hug [src]. Dawwww... ")) - COOLDOWN_START(src, last_hug_time, 5 SECONDS) - -/obj/item/toy/farwadoll/pred - name = "strange plush doll" - desc = "A plush doll depicting some sort of tall humanoid biped..?" - w_class = SIZE_TINY - icon_state = "predplush" - -/obj/item/toy/plushie_cade - name = "plushie barricade" - desc = "Great for squeezing whenever you're scared. Or lightly hurt. Or in any other situation." - icon_state = "plushie_cade" - item_state = "plushie_cade" - w_class = SIZE_SMALL - COOLDOWN_DECLARE(last_hug_time) - -/obj/item/toy/plushie_cade/attack_self(mob/user) - ..() - - if(COOLDOWN_FINISHED(src, last_hug_time)) - user.visible_message(SPAN_NOTICE("[user] hugs [src] tightly!"), SPAN_NOTICE("You hug [src]. You feel safe.")) - playsound(user, "plush", 25, TRUE) - COOLDOWN_START(src, last_hug_time, 2.5 SECONDS) - - /obj/item/computer3_part name = "computer part" desc = "Holy jesus you donnit now" @@ -567,3 +470,188 @@ /obj/item/toy/festivizer/xeno name = "strange resin-covered festivizer decorator" desc = "This bizarre festivizer is covered in goopy goop and schmuck. Ew! It's so sticky, *anything* could grab onto it! Grab it and touch other things to festivize them!" + +/obj/item/toy/plush + name = "generic plushie" + desc = "perfectly generic" + icon = 'icons/obj/items/plush.dmi' + icon_state = "debug" + w_class = SIZE_SMALL + COOLDOWN_DECLARE(last_hug_time) + black_market_value = 10 + +/obj/item/toy/plush/attack_self(mob/user) + ..() + if(!COOLDOWN_FINISHED(src, last_hug_time)) + return + user.visible_message(SPAN_NOTICE("[user] hugs [src] tightly!"), SPAN_NOTICE("You hug [src].")) + playsound(user, "plush", 25, TRUE) + COOLDOWN_START(src, last_hug_time, 2.5 SECONDS) + +/obj/item/toy/plush/farwa + name = "Farwa plush" + desc = "A Farwa plush doll. It's soft and comforting!" + icon_state = "farwa" + black_market_value = 25 + +/obj/item/toy/plush/barricade + name = "plushie barricade" + desc = "Great for squeezing whenever you're scared. Or lightly hurt. Or in any other situation." + icon_state = "barricade" + item_state = "cade_plush" + +/obj/item/toy/plush/shark //A few more generic plushies to increase the size of the plushie loot pool + name = "shark plush" + desc = "A plushie depicting a somewhat cartoonish shark. The tag notes that it was made by an obscure furniture manufacturer in Scandinavia." + icon_state = "shark" + +/obj/item/toy/plush/bee + name = "bee plush" + desc = "A cute toy that awakens the warrior spirit in the most reserved marine." + icon_state = "bee" + +/obj/item/toy/plush/moth + name = "moth plush" + desc = "A plush doll of a bug." + icon_state = "moth" + +/obj/item/toy/plush/rock + name = "rock plush" + desc = "It says it is a plush on the tag, at least." + icon_state = "rock" + +/obj/item/toy/plush/therapy + name = "therapy plush" + desc = "A therapeutic toy to assist marines in recovering from mental and behavioral disorders after experiencing the trauma of battles." + icon_state = "therapy" + +/obj/item/toy/plush/therapy/red + name = "red therapy plush" + color = "#FC5274" + +/obj/item/toy/plush/therapy/blue + name = "blue therapy plush" + color = "#9EBAE0" + +/obj/item/toy/plush/therapy/green + name = "green therapy plush" + color = "#A3C940" + +/obj/item/toy/plush/therapy/orange + name = "orange therapy plush" + color = "#FD8535" + +/obj/item/toy/plush/therapy/purple + name = "purple therapy plush" + color = "#A26AC7" + +/obj/item/toy/plush/therapy/yellow + name = "yellow therapy plush" + color = "#FFE492" + +/obj/item/toy/plush/therapy/random_color + ///Hexadecimal 0-F (0-15) + var/static/list/hexadecimal = list("0", "1", "2", "3" , "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") + +/obj/item/toy/plush/therapy/random_color/Initialize(mapload, ...) + . = ..() + var/color_code = "#[pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)][pick(hexadecimal)]" //This is dumb and I hope theres a better way I'm missing + color = color_code + desc = "A custom therapy plush, in a unique color." + +/obj/item/toy/plush/random_plushie //Not using an effect so it can fit into storage from loadout + name = "random plush" + desc = "This plush looks awfully standard and bland. Is it actually yours?" + /// Standard plushies for the spawner to pick from + var/list/plush_list = list( + /obj/item/toy/plush/farwa, + /obj/item/toy/plush/barricade, + /obj/item/toy/plush/bee, + /obj/item/toy/plush/shark, + /obj/item/toy/plush/moth, + /obj/item/toy/plush/rock, + ) + ///Therapy plushies left separately to not flood the entire list + var/list/therapy_plush_list = list( + /obj/item/toy/plush/therapy, + /obj/item/toy/plush/therapy/red, + /obj/item/toy/plush/therapy/blue, + /obj/item/toy/plush/therapy/green, + /obj/item/toy/plush/therapy/orange, + /obj/item/toy/plush/therapy/purple, + /obj/item/toy/plush/therapy/yellow, + /obj/item/toy/plush/therapy/random_color, + ) + +/obj/item/toy/plush/random_plushie/Initialize(mapload, ...) + . = ..() + if(mapload) //Placed in mapping, will be randomized instantly on spawn + create_plushie() + return INITIALIZE_HINT_QDEL + +/obj/item/toy/plush/random_plushie/pickup(mob/user, silent) + . = ..() + RegisterSignal(user, COMSIG_POST_SPAWN_UPDATE, PROC_REF(create_plushie), override = TRUE) + +///The randomizer picking and spawning a plushie on either the ground or in the humans backpack. Needs var/source due to signals +/obj/item/toy/plush/random_plushie/proc/create_plushie(datum/source) + SIGNAL_HANDLER + if(source) + UnregisterSignal(source, COMSIG_POST_SPAWN_UPDATE) + var/turf/spawn_location = get_turf(src) + var/plush_list_variety = pick(60; plush_list, 40; therapy_plush_list) + var/random_plushie = pick(plush_list_variety) + var/obj/item/toy/plush/plush = new random_plushie(spawn_location) //Starts on floor by default + var/mob/living/carbon/human/user = source + + if(!user) //If it didn't spawn on a humanoid + qdel(src) + return + + var/obj/item/storage/backpack/storage = locate() in user //If the user has a backpack, put it there + if(storage?.can_be_inserted(plush, user, stop_messages = TRUE)) + storage.attempt_item_insertion(plush, TRUE, user) + if(plush.loc == spawn_location) // Still on the ground + user.put_in_hands(plush, drop_on_fail = TRUE) + qdel(src) + +//Admin plushies +/obj/item/toy/plush/yautja + name = "strange plush" + desc = "A plush doll depicting some sort of tall humanoid biped..?" + icon_state = "yautja" + black_market_value = 100 + +/obj/item/toy/plush/runner + name = "\improper XX-121 therapy plush" + desc = "Don't be sad! Be glad (that you're alive)!" + icon_state = "runner" + /// If the runner is wearing a beret + var/beret = FALSE + +/obj/item/toy/plush/runner/Initialize(mapload, ...) + . = ..() + if(beret) + update_icon() + +/obj/item/toy/plush/runner/attackby(obj/item/attacking_object, mob/user) + . = ..() + if(beret) + return + if(!istypestrict(attacking_object, /obj/item/clothing/head/beret/marine/mp)) + return + var/beret_attack = attacking_object + to_chat(user, SPAN_NOTICE("You put [beret_attack] on [src].")) + qdel(beret_attack) + beret = TRUE + update_icon() + +/obj/item/toy/plush/runner/update_icon() + . = ..() + if(beret) + icon_state = "runner_beret" + return + icon_state = "runner" + +/obj/item/toy/plush/shark/alt + icon_state = "shark_alt" diff --git a/code/game/objects/items/weapons/blades.dm b/code/game/objects/items/weapons/blades.dm index 4b4b31539064..2fe80f123bce 100644 --- a/code/game/objects/items/weapons/blades.dm +++ b/code/game/objects/items/weapons/blades.dm @@ -1,38 +1,36 @@ -/obj/item/weapon/claymore - name = "claymore" - desc = "What are you standing around staring at this for? Get to killing!" - icon_state = "claymore" - item_state = "claymore" +/obj/item/weapon/sword + name = "combat sword" + desc = "A dusty sword commonly seen in historical museums. Where you got this is a mystery, for sure. Only a mercenary would be nuts enough to carry one of these. Sharpened to deal massive damage." + icon_state = "mercsword" + item_state = "machete" flags_atom = FPRINT|CONDUCT flags_equip_slot = SLOT_WAIST force = MELEE_FORCE_STRONG throwforce = MELEE_FORCE_WEAK sharp = IS_SHARP_ITEM_BIG edge = 1 - w_class = SIZE_MEDIUM + w_class = SIZE_LARGE hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") attack_speed = 9 -/obj/item/weapon/claymore/mercsword - name = "combat sword" - desc = "A dusty sword commonly seen in historical museums. Where you got this is a mystery, for sure. Only a mercenary would be nuts enough to carry one of these. Sharpened to deal massive damage." - icon_state = "mercsword" - item_state = "machete" +/obj/item/weapon/sword/claymore + name = "claymore" + desc = "What are you standing around staring at this for? Get to killing!" + icon_state = "claymore" + item_state = "claymore" -/obj/item/weapon/claymore/mercsword/ceremonial +/obj/item/weapon/sword/ceremonial name = "Ceremonial Sword" desc = "A fancy ceremonial sword passed down from generation to generation. Despite this, it has been very well cared for, and is in top condition." icon_state = "ceremonial" - item_state = "machete" -/obj/item/weapon/claymore/mercsword/machete +/obj/item/weapon/sword/machete name = "\improper M2132 machete" desc = "Latest issue of the USCM Machete. Great for clearing out jungle or brush on outlying colonies. Found commonly in the hands of scouts and trackers, but difficult to carry with the usual kit." icon_state = "machete" - w_class = SIZE_LARGE -/obj/item/weapon/claymore/mercsword/machete/attack_self(mob/user) +/obj/item/weapon/sword/machete/attack_self(mob/user) if(user.action_busy) return @@ -49,14 +47,13 @@ return ..() -/obj/item/weapon/claymore/mercsword/machete/arnold +/obj/item/weapon/sword/machete/arnold name = "\improper M2100 \"Ngájhe\" machete" desc = "An older issue USCM machete, never left testing. Designed in the Central African Republic. The notching made it hard to clean, and as such the USCM refused to adopt it - despite the superior bludgeoning power offered. Difficult to carry with the usual kit." icon_state = "arnold-machete" - w_class = SIZE_LARGE force = MELEE_FORCE_TIER_11 -/obj/item/weapon/claymore/hefa +/obj/item/weapon/sword/hefa name = "HEFA sword" icon_state = "hefasword" item_state = "hefasword" @@ -65,7 +62,7 @@ var/primed = FALSE -/obj/item/weapon/claymore/hefa/proc/apply_explosion_overlay() +/obj/item/weapon/sword/hefa/proc/apply_explosion_overlay() var/obj/effect/overlay/O = new /obj/effect/overlay(loc) O.name = "grenade" O.icon = 'icons/effects/explosion.dmi' @@ -73,7 +70,7 @@ QDEL_IN(O, 7) return -/obj/item/weapon/claymore/hefa/attack_self(mob/user) +/obj/item/weapon/sword/hefa/attack_self(mob/user) ..() primed = !primed @@ -82,7 +79,7 @@ msg = "You de-activate \the [src]!" to_chat(user, SPAN_NOTICE(msg)) -/obj/item/weapon/claymore/hefa/attack(mob/target, mob/user) +/obj/item/weapon/sword/hefa/attack(mob/target, mob/user) . = ..() if(!primed) return @@ -97,22 +94,15 @@ cell_explosion(epicenter, 40, 18, EXPLOSION_FALLOFF_SHAPE_LINEAR, user.dir, cause_data) qdel(src) -/obj/item/weapon/katana +/obj/item/weapon/sword/katana name = "katana" desc = "A finely made Japanese sword, with a well sharpened blade. The blade has been filed to a molecular edge, and is extremely deadly. Commonly found in the hands of mercenaries and yakuza." icon_state = "katana" - flags_atom = FPRINT|CONDUCT + item_state = "katana" force = MELEE_FORCE_VERY_STRONG - throwforce = MELEE_FORCE_WEAK - sharp = IS_SHARP_ITEM_BIG - edge = 1 - w_class = SIZE_MEDIUM - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - attack_speed = 9 //To do: replace the toys. -/obj/item/weapon/katana/replica +/obj/item/weapon/sword/katana/replica name = "replica katana" desc = "A cheap knock-off commonly found in regular knife stores. Can still do some damage." force = MELEE_FORCE_WEAK @@ -246,3 +236,142 @@ WEAR_L_HAND = 'icons/mob/humans/onmob/items_lefthand_64.dmi', WEAR_R_HAND = 'icons/mob/humans/onmob/items_righthand_64.dmi' ) + +/obj/item/weapon/straight_razor + name = "straight razor" + desc = "The commandant's favorite weapon against marines who dare break the grooming standards." + icon_state = "razor" + hitsound = 'sound/weapons/genhit3.ogg' + force = MELEE_FORCE_TIER_1 + throwforce = MELEE_FORCE_TIER_1 + throw_speed = SPEED_VERY_FAST + throw_range = 6 + ///Icon state for opened razor + var/enabled_icon = "razor" + ///Icon state for closed razor + var/disabled_icon = "razor_off" + ///If the razor is able to be used + var/razor_opened = FALSE + ///Time taken to open/close the razor + var/interaction_time = 3 SECONDS + +/obj/item/weapon/straight_razor/Initialize(mapload, ...) + . = ..() + RegisterSignal(src, COMSIG_ITEM_ATTEMPTING_EQUIP, PROC_REF(can_fit_in_shoe)) + change_razor_state(razor_opened) + if(prob(1)) + desc += " There is phrase etched into it, \"It can guarantee the closest shave you'll ever know.\"..." + +/obj/item/weapon/straight_razor/update_icon() + . = ..() + if(razor_opened) + icon_state = enabled_icon + return + icon_state = disabled_icon + +/obj/item/weapon/straight_razor/attack_hand(mob/user) + if(loc != user) //Only do unique stuff if you are holding it + return ..() + + if(!do_after(user, interaction_time, INTERRUPT_INCAPACITATED, BUSY_ICON_HOSTILE)) + return + playsound(user, 'sound/weapons/flipblade.ogg', 15, 1) + change_razor_state(!razor_opened) + to_chat(user, SPAN_NOTICE("You [razor_opened ? "reveal" : "hide"] [src]'s blade.")) + +///Check if the item can fit as a boot knife, var/source for signals +/obj/item/weapon/straight_razor/proc/can_fit_in_shoe(source = src, mob/user, slot) + if(slot != WEAR_IN_SHOES) //Only check if you try putting it in a shoe + return + if(razor_opened) + to_chat(user, SPAN_NOTICE("You cannot store [src] in your shoes until the blade is hidden.")) + return COMPONENT_CANCEL_EQUIP + +///Changes all the vars for the straight razor +/obj/item/weapon/straight_razor/proc/change_razor_state(opening = FALSE) + razor_opened = opening + update_icon() + if(opening) + force = MELEE_FORCE_NORMAL + throwforce = MELEE_FORCE_NORMAL + sharp = IS_SHARP_ITEM_ACCURATE + edge = TRUE + attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + hitsound = 'sound/weapons/slash.ogg' + if(!(flags_item & CAN_DIG_SHRAPNEL)) + flags_item |= CAN_DIG_SHRAPNEL + return + force = MELEE_FORCE_TIER_1 + throwforce = MELEE_FORCE_TIER_1 + sharp = FALSE + edge = FALSE + attack_verb = list("smashed", "beaten", "slammed", "struck", "smashed", "battered", "cracked") + hitsound = 'sound/weapons/genhit3.ogg' + if(flags_item & CAN_DIG_SHRAPNEL) + flags_item &= ~CAN_DIG_SHRAPNEL + +/obj/item/weapon/straight_razor/verb/change_hair_style() + set name = "Change Hair Style" + set desc = "Change your hair style" + set category = "Object" + set src in usr + + var/mob/living/carbon/human/human_user = usr + if(!istype(human_user)) + return + + if(!razor_opened) + to_chat(human_user, SPAN_NOTICE("You need to reveal [src]'s blade to change your hairstyle.")) + return + + var/list/species_facial_hair = GLOB.facial_hair_styles_list + var/list/species_hair = GLOB.hair_styles_list + + if(human_user.species) //Facial hair + species_facial_hair = list() + for(var/current_style in GLOB.facial_hair_styles_list) + var/datum/sprite_accessory/facial_hair/temp_beard_style = GLOB.facial_hair_styles_list[current_style] + if(!(human_user.species.name in temp_beard_style.species_allowed)) + continue + if(!temp_beard_style.selectable) + continue + species_facial_hair += current_style + + if(human_user.species) //Hair + species_hair = list() + for(var/current_style in GLOB.hair_styles_list) + var/datum/sprite_accessory/hair/temp_hair_style = GLOB.hair_styles_list[current_style] + if(!(human_user.species.name in temp_hair_style.species_allowed)) + continue + if(!temp_hair_style.selectable) + continue + species_hair += current_style + + var/new_beard_style + var/new_hair_style + if(human_user.gender == MALE) + new_beard_style = tgui_input_list(human_user, "Select a facial hair style", "Grooming", species_facial_hair) + new_hair_style = tgui_input_list(human_user, "Select a hair style", "Grooming", species_hair) + + if(loc != human_user) + to_chat(human_user, SPAN_NOTICE("You are too far from [src] to change your hair styles.")) + return + + if(!new_beard_style && !new_hair_style) + return + + if(!do_after(human_user, interaction_time, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + return + + if(!razor_opened) + to_chat(human_user, SPAN_NOTICE("You need to reveal [src]'s blade to change your hairstyle.")) + return + + if(new_beard_style) + human_user.f_style = new_beard_style + if(new_hair_style) + human_user.h_style = new_hair_style + + human_user.apply_damage(rand(1,5), BRUTE, "head", src) + human_user.update_hair() + diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 20bf8ac951e9..0497a410a373 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -89,7 +89,7 @@ /obj/item/weapon/shield/riot/attackby(obj/item/W as obj, mob/user as mob) if(cooldown < world.time - 25) - if(istype(W, /obj/item/weapon/baton) || istype(W, /obj/item/weapon/claymore) || istype(W, /obj/item/weapon/baseballbat) || istype(W, /obj/item/weapon/katana) || istype(W, /obj/item/weapon/twohanded/fireaxe) || istype(W, /obj/item/weapon/chainofcommand)) + if(istype(W, /obj/item/weapon/baton) || istype(W, /obj/item/weapon/sword) || istype(W, /obj/item/weapon/baseballbat) || istype(W, /obj/item/weapon/twohanded/fireaxe) || istype(W, /obj/item/weapon/chainofcommand)) user.visible_message(SPAN_WARNING("[user] bashes [src] with [W]!")) playsound(user.loc, 'sound/effects/shieldbash.ogg', 25, 1) cooldown = world.time diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 6cb9f58aae37..82fdf30f0fc4 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -197,9 +197,9 @@ return TRUE /obj/item/weapon/baton/emp_act(severity) + . = ..() if(bcell) bcell.emp_act(severity) //let's not duplicate code everywhere if we don't have to please. - ..() //secborg stun baton module /obj/item/weapon/baton/robot/attack_self(mob/user) diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index aaa2a33d4e63..efa898ba9937 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -167,7 +167,7 @@ update_icon(user) -/obj/item/weapon/katana/sharp +/obj/item/weapon/sword/katana/sharp name = "absurdly sharp katana" desc = "

That's it. I'm sick of all this \"Masterwork Bastard Sword\" bullshit that's going on in CM-SS13 right now. Katanas deserve much better than that. Much, much better than that.

\

I should know what I'm talking about. I myself commissioned a genuine katana in Japan for 2,400,000 Yen (that's about $20,000) and have been practicing with it for almost 2 years now. I can even cut slabs of solid steel with my katana.

\ @@ -190,7 +190,7 @@ attack_verb = list("sliced", "diced", "cut") -/obj/item/weapon/katana/sharp/attack(mob/living/M, mob/living/user) +/obj/item/weapon/sword/katana/sharp/attack(mob/living/M, mob/living/user) if(flags_item & NOBLUDGEON) return @@ -223,7 +223,7 @@ //if the target also has a katana (and we aren't attacking ourselves), we add some suspense - if( ( istype(M.get_active_hand(), /obj/item/weapon/katana) || istype(M.get_inactive_hand(), /obj/item/weapon/katana) ) && M != user ) + if( ( istype(M.get_active_hand(), /obj/item/weapon/sword/katana) || istype(M.get_inactive_hand(), /obj/item/weapon/sword/katana) ) && M != user ) if(prob(50)) user.visible_message(SPAN_DANGER("[M] and [user] cross blades!")) diff --git a/code/game/objects/prop.dm b/code/game/objects/prop.dm index e59c24b30d5f..c067a9730e70 100644 --- a/code/game/objects/prop.dm +++ b/code/game/objects/prop.dm @@ -11,6 +11,66 @@ w_class = SIZE_SMALL garbage = TRUE +/obj/item/prop/geiger_counter + name = "geiger counter" + desc = "A geiger counter measures the radiation it receives. This type automatically records and transfers any information it reads, provided it has a battery, with no user input required beyond being enabled." + icon = 'icons/obj/items/devices.dmi' + icon_state = "geiger" + item_state = "" + w_class = SIZE_SMALL + flags_equip_slot = SLOT_WAIST + ///Whether the geiger counter is on or off + var/toggled_on = FALSE + ///Iconstate of geiger counter when on + var/enabled_state = "geiger_on" + ///Iconstate of geiger counter when off + var/disabled_state = "geiger" + ///New battery it will spawn with + var/starting_battery = /obj/item/cell/crap + ///Battery inside geiger counter + var/obj/item/cell/battery //It doesn't drain the battery, but it has a battery for emergency use + +/obj/item/prop/geiger_counter/Initialize(mapload, ...) + . = ..() + if(!starting_battery) + return + battery = new starting_battery(src) + +/obj/item/prop/geiger_counter/Destroy() + . = ..() + if(battery) + qdel(battery) + +/obj/item/prop/geiger_counter/attack_self(mob/user) + . = ..() + toggled_on = !toggled_on + if(!battery) + to_chat(user, SPAN_NOTICE("[src] is missing a battery.")) + return + to_chat(user, SPAN_NOTICE("You [toggled_on ? "enable" : "disable"] [src].")) + update_icon() + +/obj/item/prop/geiger_counter/attackby(obj/item/attacking_item, mob/user) + . = ..() + if(!HAS_TRAIT(attacking_item, TRAIT_TOOL_SCREWDRIVER) && !HAS_TRAIT(attacking_item, TRAIT_TOOL_CROWBAR)) + return + + if(!battery) + to_chat(user, SPAN_NOTICE("There is no battery for you to remove.")) + return + to_chat(user, SPAN_NOTICE("You jam [battery] out of [src] with [attacking_item], prying it out irreversibly.")) + user.put_in_hands(battery) + battery = null + update_icon() + +/obj/item/prop/geiger_counter/update_icon() + . = ..() + + if(battery && toggled_on) + icon_state = enabled_state + return + icon_state = disabled_state + /obj/item/prop/tableflag name = "United Americas table flag" icon = 'icons/obj/items/items.dmi' diff --git a/code/game/objects/structures/blocker.dm b/code/game/objects/structures/blocker.dm index 284daf0028aa..f85b1e65fff5 100644 --- a/code/game/objects/structures/blocker.dm +++ b/code/game/objects/structures/blocker.dm @@ -105,9 +105,21 @@ /obj/structure/blocker/forcefield/vehicles types = list(/obj/vehicle/) + +/obj/structure/blocker/forcefield/vehicles/handle_vehicle_bump(obj/vehicle/multitile/multitile_vehicle) + if(multitile_vehicle.vehicle_flags & VEHICLE_BYPASS_BLOCKERS) + return TRUE + return FALSE + /obj/structure/blocker/forcefield/multitile_vehicles types = list(/obj/vehicle/multitile/) + +/obj/structure/blocker/forcefield/multitile_vehicles/handle_vehicle_bump(obj/vehicle/multitile/multitile_vehicle) + if(multitile_vehicle.vehicle_flags & VEHICLE_BYPASS_BLOCKERS) + return TRUE + return FALSE + /obj/structure/blocker/forcefield/human types = list(/mob/living/carbon/human) icon_state = "purple_line" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet/level_red.dm b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet/level_red.dm index 093aac33f7d0..487ffd546d8e 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet/level_red.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet/level_red.dm @@ -59,6 +59,13 @@ . = ..() new /obj/item/storage/box/guncase/m41aMK1(src) +//4 MK1 (with AP) cabinet(using guncase because it fit well here it seem) +/obj/structure/closet/secure_closet/guncabinet/red/cic_armory_mk1_rifle_ap + +/obj/structure/closet/secure_closet/guncabinet/red/cic_armory_mk1_rifle_ap/Initialize() + . = ..() + new /obj/item/storage/box/guncase/m41aMK1AP(src) + // UPPER MEDBAY ARMORY //1 shotgun armory closet 2 guns and 4 mags diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index e290a23a61e9..331cb884bd59 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -30,6 +30,7 @@ return 0 /obj/structure/closet/secure_closet/emp_act(severity) + . = ..() for(var/obj/O in src) O.emp_act(severity) if(!broken) @@ -42,7 +43,6 @@ else src.req_access = list() src.req_access += pick(get_access(ACCESS_LIST_MARINE_MAIN)) - ..() /obj/structure/closet/secure_closet/proc/togglelock(mob/living/user) if(src.opened) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 9f0417ccb372..119615ab7aed 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -12,6 +12,19 @@ throwpass = 1 //prevents moving crates by hurling things at them store_mobs = FALSE var/rigged = 0 + /// Types this crate can be made into + var/list/crate_customizing_types = list( + "Plain" = /obj/structure/closet/crate, + "Weapons" = /obj/structure/closet/crate/weapon, + "Supply" = /obj/structure/closet/crate/supply, + "Ammo" = /obj/structure/closet/crate/ammo, + "Construction" = /obj/structure/closet/crate/construction, + "Explosives" = /obj/structure/closet/crate/explosives, + "Alpha" = /obj/structure/closet/crate/alpha, + "Bravo" = /obj/structure/closet/crate/bravo, + "Charlie" = /obj/structure/closet/crate/charlie, + "Delta" = /obj/structure/closet/crate/delta, + ) /obj/structure/closet/crate/initialize_pass_flags(datum/pass_flags_container/PF) ..() @@ -207,6 +220,7 @@ icon_state = "closed_freezer" icon_opened = "open_freezer" icon_closed = "closed_freezer" + crate_customizing_types = null var/target_temp = T0C - 40 var/cooling_power = 40 diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index 2f2877ba7539..f1b58e6f657b 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -28,9 +28,8 @@ material_sheet = new parts_type(current_turf, 2) // Move the objects back to the turf, above the crate material - for(var/atom/movable/moving_atom in contents) - var/atom/movable/current_atom = contents[1] - current_atom.forceMove(current_turf) + for(var/atom/movable/moving_atom as anything in contents) + moving_atom.forceMove(current_turf) deconstruct(TRUE) diff --git a/code/game/objects/structures/crates_lockers/secure_crates.dm b/code/game/objects/structures/crates_lockers/secure_crates.dm index a308c4c0a21c..28a77e0c81c0 100644 --- a/code/game/objects/structures/crates_lockers/secure_crates.dm +++ b/code/game/objects/structures/crates_lockers/secure_crates.dm @@ -4,6 +4,7 @@ icon_state = "secure_locked_basic" icon_opened = "secure_open_basic" icon_closed = "secure_locked_basic" + crate_customizing_types = null var/icon_locked = "secure_locked_basic" var/icon_unlocked = "secure_unlocked_basic" var/sparks = "securecratesparks" @@ -86,6 +87,7 @@ ..() /obj/structure/closet/crate/secure/emp_act(severity) + . = ..() for(var/obj/O in src) O.emp_act(severity) if(!broken && !opened && prob(50/severity)) @@ -105,7 +107,6 @@ else src.req_access = list() src.req_access += pick(get_access(ACCESS_LIST_MARINE_MAIN)) - ..() //------------------------------------ diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index 7b54f0447fae..e4ee4a1b662b 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -5,13 +5,15 @@ icon_state = "extinguisher" anchored = TRUE density = FALSE - var/obj/item/tool/extinguisher/has_extinguisher = new/obj/item/tool/extinguisher + var/obj/item/tool/extinguisher/has_extinguisher var/opened = 0 var/base_icon /obj/structure/extinguisher_cabinet/Initialize() . = ..() base_icon = initial(icon_state) + has_extinguisher = new /obj/item/tool/extinguisher() + has_extinguisher.forceMove(src) /obj/structure/extinguisher_cabinet/lifeboat name = "extinguisher cabinet" @@ -21,15 +23,15 @@ /obj/structure/extinguisher_cabinet/alt icon_state = "extinguisher_alt" -/obj/structure/extinguisher_cabinet/attackby(obj/item/O, mob/user) +/obj/structure/extinguisher_cabinet/attackby(obj/item/item, mob/user) if(isrobot(user)) return - if(istype(O, /obj/item/tool/extinguisher)) + if(istype(item, /obj/item/tool/extinguisher)) if(!has_extinguisher && opened) user.drop_held_item() - contents += O - has_extinguisher = O - to_chat(user, SPAN_NOTICE("You place [O] in [src].")) + item.forceMove(src) + has_extinguisher = item + to_chat(user, SPAN_NOTICE("You place [item] in [src].")) else opened = !opened else @@ -45,7 +47,7 @@ user.put_in_hands(has_extinguisher) to_chat(user, SPAN_NOTICE("You take [has_extinguisher] from [src].")) has_extinguisher = null - opened = 1 + opened = TRUE else opened = !opened update_icon() diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 9c1f46de50d5..b1e950dd18f0 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -72,6 +72,7 @@ PLANT_CUT_MACHETE = 3 = Needs at least a machete to be cut down addtimer(CALLBACK(src, PROC_REF(burn_up)), spread_time + 5 SECONDS) /obj/structure/flora/proc/spread_fire() + SIGNAL_HANDLER for(var/D in cardinal) //Spread fire var/turf/T = get_step(src.loc, D) if(T) @@ -82,6 +83,7 @@ PLANT_CUT_MACHETE = 3 = Needs at least a machete to be cut down new /obj/flamer_fire(T, create_cause_data("wildfire")) /obj/structure/flora/proc/burn_up() + SIGNAL_HANDLER new /obj/effect/decal/cleanable/dirt(loc) if(center) new /obj/effect/decal/cleanable/dirt(loc) //Produces more ash at the center @@ -717,7 +719,7 @@ ICEY GRASS. IT LOOKS LIKE IT'S MADE OF ICE. //hatchets and shiet can clear away undergrowth if(I && (I.sharp >= IS_SHARP_ITEM_ACCURATE) && !stump) var/damage = rand(2,5) - if(istype(I,/obj/item/weapon/claymore/mercsword)) + if(istype(I,/obj/item/weapon/sword)) damage = rand(8,18) if(indestructable) //this bush marks the edge of the map, you can't destroy it diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index e719359ab439..6cd6a5cd0300 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -173,6 +173,14 @@ return do_reinforced_wall(W, user) if(STATE_DISPLACED) if(HAS_TRAIT(W, TRAIT_TOOL_CROWBAR)) + var/turf/open/floor = loc + if(!floor.allow_construction) + to_chat(user, SPAN_WARNING("The girder must be secured on a proper surface!")) + return + var/obj/structure/tunnel/tunnel = locate(/obj/structure/tunnel) in loc + if(tunnel) + to_chat(user, SPAN_WARNING("The girder cannot be secured on a tunnel!")) + return playsound(loc, 'sound/items/Crowbar.ogg', 25, 1) to_chat(user, SPAN_NOTICE("Now securing the girder...")) if(!do_after(user, 40 * user.get_skill_duration_multiplier(SKILL_CONSTRUCTION), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index dc8cf08d13f1..b3fb2423008a 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -113,7 +113,7 @@ else . = ..() -/obj/structure/morgue/relaymove(mob/user) +/obj/structure/morgue/relaymove(mob/living/user) if(user.is_mob_incapacitated()) return if(exit_stun) diff --git a/code/game/objects/structures/props.dm b/code/game/objects/structures/props.dm index bd5610487ea0..f465e1535d68 100644 --- a/code/game/objects/structures/props.dm +++ b/code/game/objects/structures/props.dm @@ -805,14 +805,14 @@ /obj/structure/prop/brazier/campfire/attackby(obj/item/attacking_item, mob/user) if(!istype(attacking_item, /obj/item/stack/sheet/wood)) - to_chat(SPAN_NOTICE("You cannot fuel [src] with [attacking_item].")) + to_chat(user, SPAN_NOTICE("You cannot fuel [src] with [attacking_item].")) return var/obj/item/stack/sheet/wood/fuel = attacking_item if(remaining_fuel >= initial(remaining_fuel)) to_chat(user, SPAN_NOTICE("You cannot fuel [src] further.")) return if(!fuel.use(1)) - to_chat(SPAN_NOTICE("You do not have enough [attacking_item] to fuel [src].")) + to_chat(user, SPAN_NOTICE("You do not have enough [attacking_item] to fuel [src].")) return visible_message(SPAN_NOTICE("[user] fuels [src] with [fuel].")) remaining_fuel++ diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index ec277929facb..adabf0c54141 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -570,7 +570,7 @@ /obj/structure/sign/ROsign name = "\improper USCM Requisitions Office Guidelines" - desc = " 1. You are not entitled to service or equipment. Attachments are a privilege, not a right.\n 2. You must be fully dressed to obtain service. Cyrosleep underwear is non-permissible.\n 3. The Requsitions Officer has the final say and the right to decline service. Only the Acting Commanding Officer may override their decisions.\n 4. Please treat your Requsitions staff with respect. They work hard." + desc = " 1. You are not entitled to service or equipment. Attachments are a privilege, not a right.\n 2. You must be fully dressed to obtain service. Cryosleep underwear is non-permissible.\n 3. The Quartermaster has the final say and the right to decline service. Only the Acting Commanding Officer may override their decisions.\n 4. Please treat your Requsitions staff with respect. They work hard." icon_state = "roplaque" /obj/structure/sign/prop1 diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 7979994915f4..bc3b4ad7f4d0 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -404,7 +404,17 @@ var/global/list/activated_medevac_stretchers = list() //bedroll /obj/structure/bed/bedroll - name = "bedroll" - desc = "bedroll" + name = "unfolded bedroll" + desc = "Perfect for those long missions, when there's nowhere else to sleep, you remembered to bring at least one thing of comfort." + icon = 'icons/monkey_icos.dmi' icon_state = "bedroll_o" + buckling_y = 0 + foldabletype = /obj/item/roller/bedroll + accepts_bodybag = FALSE + +/obj/item/roller/bedroll + name = "folded bedroll" + desc = "A standard issue USCMC bedroll, They've been in service for as long as you can remember. The tag on it states to unfold it before rest, but who needs rules anyway, right?" icon = 'icons/monkey_icos.dmi' + icon_state = "bedroll" + rollertype = /obj/structure/bed/bedroll diff --git a/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm b/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm index 7a4274c2c16e..6375fcd13823 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/xeno_nest.dm @@ -53,7 +53,7 @@ current_mob.pixel_y = buckling_y["[dir]"] current_mob.pixel_x = buckling_x["[dir]"] current_mob.dir = turn(dir, 180) - current_mob.density = FALSE + ADD_TRAIT(current_mob, TRAIT_UNDENSE, XENO_NEST_TRAIT) pixel_y = buckling_y["[dir]"] pixel_x = buckling_x["[dir]"] if(dir == SOUTH) @@ -67,7 +67,7 @@ current_mob.pixel_y = initial(buckled_mob.pixel_y) current_mob.pixel_x = initial(buckled_mob.pixel_x) - current_mob.density = !(current_mob.lying || current_mob.stat == DEAD) + REMOVE_TRAIT(current_mob, TRAIT_UNDENSE, XENO_NEST_TRAIT) if(dir == SOUTH) current_mob.layer = initial(current_mob.layer) if(!ishuman(current_mob)) diff --git a/code/game/objects/structures/surface.dm b/code/game/objects/structures/surface.dm index efc69002424f..13a81af2dc3d 100644 --- a/code/game/objects/structures/surface.dm +++ b/code/game/objects/structures/surface.dm @@ -1,159 +1,20 @@ //Surface structures are structures that can have items placed on them /obj/structure/surface health = 100 - var/list/update_types = list( - /obj/item/reagent_container/glass, - /obj/item/storage, - /obj/item/reagent_container/food/snacks - ) - //add items there that behave like structures for whatever dumb reason - var/list/blacklisted_item_types = list( - /obj/item/device/radio/intercom, - /obj/item/device/sentry_computer - ) -/obj/structure/surface/Initialize() - . = ..() - return INITIALIZE_HINT_LATELOAD - -/obj/structure/surface/LateInitialize() - attach_all() - update_icon() - -/obj/structure/surface/Destroy() - detach_all() - . = ..() - -/obj/structure/surface/ex_act(severity, direction, datum/cause_data/cause_data) - health -= severity - if(health <= 0) - var/location = get_turf(src) - handle_debris(severity, direction) - detach_all() - for(var/obj/item/O in loc) - O.explosion_throw(severity, direction) - qdel(src) - if(prob(66)) - create_shrapnel(location, rand(1,4), direction, , /datum/ammo/bullet/shrapnel/light, cause_data) - return TRUE - -/obj/structure/surface/proc/attach_all() - for(var/obj/item/O in loc) - if(in_blacklist(O)) - continue - attach_item(O, FALSE) - draw_item_overlays() - -/obj/structure/surface/proc/in_blacklist(obj/item/O) - for(var/allowed_type in blacklisted_item_types) - if(istype(O, allowed_type)) - return TRUE - return FALSE - -/obj/structure/surface/proc/attach_item(obj/item/O, update = TRUE) - if(!O) +/obj/structure/surface/attackby(obj/item/attacking_item, mob/user, click_data) + if(!user.drop_inv_item_to_loc(attacking_item, loc)) return - if(O.luminosity) //it can't make light as an overlay - return - O.forceMove(src) - RegisterSignal(O, COMSIG_ATOM_DECORATED, PROC_REF(decorate_update)) - if(update) - draw_item_overlays() - -/obj/structure/surface/proc/detach_item(obj/item/O) - O.scatter_item() - UnregisterSignal(O, COMSIG_ATOM_DECORATED) - draw_item_overlays() - return - -/obj/structure/surface/proc/decorate_update(obj/item/O) - SIGNAL_HANDLER - draw_item_overlays() -/obj/structure/surface/proc/detach_all() - overlays.Cut() - for(var/obj/item/O in contents) - UnregisterSignal(O, COMSIG_ATOM_DECORATED) - O.forceMove(loc) + auto_align(attacking_item, click_data) + user.next_move = world.time + 2 + return TRUE -/obj/structure/surface/proc/get_item(list/click_data) - var/i = LAZYLEN(contents) - if(!click_data) - return - if(i < 1) - return FALSE - for(i, i >= 1, i--)//starting from the end because that's where the topmost is - var/obj/item/O = contents[i] - var/bounds_x = text2num(click_data["icon-x"])-1 - O.pixel_x - var/bounds_y = text2num(click_data["icon-y"])-1 - O.pixel_y - if(bounds_x < 0 || bounds_y < 0) - continue - var/icon/I = icon(O.icon, O.icon_state) - var/p = I.GetPixel(bounds_x, bounds_y) - if(p) - return O - return FALSE - -/obj/structure/surface/proc/draw_item_overlays() - overlays.Cut() - for(var/obj/item/O in contents) - var/image/I = image(O.icon) - I.appearance = O.appearance - I.appearance_flags |= RESET_COLOR - I.overlays = O.overlays - LAZYADD(overlays, I) - -/obj/structure/surface/clicked(mob/user, list/mods) - if(mods["shift"] && !mods["middle"]) - var/obj/item/O = get_item(mods) - if(!O) - return ..() - if(O.can_examine(user)) - O.examine(user) - return TRUE - ..() - -/obj/structure/surface/proc/try_to_open_container(mob/user, mods) - if(!Adjacent(user)) - return - - if(ishuman(user) || isrobot(user)) - var/obj/item/O = get_item(mods) - if(O && isstorage(O)) - var/obj/item/storage/S = O - S.open(usr) - return TRUE - -/obj/structure/surface/attack_hand(mob/user, click_data) - . = ..() - if(click_data && click_data["alt"]) - return - var/obj/item/O = get_item(click_data) - if(!O) - return - O.attack_hand(user) - if(!LAZYISIN(contents, O))//in case attack_hand did not pick up the item - detach_item(O) - -/obj/structure/surface/attackby(obj/item/W, mob/user, click_data) - var/obj/item/O = get_item(click_data) - if(!O || click_data["ctrl"])//holding the ctrl key will force it to place the object - // Placing stuff on tables - if(user.drop_inv_item_to_loc(W, loc)) - auto_align(W, click_data) - user.next_move = world.time + 2 - return TRUE - else if(!O.attackby(W, user)) - W.afterattack(O, user, TRUE) - for(var/type in update_types) - if(istype(O, type)) - draw_item_overlays() - -/obj/structure/surface/proc/auto_align(obj/item/W, click_data) - if(!W.center_of_mass) // Clothing, material stacks, generally items with large sprites where exact placement would be unhandy. - W.pixel_x = rand(-W.randpixel, W.randpixel) - W.pixel_y = rand(-W.randpixel, W.randpixel) - W.pixel_z = 0 +/obj/structure/surface/proc/auto_align(obj/item/new_item, click_data) + if(!new_item.center_of_mass) // Clothing, material stacks, generally items with large sprites where exact placement would be unhandy. + new_item.pixel_x = rand(-new_item.randpixel, new_item.randpixel) + new_item.pixel_y = rand(-new_item.randpixel, new_item.randpixel) + new_item.pixel_z = 0 return if(!click_data) @@ -169,16 +30,8 @@ var/cell_x = Clamp(round(mouse_x/CELLSIZE), 0, CELLS-1) // Ranging from 0 to CELLS-1 var/cell_y = Clamp(round(mouse_y/CELLSIZE), 0, CELLS-1) - var/list/center = cached_key_number_decode(W.center_of_mass) - - W.pixel_x = (CELLSIZE * (cell_x + 0.5)) - center["x"] - W.pixel_y = (CELLSIZE * (cell_y + 0.5)) - center["y"] - W.pixel_z = 0 - - if(!(W.flags_item & NOTABLEMERGE)) - attach_item(W) + var/list/center = cached_key_number_decode(new_item.center_of_mass) -/obj/structure/surface/MouseDrop(atom/over) - . = ..() - if(over == usr && usr && usr.client && usr.client.lmb_last_mousedown_mods) - return try_to_open_container(usr, usr.client.lmb_last_mousedown_mods) + new_item.pixel_x = (CELLSIZE * (cell_x + 0.5)) - center["x"] + new_item.pixel_y = (CELLSIZE * (cell_y + 0.5)) - center["y"] + new_item.pixel_z = 0 diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index db3ce98339a3..8d6441293f86 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -434,8 +434,6 @@ verbs -= /obj/structure/surface/table/verb/do_flip verbs += /obj/structure/surface/table/proc/do_put - detach_all() - var/list/targets = list(get_step(src, dir), get_step(src, turn(dir, 45)), get_step(src, turn(dir, -45))) for(var/atom/movable/movable_on_table in get_turf(src)) if(!movable_on_table.anchored) @@ -479,7 +477,6 @@ var/obj/structure/surface/table/T = locate() in get_step(src.loc,D) if(T && T.flipped && T.dir == src.dir) T.unflip() - attach_all() update_icon() update_adjacent() diff --git a/code/game/objects/structures/vulture_spotter.dm b/code/game/objects/structures/vulture_spotter.dm index 50505ab239b8..44efd5ce84ea 100644 --- a/code/game/objects/structures/vulture_spotter.dm +++ b/code/game/objects/structures/vulture_spotter.dm @@ -92,7 +92,7 @@ user.lighting_alpha = 127 user.sync_lighting_plane_alpha() user.overlay_fullscreen("vulture_spotter", /atom/movable/screen/fullscreen/vulture/spotter) - user.freeze() + ADD_TRAIT(user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Vulture spotter")) user.status_flags |= IMMOBILE_ACTION user.visible_message(SPAN_NOTICE("[user] looks through [src]."),SPAN_NOTICE("You look through [src], ready to go!")) user.forceMove(loc) @@ -105,7 +105,7 @@ /obj/structure/vulture_spotter_tripod/on_unset_interaction(mob/user) user.status_flags &= ~IMMOBILE_ACTION user.visible_message(SPAN_NOTICE("[user] looks up from [src]."),SPAN_NOTICE("You look up from [src].")) - user.unfreeze() + REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Vulture spotter")) user.reset_view(null) user.Move(get_step(src, reverse_direction(src.dir))) user.client?.change_view(world_view_size, src) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index e8f40c1d52b3..422a42c66541 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -327,7 +327,7 @@ var/datum/controller/supply/supply_controller = new() M.count_niche_stat(STATISTICS_NICHE_CRATES) playsound(C.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh - var/obj/structure/droppod/supply/pod = new() + var/obj/structure/droppod/supply/pod = new(null, C) C.forceMove(pod) pod.launch(T) visible_message("[icon2html(src, viewers(src))] [SPAN_BOLDNOTICE("'[C.name]' supply drop launched! Another launch will be available in five minutes.")]") @@ -1315,6 +1315,14 @@ var/datum/controller/supply/supply_controller = new() /datum/vehicle_order/tank/has_vehicle_lock() return +/datum/vehicle_order/tank/broken + name = "Smashed M34A2 Longstreet Light Tank" + ordered_vehicle = /obj/effect/vehicle_spawner/tank/hull/broken + +/datum/vehicle_order/tank/plain + name = "M34A2 Longstreet Light Tank" + ordered_vehicle = /obj/effect/vehicle_spawner/tank + /datum/vehicle_order/apc name = "M577 Armored Personnel Carrier" ordered_vehicle = /obj/effect/vehicle_spawner/apc/decrepit @@ -1327,18 +1335,19 @@ var/datum/controller/supply/supply_controller = new() name = "M577-CMD Armored Personnel Carrier" ordered_vehicle = /obj/effect/vehicle_spawner/apc_cmd/decrepit +/datum/vehicle_order/apc/empty + name = "Barebones M577 Armored Personal Carrier" + ordered_vehicle = /obj/effect/vehicle_spawner/apc/unarmed/broken + /obj/structure/machinery/computer/supplycomp/vehicle/Initialize() . = ..() vehicles = list( - /datum/vehicle_order/apc, - /datum/vehicle_order/apc/med, - /datum/vehicle_order/apc/cmd, + new /datum/vehicle_order/apc(), + new /datum/vehicle_order/apc/med(), + new /datum/vehicle_order/apc/cmd(), ) - for(var/order as anything in vehicles) - new order - if(!VehicleElevatorConsole) VehicleElevatorConsole = src @@ -1408,6 +1417,7 @@ var/datum/controller/supply/supply_controller = new() return if(!is_admin_level(SSshuttle.vehicle_elevator.z)) + to_chat(usr, SPAN_WARNING("The elevator needs to be in the cargo bay dock to call a vehicle up. Ask someone to send it away.")) return if(ismaintdrone(usr)) diff --git a/code/game/turfs/floor_types.dm b/code/game/turfs/floor_types.dm index 4e47fd004f74..e9c6b9a2048e 100644 --- a/code/game/turfs/floor_types.dm +++ b/code/game/turfs/floor_types.dm @@ -203,6 +203,13 @@ icon_state = "default" plating_type = /turf/open/floor/plating/almayer +/// Admin level thunderdome floor. Doesn't get damaged by explosions and such for pristine testing +/turf/open/floor/tdome + icon = 'icons/turf/almayer.dmi' + icon_state = "plating" + plating_type = /turf/open/floor/tdome + hull_floor = TRUE + //Cargo elevator /turf/open/floor/almayer/empty name = "empty space" diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index a4781e1a6609..93eb45c3b79c 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -185,6 +185,7 @@ name = "cave" icon = 'icons/turf/floors/bigred.dmi' icon_state = "mars_cave_1" + is_groundmap_turf = TRUE /turf/open/mars_cave/Initialize(mapload, ...) @@ -283,6 +284,7 @@ name = "ground dirt" icon = 'icons/turf/ground_map.dmi' icon_state = "desert" + is_groundmap_turf = TRUE /turf/open/gm/attackby(obj/item/I, mob/user) @@ -646,6 +648,7 @@ baseturfs = /turf/open/gm/riverdeep supports_surgery = FALSE minimap_color = MINIMAP_WATER + is_groundmap_turf = FALSE // Not real ground /turf/open/gm/riverdeep/Initialize(mapload, ...) @@ -724,6 +727,7 @@ allow_construction = FALSE var/bushes_spawn = 1 var/plants_spawn = 1 + is_groundmap_turf = TRUE name = "wet grass" desc = "Thick, long, wet grass." icon = 'icons/turf/floors/jungle.dmi' diff --git a/code/game/turfs/walls/wall_types.dm b/code/game/turfs/walls/wall_types.dm index 1b4091eb2aab..f976da220b29 100644 --- a/code/game/turfs/walls/wall_types.dm +++ b/code/game/turfs/walls/wall_types.dm @@ -28,15 +28,23 @@ /obj/structure/machinery/cm_vending/sorted/cargo_guns/cargo/blend, ) + /// The type of wall decoration we use, to avoid the wall changing icon all the time + var/decoration_type + +/turf/closed/wall/almayer/Initialize(mapload, ...) + if(!special_icon && prob(20)) + decoration_type = rand(0,3) + return ..() + /turf/closed/wall/almayer/update_icon() - ..() - if(special_icon) - return + if(decoration_type == null) + return ..() if(neighbors_list in list(EAST|WEST)) - var/r1 = rand(0,10) //Make a random chance for this to happen - var/r2 = rand(0,3) // Which wall if we do choose it - if(r1 >= 9) - overlays += image(icon, icon_state = "almayer_deco_wall[r2]") + special_icon = TRUE + icon_state = "almayer_deco_wall[decoration_type]" + else // Wall connection was broken, return to normality + special_icon = FALSE + return ..() /turf/closed/wall/almayer/take_damage(dam, mob/M) var/damage_check = max(0, damage + dam) diff --git a/code/game/verbs/who.dm b/code/game/verbs/who.dm index 8a249d297cbe..faa857f8518f 100644 --- a/code/game/verbs/who.dm +++ b/code/game/verbs/who.dm @@ -160,7 +160,7 @@ if(CONFIG_GET(flag/show_manager)) LAZYSET(mappings, "Management", R_PERMISSIONS) if(CONFIG_GET(flag/show_devs)) - LAZYSET(mappings, "Maintainers", R_PROFILER) + LAZYSET(mappings, "Maintainers", R_PROFILER) LAZYSET(mappings, "Admins", R_ADMIN) if(CONFIG_GET(flag/show_mods)) LAZYSET(mappings, "Moderators", R_MOD) diff --git a/code/game/world.dm b/code/game/world.dm index fce40ca468ae..f5388ed6fd52 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -71,8 +71,6 @@ var/list/reboot_sfx = file2list("config/reboot_sfx.txt") RoleAuthority = new /datum/authority/branch/role() to_world(SPAN_DANGER("\b Job setup complete")) - if(!EvacuationAuthority) EvacuationAuthority = new - initiate_minimap_icons() change_tick_lag(CONFIG_GET(number/ticklag)) @@ -91,8 +89,8 @@ var/list/reboot_sfx = file2list("config/reboot_sfx.txt") update_status() //Scramble the coords obsfucator - obfs_x = rand(-500, 500) //A number between -100 and 100 - obfs_y = rand(-500, 500) //A number between -100 and 100 + GLOB.obfs_x = rand(-500, 500) //A number between -100 and 100 + GLOB.obfs_y = rand(-500, 500) //A number between -100 and 100 spawn(3000) //so we aren't adding to the round-start lag if(CONFIG_GET(flag/ToRban)) @@ -174,11 +172,6 @@ var/world_topic_spam_protect_time = world.timeofday response["response"] = "Payload too large" return json_encode(response) - if(SSfail_to_topic?.IsRateLimited(addr)) - response["statuscode"] = 429 - response["response"] = "Rate limited" - return json_encode(response) - var/logging = CONFIG_GET(flag/log_world_topic) var/topic_decoded = rustg_url_decode(T) if(!rustg_json_is_valid(topic_decoded)) diff --git a/code/global.dm b/code/global.dm index bdde529a9af8..e329cbdd00d5 100644 --- a/code/global.dm +++ b/code/global.dm @@ -153,14 +153,6 @@ var/list/nato_phonetic_alphabet = list("Alpha", "Bravo", "Charlie", "Delta", "Ec var/distress_cancel = 0 var/destroy_cancel = 0 -//Coordinate obsfucator -//Used by the rangefinders and linked systems to prevent coords collection/prefiring - -/// A number between -500 and 500. -var/global/obfs_x = 0 -/// A number between -500 and 500. -var/global/obfs_y = 0 - // Which lobby art is on display // This is updated by the lobby art turf when it initializes var/displayed_lobby_art = -1 diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 5042167023e6..38b63b94570c 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -261,7 +261,7 @@ if("Remove") if(!GLOB.trait_name_map) GLOB.trait_name_map = generate_trait_name_map() - for(var/trait in D.status_traits) + for(var/trait in D._status_traits) var/name = GLOB.trait_name_map[trait] || trait available_traits[name] = trait @@ -282,7 +282,7 @@ if("All") source = null if("Specific") - source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D.status_traits[chosen_trait]) + source = input("Source to be removed","Trait Remove/Add") as null|anything in sort_list(D._status_traits[chosen_trait]) if(!source) return REMOVE_TRAIT(D,chosen_trait,source) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7d9127313094..207eebd3e409 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -69,6 +69,7 @@ var/list/admin_verbs_default = list( /client/proc/toggle_ares_ping, /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, ) var/list/admin_verbs_admin = list( @@ -99,10 +100,8 @@ var/list/admin_verbs_ban = list( ) var/list/admin_verbs_sounds = list( - /client/proc/play_web_sound, - /client/proc/play_sound, - /client/proc/stop_web_sound, - /client/proc/stop_sound, + /client/proc/play_admin_sound, + /client/proc/stop_admin_sound, /client/proc/cmd_admin_vox_panel ) diff --git a/code/modules/admin/fax_templates.dm b/code/modules/admin/fax_templates.dm index 91b23abb2422..459ab675d3a3 100644 --- a/code/modules/admin/fax_templates.dm +++ b/code/modules/admin/fax_templates.dm @@ -1,11 +1,13 @@ /proc/generate_templated_fax(show_wy_logo, fax_header, fax_subject, addressed_to, message_body, sent_by, sent_title, sent_department) + var/datum/asset/asset = get_asset_datum(/datum/asset/simple/paper) + var/dat = "" dat += "