diff --git a/code/ATMOSPHERICS/components/shutoff.dm b/code/ATMOSPHERICS/components/shutoff.dm index 55d11627777..ea1f9fde705 100644 --- a/code/ATMOSPHERICS/components/shutoff.dm +++ b/code/ATMOSPHERICS/components/shutoff.dm @@ -26,7 +26,7 @@ GLOBAL_LIST_EMPTY(shutoff_valves) /obj/machinery/atmospherics/valve/shutoff/Destroy() GLOB.shutoff_valves -= src - ..() + . = ..() /obj/machinery/atmospherics/valve/shutoff/attack_ai(mob/user as mob) return src.attack_hand(user) diff --git a/code/__defines/_reagents.dm b/code/__defines/_reagents.dm index bb5da52505c..7759ba3cc30 100644 --- a/code/__defines/_reagents.dm +++ b/code/__defines/_reagents.dm @@ -69,6 +69,8 @@ #define REAGENT_ID_POTASSIUM "potassium" #define REAGENT_RADIUM "Radium" #define REAGENT_ID_RADIUM "radium" +#define REAGENT_CONCENTRATEDRADIUM "Concentrated Radium" +#define REAGENT_ID_CONCENTRATEDRADIUM "concentrated_radium" #define REAGENT_SILICON "Silicon" #define REAGENT_ID_SILICON "silicon" #define REAGENT_SODIUM "Sodium" @@ -1302,6 +1304,8 @@ #define REAGENT_ID_SIFSAP "sifsap" #define REAGENT_STOMACID "Digestive acid" #define REAGENT_ID_STOMACID "stomacid" +#define REAGENT_DIETSTOMACID "Diluted digestive acid" +#define REAGENT_ID_DIETSTOMACID "diet_stomacid" #define REAGENT_THERMITEV "Pyrotoxin" #define REAGENT_ID_THERMITEV "thermite_v" #define REAGENT_CONDENSEDCAPSAICINV "Irritant toxin" @@ -1353,3 +1357,18 @@ #define REAGENT_ID_SLIMEBONEFIXER "slime_bone_fixer" #define REAGENT_SLIMEORGANFIXER "Agent C" #define REAGENT_ID_SLIMEORGANFIXER "slime_organ_fixer" + +// Vore Belly Options + +#define REAGENT_ID_WATER_BELLY "water_liquidbelly" +#define REAGENT_ID_MILK_BELLY "milk_liquidbelly" +#define REAGENT_ID_CREAM_BELLY "cream_liquidbelly" +#define REAGENT_ID_HONEY_BELLY "honey_liquidbelly" +#define REAGENT_ID_CHERRYJELLY_BELLY "cherry_liquidbelly" +#define REAGENT_ID_STOMACID_BELLY "stomacid_liquidbelly" +#define REAGENT_ID_DIETSTOMACID_BELLY "diet_stomacid_liquidbelly" +#define REAGENT_ID_CLEANER_BELLY "cleaner_liquidbelly" +#define REAGENT_ID_LUBE_BELLY "lube_liquidbelly" +#define REAGENT_ID_BIOMASS_BELLY "biomass_liquidbelly" +#define REAGENT_ID_CONCENTRATEDRADIUM_BELLY "cradium_liquidbelly" +#define REAGENT_ID_TRICORDRAZINE_BELLY "tricordrazine_liquidbelly" diff --git a/code/__defines/belly_messages.dm b/code/__defines/belly_messages.dm new file mode 100644 index 00000000000..69eaff17d50 --- /dev/null +++ b/code/__defines/belly_messages.dm @@ -0,0 +1,83 @@ +// Vore belly options + +#define STRUGGLE_OUTSIDE "smo" +#define STRUGGLE_INSIDE "smi" + +#define ABSORBED_STRUGGLE_OUSIDE "asmo" +#define ABSORBED_STRUGGLE_INSIDE "asmi" + +#define ESCAPE_ATTEMPT_OWNER "escao" +#define ESCAPE_ATTEMPT_PREY "escap" + +#define ESCAPE_OWNER "esco" +#define ESCAPE_PREY "escp" +#define ESCAPE_OUTSIDE "escout" + +#define ESCAPE_ITEM_OWNER "escio" +#define ESCAPE_ITEM_PREY "escip" +#define ESCAPE_ITEM_OUTSIDE "esciout" + +#define ESCAPE_FAIL_OWNER "escfo" +#define ESCAPE_FAIL_PREY "escfp" + +#define ABSORBED_ESCAPE_ATTEMPT_OWNER "aescao" +#define ABSORBED_ESCAPE_ATTEMPT_PREY "aescap" + +#define ABSORBED_ESCAPE_OWNER "aesco" +#define ABSORBED_ESCAPE_PREY "aescp" +#define ABSORBED_ESCAPE_OUTSIDE "aescout" + +#define FULL_ABSORBED_ESCAPE_OWNER "aescfo" +#define FULL_ABSORBED_ESCAPE_PREY "aescfp" + +#define PRIMARY_TRANSFER_OWNER "trnspo" +#define PRIMARY_TRANSFER_PREY "trnspp" + +#define SECONDARY_TRANSFER_OWNER "trnsso" +#define SECONDARY_TRANSFER_PREY "trnssp" + +#define PRIMARY_AUTO_TRANSFER_OWNER "atrnspo" +#define PRIMARY_AUTO_TRANSFER_PREY "atrnspp" + +#define SECONDARY_AUTO_TRANSFER_OWNER "atrnsso" +#define SECONDARY_AUTO_TRANSFER_PREY "atrnssp" + +#define DIGEST_CHANCE_OWNER "stmodo" +#define DIGEST_CHANCE_PREY "stmodp" + +#define ABSORB_CHANCE_OWNER "stmoao" +#define ABSORB_CHANCE_PREY "stmoap" + +#define DIGEST_OWNER "dmo" +#define DIGEST_PREY "dmp" + +#define EXAMINES "em" +#define EXAMINES_ABSORBED "ema" + +#define ABSORB_OWNER "amo" +#define ABSORB_PREY "amp" + +#define UNABSORBS_OWNER "uamo" +#define UNABSORBS_PREY "uamp" + +#define BELLY_MODE_DIGEST "im_digest" +#define BELLY_MODE_HOLD "im_hold" +#define BELLY_MODE_HOLD_ABSORB "im_holdabsorbed" +#define BELLY_MODE_ABSORB "im_absorb" +#define BELLY_MODE_HEAL "im_heal" +#define BELLY_MODE_DRAIN "im_drain" +#define BELLY_MODE_STEAL "im_steal" +#define BELLY_MODE_EGG "im_egg" +#define BELLY_MODE_SHRINK "im_shrink" +#define BELLY_MODE_GROW "im_grow" +#define BELLY_MODE_UNABSORB "im_unabsorb" + +#define VB_MESSAGE_SANIRY(type) ASSERT(type == STRUGGLE_OUTSIDE || type == STRUGGLE_INSIDE || type == ABSORBED_STRUGGLE_OUSIDE || type == ABSORBED_STRUGGLE_INSIDE || type == ESCAPE_ATTEMPT_OWNER || type == ESCAPE_ATTEMPT_PREY ||\ + type == ESCAPE_PREY || type == ESCAPE_OWNER || type == ESCAPE_OUTSIDE || type == ESCAPE_ITEM_PREY || type == ESCAPE_ITEM_OWNER || type == ESCAPE_ITEM_OUTSIDE || type == ESCAPE_FAIL_PREY ||\ + type == ESCAPE_FAIL_OWNER || type == ABSORBED_ESCAPE_ATTEMPT_OWNER || type == ABSORBED_ESCAPE_ATTEMPT_PREY || type == ABSORBED_ESCAPE_PREY || type == ABSORBED_ESCAPE_OWNER ||\ + type == ABSORBED_ESCAPE_OUTSIDE || type == FULL_ABSORBED_ESCAPE_PREY || type == FULL_ABSORBED_ESCAPE_OWNER || type == PRIMARY_TRANSFER_PREY || type == PRIMARY_TRANSFER_OWNER ||\ + type == SECONDARY_TRANSFER_PREY || type == SECONDARY_TRANSFER_OWNER || type == PRIMARY_AUTO_TRANSFER_PREY || type == PRIMARY_AUTO_TRANSFER_OWNER || type == SECONDARY_AUTO_TRANSFER_PREY ||\ + type == SECONDARY_AUTO_TRANSFER_OWNER || type == DIGEST_CHANCE_PREY || type == DIGEST_CHANCE_OWNER || type == ABSORB_CHANCE_PREY || type == ABSORB_CHANCE_OWNER || type == DIGEST_OWNER ||\ + type == DIGEST_PREY || type == ABSORB_OWNER || type == ABSORB_PREY || type == UNABSORBS_OWNER || type == UNABSORBS_PREY || type == EXAMINES || type == EXAMINES_ABSORBED ||\ + type == BELLY_MODE_DIGEST || type == BELLY_MODE_HOLD || type == BELLY_MODE_HOLD_ABSORB || type == BELLY_MODE_ABSORB || type == BELLY_MODE_HEAL || type == BELLY_MODE_DRAIN ||\ + type == BELLY_MODE_STEAL || type == BELLY_MODE_EGG || type == BELLY_MODE_SHRINK || type == BELLY_MODE_GROW || type == BELLY_MODE_UNABSORB) diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm index 266d2f583af..38aefcd8703 100644 --- a/code/__defines/belly_modes_vr.dm +++ b/code/__defines/belly_modes_vr.dm @@ -22,11 +22,15 @@ #define DM_FLAG_JAMSENSORS 0x20 #define DM_FLAG_FORCEPSAY 0x40 #define DM_FLAG_SPARELIMB 0x80 +#define DM_FLAG_SLOWBODY 0x100 +#define DM_FLAG_MUFFLEITEMS 0x200 +#define DM_FLAG_TURBOMODE 0x400 //Item related modes #define IM_HOLD "Hold" #define IM_DIGEST_FOOD "Digest (Food Only)" #define IM_DIGEST "Digest" +#define IM_DIGEST_PARALLEL "Digest (Dispersed Damage)" //Stance for hostile mobs to be in while devouring someone. #define HOSTILE_STANCE_EATING 99 @@ -49,3 +53,40 @@ #define DM_FLAG_VORESPRITE_TAIL 0x2 #define DM_FLAG_VORESPRITE_MARKING 0x4 #define DM_FLAG_VORESPRITE_ARTICLE 0x8 + +//Belly Reagents mode flags +#define DM_FLAG_REAGENTSNUTRI 0x1 +#define DM_FLAG_REAGENTSDIGEST 0x2 +#define DM_FLAG_REAGENTSABSORB 0x4 +#define DM_FLAG_REAGENTSDRAIN 0x8 + +//For belly fullscreen shennanigans outside of bellies, due to Life() clearing belly fullscreens outside of bellies. +#define ATOM_BELLY_FULLSCREEN "belly_atom_vfx" + +//Auto-transfer mob flags +#define AT_FLAG_CREATURES 0x1 +#define AT_FLAG_ABSORBED 0x2 +#define AT_FLAG_CARBON 0x4 +#define AT_FLAG_SILICON 0x8 +#define AT_FLAG_MOBS 0x10 +#define AT_FLAG_ANIMALS 0x20 +#define AT_FLAG_MICE 0x40 +#define AT_FLAG_DEAD 0x80 +#define AT_FLAG_CANDIGEST 0x100 +#define AT_FLAG_CANABSORB 0x200 +#define AT_FLAG_HEALTHY 0x400 + +//Auto-transfer item flags +#define AT_FLAG_ITEMS 0x1 +#define AT_FLAG_TRASH 0x2 +#define AT_FLAG_EGGS 0x4 +#define AT_FLAG_REMAINS 0x8 +#define AT_FLAG_INDIGESTIBLE 0x10 +#define AT_FLAG_RECYCLABLE 0x20 +#define AT_FLAG_ORES 0x40 +#define AT_FLAG_CLOTHES 0x80 +#define AT_FLAG_FOOD 0x100 + +//Vorespawn flags +#define VS_FLAG_ABSORB_YES 0x1 +#define VS_FLAG_ABSORB_PREY 0x2 diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 8073d6a8ca1..d2efee687f0 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -5,6 +5,7 @@ #define CHEM_TOUCH 1 #define CHEM_INGEST 2 #define CHEM_BLOOD 3 +#define CHEM_VORE 4 // vore belly interactions #define MINIMUM_CHEMICAL_VOLUME 0.01 diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index 49f80fd19ab..2aa9f41c5ff 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -813,6 +813,13 @@ #define COMSIG_OBSERVER_APC "observer_apc" #define COMSIG_OBSERVER_GLOBALMOVED "observer_global_move" +// Bellies +///from /obj/belly/HandleBellyReagents() and /obj/belly/update_internal_overlay() +#define COMSIG_BELLY_UPDATE_VORE_FX "update_vore_fx" +///from /obj/belly/process() +#define COMSIG_BELLY_UPDATE_PREY_LOOP "update_prey_loop" +/// COMSIG used to get messages where they need to go +#define COMSIG_VISIBLE_MESSAGE "visible_message" //Unittest data update #ifdef UNIT_TEST diff --git a/code/__defines/map.dm b/code/__defines/map.dm index 66c21202500..045119d1c61 100644 --- a/code/__defines/map.dm +++ b/code/__defines/map.dm @@ -7,11 +7,12 @@ #define MAP_LEVEL_EMPTY 0x020 // Empty Z-levels that may be used for various things (currently used by bluespace jump) #define MAP_LEVEL_CONSOLES 0x040 // Z-levels available to various consoles, such as the crew monitor (when that gets coded in). Defaults to station_levels if unset. #define MAP_LEVEL_XENOARCH_EXEMPT 0x080 // Z-levels exempt from xenoarch digsite generation. -#define MAP_LEVEL_PERSIST 0x100 // Z-levels where SSpersistence should persist between rounds -#define MAP_LEVEL_MAPPABLE 0x200 // Z-levels where mapping units will work fully -#define MAP_LEVEL_BELOW_BLOCKED 0x400 // Z-levels in multiz with level below not meant to be 'normally' accessible +#define MAP_LEVEL_VORESPAWN 0x100 // Z-levels players are allowed to late join to via vorish means. Usually non-dangerous locations. +#define MAP_LEVEL_PERSIST 0x200 // Z-levels where SSpersistence should persist between rounds +#define MAP_LEVEL_MAPPABLE 0x400 // Z-levels where mapping units will work fully +#define MAP_LEVEL_BELOW_BLOCKED 0x800 // Z-levels in multiz with level below not meant to be 'normally' accessible // Misc map defines. -#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge. //VOREStation Edit +#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge. #define CELL_ALIVE(VAL) (VAL == cell_live_value) diff --git a/code/__defines/math.dm b/code/__defines/math.dm index 57c9b56ce30..4d141e562d6 100644 --- a/code/__defines/math.dm +++ b/code/__defines/math.dm @@ -228,3 +228,10 @@ if(num < 0) return 0 return sqrt(num) + +//Proc to check if a flag is active to use in universal math +/proc/global_flag_check(element, flag) + if(element & flag) + return 1 + else + return 0 diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 4e31ab3309f..1cf7a2c62a8 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -480,7 +480,9 @@ #define VIS_CH_STOMACH 34 -#define VIS_COUNT 34 //Must be highest number from above. +#define VIS_SOULCATCHER 35 + +#define VIS_COUNT 35 //Must be highest number from above. //Some mob icon layering defines #define BODY_LAYER -100 diff --git a/code/__defines/nif.dm b/code/__defines/nif.dm new file mode 100644 index 00000000000..439edbab6a1 --- /dev/null +++ b/code/__defines/nif.dm @@ -0,0 +1,13 @@ +//These two also have NIF FLAG representations. These are the local setting representations. +#define NIF_SC_CATCHING_ME 0x1 +#define NIF_SC_CATCHING_OTHERS 0x2 +//These are purely local setings flags, without global representation. +#define NIF_SC_ALLOW_EARS 0x4 +#define NIF_SC_ALLOW_EYES 0x8 +#define NIF_SC_BACKUPS 0x10 +#define NIF_SC_PROJECTING 0x20 +#define SOULGEM_CATCHING_GHOSTS 0x200 +#define SOULGEM_ACTIVE 0x400 +#define SOULGEM_SHOW_VORE_SFX 0x800 +#define SOULGEM_CATCHING_DRAIN 0x1000 +#define SOULGEM_SEE_SR_SOULS 0x2000 diff --git a/code/__defines/soulcatcher.dm b/code/__defines/soulcatcher.dm new file mode 100644 index 00000000000..871a0d77f2c --- /dev/null +++ b/code/__defines/soulcatcher.dm @@ -0,0 +1,5 @@ +#define SOULCATCHER_ALLOW_CAPTURE 0x1 +#define SOULCATCHER_ALLOW_TRANSFER 0x2 +#define SOULCATCHER_ALLOW_DELETION 0x4 +#define SOULCATCHER_ALLOW_DELETION_INSTANT 0x8 +#define SOULCATCHER_ALLOW_TAKEOVER 0x10 diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm index 1ac622f55b4..4bd3ecf7775 100644 --- a/code/_helpers/global_lists.dm +++ b/code/_helpers/global_lists.dm @@ -376,3 +376,27 @@ var/global/list/blacklisted_artifact_effects = list( /datum/artifact_effect/gas/phoron, /datum/artifact_effect/extreme ) + +//stuff that only synths can eat +var/global/list/edible_tech = list(/obj/item/cell, + /obj/item/circuitboard, + /obj/item/integrated_circuit, + /obj/item/broken_device, + /obj/item/brokenbug, + ) + +var/global/list/item_digestion_blacklist = list( + /obj/item/hand_tele, + /obj/item/card/id, + /obj/item/gun, + /obj/item/pinpointer, + /obj/item/clothing/shoes/magboots, + /obj/item/areaeditor/blueprints, + /obj/item/disk/nuclear, + /obj/item/perfect_tele_beacon, + /obj/item/organ/internal/brain/slime, + /obj/item/mmi/digital/posibrain, + /obj/item/mmi/digital/robot, + /obj/item/rig/protean) + +var/global/list/item_tf_spawnpoints = list() // Global variable tracking which items are item tf spawnpoints diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index 953251c6e10..939a451cc9a 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1584,6 +1584,7 @@ GLOBAL_REAL_VAR(list/stack_trace_storage) . += new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags . += new /obj/screen/plane_master{plane = PLANE_CH_STOMACH} //Stomachs . += new /obj/screen/plane_master{plane = PLANE_AUGMENTED} //Augmented reality + . += new /obj/screen/plane_master{plane = PLANE_SOULCATCHER} //Soulcatcher //VOREStation Add End /proc/CallAsync(datum/source, proctype, list/arguments) set waitfor = FALSE diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 5508d5e168b..2f0fc843e91 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -62,6 +62,10 @@ /datum/config_entry/number/footstep_volume default = 0 +/// In future see about making a function to adjust volume serverside in config.txt, easy to do with reenable values. - Jack +/datum/config_entry/number/vorefootstep_volume + default = 75 + /datum/config_entry/flag/use_loyalty_implants /datum/config_entry/flag/show_human_death_message diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 909b4f501c1..abe7fd0ef58 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -29,6 +29,8 @@ var/cloaked = FALSE //If we're cloaked or not var/image/cloaked_selfimage //The image we use for our client to let them see where we are + var/belly_cycles = 0 // Counting current belly process cycles for autotransfer. + var/autotransferable = TRUE // Toggle for autotransfer mechanics. /atom/movable/Initialize(mapload) . = ..() @@ -665,3 +667,10 @@ var/direction = get_dir(old_loc, new_loc) loc = new_loc Moved(old_loc, direction, TRUE) + +// Helper procs called on entering/exiting a belly. Does nothing by default, override on children for special behavior. +/atom/movable/proc/enter_belly(obj/belly/B) + return + +/atom/movable/proc/exit_belly(obj/belly/B) + return diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index d6e8d75a8b0..699ad5ade57 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -212,6 +212,8 @@ return TRUE */ +/datum/job/proc/update_limit(var/comperator) + return // Check client-specific availability rules. /datum/job/proc/player_has_enough_pto(client/C) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 8b9ea2d75a9..d500950cff6 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -83,6 +83,13 @@ var/global/datum/controller/occupations/job_master return 1 return 0 +/datum/controller/occupations/proc/update_limit(var/rank, var/comperator) + var/datum/job/job = GetJob(rank) + if(job && job.total_positions != -1) + job.update_limit(comperator) + return 1 + return 0 + /datum/controller/occupations/proc/FindOccupationCandidates(datum/job/job, level, flag) Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]") var/list/candidates = list() @@ -351,7 +358,7 @@ var/global/datum/controller/occupations/job_master return 1 -/datum/controller/occupations/proc/EquipRank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0) +/datum/controller/occupations/proc/EquipRank(var/mob/living/carbon/human/H, var/rank, var/joined_late = 0, var/announce = TRUE) if(!H) return null var/datum/job/job = GetJob(rank) @@ -428,7 +435,7 @@ var/global/datum/controller/occupations/job_master //else if(G.slot == slot_wear_suit && H.client?.prefs?.no_jacket) continue - if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) + if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) //RS ADD continue if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot)) to_chat(H, span_notice("Equipping you with \the [thing]!")) @@ -457,7 +464,7 @@ var/global/datum/controller/occupations/job_master var/datum/gear/G = gear_datums[thing] if(G.slot == slot_wear_suit && H.client?.prefs?.no_jacket) continue - if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) + if(G.slot == slot_shoes && H.client?.prefs?.shoe_hater) //RS ADD continue if(G.slot in custom_equip_slots) spawn_in_storage += thing @@ -499,7 +506,7 @@ var/global/datum/controller/occupations/job_master return H // TWEET PEEP - if(rank == JOB_SITE_MANAGER) + if(rank == JOB_SITE_MANAGER && announce) var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP) ? null : sound('sound/misc/boatswain.ogg', volume=20) captain_announcement.Announce("All hands, [alt_title ? alt_title : JOB_SITE_MANAGER] [H.real_name] on deck!", new_sound = announce_sound, zlevel = H.z) @@ -659,31 +666,305 @@ var/global/datum/controller/occupations/job_master var/datum/spawnpoint/spawnpos var/fail_deadly = FALSE + var/obj/belly/vore_spawn_gut + var/absorb_choice = FALSE // Ability to start absorbed with vorespawn + var/mob/living/prey_to_nomph + var/obj/item/item_to_be // Item TF spawning + var/mob/living/item_carrier // Capture crystal spawning + var/vorgans = FALSE // capture crystal simplemob spawning - var/datum/job/J = SSjob.get_job(rank) - fail_deadly = J?.offmap_spawn + // Remove fail_deadly addition on offmap_spawn //Spawn them at their preferred one if(C && C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)) - if(!(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) in using_map.allowed_spawns)) - if(fail_deadly) - to_chat(C, span_warning("Your chosen spawnpoint is unavailable for this map and your job requires a specific spawnpoint. Please correct your spawn point choice.")) - return + if(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) == "Vorespawn - Prey") + var/list/preds = list() + var/list/pred_names = list() //This is cringe + for(var/client/V in GLOB.clients) + if(!isliving(V.mob)) + continue + var/mob/living/M = V.mob + if(M.stat == UNCONSCIOUS || M.stat == DEAD || (M.client.is_afk(10 MINUTES) && !M.no_latejoin_vore_warning)) + continue + if(!M.latejoin_vore) + continue + if(!(M.z in using_map.vorespawn_levels)) + continue + preds += M + pred_names += M.real_name //very cringe + + if(preds.len) + var/pred_name = tgui_input_list(C, "Choose a Predator.", "Pred Spawnpoint", pred_names) + if(!pred_name) + return + var/index = pred_names.Find(pred_name) + var/mob/living/pred = preds[index] + var/list/available_bellies = list() + for(var/obj/belly/Y in pred.vore_organs) + if(Y.vorespawn_blacklist) + continue + if(LAZYLEN(Y.vorespawn_whitelist) && !(C.ckey in Y.vorespawn_whitelist)) + continue + available_bellies += Y + var/backup = tgui_alert(C, "Do you want a mind backup?", "Confirm", list("Yes", "No")) + if(backup == "Yes") + backup = 1 + vore_spawn_gut = tgui_input_list(C, "Choose a Belly.", "Belly Spawnpoint", available_bellies) + if(!vore_spawn_gut) + return + if(vore_spawn_gut.vorespawn_absorbed & VS_FLAG_ABSORB_YES) + absorb_choice = TRUE + if(vore_spawn_gut.vorespawn_absorbed & VS_FLAG_ABSORB_PREY) + if(tgui_alert(C, "Do you want to start absorbed into [pred]'s [vore_spawn_gut]?", "Confirm", list("Yes", "No")) != "Yes") + absorb_choice = FALSE + else if(tgui_alert(C, "[pred]'s [vore_spawn_gut] will start with you absorbed. Continue?", "Confirm", list("Yes", "No")) != "Yes") + return + to_chat(C, span_boldwarning("[pred] has received your spawn request. Please wait.")) + log_admin("[key_name(C)] has requested to vore spawn into [key_name(pred)]") + message_admins("[key_name(C)] has requested to vore spawn into [key_name(pred)]") + + var/confirm + if(pred.no_latejoin_vore_warning) + if(pred.no_latejoin_vore_warning_time > 0) + if(absorb_choice) + confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn absorbed as your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), pred.no_latejoin_vore_warning_time SECONDS) + else + confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn into your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), pred.no_latejoin_vore_warning_time SECONDS) + if(!confirm) + confirm = "Yes" + else + if(absorb_choice) + confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn absorbed as your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes")) + else + confirm = tgui_alert(pred, "[C.prefs.real_name] is attempting to spawn into your [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes")) + if(confirm != "Yes") + to_chat(C, span_warning("[pred] has declined your spawn request.")) + var/message = sanitizeSafe(input(pred,"Do you want to leave them a message?")as text|null) + if(message) + to_chat(C, span_notice("[pred] message : [message]")) + return + if(!vore_spawn_gut || QDELETED(vore_spawn_gut)) + to_chat(C, span_warning("Somehow, the belly you were trying to enter no longer exists.")) + return + if(pred.stat == UNCONSCIOUS || pred.stat == DEAD) + to_chat(C, span_warning("[pred] is not conscious.")) + to_chat(pred, span_warning("You must be conscious to accept.")) + return + if(!(pred.z in using_map.vorespawn_levels)) + to_chat(C, span_warning("[pred] is no longer in station grounds.")) + to_chat(pred, span_warning("You must be within station grounds to accept.")) + return + if(backup) + addtimer(CALLBACK(src, PROC_REF(m_backup_client), C), 5 SECONDS) + log_admin("[key_name(C)] has vore spawned into [key_name(pred)]") + message_admins("[key_name(C)] has vore spawned into [key_name(pred)]") + to_chat(C, span_notice("You have been spawned via vore. You are free to roleplay how you got there as you please, such as teleportation or having had already been there.")) + if(vore_spawn_gut.entrance_logs) + to_chat(pred, span_notice("Your prey has spawned via vore. You are free to roleplay this how you please, such as teleportation or having had already been there.")) else - to_chat(C, span_warning("Your chosen spawnpoint ([C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.")) - spawnpos = null - else + to_chat(C, span_warning("No predators were available to accept you.")) + return spawnpos = spawntypes[C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)] + if(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) == "Vorespawn - Pred") //Same as above, but in reverse! + var/list/preys = list() + var/list/prey_names = list() //This is still cringe + for(var/client/V in GLOB.clients) + if(!isliving(V.mob)) + continue + var/mob/living/M = V.mob + if(M.stat == UNCONSCIOUS || M.stat == DEAD || (M.client.is_afk(10 MINUTES) && !M.no_latejoin_prey_warning)) + continue + if(!M.latejoin_prey) + continue + if(!(M.z in using_map.vorespawn_levels)) + continue + preys += M + prey_names += M.real_name + if(preys.len) + var/prey_name = tgui_input_list(C, "Choose a Prey to spawn nom.", "Prey Spawnpoint", prey_names) + if(!prey_name) + return + var/index = prey_names.Find(prey_name) + var/mob/living/prey = preys[index] + var/list/available_bellies = list() + + var/datum/vore_preferences/P = C.prefs_vr + for(var/Y in P.belly_prefs) + available_bellies += Y["name"] + vore_spawn_gut = tgui_input_list(C, "Choose your Belly.", "Belly Spawnpoint", available_bellies) + if(!vore_spawn_gut) + return + if(alert(C, "Do you want to instantly absorb them?", "Confirm", "Yes", "No") == "Yes") + absorb_choice = TRUE + to_chat(C, span_boldwarning("[prey] has received your spawn request. Please wait.")) + log_admin("[key_name(C)] has requested to pred spawn onto [key_name(prey)]") + message_admins("[key_name(C)] has requested to pred spawn onto [key_name(prey)]") + + var/confirm + if(prey.no_latejoin_prey_warning) + if(prey.no_latejoin_prey_warning_time > 0) + if(absorb_choice) + confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore and instantly absorb you with their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), prey.no_latejoin_prey_warning_time SECONDS) + else + confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore you into their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes"), prey.no_latejoin_prey_warning_time SECONDS) + if(!confirm) + confirm = "Yes" + else + if(absorb_choice) + confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore and instantly absorb you with their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes")) + else + confirm = tgui_alert(prey, "[C.prefs.real_name] is attempting to televore you into their [vore_spawn_gut]. Let them?", "Confirm", list("No", "Yes")) + if(confirm != "Yes") + to_chat(C, span_warning("[prey] has declined your spawn request.")) + var/message = sanitizeSafe(input(prey,"Do you want to leave them a message?")as text|null) + if(message) + to_chat(C, span_notice("[prey] message : [message]")) + return + if(prey.stat == UNCONSCIOUS || prey.stat == DEAD) + to_chat(C, span_warning("[prey] is not conscious.")) + to_chat(prey, span_warning("You must be conscious to accept.")) + return + if(!(prey.z in using_map.vorespawn_levels)) + to_chat(C, span_warning("[prey] is no longer in station grounds.")) + to_chat(prey, span_warning("You must be within station grounds to accept.")) + return + log_admin("[key_name(C)] has pred spawned onto [key_name(prey)]") + message_admins("[key_name(C)] has pred spawned onto [key_name(prey)]") + prey_to_nomph = prey + else + to_chat(C, span_warning("No prey were available to accept you.")) + return + // Item TF spawnpoints! + else if(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) == "Item TF spawn") + var/list/items = list() + var/list/item_names = list() + var/list/carriers = list() + for(var/obj/item/I in item_tf_spawnpoints) + if(LAZYLEN(I.ckeys_allowed_itemspawn)) + if(!(C.ckey in I.ckeys_allowed_itemspawn)) + continue + var/atom/item_loc = I.loc + var/mob/living/carrier + while(!isturf(item_loc)) + if(isliving(item_loc)) + carrier = item_loc + break + else + item_loc = item_loc.loc + if(istype(carrier)) + if(!(carrier.z in using_map.vorespawn_levels)) + continue + if(carrier.stat == UNCONSCIOUS || carrier.stat == DEAD || carrier.client.is_afk(10 MINUTES)) + continue + carriers += carrier + else + if(!(item_loc.z in using_map.vorespawn_levels)) + continue + carriers += null + + if(istype(I, /obj/item/capture_crystal)) + if(carrier) + items += I + var/obj/item/capture_crystal/cryst = I + if(cryst.spawn_mob_type) + item_names += "\a [cryst.spawn_mob_name] inside of [carrier]'s [I.name] ([I.loc.name])" + else + item_names += "Inside of [carrier]'s [I.name] ([I.loc.name])" + else if(I.name == initial(I.name)) + items += I + if(carrier) + item_names += "[carrier]'s [I.name] ([I.loc.name])" + else + item_names += "[I.name] ([I.loc.name])" + else + items += I + if(carrier) + item_names += "[carrier]'s [I.name] (\a [initial(I.name)] at [I.loc.name])" + else + item_names += "[I.name] (\a [initial(I.name)] at [I.loc.name])" + if(LAZYLEN(items)) + var/backup = tgui_alert(C, "Do you want a mind backup?", "Confirm", list("Yes", "No")) + if(backup == "Yes") + backup = 1 + var/item_name = tgui_input_list(C, "Choose an Item to spawn as.", "Item TF Spawnpoint", item_names) + if(!item_name) + return + var/index = item_names.Find(item_name) + var/obj/item/item = items[index] + + var/mob/living/carrier = carriers[index] + if(istype(carrier)) + to_chat(C, span_boldwarning("[carrier] has received your spawn request. Please wait.")) + log_and_message_admins("[key_name(C)] has requested to item spawn into [key_name(carrier)]'s possession") + + var/confirm = tgui_alert(carrier, "[C.prefs.real_name] is attempting to join as the [item_name] in your possession.", "Confirm", list("No", "Yes")) + if(confirm != "Yes") + to_chat(C, span_warning("[carrier] has declined your spawn request.")) + var/message = sanitizeSafe(input(carrier,"Do you want to leave them a message?")as text|null) + if(message) + to_chat(C, span_notice("[carrier] message : [message]")) + return + if(carrier.stat == UNCONSCIOUS || carrier.stat == DEAD) + to_chat(C, span_warning("[carrier] is not conscious.")) + to_chat(carrier, span_warning("You must be conscious to accept.")) + return + if(!(carrier.z in using_map.vorespawn_levels)) + to_chat(C, span_warning("[carrier] is no longer in station grounds.")) + to_chat(carrier, span_warning("You must be within station grounds to accept.")) + return + log_and_message_admins("[key_name(C)] has item spawned onto [key_name(carrier)]") + item_to_be = item + item_carrier = carrier + if(backup) + addtimer(CALLBACK(src, PROC_REF(m_backup_client), C), 5 SECONDS) + else + var/confirm = tgui_alert(C, "\The [item.name] is currently not in any character's possession! Do you still want to spawn as it?", "Confirm", list("No", "Yes")) + if(confirm != "Yes") + return + log_and_message_admins("[key_name(C)] has item spawned into \a [item.name] that was not held by anyone") + item_to_be = item + if(backup) + addtimer(CALLBACK(src, PROC_REF(m_backup_client), C), 5 SECONDS) + if(istype(item, /obj/item/capture_crystal)) + var/obj/item/capture_crystal/cryst = item + if(cryst.spawn_mob_type) + var/confirm = tgui_alert(C, "Do you want to spawn with your slot's vore organs and prefs?", "Confirm", list("No", "Yes")) + if(confirm == "Yes") + vorgans = TRUE + else + to_chat(C, span_warning("No items were available to accept you.")) + return + else + if(!(C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint) in using_map.allowed_spawns)) + if(fail_deadly) + to_chat(C, span_warning("Your chosen spawnpoint is unavailable for this map and your job requires a specific spawnpoint. Please correct your spawn point choice.")) + return + else + to_chat(C, span_warning("Your chosen spawnpoint ([C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)]) is unavailable for the current map. Spawning you at one of the enabled spawn points instead.")) + spawnpos = null + else + spawnpos = spawntypes[C.prefs.read_preference(/datum/preference/choiced/living/spawnpoint)] //We will return a list key'd by "turf" and "msg" - . = list("turf","msg") + . = list("turf","msg", "voreny", "prey", "itemtf", "vorgans", "carrier") // Item TF spawnpoints, spawn as mob + if(vore_spawn_gut) + .["voreny"] = vore_spawn_gut + .["absorb"] = absorb_choice + if(prey_to_nomph) + .["prey"] = prey_to_nomph //We pass this on later to reverse the vorespawn in new_player.dm + // Item TF spawnpoints + if(item_to_be) + .["carrier"] = item_carrier + .["vorgans"] = vorgans + .["itemtf"] = item_to_be if(spawnpos && istype(spawnpos) && spawnpos.turfs.len) if(spawnpos.check_job_spawning(rank)) .["turf"] = spawnpos.get_spawn_position() .["msg"] = spawnpos.msg .["channel"] = spawnpos.announce_channel else - if(fail_deadly) + var/datum/job/J = SSjob.get_job(rank) + if(fail_deadly || J?.offmap_spawn) to_chat(C, span_warning("Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Please correct your spawn point choice.")) return to_chat(C, span_filter_warning("Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.")) @@ -694,3 +975,9 @@ var/global/datum/controller/occupations/job_master var/spawning = pick(latejoin) .["turf"] = get_turf(spawning) .["msg"] = "has arrived on the station" + +/datum/controller/occupations/proc/m_backup_client(var/client/C) //Same as m_backup, but takes a client entry. Used for vore late joining. + if(!ishuman(C.mob)) + return + var/mob/living/carbon/human/CM = C.mob + SStranscore.m_backup(CM.mind, CM.nif, TRUE) diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm index 6f8ec101af9..7f18d062319 100644 --- a/code/game/machinery/Beacon.dm +++ b/code/game/machinery/Beacon.dm @@ -22,7 +22,7 @@ /obj/machinery/bluespace_beacon/Destroy() if(Beacon) qdel(Beacon) - ..() + . = ..() // update the invisibility and icon /obj/machinery/bluespace_beacon/hide(var/intact) diff --git a/code/game/machinery/bomb_tester_vr.dm b/code/game/machinery/bomb_tester_vr.dm index baa6c6633a4..3bdf6432dc9 100644 --- a/code/game/machinery/bomb_tester_vr.dm +++ b/code/game/machinery/bomb_tester_vr.dm @@ -42,7 +42,7 @@ tank1 = null //Base machine Destroy() tank2 = null //handles deleting contents test_canister = null - ..() + . = ..() /obj/machinery/bomb_tester/dismantle() if(tank1) diff --git a/code/game/machinery/computer/RCON_Console.dm b/code/game/machinery/computer/RCON_Console.dm index 60e37ed5069..e041a567190 100644 --- a/code/game/machinery/computer/RCON_Console.dm +++ b/code/game/machinery/computer/RCON_Console.dm @@ -22,7 +22,7 @@ /obj/machinery/computer/rcon/Destroy() qdel(rcon) rcon = null - ..() + . = ..() // Proc: attack_hand() // Parameters: 1 (user - Person which clicked this computer) diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index eceacea8eac..f5380330237 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -18,7 +18,7 @@ var/global/list/minor_air_alarms = list() /obj/machinery/computer/atmos_alert/Destroy() atmosphere_alarm.unregister_alarm(src) - ..() + . = ..() /obj/machinery/computer/atmos_alert/attack_hand(mob/user) tgui_interact(user) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index ad469fc7c1b..b6586387005 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -17,7 +17,7 @@ /obj/machinery/computer/crew/Destroy() qdel(crew_monitor) crew_monitor = null - ..() + . = ..() /obj/machinery/computer/crew/attack_ai(mob/user) attack_hand(user) diff --git a/code/game/machinery/computer/shutoff_monitor.dm b/code/game/machinery/computer/shutoff_monitor.dm index d770f968764..2f08d5a0364 100644 --- a/code/game/machinery/computer/shutoff_monitor.dm +++ b/code/game/machinery/computer/shutoff_monitor.dm @@ -13,7 +13,7 @@ /obj/machinery/computer/shutoff_monitor/Destroy() QDEL_NULL(monitor) - ..() + . = ..() /obj/machinery/computer/shutoff_monitor/attack_hand(var/mob/user as mob) ..() diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index c7d9a32a10b..0a5692a8977 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -25,7 +25,7 @@ /obj/machinery/computer/station_alert/Destroy() alarm_monitor.unregister_alarm(src) qdel(alarm_monitor) - ..() + . = ..() /obj/machinery/computer/station_alert/attack_ai(mob/user) add_fingerprint(user) diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index e5156418b32..fff5cc2e704 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -15,7 +15,7 @@ var/list/doppler_arrays = list() /obj/machinery/doppler_array/Destroy() doppler_arrays -= src - ..() + . = ..() /obj/machinery/doppler_array/proc/sense_explosion(var/x0,var/y0,var/z0,var/devastation_range,var/heavy_impact_range,var/light_impact_range,var/took) if(stat & NOPOWER) return diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 30c73aa30a6..f58515b19e1 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -91,7 +91,7 @@ /obj/machinery/embedded_controller/radio/Destroy() if(radio_controller) radio_controller.remove_object(src,frequency) - ..() + . = ..() /obj/machinery/embedded_controller/radio/update_icon() if(on && program) diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index c4dbb902ad2..8b5bb2d497d 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -184,7 +184,7 @@ /obj/machinery/magnetic_module/Destroy() if(radio_controller) radio_controller.remove_object(src, freq) - ..() + . = ..() /obj/machinery/magnetic_controller name = "Magnetic Control Console" @@ -391,4 +391,4 @@ /obj/machinery/magnetic_controller/Destroy() if(radio_controller) radio_controller.remove_object(src, frequency) - ..() + . = ..() diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 775b23b6b8c..7502d9f01bc 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -202,7 +202,7 @@ Transponder Codes: