diff --git a/code/__defines/chat.dm b/code/__defines/chat.dm index 3fb1d2e2dde..1a9ac039146 100644 --- a/code/__defines/chat.dm +++ b/code/__defines/chat.dm @@ -34,6 +34,3 @@ #define MESSAGE_TYPE_ADMINLOG "adminlog" #define MESSAGE_TYPE_ATTACKLOG "attacklog" #define MESSAGE_TYPE_DEBUG "debug" - -/// Adds a generic box around whatever message you're sending in chat. Really makes things stand out. -#define examine_block(str) ("
" + str + "
") diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index ad7c9b4f346..2623cadaafb 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -128,7 +128,7 @@ #define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" ///from base of atom/handle_atom_del(): (atom/deleted) #define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" -///from base of atom/has_gravity(): (turf/location, list/forced_gravities) +///from base of atom/get_gravity(): (turf/location, list/forced_gravities) #define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" ///from proc/get_rad_contents(): () #define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" @@ -219,7 +219,7 @@ ///from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps) #define COMSIG_TURF_CHANGE "turf_change" -///from base of atom/has_gravity(): (atom/asker, list/forced_gravities) +///from base of atom/get_gravity(): (atom/asker, list/forced_gravities) #define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" ///from base of turf/multiz_turf_del(): (turf/source, direction) #define COMSIG_TURF_MULTIZ_DEL "turf_multiz_del" diff --git a/code/__defines/span_vr.dm b/code/__defines/span_vr.dm index 610670c3763..6e2e2f89736 100644 --- a/code/__defines/span_vr.dm +++ b/code/__defines/span_vr.dm @@ -1,5 +1,8 @@ // Sorted by however I felt like it -// We have two other ways of doing this, so why not a third. This one atleast has more span options. + +// Adds a generic box around whatever message you're sending in chat. Really makes things stand out. +#define examine_block(str) ("
" + str + "
") + #define span_ooc(str) ("" + str + "") #define span_looc(str) ("" + str + "") #define span_rlooc(str) ("" + str + "") @@ -50,12 +53,12 @@ #define span_hear(str) ("" + str + "") #define span_attack(str) ("" + str + "") -#define span_moderate(str) ("" + str + "") #define span_disarm(str) ("" + str + "") #define span_passive(str) ("" + str + "") #define span_critical(str) ("" + str + "") #define span_danger(str) ("" + str + "") +#define span_bolddanger(str) ("" + str + "") #define span_userdanger(str) ("" + str + "") #define span_warning(str) ("" + str + "") #define span_warningplain(str) ("" + str + "") @@ -75,8 +78,6 @@ #define span_sinister(str) ("" + str + "") -#define span_reflex_shoot(str) ("" + str + "") - /* Direct communication spans */ #define span_psay(str) ("" + str + "") diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm index 26124773229..00f1e9ba9cc 100644 --- a/code/_helpers/_lists.dm +++ b/code/_helpers/_lists.dm @@ -881,3 +881,11 @@ var/global/list/json_cache = list() else used_key_list[input_key] = 1 return input_key + +// Generic listoflist safe add and removal macros: +///If value is a list, wrap it in a list so it can be used with list add/remove operations +#define LIST_VALUE_WRAP_LISTS(value) (islist(value) ? list(value) : value) +///Add an untyped item to a list, taking care to handle list items by wrapping them in a list to remove the footgun +#define UNTYPED_LIST_ADD(list, item) (list += LIST_VALUE_WRAP_LISTS(item)) +///Remove an untyped item to a list, taking care to handle list items by wrapping them in a list to remove the footgun +#define UNTYPED_LIST_REMOVE(list, item) (list -= LIST_VALUE_WRAP_LISTS(item)) diff --git a/code/controllers/autotransfer.dm b/code/controllers/autotransfer.dm index 5ba87753d80..e94163ea464 100644 --- a/code/controllers/autotransfer.dm +++ b/code/controllers/autotransfer.dm @@ -25,6 +25,6 @@ var/datum/controller/transfer_controller/transfer_controller shift_hard_end = timerbuffer + config.vote_autotransfer_interval //If shuttle somehow gets recalled, let's force it to call again next time a vote would occur. timerbuffer = timerbuffer + config.vote_autotransfer_interval //Just to make sure a vote doesn't occur immediately afterwords. else if (round_duration_in_ds >= timerbuffer - 1 MINUTE) - new /datum/vote/crew_transfer + SSvote.start_vote(new /datum/vote/crew_transfer) //VOREStation Edit END timerbuffer = timerbuffer + config.vote_autotransfer_interval diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm index 0cad319b7da..797c5f88fb1 100644 --- a/code/controllers/subsystems/throwing.dm +++ b/code/controllers/subsystems/throwing.dm @@ -121,7 +121,7 @@ SUBSYSTEM_DEF(throwing) //calculate how many tiles to move, making up for any missed ticks. var/tilestomove = CEILING(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait), 1) while (tilestomove-- > 0) - if ((dist_travelled >= maxrange || AM.loc == target_turf) && (A && A.has_gravity())) + if ((dist_travelled >= maxrange || AM.loc == target_turf) && (A && A.get_gravity())) finalize() return diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index cf9721060fd..88869572022 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -226,7 +226,7 @@ var/global/datum/controller/subsystem/ticker/ticker mode.cleanup() //call a transfer shuttle vote to_world(span_danger("The round has ended!")) - new /datum/vote/crew_transfer + SSvote.start_vote(new /datum/vote/crew_transfer) // Called during GAME_STATE_FINISHED (RUNLEVEL_POSTGAME) /datum/controller/subsystem/ticker/proc/post_game_tick() diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 7130c724b4d..ed8e81f9928 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -183,7 +183,7 @@ var/list/outfits_decls_by_type_ pda.ownjob = assignment pda.ownrank = rank pda.name = "PDA-[H.real_name] ([assignment])" - if(H.client.prefs.ringtone) // if null we use the job default + if(H.client?.prefs.ringtone) // if null we use the job default pda.ttone = H.client.prefs.ringtone return pda diff --git a/code/datums/riding.dm b/code/datums/riding.dm index f0b2f53b952..72b4f2bd984 100644 --- a/code/datums/riding.dm +++ b/code/datums/riding.dm @@ -119,7 +119,7 @@ ridden.unbuckle_mob(M) /datum/riding/proc/Process_Spacemove(direction) - if(ridden.has_gravity()) + if(ridden.get_gravity()) return TRUE return FALSE diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 7132a5a60eb..89491a5efb2 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -37,7 +37,7 @@ var/static_environ = 0 var/music = null - var/has_gravity = 1 + var/has_gravity = 1 // Don't check this var directly; use get_gravity() instead var/secret_name = FALSE // This tells certain things that display areas' names that they shouldn't display this area's name. var/obj/machinery/power/apc/apc = null var/no_air = null @@ -382,7 +382,7 @@ var/list/mob/living/forced_ambiance_list = new if(!L.lastarea) L.lastarea = src var/area/oldarea = L.lastarea - if((oldarea.has_gravity == 0) && (has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together. + if((oldarea.get_gravity() == 0) && (get_gravity() == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together. thunk(L) L.update_floating( L.Check_Dense_Object() ) @@ -427,10 +427,10 @@ var/list/mob/living/forced_ambiance_list = new src.has_gravity = gravitystate for(var/mob/M in src) - if(has_gravity) + if(get_gravity()) thunk(M) M.update_floating( M.Check_Dense_Object() ) - M.update_gravity(has_gravity) + M.update_gravity(get_gravity()) /area/proc/thunk(mob) if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing. @@ -471,17 +471,17 @@ var/list/mob/living/forced_ambiance_list = new for(var/obj/machinery/door/blast/temp_blast in src) temp_blast.open() -/area/has_gravity() +/area/get_gravity() return has_gravity -/area/space/has_gravity() +/area/space/get_gravity() return 0 -/proc/has_gravity(atom/AT, turf/T) +/proc/get_gravity(atom/AT, turf/T) if(!T) T = get_turf(AT) var/area/A = get_area(T) - if(A && A.has_gravity()) + if(A && A.get_gravity()) return 1 return 0 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 52c1fac4036..4f518c0fd8e 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -595,13 +595,13 @@ /atom/proc/InsertedContents() return contents -/atom/proc/has_gravity(turf/T) +/atom/proc/get_gravity(turf/T) if(!T || !isturf(T)) T = get_turf(src) if(istype(T, /turf/space)) // Turf never has gravity return FALSE var/area/A = get_area(T) - if(A && A.has_gravity()) + if(A && A.get_gravity()) return TRUE return FALSE diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 13dcb633fd3..4f8f7cac36d 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -137,7 +137,7 @@ for(var/I in req_components) if(istype(P, text2path(I)) && (req_components[I] > 0)) playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) - if(P.is_cable_coil)) + if(P.is_cable_coil) var/obj/item/stack/cable_coil/CP = P if(CP.get_amount() > 1) var/camt = min(CP.amount, req_components[I]) // amount of cable to take, idealy amount required, but limited by amount provided diff --git a/code/game/mecha/combat/fighter.dm b/code/game/mecha/combat/fighter.dm index 2c522586842..387506e7d1b 100644 --- a/code/game/mecha/combat/fighter.dm +++ b/code/game/mecha/combat/fighter.dm @@ -167,7 +167,7 @@ return (stabilization_enabled && has_charge(step_energy_drain)) /obj/mecha/combat/fighter/proc/consider_gravity(var/moved = FALSE) - var/gravity = has_gravity() + var/gravity = get_gravity() if(gravity && ground_capable && occupant) start_hover() else if((!gravity && ground_capable) || !occupant) diff --git a/code/game/objects/items/devices/scanners/health.dm b/code/game/objects/items/devices/scanners/health.dm index ad8029bc78b..37ba27100eb 100644 --- a/code/game/objects/items/devices/scanners/health.dm +++ b/code/game/objects/items/devices/scanners/health.dm @@ -366,7 +366,7 @@ else dat += span_notice("Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]. Basis: [blood_reagent].") dat += "
" - dat += span_notice("Subject's pulse: [H.pulse == PULSE_THREADY || H.pulse == PULSE_NONE ? span_red(H.get_pulse(GETPULSE_TOOL)) : span_blue(H.get_pulse(GETPULSE_TOOL))] bpm.") // VORE Edit: Missed a linebreak here. + dat += span_notice("Subject's pulse: [H.pulse == PULSE_THREADY || H.pulse == PULSE_NONE ? span_red(H.get_pulse(GETPULSE_TOOL) + " bpm") : span_blue(H.get_pulse(GETPULSE_TOOL) + " bpm")].") // VORE Edit: Missed a linebreak here. dat += "
" if(istype(H.species, /datum/species/xenochimera)) // VOREStation Edit Start: Visible feedback for medmains on Xenochimera. if(H.stat == DEAD && H.revive_ready == REVIVING_READY && !H.hasnutriment()) diff --git a/code/game/objects/items/devices/tvcamera.dm b/code/game/objects/items/devices/tvcamera.dm index f439221d299..8ddce4ed256 100644 --- a/code/game/objects/items/devices/tvcamera.dm +++ b/code/game/objects/items/devices/tvcamera.dm @@ -133,8 +133,9 @@ if(!A || QDELETED(A)) show_tvs(loc) - if(get_dist(get_turf(src), get_turf(A)) > 5) + if(get_dist(get_turf(src), get_turf(A)) > 0) // No realtime updates show_tvs(loc) + update_feed() /obj/item/tvcamera/update_icon() ..() @@ -150,6 +151,9 @@ H.update_inv_l_hand() H.update_inv_belt() +/obj/item/tvcamera/proc/update_feed() + if(camera.status) + SEND_SIGNAL(camera, COMSIG_OBSERVER_MOVED) // Forward the movement signal //Assembly by roboticist diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 14befc37575..e1b812f8801 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -136,7 +136,7 @@ W.set_color() W.set_up(my_target) - if((istype(usr.loc, /turf/space)) || (usr.lastarea.has_gravity == 0)) + if((istype(usr.loc, /turf/space)) || (usr.lastarea.get_gravity() == 0)) user.inertia_dir = get_dir(target, user) step(user, user.inertia_dir) else diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 8ecf7256e2c..8751a723377 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -147,7 +147,7 @@ /turf/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) var/turf/T = get_turf(user) var/area/A = T.loc - if((istype(A) && !(A.has_gravity)) || (istype(T,/turf/space))) + if((istype(A) && !(A.get_gravity())) || (istype(T,/turf/space))) return if(istype(O, /obj/screen)) return @@ -302,7 +302,7 @@ // Called when turf is hit by a thrown object /turf/hitby(atom/movable/AM as mob|obj, var/speed) if(density) - if(!has_gravity(AM)) //Checked a different codebase for reference. Turns out it's only supposed to happen in no-gravity + if(!get_gravity(AM)) //Checked a different codebase for reference. Turns out it's only supposed to happen in no-gravity spawn(2) step(AM, turn(AM.last_move, 180)) //This makes it float away after hitting a wall in 0G if(isliving(AM)) diff --git a/code/global.dm b/code/global.dm index 92c11ee868e..f7fd886b891 100644 --- a/code/global.dm +++ b/code/global.dm @@ -139,7 +139,8 @@ var/list/emergency_module_types = list( ) // List of modules available to AI shells var/list/shell_module_types = list( - "Standard", "Service", "Clerical" + "Standard", "Engineering", "Surgeon", "Crisis", + "Miner", "Janitor", "Service", "Clerical", "Security" ) // List of whitelisted modules var/list/whitelisted_module_types = list( diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index 94fabe44e8e..3add1b74082 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -127,7 +127,8 @@ var/list/admin_verbs_admin = list( /client/proc/unmake_mentor, /client/proc/removetickets, /client/proc/delbook, - /client/proc/toggle_spawning_with_recolour + /client/proc/toggle_spawning_with_recolour, + /client/proc/start_vote ) var/list/admin_verbs_ban = list( @@ -416,7 +417,8 @@ var/list/admin_verbs_mod = list( /client/proc/getserverlog, //allows us to fetch server logs (diary) for other days, /datum/admins/proc/view_persistent_data, /datum/admins/proc/view_txt_log, //shows the server log (diary) for today, - /datum/admins/proc/view_atk_log //shows the server combat-log, doesn't do anything presently, + /datum/admins/proc/view_atk_log, //shows the server combat-log, doesn't do anything presently, + /client/proc/start_vote ) var/list/admin_verbs_event_manager = list( @@ -559,7 +561,8 @@ var/list/admin_verbs_event_manager = list( /client/proc/cmd_debug_del_all, /client/proc/toggle_random_events, /client/proc/modify_server_news, - /client/proc/toggle_spawning_with_recolour + /client/proc/toggle_spawning_with_recolour, + /client/proc/start_vote ) diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm index 47f034287d6..8892232165f 100644 --- a/code/modules/admin/create_object.dm +++ b/code/modules/admin/create_object.dm @@ -21,8 +21,7 @@ var/list/choices = list("/obj", "/obj/structure", "/obj/item", - "/obj/item", - "/obj/item", + "/obj/item/melee", "/obj/item/gun", "/obj/item/reagent_containers", "/obj/item/reagent_containers/food", diff --git a/code/modules/casino/slots.dm b/code/modules/casino/slots.dm index c3d490580d2..bfc9e074911 100644 --- a/code/modules/casino/slots.dm +++ b/code/modules/casino/slots.dm @@ -59,7 +59,7 @@ /obj/machinery/slot_machine/attackby(obj/item/W as obj, mob/user as mob) if(busy) - to_chat(user,"The slot machine is currently running. ") + to_chat(user,span_notice("The slot machine is currently running.")) return if(W.has_tool_quality(TOOL_WRENCH)) playsound(src, W.usesound, 100, 1) @@ -104,10 +104,10 @@ if (isbroken) return if (busy) - to_chat(user,"The slot machine is currently rolling. ") + to_chat(user,span_notice("The slot machine is currently rolling.")) return if(cashmoney.worth < 5) - to_chat(user,"You dont have enough chips to gamble! ") + to_chat(user,span_notice("You dont have enough chips to gamble!")) return to_chat(user,span_notice("You puts 5 credits in the slot machine and presses start.")) @@ -289,7 +289,7 @@ /obj/machinery/station_slot_machine/attackby(obj/item/W as obj, mob/user as mob) if(busy) - to_chat(user,"The slot machine is currently running. ") + to_chat(user,span_notice("The slot machine is currently running.")) return if(W.has_tool_quality(TOOL_WRENCH)) playsound(src, W.usesound, 100, 1) @@ -333,10 +333,10 @@ if (isbroken) return if (busy) - to_chat(user,"The slot machine is currently rolling. ") + to_chat(user,span_notice("The slot machine is currently rolling.")) return if(cashmoney.worth < 5) - to_chat(user,"You dont have enough Thalers to gamble! ") + to_chat(user,span_notice("You dont have enough Thalers to gamble!")) return to_chat(user,span_notice("You puts 5 Thalers in the slot machine and presses start.")) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index 56460d2990c..794ef104722 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -79,7 +79,7 @@ if(holder && !holder.fakekey && (holder.rights & R_ADMIN|R_FUN|R_EVENT) && config.allow_admin_ooccolor && (src.prefs.ooccolor != initial(src.prefs.ooccolor))) // keeping this for the badmins to_chat(target, span_ooc("" + create_text_tag("ooc", "OOC:", target) + " [display_name]: [span_message(msg)]")) else - to_chat(target, span_ooc("" + create_text_tag("ooc", "OOC:", target) + " [display_name]: " + span_message(msg))) + to_chat(target, span_ooc("" + create_text_tag("ooc", "OOC:", target) + " [display_name]: " + span_message(msg)) + "") /client/verb/looc(msg as text) set name = "LOOC" diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index b98409fef61..b3c441921e9 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -930,7 +930,7 @@ if(wearer.transforming || !wearer.canmove) return - if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.has_gravity == 0)) + if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.get_gravity() == 0)) if(!wearer.Process_Spacemove(0)) return 0 diff --git a/code/modules/economy/coins.dm b/code/modules/economy/coins.dm index 63235dcd6c6..1d29b160611 100644 --- a/code/modules/economy/coins.dm +++ b/code/modules/economy/coins.dm @@ -100,5 +100,5 @@ comment = "tails" else if(result == 2) comment = "heads" - user.visible_message(span_notice("[user] has thrown \the [src]. It lands on [comment]! "), \ - span_notice("You throw \the [src]. It lands on [comment]! ")) + user.visible_message(span_notice("[user] has thrown \the [src]. It lands on [comment]!"), \ + span_notice("You throw \the [src]. It lands on [comment]!")) diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm index 85464795d54..1c878358618 100644 --- a/code/modules/events/communications_blackout.dm +++ b/code/modules/events/communications_blackout.dm @@ -1,10 +1,10 @@ /datum/event/communications_blackout/announce() var/alert = pick( "Ionospheric anomalies detected. Temporary telecommunication failure imminent. Please contact you*%fj00)`5vc-BZZT", \ - "Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v�-BZZZT", \ + "Ionospheric anomalies detected. Temporary telecommunication failu*3mga;b4;'1v¬-BZZZT", \ "Ionospheric anomalies detected. Temporary telec#MCi46:5.;@63-BZZZZT", \ "Ionospheric anomalies dete'fZ\\kg5_0-BZZZZZT", \ - "Ionospheri:%� MCayj^j<.3-BZZZZZZT", \ - "#4nd%;f4y6,>�%-BZZZZZZZT") + "Ionospheri:%£ MCayj^j<.3-BZZZZZZT", \ + "#4nd%;f4y6,>£%-BZZZZZZZT") for(var/mob/living/silicon/ai/A in player_list) //AIs are always aware of communication blackouts. to_chat(A, "
") diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 787d331cec8..5628effdcf0 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -320,7 +320,7 @@ user.visible_message(span_notice("\The [user] crudely slices \the [src] with [W]!"), span_notice("You crudely slice \the [src] with your [W]!")) slices_lost = rand(1,min(1,round(slices_num/2))) else - user.visible_message("\The [user] slices \the [src]!", span_notice("You slice \the [src]!")) + user.visible_message(span_notice("\The [user] slices \the [src]!"), span_notice("You slice \the [src]!")) var/reagents_per_slice = reagents.total_volume/slices_num for(var/i=1 to (slices_num-slices_lost)) diff --git a/code/modules/holodeck/HolodeckControl.dm b/code/modules/holodeck/HolodeckControl.dm index 05b08ec4f4d..9810569fa2f 100644 --- a/code/modules/holodeck/HolodeckControl.dm +++ b/code/modules/holodeck/HolodeckControl.dm @@ -119,7 +119,7 @@ data["safetyDisabled"] = safety_disabled data["emagged"] = emagged data["gravity"] = FALSE - if(linkedholodeck.has_gravity) + if(linkedholodeck.get_gravity()) data["gravity"] = TRUE return data @@ -272,7 +272,7 @@ else loadProgram(powerdown_program, 0) - if(!linkedholodeck.has_gravity) + if(!linkedholodeck.get_gravity()) linkedholodeck.gravitychange(1) active = 0 @@ -379,7 +379,7 @@ active = 1 update_use_power(USE_POWER_IDLE) - if(A.has_gravity) + if(A.get_gravity()) A.gravitychange(0) else A.gravitychange(1) @@ -388,7 +388,7 @@ //Turn it back to the regular non-holographic room loadProgram(powerdown_program, 0) - if(!linkedholodeck.has_gravity) + if(!linkedholodeck.get_gravity()) linkedholodeck.gravitychange(1) active = 0 diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 769dbc52333..8047bdd0240 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -295,8 +295,8 @@ Book Cart End /obj/item/book/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) if(user.zone_sel.selecting == O_EYES) - user.visible_message(span_notice("You open up the book and show it to [M]. "), \ - span_notice(" [user] opens up a book and shows it to [M]. ")) + user.visible_message(span_notice("You open up the book and show it to [M]."), \ + span_notice(" [user] opens up a book and shows it to [M].")) M << browse("Penned by [author].
" + "[dat]", "window=book") user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //to prevent spam diff --git a/code/modules/looking_glass/lg_console.dm b/code/modules/looking_glass/lg_console.dm index a5ff493c815..fe8f9f0f5f0 100644 --- a/code/modules/looking_glass/lg_console.dm +++ b/code/modules/looking_glass/lg_console.dm @@ -78,7 +78,7 @@ data["supportedPrograms"] = program_list data["currentProgram"] = current_program data["immersion"] = immersion - if(my_area?.has_gravity) + if(my_area?.get_gravity()) data["gravity"] = 1 else data["gravity"] = 0 @@ -147,7 +147,7 @@ last_gravity_change = world.time - if(A.has_gravity) + if(A.get_gravity()) A.gravitychange(0) else A.gravitychange(1) diff --git a/code/modules/mining/mine_outcrops.dm b/code/modules/mining/mine_outcrops.dm index 2130ce68e9d..c8da8a4de9f 100644 --- a/code/modules/mining/mine_outcrops.dm +++ b/code/modules/mining/mine_outcrops.dm @@ -100,7 +100,7 @@ if (istype(W, /obj/item/melee/shock_maul)) var/obj/item/melee/shock_maul/S = W if(!S.wielded || !S.status) - to_chat(user, span_warning("\The [src] must be wielded in two hands and powered on to be used for mining!")) + to_chat(user, span_warning("\The [S] must be wielded in two hands and powered on to be used for mining!")) return to_chat(user, span_notice("You pulverize \the [src]!")) for(var/i=0;i<(rand(mindrop,upperdrop));i++) diff --git a/code/modules/mob/animations.dm b/code/modules/mob/animations.dm index 3e1d2b50456..331a7daef1e 100644 --- a/code/modules/mob/animations.dm +++ b/code/modules/mob/animations.dm @@ -94,7 +94,7 @@ note dizziness decrements automatically in the mob's Life() proc. var/turf/turf = get_turf(src) if(!istype(turf,/turf/space)) var/area/A = turf.loc - if(istype(A) && A.has_gravity) + if(istype(A) && A.get_gravity()) make_floating(0) return else if (Check_Shoegrip()) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ec5b81e1b88..c79ff8e4f02 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1754,7 +1754,7 @@ // Drag damage is handled in a parent /mob/living/carbon/human/dragged(var/mob/living/dragger, var/oldloc) var/area/A = get_area(src) - if(lying && !buckled && A.has_gravity() && prob(getBruteLoss() * 200 / maxHealth)) + if(lying && !buckled && A.get_gravity() && prob(getBruteLoss() * 200 / maxHealth)) var/bloodtrail = 1 if(species?.flags & NO_BLOOD) bloodtrail = 0 diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index f00df83d4d7..acb8a5e8add 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -292,7 +292,7 @@ if(buckled || lying || throwing) return // people flying, lying down or sitting do not step - if(!has_gravity(src) && prob(75)) + if(!get_gravity(src) && prob(75)) return // Far less likely to make noise in no gravity playsound(T, S, volume, FALSE) @@ -301,4 +301,4 @@ /mob/living/carbon/human/set_dir(var/new_dir) . = ..() if(. && (species.tail || tail_style)) - update_tail_showing() \ No newline at end of file + update_tail_showing() diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 5e782f85ebf..421c3351ac5 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -64,7 +64,7 @@ //stuff in the stomach //handle_stomach() //VOREStation Code - update_gravity(mob_has_gravity()) + update_gravity(mob_get_gravity()) update_pulling() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index c707e358a8b..dae5d76551a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1143,7 +1143,7 @@ src.visible_message(span_warning("[src] has thrown [item].")) - if((isspace(src.loc)) || (src.lastarea?.has_gravity == 0)) + if((isspace(src.loc)) || (src.lastarea?.get_gravity() == 0)) src.inertia_dir = get_dir(target, src) step(src, inertia_dir) item.throw_at(target, throw_range, item.throw_speed, src) @@ -1174,7 +1174,7 @@ //actually throw it! src.visible_message(span_warning("[src] has thrown [item].")) - if((isspace(src.loc)) || (src.lastarea?.has_gravity == 0)) + if((isspace(src.loc)) || (src.lastarea?.get_gravity() == 0)) src.inertia_dir = get_dir(target, src) step(src, inertia_dir) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index c7ceb2a94af..46d6237afe3 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -264,7 +264,7 @@ default behaviour is: /mob/living/proc/dragged(var/mob/living/dragger, var/oldloc) var/area/A = get_area(src) - if(lying && !buckled && pull_damage() && A.has_gravity() && (prob(getBruteLoss() * 200 / maxHealth))) + if(lying && !buckled && pull_damage() && A.get_gravity() && (prob(getBruteLoss() * 200 / maxHealth))) adjustBruteLoss(2) visible_message(span_danger("\The [src]'s [isSynthetic() ? "state" : "wounds"] worsen terribly from being dragged!")) @@ -303,7 +303,7 @@ default behaviour is: if(!isturf(loc)) return - else if(lastarea?.has_gravity == 0) + else if(lastarea?.get_gravity() == 0) inertial_drift() //VOREStation Edit Start else if(flying) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index da67867ce7b..fd1042f0cca 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -208,7 +208,7 @@ return result // Can't control ourselves when drifting - if((isspace(loc) || my_mob.lastarea?.has_gravity == 0) && isturf(loc)) + if((isspace(loc) || my_mob.lastarea?.get_gravity() == 0) && isturf(loc)) if(!my_mob.Process_Spacemove(0)) return 0 @@ -447,7 +447,7 @@ if(istype(turf,/turf/simulated/floor)) // Floors don't count if they don't have gravity var/area/A = turf.loc - if(istype(A) && A.has_gravity == 0) + if(istype(A) && A.get_gravity() == 0) if(shoegrip == null) shoegrip = Check_Shoegrip() //Shoegrip is only ever checked when a zero-gravity floor is encountered to reduce load if(!shoegrip) @@ -486,8 +486,8 @@ prob_slip = round(prob_slip) return(prob_slip) -/mob/proc/mob_has_gravity(turf/T) - return has_gravity(src, T) +/mob/proc/mob_get_gravity(turf/T) + return get_gravity(src, T) /mob/proc/update_gravity() return diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index 53b29e8ae9a..cfbcebbf420 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -30,7 +30,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image update_Login_details() //handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying if(join_motd) join_motd = GLOB.is_valid_url.Replace(join_motd,span_linkify("$1")) - to_chat(src, "
[join_motd]
") + to_chat(src, examine_block("
[join_motd]
")) if(has_respawned) to_chat(usr, config.respawn_message) diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 767d684b4c4..a1dc794bb85 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -68,7 +68,7 @@ var/area/area = get_area(src) - if(area.has_gravity() && !can_overcome_gravity()) + if(area.get_gravity() && !can_overcome_gravity()) if(direction == UP) var/obj/structure/lattice/lattice = locate() in destination.contents var/obj/structure/catwalk/catwalk = locate() in destination.contents @@ -278,7 +278,7 @@ // No gravity in space, apparently. var/area/area = get_area(src) - if(!area.has_gravity()) + if(!area.get_gravity()) return if(throwing) diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm index 366bf15968b..6f00ce1a40e 100644 --- a/code/modules/nifsoft/nif.dm +++ b/code/modules/nifsoft/nif.dm @@ -387,7 +387,7 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable last_notification = message // TGUI Hook - to_chat(human,span_filter_nif("\[[icon2html(src.big_icon, human.client)]NIF\] displays, " + alert ? span_danger(message) : span_notice(message))) + to_chat(human,span_filter_nif("\[[icon2html(src.big_icon, human.client)]NIF\] displays, " + (alert ? span_danger(message) : span_notice(message)))) if(prob(1)) human.visible_message(span_notice("\The [human] [pick(look_messages)].")) if(alert) human << bad_sound diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index bb5be2ddaaf..9ec1dc24b59 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -890,7 +890,7 @@ Note that amputating the affected organ does in fact remove the infection from t var/gore_sound = "[(robotic >= ORGAN_ROBOT) ? "tortured metal" : "ripping tendons and flesh"]" owner.visible_message( span_danger("\The [owner]'s [src.name] flies off in an arc!"),\ - span_moderate("Your [src.name] goes flying off!"),\ + span_bolddanger("Your [src.name] goes flying off!"),\ span_danger("You hear a terrible sound of [gore_sound].")) if(DROPLIMB_BURN) if(cannot_gib) @@ -898,7 +898,7 @@ Note that amputating the affected organ does in fact remove the infection from t var/gore = "[(robotic >= ORGAN_ROBOT) ? "": " of burning flesh"]" owner.visible_message( span_danger("\The [owner]'s [src.name] flashes away into ashes!"),\ - span_moderate("Your [src.name] flashes away into ashes!"),\ + span_bolddanger("Your [src.name] flashes away into ashes!"),\ span_danger("You hear a crackling sound[gore].")) if(DROPLIMB_BLUNT) if(cannot_gib) @@ -907,7 +907,7 @@ Note that amputating the affected organ does in fact remove the infection from t var/gore_sound = "[(status >= ORGAN_ROBOT) ? "rending sound of tortured metal" : "sickening splatter of gore"]" owner.visible_message( span_danger("\The [owner]'s [src.name] explodes[gore]!"),\ - span_moderate("Your [src.name] explodes[gore]!"),\ + span_bolddanger("Your [src.name] explodes[gore]!"),\ span_danger("You hear the [gore_sound].")) var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed(). diff --git a/code/modules/pda/pda.dm b/code/modules/pda/pda.dm index f279b415200..1d4c860136e 100644 --- a/code/modules/pda/pda.dm +++ b/code/modules/pda/pda.dm @@ -79,6 +79,8 @@ var/global/list/obj/item/pda/PDAs = list() var/list/notifying_programs = list() var/retro_mode = 0 + var/gunshot_residue // VOREstation edit: prevents wrist PDA from preventing gun use + /obj/item/pda/examine(mob/user) . = ..() if(Adjacent(user)) diff --git a/code/modules/power/gravitygenerator_vr.dm b/code/modules/power/gravitygenerator_vr.dm index 61e9669aef2..cce29f07c59 100644 --- a/code/modules/power/gravitygenerator_vr.dm +++ b/code/modules/power/gravitygenerator_vr.dm @@ -393,7 +393,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) for(var/mob/M as anything in player_list) if(!(M.z in levels)) continue - M.update_gravity(M.mob_has_gravity()) + M.update_gravity(M.mob_get_gravity()) shake_camera(M, 15, 1) M.playsound_local(src, null, 50, 1, 0.5, S = alert_sound) diff --git a/code/modules/reagents/machinery/chem_master.dm b/code/modules/reagents/machinery/chem_master.dm index 4daf890ed88..e040459dfd0 100644 --- a/code/modules/reagents/machinery/chem_master.dm +++ b/code/modules/reagents/machinery/chem_master.dm @@ -226,12 +226,14 @@ if(condi || !reagents.total_volume) return tgui_modal_input(src, id, "Please enter the amount of patches to make (max [MAX_MULTI_AMOUNT] at a time):", null, arguments, pillamount, 5) - if("create_bottle") + if("create_bottle", "create_bottle_two") if(condi || !reagents.total_volume) return var/num = round(text2num(arguments["num"] || 1)) if(!num) return + if(id == "create_bottle_two") + num = 2 arguments["num"] = num var/amount_per_bottle = CLAMP(reagents.total_volume / num, 0, MAX_UNITS_PER_BOTTLE) var/default_name = "[reagents.get_master_reagent_name()]" @@ -349,7 +351,7 @@ if(condi || !reagents.total_volume) return tgui_act("modal_open", list("id" = "create_patch", "arguments" = list("num" = answer)), ui, state) - if("create_bottle") + if("create_bottle", "create_bottle_two") if(condi || !reagents.total_volume) return var/count = CLAMP(round(text2num(arguments["num"]) || 0), 0, MAX_MULTI_AMOUNT) diff --git a/code/modules/reagents/reactions/instant/drinks.dm b/code/modules/reagents/reactions/instant/drinks.dm index 3f470a5714b..75e15d188cc 100644 --- a/code/modules/reagents/reactions/instant/drinks.dm +++ b/code/modules/reagents/reactions/instant/drinks.dm @@ -767,7 +767,7 @@ /decl/chemical_reaction/instant/drinks/minttea_decaf name = "Decaf Mint Tea" id = "decafminttea" - result = "decafminttea" + result = "mintteadecaf" required_reagents = list("teadecaf" = 5, "mint" = 1) result_amount = 6 @@ -781,7 +781,7 @@ /decl/chemical_reaction/instant/drinks/lemontea_decaf name = "Decaf Lemon Tea" id = "decaflemontea" - result = "decaflemontea" + result = "lemonteadecaf" required_reagents = list("teadecaf" = 5, "lemonjuice" = 1) result_amount = 6 @@ -795,7 +795,7 @@ /decl/chemical_reaction/instant/drinks/limetea_decaf name = "Decaf Lime Tea" id = "decaflimetea" - result = "decaflimetea" + result = "limeteadecaf" required_reagents = list("teadecaf" = 5, "limejuice" = 1) result_amount = 6 @@ -809,7 +809,7 @@ /decl/chemical_reaction/instant/drinks/orangetea_decaf name = "Decaf Orange Tea" id = "decaforangetea" - result = "decaforangetea" + result = "orangeteadecaf" required_reagents = list("teadecaf" = 5, "orangejuice" = 1) result_amount = 6 @@ -823,7 +823,7 @@ /decl/chemical_reaction/instant/drinks/berrytea_decaf name = "Decaf Berry Tea" id = "decafberrytea" - result = "decafberrytea" + result = "berryteadecaf" required_reagents = list("teadecaf" = 5, "berryjuice" = 1) result_amount = 6 diff --git a/code/modules/reagents/reagents/food_drinks.dm b/code/modules/reagents/reagents/food_drinks.dm index 775f04bdafd..258d19b89d5 100644 --- a/code/modules/reagents/reagents/food_drinks.dm +++ b/code/modules/reagents/reagents/food_drinks.dm @@ -1809,7 +1809,7 @@ glass_desc = "Glorious brainfreezing mixture." allergen_type = ALLERGEN_DAIRY //Made with dairy products -/datum/reagent/milkshake/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) +/datum/reagent/drink/milkshake/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) ..() var/effective_dose = dose/2 @@ -4050,7 +4050,7 @@ allergen_type = ALLERGEN_GRAINS|ALLERGEN_FRUIT //Made from manhattan(whiskey(grains), vermouth(fruit)) -/datum/reagent/drink/soemmerfire/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) +/datum/reagent/ethanol/soemmerfire/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) ..() if(alien == IS_DIONA) return @@ -4119,7 +4119,7 @@ glass_name = "Vox's Delight" glass_desc = "Not recommended if you enjoy having organs." -/datum/reagent/drink/voxdelight/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) +/datum/reagent/ethanol/voxdelight/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) ..() if(alien == IS_DIONA) return @@ -4193,7 +4193,7 @@ allergen_type = ALLERGEN_GRAINS //Made from vodka(grains) -/datum/reagent/drink/slimeshot/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) +/datum/reagent/ethanol/slimeshot/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) ..() if(alien == IS_DIONA) return diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index 7883c303d65..75f4fb1cacb 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -55,8 +55,6 @@ using metal and glass, it uses glass and reagents (usually sulphuric acid). build(D) progress = 0 removeFromQueue(1) - if(linked_console) - linked_console.updateUsrDialog() update_icon() else if(busy) @@ -163,7 +161,6 @@ using metal and glass, it uses glass and reagents (usually sulphuric acid). to_chat(user, span_filter_notice("The fabricator cannot hold more [sname].")) busy = 0 - updateUsrDialog() return /obj/machinery/r_n_d/circuit_imprinter/proc/addToQueue(var/datum/design/D) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 46861f544ba..e6f87f61180 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -69,8 +69,6 @@ build(D) progress = 0 removeFromQueue(1) - if(linked_console) - linked_console.updateUsrDialog() flick("[initial(icon_state)]_finish", src) update_icon() else @@ -179,7 +177,6 @@ spawn(10) cut_overlay("protolathe_[t]") - updateUsrDialog() return /obj/machinery/r_n_d/protolathe/proc/addToQueue(var/datum/design/D) diff --git a/code/modules/research/rdconsole_tgui.dm b/code/modules/research/rdconsole_tgui.dm index 5208630cb56..743de3d7c1a 100644 --- a/code/modules/research/rdconsole_tgui.dm +++ b/code/modules/research/rdconsole_tgui.dm @@ -23,10 +23,14 @@ . = ..() if(locked && !allowed(user) && !emagged) . = min(., STATUS_UPDATE) + if(busy_msg) + . = min(., STATUS_UPDATE) /obj/machinery/computer/rdconsole/tgui_static_data(mob/user) var/list/data = ..() + data["sheet_material_amount"] = SHEET_MATERIAL_AMOUNT + data["tech"] = tgui_GetResearchLevelsInfo() data["designs"] = tgui_GetDesignInfo(design_page) @@ -45,138 +49,104 @@ data["builder_page"] = builder_page data["design_page"] = design_page - data["info"] = null - if(!locked && !busy_msg) - data["info"] = list( - "sync" = sync, - "is_public" = is_public, + data["sync"] = sync + data["is_public"] = is_public + + // Skip the rest of the data if it's locked + if(locked) + return data + + if(linked_destroy) + data["linked_destroy"] = list( + "loaded_item" = linked_destroy.loaded_item, + "origin_tech" = tgui_GetOriginTechForItem(linked_destroy.loaded_item), ) + else + data["linked_destroy"] = null - data["info"]["linked_destroy"] = list("present" = FALSE) - if(linked_destroy) - data["info"]["linked_destroy"] = list( - "present" = TRUE, - "loaded_item" = linked_destroy.loaded_item, - "origin_tech" = tgui_GetOriginTechForItem(linked_destroy.loaded_item), - ) + if(linked_lathe) + var/list/reagents = list() + for(var/datum/reagent/R as anything in linked_lathe.reagents.reagent_list) + UNTYPED_LIST_ADD(reagents, list( + "name" = R.name, + "id" = R.id, + "volume" = R.volume + )) - data["info"]["linked_lathe"] = list("present" = FALSE) - if(linked_lathe) - data["info"]["linked_lathe"] = list( - "present" = TRUE, - "total_materials" = linked_lathe.TotalMaterials(), - "max_materials" = linked_lathe.max_material_storage, - "total_volume" = linked_lathe.reagents.total_volume, - "max_volume" = linked_lathe.reagents.maximum_volume, - "busy" = linked_lathe.busy, - ) + var/list/queue = list() + var/i = 1 + for(var/datum/design/D as anything in linked_lathe.queue) + UNTYPED_LIST_ADD(queue, list( + "name" = D.name, + "index" = i + )) + i += 1 - var/list/materials = list() - for(var/M in linked_lathe.materials) - var/amount = linked_lathe.materials[M] - var/hidden_mat = FALSE - for(var/HM in linked_lathe.hidden_materials) - if(M == HM && amount == 0) - hidden_mat = TRUE - break - if(hidden_mat) - continue - materials.Add(list(list( - "name" = M, - "amount" = amount, - "sheets" = round(amount / SHEET_MATERIAL_AMOUNT), - "removable" = amount >= SHEET_MATERIAL_AMOUNT, - ))) - data["info"]["linked_lathe"]["mats"] = materials + data["linked_lathe"] = list( + "total_materials" = linked_lathe.TotalMaterials(), + "max_materials" = linked_lathe.max_material_storage, + "total_volume" = linked_lathe.reagents.total_volume, + "max_volume" = linked_lathe.reagents.maximum_volume, + "busy" = linked_lathe.busy, + "materials" = linked_lathe.materials, + "reagents" = reagents, + "queue" = queue, + ) + else + data["linked_lathe"] = null - var/list/reagents = list() - for(var/datum/reagent/R in linked_lathe.reagents.reagent_list) - reagents.Add(list(list( - "name" = R.name, - "id" = R.id, - "volume" = R.volume, - ))) - data["info"]["linked_lathe"]["reagents"] = reagents + if(linked_imprinter) + var/list/reagents = list() + for(var/datum/reagent/R as anything in linked_imprinter.reagents.reagent_list) + UNTYPED_LIST_ADD(reagents, list( + "name" = R.name, + "id" = R.id, + "volume" = R.volume + )) - var/list/queue = list() - var/i = 1 - for(var/datum/design/D in linked_lathe.queue) - queue.Add(list(list( - "name" = D.name, - "index" = i, // ugghhhh - ))) - i++ - data["info"]["linked_lathe"]["queue"] = queue + var/list/queue = list() + var/i = 1 + for(var/datum/design/D as anything in linked_imprinter.queue) + UNTYPED_LIST_ADD(queue, list( + "name" = D.name, + "index" = i + )) + i += 1 - data["info"]["linked_imprinter"] = list("present" = FALSE) - if(linked_imprinter) - data["info"]["linked_imprinter"] = list( - "present" = TRUE, - "total_materials" = linked_imprinter.TotalMaterials(), - "max_materials" = linked_imprinter.max_material_storage, - "total_volume" = linked_imprinter.reagents.total_volume, - "max_volume" = linked_imprinter.reagents.maximum_volume, - "busy" = linked_imprinter.busy, - ) + data["linked_imprinter"] = list( + "total_materials" = linked_imprinter.TotalMaterials(), + "max_materials" = linked_imprinter.max_material_storage, + "total_volume" = linked_imprinter.reagents.total_volume, + "max_volume" = linked_imprinter.reagents.maximum_volume, + "busy" = linked_imprinter.busy, + "materials" = linked_imprinter.materials, + "reagents" = reagents, + "queue" = queue + ) + else + data["linked_imprinter"] = null - var/list/materials = list() - for(var/M in linked_imprinter.materials) - var/amount = linked_imprinter.materials[M] - var/hidden_mat = FALSE - for(var/HM in linked_imprinter.hidden_materials) - if(M == HM && amount == 0) - hidden_mat = TRUE - break - if(hidden_mat) - continue - materials.Add(list(list( - "name" = M, - "amount" = amount, - "sheets" = round(amount / SHEET_MATERIAL_AMOUNT), - "removable" = amount >= SHEET_MATERIAL_AMOUNT, - ))) - data["info"]["linked_imprinter"]["mats"] = materials + if(t_disk) + data["t_disk"] = list( + "stored" = t_disk.stored ? list( + "name" = t_disk.stored.name, + "level" = t_disk.stored.level, + "desc" = t_disk.stored.desc, + ) : null, + ) + else + data["t_disk"] = null - var/list/reagents = list() - for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list) - reagents.Add(list(list( - "name" = R.name, - "id" = R.id, - "volume" = R.volume, - ))) - data["info"]["linked_imprinter"]["reagents"] = reagents - - var/list/queue = list() - var/i = 1 - for(var/datum/design/D in linked_imprinter.queue) - queue.Add(list(list( - "name" = D.name, - "index" = i, // ugghhhh - ))) - i++ - data["info"]["linked_imprinter"]["queue"] = queue - - data["info"]["t_disk"] = list("present" = FALSE) - if(t_disk) - data["info"]["t_disk"] = list( - "present" = TRUE, - "stored" = !!t_disk.stored, - ) - if(t_disk.stored) - data["info"]["t_disk"]["name"] = t_disk.stored.name - data["info"]["t_disk"]["level"] = t_disk.stored.level - data["info"]["t_disk"]["desc"] = t_disk.stored.desc - - data["info"]["d_disk"] = list("present" = FALSE) - if(d_disk) - data["info"]["d_disk"] = list( - "present" = TRUE, - "stored" = !!d_disk.blueprint, - ) - if(d_disk.blueprint) - data["info"]["d_disk"]["name"] = d_disk.blueprint.name - data["info"]["d_disk"]["build_type"] = d_disk.blueprint.build_type - data["info"]["d_disk"]["materials"] = d_disk.blueprint.materials + if(d_disk) + data["d_disk"] = list( + "stored" = d_disk.blueprint ? list( + "name" = d_disk.blueprint.name, + "build_type" = d_disk.blueprint.build_type, + "materials" = d_disk.blueprint.materials, + ) : null, + ) + else + data["d_disk"] = null return data @@ -244,6 +214,9 @@ ))) data = sortTim(data, GLOBAL_PROC_REF(cmp_designs_rdconsole), FALSE) + if((ENTRIES_PER_RDPAGE * page) > LAZYLEN(data)) + return null + if(LAZYLEN(data) > ENTRIES_PER_RDPAGE) var/first_index = clamp(ENTRIES_PER_RDPAGE * page, 1, LAZYLEN(data)) var/last_index = min((ENTRIES_PER_RDPAGE * page) + ENTRIES_PER_RDPAGE, LAZYLEN(data) + 1) @@ -282,6 +255,9 @@ ))) data = sortTim(data, GLOBAL_PROC_REF(cmp_designs_rdconsole), FALSE) + if((ENTRIES_PER_RDPAGE * page) > LAZYLEN(data)) + return null + if(LAZYLEN(data) > ENTRIES_PER_RDPAGE) var/first_index = clamp(ENTRIES_PER_RDPAGE * page, 1, LAZYLEN(data)) var/last_index = min((ENTRIES_PER_RDPAGE * page) + ENTRIES_PER_RDPAGE, LAZYLEN(data) + 1) @@ -304,7 +280,11 @@ "id" = D.id, ))) + data = sortTim(data, GLOBAL_PROC_REF(cmp_designs_rdconsole), FALSE) + if((ENTRIES_PER_RDPAGE * page) > LAZYLEN(data)) + return null + if(LAZYLEN(data) > ENTRIES_PER_RDPAGE) var/first_index = clamp(ENTRIES_PER_RDPAGE * page, 1, LAZYLEN(data)) var/last_index = clamp((ENTRIES_PER_RDPAGE * page) + ENTRIES_PER_RDPAGE, 1, LAZYLEN(data) + 1) @@ -318,7 +298,6 @@ return TRUE add_fingerprint(usr) - usr.set_machine(src) switch(action) if("search") @@ -411,8 +390,6 @@ to_chat(usr, span_notice("The destructive analyzer is busy at the moment.")) return - if(tgui_alert(usr, "Proceeding will destroy loaded item. Continue?", "Destructive analyzer confirmation", list("Yes", "No")) != "Yes" || !linked_destroy) - return linked_destroy.busy = 1 busy_msg = "Processing and Updating Database..." flick("d_analyzer_process", linked_destroy) diff --git a/code/modules/shuttles/shuttle.dm b/code/modules/shuttles/shuttle.dm index 51d2d9ba365..9f457863cee 100644 --- a/code/modules/shuttles/shuttle.dm +++ b/code/modules/shuttles/shuttle.dm @@ -295,9 +295,9 @@ var/new_grav = 1 if(destination.flags & SLANDMARK_FLAG_ZERO_G) var/area/new_area = get_area(destination) - new_grav = new_area.has_gravity + new_grav = new_area.get_gravity() for(var/area/our_area in shuttle_area) - if(our_area.has_gravity != new_grav) + if(our_area.get_gravity() != new_grav) our_area.gravitychange(new_grav) // TODO - Old code used to throw stuff out of the way instead of squashing. Should we? diff --git a/code/modules/vehicles/Securitrain_vr.dm b/code/modules/vehicles/Securitrain_vr.dm index 0dd72534d8a..883d2013df0 100644 --- a/code/modules/vehicles/Securitrain_vr.dm +++ b/code/modules/vehicles/Securitrain_vr.dm @@ -182,7 +182,7 @@ if(is_train_head() && istype(load, /mob/living/carbon/human)) var/mob/living/carbon/human/D = load - to_chat(D, span_danger("You ran over \the [M]!") + to_chat(D, span_danger("You ran over \the [M]!")) visible_message(span_danger("\The [src] ran over \the [M]!")) add_attack_logs(D,M,"Ran over with [src.name]") attack_log += text("\[[time_stamp()]\] [span_red("ran over [M.name] ([M.ckey]), driven by [D.name] ([D.ckey])")]") diff --git a/code/modules/vore/eating/belly_messages.dm b/code/modules/vore/eating/belly_messages.dm new file mode 100644 index 00000000000..a50765cfb98 --- /dev/null +++ b/code/modules/vore/eating/belly_messages.dm @@ -0,0 +1,507 @@ +/obj/belly + // Don't forget to watch your commas at the end of each line if you change these. + var/list/struggle_messages_outside = list( + "%pred's %belly wobbles with a squirming meal.", + "%pred's %belly jostles with movement.", + "%pred's %belly briefly swells outward as someone pushes from inside.", + "%pred's %belly fidgets with a trapped victim.", + "%pred's %belly jiggles with motion from inside.", + "%pred's %belly sloshes around.", + "%pred's %belly gushes softly.", + "%pred's %belly lets out a wet squelch.") + + var/list/struggle_messages_inside = list( + "Your useless squirming only causes %pred's slimy %belly to squelch over your body.", + "Your struggles only cause %pred's %belly to gush softly around you.", + "Your movement only causes %pred's %belly to slosh around you.", + "Your motion causes %pred's %belly to jiggle.", + "You fidget around inside of %pred's %belly.", + "You shove against the walls of %pred's %belly, making it briefly swell outward.", + "You jostle %pred's %belly with movement.", + "You squirm inside of %pred's %belly, making it wobble around.") + + var/list/absorbed_struggle_messages_outside = list( + "%pred's %belly wobbles, seemingly on its own.", + "%pred's %belly jiggles without apparent cause.", + "%pred's %belly seems to shake for a second without an obvious reason.") + + var/list/absorbed_struggle_messages_inside = list( + "You try and resist %pred's %belly, but only cause it to jiggle slightly.", + "Your fruitless mental struggles only shift %pred's %belly a tiny bit.", + "You can't make any progress freeing yourself from %pred's %belly.") + + var/list/escape_attempt_messages_owner = list( + "%prey is attempting to free themselves from your %belly!") + + var/list/escape_attempt_messages_prey = list( + "You start to climb out of %pred's %belly.") + + var/list/escape_messages_owner = list( + "%prey climbs out of your %belly!") + + var/list/escape_messages_prey = list( + "You climb out of %pred's %belly.") + + var/list/escape_messages_outside = list( + "%prey climbs out of %pred's %belly!") + + var/list/escape_item_messages_owner = list( + "%item suddenly slips out of your %belly!") + + var/list/escape_item_messages_prey = list( + "Your struggles successfully cause %pred to squeeze your %item out of their %belly.") + + var/list/escape_item_messages_outside = list( + "%item suddenly slips out of %pred's %belly!") + + var/list/escape_fail_messages_owner = list( + "%prey's attempt to escape from your %belly has failed!") + + var/list/escape_fail_messages_prey = list( + "Your attempt to escape %pred's %belly has failed!") + + var/list/escape_attempt_absorbed_messages_owner = list( + "%prey is attempting to free themselves from your %belly!") + + var/list/escape_attempt_absorbed_messages_prey = list( + "You try to force yourself out of %pred's %belly.") + + var/list/escape_absorbed_messages_owner = list( + "%prey forces themselves free of your %belly!") + + var/list/escape_absorbed_messages_prey = list( + "You manage to free yourself from %pred's %belly.") + + var/list/escape_absorbed_messages_outside = list( + "%prey climbs out of %pred's %belly!") + + var/list/escape_fail_absorbed_messages_owner = list( + "%prey's attempt to escape form your %belly has failed!") + + var/list/escape_fail_absorbed_messages_prey = list( + "Before you manage to reach freedom, you feel yourself getting dragged back into %pred's %belly!") + + var/list/primary_transfer_messages_owner = list( + "%prey slid into your %dest due to their struggling inside your %belly!") + + var/list/primary_transfer_messages_prey = list( + "Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into pred's %dest!") + + var/list/secondary_transfer_messages_owner = list( + "%prey slid into your %dest due to their struggling inside your %belly!") + + var/list/secondary_transfer_messages_prey = list( + "Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into pred's %dest!") + + var/list/digest_chance_messages_owner = list( + "You feel your %belly beginning to become active!") + + var/list/digest_chance_messages_prey = list( + "In response to your struggling, %pred's %belly begins to get more active...") + + var/list/absorb_chance_messages_owner = list( + "You feel your %belly start to cling onto its contents...") + + var/list/absorb_chance_messages_prey = list( + "In response to your struggling, %pred's %belly begins to cling more tightly...") + + var/list/select_chance_messages_owner = list( + "You feel your %belly beginning to become active!") + + var/list/select_chance_messages_prey = list( + "In response to your struggling, %pred's %belly begins to get more active...") + + var/list/digest_messages_owner = list( + "You feel %prey's body succumb to your digestive system, which breaks it apart into soft slurry.", + "You hear a lewd glorp as your %belly muscles grind %prey into a warm pulp.", + "Your %belly lets out a rumble as it melts %prey into sludge.", + "You feel a soft gurgle as %prey's body loses form in your %belly. They're nothing but a soft mass of churning slop now.", + "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your thighs.", + "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your rump.", + "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your belly.", + "Your %belly groans as %prey falls apart into a thick soup. You can feel their remains soon flowing deeper into your body to be absorbed.", + "Your %belly kneads on every fiber of %prey, softening them down into mush to fuel your next hunt.", + "Your %belly churns %prey down into a hot slush. You can feel the nutrients coursing through your digestive track with a series of long, wet glorps.") + + var/list/digest_messages_prey = list( + "Your body succumbs to %pred's digestive system, which breaks you apart into soft slurry.", + "%pred's %belly lets out a lewd glorp as their muscles grind you into a warm pulp.", + "%pred's %belly lets out a rumble as it melts you into sludge.", + "%pred feels a soft gurgle as your body loses form in their %belly. You're nothing but a soft mass of churning slop now.", + "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's thighs.", + "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's rump.", + "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's belly.", + "%pred's %belly groans as you fall apart into a thick soup. Your remains soon flow deeper into %pred's body to be absorbed.", + "%pred's %belly kneads on every fiber of your body, softening you down into mush to fuel their next hunt.", + "%pred's %belly churns you down into a hot slush. Your nutrient-rich remains course through their digestive track with a series of long, wet glorps.") + + var/list/absorb_messages_owner = list( + "You feel %prey becoming part of you.") + + var/list/absorb_messages_prey = list( + "You feel yourself becoming part of %pred's %belly!") + + var/list/unabsorb_messages_owner = list( + "You feel %prey reform into a recognizable state again.") + + var/list/unabsorb_messages_prey = list( + "You are released from being part of %pred's %belly.") + + var/list/examine_messages = list( + "They have something solid in their %belly!", + "It looks like they have something in their %belly!") + + var/list/examine_messages_absorbed = list( + "Their body looks somewhat larger than usual around the area of their %belly.", + "Their %belly looks larger than usual.") + +GLOBAL_LIST_INIT(vore_words_goo, list("muck","goo","sludge","slime","mire","ectoplasm","quagmire","glop","jelly","ooze","slush","mush","quicksand"))//%goo +GLOBAL_LIST_INIT(vore_words_hbellynoises, list("gurgle","gloorp","squelch","gloosh","squish","groan","grrrrrrn","sloooooOrp","slooosh","grrrbles","worbles"))//%happybelly +GLOBAL_LIST_INIT(vore_words_fat, list("love handles","fat","pudge","plumpness","squish","chunk","meat","softness","blubber","flab","paunch","hip dip","mass","dough","chub","marshmellowy goodness","girth","fluff","thickness","jello","adipose "))//%fat +GLOBAL_LIST_INIT(vore_words_grip, list("grip","grasp","clutch","hold"))//%grip +GLOBAL_LIST_INIT(vore_words_cozyholdingwords, list("soft","cozy","comfortable","gentle","snug","safe","restful","snuggly","intimate","secure"))//%cozy +GLOBAL_LIST_INIT(vore_words_angry, list("hated","unsafe","angry"))//%angry +GLOBAL_LIST_INIT(vore_words_acid, list("acid","burbling goo","angry slop","chime","devouring liquid","slop","liquid","goo","mush","boiling liquid","hot oil"))//%acid +GLOBAL_LIST_INIT(vore_words_snackname, list("snack","lunch","meat","calories","food","meal","dinner","chow","future pudge","fuel"))//%snack +GLOBAL_LIST_INIT(vore_words_hot, list("sweltering","hot","boiling","sizzling","burning","steaming","firey"))//%hot +GLOBAL_LIST_INIT(vore_words_snake, list("snake","serpent","reptilian","noodle","snek","noperope","throattube","armless mouth"))//%snake + +/// Replaces a bunch of format strings with relevant messages. +/// `prey` may be a string or a specific prey ref. +/obj/belly/proc/belly_format_string(message, prey, use_absorbed_count = FALSE, item = null, dest = null, use_first_only = FALSE) + if(islist(message)) + . = "[pick(message)]" + else + . = "[message]" + + . = replacetext(., "%belly", lowertext(name)) + . = replacetext(., "%pred", owner) + . = replacetext(., "%prey", prey) + + var/total_prey_count = 0 + var/all_object_and_prey_count = LAZYLEN(contents) + var/ghost_count = 0 + var/absorbed_count = 0 + for(var/mob/M in contents) + total_prey_count++ + + if(isobserver(M)) + all_object_and_prey_count-- + ghost_count++ + + if(isliving(M)) + var/mob/living/L = M + if(L.absorbed) + absorbed_count++ + + . = replacetext(., "%countpreytotal", total_prey_count) + . = replacetext(., "%countpreyabsorbed", absorbed_count) + . = replacetext(., "%countprey", use_absorbed_count ? absorbed_count : total_prey_count) + . = replacetext(., "%countghosts", ghost_count) + . = replacetext(., "%count", all_object_and_prey_count) + + if(!isnull(item)) + . = replacetext(., "%item", item) + if(!isnull(dest)) + . = replacetext(., "%dest", dest) + + // Belly messages + . = replacetext(., "%goo", use_first_only ? GLOB.vore_words_goo[1] : pick(GLOB.vore_words_goo)) + . = replacetext(., "%happybelly", use_first_only ? GLOB.vore_words_hbellynoises[1] : pick(GLOB.vore_words_hbellynoises)) + . = replacetext(., "%fat", use_first_only ? GLOB.vore_words_fat[1] : pick(GLOB.vore_words_fat)) + . = replacetext(., "%grip", use_first_only ? GLOB.vore_words_grip[1] : pick(GLOB.vore_words_grip)) + . = replacetext(., "%cozy", use_first_only ? GLOB.vore_words_cozyholdingwords[1] : pick(GLOB.vore_words_cozyholdingwords)) + . = replacetext(., "%angry", use_first_only ? GLOB.vore_words_angry[1] : pick(GLOB.vore_words_angry)) + . = replacetext(., "%acid", use_first_only ? GLOB.vore_words_acid[1] : pick(GLOB.vore_words_acid)) + . = replacetext(., "%snack", use_first_only ? GLOB.vore_words_snackname[1] : pick(GLOB.vore_words_snackname)) + . = replacetext(., "%hot", use_first_only ? GLOB.vore_words_hot[1] : pick(GLOB.vore_words_hot)) + . = replacetext(., "%snake", use_first_only ? GLOB.vore_words_snake[1] : pick(GLOB.vore_words_snake)) + +// Get the line that should show up in Examine message if the owner of this belly +// is examined. By making this a proc, we not only take advantage of polymorphism, +// but can easily make the message vary based on how many people are inside, etc. +// Returns a string which shoul be appended to the Examine output. +/obj/belly/proc/get_examine_msg() + if(!(contents.len) || !(examine_messages.len)) + return "" + + var/raw_message = pick(examine_messages) + var/total_bulge = 0 + + var/list/vore_contents = list() + for(var/G in contents) + if(!isobserver(G)) + vore_contents += G //Exclude any ghosts from %prey + + for(var/mob/living/P in contents) + if(!P.absorbed) //This is required first, in case there's a person absorbed and not absorbed in a stomach. + total_bulge += P.size_multiplier + + if(total_bulge < bulge_size || bulge_size == 0) + return "" + + return(span_red("[belly_format_string(raw_message, english_list(vore_contents))]")) + +/obj/belly/proc/get_examine_msg_absorbed() + if(!(contents.len) || !(examine_messages_absorbed.len) || !display_absorbed_examine) + return "" + + var/raw_message = pick(examine_messages_absorbed) + + var/absorbed_count = 0 + var/list/absorbed_victims = list() + for(var/mob/living/L in contents) + if(L.absorbed) + absorbed_victims += L + absorbed_count++ + + if(!absorbed_count) + return "" + + return(span_red("[belly_format_string(raw_message, english_list(absorbed_victims), use_absorbed_count = TRUE)]")) + +// The next function gets the messages set on the belly, in human-readable format. +// This is useful in customization boxes and such. The delimiter right now is \n\n so +// in message boxes, this looks nice and is easily delimited. +/obj/belly/proc/get_messages(type, delim = "\n\n") + ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") + + var/list/raw_messages + switch(type) + if("smo") + raw_messages = struggle_messages_outside + if("smi") + raw_messages = struggle_messages_inside + if("asmo") + raw_messages = absorbed_struggle_messages_outside + if("asmi") + raw_messages = absorbed_struggle_messages_inside + if("escao") + raw_messages = escape_attempt_messages_owner + if("escap") + raw_messages = escape_attempt_messages_prey + if("esco") + raw_messages = escape_messages_owner + if("escp") + raw_messages = escape_messages_prey + if("escout") + raw_messages = escape_messages_outside + if("escio") + raw_messages = escape_item_messages_owner + if("escip") + raw_messages = escape_item_messages_prey + if("esciout") + raw_messages = escape_item_messages_outside + if("escfo") + raw_messages = escape_fail_messages_owner + if("escfp") + raw_messages = escape_fail_messages_prey + if("aescao") + raw_messages = escape_attempt_absorbed_messages_owner + if("aescap") + raw_messages = escape_attempt_absorbed_messages_prey + if("aesco") + raw_messages = escape_absorbed_messages_owner + if("aescp") + raw_messages = escape_absorbed_messages_prey + if("aescout") + raw_messages = escape_absorbed_messages_outside + if("aescfo") + raw_messages = escape_fail_absorbed_messages_owner + if("aescfp") + raw_messages = escape_fail_absorbed_messages_prey + if("trnspo") + raw_messages = primary_transfer_messages_owner + if("trnspp") + raw_messages = primary_transfer_messages_prey + if("trnsso") + raw_messages = secondary_transfer_messages_owner + if("trnssp") + raw_messages = secondary_transfer_messages_prey + if("stmodo") + raw_messages = digest_chance_messages_owner + if("stmodp") + raw_messages = digest_chance_messages_prey + if("stmoao") + raw_messages = absorb_chance_messages_owner + if("stmoap") + raw_messages = absorb_chance_messages_prey + if("dmo") + raw_messages = digest_messages_owner + if("dmp") + raw_messages = digest_messages_prey + if("em") + raw_messages = examine_messages + if("ema") + raw_messages = examine_messages_absorbed + if("amo") + raw_messages = absorb_messages_owner + if("amp") + raw_messages = absorb_messages_prey + if("uamo") + raw_messages = unabsorb_messages_owner + if("uamp") + raw_messages = unabsorb_messages_prey + if("im_digest") + raw_messages = emote_lists[DM_DIGEST] + if("im_hold") + raw_messages = emote_lists[DM_HOLD] + if("im_holdabsorbed") + raw_messages = emote_lists[DM_HOLD_ABSORBED] + if("im_absorb") + raw_messages = emote_lists[DM_ABSORB] + if("im_heal") + raw_messages = emote_lists[DM_HEAL] + if("im_drain") + raw_messages = emote_lists[DM_DRAIN] + if("im_steal") + raw_messages = emote_lists[DM_SIZE_STEAL] + if("im_egg") + raw_messages = emote_lists[DM_EGG] + if("im_shrink") + raw_messages = emote_lists[DM_SHRINK] + if("im_grow") + raw_messages = emote_lists[DM_GROW] + if("im_unabsorb") + raw_messages = emote_lists[DM_UNABSORB] + var/messages = null + if(raw_messages) + messages = raw_messages.Join(delim) + return messages + +// The next function sets the messages on the belly, from human-readable var +// replacement strings and linebreaks as delimiters (two \n\n by default). +// They also sanitize the messages. +// Give them a limit for each type... +/obj/belly/proc/set_messages(raw_text, type, delim = "\n\n", limit) + if(!limit) + CRASH("[src] set message called without limit!") + ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") + + var/list/raw_list + + if(findtext(raw_text, delim)) + raw_list = splittext(html_encode(raw_text), delim) + else + raw_list = list(raw_text) + for(var/i = 1, i <= raw_list.len, i++) + if(!length(raw_list[i])) + raw_list.Cut(i, i + 1) + i-- + if(raw_list.len > 10) + raw_list.Cut(11) + log_debug("[owner] tried to set [lowertext(name)] with 11+ messages") + + var/realIndex = 0 + for(var/i = 1, i <= raw_list.len, i++) + realIndex++ + raw_list[i] = readd_quotes(raw_list[i]) + //Also fix % sign for var replacement + raw_list[i] = replacetext(raw_list[i],"%","%") + if(length(raw_list[i]) > limit || length(raw_list[i]) < 10) + to_chat(owner, span_warning("One of the message for [lowertext(name)] exceeded the limit of [limit] characters or has been below the lower limit of 10 characters and has been removed. Actual length: [length(raw_list[i])]")) + //Reflect message to the player so that they don't just lose it + to_chat(owner, span_warning("Message [realIndex]: [raw_list[i]]")) + log_debug("[owner] tried to set [lowertext(name)] [type] message with >[limit] or <10 characters") + raw_list.Cut(i, i + 1) + i-- + + ASSERT(raw_list.len <= 10) //Sanity + + switch(type) + if("smo") + struggle_messages_outside = raw_list + if("smi") + struggle_messages_inside = raw_list + if("asmo") + absorbed_struggle_messages_outside = raw_list + if("asmi") + absorbed_struggle_messages_inside = raw_list + if("escao") + escape_attempt_messages_owner = raw_list + if("escap") + escape_attempt_messages_prey = raw_list + if("esco") + escape_messages_owner = raw_list + if("escp") + escape_messages_prey = raw_list + if("escout") + escape_messages_outside = raw_list + if("escio") + escape_item_messages_owner = raw_list + if("escip") + escape_item_messages_prey = raw_list + if("esciout") + escape_item_messages_outside = raw_list + if("escfo") + escape_fail_messages_owner = raw_list + if("escfp") + escape_fail_messages_prey = raw_list + if("aescao") + escape_attempt_absorbed_messages_owner = raw_list + if("aescap") + escape_attempt_absorbed_messages_prey = raw_list + if("aesco") + escape_absorbed_messages_owner = raw_list + if("aescp") + escape_absorbed_messages_prey = raw_list + if("aescout") + escape_absorbed_messages_outside = raw_list + if("aescfo") + escape_fail_absorbed_messages_owner = raw_list + if("aescfp") + escape_fail_absorbed_messages_prey = raw_list + if("trnspo") + primary_transfer_messages_owner = raw_list + if("trnspp") + primary_transfer_messages_prey = raw_list + if("trnsso") + secondary_transfer_messages_owner = raw_list + if("trnssp") + secondary_transfer_messages_prey = raw_list + if("stmodo") + digest_chance_messages_owner = raw_list + if("stmodp") + digest_chance_messages_prey = raw_list + if("stmoao") + absorb_chance_messages_owner = raw_list + if("stmoap") + absorb_chance_messages_prey = raw_list + if("dmo") + digest_messages_owner = raw_list + if("dmp") + digest_messages_prey = raw_list + if("amo") + absorb_messages_owner = raw_list + if("amp") + absorb_messages_prey = raw_list + if("uamo") + unabsorb_messages_owner = raw_list + if("uamp") + unabsorb_messages_prey = raw_list + if("em") + examine_messages = raw_list + if("ema") + examine_messages_absorbed = raw_list + if("im_digest") + emote_lists[DM_DIGEST] = raw_list + if("im_hold") + emote_lists[DM_HOLD] = raw_list + if("im_holdabsorbed") + emote_lists[DM_HOLD_ABSORBED] = raw_list + if("im_absorb") + emote_lists[DM_ABSORB] = raw_list + if("im_heal") + emote_lists[DM_HEAL] = raw_list + if("im_drain") + emote_lists[DM_DRAIN] = raw_list + if("im_steal") + emote_lists[DM_SIZE_STEAL] = raw_list + if("im_egg") + emote_lists[DM_EGG] = raw_list + if("im_shrink") + emote_lists[DM_SHRINK] = raw_list + if("im_grow") + emote_lists[DM_GROW] = raw_list + if("im_unabsorb") + emote_lists[DM_UNABSORB] = raw_list diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index 804f28a8c51..73c99c9e6cf 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -116,162 +116,6 @@ var/tmp/recent_sound = FALSE // Prevent audio spam var/tmp/drainmode = DR_NORMAL // Simply drains the prey then does nothing. - // Don't forget to watch your commas at the end of each line if you change these. - var/list/struggle_messages_outside = list( - "%pred's %belly wobbles with a squirming meal.", - "%pred's %belly jostles with movement.", - "%pred's %belly briefly swells outward as someone pushes from inside.", - "%pred's %belly fidgets with a trapped victim.", - "%pred's %belly jiggles with motion from inside.", - "%pred's %belly sloshes around.", - "%pred's %belly gushes softly.", - "%pred's %belly lets out a wet squelch.") - - var/list/struggle_messages_inside = list( - "Your useless squirming only causes %pred's slimy %belly to squelch over your body.", - "Your struggles only cause %pred's %belly to gush softly around you.", - "Your movement only causes %pred's %belly to slosh around you.", - "Your motion causes %pred's %belly to jiggle.", - "You fidget around inside of %pred's %belly.", - "You shove against the walls of %pred's %belly, making it briefly swell outward.", - "You jostle %pred's %belly with movement.", - "You squirm inside of %pred's %belly, making it wobble around.") - - var/list/absorbed_struggle_messages_outside = list( - "%pred's %belly wobbles, seemingly on its own.", - "%pred's %belly jiggles without apparent cause.", - "%pred's %belly seems to shake for a second without an obvious reason.") - - var/list/absorbed_struggle_messages_inside = list( - "You try and resist %pred's %belly, but only cause it to jiggle slightly.", - "Your fruitless mental struggles only shift %pred's %belly a tiny bit.", - "You can't make any progress freeing yourself from %pred's %belly.") - - var/list/escape_attempt_messages_owner = list( - "%prey is attempting to free themselves from your %belly!") - - var/list/escape_attempt_messages_prey = list( - "You start to climb out of %pred's %belly.") - - var/list/escape_messages_owner = list( - "%prey climbs out of your %belly!") - - var/list/escape_messages_prey = list( - "You climb out of %pred's %belly.") - - var/list/escape_messages_outside = list( - "%prey climbs out of %pred's %belly!") - - var/list/escape_item_messages_owner = list( - "%item suddenly slips out of your %belly!") - - var/list/escape_item_messages_prey = list( - "Your struggles successfully cause %pred to squeeze your %item out of their %belly.") - - var/list/escape_item_messages_outside = list( - "%item suddenly slips out of %pred's %belly!") - - var/list/escape_fail_messages_owner = list( - "%prey's attempt to escape from your %belly has failed!") - - var/list/escape_fail_messages_prey = list( - "Your attempt to escape %pred's %belly has failed!") - - var/list/escape_attempt_absorbed_messages_owner = list( - "%prey is attempting to free themselves from your %belly!") - - var/list/escape_attempt_absorbed_messages_prey = list( - "You try to force yourself out of %pred's %belly.") - - var/list/escape_absorbed_messages_owner = list( - "%prey forces themselves free of your %belly!") - - var/list/escape_absorbed_messages_prey = list( - "You manage to free yourself from %pred's %belly.") - - var/list/escape_absorbed_messages_outside = list( - "%prey climbs out of %pred's %belly!") - - var/list/escape_fail_absorbed_messages_owner = list( - "%prey's attempt to escape form your %belly has failed!") - - var/list/escape_fail_absorbed_messages_prey = list( - "Before you manage to reach freedom, you feel yourself getting dragged back into %pred's %belly!") - - var/list/primary_transfer_messages_owner = list( - "%prey slid into your %dest due to their struggling inside your %belly!") - - var/list/primary_transfer_messages_prey = list( - "Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into pred's %dest!") - - var/list/secondary_transfer_messages_owner = list( - "%prey slid into your %dest due to their struggling inside your %belly!") - - var/list/secondary_transfer_messages_prey = list( - "Your attempt to escape %pred's %belly has failed and your struggles only results in you sliding into pred's %dest!") - - var/list/digest_chance_messages_owner = list( - "You feel your %belly beginning to become active!") - - var/list/digest_chance_messages_prey = list( - "In response to your struggling, %pred's %belly begins to get more active...") - - var/list/absorb_chance_messages_owner = list( - "You feel your %belly start to cling onto its contents...") - - var/list/absorb_chance_messages_prey = list( - "In response to your struggling, %pred's %belly begins to cling more tightly...") - - var/list/select_chance_messages_owner = list( - "You feel your %belly beginning to become active!") - - var/list/select_chance_messages_prey = list( - "In response to your struggling, %pred's %belly begins to get more active...") - - var/list/digest_messages_owner = list( - "You feel %prey's body succumb to your digestive system, which breaks it apart into soft slurry.", - "You hear a lewd glorp as your %belly muscles grind %prey into a warm pulp.", - "Your %belly lets out a rumble as it melts %prey into sludge.", - "You feel a soft gurgle as %prey's body loses form in your %belly. They're nothing but a soft mass of churning slop now.", - "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your thighs.", - "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your rump.", - "Your %belly begins gushing %prey's remains through your system, adding some extra weight to your belly.", - "Your %belly groans as %prey falls apart into a thick soup. You can feel their remains soon flowing deeper into your body to be absorbed.", - "Your %belly kneads on every fiber of %prey, softening them down into mush to fuel your next hunt.", - "Your %belly churns %prey down into a hot slush. You can feel the nutrients coursing through your digestive track with a series of long, wet glorps.") - - var/list/digest_messages_prey = list( - "Your body succumbs to %pred's digestive system, which breaks you apart into soft slurry.", - "%pred's %belly lets out a lewd glorp as their muscles grind you into a warm pulp.", - "%pred's %belly lets out a rumble as it melts you into sludge.", - "%pred feels a soft gurgle as your body loses form in their %belly. You're nothing but a soft mass of churning slop now.", - "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's thighs.", - "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's rump.", - "%pred's %belly begins gushing your remains through their system, adding some extra weight to %pred's belly.", - "%pred's %belly groans as you fall apart into a thick soup. Your remains soon flow deeper into %pred's body to be absorbed.", - "%pred's %belly kneads on every fiber of your body, softening you down into mush to fuel their next hunt.", - "%pred's %belly churns you down into a hot slush. Your nutrient-rich remains course through their digestive track with a series of long, wet glorps.") - - var/list/absorb_messages_owner = list( - "You feel %prey becoming part of you.") - - var/list/absorb_messages_prey = list( - "You feel yourself becoming part of %pred's %belly!") - - var/list/unabsorb_messages_owner = list( - "You feel %prey reform into a recognizable state again.") - - var/list/unabsorb_messages_prey = list( - "You are released from being part of %pred's %belly.") - - var/list/examine_messages = list( - "They have something solid in their %belly!", - "It looks like they have something in their %belly!") - - var/list/examine_messages_absorbed = list( - "Their body looks somewhat larger than usual around the area of their %belly.", - "Their %belly looks larger than usual.") - var/item_digest_mode = IM_DIGEST_FOOD // Current item-related mode from item_digest_modes var/contaminates = FALSE // Whether the belly will contaminate stuff var/contamination_flavor = "Generic" // Determines descriptions of contaminated items @@ -422,11 +266,7 @@ if(istype(thing, /mob/observer)) //Ports CHOMPStation PR#3072 if(desc) //Ports CHOMPStation PR#4772 //Allow ghosts see where they are if they're still getting squished along inside. - var/formatted_desc - formatted_desc = replacetext(desc, "%belly", lowertext(name)) //replace with this belly's name - formatted_desc = replacetext(formatted_desc, "%pred", owner) //replace with this belly's owner - formatted_desc = replacetext(formatted_desc, "%prey", thing) //replace with whatever mob entered into this belly - to_chat(thing, span_notice("[formatted_desc]")) + to_chat(thing, span_vnotice("[belly_format_string(desc, thing)]")) if(OldLoc in contents) return //Someone dropping something (or being stripdigested) @@ -459,11 +299,7 @@ //Was there a description text? If so, it's time to format it! if(raw_desc) //Replace placeholder vars - var/formatted_desc - formatted_desc = replacetext(raw_desc, "%belly", lowertext(name)) //replace with this belly's name - formatted_desc = replacetext(formatted_desc, "%pred", owner) //replace with this belly's owner - formatted_desc = replacetext(formatted_desc, "%prey", M) //replace with whatever mob entered into this belly - to_chat(M, span_vnotice("[formatted_desc]")) + to_chat(M, span_vnotice("[belly_format_string(raw_desc, M)]")) var/taste if(can_taste && (taste = M.get_taste_message(FALSE))) @@ -753,318 +589,6 @@ if(owner.mind) owner.mind.vore_prey_eaten++ -// Get the line that should show up in Examine message if the owner of this belly -// is examined. By making this a proc, we not only take advantage of polymorphism, -// but can easily make the message vary based on how many people are inside, etc. -// Returns a string which shoul be appended to the Examine output. -/obj/belly/proc/get_examine_msg() - if(!(contents.len) || !(examine_messages.len)) - return "" - - var/formatted_message - var/raw_message = pick(examine_messages) - var/total_bulge = 0 - - var/living_count = 0 - for(var/mob/living/L in contents) - living_count++ - - var/count_total = contents.len - for(var/mob/observer/C in contents) - count_total-- //Exclude any ghosts from %count - - var/list/vore_contents = list() - for(var/G in contents) - if(!isobserver(G)) - vore_contents += G //Exclude any ghosts from %prey - - for(var/mob/living/P in contents) - if(!P.absorbed) //This is required first, in case there's a person absorbed and not absorbed in a stomach. - total_bulge += P.size_multiplier - - if(total_bulge < bulge_size || bulge_size == 0) - return "" - - formatted_message = replacetext(raw_message, "%belly", lowertext(name)) - formatted_message = replacetext(formatted_message, "%pred", owner) - formatted_message = replacetext(formatted_message, "%prey", english_list(vore_contents)) - formatted_message = replacetext(formatted_message, "%countprey", living_count) - formatted_message = replacetext(formatted_message, "%count", count_total) - - return(span_red("[formatted_message]")) - -/obj/belly/proc/get_examine_msg_absorbed() - if(!(contents.len) || !(examine_messages_absorbed.len) || !display_absorbed_examine) - return "" - - var/formatted_message - var/raw_message = pick(examine_messages_absorbed) - - var/absorbed_count = 0 - var/list/absorbed_victims = list() - for(var/mob/living/L in contents) - if(L.absorbed) - absorbed_victims += L - absorbed_count++ - - if(!absorbed_count) - return "" - - formatted_message = replacetext(raw_message, "%belly", lowertext(name)) - formatted_message = replacetext(formatted_message, "%pred", owner) - formatted_message = replacetext(formatted_message, "%prey", english_list(absorbed_victims)) - formatted_message = replacetext(formatted_message, "%countprey", absorbed_count) - - return(span_red("[formatted_message]")) - -// The next function gets the messages set on the belly, in human-readable format. -// This is useful in customization boxes and such. The delimiter right now is \n\n so -// in message boxes, this looks nice and is easily delimited. -/obj/belly/proc/get_messages(type, delim = "\n\n") - ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") - - var/list/raw_messages - switch(type) - if("smo") - raw_messages = struggle_messages_outside - if("smi") - raw_messages = struggle_messages_inside - if("asmo") - raw_messages = absorbed_struggle_messages_outside - if("asmi") - raw_messages = absorbed_struggle_messages_inside - if("escao") - raw_messages = escape_attempt_messages_owner - if("escap") - raw_messages = escape_attempt_messages_prey - if("esco") - raw_messages = escape_messages_owner - if("escp") - raw_messages = escape_messages_prey - if("escout") - raw_messages = escape_messages_outside - if("escio") - raw_messages = escape_item_messages_owner - if("escip") - raw_messages = escape_item_messages_prey - if("esciout") - raw_messages = escape_item_messages_outside - if("escfo") - raw_messages = escape_fail_messages_owner - if("escfp") - raw_messages = escape_fail_messages_prey - if("aescao") - raw_messages = escape_attempt_absorbed_messages_owner - if("aescap") - raw_messages = escape_attempt_absorbed_messages_prey - if("aesco") - raw_messages = escape_absorbed_messages_owner - if("aescp") - raw_messages = escape_absorbed_messages_prey - if("aescout") - raw_messages = escape_absorbed_messages_outside - if("aescfo") - raw_messages = escape_fail_absorbed_messages_owner - if("aescfp") - raw_messages = escape_fail_absorbed_messages_prey - if("trnspo") - raw_messages = primary_transfer_messages_owner - if("trnspp") - raw_messages = primary_transfer_messages_prey - if("trnsso") - raw_messages = secondary_transfer_messages_owner - if("trnssp") - raw_messages = secondary_transfer_messages_prey - if("stmodo") - raw_messages = digest_chance_messages_owner - if("stmodp") - raw_messages = digest_chance_messages_prey - if("stmoao") - raw_messages = absorb_chance_messages_owner - if("stmoap") - raw_messages = absorb_chance_messages_prey - if("dmo") - raw_messages = digest_messages_owner - if("dmp") - raw_messages = digest_messages_prey - if("em") - raw_messages = examine_messages - if("ema") - raw_messages = examine_messages_absorbed - if("amo") - raw_messages = absorb_messages_owner - if("amp") - raw_messages = absorb_messages_prey - if("uamo") - raw_messages = unabsorb_messages_owner - if("uamp") - raw_messages = unabsorb_messages_prey - if("im_digest") - raw_messages = emote_lists[DM_DIGEST] - if("im_hold") - raw_messages = emote_lists[DM_HOLD] - if("im_holdabsorbed") - raw_messages = emote_lists[DM_HOLD_ABSORBED] - if("im_absorb") - raw_messages = emote_lists[DM_ABSORB] - if("im_heal") - raw_messages = emote_lists[DM_HEAL] - if("im_drain") - raw_messages = emote_lists[DM_DRAIN] - if("im_steal") - raw_messages = emote_lists[DM_SIZE_STEAL] - if("im_egg") - raw_messages = emote_lists[DM_EGG] - if("im_shrink") - raw_messages = emote_lists[DM_SHRINK] - if("im_grow") - raw_messages = emote_lists[DM_GROW] - if("im_unabsorb") - raw_messages = emote_lists[DM_UNABSORB] - var/messages = null - if(raw_messages) - messages = raw_messages.Join(delim) - return messages - -// The next function sets the messages on the belly, from human-readable var -// replacement strings and linebreaks as delimiters (two \n\n by default). -// They also sanitize the messages. -// Give them a limit for each type... -/obj/belly/proc/set_messages(raw_text, type, delim = "\n\n", limit) - if(!limit) - CRASH("[src] set message called without limit!") - ASSERT(type == "smo" || type == "smi" || type == "asmo" || type == "asmi" || type == "escao" || type == "escap" || type == "escp" || type == "esco" || type == "escout" || type == "escip" || type == "escio" || type == "esciout" || type == "escfp" || type == "escfo" || type == "aescao" || type == "aescap" || type == "aescp" || type == "aesco" || type == "aescout" || type == "aescfp" || type == "aescfo" || type == "trnspp" || type == "trnspo" || type == "trnssp" || type == "trnsso" || type == "stmodp" || type == "stmodo" || type == "stmoap" || type == "stmoao" || type == "dmo" || type == "dmp" || type == "amo" || type == "amp" || type == "uamo" || type == "uamp" || type == "em" || type == "ema" || type == "im_digest" || type == "im_hold" || type == "im_holdabsorbed" || type == "im_absorb" || type == "im_heal" || type == "im_drain" || type == "im_steal" || type == "im_egg" || type == "im_shrink" || type == "im_grow" || type == "im_unabsorb") - - var/list/raw_list - - if(findtext(raw_text, delim)) - raw_list = splittext(html_encode(raw_text), delim) - else - raw_list = list(raw_text) - for(var/i = 1, i <= raw_list.len, i++) - if(!length(raw_list[i])) - raw_list.Cut(i, i + 1) - i-- - if(raw_list.len > 10) - raw_list.Cut(11) - log_debug("[owner] tried to set [lowertext(name)] with 11+ messages") - - var/realIndex = 0 - for(var/i = 1, i <= raw_list.len, i++) - realIndex++ - raw_list[i] = readd_quotes(raw_list[i]) - //Also fix % sign for var replacement - raw_list[i] = replacetext(raw_list[i],"%","%") - if(length(raw_list[i]) > limit || length(raw_list[i]) < 10) - to_chat(owner, span_warning("One of the message for [lowertext(name)] exceeded the limit of [limit] characters or has been below the lower limit of 10 characters and has been removed. Actual length: [length(raw_list[i])]")) - //Reflect message to the player so that they don't just lose it - to_chat(owner, span_warning("Message [realIndex]: [raw_list[i]]")) - log_debug("[owner] tried to set [lowertext(name)] [type] message with >[limit] or <10 characters") - raw_list.Cut(i, i + 1) - i-- - - ASSERT(raw_list.len <= 10) //Sanity - - switch(type) - if("smo") - struggle_messages_outside = raw_list - if("smi") - struggle_messages_inside = raw_list - if("asmo") - absorbed_struggle_messages_outside = raw_list - if("asmi") - absorbed_struggle_messages_inside = raw_list - if("escao") - escape_attempt_messages_owner = raw_list - if("escap") - escape_attempt_messages_prey = raw_list - if("esco") - escape_messages_owner = raw_list - if("escp") - escape_messages_prey = raw_list - if("escout") - escape_messages_outside = raw_list - if("escio") - escape_item_messages_owner = raw_list - if("escip") - escape_item_messages_prey = raw_list - if("esciout") - escape_item_messages_outside = raw_list - if("escfo") - escape_fail_messages_owner = raw_list - if("escfp") - escape_fail_messages_prey = raw_list - if("aescao") - escape_attempt_absorbed_messages_owner = raw_list - if("aescap") - escape_attempt_absorbed_messages_prey = raw_list - if("aesco") - escape_absorbed_messages_owner = raw_list - if("aescp") - escape_absorbed_messages_prey = raw_list - if("aescout") - escape_absorbed_messages_outside = raw_list - if("aescfo") - escape_fail_absorbed_messages_owner = raw_list - if("aescfp") - escape_fail_absorbed_messages_prey = raw_list - if("trnspo") - primary_transfer_messages_owner = raw_list - if("trnspp") - primary_transfer_messages_prey = raw_list - if("trnsso") - secondary_transfer_messages_owner = raw_list - if("trnssp") - secondary_transfer_messages_prey = raw_list - if("stmodo") - digest_chance_messages_owner = raw_list - if("stmodp") - digest_chance_messages_prey = raw_list - if("stmoao") - absorb_chance_messages_owner = raw_list - if("stmoap") - absorb_chance_messages_prey = raw_list - if("dmo") - digest_messages_owner = raw_list - if("dmp") - digest_messages_prey = raw_list - if("amo") - absorb_messages_owner = raw_list - if("amp") - absorb_messages_prey = raw_list - if("uamo") - unabsorb_messages_owner = raw_list - if("uamp") - unabsorb_messages_prey = raw_list - if("em") - examine_messages = raw_list - if("ema") - examine_messages_absorbed = raw_list - if("im_digest") - emote_lists[DM_DIGEST] = raw_list - if("im_hold") - emote_lists[DM_HOLD] = raw_list - if("im_holdabsorbed") - emote_lists[DM_HOLD_ABSORBED] = raw_list - if("im_absorb") - emote_lists[DM_ABSORB] = raw_list - if("im_heal") - emote_lists[DM_HEAL] = raw_list - if("im_drain") - emote_lists[DM_DRAIN] = raw_list - if("im_steal") - emote_lists[DM_SIZE_STEAL] = raw_list - if("im_egg") - emote_lists[DM_EGG] = raw_list - if("im_shrink") - emote_lists[DM_SHRINK] = raw_list - if("im_grow") - emote_lists[DM_GROW] = raw_list - if("im_unabsorb") - emote_lists[DM_UNABSORB] = raw_list - - return - // Handle the death of a mob via digestion. // Called from the process_Life() methods of bellies that digest prey. // Default implementation calls M.death() and removes from internal contents. @@ -1117,33 +641,13 @@ // Handle a mob being absorbed /obj/belly/proc/absorb_living(mob/living/M) - var/absorb_alert_owner = pick(absorb_messages_owner) - var/absorb_alert_prey = pick(absorb_messages_prey) - - var/absorbed_count = 0 - for(var/mob/living/L in contents) - if(L.absorbed) - absorbed_count++ - - //Replace placeholder vars - absorb_alert_owner = replacetext(absorb_alert_owner, "%pred", owner) - absorb_alert_owner = replacetext(absorb_alert_owner, "%prey", M) - absorb_alert_owner = replacetext(absorb_alert_owner, "%belly", lowertext(name)) - absorb_alert_owner = replacetext(absorb_alert_owner, "%countprey", absorbed_count) - - absorb_alert_prey = replacetext(absorb_alert_prey, "%pred", owner) - absorb_alert_prey = replacetext(absorb_alert_prey, "%prey", M) - absorb_alert_prey = replacetext(absorb_alert_prey, "%belly", lowertext(name)) - absorb_alert_prey = replacetext(absorb_alert_prey, "%countprey", absorbed_count) - M.absorbed = TRUE if(M.ckey) handle_absorb_langs(M, owner) - GLOB.prey_absorbed_roundstat++ - to_chat(M, span_vnotice("[absorb_alert_prey]")) - to_chat(owner, span_vnotice("[absorb_alert_owner]")) + to_chat(M, span_vnotice("[belly_format_string(absorb_messages_prey, M, use_absorbed_count = TRUE)]")) + to_chat(owner, span_vnotice("[belly_format_string(absorb_messages_owner, M, use_absorbed_count = TRUE)]")) if(M.noisy) //Mute drained absorbee hunger if enabled. M.noisy = FALSE @@ -1177,11 +681,7 @@ if(absorbed_desc) //Replace placeholder vars - var/formatted_abs_desc - formatted_abs_desc = replacetext(absorbed_desc, "%belly", lowertext(name)) //replace with this belly's name - formatted_abs_desc = replacetext(formatted_abs_desc, "%pred", owner) //replace with this belly's owner - formatted_abs_desc = replacetext(formatted_abs_desc, "%prey", M) //replace with whatever mob entered into this belly - to_chat(M, span_vnotice("[formatted_abs_desc]")) + to_chat(M, span_vnotice("[belly_format_string(absorbed_desc, M)]")) //Update owner owner.updateVRPanel() @@ -1203,32 +703,13 @@ // Handle a mob being unabsorbed /obj/belly/proc/unabsorb_living(mob/living/M) - var/unabsorb_alert_owner = pick(unabsorb_messages_owner) - var/unabsorb_alert_prey = pick(unabsorb_messages_prey) - - var/absorbed_count = 0 - for(var/mob/living/L in contents) - if(L.absorbed) - absorbed_count++ - - //Replace placeholder vars - unabsorb_alert_owner = replacetext(unabsorb_alert_owner, "%pred", owner) - unabsorb_alert_owner = replacetext(unabsorb_alert_owner, "%prey", M) - unabsorb_alert_owner = replacetext(unabsorb_alert_owner, "%belly", lowertext(name)) - unabsorb_alert_owner = replacetext(unabsorb_alert_owner, "%countprey", absorbed_count) - - unabsorb_alert_prey = replacetext(unabsorb_alert_prey, "%pred", owner) - unabsorb_alert_prey = replacetext(unabsorb_alert_prey, "%prey", M) - unabsorb_alert_prey = replacetext(unabsorb_alert_prey, "%belly", lowertext(name)) - unabsorb_alert_prey = replacetext(unabsorb_alert_prey, "%countprey", absorbed_count) - M.absorbed = FALSE handle_absorb_langs(M, owner) - to_chat(M, span_vnotice("[unabsorb_alert_prey]")) - to_chat(owner, span_vnotice("[unabsorb_alert_owner]")) + to_chat(M, span_vnotice(belly_format_string(unabsorb_messages_prey, M, use_absorbed_count = TRUE))) + to_chat(owner, span_vnotice(belly_format_string(unabsorb_messages_owner, M, use_absorbed_count = TRUE))) if(desc) - to_chat(M, span_vnotice("[desc]")) + to_chat(M, span_vnotice("[belly_format_string(desc, M)]")) //Update owner owner.updateVRPanel() @@ -1284,46 +765,13 @@ R.setClickCooldown(50) - var/living_count = 0 - for(var/mob/living/L in contents) - living_count++ - - var/escape_attempt_owner_message = pick(escape_attempt_messages_owner) - var/escape_attempt_prey_message = pick(escape_attempt_messages_prey) - var/escape_fail_owner_message = pick(escape_fail_messages_owner) - var/escape_fail_prey_message = pick(escape_fail_messages_prey) - - escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%pred", owner) - escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%prey", R) - escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%belly", lowertext(name)) - escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%countprey", living_count) - escape_attempt_owner_message = replacetext(escape_attempt_owner_message, "%count", contents.len) - - escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%pred", owner) - escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%prey", R) - escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%belly", lowertext(name)) - escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%countprey", living_count) - escape_attempt_prey_message = replacetext(escape_attempt_prey_message, "%count", contents.len) - - escape_fail_owner_message = replacetext(escape_fail_owner_message, "%pred", owner) - escape_fail_owner_message = replacetext(escape_fail_owner_message, "%prey", R) - escape_fail_owner_message = replacetext(escape_fail_owner_message, "%belly", lowertext(name)) - escape_fail_owner_message = replacetext(escape_fail_owner_message, "%countprey", living_count) - escape_fail_owner_message = replacetext(escape_fail_owner_message, "%count", contents.len) - - escape_fail_prey_message = replacetext(escape_fail_prey_message, "%pred", owner) - escape_fail_prey_message = replacetext(escape_fail_prey_message, "%prey", R) - escape_fail_prey_message = replacetext(escape_fail_prey_message, "%belly", lowertext(name)) - escape_fail_prey_message = replacetext(escape_fail_prey_message, "%countprey", living_count) - escape_fail_prey_message = replacetext(escape_fail_prey_message, "%count", contents.len) - - escape_attempt_owner_message = span_vwarning("[escape_attempt_owner_message]") - escape_attempt_prey_message = span_vwarning("[escape_attempt_prey_message]") - escape_fail_owner_message = span_vwarning("[escape_fail_owner_message]") - escape_fail_prey_message = span_vnotice("[escape_fail_prey_message]") + var/escape_attempt_owner_message = span_vwarning(belly_format_string(escape_attempt_messages_owner, R)) + var/escape_attempt_prey_message = span_vwarning(belly_format_string(escape_attempt_messages_prey, R)) + var/escape_fail_owner_message = span_vwarning(belly_format_string(escape_fail_messages_owner, R)) + var/escape_fail_prey_message = span_vnotice(belly_format_string(escape_fail_messages_prey, R)) if(owner.stat) //If owner is stat (dead, KO) we can actually escape - escape_attempt_prey_message = replacetext(escape_attempt_prey_message, new/regex("^(]*)?>.*)(
)$", ""), "$1 (This will take around [escapetime/10] seconds.)$2") + escape_attempt_prey_message = span_vwarning("[escape_attempt_prey_message] (will take around [escapetime/10] seconds.)") to_chat(R, escape_attempt_prey_message) to_chat(owner, escape_attempt_owner_message) @@ -1342,23 +790,9 @@ to_chat(owner, escape_fail_owner_message) return return - var/struggle_outer_message = pick(struggle_messages_outside) - var/struggle_user_message = pick(struggle_messages_inside) - struggle_outer_message = replacetext(struggle_outer_message, "%pred", owner) - struggle_outer_message = replacetext(struggle_outer_message, "%prey", R) - struggle_outer_message = replacetext(struggle_outer_message, "%belly", lowertext(name)) - struggle_outer_message = replacetext(struggle_outer_message, "%countprey", living_count) - struggle_outer_message = replacetext(struggle_outer_message, "%count", contents.len) - - struggle_user_message = replacetext(struggle_user_message, "%pred", owner) - struggle_user_message = replacetext(struggle_user_message, "%prey", R) - struggle_user_message = replacetext(struggle_user_message, "%belly", lowertext(name)) - struggle_user_message = replacetext(struggle_user_message, "%countprey", living_count) - struggle_user_message = replacetext(struggle_user_message, "%count", contents.len) - - struggle_outer_message = span_valert("[struggle_outer_message]") - struggle_user_message = span_valert("[struggle_user_message]") + var/struggle_outer_message = span_valert(belly_format_string(struggle_messages_outside, R)) + var/struggle_user_message = span_valert(belly_format_string(struggle_messages_inside, R)) for(var/mob/M in hearers(4, owner)) M.show_message(struggle_outer_message, 2) // hearable @@ -1386,34 +820,9 @@ to_chat(owner, escape_attempt_owner_message) if(do_after(R, escapetime)) if(escapable && C) - var/escape_item_owner_message = pick(escape_item_messages_owner) - var/escape_item_prey_message = pick(escape_item_messages_prey) - var/escape_item_outside_message = pick(escape_item_messages_outside) - - escape_item_owner_message = replacetext(escape_item_owner_message, "%pred", owner) - escape_item_owner_message = replacetext(escape_item_owner_message, "%prey", R) - escape_item_owner_message = replacetext(escape_item_owner_message, "%belly", lowertext(name)) - escape_item_owner_message = replacetext(escape_item_owner_message, "%countprey", living_count) - escape_item_owner_message = replacetext(escape_item_owner_message, "%count", contents.len) - escape_item_owner_message = replacetext(escape_item_owner_message, "%item", C) - - escape_item_prey_message = replacetext(escape_item_prey_message, "%pred", owner) - escape_item_prey_message = replacetext(escape_item_prey_message, "%prey", R) - escape_item_prey_message = replacetext(escape_item_prey_message, "%belly", lowertext(name)) - escape_item_prey_message = replacetext(escape_item_prey_message, "%countprey", living_count) - escape_item_prey_message = replacetext(escape_item_prey_message, "%count", contents.len) - escape_item_prey_message = replacetext(escape_item_prey_message, "%item", C) - - escape_item_outside_message = replacetext(escape_item_outside_message, "%pred", owner) - escape_item_outside_message = replacetext(escape_item_outside_message, "%prey", R) - escape_item_outside_message = replacetext(escape_item_outside_message, "%belly", lowertext(name)) - escape_item_outside_message = replacetext(escape_item_outside_message, "%countprey", living_count) - escape_item_outside_message = replacetext(escape_item_outside_message, "%count", contents.len) - escape_item_outside_message = replacetext(escape_item_outside_message, "%item", C) - - escape_item_owner_message = span_vwarning("[escape_item_owner_message]") - escape_item_prey_message = span_vwarning("[escape_item_prey_message]") - escape_item_outside_message = span_vwarning("[escape_item_outside_message]") + var/escape_item_owner_message = span_vwarning(belly_format_string(escape_item_messages_owner, R, item = C)) + var/escape_item_prey_message = span_vwarning(belly_format_string(escape_item_messages_prey, R, item = C)) + var/escape_item_outside_message = span_vwarning(belly_format_string(escape_item_messages_outside, R, item = C)) release_specific_contents(C) to_chat(R, escape_item_prey_message) @@ -1422,31 +831,10 @@ M.show_message(escape_item_outside_message, 2) return if(escapable && (R.loc == src) && !R.absorbed) //Does the owner still have escapable enabled? - var/escape_owner_message = pick(escape_messages_owner) - var/escape_prey_message = pick(escape_messages_prey) - var/escape_outside_message = pick(escape_messages_outside) + var/escape_owner_message = span_vwarning(belly_format_string(escape_messages_owner, R)) + var/escape_prey_message = span_vwarning(belly_format_string(escape_messages_prey, R)) + var/escape_outside_message = span_vwarning(belly_format_string(escape_messages_outside, R)) - escape_owner_message = replacetext(escape_owner_message, "%pred", owner) - escape_owner_message = replacetext(escape_owner_message, "%prey", R) - escape_owner_message = replacetext(escape_owner_message, "%belly", lowertext(name)) - escape_owner_message = replacetext(escape_owner_message, "%countprey", living_count) - escape_owner_message = replacetext(escape_owner_message, "%count", contents.len) - - escape_prey_message = replacetext(escape_prey_message, "%pred", owner) - escape_prey_message = replacetext(escape_prey_message, "%prey", R) - escape_prey_message = replacetext(escape_prey_message, "%belly", lowertext(name)) - escape_prey_message = replacetext(escape_prey_message, "%countprey", living_count) - escape_prey_message = replacetext(escape_prey_message, "%count", contents.len) - - escape_outside_message = replacetext(escape_outside_message, "%pred", owner) - escape_outside_message = replacetext(escape_outside_message, "%prey", R) - escape_outside_message = replacetext(escape_outside_message, "%belly", lowertext(name)) - escape_outside_message = replacetext(escape_outside_message, "%countprey", living_count) - escape_outside_message = replacetext(escape_outside_message, "%count", contents.len) - - escape_owner_message = span_vwarning("[escape_owner_message]") - escape_prey_message = span_vwarning("[escape_prey_message]") - escape_outside_message = span_vwarning("[escape_outside_message]") release_specific_contents(R) to_chat(R, escape_prey_message) to_chat(owner, escape_owner_message) @@ -1472,25 +860,8 @@ transferchance = 0 transferlocation = null return - var/primary_transfer_owner_message = pick(primary_transfer_messages_owner) - var/primary_transfer_prey_message = pick(primary_transfer_messages_prey) - - primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%pred", owner) - primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%prey", R) - primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%belly", lowertext(name)) - primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%countprey", living_count) - primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%count", contents.len) - primary_transfer_owner_message = replacetext(primary_transfer_owner_message, "%dest", transferlocation) - - primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%pred", owner) - primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%prey", R) - primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%belly", lowertext(name)) - primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%countprey", living_count) - primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%count", contents.len) - primary_transfer_prey_message = replacetext(primary_transfer_prey_message, "%dest", transferlocation) - - primary_transfer_owner_message = span_vwarning("[primary_transfer_owner_message]") - primary_transfer_prey_message = span_vwarning("[primary_transfer_prey_message]") + var/primary_transfer_owner_message = span_vwarning(belly_format_string(primary_transfer_messages_owner, R, dest = transferlocation)) + var/primary_transfer_prey_message = span_vwarning(belly_format_string(primary_transfer_messages_prey, R, dest = transferlocation)) to_chat(R, primary_transfer_prey_message) to_chat(owner, primary_transfer_owner_message) @@ -1513,25 +884,8 @@ transferlocation_secondary = null return - var/secondary_transfer_owner_message = pick(secondary_transfer_messages_owner) - var/secondary_transfer_prey_message = pick(secondary_transfer_messages_prey) - - secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%pred", owner) - secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%prey", R) - secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%belly", lowertext(name)) - secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%countprey", living_count) - secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%count", contents.len) - secondary_transfer_owner_message = replacetext(secondary_transfer_owner_message, "%dest", transferlocation_secondary) - - secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%pred", owner) - secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%prey", R) - secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%belly", lowertext(name)) - secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%countprey", living_count) - secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%count", contents.len) - secondary_transfer_prey_message = replacetext(secondary_transfer_prey_message, "%dest", transferlocation_secondary) - - secondary_transfer_owner_message = span_vwarning("[secondary_transfer_owner_message]") - secondary_transfer_prey_message = span_vwarning("[secondary_transfer_prey_message]") + var/secondary_transfer_owner_message = span_vwarning(belly_format_string(secondary_transfer_messages_owner, R, dest = transferlocation_secondary)) + var/secondary_transfer_prey_message = span_vwarning(belly_format_string(secondary_transfer_messages_prey, R, dest = transferlocation_secondary)) to_chat(R, secondary_transfer_prey_message) to_chat(owner, secondary_transfer_owner_message) @@ -1542,23 +896,8 @@ return else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance. - var/absorb_chance_owner_message = pick(absorb_chance_messages_owner) - var/absorb_chance_prey_message = pick(absorb_chance_messages_prey) - - absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%pred", owner) - absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%prey", R) - absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%belly", lowertext(name)) - absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%countprey", living_count) - absorb_chance_owner_message = replacetext(absorb_chance_owner_message, "%count", contents.len) - - absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%pred", owner) - absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%prey", R) - absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%belly", lowertext(name)) - absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%countprey", living_count) - absorb_chance_prey_message = replacetext(absorb_chance_prey_message, "%count", contents.len) - - absorb_chance_owner_message = span_vwarning("[absorb_chance_owner_message]") - absorb_chance_prey_message = span_vwarning("[absorb_chance_prey_message]") + var/absorb_chance_owner_message = span_vwarning(belly_format_string(absorb_chance_messages_owner, R)) + var/absorb_chance_prey_message = span_vwarning(belly_format_string(absorb_chance_messages_prey, R)) to_chat(R, absorb_chance_prey_message) to_chat(owner, absorb_chance_owner_message) @@ -1566,46 +905,16 @@ return else if(prob(digestchance) && digest_mode != DM_DIGEST) //Then, let's see if it should run the digest chance. - var/digest_chance_owner_message = pick(digest_chance_messages_owner) - var/digest_chance_prey_message = pick(digest_chance_messages_prey) - - digest_chance_owner_message = replacetext(digest_chance_owner_message, "%pred", owner) - digest_chance_owner_message = replacetext(digest_chance_owner_message, "%prey", R) - digest_chance_owner_message = replacetext(digest_chance_owner_message, "%belly", lowertext(name)) - digest_chance_owner_message = replacetext(digest_chance_owner_message, "%countprey", living_count) - digest_chance_owner_message = replacetext(digest_chance_owner_message, "%count", contents.len) - - digest_chance_prey_message = replacetext(digest_chance_prey_message, "%pred", owner) - digest_chance_prey_message = replacetext(digest_chance_prey_message, "%prey", R) - digest_chance_prey_message = replacetext(digest_chance_prey_message, "%belly", lowertext(name)) - digest_chance_prey_message = replacetext(digest_chance_prey_message, "%countprey", living_count) - digest_chance_prey_message = replacetext(digest_chance_prey_message, "%count", contents.len) - - digest_chance_owner_message = span_vwarning("[digest_chance_owner_message]") - digest_chance_prey_message = span_vwarning("[digest_chance_prey_message]") + var/digest_chance_owner_message = span_vwarning(belly_format_string(digest_chance_messages_owner, R)) + var/digest_chance_prey_message = span_vwarning(belly_format_string(digest_chance_messages_prey, R)) to_chat(R, digest_chance_prey_message) to_chat(owner, digest_chance_owner_message) digest_mode = DM_DIGEST return else if(prob(selectchance) && digest_mode != DM_SELECT) //Finally, let's see if it should run the selective mode chance. - var/select_chance_owner_message = pick(select_chance_messages_owner) - var/select_chance_prey_message = pick(select_chance_messages_prey) - - select_chance_owner_message = replacetext(select_chance_owner_message, "%pred", owner) - select_chance_owner_message = replacetext(select_chance_owner_message, "%prey", R) - select_chance_owner_message = replacetext(select_chance_owner_message, "%belly", lowertext(name)) - select_chance_owner_message = replacetext(select_chance_owner_message, "%countprey", living_count) - select_chance_owner_message = replacetext(select_chance_owner_message, "%count", contents.len) - - select_chance_prey_message = replacetext(select_chance_prey_message, "%pred", owner) - select_chance_prey_message = replacetext(select_chance_prey_message, "%prey", R) - select_chance_prey_message = replacetext(select_chance_prey_message, "%belly", lowertext(name)) - select_chance_prey_message = replacetext(select_chance_prey_message, "%countprey", living_count) - select_chance_prey_message = replacetext(select_chance_prey_message, "%count", contents.len) - - select_chance_owner_message = span_vwarning("[select_chance_owner_message]") - select_chance_prey_message = span_vwarning("[select_chance_prey_message]") + var/select_chance_owner_message = span_vwarning(belly_format_string(select_chance_messages_owner, R)) + var/select_chance_prey_message = span_vwarning(belly_format_string(select_chance_messages_prey, R)) to_chat(R, select_chance_prey_message) to_chat(owner, select_chance_owner_message) @@ -1623,26 +932,8 @@ R.setClickCooldown(50) - var/struggle_outer_message = pick(absorbed_struggle_messages_outside) - var/struggle_user_message = pick(absorbed_struggle_messages_inside) - - var/absorbed_count = 0 - for(var/mob/living/L in contents) - if(L.absorbed) - absorbed_count++ - - struggle_outer_message = replacetext(struggle_outer_message, "%pred", owner) - struggle_outer_message = replacetext(struggle_outer_message, "%prey", R) - struggle_outer_message = replacetext(struggle_outer_message, "%belly", lowertext(name)) - struggle_outer_message = replacetext(struggle_outer_message, "%countprey", absorbed_count) - - struggle_user_message = replacetext(struggle_user_message, "%pred", owner) - struggle_user_message = replacetext(struggle_user_message, "%prey", R) - struggle_user_message = replacetext(struggle_user_message, "%belly", lowertext(name)) - struggle_user_message = replacetext(struggle_user_message, "%countprey", absorbed_count) - - struggle_outer_message = span_valert("[struggle_outer_message]") - struggle_user_message = span_valert("[struggle_user_message]") + var/struggle_outer_message = span_valert(belly_format_string(absorbed_struggle_messages_outside, R, use_absorbed_count = TRUE)) + var/struggle_user_message = span_valert(belly_format_string(absorbed_struggle_messages_inside, R, use_absorbed_count = TRUE)) for(var/mob/M in hearers(4, owner)) M.show_message(struggle_outer_message, 2) // hearable @@ -1662,59 +953,16 @@ //absorb resists if(escapable || owner.stat) //If the stomach has escapable enabled or the owner is dead/unconscious if(prob(escapechance) || owner.stat) //Let's have it check to see if the prey's escape attempt starts. - - - var/living_count = 0 - for(var/mob/living/L in contents) - living_count++ - - var/escape_attempt_absorbed_owner_message = pick(escape_attempt_absorbed_messages_owner) - var/escape_attempt_absorbed_prey_message = pick(escape_attempt_absorbed_messages_prey) - - escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%pred", owner) - escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%prey", R) - escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%belly", lowertext(name)) - escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%countprey", living_count) - escape_attempt_absorbed_owner_message = replacetext(escape_attempt_absorbed_owner_message, "%count", contents.len) - - escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%pred", owner) - escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%prey", R) - escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%belly", lowertext(name)) - escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%countprey", living_count) - escape_attempt_absorbed_prey_message = replacetext(escape_attempt_absorbed_prey_message, "%count", contents.len) - - escape_attempt_absorbed_owner_message = span_vwarning("[escape_attempt_absorbed_owner_message]") - escape_attempt_absorbed_prey_message = span_vwarning("[escape_attempt_absorbed_prey_message]") + var/escape_attempt_absorbed_owner_message = span_vwarning(belly_format_string(escape_attempt_absorbed_messages_owner, R)) + var/escape_attempt_absorbed_prey_message = span_vwarning(belly_format_string(escape_attempt_absorbed_messages_prey, R)) to_chat(R, escape_attempt_absorbed_prey_message) to_chat(owner, escape_attempt_absorbed_owner_message) if(do_after(R, escapetime)) if((escapable || owner.stat) && (R.loc == src) && prob(escapechance_absorbed)) //Does the escape attempt succeed? - var/escape_absorbed_owner_message = pick(escape_absorbed_messages_owner) - var/escape_absorbed_prey_message = pick(escape_absorbed_messages_prey) - var/escape_absorbed_outside_message = pick(escape_absorbed_messages_outside) - - escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%pred", owner) - escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%prey", R) - escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%belly", lowertext(name)) - escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%countprey", living_count) - escape_absorbed_owner_message = replacetext(escape_absorbed_owner_message, "%count", contents.len) - - escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%pred", owner) - escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%prey", R) - escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%belly", lowertext(name)) - escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%countprey", living_count) - escape_absorbed_prey_message = replacetext(escape_absorbed_prey_message, "%count", contents.len) - - escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%pred", owner) - escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%prey", R) - escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%belly", lowertext(name)) - escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%countprey", living_count) - escape_absorbed_outside_message = replacetext(escape_absorbed_outside_message, "%count", contents.len) - - escape_absorbed_owner_message = span_vwarning("[escape_absorbed_owner_message]") - escape_absorbed_prey_message = span_vwarning("[escape_absorbed_prey_message]") - escape_absorbed_outside_message = span_vwarning("[escape_absorbed_outside_message]") + var/escape_absorbed_owner_message = span_vwarning(belly_format_string(escape_absorbed_messages_owner, R)) + var/escape_absorbed_prey_message = span_vwarning(belly_format_string(escape_absorbed_messages_prey, R)) + var/escape_absorbed_outside_message = span_vwarning(belly_format_string(escape_absorbed_messages_outside, R)) release_specific_contents(R) to_chat(R, escape_absorbed_prey_message) @@ -1725,24 +973,8 @@ else if(!(R.loc == src)) //Aren't even in the belly. Quietly fail. return else //Belly became inescapable or you failed your roll. - - var/escape_fail_absorbed_owner_message = pick(escape_fail_absorbed_messages_owner) - var/escape_fail_absorbed_prey_message = pick(escape_fail_absorbed_messages_prey) - - escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%pred", owner) - escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%prey", R) - escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%belly", lowertext(name)) - escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%countprey", living_count) - escape_fail_absorbed_owner_message = replacetext(escape_fail_absorbed_owner_message, "%count", contents.len) - - escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%pred", owner) - escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%prey", R) - escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%belly", lowertext(name)) - escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%countprey", living_count) - escape_fail_absorbed_prey_message = replacetext(escape_fail_absorbed_prey_message, "%count", contents.len) - - escape_fail_absorbed_owner_message = span_vwarning("[escape_fail_absorbed_owner_message]") - escape_fail_absorbed_prey_message = span_vnotice("[escape_fail_absorbed_prey_message]") + var/escape_fail_absorbed_owner_message = span_vwarning(belly_format_string(escape_fail_absorbed_messages_owner, R)) + var/escape_fail_absorbed_prey_message = span_vnotice(belly_format_string(escape_fail_absorbed_messages_prey, R)) to_chat(R, escape_fail_absorbed_prey_message) to_chat(owner, escape_fail_absorbed_owner_message) diff --git a/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes_vr.dm index 73a8f5ce341..95ee35c879d 100644 --- a/code/modules/vore/eating/bellymodes_vr.dm +++ b/code/modules/vore/eating/bellymodes_vr.dm @@ -107,25 +107,12 @@ if(emote_active) var/list/EL = emote_lists[digest_mode] if((LAZYLEN(EL) || LAZYLEN(emote_lists[DM_HOLD_ABSORBED]) || (digest_mode == DM_DIGEST && LAZYLEN(emote_lists[DM_HOLD])) || (digest_mode == DM_SELECT && (LAZYLEN(emote_lists[DM_HOLD])||LAZYLEN(emote_lists[DM_DIGEST])||LAZYLEN(emote_lists[DM_ABSORB])) )) && next_emote <= world.time) - var/living_count = 0 - var/absorbed_count = 0 - for(var/mob/living/L in contents) - living_count++ - if(L.absorbed) - absorbed_count++ next_emote = world.time + (emote_time SECONDS) for(var/mob/living/M in contents) if(M.absorbed) EL = emote_lists[DM_HOLD_ABSORBED] - - var/raw_message = pick(EL) - var/formatted_message - formatted_message = replacetext(raw_message, "%belly", lowertext(name)) - formatted_message = replacetext(formatted_message, "%pred", owner) - formatted_message = replacetext(formatted_message, "%prey", M) - formatted_message = replacetext(formatted_message, "%countprey", absorbed_count) - if(formatted_message) - to_chat(M, span_vnotice("[formatted_message]")) + if(LAZYLEN(EL)) + to_chat(M, span_vnotice(belly_format_string(EL, M, use_absorbed_count = TRUE))) else if (digest_mode == DM_SELECT) var/datum/digest_mode/selective/DM_S = GLOB.digest_modes[DM_SELECT] @@ -133,15 +120,8 @@ else if(digest_mode == DM_DIGEST && !M.digestable) EL = emote_lists[DM_HOLD] // Use Hold's emote list if we're indigestible - var/raw_message = pick(EL) - var/formatted_message - formatted_message = replacetext(raw_message, "%belly", lowertext(name)) - formatted_message = replacetext(formatted_message, "%pred", owner) - formatted_message = replacetext(formatted_message, "%prey", M) - formatted_message = replacetext(formatted_message, "%countprey", living_count) - formatted_message = replacetext(formatted_message, "%count", contents.len) - if(formatted_message) - to_chat(M, span_vnotice("[formatted_message]")) + if(LAZYLEN(EL)) + to_chat(M, span_vnotice(belly_format_string(EL, M))) if(to_update) updateVRPanels() @@ -260,32 +240,15 @@ return did_an_item /obj/belly/proc/handle_digestion_death(mob/living/M) - var/digest_alert_owner = pick(digest_messages_owner) - var/digest_alert_prey = pick(digest_messages_prey) + var/digest_alert_owner = span_vnotice(belly_format_string(digest_messages_owner, M)) + var/digest_alert_prey = span_vnotice(belly_format_string(digest_messages_prey, M)) var/compensation = M.maxHealth / 5 //Dead body bonus. if(ishuman(M)) compensation += M.getOxyLoss() //How much of the prey's damage was caused by passive crit oxyloss to compensate the lost nutrition. - var/living_count = 0 - for(var/mob/living/L in contents) - living_count++ - - //Replace placeholder vars - digest_alert_owner = replacetext(digest_alert_owner, "%pred", owner) - digest_alert_owner = replacetext(digest_alert_owner, "%prey", M) - digest_alert_owner = replacetext(digest_alert_owner, "%belly", lowertext(name)) - digest_alert_owner = replacetext(digest_alert_owner, "%countprey", living_count) - digest_alert_owner = replacetext(digest_alert_owner, "%count", contents.len) - - digest_alert_prey = replacetext(digest_alert_prey, "%pred", owner) - digest_alert_prey = replacetext(digest_alert_prey, "%prey", M) - digest_alert_prey = replacetext(digest_alert_prey, "%belly", lowertext(name)) - digest_alert_prey = replacetext(digest_alert_prey, "%countprey", living_count) - digest_alert_prey = replacetext(digest_alert_prey, "%count", contents.len) - //Send messages - to_chat(owner, span_vnotice("[digest_alert_owner]")) - to_chat(M, span_vnotice("[digest_alert_prey]")) + to_chat(owner, digest_alert_owner) + to_chat(M, digest_alert_prey) if(M.ckey) GLOB.prey_digested_roundstat++ diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 54900800d5a..81b259a5210 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -339,6 +339,8 @@ B.name = "Stomach" B.desc = "It appears to be rather warm and wet. Makes sense, considering it's inside \the [name]." B.can_taste = TRUE + else + vore_selected = vore_organs[1] return TRUE diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 8aac1d5a094..b046631ffae 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -96,6 +96,23 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", . = icon2base64(getFlatIcon(target,defdir=SOUTH,no_anim=TRUE)) nom_icons[key] = . +/datum/vore_look/tgui_static_data(mob/user) + var/list/data = ..() + + data["vore_words"] = list( + "%goo" = GLOB.vore_words_goo, + "%happybelly" = GLOB.vore_words_hbellynoises, + "%fat" = GLOB.vore_words_fat, + "%grip" = GLOB.vore_words_grip, + "%cozy" = GLOB.vore_words_cozyholdingwords, + "%angry" = GLOB.vore_words_angry, + "%acid" = GLOB.vore_words_acid, + "%snack" = GLOB.vore_words_snackname, + "%hot" = GLOB.vore_words_hot, + "%snake" = GLOB.vore_words_snake, + ) + + return data /datum/vore_look/tgui_data(mob/user) var/list/data = list() @@ -118,14 +135,8 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", else if(inside_belly.desc) inside_desc = inside_belly.desc - //I'd rather not copy-paste this code twice into the previous if-statement - //Technically we could just format the text anyway, but IDK how demanding unnecessary text-replacements are - if((host.absorbed && inside_belly.absorbed_desc) || (inside_belly.desc)) - var/formatted_desc - formatted_desc = replacetext(inside_desc, "%belly", lowertext(inside_belly.name)) //replace with this belly's name - formatted_desc = replacetext(formatted_desc, "%pred", pred) //replace with the pred of this belly - formatted_desc = replacetext(formatted_desc, "%prey", host) //replace with whoever's reading this - inside_desc = formatted_desc + if(inside_desc != "No description.") + inside_desc = inside_belly.belly_format_string(inside_desc, host, use_first_only = TRUE) inside = list( "absorbed" = host.absorbed, diff --git a/tgui/packages/tgui/components/NanoMap.jsx b/tgui/packages/tgui/components/NanoMap.tsx similarity index 56% rename from tgui/packages/tgui/components/NanoMap.jsx rename to tgui/packages/tgui/components/NanoMap.tsx index 4c606a1eed3..da8e6678fc1 100644 --- a/tgui/packages/tgui/components/NanoMap.jsx +++ b/tgui/packages/tgui/components/NanoMap.tsx @@ -1,7 +1,11 @@ -import { Component } from 'react'; +import { KEY_DOWN, KEY_E, KEY_S, KEY_UP, KEY_W } from 'common/keycodes'; +import React, { Component, PropsWithChildren } from 'react'; +import { resolveAsset } from 'tgui/assets'; +import { useBackend } from 'tgui/backend'; +import { KeyEvent } from 'tgui/events'; +import { KeyListener } from 'tgui-core/components'; -import { resolveAsset } from '../assets'; -import { useBackend } from '../backend'; +import { logger } from '../logging'; import { Box, Button, Icon, LabeledList, Slider, Tooltip } from '.'; const pauseEvent = (e) => { @@ -16,8 +20,56 @@ const pauseEvent = (e) => { return false; }; -export class NanoMap extends Component { - constructor(props) { +type Props = PropsWithChildren<{ + zoomScale: number; + onZoom?: (zoom: number) => void; +}>; + +type State = { + offsetX: number; + offsetY: number; + dragging: boolean; + originX: number; + originY: number; + zoom: number; +}; + +export class NanoMap extends Component { + static Marker: React.FC; + static Zoomer: React.FC; + + handleDragStart: React.MouseEventHandler; + handleDragMove: (e: MouseEvent) => void; + handleDragEnd: (e: MouseEvent) => void; + handleZoom: (e: Event, v: number) => void; + handleKey: (e: KeyEvent) => void; + ref: EventTarget; + + setZoom(zoom: number) { + const newZoom = Math.min(Math.max(zoom, 1), 8); + this.setState((state) => { + let zoomDifference = -(state.zoom - newZoom); + + let newOffsetX = + state.offsetX - (this.props.zoomScale / 2) * zoomDifference; + + let newOffsetY = + state.offsetY - (this.props.zoomScale / 2) * zoomDifference; + + return { + ...state, + zoom: newZoom, + offsetX: newOffsetX, + offsetY: newOffsetY, + }; + }); + + if (this.props.onZoom) { + this.props.onZoom(newZoom); + } + } + + constructor(props: Props) { super(props); // Auto center based on window size @@ -27,15 +79,14 @@ export class NanoMap extends Component { this.state = { offsetX: Xcenter, offsetY: Ycenter, - transform: 'none', dragging: false, - originX: null, - originY: null, + originX: 0, + originY: 0, zoom: 1, }; // Dragging - this.handleDragStart = (e) => { + this.handleDragStart = (e: React.MouseEvent) => { this.ref = e.target; this.setState({ dragging: false, @@ -47,7 +98,7 @@ export class NanoMap extends Component { pauseEvent(e); }; - this.handleDragMove = (e) => { + this.handleDragMove = (e: MouseEvent) => { this.setState((prevState) => { const state = { ...prevState }; const newOffsetX = e.screenX - state.originX; @@ -65,57 +116,38 @@ export class NanoMap extends Component { pauseEvent(e); }; - this.handleDragEnd = (e) => { + this.handleDragEnd = (e: MouseEvent) => { this.setState({ dragging: false, - originX: null, - originY: null, + originX: 0, + originY: 0, }); document.removeEventListener('mousemove', this.handleDragMove); document.removeEventListener('mouseup', this.handleDragEnd); pauseEvent(e); }; - this.handleOnClick = (e) => { - let byondX = e.offsetX / this.state.zoom / this.props.zoomScale; - let byondY = 1 - e.offsetY / this.state.zoom / this.props.zoomScale; // Byond origin is bottom left, this is top left - - e.byondX = byondX; - e.byondY = byondY; - if (typeof this.props.onClick === 'function') { - this.props.onClick(e); - } + this.handleZoom = (_e: Event, value: number) => { + this.setZoom(value); }; - this.handleZoom = (_e, value) => { - this.setState((state) => { - const newZoom = Math.min(Math.max(value, 1), 8); - let zoomDiff = (newZoom - state.zoom) * 1.5; - state.zoom = newZoom; - - let newOffsetX = state.offsetX - 262 * zoomDiff; - if (newOffsetX < -500) { - newOffsetX = -500; + this.handleKey = (e: KeyEvent) => { + switch (e.code) { + case KEY_UP: + case KEY_W: { + this.setZoom(this.state.zoom + 1); + break; } - if (newOffsetX > 500) { - newOffsetX = 500; + case KEY_DOWN: + case KEY_S: { + this.setZoom(this.state.zoom - 1); + break; } - - let newOffsetY = state.offsetY - 256 * zoomDiff; - if (newOffsetY < -200) { - newOffsetY = -200; + case KEY_E: { + logger.log(this.state.offsetX, this.state.offsetY); + break; } - if (newOffsetY > 200) { - newOffsetY = 200; - } - - state.offsetX = newOffsetX; - state.offsetY = newOffsetY; - if (props.onZoom) { - props.onZoom(state.zoom); - } - return state; - }); + } }; } @@ -144,25 +176,35 @@ export class NanoMap extends Component { }; return ( - + {children} + ); } } -const NanoMapMarker = (props) => { +type NanoMapMarkerProps = { + x: number; + y: number; + zoom: number; + icon: string; + tooltip: string; + color: string; + onClick?: (e: React.MouseEvent) => void; +}; + +const NanoMapMarker = (props: NanoMapMarkerProps) => { const { x, y, zoom = 1, icon, tooltip, color, onClick } = props; - const handleOnClick = (e) => { + const handleOnClick = (e: React.MouseEvent) => { pauseEvent(e); if (onClick) { onClick(e); @@ -172,7 +214,7 @@ const NanoMapMarker = (props) => { const rx = x * 2 * zoom - zoom - 3; const ry = y * 2 * zoom - zoom - 3; return ( -
+ { left={rx + 'px'} onMouseDown={handleOnClick} > - - + -
+ ); }; NanoMap.Marker = NanoMapMarker; -const NanoMapZoomer = (props) => { - const { act, config, data } = useBackend(); +type Data = { + map_levels: number[]; +}; + +type NanoMapZoomerProps = { + zoom: number; + onZoom: (e: Event, v: number) => void; +}; + +const NanoMapZoomer = (props: NanoMapZoomerProps) => { + const { act, config, data } = useBackend(); return ( v + 'x'} value={props.zoom} onDrag={(e, v) => props.onZoom(e, v)} diff --git a/tgui/packages/tgui/interfaces/ChemMaster/ChemMasterProductionChemical.tsx b/tgui/packages/tgui/interfaces/ChemMaster/ChemMasterProductionChemical.tsx index d2d69c12b39..35110f43ba1 100644 --- a/tgui/packages/tgui/interfaces/ChemMaster/ChemMasterProductionChemical.tsx +++ b/tgui/packages/tgui/interfaces/ChemMaster/ChemMasterProductionChemical.tsx @@ -73,6 +73,12 @@ export const ChemMasterProductionChemical = (props: { > Create bottle (60u max) + - {buildFiveName && ( - - )} - - - - {design.mat_list.join(' ')} - - - {design.chem_list.join(' ')} - - - - - - )) - ) : ( - - No items could be found matching the parameters (page or search). - - )} - - ); -}; - -export const PaginationChevrons = (props: { target: string }) => { - const { act } = useBackend(); - - const { target } = props; - - return ( - <> - - - ) : ( - - )} - - ); - } - return ( - - - - ); - })) || Queue Empty.} - - ); -}; - -export const ResearchConsoleConstructorMats = (props: { - name: string; - mats: mat[]; - matsStates: mat[]; - onMatsState: Function; -}) => { - const { act } = useBackend(); - - const { name, mats } = props; - - const ejectSheetAction: string = - name === 'Protolathe' ? 'lathe_ejectsheet' : 'imprinter_ejectsheet'; - - return ( - - {mats.map((mat) => { - return ( - - - props.onMatsState({ - ...props.matsStates, - [mat.name]: val, - }) - } - /> - - - - } - > - {mat.amount} cm³ - - ); - })} - - ); -}; - -export const ResearchConsoleConstructorChems = (props: { - name: string; - reagents: reagent[]; -}) => { - const { act } = useBackend(); - - const { name, reagents } = props; - - const ejectChemAction: string = - name === 'Protolathe' ? 'disposeP' : 'disposeI'; - const ejectAllChemAction: string = - name === 'Protolathe' ? 'disposeallP' : 'disposeallI'; - return ( - - - {(reagents.length && - reagents.map((chem) => ( - - {chem.volume}u - - - ))) || ( - No chems detected - )} - - act(ejectAllChemAction)} - > - Disposal All Chemicals In Storage - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleDestructiveAnalyzer.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleDestructiveAnalyzer.tsx deleted file mode 100644 index 4d77a554e23..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleDestructiveAnalyzer.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useBackend } from '../../backend'; -import { Box, Button, LabeledList, Section } from '../../components'; -import { Data, destroyer } from './types'; - -export const ResearchConsoleDestructiveAnalyzer = (props: { - name: string; - linked_destroy: destroyer; -}) => { - const { act, data } = useBackend(); - - const { linked_destroy, name } = props; - - if (!linked_destroy.present) { - return
No destructive analyzer found.
; - } - - const { loaded_item, origin_tech } = linked_destroy; - - return ( -
- {(loaded_item && ( - - - {loaded_item} - - - {(origin_tech.length && - origin_tech.map((tech) => ( - - {tech.level}   - {tech.current && '(Current: ' + tech.current + ')'} - - ))) || ( - - No origin tech found. - - )} - - - - - - - )) || No Item Loaded. Standing-by...} -
- ); -}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleDisk.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleDisk.tsx deleted file mode 100644 index 10652d7add5..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleDisk.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import { useBackend } from '../../backend'; -import { Box, Button, Input, LabeledList, Section } from '../../components'; -import { paginationTitle } from './constants'; -import { PaginationChevrons } from './ResearchConsoleBuildMenu'; -import { d_disk, Data, t_disk } from './types'; - -export const TechDisk = (props) => { - const { act, data } = useBackend(); - - const { tech } = data; - - const { disk, saveDialog, onSaveDialog } = props; - - if (!disk || !disk.present) { - return null; - } - - if (saveDialog) { - return ( -
onSaveDialog(false)}> - Back - - } - > - - {tech.map((level) => ( - - - - ))} - -
- ); - } - - return ( - - - - (Technology Data Disk) - - - {(disk.stored && ( - - {disk.name} - Level: {disk.level} - Description: {disk.desc} - - - - - - - )) || ( - - This disk has no data stored on it. - - - - )} - - ); -}; - -const DataDisk = (props) => { - const { act, data } = useBackend(); - - const { designs } = data; - - const { disk, saveDialog, onSaveDialog } = props; - - if (!disk || !disk.present) { - return null; - } - - if (saveDialog) { - return ( -
- - { || null} - - } - > - act('search', { search: v })} - mb={1} - /> - {(designs && designs.length && ( - - {designs.map((item) => ( - - - - ))} - - )) || No designs found.} -
- ); - } - - return ( - - {(disk.stored && ( - - - {disk.name} - - {disk.build_type} - - - {Object.keys(disk.materials).map((mat) => ( - - {mat} x {disk.materials[mat]} - - ))} - - - - - - - - - )) || ( - - This disk has no data stored on it. - - - - )} - - ); -}; - -export const ResearchConsoleDisk = (props: { - saveDialogTech: boolean; - saveDialogDesign: boolean; - onSaveDialogTech: Function; - onSaveDialogDesign: Function; - d_disk: d_disk; - t_disk: t_disk; -}) => { - const { d_disk, t_disk } = props; - - const { - saveDialogTech, - onSaveDialogTech, - saveDialogDesign, - onSaveDialogDesign, - } = props; - - if (!d_disk.present && !t_disk.present) { - return
No disk inserted.
; - } - - return ( -
- - -
- ); -}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleSettings.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleSettings.tsx deleted file mode 100644 index 24520707603..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleSettings.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { BooleanLike } from 'common/react'; - -import { useBackend } from '../../backend'; -import { Box, Button, LabeledList, Section, Tabs } from '../../components'; -import { Data, destroyer, info, modularDevice } from './types'; - -export const ResearchConsoleSettings = (props: { - info: info; - settingsTab: number; - onSettingsTab: Function; -}) => { - const { data } = useBackend(); - - const { settingsTab, onSettingsTab, info } = props; - - const { is_public, sync, linked_destroy, linked_imprinter, linked_lathe } = - info; - - const tab: React.JSX.Element[] = []; - - tab[0] = ; - tab[1] = ( - - ); - - return ( -
- - onSettingsTab(0)} - selected={settingsTab === 0} - > - General - - onSettingsTab(1)} - selected={settingsTab === 1} - > - Device Linkages - - - {tab[settingsTab] || Error} -
- ); -}; - -const ResearchConsoleSettingsSync = (props: { - is_public: BooleanLike; - sync: BooleanLike; -}) => { - const { act } = useBackend(); - - const { sync, is_public } = props; - - return ( - - {!is_public && - ((sync && ( - <> - - - - )) || ( - - ))} - - - - ); -}; - -const ResearchConsoleSettingsLink = (props: { - linked_destroy: destroyer; - linked_lathe: modularDevice; - linked_imprinter: modularDevice; -}) => { - const { act } = useBackend(); - - const { linked_destroy, linked_lathe, linked_imprinter } = props; - - return ( - - - - {(linked_destroy.present && ( - - - - )) || - null} - {(linked_lathe.present && ( - - - - )) || - null} - {(linked_imprinter.present && ( - - - - )) || - null} - - - ); -}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleViewDesigns.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleViewDesigns.tsx deleted file mode 100644 index 2c9b8a87c88..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleViewDesigns.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useBackend } from '../../backend'; -import { Box, Button, Input, LabeledList, Section } from '../../components'; -import { paginationTitle } from './constants'; -import { PaginationChevrons } from './ResearchConsoleBuildMenu'; -import { Data } from './types'; - -export const ResearchConsoleViewDesigns = (props) => { - const { act, data } = useBackend(); - - const { designs } = data; - - return ( -
- - { || null} - - } - > - act('search', { search: v })} - mb={1} - /> - {(designs && designs.length && ( - - {designs.map((design) => ( - - {design.desc} - - ))} - - )) || No designs found.} -
- ); -}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleViewResearch.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleViewResearch.tsx deleted file mode 100644 index c1157214804..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/ResearchConsoleViewResearch.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { useBackend } from '../../backend'; -import { Box, Button, Section, Table } from '../../components'; -import { Data } from './types'; - -export const ResearchConsoleViewResearch = (props) => { - const { act, data } = useBackend(); - - const { tech } = data; - - return ( -
act('print', { print: 1 })}> - Print This Page - - } - > - - {tech.map((thing) => ( - - - {thing.name} - - Level {thing.level} - - - {thing.desc} - - - ))} -
-
- ); -}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/constants.ts b/tgui/packages/tgui/interfaces/ResearchConsole/constants.ts deleted file mode 100644 index 15fb7a2eb71..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/constants.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { menue } from './types'; - -export const menus: menue = [ - { - name: 'Protolathe', - icon: 'wrench', - }, - { - name: 'Circuit Imprinter', - icon: 'digital-tachograph', - }, - { - name: 'Destructive Analyzer', - icon: 'eraser', - }, - { - name: 'Settings', - icon: 'cog', - }, - { - name: 'Research List', - icon: 'flask', - }, - { - name: 'Design List', - icon: 'file', - }, - { name: 'Disk Operations', icon: 'save' }, -]; - -export function paginationTitle(title: string, page: number) { - if (typeof page === 'number') { - return title + ' - Page ' + (page + 1); - } - - return title; -} diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/data.ts b/tgui/packages/tgui/interfaces/ResearchConsole/data.ts new file mode 100644 index 00000000000..2b8b18bf7da --- /dev/null +++ b/tgui/packages/tgui/interfaces/ResearchConsole/data.ts @@ -0,0 +1,142 @@ +import { BooleanLike } from 'common/react'; + +export enum Tab { + Protolathe = 0, + CircuitImprinter = 1, + DestructiveAnalyzer = 2, + DesignList = 3, + ResearchList = 4, + Misc = 5, +} + +export type Tech = { + name: string; + level: number; + desc: string; + id: string; +}; + +export type Design = { + name: string; + desc: string; + id: string; +}; + +export type ConstructorDesign = { + name: string; + id: string; + mat_list: string[]; + chem_list: string[]; +}; + +export enum ConstructorEnum { + Protolathe = 'protolathe', + CircuitImprinter = 'circuit_imprinter', +} + +export const constructorEnumToName = { + [ConstructorEnum.Protolathe]: 'Protolathe', + [ConstructorEnum.CircuitImprinter]: 'Circuit Imprinter', +}; + +export const constructorEnumToData = { + [ConstructorEnum.Protolathe]: 'lathe_designs', + [ConstructorEnum.CircuitImprinter]: 'imprinter_designs', +}; + +export const constructorEnumToEjectAction = { + [ConstructorEnum.Protolathe]: 'lathe_ejectsheet', + [ConstructorEnum.CircuitImprinter]: 'imprinter_ejectsheet', +}; + +export const constructorEnumToEjectReagentAction = { + [ConstructorEnum.Protolathe]: 'disposeP', + [ConstructorEnum.CircuitImprinter]: 'disposeI', +}; + +export const constructorEnumToEjectReagentAllAction = { + [ConstructorEnum.Protolathe]: 'disposeallP', + [ConstructorEnum.CircuitImprinter]: 'disposeallI', +}; + +export const constructorEnumToRemoveQueue = { + [ConstructorEnum.Protolathe]: 'removeP', + [ConstructorEnum.CircuitImprinter]: 'removeI', +}; + +export const constructorEnumToBuild = { + [ConstructorEnum.Protolathe]: 'build', + [ConstructorEnum.CircuitImprinter]: 'imprint', +}; + +export const constructorEnumToBuildFive = { + [ConstructorEnum.Protolathe]: 'buildfive', + [ConstructorEnum.CircuitImprinter]: null, +}; + +export type StaticData = { + sheet_material_amount: number; + tech: Tech[]; + designs: Design[]; + lathe_designs: ConstructorDesign[]; + imprinter_designs: ConstructorDesign[]; +}; + +export type OriginTech = { + name: string; + level: number; + current: number; +}; + +export type LinkedDestroyer = { + loaded_item: string; + origin_tech: OriginTech[]; +}; + +export type Reagent = { + name: string; + id: string; + volume: number; +}; + +export type LinkedConstructor = { + total_materials: number; + max_materials: number; + total_volume: number; + max_volume: number; + busy: BooleanLike; + materials: Record; + reagents: Reagent[]; + queue: { name: string; index: number }[]; +}; + +export type TDisk = { + stored: { name: string; level: number; desc: string } | null; +}; + +export type DDisk = { + stored: { + name: string; + build_type: number; + materials: Record; + } | null; +}; + +export type Data = StaticData & { + locked: BooleanLike; + busy_msg: string | null; + search: string; + + builder_page: number; + design_page: number; + + sync: BooleanLike; + is_public: BooleanLike; + + linked_destroy: LinkedDestroyer | null; + linked_lathe: LinkedConstructor | null; + linked_imprinter: LinkedConstructor | null; + + t_disk: TDisk | null; + d_disk: DDisk | null; +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/index.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/index.tsx index af16487a367..fc1b9b4858e 100644 --- a/tgui/packages/tgui/interfaces/ResearchConsole/index.tsx +++ b/tgui/packages/tgui/interfaces/ResearchConsole/index.tsx @@ -1,129 +1,188 @@ -import { useEffect, useState } from 'react'; +import { useBackend, useSharedState } from 'tgui/backend'; +import { Box, Button, Icon, Section, Stack, Tabs } from 'tgui/components'; +import { Window } from 'tgui/layouts'; +import { FitText } from 'tgui-core/components'; -import { useBackend, useSharedState } from '../../backend'; -import { Box, Button, Section, Tabs } from '../../components'; -import { Window } from '../../layouts'; -import { menus } from './constants'; -import { ResearchConsoleConstructor } from './ResearchConsoleConstructor'; -import { ResearchConsoleDestructiveAnalyzer } from './ResearchConsoleDestructiveAnalyzer'; -import { ResearchConsoleDisk } from './ResearchConsoleDisk'; -import { ResearchConsoleSettings } from './ResearchConsoleSettings'; -import { ResearchConsoleViewDesigns } from './ResearchConsoleViewDesigns'; -import { ResearchConsoleViewResearch } from './ResearchConsoleViewResearch'; -import { Data, mat } from './types'; +import { ConstructorEnum, Data, Tab } from './data'; +import { Constructor } from './pages/Constructor'; +import { DesignList } from './pages/DesignList'; +import { DestructiveAnalyzer } from './pages/DestructiveAnalyzer'; +import { LockScreen } from './pages/LockScreen'; +import { Misc } from './pages/Misc'; +import { ResearchList } from './pages/ResearchList'; export const ResearchConsole = (props) => { - const { act, data } = useBackend(); - - const { busy_msg, locked, info, imprinter_designs, lathe_designs } = data; - - const [menu, setMenu] = useSharedState('rdmenu', 0); - const [protoTab, setProtoTab] = useSharedState('protoTab', 0); - const [settingsTab, setSettingsTab] = useSharedState( - 'settingsTab', - 0, - ); - const [saveDialogTech, setSaveDialogTech] = useSharedState( - 'saveDialogTech', - false, - ); - const [saveDialogDesign, setSaveDialogDesign] = useSharedState( - 'saveDialogData', - false, - ); - - const [matsStates, setMatsState] = useState({} as mat[]); - - useEffect(() => { - setMatsState({} as mat[]); - }, [menu]); - - let allTabsDisabled = false; - if (busy_msg || locked) { - allTabsDisabled = true; - } - - const tab: React.JSX.Element[] = []; - - tab[0] = (info && ( - - )) || ; - - tab[1] = (info && ( - - )) || ; - - tab[2] = (info && ( - - )) || ; - - tab[3] = (info && ( - - )) || ; - - tab[4] = ; - - tab[5] = ; - - tab[6] = (info && ( - - )) || ; + const { data } = useBackend(); return ( - - - {menus.map((obj, i) => ( - setMenu(i)} - > - {obj.name} - - ))} - - {(busy_msg &&
{busy_msg}
) || - (locked && ( -
- -
- )) || - tab[menu]} + + {data.locked ? : }
); }; + +export const PaginationChevrons = (props: { target: string }) => { + const { act } = useBackend(); + const { target } = props; + + return ( + <> + + {!!buildActFive && ( + + )} + + + + + )) + ) : ( + + No items could be found matching the parameters (page or search). + + )} + + ); +}; + +const QueueTab = (props: { + type: ConstructorEnum; + linked_data: LinkedConstructor; +}) => { + const { act, data } = useBackend(); + const { type, linked_data } = props; + + const removeQueueAction = constructorEnumToRemoveQueue[type]; + + return ( + + {linked_data.queue.length ? ( + linked_data.queue.map((item) => ( + + {item.index === 1 && !linked_data.busy ? ( + (Awaiting Materials) + ) : null} + + + )) + ) : ( + Queue Empty. + )} + + ); +}; + +const NEVER_HIDE_MATERIALS = [ + 'steel', + 'glass', + 'plastic', + 'gold', + 'silver', + 'osmium', + 'lead', + 'phoron', + 'uranium', + 'diamond', + 'titanium', +]; + +const MatStorageTab = (props: { + type: ConstructorEnum; + linked_data: LinkedConstructor; +}) => { + const { act, data } = useBackend(); + const { type, linked_data } = props; + + const ejectAction = constructorEnumToEjectAction[type]; + + const [matEjectStates, setMatEjectStates] = useState>( + {}, + ); + + return ( + + {Object.entries(linked_data.materials).map(([mat, amount]) => { + if (amount === 0 && !NEVER_HIDE_MATERIALS.includes(mat)) { + return; + } + return ( + + { + setMatEjectStates({ + ...matEjectStates, + [mat]: val, + }); + }} + /> + + + + } + > + {amount} cm³ + + ); + })} + + ); +}; + +const ChemStorageTab = (props: { + type: ConstructorEnum; + linked_data: LinkedConstructor; +}) => { + const { act, data } = useBackend(); + const { type, linked_data } = props; + + const ejectChemAction = constructorEnumToEjectReagentAction[type]; + const ejectAllChemAction = constructorEnumToEjectReagentAllAction[type]; + + return ( + + + {linked_data.reagents?.length ? ( + linked_data.reagents.map((chem) => ( + + {chem.volume}u + + + )) + ) : ( + No chems detected + )} + + act(ejectAllChemAction)} + > + Dispose of All Chemicals In Storage + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/pages/DesignList.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/pages/DesignList.tsx new file mode 100644 index 00000000000..874ef2e407c --- /dev/null +++ b/tgui/packages/tgui/interfaces/ResearchConsole/pages/DesignList.tsx @@ -0,0 +1,58 @@ +import { useBackend } from 'tgui/backend'; +import { Box, Button, Input, LabeledList, Section } from 'tgui/components'; + +import { PaginationChevrons } from '..'; +import { Data } from '../data'; + +export const DesignList = (props) => { + const { act, data } = useBackend(); + + return ( +
+ + + + } + > + act('search', { search: v })} + mb={1} + /> + {(!!data.designs?.length && ( + + {data.designs.map((design) => ( + + act('copy_design', { copy_design_ID: design.id }) + } + > + Save To Disk + + ) + } + > + {design.desc} + + ))} + + )) || No designs found.} +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/pages/DestructiveAnalyzer.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/pages/DestructiveAnalyzer.tsx new file mode 100644 index 00000000000..8d42af68307 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ResearchConsole/pages/DestructiveAnalyzer.tsx @@ -0,0 +1,155 @@ +import { classes } from 'common/react'; +import { useEffect, useState } from 'react'; +import { useBackend } from 'tgui/backend'; +import { Box, Button, Icon, Section, Stack, Table } from 'tgui/components'; +import { BoxProps } from 'tgui/components/Box'; + +import { Data, LinkedDestroyer } from '../data'; + +export const DestructiveAnalyzer = (props) => { + const { act, data } = useBackend(); + + let inner; + + if (!data.linked_destroy) { + inner = No Destructive Analyzer linked.; + } else if (!data.linked_destroy.loaded_item) { + inner = No item loaded.; + } else { + inner = ; + } + + return ( +
+ {inner} +
+ ); +}; + +const DestroyButton = (props: { destroyer: LinkedDestroyer }) => { + const { act } = useBackend(); + const { destroyer } = props; + + let [buttonPressed, setButtonPressed] = useState(false); + + return ( + + +
act('eject_item')}>Eject} + fontSize={1.2} + mt={2} + ml={1} + backgroundColor="#0a0a0a" + height="95%" + style={{ borderRadius: '5px' }} + > + + {destroyer.loaded_item} + + + + Tech Levels - Name + + Level + + + Current + + + {destroyer.origin_tech.map((tech) => ( + + {tech.name} + {tech.level} + + {tech.current} + {tech.level >= tech.current ? ( + + ) : null} + + + ))} +
+
+
+ + + + {/* https://codepen.io/ovr/pen/yLXBbB */} + + + + +
+ ); +}; + +export const AnimatedArrows = (props: { on: boolean } & BoxProps) => { + const { on, ...rest } = props; + + const [activeArrow, setActiveArrow] = useState(0); + + // Lower to make it animate faster + const SPEED = 200; + + useEffect(() => { + const id = setInterval(() => { + setActiveArrow((arrow) => (arrow + 1) % 3); + }, SPEED); + return () => clearInterval(id); + }, []); + + return ( + + + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/pages/LockScreen.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/pages/LockScreen.tsx new file mode 100644 index 00000000000..ba3123ea357 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ResearchConsole/pages/LockScreen.tsx @@ -0,0 +1,73 @@ +import { useEffect, useRef } from 'react'; +import { useBackend } from 'tgui/backend'; +import { Box, Button, Section, Stack } from 'tgui/components'; + +export const LockScreen = (props) => { + const { act } = useBackend(); + const canvasRef = useRef(null); + const image = useRef(document.createElement('img')); + + useEffect(() => { + image.current.src = `${Byond.iconRefMap['icons/obj/machines/research.dmi']}?state=protolathe`; + }, [image]); + + let randomSizeDiff = 0; + useEffect(() => { + randomSizeDiff = Math.floor(Math.random() * 25); + + let x = 0; + let y = 0; + let x_i = 4; + let y_i = 4; + const interval = setInterval( + () => { + const current = canvasRef.current; + if (!current) { + return; + } + + const context = current.getContext('2d'); + if (!context) { + return; + } + + if (x < 0 || x > current.width - 64) { + x_i = -x_i; + } + x += x_i; + + if (y < 0 || y > current.height - 64) { + y_i = -y_i; + } + y += y_i; + + context.drawImage(image.current, x, y, 64, 64); + }, + (1 / 60) * 1000, // 60fps + ); + + () => clearInterval(interval); + }, []); + + return ( +
+ This interface is currently locked. + + Would you like to{' '} + {' '} + it? + + + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/pages/Misc.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/pages/Misc.tsx new file mode 100644 index 00000000000..1811b47cf37 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ResearchConsole/pages/Misc.tsx @@ -0,0 +1,310 @@ +import { useBackend } from 'tgui/backend'; +import { Box, Button, Icon, Section, Stack, Tooltip } from 'tgui/components'; +import { DmIcon } from 'tgui-core/components'; + +import { Data, DDisk, TDisk } from '../data'; + +export const Misc = (props) => { + const { act, data } = useBackend(); + + return ( +
+ + + + + + + + + +
+ ); +}; + +const Settings = (props) => { + const { act, data } = useBackend(); + + return ( +
+ + + +
+ ); +}; + +const SyncSettings = (props: { is_public: boolean; sync: boolean }) => { + const { act } = useBackend(); + const { is_public, sync } = props; + + if (is_public) { + return null; + } + + return sync ? ( + <> + + + + ) : ( + + ); +}; + +const DiskOptions = (props) => { + const { act, data } = useBackend(); + + return ( +
+ {!!data.t_disk && } + {!!data.d_disk && } + {!(data.t_disk || data.d_disk) && ( + No Disk Inserted + )} +
+ ); +}; + +const TechDiskOptions = (props: { data: TDisk }) => { + const { data } = props; + const { act } = useBackend(); + + return ( + + + + + + + + Technology Disk + + + {data.stored ? ( + + + {data.stored.name} + + Level {data.stored.level} + + ) : ( + Disk is empty. + )} + + + + + + + + + + + + + + + + + + + ); +}; + +enum MachineType { + Protolathe, + CircuitImprinter, + DestructiveAnalyzer, +} + +const machineTypeToState = { + [MachineType.Protolathe]: 'protolathe', + [MachineType.CircuitImprinter]: 'circuit_imprinter', + [MachineType.DestructiveAnalyzer]: 'd_analyzer', +}; + +const machineTypeToName = { + [MachineType.Protolathe]: 'Protolathe', + [MachineType.CircuitImprinter]: 'Circuit Imprinter', + [MachineType.DestructiveAnalyzer]: 'Destructive Analyzer', +}; + +const machineTypeToLink = { + [MachineType.Protolathe]: 'lathe', + [MachineType.CircuitImprinter]: 'imprinter', + [MachineType.DestructiveAnalyzer]: 'destroy', +}; + +const Machine = (props: { type: MachineType; exists: boolean }) => { + const { act } = useBackend(); + const { type, exists } = props; + return ( + + + + + + + + {machineTypeToName[type]} + + + + {exists ? 'Connected' : 'Not Connected'} + + + {!!exists && ( + + + + )} + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/pages/ResearchList.tsx b/tgui/packages/tgui/interfaces/ResearchConsole/pages/ResearchList.tsx new file mode 100644 index 00000000000..cfef50fe217 --- /dev/null +++ b/tgui/packages/tgui/interfaces/ResearchConsole/pages/ResearchList.tsx @@ -0,0 +1,45 @@ +import { useBackend } from 'tgui/backend'; +import { Box, Button, Section, Table } from 'tgui/components'; + +import { Data } from '../data'; + +export const ResearchList = (props) => { + const { act, data } = useBackend(); + + return ( +
act('print', { print: 1 })}> + Print This Page + + } + > + + {data.tech.map((thing) => ( + + + {thing.name} + - Level {thing.level} + + + {thing.desc} + + {!!data.t_disk && !data.t_disk.stored && ( + + + + )} + + ))} +
+
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/ResearchConsole/types.ts b/tgui/packages/tgui/interfaces/ResearchConsole/types.ts deleted file mode 100644 index ae377ead937..00000000000 --- a/tgui/packages/tgui/interfaces/ResearchConsole/types.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { BooleanLike } from 'common/react'; - -export type Data = { - tech: { name: string; level: number; desc: string; id: string }[]; - designs: { name: string; desc: string; id: string }[]; - lathe_designs: design[]; - imprinter_designs: design[]; - locked: BooleanLike; - busy_msg: string | null; - search: string | undefined; - builder_page: number; - design_page: number; - info: info | null; -}; - -export type menue = { name: string; icon: string }[]; - -export type destroyer = { - present: BooleanLike; - loaded_item: string | undefined; - origin_tech: { name: string; level: number; current: number | null }[]; -}; - -export type modularDevice = { - present: BooleanLike; - total_materials: number; - max_materials: number; - total_volume: number; - max_volume: number; - busy: BooleanLike; - mats: mat[]; - reagents: reagent[]; - queue: { name: string; index: number }[]; -}; - -export type design = { - name: string; - id: string; - mat_list: string[]; - chem_list: string[]; -}; - -export type mat = { - name: string; - amount: number; - sheets: number; - removable: BooleanLike; -}; - -export type reagent = { name: string; id: string; volume: number }; - -export type info = { - sync: BooleanLike; - is_public: BooleanLike; - linked_destroy: destroyer; - linked_lathe: modularDevice; - linked_imprinter: modularDevice; - t_disk: t_disk; - d_disk: d_disk; -}; - -export type d_disk = { - present: BooleanLike; - stored: BooleanLike; - name: string | undefined; - build_type: number | undefined; - materials: Record[] | undefined; -}; - -export type t_disk = { - present: BooleanLike; - stored: BooleanLike; - name: string | undefined; - level: number | undefined; - desc: string | undefined; -}; diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx index 20b513fefb2..9f7ad6713b3 100644 --- a/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx +++ b/tgui/packages/tgui/interfaces/VorePanel/VoreSelectedBellyTabs/VoreSelectedBellyDescriptions.tsx @@ -1,9 +1,9 @@ import { ReactNode, useEffect, useState } from 'react'; import { useBackend } from 'tgui/backend'; -import { Box, Button, LabeledList } from 'tgui/components'; +import { Box, Button, Dimmer, LabeledList, Section } from 'tgui/components'; import { SYNTAX_COLOR, SYNTAX_REGEX } from '../constants'; -import { selectedData } from '../types'; +import { Data, selectedData } from '../types'; import { VoreSelectedBellyDescriptionsBellymode } from '../VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsBellymode'; import { VoreSelectedBellyDescriptionsEscape } from '../VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsEscape'; import { VoreSelectedBellyDescriptionsIdle } from '../VoreSelectedBellyDescriptionTexts/VoreSelectedBellyDescriptionsIdle'; @@ -30,7 +30,7 @@ const DescriptionSyntaxHighlighting = (props: { desc: string }) => { while ((result = regexCopy.exec(desc)) !== null) { elements.push(<>{desc.substring(lastIndex, result.index)}); elements.push( - + {result[0]} , ); @@ -48,7 +48,8 @@ const DescriptionSyntaxHighlighting = (props: { desc: string }) => { export const VoreSelectedBellyDescriptions = (props: { belly: selectedData; }) => { - const { act } = useBackend(); + const { act, data } = useBackend(); + const [showFormatHelp, setShowFormatHelp] = useState(false); const { belly } = props; const { @@ -65,6 +66,57 @@ export const VoreSelectedBellyDescriptions = (props: { return ( + {showFormatHelp && ( + +
setShowFormatHelp(false)} + /> + } + scrollable + backgroundColor="black" + > + + Belly Name + Pred Name + Prey Name + + Number of prey alive, absorbed, and ghosts. + + + Number of prey absorbed. + + + Number of prey alive or absorbed, depending on whether prey is + absorbed. + + + Number of prey ghosts. + + + Number of prey and items, minus ghosts. + + + Only used in resist messages - item the prey is using to escape. + + + Only used in transfer messages - belly prey is going to. + + {Object.entries(data.vore_words).map(([word, options]) => ( + + Replaces self with one of these options: {options.join(', ')} + + ))} + +
+
+ )} +