diff --git a/_maps/map_files/voidcrew/beach.dmm b/_maps/voidcrew/planets/beach.dmm similarity index 100% rename from _maps/map_files/voidcrew/beach.dmm rename to _maps/voidcrew/planets/beach.dmm diff --git a/_maps/map_files/voidcrew/ice.dmm b/_maps/voidcrew/planets/ice.dmm similarity index 100% rename from _maps/map_files/voidcrew/ice.dmm rename to _maps/voidcrew/planets/ice.dmm diff --git a/_maps/map_files/voidcrew/jungle.dmm b/_maps/voidcrew/planets/jungle.dmm similarity index 100% rename from _maps/map_files/voidcrew/jungle.dmm rename to _maps/voidcrew/planets/jungle.dmm diff --git a/_maps/map_files/voidcrew/lava.dmm b/_maps/voidcrew/planets/lava.dmm similarity index 100% rename from _maps/map_files/voidcrew/lava.dmm rename to _maps/voidcrew/planets/lava.dmm diff --git a/_maps/map_files/voidcrew/wasteland.dmm b/_maps/voidcrew/planets/wasteland.dmm similarity index 100% rename from _maps/map_files/voidcrew/wasteland.dmm rename to _maps/voidcrew/planets/wasteland.dmm diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 43ff0c3fc23..114aeaf9fc9 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -40,10 +40,10 @@ #define R_SPAWN (1<<12) #define R_AUTOADMIN (1<<13) #define R_DBRANKS (1<<14) -#define R_ECONOMY (1<<15) #define R_DEFAULT R_AUTOADMIN +// VOIDCREW EDIT: Include the Economy permission in the complete admin permission mask (voidcrew/modules/admin). #define R_EVERYTHING (1<<16)-1 //the sum of all other rank permissions, used for +EVERYTHING #define ADMIN_QUE(user) "(?)" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm index 2474b261646..d468be8bf80 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -21,8 +21,6 @@ #define COMPONENT_MOVE_CONTENTS MOVE_CONTENTS /// From base of /atom/movable/afterShuttleMove (turf/oldT) #define COMSIG_ATOM_AFTER_SHUTTLE_MOVE "movable_after_shuttle_move" -/// VOIDCREW ADDITION. From base of /atom/movable/lateShuttleMove, once every moved atom has landed and rotated: (turf/oldT, list/movement_force, move_dir) -#define COMSIG_ATOM_LATE_SHUTTLE_MOVE "movable_late_shuttle_move" ///called on a movable (NOT living) when it starts pulling (atom/movable/pulled, state, force) #define COMSIG_ATOM_START_PULL "movable_start_pull" /// called on /atom when something attempts to pass through it (atom/movable/source, atom/movable/passing, dir) diff --git a/code/__DEFINES/explosions.dm b/code/__DEFINES/explosions.dm index 402fefbde8a..7940cf20709 100644 --- a/code/__DEFINES/explosions.dm +++ b/code/__DEFINES/explosions.dm @@ -20,6 +20,7 @@ /// A wrapper for [/atom/proc/ex_act] to ensure that the explosion propagation and attendant signal are always handled. /// VOIDCREW: recheck outpost protection when queued or direct damage is applied. +// VOIDCREW EDIT START: Block explosions on protected trader outposts before contents and signals fire (voidcrew/modules/trade/outpost_security.dm). #define EX_ACT(target, args...)\ if(!is_trader_outpost_protected(target)) { \ if(!(target.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) { \ @@ -30,6 +31,7 @@ target.ex_act(##args);\ } \ } +// VOIDCREW EDIT END // Internal explosion argument list keys. // Must match the arguments to [/datum/controller/subsystem/explosions/proc/propagate_blastwave] diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index 51ec9205b0e..d2f5528bc49 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -143,9 +143,6 @@ #define REACTION_PH_VOL_CONSTANT (1<<6) ///If a reaction will generate its impure/inverse reagents in the middle of a reaction, as apposed to being determined on ingestion/on reaction completion #define REACTION_REAL_TIME_SPLIT (1<<7) -//VOIDCREW EDIT ADDITION: reaction refuses to run inside a grown food item, so plant -//chemistry can't be used to mass-produce the mob-spawning mixtures. -//VOIDCREW EDIT END ///Used for overheat_temp - This sets the overheat so high it effectively has no overheat temperature. #define NO_OVERHEAT 99999 diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index 9e04917b240..0660f78dc57 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,6 +1,7 @@ // tgstation-server DMAPI // The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF RFC 2119. +// VOIDCREW EDIT: Match the vendored TGS DMAPI 7.4.0 version and deployment entry point in code/modules/tgs. #define TGS_DMAPI_VERSION "7.4.0" // All functions and datums outside this document are subject to change with any version and should not be relied on. @@ -587,9 +588,11 @@ /// Trigger a TGS deployment for the current instance. The current state of the repository will not be changed. +// VOIDCREW EDIT START: Match the vendored TGS DMAPI 7.4.0 version and deployment entry point in code/modules/tgs. /world/proc/TgsTriggerDeployment() CAN_BE_REDEFINED(TRUE) return +// VOIDCREW EDIT END /* The MIT License diff --git a/code/__DEFINES/wiremod.dm b/code/__DEFINES/wiremod.dm index 2618804ed8d..b606f938869 100644 --- a/code/__DEFINES/wiremod.dm +++ b/code/__DEFINES/wiremod.dm @@ -40,9 +40,6 @@ /// Associative List datatype. Derivative of list. #define PORT_TYPE_ASSOC_LIST(key_datatype, datatype) SSwiremod_composite.composite_datatype(PORT_COMPOSITE_TYPE_ASSOC_LIST, key_datatype, datatype) -//VOIDCREW EDIT ADDITION: chemistry circuits -//VOIDCREW EDIT END - // Other datatypes /// Atom datatype #define PORT_TYPE_ATOM "entity" diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 7559cfbaed1..ce3a4537eb9 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -315,8 +315,10 @@ // VOIDCREW EDIT: degrade to an empty result rather than throwing. Every caller reads // the result as "the atoms this operation applies to", so an empty list is the no-op. if(!islist(atoms) || !islist(typecache)) + // VOIDCREW EDIT START: Reject malformed typecache inputs without unsafe mass deletion; diagnostics live in voidcrew/edits/__HELPERS/_lists.dm. warn_bad_typecache_filter("typecache_filter_list", atoms, typecache) return + // VOIDCREW EDIT END for(var/atom/atom_checked as anything in atoms) if (typecache[atom_checked.type]) . += atom_checked @@ -329,8 +331,10 @@ // everything this returns, so a missing typecache must never be read as "nothing is // excluded". Empty means nothing gets deleted, which is the recoverable direction. if(!islist(atoms) || !islist(typecache)) + // VOIDCREW EDIT START: Reject malformed typecache inputs without unsafe mass deletion; diagnostics live in voidcrew/edits/__HELPERS/_lists.dm. warn_bad_typecache_filter("typecache_filter_list_reverse", atoms, typecache) return + // VOIDCREW EDIT END for(var/atom/atom_checked as anything in atoms) if(!typecache[atom_checked.type]) . += atom_checked @@ -340,8 +344,10 @@ . = list() // VOIDCREW EDIT: as above. if(!islist(atoms) || !islist(typecache_include) || !islist(typecache_exclude)) + // VOIDCREW EDIT START: Reject malformed typecache inputs without unsafe mass deletion; diagnostics live in voidcrew/edits/__HELPERS/_lists.dm. warn_bad_typecache_filter("typecache_filter_multi_list_exclusion", atoms, typecache_include) return + // VOIDCREW EDIT END for(var/atom/atom_checked as anything in atoms) if(typecache_include[atom_checked.type] && !typecache_exclude[atom_checked.type]) . += atom_checked diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm index 616ad0f10b9..f333291786d 100644 --- a/code/__HELPERS/areas.dm +++ b/code/__HELPERS/areas.dm @@ -131,11 +131,13 @@ GLOBAL_LIST_INIT(typecache_powerfailure_safe_areas, typecacheof(list( var/turf_count = length(turfs) if(!turf_count) // Check if we're in or adjacent to a shuttle area to give a more helpful error + // VOIDCREW EDIT START: Explain why hull areas need a ship expansion permit (voidcrew/modules/shuttle). var/area/current_area = get_area(creator) if(istype(current_area, /area/shuttle)) error = "You cannot use regular blueprints in a shuttle area. Use a shuttle expansion permit instead." else error = "The new area must be completely airtight and not a part of a shuttle." + // VOIDCREW EDIT END else if(turf_count > BP_MAX_ROOM_SIZE) error = "The room you're in is too big. It is [turf_count >= BP_MAX_ROOM_SIZE *2 ? "more than 100" : ((turf_count / BP_MAX_ROOM_SIZE)-1)*100]% larger than allowed." if(error) diff --git a/code/__HELPERS/logging/attack.dm b/code/__HELPERS/logging/attack.dm index b777b46ffc4..18c2500e79e 100644 --- a/code/__HELPERS/logging/attack.dm +++ b/code/__HELPERS/logging/attack.dm @@ -28,8 +28,10 @@ var/postfix = "[sobject][saddition][hp]" // VOIDCREW: ranged attacks can cross hulls; preserve the target's location too. + // VOIDCREW EDIT START: Record the target ship and overmap zone for cross-hull attacks (voidcrew/modules/admin). if(target && target != user) postfix += " \[Target location: [overmap_zone_log_context(target)]\]" + // VOIDCREW EDIT END var/message = "[what_done] [starget][postfix]" user.log_message(message, LOG_ATTACK, color="red") diff --git a/code/__HELPERS/logging/mob.dm b/code/__HELPERS/logging/mob.dm index 7461260a464..0191fedae16 100644 --- a/code/__HELPERS/logging/mob.dm +++ b/code/__HELPERS/logging/mob.dm @@ -17,8 +17,10 @@ return // VOIDCREW: keep the actual ship/zone visible in both individual and disk logs. + // VOIDCREW EDIT START: Record the attacker ship and overmap zone in combat logs (voidcrew/modules/admin). if(message_type == LOG_ATTACK || message_type == LOG_VICTIM) message += " \[Location: [overmap_zone_log_context(src)]\]" + // VOIDCREW EDIT END // Cannot use the list as a map if the key is a number, so we stringify it (thank you BYOND) var/smessage_type = num2text(message_type, MAX_BITFLAG_DIGITS) diff --git a/code/__HELPERS/paths/jps.dm b/code/__HELPERS/paths/jps.dm index 33b7eb0b75a..6fb6b4b357c 100644 --- a/code/__HELPERS/paths/jps.dm +++ b/code/__HELPERS/paths/jps.dm @@ -125,8 +125,10 @@ // These were inline list() literals, which meant two list allocations for every single node // popped off the open heap. Statics: same contents, allocated once for the whole round. + // VOIDCREW EDIT START: Reuse direction lists in fleet-scale pathfinding instead of allocating lists per node. var/static/list/cardinal_scans = list(EAST, WEST, NORTH, SOUTH) var/static/list/diagonal_scans = list(NORTHEAST, SOUTHEAST, NORTHWEST, SOUTHWEST) + // VOIDCREW EDIT END while(!open.is_empty() && !path) var/datum/jps_node/current_processed_node = open.pop() //get the lower f_value turf in the open list @@ -134,9 +136,11 @@ continue var/turf/current_turf = current_processed_node.tile + // VOIDCREW EDIT: Reuse direction lists in fleet-scale pathfinding instead of allocating lists per node. for(var/scan_direction as anything in cardinal_scans) lateral_scan_spec(current_turf, scan_direction, current_processed_node) + // VOIDCREW EDIT: Reuse direction lists in fleet-scale pathfinding instead of allocating lists per node. for(var/scan_direction as anything in diagonal_scans) diag_scan_spec(current_turf, scan_direction, current_processed_node) diff --git a/code/__HELPERS/priority_announce.dm b/code/__HELPERS/priority_announce.dm index f06403fe0dc..a36ed7ccb3c 100644 --- a/code/__HELPERS/priority_announce.dm +++ b/code/__HELPERS/priority_announce.dm @@ -172,6 +172,7 @@ var/finalized_announcement = CHAT_ALERT_COLORED_SPAN(current_level_color, jointext(level_announcement_strings, "")) + // VOIDCREW EDIT: Keep ship security announcements scoped to their recipient crew (voidcrew/modules/comms/communications_console.dm). dispatch_announcement_to_players(finalized_announcement, players, current_level_sound) /// Proc that just generates a custom header based on variables fed into `priority_announce()` diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm index bc25316a9c5..8d6d5dda46e 100644 --- a/code/__HELPERS/radiation.dm +++ b/code/__HELPERS/radiation.dm @@ -33,11 +33,14 @@ if(!SSradiation.can_fire) return + // VOIDCREW EDIT START: Skip radiation sources that cannot resolve a weak reference during deletion. var/datum/weakref/source_ref = WEAKREF(source) if(isnull(source_ref)) // null or mid-qdel source: WEAKREF() returns null and the pulse could never resolve return + // VOIDCREW EDIT END var/datum/radiation_pulse_information/pulse_information = new + // VOIDCREW EDIT: Skip radiation sources that cannot resolve a weak reference during deletion. pulse_information.source_ref = source_ref pulse_information.max_range = max_range pulse_information.threshold = threshold diff --git a/code/__HELPERS/shuttle.dm b/code/__HELPERS/shuttle.dm index 24052a5b466..e19ebf9543e 100644 --- a/code/__HELPERS/shuttle.dm +++ b/code/__HELPERS/shuttle.dm @@ -346,7 +346,7 @@ GLOBAL_LIST_EMPTY(shuttle_frames_by_turf) var/list/area_turfs = checked_area.get_turfs_by_zlevel(z) if(!checked_area.allow_shuttle_docking) . |= INTERSECTS_NON_WHITELISTED_AREA - // VOIDCREW EDIT ADDITION: a virtual domain's reservation floor is plain + // VOIDCREW EDIT ADDITION START: a virtual domain's reservation floor is plain // /area/space, which whitelists docking. Without this a bitrunner frames up a // shuttle inside VR and flies it - and everything they looted - back to the ship. else if(SSbitrunning.is_domain_turf(checked_turf)) @@ -503,10 +503,12 @@ GLOBAL_LIST_EMPTY(shuttle_frames_by_turf) shuttle.underlying_areas_by_turf += underlying_areas SEND_SIGNAL(shuttle, COMSIG_SHUTTLE_EXPANDED, turfs) if(bounds_need_recalculation) + // VOIDCREW EDIT: Release the transit reservation before recalculating changed hull bounds (voidcrew/modules/shuttle). release_assigned_transit(shuttle) //VOID EDIT - was QDEL_NULL, which leaks the reservation shuttle.calculate_docking_port_information() shuttle.initiate_docking(shuttle.get_docked(), force = TRUE) + // VOIDCREW EDIT REMOVAL: Keep routine player hull expansions in the shuttle log without per-expansion admin announcements (voidcrew/modules/shuttle). log_shuttle("[key_name(user)] expanded [shuttle] at [get_area(user)].") // VOIDCREW EDIT END @@ -564,6 +566,7 @@ GLOBAL_LIST_EMPTY(shuttle_frames_by_turf) if(docking_port_needs_relocated) shuttle.forceMove(pick(shuttle.underlying_areas_by_turf)) if(bounds_need_recalculation) + // VOIDCREW EDIT: Release the transit reservation before recalculating changed hull bounds (voidcrew/modules/shuttle). release_assigned_transit(shuttle) //VOID EDIT - was QDEL_NULL, which leaks the reservation shuttle.calculate_docking_port_information() // VOIDCREW EDIT END diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 29395bd0835..c34acdaa3e6 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -33,7 +33,7 @@ GLOBAL_PROTECT(##log_var_name);\ // These should be used where the log category cannot easily be a json log file. DECLARE_LOG(config_error_log, DONT_START_LOG) DECLARE_LOG(perf_log, DONT_START_LOG) // Declared here but name is set in time_track subsystem -DECLARE_LOG(worldgen_log, START_LOG) // Planet/ruin/asteroid/ship generation timing, correlated with time dilation - see code/__HELPERS/logging/worldgen.dm +DECLARE_LOG(worldgen_log, START_LOG) // Planet/ruin/asteroid/ship generation timing, correlated with time dilation - see voidcrew/modules/worldgen_logging/worldgen.dm // VOIDCREW EDIT: metrics records world-generation timing. #ifdef REFERENCE_TRACKING_LOG_APART DECLARE_LOG_NAMED(harddel_log, "harddels", START_LOG) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 19d836a68f1..09152dcb06d 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -25,8 +25,10 @@ var/mod = next_move_modifier var/adj = next_move_adjust // MonkeStation's crit item usage: actions in soft crit take four times as long. + // VOIDCREW EDIT START: Allow slow item actions in soft crit through incapacitated_except_softcrit(). if(stat == SOFT_CRIT) mod *= 4 + // VOIDCREW EDIT END for(var/datum/status_effect/effect as anything in status_effects) mod *= effect.nextmove_modifier() adj += effect.nextmove_adjust() @@ -110,6 +112,7 @@ CtrlClickOn(A) return + // VOIDCREW EDIT: Allow slow item actions in soft crit through incapacitated_except_softcrit(). if(incapacitated_except_softcrit(INCAPABLE_RESTRAINTS|INCAPABLE_STASIS)) return diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 28b2a90962e..3df4d448587 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -131,6 +131,7 @@ /atom/movable/screen/alert/MouseExited() + // VOIDCREW EDIT: Run parent screen initialization for Voidcrew HUD extensions in voidcrew/edits/_onclick/hud. . = ..() closeToolTip(usr) diff --git a/code/_onclick/hud/blob_overmind.dm b/code/_onclick/hud/blob_overmind.dm index e2c4f57c573..10e85b488e3 100644 --- a/code/_onclick/hud/blob_overmind.dm +++ b/code/_onclick/hud/blob_overmind.dm @@ -8,6 +8,7 @@ openToolTip(usr,src,params,title = name,content = desc, theme = "blob") /atom/movable/screen/blob/MouseExited() + // VOIDCREW EDIT: Run parent screen initialization for Voidcrew HUD extensions in voidcrew/edits/_onclick/hud. . = ..() closeToolTip(usr) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index e409332dff5..cd19b7874e5 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -192,6 +192,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( // A hud can outlive its mob (and plane groups can be rebuilt while detached), and this // runs at the very top of build_planes_offset() - runtiming here skips the whole // offset rebuild, which is how clients end up rendering to planes that have no master. + // VOIDCREW EDIT: Tolerate a HUD that outlives its mob during plane offset rebuilding. return should_sight_scale(mymob?.sight) // VOIDCREW EDIT END @@ -279,6 +280,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( /datum/hud/proc/build_plane_groups(starting_offset, ending_offset) for(var/group_key in master_groups) var/datum/plane_master_group/group = master_groups[group_key] + // VOIDCREW EDIT START: Refresh newly built HUD planes after live z-level growth (voidcrew/edits/_onclick/hud). var/list/atom/movable/screen/plane_master/new_planes = group.build_plane_masters(starting_offset, ending_offset) if(!length(new_planes)) continue @@ -287,6 +289,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( // Match what group creation does after show_hud(), so the planes we just added get the same multiz // scaling and in/out of bounds treatment a client who connected after the load would have gotten group.build_planes_offset(src, current_plane_offset) + // VOIDCREW EDIT END /// Returns the plane master that matches the input plane from the passed in group /datum/hud/proc/get_plane_master(plane, group_key = PLANE_GROUP_MAIN) @@ -812,21 +815,25 @@ GLOBAL_LIST_INIT(available_ui_styles, list( if(!length(actions)) palette.set_expanded(FALSE) +// VOIDCREW EDIT REMOVAL: Disable the upstream palette layout replaced by voidcrew/edits/_onclick/hud, preserving the existing override chain. ///Commenting out due to this being replaced in 'voidcrew\edits\_onclick\hud' and the return ..() requirement // /datum/action_group/palette/refresh_actions() // var/atom/movable/screen/button_palette/palette = owner.toggle_palette // var/atom/movable/screen/palette_scroll/scroll_down = owner.palette_down // var/atom/movable/screen/palette_scroll/scroll_up = owner.palette_up +// VOIDCREW EDIT REMOVAL: Disable the upstream palette layout replaced by voidcrew/edits/_onclick/hud, preserving the existing override chain. // var/actions_above = round((owner.listed_actions.size() - 1) / owner.listed_actions.column_max) // north_offset = initial(north_offset) + actions_above +// VOIDCREW EDIT REMOVAL: Disable the upstream palette layout replaced by voidcrew/edits/_onclick/hud, preserving the existing override chain. // palette.screen_loc = ui_action_palette_offset(actions_above) // var/action_count = length(owner?.mymob?.actions) // var/our_row_count = round((length(actions) - 1) / column_max) // if(!action_count) // palette.screen_loc = null +// VOIDCREW EDIT REMOVAL: Disable the upstream palette layout replaced by voidcrew/edits/_onclick/hud, preserving the existing override chain. // if(palette.expanded && action_count && our_row_count >= max_rows) // scroll_down.screen_loc = ui_palette_scroll_offset(actions_above) // scroll_up.screen_loc = ui_palette_scroll_offset(actions_above) @@ -834,6 +841,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( // scroll_down.screen_loc = null // scroll_up.screen_loc = null +// VOIDCREW EDIT REMOVAL: Disable the upstream palette layout replaced by voidcrew/edits/_onclick/hud, preserving the existing override chain. // return ..() /datum/action_group/palette/ButtonNumberToScreenCoords(number, landing) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 28771c1bd3a..30aa542be69 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -65,11 +65,13 @@ using = new /atom/movable/screen/navigate(null, src) using.icon = ui_style using.screen_loc = ui_human_navigate + // VOIDCREW EDIT START: Install the skill-report HUD shortcut defined in voidcrew/edits/_onclick/hud/screen_extensions.dm. static_inventory += using using = new /atom/movable/screen/skills(null, src) using.icon = ui_style using.screen_loc = ui_human_skills + // VOIDCREW EDIT END static_inventory += using using = new /atom/movable/screen/area_creator(null, src) @@ -392,7 +394,6 @@ screenmob.client.screen -= H.head - /datum/hud/human/persistent_inventory_update(mob/viewer) if(!mymob) return diff --git a/code/_onclick/hud/new_player.dm b/code/_onclick/hud/new_player.dm index 7c02482db14..e116b34224b 100644 --- a/code/_onclick/hud/new_player.dm +++ b/code/_onclick/hud/new_player.dm @@ -225,9 +225,11 @@ // transfer ran straight into "Cannot read null.prefs" here. The prefs datum is also // per-client, and /datum/preferences/ui_status() closes the menu unless // user.client == parent, so reading it off any other client's mob is wrong anyway. + // VOIDCREW EDIT START: Resolve preferences from the clicking client safely across logout and mob transfer. var/datum/preferences/preferences = usr.client?.prefs if(!preferences) return + // VOIDCREW EDIT END preferences.current_window = PREFERENCE_TAB_CHARACTER_PREFERENCES preferences.update_static_data(usr) preferences.ui_interact(usr) @@ -422,9 +424,11 @@ return // Same as the Character Setup button above: the clicking client's own prefs. + // VOIDCREW EDIT START: Resolve preferences from the clicking client safely across logout and mob transfer. var/datum/preferences/preferences = usr.client?.prefs if(!preferences) return + // VOIDCREW EDIT END preferences.current_window = PREFERENCE_TAB_GAME_PREFERENCES preferences.update_static_data(usr) preferences.ui_interact(usr) @@ -764,8 +768,10 @@ var/new_maptext var/round_started = SSticker.HasRoundStarted() if(round_started) + // VOIDCREW EDIT START: Show fleet player count without a station map name in the lobby HUD. new_maptext = "[LAZYLEN(GLOB.clients)] player\s online
\ [ROUND_TIME()] in
" + // VOIDCREW EDIT END var/datum/station_trait/overflow_job_bureaucracy/overflow = locate() in SSstation.station_traits if(overflow) new_maptext += "[overflow.chosen_job_name] overflow" diff --git a/code/_onclick/hud/parallax/parallax.dm b/code/_onclick/hud/parallax/parallax.dm index f94d56ea184..f60d0eb70b7 100644 --- a/code/_onclick/hud/parallax/parallax.dm +++ b/code/_onclick/hud/parallax/parallax.dm @@ -177,6 +177,7 @@ return C.parallax_animate_timers -= layer if(!layer.scroll_loops) // VOIDCREW EDIT ADDITION - see set_parallax_movedir() + // VOIDCREW EDIT: Do not reschedule parallax animation after its scroll loop has been disabled (voidcrew/edits/_onclick/hud). return // If we are moving in a direction, we used the QUAD_EASING function with EASE_IN diff --git a/code/_onclick/hud/rendering/plane_master_group.dm b/code/_onclick/hud/rendering/plane_master_group.dm index 473240dde7c..34bb6d989d9 100644 --- a/code/_onclick/hud/rendering/plane_master_group.dm +++ b/code/_onclick/hud/rendering/plane_master_group.dm @@ -96,6 +96,7 @@ /// Returns the list of plane masters we just built, so callers that run after we already have a hud can show them // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/plane_master_group/proc/build_plane_masters(starting_offset, ending_offset) + // VOIDCREW EDIT: Return new plane masters so the HUD can show and offset planes after a live map load. var/list/atom/movable/screen/plane_master/built = list() for(var/atom/movable/screen/plane_master/mytype as anything in get_plane_types()) for(var/plane_offset in starting_offset to ending_offset) @@ -104,8 +105,10 @@ var/atom/movable/screen/plane_master/instance = new mytype(null, null, src, plane_offset) plane_masters["[instance.plane]"] = instance prep_plane_instance(instance) + // VOIDCREW EDIT START: Return new plane masters so the HUD can show and offset planes after a live map load. built += instance return built + // VOIDCREW EDIT END /// Similarly, exists so subtypes can do unique behavior to planes on creation // VOIDCREW EDIT END diff --git a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm index 71a68188a81..5ee0847d7b2 100644 --- a/code/_onclick/hud/rendering/plane_masters/_plane_master.dm +++ b/code/_onclick/hud/rendering/plane_masters/_plane_master.dm @@ -215,6 +215,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) // all pass `our_hud?.mymob`). hide_from() below tolerates that, so this must too - // a runtime here aborts whatever loop is walking the plane masters and leaves the // client with planes nothing is managing. + // VOIDCREW EDIT: Tolerate detached HUD mobs while hiding and restoring plane masters. var/client/our_client = relevant?.client if(our_client) for(var/atom/movable/render_plane_relay/relay as anything in relays) @@ -234,6 +235,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) if(!(critical & PLANE_CRITICAL_NO_RELAY)) return + // VOIDCREW EDIT: Tolerate detached HUD mobs while hiding and restoring plane masters. var/client/our_client = relevant?.client if(our_client) for(var/atom/movable/render_plane_relay/relay as anything in relays) diff --git a/code/_onclick/hud/rendering/render_plate.dm b/code/_onclick/hud/rendering/render_plate.dm index 09666fcff50..d0a5c0e1050 100644 --- a/code/_onclick/hud/rendering/render_plate.dm +++ b/code/_onclick/hud/rendering/render_plate.dm @@ -206,8 +206,10 @@ // unhide_plane() callsite passes `our_hud?.mymob`, so null gets here for real. Runtiming // would abort whichever loop is walking the plane masters (show_hud(), build_planes_offset(), // the COMSIG_PLANE_OFFSET_INCREASE fanout) and leave planes with no master managing them. + // VOIDCREW EDIT START: Guard detached HUD mobs during lighting plate and sight-signal cleanup. if(!istype(mymob)) return + // VOIDCREW EDIT END // This applies a backdrop to our lighting plane // Why do plane masters need a backdrop sometimes? Read https://secure.byond.com/forum/?post=2141928 // Basically, we need something to brighten @@ -233,9 +235,11 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /atom/movable/screen/plane_master/rendering_plate/lighting/hide_from(mob/oldmob) . = ..() + // VOIDCREW EDIT START: Guard detached HUD mobs during lighting plate and sight-signal cleanup. if(istype(oldmob)) oldmob.clear_fullscreen("lighting_backdrop_lit_[home.key]#[offset]") oldmob.clear_fullscreen("lighting_backdrop_unlit_[home.key]#[offset]") + // VOIDCREW EDIT END var/datum/hud/hud = home.our_hud if(hud) UnregisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change)) @@ -293,8 +297,10 @@ if(!.) return // See the lighting plate above - a null/clientless mob is a supported caller here. + // VOIDCREW EDIT START: Guard detached HUD mobs during lighting plate and sight-signal cleanup. if(!istype(mymob)) return + // VOIDCREW EDIT END RegisterSignal(mymob, COMSIG_MOB_SIGHT_CHANGE, PROC_REF(handle_sight), override = TRUE) handle_sight(mymob, mymob.sight, NONE) @@ -306,8 +312,10 @@ var/atom/movable/screen/plane_master/emissive = home.get_plane(GET_NEW_PLANE(RENDER_PLANE_EMISSIVE, offset)) emissive.remove_filter("lighting_mask") remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, offset)) + // VOIDCREW EDIT START: Guard detached HUD mobs during lighting plate and sight-signal cleanup. if(istype(oldmob)) UnregisterSignal(oldmob, COMSIG_MOB_SIGHT_CHANGE) + // VOIDCREW EDIT END // VOIDCREW EDIT END /atom/movable/screen/plane_master/rendering_plate/light_mask/proc/handle_sight(datum/source, new_sight, old_sight) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index f94402fbeec..eb78d5e0d8f 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -132,7 +132,6 @@ var/mob/living/navigator = usr navigator.navigate() -/// Shortcut to the same personal skill report provided by the View Skills verb. /atom/movable/screen/craft name = "crafting menu" icon = 'icons/hud/screen_midnight.dmi' @@ -187,6 +186,7 @@ if(world.time <= usr.next_move) return TRUE + // VOIDCREW EDIT: Allow inventory interaction in soft crit via incapacitated_except_softcrit(). if(usr.incapacitated_except_softcrit(INCAPABLE_STASIS)) return TRUE if(ismecha(usr.loc)) // stops inventory actions in a mech @@ -279,6 +279,7 @@ return TRUE if(world.time <= user.next_move) return TRUE + // VOIDCREW EDIT: Allow inventory interaction in soft crit via incapacitated_except_softcrit(). if(user.incapacitated_except_softcrit()) return TRUE if (ismecha(user.loc)) // stops inventory actions in a mech @@ -525,6 +526,7 @@ if(world.time <= usr.next_move) return TRUE + // VOIDCREW EDIT: Allow inventory interaction in soft crit via incapacitated_except_softcrit(). if(usr.incapacitated_except_softcrit()) return TRUE if(ismecha(usr.loc)) // stops inventory actions in a mech @@ -644,6 +646,7 @@ // VOIDCREW EDIT START - PR #284: Port MonkeStation soft-crit item use. /atom/movable/screen/zone_sel/MouseExited(location, control, params) + // VOIDCREW EDIT: Allow inventory interaction in soft crit via incapacitated_except_softcrit(). . = ..() if(!isobserver(usr) && hovering) vis_contents -= hover_overlays_cache[hovering] @@ -803,6 +806,7 @@ // VOIDCREW EDIT START - PR #284: Port MonkeStation soft-crit item use. /atom/movable/screen/healthdoll/human/update_body_zones() + // VOIDCREW EDIT REMOVAL: Allow inventory interaction in soft crit via incapacitated_except_softcrit(). vis_contents.Cut() QDEL_LIST_ASSOC_VAL(limbs) limbs ||= list() diff --git a/code/_onclick/hud/screentip.dm b/code/_onclick/hud/screentip.dm index 5aae8dc4809..dac8a1a536c 100644 --- a/code/_onclick/hud/screentip.dm +++ b/code/_onclick/hud/screentip.dm @@ -7,79 +7,17 @@ maptext_width = 480 maptext = "" layer = SCREENTIP_LAYER //Added to make screentips appear above action buttons (and other /atom/movable/screen objects) - /// Weak reference so hovering cannot keep a deleted target alive. - var/datum/weakref/hovered_atom_ref - /// Invalidates text measurements that finish after the pointer has moved on. - var/hover_version = 0 - var/showing_hover = FALSE - /// Refreshed separately from mouse events, including while our ship is moving. - var/fallback_maptext = "" /atom/movable/screen/screentip/Initialize(mapload, datum/hud/hud_owner) . = ..() update_view() + // VOIDCREW EDIT START: Initialize the persistent hover and overmap fallback lifecycle in voidcrew/edits/_onclick/hud/screen_extensions.dm. update_fallback() START_PROCESSING(SSprocessing, src) if(hud?.mymob) RegisterSignal(hud.mymob, list(COMSIG_MOB_LOGIN, COMSIG_MOB_LOGOUT), PROC_REF(on_connection_changed)) + // VOIDCREW EDIT END -/atom/movable/screen/screentip/Destroy() - STOP_PROCESSING(SSprocessing, src) - hovered_atom_ref = null - return ..() - -/atom/movable/screen/screentip/process(seconds_per_tick) - if(!hud?.mymob?.client) - return - if(hovered_atom_ref && !hovered_atom_ref.resolve()) - clear_hover() - update_fallback() - -/// Starts a hover and returns the version to use for asynchronous text measurement. -/atom/movable/screen/screentip/proc/begin_hover(atom/target) - hovered_atom_ref = WEAKREF(target) - return ++hover_version - -/// An exit from an older target must not clear a more recent hover. -/atom/movable/screen/screentip/proc/clear_hover(atom/target) - if(target && !IS_WEAKREF_OF(target, hovered_atom_ref)) - return - hovered_atom_ref = null - hover_version++ - set_hover_text("") - -/// Empty or suppressed hover text gives the fallback its turn. -/atom/movable/screen/screentip/proc/set_hover_text(new_maptext, text_y = 10) - showing_hover = length(new_maptext) > 0 - if(showing_hover) - maptext = new_maptext - maptext_y = text_y - else - show_fallback() - -/atom/movable/screen/screentip/proc/show_fallback() - maptext = hud?.screentips_enabled == SCREENTIP_PREFERENCE_DISABLED ? "" : fallback_maptext - maptext_y = 10 - -/atom/movable/screen/screentip/proc/update_fallback() - fallback_maptext = hud?.screentips_enabled == SCREENTIP_PREFERENCE_DISABLED ? "" : get_fallback_maptext() - if(!showing_hover) - show_fallback() - -/// Reused HUDs must not retain a hover from the previous connection. -/atom/movable/screen/screentip/proc/on_connection_changed(datum/source) - SIGNAL_HANDLER - update_fallback() - clear_hover() - -/// Reapply a changed preference even when the pointer stays still. -/atom/movable/screen/screentip/proc/refresh_hover() - update_fallback() - var/atom/target = hovered_atom_ref?.resolve() - if(target && hud?.mymob?.client) - target.on_mouse_enter(hud.mymob.client) - else - clear_hover() /atom/movable/screen/screentip/proc/update_view(datum/source) SIGNAL_HANDLER diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index f46b6f2d80b..80bc0e6dd5c 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -39,9 +39,11 @@ // base_click_alt() is a dead end for ghosts: can_perform_action() is always false for them, // so alt clicking as a ghost did nothing at all. if(LAZYACCESS(modifiers, RIGHT_CLICK)) + // VOIDCREW EDIT START: Dispatch observer alt clicks to the loot and admin tagging handlers in voidcrew/edits/_onclick. AltClickSecondaryOn(A) else AltClickOn(A) + // VOIDCREW EDIT END return if(LAZYACCESS(modifiers, CTRL_CLICK)) CtrlClickOn(A) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 92664d6d18b..51174623d64 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -53,14 +53,18 @@ return FALSE if(!right_click_attack_chain(attack_target, modifiers)) + // VOIDCREW EDIT START: Report actual resolved unarmed damage to Voidcrew combat listeners after the attack. var/mob/living/living_target = isliving(attack_target) ? attack_target : null var/health_before = living_target?.health var/stamina_before = living_target?.getStaminaLoss() + // VOIDCREW EDIT END resolve_unarmed_attack(attack_target, modifiers) // Report real damage after pacifism, blocking, and attack-type checks have run. // Keep the local reference through the call so lethal DEL_ON_DEATH hits still report their result. + // VOIDCREW EDIT START: Report actual resolved unarmed damage to Voidcrew combat listeners after the attack. if(living_target) SEND_SIGNAL(src, COMSIG_LIVING_AFTER_UNARMED_ATTACK, attack_target, modifiers, max(0, health_before - living_target.health), max(0, living_target.getStaminaLoss() - stamina_before)) + // VOIDCREW EDIT END return TRUE // VOIDCREW EDIT END diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 7157b0aa1b3..6a7fd36072f 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -461,8 +461,6 @@ /datum/config_entry/string/new_player_alert_role_id -/// Discord role ID pinged in the new-round announcement sent to CHANNEL_ANNOUNCE_NEW_GAME channels -/datum/config_entry/string/new_round_alert_role_id /datum/config_entry/keyed_list/positive_station_traits default = list("0" = 8, "1" = 4, "2" = 2, "3" = 1) diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 189760f6984..e74fa74626a 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -135,6 +135,7 @@ SUBSYSTEM_DEF(air) // outside process_rebuilds() - that block only runs when a queue is non-empty, and an // orphan by definition is not in any queue. Runs before the drain so it can never be // editing networks/expansion_queue while expand_pipeline() is walking them. + // VOIDCREW EDIT: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). reap_orphan_pipelines() // Every time we fire, we want to make sure pipenets are rebuilt. The game state could have changed between each fire() proc call @@ -310,6 +311,7 @@ SUBSYSTEM_DEF(air) // constantly: pipe/nullify_node() queues the neighbour it just disconnected from, and // during a mass deletion that neighbour is very often already in the qdel queue. if(QDELETED(atmos_machine)) + // VOIDCREW EDIT: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). return if(istype(atmos_machine, /obj/machinery/atmospherics) && !atmos_machine.rebuilding) rebuild_queue += atmos_machine @@ -327,6 +329,7 @@ SUBSYSTEM_DEF(air) for(var/list/packet in expansion_queue.Copy()) if(packet[SSAIR_REBUILD_PIPELINE] == line) expansion_queue -= packet +// VOIDCREW EDIT REMOVAL: Remove every queued expansion packet for a deleted pipeline instead of stopping after the first match. /datum/controller/subsystem/air/proc/process_atoms(resumed = FALSE) if(!resumed) @@ -428,6 +431,7 @@ SUBSYSTEM_DEF(air) return /datum/controller/subsystem/air/proc/process_rebuilds() + // VOIDCREW EDIT: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). reap_pipeline_husks() //Yes this does mean rebuilding pipenets can freeze up the subsystem forever, but if we're in that situation something else is very wrong var/list/currentrun = rebuild_queue @@ -506,11 +510,13 @@ SUBSYSTEM_DEF(air) // expansion_queue, which is the list this very drain is walking. Park it and // let reap_pipeline_husks() take it on a later fire - leaving it was a // permanent member-less pipeline in SSair.networks, one per site build. + // VOIDCREW EDIT START: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). if(stolen_from && stolen_from != net && !QDELETED(stolen_from) && !length(stolen_from.members) && !length(stolen_from.other_atmos_machines)) if(stolen_from.building) pipeline_husks |= stolen_from else qdel(stolen_from) + // VOIDCREW EDIT END if(item.air_temporary) net.air.merge(item.air_temporary) @@ -770,6 +776,7 @@ SUBSYSTEM_DEF(air) // pipeline into SSair.networks, and a machine that deleted itself during its own // Initialize() will never delete that pipeline again. if(QDELETED(AM)) + // VOIDCREW EDIT: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). continue var/list/targets = AM.get_rebuild_targets() for(var/datum/pipeline/build_off as anything in targets) @@ -804,6 +811,7 @@ GLOBAL_LIST_EMPTY(colored_images) // (stacked pipes on one turf, which every voidcrew hull has some of). Minting a // pipeline for it leaks one per template load, and this soak loads constantly. if(QDELETED(AM)) + // VOIDCREW EDIT: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). continue var/list/targets = AM.get_rebuild_targets() for(var/datum/pipeline/build_off as anything in targets) @@ -863,8 +871,10 @@ GLOBAL_LIST_EMPTY(colored_images) // ADD_GAS below then indexes a null list once per turf that uses the string. // Warn once for the mix instead and leave that component out. if(!ispath(path)) + // VOIDCREW EDIT START: Keep atmos rebuild cleanup safe across repeated site loads (voidcrew/edits/controllers/subsystem/air.dm). stack_trace("parse_gas_string(): unknown gas id \"[id]\" in gas string \"[gas_string]\" - ignoring it.") continue + // VOIDCREW EDIT END ADD_GAS(path, gases) gases[path][MOLES] = text2num(gas[id]) diff --git a/code/controllers/subsystem/area_contents.dm b/code/controllers/subsystem/area_contents.dm index c15bdc48152..196a16b0679 100644 --- a/code/controllers/subsystem/area_contents.dm +++ b/code/controllers/subsystem/area_contents.dm @@ -35,11 +35,13 @@ SUBSYSTEM_DEF(area_contents) var/area/test = currentrun[length(currentrun)] // A destroyed area has both bookkeeping lists nulled, so there is nothing to mark and // marking it would only pin the corpse until the next drain. + // VOIDCREW EDIT START: Discard destroyed areas from deferred turf bookkeeping during site teardown. if(!QDELETED(test)) for (var/area_zlevel in 1 to length(test.turfs_to_uncontain_by_zlevel)) if(length(test.turfs_to_uncontain_by_zlevel[area_zlevel]) > ALLOWED_LOOSE_TURFS) marked_for_clearing |= test break + // VOIDCREW EDIT END currentrun.len-- if(MC_TICK_CHECK) return @@ -50,11 +52,13 @@ SUBSYSTEM_DEF(area_contents) // Marked during the scan, died before the drain reached it. /area/Destroy() nulls // turfs_to_uncontain_by_zlevel, so every length() below would read 0 anyway - drop it // rather than leaving a dead area sitting at the end of the list. + // VOIDCREW EDIT START: Discard destroyed areas from deferred turf bookkeeping during site teardown. if(QDELETED(clear) || isnull(clear.turfs_to_uncontain_by_zlevel)) marked_for_clearing.len-- if(MC_TICK_CHECK) return continue + // VOIDCREW EDIT END for (var/area_zlevel in 1 to length(clear.turfs_to_uncontain_by_zlevel)) if (!length(clear.turfs_to_uncontain_by_zlevel[area_zlevel])) diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 987d1b93302..19dfaf97ef5 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -57,16 +57,19 @@ SUBSYSTEM_DEF(atoms) clear_tracked_initalize(source) SSicon_smooth.free_deferred(source) + // VOIDCREW EDIT START: Give nested live template loads separate late-initialization queues. while(length(late_loaders)) // Late callbacks can load another map. Give that load its own queue so it // cannot repeat or clear the callbacks this invocation is still processing. var/list/current_late_loaders = late_loaders late_loaders = list() for(var/atom/A as anything in current_late_loaders) + // VOIDCREW EDIT END //I hate that we need this if(QDELETED(A)) continue A.LateInitialize() + // VOIDCREW EDIT: Give nested live template loads separate late-initialization queues. testing("Late initialized [length(current_late_loaders)] atoms") if (created_atoms) diff --git a/code/controllers/subsystem/explosions.dm b/code/controllers/subsystem/explosions.dm index 0e86ab70806..c1f1321cc67 100644 --- a/code/controllers/subsystem/explosions.dm +++ b/code/controllers/subsystem/explosions.dm @@ -189,7 +189,6 @@ ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effec explosion(epicenter, devastation_range = round(range * 0.25), heavy_impact_range = round(range * 0.5), light_impact_range = round(range), flame_range = flame_range*range, flash_range = flash_range*range, adminlog = adminlog, ignorecap = ignorecap, silent = silent, smoke = smoke, explosion_cause = explosion_cause) - /** * Makes a given atom explode. * @@ -301,9 +300,11 @@ ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effec if(!epicenter) return // VOIDCREW: suppress the blast before smoke, flashes, fire, or chain reactions. + // VOIDCREW EDIT START: Stop protected outpost blasts before smoke, flash, ignition and damage (voidcrew/modules/trade/outpost_security.dm). if(is_trader_outpost_protected(epicenter)) log_game("OUTPOST PROTECTION: Suppressed explosion ([devastation_range], [heavy_impact_range], [light_impact_range]) at [AREACOORD(epicenter)]. Cause: [explosion_cause]. Last fingerprints: [key_name(explosion_cause?.fingerprintslast)].") return + // VOIDCREW EDIT END if(isnull(flame_range)) flame_range = light_impact_range @@ -397,8 +398,10 @@ ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effec //flash mobs if(flash_range) for(var/mob/living/L in viewers(flash_range, epicenter)) + // VOIDCREW EDIT START: Stop protected outpost blasts before smoke, flash, ignition and damage (voidcrew/modules/trade/outpost_security.dm). if(is_trader_outpost_protected(L)) // VOIDCREW continue + // VOIDCREW EDIT END L.flash_act() var/list/affected_turfs = prepare_explosion_turfs(max_range, epicenter, protect_epicenter, explosion_direction, explosion_arc) @@ -414,9 +417,11 @@ ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effec //we presuppose that we'll be iterating away from the epicenter for(var/turf/explode as anything in affected_turfs) // VOIDCREW: outside blasts cannot damage, ignite, or throw outpost contents. + // VOIDCREW EDIT START: Stop protected outpost blasts before smoke, flash, ignition and damage (voidcrew/modules/trade/outpost_security.dm). if(is_trader_outpost_protected(explode)) cached_exp_block[explode] = INFINITY continue + // VOIDCREW EDIT END var/our_x = explode.x var/our_y = explode.y var/dist = CHEAP_HYPOTENUSE(our_x, our_y, x0, y0) @@ -541,7 +546,7 @@ ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effec else creaking = FALSE - // VOIDCREW EDIT ADDITION: packed-level containment. Resolved once, outside the loop. + // VOIDCREW EDIT ADDITION START: packed-level containment. Resolved once, outside the loop. // The walk below is GLOB.player_list filtered on bare z, and its reach is // heavy_impact_range * 15 + devastation_range * 20 - well over 100 tiles for a large // blast, against the 6 tiles that separate two tenants of a packed level. playsound_local() @@ -554,7 +559,7 @@ ADMIN_VERB(check_bomb_impacts, R_DEBUG, "Check Bomb Impact", "See what the effec var/turf/listener_turf = get_turf(listener) if(!listener_turf || listener_turf.z != blast_z) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START if(map_region_excludes_turf(blast_region, listener_turf)) continue // VOIDCREW EDIT END diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 720fca4164f..3f0cb526334 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -943,10 +943,12 @@ SUBSYSTEM_DEF(job) job_debug("[debug_prefix]: Player has no mind, Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_GENERIC + // VOIDCREW EDIT START: Use canonical role eligibility and configuration for mapper-selected silicon crew (voidcrew/modules/ship_upgrades). var/eligibility_title = possible_job.ship_role == "crew" ? possible_job.title : initial(possible_job.title) if(possible_job.ship_role != "crew" && !possible_job.config_check()) return JOB_UNAVAILABLE_GENERIC if(eligibility_title in LAZYACCESS(prevented_occupations, player.mind)) + // VOIDCREW EDIT END job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_ANTAG_INCOMPAT, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_ANTAG_INCOMPAT @@ -960,6 +962,7 @@ SUBSYSTEM_DEF(job) return JOB_UNAVAILABLE_PLAYTIME // Run the banned check last since it should be the rarest check to fail and can access the database. + // VOIDCREW EDIT: Use canonical role eligibility and configuration for mapper-selected silicon crew (voidcrew/modules/ship_upgrades). if(is_banned_from(player.ckey, eligibility_title)) job_debug("[debug_prefix] Error: [get_job_unavailable_error_message(JOB_UNAVAILABLE_BANNED, possible_job.title)], Player: [player][add_job_to_log ? ", Job: [possible_job]" : ""]") return JOB_UNAVAILABLE_BANNED diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 68803f4e2ce..39d8aa0f1e9 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -32,7 +32,7 @@ SUBSYSTEM_DEF(lighting) /datum/controller/subsystem/lighting/proc/create_all_lighting_objects() for(var/area/area as anything in GLOB.areas) - // VOIDCREW EDIT: ambient-lit ground (a planet surface, static_lighting FALSE) carries + // VOIDCREW EDIT START: ambient-lit ground (a planet surface, static_lighting FALSE) carries // no lighting objects at all - that is where the memory saving comes from - EXCEPT // turfs that light themselves, like the fallout zone's hazard green. Those need an // object apiece or their own light has nothing to render on, and roundstart planets @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(lighting) for(var/turf/area_turf as anything in zlevel_turfs) if(area_turf.space_lit) continue - // VOIDCREW EDIT: see above + // VOIDCREW EDIT START: see above if(ambient_lit_area && area_turf.skips_lighting_object()) continue // END VOIDCREW EDIT @@ -67,6 +67,7 @@ SUBSYSTEM_DEF(lighting) // with needs_update set but in no queue, so EFFECT_UPDATE refuses to requeue // them and they stay dark forever. Salvage the remainder instead of leaking it. if(length(current_sources)) + // VOIDCREW EDIT: Handle planetary ambient lighting and interrupted source drains (voidcrew/edits/lighting.dm). sources_queue = current_sources + sources_queue current_sources = sources_queue sources_queue = list() diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 383b6e4b3d4..291620ff702 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -61,9 +61,6 @@ SUBSYSTEM_DEF(mapping) var/list/used_turfs = list() //list of turf = datum/turf_reservation /// List of lists of turfs to reserve var/list/lists_to_reserve = list() - // VOIDCREW EDIT ADDITION: one-shot latch for the dead-area recovery in fire() below. - // VOIDCREW EDIT ADDITION: released reservation turfs whose starlight has been switched - // VOIDCREW EDIT ADDITION: world.time the next used_turfs orphan sweep may run at. var/list/reservation_ready = list() var/clearing_reserved_turfs = FALSE @@ -197,6 +194,7 @@ SUBSYSTEM_DEF(mapping) var/turf/reserving_turf = packet[packetlen] reserving_turf.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE) LAZYINITLIST(unused_turfs["[reserving_turf.z]"]) + // VOIDCREW EDIT: Use turf-keyed reservation membership so handing back large sites avoids quadratic list scans. unused_turfs["[reserving_turf.z]"][reserving_turf] = TRUE var/area/old_area = reserving_turf.loc // VOIDCREW EDIT ADDITION START - never wedge the reservation queue on a dead area. @@ -219,7 +217,7 @@ SUBSYSTEM_DEF(mapping) reserving_turf.turf_flags = UNUSED_RESERVATION_TURF // reservation turfs are not allowed to interact with atmos at all reserving_turf.blocks_air = TRUE - // VOIDCREW EDIT ADDITION - darken a released reservation turf. + // VOIDCREW EDIT ADDITION START - darken a released reservation turf. // // A reservation is filled with space, content is stamped or carved into it, and the // space turfs bordering that content light themselves through enable_starlight(). @@ -259,48 +257,6 @@ SUBSYSTEM_DEF(mapping) // VOIDCREW EDIT ADDITION: only once the drain is idle, and rate limited inside. reconcile_used_turfs() -/** - * VOIDCREW ADDITION: takes the turfs darkened by the reservation drain out of - * GLOB.starlight, in one linear pass over the list rather than one linear scan per turf. - * - * `GLOB.starlight -= turf` inside the drain loop is the obvious spelling and it is - * quadratic: the loop runs once per released turf and the list can hold as many entries - * again, which on a large release is a multi-second world freeze. Rebuilding the list once - * against an assoc membership set is O(len(GLOB.starlight)) no matter how many turfs were - * released, and the drain only pays it once per REBUILD_STARLIGHT_AFTER turfs plus once at - * the end of each fire. - * - * Leaving the entries in place instead is not an option: enable_starlight() only appends - * when `!light_on`, so a member whose light we switched off would be appended a SECOND - * time the next time that ground is lit, and BYOND's Remove() only ever drops one of them. - * That trades a bounded datum leak for an unbounded list leak. - * - * A turf that was re-lit between being queued and being flushed is kept: the queue is a - * request to drop the entry, `light_on` is the ground truth about whether it still belongs. - */ -/// Turfs the reservation drain may darken before the GLOB.starlight compaction is worth a pass. -#define REBUILD_STARLIGHT_AFTER 1000 - -/datum/controller/subsystem/mapping/proc/release_reservation_starlight(force = FALSE) - var/list/released = starlight_release_queue - if(!length(released)) - return - if(!force && length(released) < REBUILD_STARLIGHT_AFTER) - return - starlight_release_queue = null - - var/list/kept = list() - for(var/turf/open/space/lit as anything in GLOB.starlight) - // `as anything`, so this also drops the nulls a hard delete leaves in place and - // anything a raw turf swap retargeted into something that is no longer space. - if(isnull(lit)) - continue - if(released[lit] && !lit.light_on) - continue - kept += lit - GLOB.starlight = kept - -#undef REBUILD_STARLIGHT_AFTER /datum/controller/subsystem/mapping/proc/calculate_default_z_level_gravities() for(var/z_level in 1 to length(z_list)) @@ -679,8 +635,10 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away // nothing. An away mission is a deliberate admin act, so this asks rather than refuses - // but the cost is permanent, BYOND never frees a z-level. See effective_z_ceiling(). if(!SSmapping.z_headroom(1)) + // VOIDCREW EDIT START: Enforce and log the permanent z-level capacity budget for live mapping (voidcrew/mapping/_mapping.dm). if(tgui_alert(user, "world.maxz is [world.maxz], at the effective ceiling of [SSmapping.effective_z_ceiling()] (configured [CONFIG_GET(number/max_z_levels)], scaled for [length(GLOB.clients)] clients). An away mission mints another z-level and BYOND never frees one - that is roughly 120 MB of address space gone for the rest of the round, on top of a server that is already at its budget. Load anyway?", "Z ceiling", list("Load anyway", "Cancel")) != "Load anyway") return + // VOIDCREW EDIT END var/list/possible_options = GLOB.potentialRandomZlevels + "Custom" var/away_name @@ -718,6 +676,7 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away /// VOIDCREW EDIT: `mint_reason` is passed through to add_new_zlevel() for the per-mint log line. /datum/controller/subsystem/mapping/proc/add_reservation_zlevel(for_shuttles, mint_reason = null) num_of_res_levels++ + // VOIDCREW EDIT: Enforce and log the permanent z-level capacity budget for live mapping (voidcrew/mapping/_mapping.dm). return add_new_zlevel("Transit/Reserved #[num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE), mint_reason = mint_reason) /// Requests a /datum/turf_reservation based on the given width, height, and z_size. You can specify a z_reservation to use a specific z level, or leave it null to use any z level. @@ -814,11 +773,13 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away ) // Assoc keyed by turf, so reservations can hand turfs back with a keyed update // instead of a linear scan (see the unused_turfs declaration) + // VOIDCREW EDIT: Use turf-keyed reservation membership so handing back large sites avoids quadratic list scans. var/list/reservable_turfs = list() for(var/turf/T as anything in reserved_block) // No need to empty() these, because they just got created and are already /turf/open/space/basic. T.turf_flags = UNUSED_RESERVATION_TURF T.blocks_air = TRUE + // VOIDCREW EDIT: Use turf-keyed reservation membership so handing back large sites avoids quadratic list scans. reservable_turfs[T] = TRUE CHECK_TICK @@ -826,6 +787,7 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away if(SSatoms.initialized) SSatoms.InitializeAtoms(Z_TURFS(z)) + // VOIDCREW EDIT: Use turf-keyed reservation membership so handing back large sites avoids quadratic list scans. unused_turfs["[z]"] = reservable_turfs reservation_ready["[z]"] = TRUE clearing_reserved_turfs = FALSE @@ -838,62 +800,6 @@ ADMIN_VERB(load_away_mission, R_FUN, "Load Away Mission", "Load a specific away if(await) UNTIL(!length(turfs)) -// VOIDCREW ADDITION: how often the used_turfs orphan sweep below may run. -#define USED_TURF_RECONCILE_INTERVAL (2 MINUTES) -// VOIDCREW ADDITION: how many orphans one sweep may hand back, so a pathological -// backlog is drained over several passes instead of in one unbounded release. -#define USED_TURF_RECONCILE_MAX_RECLAIM 5000 - -/** - * VOIDCREW ADDITION: self-healing sweep for SSmapping.used_turfs. - * - * used_turfs maps turf -> the /datum/turf_reservation that claimed it, and the only thing - * that ever removes an entry is that reservation's Release(). An entry whose reservation - * is gone is therefore ground that is claimed forever: it keeps RESERVATION_TURF, never - * goes back into unused_turfs, and _reserve_area() will never hand it out again. Enough of - * those and request_turf_block_reservation() cannot fit a block on any existing reservation - * z-level and mints a permanent new 255x255 one (~65k turfs, ~48 MB) per shortfall. - * - * Release() is the fix for the known way that happened (see the note there); this is the - * net for any path that is still missed, and it also cleans up entries stranded before this - * code existed. It is deliberately narrow: an entry is only dropped when nothing live owns - * it - a null value (the reservation hard deleted, which nulls the ref in place) or a - * QDELETED one. A reservation that still exists is never touched, so this cannot race a - * live claim, and turfs claimed but not yet published are impossible because _reserve_area() - * writes used_turfs[T] and the datum ref in the same unyielding pass. - * - * O(length(used_turfs)) with no sleeps, capped and rate limited. - */ -/datum/controller/subsystem/mapping/proc/reconcile_used_turfs() - if(!initialized || clearing_reserved_turfs) - return - if(world.time < next_used_turf_reconcile) - return - next_used_turf_reconcile = world.time + USED_TURF_RECONCILE_INTERVAL - - var/list/orphans = list() - // `as anything` - a hard delete can null a key in place, and those are skipped rather - // than reclaimed: there is no turf left to hand back. - for(var/turf/claimed as anything in used_turfs) - if(isnull(claimed)) - continue - var/datum/turf_reservation/holder = used_turfs[claimed] - if(!QDELETED(holder)) - continue - orphans += claimed - if(length(orphans) >= USED_TURF_RECONCILE_MAX_RECLAIM) - break - - if(!length(orphans)) - return - - used_turfs -= orphans - log_mapping("SSmapping: reconciled [length(orphans)] used_turfs entr[length(orphans) == 1 ? "y" : "ies"] whose \ - reservation no longer exists - the ground was claimed with nothing left to release it. Handing it back.") - reserve_turfs(orphans) - -#undef USED_TURF_RECONCILE_INTERVAL -#undef USED_TURF_RECONCILE_MAX_RECLAIM //DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations(). /datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations() diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm index 5b63d1876b8..3ca4bbe9597 100644 --- a/code/controllers/subsystem/minor_mapping.dm +++ b/code/controllers/subsystem/minor_mapping.dm @@ -78,7 +78,7 @@ SUBSYSTEM_DEF(minor_mapping) for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) all_turfs += Z_TURFS(z) for(var/turf/open/floor/plating/T in all_turfs) - // VOIDCREW EDIT ADDITION: is_station_level() means "any z with a hull on it", so + // VOIDCREW EDIT ADDITION START: is_station_level() means "any z with a hull on it", so // this sweep reaches every co-tenant of every occupied encounter level - mice would // spawn inside a site whose crew has not arrived, on top of the fauna budget. Also a // CHECK_TICK: the loop accumulates every station level's turfs and walks the lot in diff --git a/code/controllers/subsystem/networks/research.dm b/code/controllers/subsystem/networks/research.dm index 0e030dec18a..54cd9b0e2f0 100644 --- a/code/controllers/subsystem/networks/research.dm +++ b/code/controllers/subsystem/networks/research.dm @@ -94,6 +94,7 @@ SUBSYSTEM_DEF(research) // console's enqueue buttons were live but the nodes were silently never researched. // Income generation stays gated exactly as before; the queue now runs for every web. if(techweb_list.should_generate_points) + // VOIDCREW EDIT START: Process ship techweb research queues even when passive point generation is disabled (voidcrew/modules/research). var/list/bitcoins = list() for(var/obj/machinery/rnd/server/miner as anything in techweb_list.techweb_servers) if(miner.working) @@ -108,6 +109,7 @@ SUBSYSTEM_DEF(research) techweb_list.add_point_list(bitcoins) techweb_list.last_income = world.time + // VOIDCREW EDIT END if(length(techweb_list.research_queue_nodes)) techweb_list.research_node_id(techweb_list.research_queue_nodes[1]) // Attempt to research the first node in queue if possible diff --git a/code/controllers/subsystem/pathfinder.dm b/code/controllers/subsystem/pathfinder.dm index fe45ddb41e9..2771e71eaa4 100644 --- a/code/controllers/subsystem/pathfinder.dm +++ b/code/controllers/subsystem/pathfinder.dm @@ -30,8 +30,10 @@ SUBSYSTEM_DEF(pathfinder) // round whether or not anything asked it for a path. With both queues empty every line // below this is a no-op, but the two list copies (one of them a deep_copy_list) still // get paid ~78k times a round. Bail before allocating anything. + // VOIDCREW EDIT START: Avoid copying empty pathfinding queues on every fleet tick. if(!length(active_pathing) && !length(source_to_maps)) return + // VOIDCREW EDIT END src.currentrun = active_pathing.Copy() src.currentmaps = deep_copy_list(source_to_maps) diff --git a/code/controllers/subsystem/radiation.dm b/code/controllers/subsystem/radiation.dm index de85a5759e2..23e33ee2fcc 100644 --- a/code/controllers/subsystem/radiation.dm +++ b/code/controllers/subsystem/radiation.dm @@ -16,6 +16,7 @@ SUBSYSTEM_DEF(radiation) // A null source_ref must be dropped, not runtimed on: a runtime aborts fire() // before the Cut(), so the same entry would wedge the whole queue forever. var/datum/weakref/source_ref = pulse_information.source_ref + // VOIDCREW EDIT: Tolerate a radiation source deleted before the pulse resolves its weak reference. var/atom/source = source_ref?.resolve() if (isnull(source)) processing.Cut(1, 2) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 9875f2c42b7..c367aa9ff15 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -169,13 +169,6 @@ SUBSYSTEM_DEF(shuttle) /// Did the supermatter start a cascade event? var/supermatter_cascade = FALSE - //VOID EDIT - Modular ship configuration for shuttle manipulator - /// Pending upgrade module selections (slot_key -> module_id) for shuttle manipulator - var/list/pending_upgrade_selections = list() - /// Pending theme selection (theme_id) for shuttle manipulator - var/pending_theme_id - //END VOID EDIT - /// List of express consoles that are waiting for pack initialization var/list/obj/machinery/computer/cargo/express/express_consoles = list() @@ -959,11 +952,13 @@ SUBSYSTEM_DEF(shuttle) L["description"] = S.description L["admin_notes"] = S.admin_notes //VOID EDIT - Check if this is a modular voidcrew ship + // VOIDCREW EDIT START: Integrate serialized live template loads and modular ship selections (voidcrew/modules/ship_upgrades/shuttle_manipulator.dm). L["is_modular"] = FALSE if(istype(S, /datum/map_template/shuttle/voidcrew)) var/datum/map_template/shuttle/voidcrew/VC = S if(VC.has_upgrade_slots) L["is_modular"] = TRUE + // VOIDCREW EDIT END //END VOID EDIT if(selected == S) @@ -1002,11 +997,13 @@ SUBSYSTEM_DEF(shuttle) data["shuttles"] += list(L) //VOID EDIT - Add modular ship data if selected template is modular + // VOIDCREW EDIT START: Integrate serialized live template loads and modular ship selections (voidcrew/modules/ship_upgrades/shuttle_manipulator.dm). data["modular_data"] = null if(selected && istype(selected, /datum/map_template/shuttle/voidcrew)) var/datum/map_template/shuttle/voidcrew/VC = selected if(VC.has_upgrade_slots) data["modular_data"] = build_modular_ui_data(VC) + // VOIDCREW EDIT END //END VOID EDIT return data @@ -1137,11 +1134,13 @@ SUBSYSTEM_DEF(shuttle) //if(preview_shuttle && (loading_template != preview_template)) if(S && !shuttle_loading) . = TRUE + // VOIDCREW EDIT REMOVAL: The serialized template-load owner now holds the load lock (voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm). unload_preview() load_template(S) if(preview_shuttle) preview_template = S user.forceMove(get_turf(preview_shuttle)) +// VOIDCREW EDIT REMOVAL: The serialized template-load owner now holds the load lock (voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm). if("replace") if(existing_shuttle == backup_shuttle) @@ -1151,6 +1150,7 @@ SUBSYSTEM_DEF(shuttle) intact for round sanity.") else if(S && !shuttle_loading) . = TRUE + // VOIDCREW EDIT REMOVAL: The serialized template-load owner now holds the load lock (voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm). // If successful, returns the mobile docking port var/obj/docking_port/mobile/mdp = action_load(S, replace = TRUE) if(mdp) @@ -1158,6 +1158,7 @@ SUBSYSTEM_DEF(shuttle) message_admins("[key_name_admin(usr)] load/replaced [mdp] with the shuttle manipulator.") log_admin("[key_name(usr)] load/replaced [mdp] with the shuttle manipulator.
") SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]") + // VOIDCREW EDIT REMOVAL: The serialized template-load owner now holds the load lock (voidcrew/modules/overmap/code/controllers/subsystem/shuttle.dm). if(emergency == mdp) //you just changed the emergency shuttle, there are events in game + captains that can change your snowflake choice. var/set_purchase = tgui_alert(usr, "Do you want to also disable shuttle purchases/random events that would change the shuttle?", "Butthurt Admin Prevention", list("Yes, disable purchases/events", "No, I want to possibly get owned")) if(set_purchase == "Yes, disable purchases/events") @@ -1175,99 +1176,6 @@ SUBSYSTEM_DEF(shuttle) return has_purchase_shuttle_access //VOID EDIT - Helper proc for building modular ship UI data -/** - * Build UI data for modular ship configuration in shuttle manipulator - * - * Returns a list with: - * - themes: list of available themes with id, name, desc, is_default, jobs - * - has_themes: boolean if there are themes to choose from - * - slots: list of upgrade slots with their available modules - * - selected_theme: currently selected theme id (from pending_theme_id) - * - selected_upgrades: currently selected modules (from pending_upgrade_selections) - */ -/datum/controller/subsystem/shuttle/proc/build_modular_ui_data(datum/map_template/shuttle/voidcrew/template) - ensure_ship_upgrades_initialized() - - var/list/data = list() - - // Get themes for this ship - var/list/ship_themes = get_themes_for_ship(template.type) - var/list/themes_data = list() - - for(var/theme_id in ship_themes) - var/datum/ship_theme/theme = ship_themes[theme_id] - var/list/theme_info = list() - theme_info["id"] = theme.id - theme_info["name"] = theme.name - theme_info["desc"] = theme.desc - theme_info["is_default"] = theme.is_default - - // Include job slots for preview - if(theme.job_slots) - var/list/jobs = list() - for(var/list/job_data in theme.job_slots) - jobs += list(list( - "name" = job_data["name"], - "slots" = job_data["slots"], - "officer" = job_data["officer"] - )) - theme_info["jobs"] = jobs - - themes_data += list(theme_info) - - data["themes"] = themes_data - data["has_themes"] = length(themes_data) > 0 - - // Determine selected theme - use pending selection or find default - var/effective_theme_id = pending_theme_id - if(!effective_theme_id && length(themes_data)) - var/datum/ship_theme/default_theme = get_default_theme_for_ship(template.type) - if(default_theme) - effective_theme_id = default_theme.id - - data["selected_theme"] = effective_theme_id - - // Get upgrade slots - from theme if selected, otherwise from template - var/list/upgrade_slot_ids = template.upgrade_slot_ids - if(effective_theme_id) - var/datum/ship_theme/selected_theme = ship_themes[effective_theme_id] - if(selected_theme?.upgrade_slot_ids) - upgrade_slot_ids = selected_theme.upgrade_slot_ids - - // Get modules filtered by theme - var/list/all_modules = get_modules_for_ship_theme(template.type, effective_theme_id) - - // Organize modules by slot - var/list/slots_data = list() - for(var/slot_key in upgrade_slot_ids) - var/list/slot_info = list() - slot_info["key"] = slot_key - // Generate display name from slot key (capitalize, replace underscores) - slot_info["display_name"] = capitalize(replacetext(slot_key, "_", " ")) - - var/list/slot_modules = list() - for(var/module_id in all_modules) - var/datum/ship_upgrade_module/module = all_modules[module_id] - if(module.slot != slot_key) - continue - - var/list/module_info = list() - module_info["id"] = module.id - module_info["name"] = module.name - module_info["desc"] = module.desc - module_info["is_default"] = module.is_default - - slot_modules += list(module_info) - - slot_info["modules"] = slot_modules - slots_data += list(slot_info) - - data["slots"] = slots_data - - // Include current pending selections - data["selected_upgrades"] = pending_upgrade_selections.Copy() - - return data //END VOID EDIT #undef MAX_TRANSIT_REQUEST_RETRIES diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 53992b2102b..6fd6b874937 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -42,6 +42,7 @@ SUBSYSTEM_DEF(statpanels) "Round Time: [ROUND_TIME()]", "Station Time: [station_time_timestamp()]", "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)", + // VOIDCREW EDIT: Show connected fleet population in the stat panel. "Connected Players: [length(GLOB.clients)]", ) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index f5a6c704c72..27a5cf0fc56 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -161,10 +161,12 @@ SUBSYSTEM_DEF(ticker) for(var/client/C in GLOB.clients) window_flash(C, ignorepref = TRUE) //let them know lobby has opened up. to_chat(world, span_notice("Welcome to [station_name()]!")) + // VOIDCREW EDIT START: Include the configured Discord round-alert role (voidcrew/controllers/configuration/new_round_alert.dm). var/new_round_alert_role = CONFIG_GET(string/new_round_alert_role_id) var/new_round_message = "[new_round_alert_role ? "<@&[new_round_alert_role]> " : ""]New round starting on [SSmapping.current_map.map_name]!" for(var/channel_tag in CONFIG_GET(str_list/channel_announce_new_game)) send2chat(new /datum/tgs_message_content(new_round_message), channel_tag) + // VOIDCREW EDIT END current_state = GAME_STATE_PREGAME SEND_SIGNAL(src, COMSIG_TICKER_ENTER_PREGAME) @@ -585,9 +587,11 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/transfer_characters() var/list/livings = list() for(var/mob/dead/new_player/player as anything in GLOB.new_player_list) + // VOIDCREW EDIT START: Notify Voidcrew crew integrations after a player character transfers into its living body. var/mob/living/living = player.transfer_character() if(living) SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CREWMEMBER_JOINED, living, living.mind.assigned_role.title) + // VOIDCREW EDIT END qdel(player) ADD_TRAIT(living, TRAIT_NO_TRANSFORM, SS_TICKER_TRAIT) if(living.client) diff --git a/code/controllers/subsystem/tts.dm b/code/controllers/subsystem/tts.dm index e78c08f24e3..d7bcff51b8c 100644 --- a/code/controllers/subsystem/tts.dm +++ b/code/controllers/subsystem/tts.dm @@ -83,6 +83,7 @@ SUBSYSTEM_DEF(tts) var/datum/http_response/response_pitch = request_pitch.into_response() if(response_pitch.errored || response_pitch.status_code != 200) if(response_pitch.errored) + // VOIDCREW EDIT: Report the pitch request failure from its own response, rather than the completed TTS response. stack_trace(response_pitch.error) pitch_enabled = FALSE rustg_file_write(json_encode(available_speakers), "data/cached_tts_voices.json") diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm index 4d5ec5f1668..ffd151171cc 100644 --- a/code/controllers/subsystem/weather.dm +++ b/code/controllers/subsystem/weather.dm @@ -10,12 +10,13 @@ SUBSYSTEM_DEF(weather) var/list/processing = list() // VOIDCREW EDIT REMOVAL START - the four "[z]"-keyed scheduler maps (eligible_zlevels, // weather_types_by_zlevel, next_hit_by_zlevel, random_weather_by_zlevel) are replaced by - // the /datum/weather_site registry below, so several places can share a z-level and each + // the registry in voidcrew/edits/controllers/subsystem/weather.dm, so several places can share a z-level and each // keep its own climate, storm and cooldown. See voidcrew/datums/weather_site.dm. // VOIDCREW EDIT REMOVAL END /datum/controller/subsystem/weather/fire(resumed = FALSE) // process active weather + // VOIDCREW EDIT START: Schedule storms per site and resume bounded weather work across ticks (voidcrew/edits/controllers/subsystem/weather.dm). if(!resumed) currentrun = processing.Copy() var/list/currentrun_cache = currentrun @@ -24,12 +25,14 @@ SUBSYSTEM_DEF(weather) if(QDELETED(weather_event) || !(weather_event in processing) || !length(weather_event.subsystem_tasks) || weather_event.stage != MAIN_STAGE) currentrun_cache.len-- resumed = FALSE + // VOIDCREW EDIT END continue if(weather_event.subsystem_tasks[weather_event.task_index] == SSWEATHER_MOBS) if(!resumed) // Only collect mobs on the impacted z-levels, the whole world's mob list gets very large with populated planets. // The z index is built once per fire cycle and shared by every storm processing this fire. + // VOIDCREW EDIT START: Schedule storms per site and resume bounded weather work across ticks (voidcrew/edits/controllers/subsystem/weather.dm). if(mobs_by_z_cache_fire != times_fired) mobs_by_z_cache = list() mobs_by_z_cache_fire = times_fired @@ -56,6 +59,7 @@ SUBSYSTEM_DEF(weather) if(z_mobs) eligible_mobs += z_mobs weather_event.current_mobs = eligible_mobs + // VOIDCREW EDIT END var/list/current_mobs_cache = weather_event.current_mobs // cache for performance while(current_mobs_cache.len) var/mob/living/target = current_mobs_cache[current_mobs_cache.len] @@ -97,8 +101,10 @@ SUBSYSTEM_DEF(weather) // Do not remove an event before all of its tasks complete. If MC_TICK_CHECK // returns above, this remains the last entry and the next fire resumes it. + // VOIDCREW EDIT START: Schedule storms per site and resume bounded weather work across ticks (voidcrew/edits/controllers/subsystem/weather.dm). currentrun_cache.len-- resumed = FALSE + // VOIDCREW EDIT END // VOIDCREW EDIT REPLACEMENT START - random weather is scheduled per site, not per z-level. // One storm per SITE replaces the old one-storm-per-z rule, so two sites sharing a @@ -186,11 +192,13 @@ SUBSYSTEM_DEF(weather) var/datum/weather/W = new weather_datum_type(z_levels, weather_data, site) // VOIDCREW EDIT - pass the scheduling site through W.telegraph() + // VOIDCREW EDIT: Schedule storms per site and resume bounded weather work across ticks (voidcrew/edits/controllers/subsystem/weather.dm). return W // VOIDCREW EDIT ADDITION START - the cooldown callback is per site now. /// VOIDCREW EDIT: kept for z-level-minded callers; addresses the level's own site. /datum/controller/subsystem/weather/proc/make_eligible(z) + // VOIDCREW EDIT: Schedule storms per site and resume bounded weather work across ticks (voidcrew/edits/controllers/subsystem/weather.dm). make_site_eligible(get_level_weather_site(z)) // VOIDCREW EDIT ADDITION END diff --git a/code/datums/actions/mobs/charge.dm b/code/datums/actions/mobs/charge.dm index 10df06a0128..65f65c172f7 100644 --- a/code/datums/actions/mobs/charge.dm +++ b/code/datums/actions/mobs/charge.dm @@ -41,12 +41,14 @@ restore_charge_actions() // VOIDCREW EDIT END StartCooldown() + // VOIDCREW EDIT REMOVAL: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return TRUE /datum/action/cooldown/mob_cooldown/charge/proc/charge_sequence(atom/movable/charger, atom/target_atom, delay, past) do_charge(charger, target_atom, delay, past) // VOIDCREW EDIT - retain the caller's charge snapshot. /datum/action/cooldown/mob_cooldown/charge/proc/do_charge(atom/movable/charger, atom/target_atom, delay, past) + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). if(QDELETED(src) || QDELETED(owner) || QDELETED(charger) || QDELETED(target_atom) || target_atom == charger) return var/chargeturf = get_turf(target_atom) @@ -62,6 +64,7 @@ finish_charge(charger, notify_owner = FALSE) // VOIDCREW EDIT - only cancel our own loop. var/charge_id = ++charge_serial // VOIDCREW EDIT - invalidate sleeping replaced invocations. + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). charging[charger] = charge_id actively_moving = FALSE // VOIDCREW EDIT BEGIN - a start listener may synchronously remove or transfer us. @@ -79,6 +82,7 @@ RegisterSignal(charger, COMSIG_LIVING_DEATH, PROC_REF(charge_end), override = TRUE) // VOIDCREW EDIT - the owner's existing clear_ref handler invokes Remove; preserve it. if(charger != owner) + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). RegisterSignal(charger, COMSIG_QDELETING, PROC_REF(charge_end), override = TRUE) charger.setDir(dir) do_charge_indicator(charger, target) @@ -135,6 +139,7 @@ if(istype(source, /datum/move_loop)) var/datum/move_loop/move_loop_source = source charger = move_loop_source.moving + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). finish_charge(charger) /datum/action/cooldown/mob_cooldown/charge/update_status_on_signal(mob/source, new_stat, old_stat) @@ -293,8 +298,10 @@ /datum/action/cooldown/mob_cooldown/charge/triple_charge/charge_sequence(atom/movable/charger, atom/target_atom, delay, past) for(var/i in 0 to 2) if(QDELETED(src) || owner != charger) // VOIDCREW EDIT - cancellation ends the whole sequence. + // VOIDCREW EDIT START: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return do_charge(charger, target_atom, charge_delay - 2 * i, charge_past) + // VOIDCREW EDIT END /datum/action/cooldown/mob_cooldown/charge/hallucination_charge name = "Hallucination Charge" @@ -316,50 +323,62 @@ return for(var/i in 0 to 2) if(QDELETED(src) || owner != charger) // VOIDCREW EDIT + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return hallucination_charge(target_atom, 4, 9 - 2 * i, 0, 4, TRUE) for(var/i in 0 to 2) if(QDELETED(src) || owner != charger) // VOIDCREW EDIT + // VOIDCREW EDIT START: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return do_charge(charger, target_atom, charge_delay - 2 * i, charge_past) + // VOIDCREW EDIT END /datum/action/cooldown/mob_cooldown/charge/hallucination_charge/do_charge(atom/movable/charger, atom/target_atom, delay, past) var/disposable_clone = charger != owner // VOIDCREW EDIT - owner may change while the parent sleeps. . = ..() + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). if(disposable_clone) qdel(charger) /datum/action/cooldown/mob_cooldown/charge/hallucination_charge/proc/hallucination_charge(atom/target_atom, clone_amount, delay, past, radius, use_self) var/mob/caster = owner // VOIDCREW EDIT - a synchronous movement/start callback can change owner. var/starting_angle = rand(1, 360) + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). if(!radius || QDELETED(caster) || QDELETED(target_atom)) return var/angle_difference = 360 / clone_amount var/self_placed = FALSE for(var/i = 1 to clone_amount) if(QDELETED(src) || QDELETED(caster) || owner != caster || QDELETED(target_atom)) // VOIDCREW EDIT + // VOIDCREW EDIT: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return var/angle = (starting_angle + angle_difference * i) var/turf/place = locate(target_atom.x + cos(angle) * radius, target_atom.y + sin(angle) * radius, target_atom.z) if(!place) continue if(use_self && !self_placed) + // VOIDCREW EDIT START: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). caster.forceMove(place) if(QDELETED(src) || QDELETED(caster) || owner != caster) // VOIDCREW EDIT return + // VOIDCREW EDIT END self_placed = TRUE continue var/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/our_clone = new /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination(place) + // VOIDCREW EDIT START: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). our_clone.appearance = caster.appearance our_clone.name = "[caster]'s hallucination" our_clone.alpha = 127.5 our_clone.move_through_mob = caster + // VOIDCREW EDIT END our_clone.spawn_blood = spawn_blood INVOKE_ASYNC(src, PROC_REF(do_charge), our_clone, target_atom, delay, past) if(QDELETED(src) || QDELETED(caster) || owner != caster) // VOIDCREW EDIT + // VOIDCREW EDIT START: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return if(use_self) do_charge(caster, target_atom, delay, past) + // VOIDCREW EDIT END /datum/action/cooldown/mob_cooldown/charge/hallucination_charge/hit_target(atom/movable/source, atom/A, damage_dealt) var/applied_damage = charge_damage @@ -378,6 +397,8 @@ /datum/action/cooldown/mob_cooldown/charge/hallucination_charge/hallucination_surround/charge_sequence(atom/movable/charger, atom/target_atom, delay, past) for(var/i in 0 to 4) if(QDELETED(src) || owner != charger) // VOIDCREW EDIT + // VOIDCREW EDIT START: Keep charge ownership and cleanup valid across cancellation and yields (voidcrew/edits/datums/actions/mobs/charge.dm). return hallucination_charge(target_atom, 2, 8, 2, 2, FALSE) do_charge(charger, target_atom, charge_delay, charge_past) + // VOIDCREW EDIT END diff --git a/code/datums/alarm.dm b/code/datums/alarm.dm index 6c39b2d5d2a..7bf555fecc0 100644 --- a/code/datums/alarm.dm +++ b/code/datums/alarm.dm @@ -127,7 +127,7 @@ if(allowed_z_levels && !(source_z in allowed_z_levels)) return - // VOIDCREW EDIT ADDITION: packed-level containment. Resolved live rather than + // VOIDCREW EDIT ADDITION START: packed-level containment. Resolved live rather than // snapshotted - a ship-mounted console changes z constantly, and its site with it. var/atom/region_anchor = region_anchor_ref?.resolve() if(region_anchor) diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index 6b9379f909c..556a7a1e8ff 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -303,8 +303,10 @@ GLOBAL_LIST_EMPTY(chasm_fallen_mobs) // Keyed by REF rather than by the region datum: GLOB.chasm_fallen_mobs holds these // forever, and a datum key would be a hard-delete blocker on every torn-down site. var/datum/region = map_region_for_turf(turf) + // VOIDCREW EDIT START: Keep chasm victims grouped by site when several encounters share a z-level (voidcrew/datums/map_footprint.dm). if(region) return "site-[REF(region)]-[z_level]" + // VOIDCREW EDIT END if(is_away_level(z_level)) return ZTRAIT_AWAY diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm index 168678d3434..912c6a602f1 100644 --- a/code/datums/components/crafting/crafting.dm +++ b/code/datums/components/crafting/crafting.dm @@ -420,8 +420,10 @@ if (recipe.category == CAT_CULT && !IS_CULTIST(user)) // Skip blood cult recipes if not cultist return FALSE //VOID EDIT - blueprint schematics: only visible while carrying the physical blueprint or holding a round-long neural imprint (voidcrew/modules/weapons_bench/blueprint.dm) + // VOIDCREW EDIT START: Gate schematic crafting on a carried blueprint or imprint (voidcrew/modules/weapons_bench/blueprint.dm). if(istype(recipe, /datum/crafting_recipe/blueprint) && !is_blueprint_recipe_available(recipe, user)) return FALSE + // VOIDCREW EDIT END //VOID EDIT END return TRUE diff --git a/code/datums/components/irradiated.dm b/code/datums/components/irradiated.dm index 5159d2bc1a1..201d5bb3b3c 100644 --- a/code/datums/components/irradiated.dm +++ b/code/datums/components/irradiated.dm @@ -176,11 +176,13 @@ // damage but deals 2 tox per 25 seconds, so an irradiated crewmember outruns // their own liver and the state is effectively permanent without heavy chemical // treatment. Showering is the intended way to come home off a contaminated planet. + // VOIDCREW EDIT START: Let washing remove planetary irradiation from crew as well as items. if (ishuman(parent)) to_chat(parent, span_nicegreen("The water sluices the contamination off your skin.")) qdel(src) return COMPONENT_CLEANED|COMPONENT_CLEANED_GAIN_XP + // VOIDCREW EDIT END // VOIDCREW EDIT END /datum/component/irradiated/proc/on_geiger_counter_scan(datum/source, mob/user, obj/item/geiger_counter/geiger_counter) diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm index 4a35bda8e8a..00c19d92709 100644 --- a/code/datums/components/orbiter.dm +++ b/code/datums/components/orbiter.dm @@ -27,6 +27,7 @@ RegisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(orbiter_glide_size_update)) // Transfer temporarily clears parent; moving an orbiter before reattachment fires its stop signal at null. + // VOIDCREW EDIT: Reattach orbiters before movement signals and tolerate a deleted orbit master. move_react(target) // VOIDCREW EDIT END @@ -39,6 +40,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/component/orbiter/Destroy() var/atom/master = parent + // VOIDCREW EDIT: Reattach orbiters before movement signals and tolerate a deleted orbit master. if(master?.orbiters == src) master.orbiters = null for(var/i in orbiter_list) @@ -63,6 +65,7 @@ orbiter_list += newcomp.orbiter_list newcomp.orbiter_list = null // A transfer into an existing orbit merges here instead of registering a new component. + // VOIDCREW EDIT: Reattach orbiters before movement signals and tolerate a deleted orbit master. move_react(parent) // VOIDCREW EDIT END @@ -70,6 +73,7 @@ /datum/component/orbiter/PostTransfer(datum/new_parent) if(!isatom(new_parent) || isarea(new_parent) || !get_turf(new_parent)) return COMPONENT_INCOMPATIBLE +// VOIDCREW EDIT REMOVAL: Reattach orbiters before movement signals and tolerate a deleted orbit master. // VOIDCREW EDIT END /datum/component/orbiter/proc/begin_orbit(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation) diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index b023a97b214..dc96ee860c7 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -463,6 +463,7 @@ // Our holder can be stale: whatever the parent is inside can move without the parent // itself moving, and only the parent moving re-runs this. Must happen before we set // LIGHTING_ON, or set_holder() applies the light and we then apply it a second time. + // VOIDCREW EDIT: Refresh contained light holders before enabling the overlay (voidcrew/edits/datums/components/overlay_lighting.dm). check_holder() overlay_lighting_flags |= LIGHTING_ON if(current_holder) diff --git a/code/datums/components/singularity.dm b/code/datums/components/singularity.dm index a78547e0f6b..ee15ec6946f 100644 --- a/code/datums/components/singularity.dm +++ b/code/datums/components/singularity.dm @@ -134,8 +134,10 @@ )) /datum/component/singularity/process(seconds_per_tick) + // VOIDCREW EDIT START: Stop singularity hazards at protected trader outpost boundaries (voidcrew/modules/trade/outpost_security.dm). if(neutralize_trader_outpost_hazard(parent)) // VOIDCREW return PROCESS_KILL + // VOIDCREW EDIT END // We want to move and eat once a second, but want to process our turf consume queue the rest of the time time_since_last_eat += seconds_per_tick digest() @@ -160,8 +162,10 @@ /datum/component/singularity/proc/consume(datum/source, atom/thing) SIGNAL_HANDLER - if(is_trader_outpost_protected(parent) || is_trader_outpost_protected(thing) || singularity_spares(thing)) // VOIDCREW EDIT + // VOIDCREW EDIT START: Preserve outpost protection and master's singularity exemptions. + if(is_trader_outpost_protected(parent) || is_trader_outpost_protected(thing) || singularity_spares(thing)) return + // VOIDCREW EDIT END if (thing == parent) stack_trace("Singularity tried to consume itself.") return @@ -209,8 +213,10 @@ for (cached_index in 1 to length(turfs_to_consume)) var/turf/tile = turfs_to_consume[cached_index] + // VOIDCREW EDIT START: Stop singularity hazards at protected trader outpost boundaries (voidcrew/modules/trade/outpost_security.dm). if(is_trader_outpost_protected(tile)) // VOIDCREW: also stop pulling across the boundary. continue + // VOIDCREW EDIT END var/dist_to_tile = get_dist(tile, parent) if(grav_pull < dist_to_tile) //If we've exited the singulo's range already, just skip us @@ -248,8 +254,10 @@ /datum/component/singularity/proc/moved(datum/source, atom/new_location) SIGNAL_HANDLER + // VOIDCREW EDIT START: Stop singularity hazards at protected trader outpost boundaries (voidcrew/modules/trade/outpost_security.dm). if(is_trader_outpost_protected(new_location)) // VOIDCREW: even stage five must respect the boundary. return COMPONENT_MOVABLE_BLOCK_PRE_MOVE + // VOIDCREW EDIT END var/atom/atom_parent = parent var/current_direction = atom_parent.dir @@ -273,8 +281,10 @@ /datum/component/singularity/proc/can_move(turf/to_move) if (!to_move) + // VOIDCREW EDIT START: Stop singularity hazards at protected trader outpost boundaries (voidcrew/modules/trade/outpost_security.dm). return FALSE if(is_trader_outpost_protected(to_move)) // VOIDCREW + // VOIDCREW EDIT END return FALSE for (var/_thing in to_move) diff --git a/code/datums/components/spawner.dm b/code/datums/components/spawner.dm index 8a80a3e7374..4e7d24ebcc8 100644 --- a/code/datums/components/spawner.dm +++ b/code/datums/components/spawner.dm @@ -19,12 +19,6 @@ var/spawn_distance /// Distance from the spawner to exclude mobs from spawning var/spawn_distance_exclude - // VOIDCREW EDIT ADDITION: cached map-tenant footprint for the presence gate in - // try_spawn_mob(). Resolved lazily on the first tick that has anyone on our z-level and - // re-resolved if the parent ever moves (structures do not, but components ride mobs and - // items too). Null means "this level is not shared", which is the common case and the - // one that keeps the plain z-level gate. - // VOIDCREW EDIT ADDITION END COOLDOWN_DECLARE(spawn_delay) /datum/component/spawner/Initialize(spawn_types = list(), spawn_time = 30 SECONDS, max_spawned = 5, max_spawn_per_attempt = 1 , faction = list(FACTION_MINING), spawn_text = null, datum/callback/spawn_callback = null, spawn_distance = 1, spawn_distance_exclude = 0, initial_spawn_delay = 0 SECONDS) @@ -65,7 +59,6 @@ if(!COOLDOWN_FINISHED(src, spawn_delay)) return - // VOIDCREW EDIT START - don't spawn where nobody is standing. // Spawned mobs die unattended out there (vacuum, weather, each other) and // validate_references() frees the slot the instant one is DEAD, so a bone pit or // monster den on a loaded-but-unvisited level emits a fresh corpse every spawn_time @@ -101,7 +94,6 @@ cached_footprint = map_footprint_at_turf(spawner_turf) if(cached_footprint && !footprint_holds_any_client(cached_footprint, clients_here)) return - // END VOIDCREW EDIT validate_references() var/spawned_total = length(spawned_things) @@ -139,6 +131,7 @@ created_mob.faction = src.faction // The assignment above deliberately replaces the mob's initialized faction list, // so restore any native-planet token it received during Initialize(). + // VOIDCREW EDIT: Spawn only near players in the same footprint and preserve native planetary factions (voidcrew/edits/datums/components/spawner.dm). inherit_planetary_faction(created_mob) RegisterSignal(created, COMSIG_MOB_STATCHANGE, PROC_REF(mob_stat_changed)) @@ -151,7 +144,6 @@ spawner.visible_message(span_danger("A creature [spawn_text] [spawner].")) - /// Remove weakrefs to atoms which have been killed or deleted without us picking it up somehow // VOIDCREW EDIT END /datum/component/spawner/proc/validate_references() diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm index def01fd5f5d..9c52edc2592 100644 --- a/code/datums/components/tether.dm +++ b/code/datums/components/tether.dm @@ -19,8 +19,6 @@ var/tether_trait_source /// If TRUE, only add TRAIT_TETHER_ATTACHED to our parent var/no_target_trait - /// Prevents infinite recursion when pulling the anchor - var/currently_pulling = FALSE /datum/component/tether/Initialize(atom/tether_target, max_dist = 7, tether_name, atom/embed_target = null, start_distance = null, \ parent_module = null, tether_trait_source = null, no_target_trait = FALSE) @@ -86,8 +84,10 @@ SIGNAL_HANDLER // Prevent infinite recursion when pulling the anchor causes their tether check to pull us back + // VOIDCREW EDIT START: Guard mutual tether pulls against recursive movement (voidcrew/edits/components/tether_pulling.dm). if (currently_pulling) return + // VOIDCREW EDIT END if (check_snap()) return @@ -100,10 +100,12 @@ var/atom/movable/movable_source = source var/atom/movable/anchor = (source == tether_target ? parent : tether_target) if (get_dist(anchor, new_loc) > cur_dist) + // VOIDCREW EDIT START: Guard mutual tether pulls against recursive movement (voidcrew/edits/components/tether_pulling.dm). currently_pulling = TRUE var/pull_success = istype(anchor) && !anchor.anchored && anchor.move_resist <= movable_source.move_force && anchor.Move(get_step_towards(anchor, new_loc)) currently_pulling = FALSE if (!pull_success) + // VOIDCREW EDIT END to_chat(source, span_warning("[tether_name] runs out of slack and prevents you from moving!")) return COMPONENT_MOVABLE_BLOCK_PRE_MOVE diff --git a/code/datums/elements/decals/_decal.dm b/code/datums/elements/decals/_decal.dm index 6f2a9a0e76a..3cd5db3bd42 100644 --- a/code/datums/elements/decals/_decal.dm +++ b/code/datums/elements/decals/_decal.dm @@ -76,6 +76,7 @@ smoothing = _smoothing RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(apply_overlay), TRUE) + // VOIDCREW EDIT: Expose attached decals while preserving remaining decal rotation listeners (voidcrew/edits/datums/elements/decals/_decal.dm). RegisterSignal(target, COMSIG_ATOM_GET_DECALS, PROC_REF(collect_decals), TRUE) if(target.flags_1 & INITIALIZED_1) target.update_appearance(UPDATE_OVERLAYS) //could use some queuing here now maybe. diff --git a/code/datums/elements/turf_transparency.dm b/code/datums/elements/turf_transparency.dm index 6ff5c9f971f..e3c144cb991 100644 --- a/code/datums/elements/turf_transparency.dm +++ b/code/datums/elements/turf_transparency.dm @@ -262,7 +262,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z) ///Called when there is no real turf below this turf /datum/element/turf_z_transparency/proc/get_baseturf_underlay(turf/our_turf) - // VOIDCREW EDIT: the map FOOTPRINT under the turf answers before the z-level, the same + // VOIDCREW EDIT START: the map FOOTPRINT under the turf answers before the z-level, the same // order /turf/ChangeTurf uses (voidcrew/edits/turf.dm). A level holds up to four planets // of different biomes and ZTRAIT_BASETURF is one value per level; without this the // open-space underlay drawn under a hole on one packed planet is painted with the @@ -278,6 +278,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z) // VOIDCREW EDIT: PLANE_SPACE is multiplied by parallax. Planetary ground must // render with the floors, below glass and plating, or the sky shows through it. var/is_space = ispath(path, /turf/open/space) + // VOIDCREW EDIT START: Use the tenant baseturf and render planetary underlays on the floor plane (voidcrew/datums/map_footprint.dm). var/mutable_appearance/underlay_appearance = mutable_appearance( initial(path.icon), initial(path.icon_state), @@ -285,6 +286,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z) offset_spokesman = our_turf, plane = is_space ? PLANE_SPACE : FLOOR_PLANE, ) + // VOIDCREW EDIT END underlay_appearance.appearance_flags = RESET_ALPHA | RESET_COLOR return underlay_appearance diff --git a/code/datums/elements/weather_listener.dm b/code/datums/elements/weather_listener.dm index 62c3c28c6e4..4b598844ac7 100644 --- a/code/datums/elements/weather_listener.dm +++ b/code/datums/elements/weather_listener.dm @@ -15,6 +15,7 @@ . = ..() if(!weather_type) weather_type = w_type + // VOIDCREW EDIT: Give each weather listener its own signal list for concurrent site storms. sound_change_signals = list() for(var/type in typesof(weather_type)) sound_change_signals += list( diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 30e8d6c95b4..06daeda1101 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -211,7 +211,7 @@ for(var/turf/T as anything in RANGE_TURFS(precision,center)) if(T.is_transition_turf()) continue // Avoid picking these. - // VOIDCREW EDIT ADDITION: never offer the world border as a landing spot. Upstream + // VOIDCREW EDIT ADDITION START: never offer the world border as a landing spot. Upstream // only ever reaches cordon through /area/misc/cordon, which the NOTELEPORT test // below catches; packed lattice levels paint their band with a raw turf swap that // leaves the AREA alone (place_cordon_turf() in voidcrew/datums/map_zones.dm), so @@ -247,7 +247,7 @@ if(HAS_TRAIT(teleported_atom, TRAIT_NO_TELEPORT)) return FALSE - // VOIDCREW EDIT ADDITION: never land anybody inside the world border. + // VOIDCREW EDIT ADDITION START: never land anybody inside the world border. // // /turf/cordon is dense, opaque, airless and indestructible - ScrapeAway() returns // itself, Melt() no-ops, explosions and acid do nothing - so a mob that arrives inside @@ -283,7 +283,7 @@ && SSmapping.get_reservation_from_turf(destination_turf) != SSmapping.get_reservation_from_turf(get_turf(original_destination))) return FALSE - // VOIDCREW EDIT ADDITION: the same containment, on the slot lattice. + // VOIDCREW EDIT ADDITION START: the same containment, on the slot lattice. // The reserved-level test above was the ONLY thing keeping an imprecise teleport inside // the site it aimed at, and it only ever worked because ruins and asteroid fields lived // on ZTRAIT_RESERVED levels. Packed sites do not - lattice levels are minted @@ -314,7 +314,7 @@ if(((origin_area.area_flags & LOCAL_TELEPORT) || (destination_area.area_flags & LOCAL_TELEPORT)) && destination_area != origin_area) return FALSE - // VOIDCREW EDIT ADDITION: bitrunning containment. The LOCAL_TELEPORT check above + // VOIDCREW EDIT ADDITION START: bitrunning containment. The LOCAL_TELEPORT check above // only covers tiles a domain template painted an area onto - the untouched floor of // the reservation is plain /area/space, which has no such flag. A quantum pad built // on one of those tiles teleports real loot out of VR and past the byteforge, which diff --git a/code/datums/mapgen/CaveGenerator.dm b/code/datums/mapgen/CaveGenerator.dm index 6fa286056b2..f7d8f2d08ef 100644 --- a/code/datums/mapgen/CaveGenerator.dm +++ b/code/datums/mapgen/CaveGenerator.dm @@ -136,6 +136,7 @@ // thousands of tiles of lit space, so this grows per churn cycle. Same guard // place_cordon_turf() carries (voidcrew/datums/map_zones.dm). if(isspaceturf(gen_turf) && gen_turf.light_on) + // VOIDCREW EDIT START: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). GLOB.starlight -= gen_turf // VOIDCREW EDIT: and its third. ChangeTurf carries the old turf's four // /datum/lighting_corner refs across its qdel()/new() pair; a raw swap gets the @@ -158,6 +159,7 @@ new_turf = new new_turf(gen_turf) if(SSlighting.initialized) new_turf.adopt_lighting_from_raw_swap(corner_ne, corner_se, corner_sw, corner_nw, old_dynamic_lumcount) + // VOIDCREW EDIT END if(gen_turf.turf_flags & NO_RUINS) new_turf.turf_flags |= NO_RUINS @@ -170,6 +172,7 @@ // every cycle, forever. Open turfs need this too: requires_activation defaults to // false, so Initialize() does not queue them and their atmos graph stays empty. if(SSair.initialized) + // VOIDCREW EDIT START: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). CALCULATE_ADJACENT_TURFS(new_turf, NORMAL_TURF) // VOIDCREW EDIT: same mid-round reality as above - thousands of turfs with no @@ -178,6 +181,7 @@ SSovermap.worldgen_yield() announce_generation_time("[name] terrain generation finished in [(REALTIMEOFDAY - start_time)/10]s!") + // VOIDCREW EDIT END /** @@ -251,6 +255,7 @@ // thousands of tiles of lit space, so this grows per churn cycle. Same guard // place_cordon_turf() carries (voidcrew/datums/map_zones.dm). if(isspaceturf(gen_turf) && gen_turf.light_on) + // VOIDCREW EDIT START: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). GLOB.starlight -= gen_turf // VOIDCREW EDIT: same corner carry as generate_terrain() above - see // /turf/proc/adopt_lighting_from_raw_swap() in voidcrew/edits/turf.dm. @@ -269,12 +274,14 @@ var/turf/new_turf = new new_turf_type(gen_turf) if(SSlighting.initialized) new_turf.adopt_lighting_from_raw_swap(corner_ne, corner_se, corner_sw, corner_nw, old_dynamic_lumcount) + // VOIDCREW EDIT END if(gen_turf.turf_flags & NO_RUINS) new_turf.turf_flags |= NO_RUINS // VOIDCREW EDIT: same mid-round adjacency scrub as generate_terrain() above if(SSair.initialized && isclosedturf(new_turf)) + // VOIDCREW EDIT: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). CALCULATE_ADJACENT_TURFS(new_turf, NORMAL_TURF) CHECK_TICK @@ -286,6 +293,7 @@ generated_turfs_per_biome[biome] = generated_turfs + // VOIDCREW EDIT: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). announce_generation_time("[name] terrain generation finished in [(REALTIMEOFDAY - start_time)/10]s!") @@ -380,6 +388,7 @@ // builds run this under the worldgen queue and must share its budget SSovermap.worldgen_yield() + // VOIDCREW EDIT: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). announce_generation_time("[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!") @@ -402,6 +411,7 @@ // No sense in doing anything here if nothing is allowed anyway. if(!flora_allowed && !features_allowed && !fauna_allowed) + // VOIDCREW EDIT: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). announce_generation_time("[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!") return @@ -411,6 +421,7 @@ CHECK_TICK + // VOIDCREW EDIT: Support safe mid-round terrain swaps and budgeted generation (voidcrew/edits/turf.dm; voidcrew/modules/overmap). announce_generation_time("[name] terrain population finished in [(REALTIMEOFDAY - start_time)/10]s!") diff --git a/code/datums/mapgen/biomes/_biome.dm b/code/datums/mapgen/biomes/_biome.dm index 8f43b7fcc9c..258e5172527 100644 --- a/code/datums/mapgen/biomes/_biome.dm +++ b/code/datums/mapgen/biomes/_biome.dm @@ -59,6 +59,7 @@ // vertices that already have them and steals them from every neighbour it shares them // with. See /turf/proc/adopt_lighting_from_raw_swap() in voidcrew/edits/turf.dm. if(!SSlighting.initialized) + // VOIDCREW EDIT START: Carry lighting corners and rebuild adjacency for live planetary terrain swaps (voidcrew/edits/turf.dm). return new turf_type(gen_turf) gen_turf.release_light_for_raw_swap() var/datum/lighting_corner/corner_ne = gen_turf.lighting_corner_NE @@ -68,6 +69,7 @@ var/old_dynamic_lumcount = gen_turf.dynamic_lumcount var/turf/new_turf = new turf_type(gen_turf) new_turf.adopt_lighting_from_raw_swap(corner_ne, corner_se, corner_sw, corner_nw, old_dynamic_lumcount) + // VOIDCREW EDIT END return new_turf @@ -103,6 +105,7 @@ // can idle a corner out from under us. See // /turf/proc/adopt_lighting_from_raw_swap() in voidcrew/edits/turf.dm. var/datum/lighting_corner/corner_ne + // VOIDCREW EDIT START: Carry lighting corners and rebuild adjacency for live planetary terrain swaps (voidcrew/edits/turf.dm). var/datum/lighting_corner/corner_se var/datum/lighting_corner/corner_sw var/datum/lighting_corner/corner_nw @@ -117,6 +120,7 @@ var/turf/new_turf = new turf_type(gen_turf) if(lighting_live) new_turf.adopt_lighting_from_raw_swap(corner_ne, corner_se, corner_sw, corner_nw, old_dynamic_lumcount) + // VOIDCREW EDIT END new_turfs += new_turf if(gen_turf.turf_flags & NO_RUINS) @@ -126,6 +130,7 @@ // raw `new` never scrubs itself out of its neighbours' atmos_adjacent_turfs. // See the matching edit in CaveGenerator.dm. if(SSair.initialized && isclosedturf(new_turf)) + // VOIDCREW EDIT: Carry lighting corners and rebuild adjacency for live planetary terrain swaps (voidcrew/edits/turf.dm). CALCULATE_ADJACENT_TURFS(new_turf, NORMAL_TURF) CHECK_TICK diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index d6389157930..2c74ecdd108 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -254,8 +254,9 @@ Unless you know what you're doing, only use the first three numbers. They're in ) sheet_type = /obj/item/stack/sheet/mineral/plasma ore_type = /obj/item/stack/ore/plasma + // VOIDCREW EDIT: Price plasma as ship fuel and enable galactic market trading (voidcrew/modules/trade). value_per_unit = 20 / SHEET_MATERIAL_AMOUNT - // VOIDCREW EDIT: plasma trades on the galactic materials market. Upstream keeps + // VOIDCREW EDIT START: plasma trades on the galactic materials market. Upstream keeps // it off because plasma is the station's dedicated export; here it's ship fuel // and the market refusing exactly plasma read as a bug to crews (rounds 14/15). tradable = TRUE diff --git a/code/datums/mind/_mind.dm b/code/datums/mind/_mind.dm index 5a0dd174995..785b94e65d9 100644 --- a/code/datums/mind/_mind.dm +++ b/code/datums/mind/_mind.dm @@ -156,6 +156,7 @@ UnregisterSignal(src, COMSIG_QDELETING) current = new_current if(current) + // VOIDCREW EDIT: Remember former player bodies so site weather keeps affecting abandoned crew. current.ever_had_mind = TRUE RegisterSignal(src, COMSIG_QDELETING, PROC_REF(clear_current)) diff --git a/code/datums/records/record.dm b/code/datums/records/record.dm index e522aa2e8df..9c231f5118b 100644 --- a/code/datums/records/record.dm +++ b/code/datums/records/record.dm @@ -123,8 +123,10 @@ /datum/record/crew/Destroy() GLOB.manifest.general -= src + // VOIDCREW EDIT START: Delete associative record photos correctly and copy their appearance before posing it. QDEL_LIST_ASSOC_VAL(record_photos) record_photos = null + // VOIDCREW EDIT END return ..() /** @@ -227,6 +229,7 @@ var/icon/picture_image if(!isicon(character_appearance)) // Direction and the height chart belong to this photo, not the saved appearance. + // VOIDCREW EDIT: Delete associative record photos correctly and copy their appearance before posing it. var/mutable_appearance/appearance = new(character_appearance) appearance.setDir(orientation) if(add_height_chart) diff --git a/code/datums/screentips/atom_context.dm b/code/datums/screentips/atom_context.dm index 779b262f992..6f6b47f0052 100644 --- a/code/datums/screentips/atom_context.dm +++ b/code/datums/screentips/atom_context.dm @@ -11,6 +11,7 @@ // re-registers over its own leftover entry. It is add_context either way, so the // duplicate warning says nothing and the stack_trace it raises is not free: inside // a try block (map loaders use them) it unwinds the whole load. + // VOIDCREW EDIT: Replace retained turf context signals during repeated live template loads. RegisterSignal(src, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(add_context), override = TRUE) /// Creates a "Type-B" contextual screentip interaction. diff --git a/code/datums/shuttles/_shuttle.dm b/code/datums/shuttles/_shuttle.dm index 3bd5c8d153e..ac94a966e5e 100644 --- a/code/datums/shuttles/_shuttle.dm +++ b/code/datums/shuttles/_shuttle.dm @@ -83,6 +83,7 @@ // its dimensions and shuttle_areas stay empty - linkup() then walks no areas at // all and every machine that binds through connect_to_shuttle() (cryopod spawn // points, airlock ids, cameras) is silently left unbound. + // VOIDCREW EDIT START: Initialize mapped hull ports before baseturf filtering so all ship machines can bind. for(var/obj/docking_port/mobile/port in place) port.calculate_docking_port_information(src) // initTemplateBounds explicitly ignores the shuttle's docking port, to ensure that it calculates the bounds of the shuttle correctly @@ -90,6 +91,7 @@ SSatoms.InitializeAtoms(list(port)) if(register) port.register() + // VOIDCREW EDIT END if(isspaceturf(place)) // This assumes all shuttles are loaded in a single spot then moved to their real destination. continue @@ -99,6 +101,7 @@ place.insert_baseturf(3, /turf/baseturf_skipover/shuttle) +// VOIDCREW EDIT REMOVAL: Docking-port initialization now runs before the baseturf skip above so shallow hull tiles still bind. //Whatever special stuff you want // VOIDCREW EDIT END /datum/map_template/shuttle/post_load(obj/docking_port/mobile/M) diff --git a/code/datums/station_alert.dm b/code/datums/station_alert.dm index f382f8fc9c9..bcbc8a9c252 100644 --- a/code/datums/station_alert.dm +++ b/code/datums/station_alert.dm @@ -19,7 +19,7 @@ src.title = title src.camera_view = camera_view listener = new(alarm_types, listener_z_level, listener_areas) - // VOIDCREW EDIT ADDITION: packed-level containment for the Z-SCOPED listeners only. + // VOIDCREW EDIT ADDITION START: packed-level containment for the Z-SCOPED listeners only. // "Same z-level" is up to four unrelated crews' sites once encounters pack onto the // slot lattice, and every alarm carries its area NAME plus that area's camera refs - // so a local alert console listed the neighbouring crew's rooms and handed an AI or diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index f3fbff56608..64c7c71797c 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -932,6 +932,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) show_contents(to_show) return FALSE + // VOIDCREW EDIT: Allow storage access during soft crit via incapacitated_except_softcrit(). if(!isliving(to_show) || !to_show.can_perform_action(parent, ALLOW_RESTING | FORBID_TELEKINESIS_REACH | ALLOW_SOFT_CRIT)) return FALSE diff --git a/code/datums/storage/subtypes/others/bag_of_holding.dm b/code/datums/storage/subtypes/others/bag_of_holding.dm index 2e6a3d52dbb..1319a187eac 100644 --- a/code/datums/storage/subtypes/others/bag_of_holding.dm +++ b/code/datums/storage/subtypes/others/bag_of_holding.dm @@ -15,9 +15,10 @@ return ..() -// VOIDCREW EDIT START - PR #380: Protect trader outposts from singularities and destructive hazards. +// VOIDCREW EDIT: PR #380: Protect trader outposts from singularities and destructive hazards. /datum/storage/bag_of_holding/proc/recursive_insertion(obj/item/to_insert, mob/living/user) // VOIDCREW: Check the bag's current location, including after the dialog. + // VOIDCREW EDIT START: Check the receiving bag location before and after the nesting dialog (voidcrew/modules/trade/bag_rift_protection.dm). if(!can_create_rift(user)) return var/safety = tgui_alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [to_insert.name]?", list("Proceed", "Abort")) @@ -30,6 +31,7 @@ || !can_insert(to_insert, user) \ || !can_create_rift(user) \ ) + // VOIDCREW EDIT END return var/turf/rift_loc = get_turf(parent) @@ -47,15 +49,3 @@ tear.start_disaster() qdel(to_insert) qdel(parent) - -/// The receiving bag can be on the other side of an area boundary from its user. -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #380: Protect trader outposts from singularities and destructive hazards. -/datum/storage/bag_of_holding/proc/can_create_rift(mob/user) - var/area/bag_area = get_area(parent) - if(!bag_area || (bag_area.area_flags & NO_BOH) || is_trader_outpost_protected(parent)) - if(user) - to_chat(user, span_warning("Bluespace interference prevents the bags from nesting here.")) - return FALSE - return TRUE -// VOIDCREW EDIT END diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index 7d3238a549f..b1820c4d40b 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -240,7 +240,6 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/proc/setup_weather_areas() var/list/affectareas = list() - // VOIDCREW EDIT ADDITION START - a site-launched storm already knows its area instances, so // it skips the world-wide get_areas() sweep and never picks up a co-tenant's areas. // // An area-scoped site that owns NOTHING impacts nothing, rather than falling through to the @@ -253,7 +252,7 @@ if(isnull(candidate_areas) && !weather_site?.area_scoped) candidate_areas = get_areas(area_type) log_packed_level_area_sweep() - // VOIDCREW EDIT ADDITION END + // VOIDCREW EDIT: Scope storm effects to their site and bound planetary weather work (voidcrew/edits/datums/weather/weather.dm). for(var/area/selected_area as anything in candidate_areas) affectareas += selected_area for(var/area/protected_area as anything in protected_areas) @@ -268,6 +267,7 @@ continue impacted_areas |= affected_area + // VOIDCREW EDIT: Use an area membership lookup for site-scoped storm eligibility (voidcrew/edits/datums/weather/weather.dm). impacted_areas_lookup[affected_area] = TRUE if(!(weather_flags & (WEATHER_THUNDER|WEATHER_TURFS))) @@ -306,6 +306,7 @@ if(weather_flags & (WEATHER_TURFS)) weather_turfs_per_tick = total_impacted_turfs * turf_weather_chance + // VOIDCREW EDIT: Scope storm effects to their site and bound planetary weather work (voidcrew/edits/datums/weather/weather.dm). weather_turfs_per_tick = min(weather_turfs_per_tick, turf_act_containers_only ? MAX_CONTAINER_ONLY_TURFS_PER_TICK : MAX_TURFS_PER_TICK) if(weather_flags & (WEATHER_THUNDER)) thunder_turfs_per_tick = total_impacted_turfs * turf_thunder_chance @@ -396,9 +397,9 @@ // the checks for if a mob should receive alerts, returns TRUE if can /datum/weather/proc/can_get_alert(mob/player) var/turf/mob_turf = get_turf(player) + // VOIDCREW EDIT START: Use an area membership lookup for site-scoped storm eligibility (voidcrew/edits/datums/weather/weather.dm). if(isnull(mob_turf)) return FALSE - // VOIDCREW EDIT ADDITION START - alerts follow the impacted AREAS, not the whole z-level. // clients_by_zlevel alone tells a crew standing in a cave (or, once several places share // a level, on the neighbouring planet) about a surface storm that cannot reach them. // Storms with no area scoping at all keep the plain on-an-impacted-z behaviour. @@ -415,8 +416,8 @@ // (flat co-tenants all sit in the one global /area/space). if(weather_site && !weather_site.contains_turf(mob_turf)) return FALSE - // VOIDCREW EDIT ADDITION END return TRUE + // VOIDCREW EDIT END /** * Returns TRUE if the living mob can be affected by the weather @@ -435,6 +436,7 @@ if(!(mob_turf.z in impacted_z_levels)) return + // VOIDCREW EDIT: Use an area membership lookup for site-scoped storm eligibility (voidcrew/edits/datums/weather/weather.dm). if(!impacted_areas_lookup[mob_turf.loc]) return @@ -564,6 +566,7 @@ hit_thing.take_damage(20, BURN, ENERGY, FALSE) playsound(weather_turf, 'sound/effects/magic/lightningbolt.ogg', 100, extrarange = 10, falloff_distance = 10) weather_turf.visible_message(span_danger("A thunderbolt strikes [weather_turf]!")) + // VOIDCREW EDIT REMOVAL: Apply the existing direct lightning strike without a generic explosion that bypasses mob weather eligibility. // A generic explosion cannot honor can_weather_act_mob() and would queue damage // against ordinary fauna on this and adjacent turfs. The direct strike above and // object burn retain the intended lightning effects without bypassing eligibility. @@ -578,6 +581,7 @@ // VOIDCREW EDIT ADDITION - a hard-deleted area is nulled IN PLACE in this list rather // than removed from it, and `as anything` skips the istype filter that would catch it. if(isnull(impacted)) + // VOIDCREW EDIT: Scope storm effects to their site and bound planetary weather work (voidcrew/edits/datums/weather/weather.dm). continue if(length(overlay_cache)) impacted.overlays -= overlay_cache diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index eafb774b9fc..8916a3259bd 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -69,6 +69,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/ash_storm/end() GLOB.ash_storm_sounds -= weak_sounds + // VOIDCREW EDIT: Remove only this storm sounds when concurrent sites have ash storms. GLOB.ash_storm_sounds -= strong_sounds for(var/turf/open/misc/asteroid/basalt/basalt as anything in GLOB.dug_up_basalt) if(!(basalt.loc in impacted_areas) || !(basalt.z in impacted_z_levels)) diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm index 3613448490a..ae9c27308d5 100644 --- a/code/datums/weather/weather_types/floor_is_lava.dm +++ b/code/datums/weather/weather_types/floor_is_lava.dm @@ -30,6 +30,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/floor_is_lava/can_weather_act_mob(mob/living/mob_to_check) + // VOIDCREW EDIT REMOVAL: Use common weather eligibility so abandoned player bodies remain affected by lava weather. . = ..() if(!. || issilicon(mob_to_check) || istype(mob_to_check.buckled, /obj/structure/bed)) return FALSE diff --git a/code/datums/weather/weather_types/rain_storm.dm b/code/datums/weather/weather_types/rain_storm.dm index 5a33473ffe4..7522a693d0f 100644 --- a/code/datums/weather/weather_types/rain_storm.dm +++ b/code/datums/weather/weather_types/rain_storm.dm @@ -34,6 +34,7 @@ // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/rain_storm/telegraph() + // VOIDCREW EDIT REMOVAL: Limit planetary rain work and preserve independent storm sounds across sites. for(var/area/impacted_area as anything in impacted_areas) start_sounds[impacted_area] = /datum/looping_sound/rain/start middle_sounds[impacted_area] = /datum/looping_sound/rain/middle @@ -79,6 +80,7 @@ weather_temperature = 455 // just hot enough to apply the fried effect whitelist_weather_reagents = list(/datum/reagent/consumable/nutriment/fat/oil) weather_flags = (WEATHER_TURFS | WEATHER_INDOORS) + // VOIDCREW EDIT: Limit planetary rain work and preserve independent storm sounds across sites. turf_act_containers_only = FALSE // admeme event on station z-levels, wants the full frying splash probability = 0 // admeme event @@ -131,6 +133,7 @@ whitelist_weather_reagents = list() probability = 0 // shouldn't spawn normally weather_flags = (WEATHER_TURFS | WEATHER_MOBS | WEATHER_INDOORS | WEATHER_BAROMETER) + // VOIDCREW EDIT: Limit planetary rain work and preserve independent storm sounds across sites. turf_act_containers_only = FALSE // wizard event on the station z, the chaotic reagent splashing is the whole point // VOIDCREW EDIT END diff --git a/code/datums/weather/weather_types/sand_storm.dm b/code/datums/weather/weather_types/sand_storm.dm index d645dee433c..45de5906a72 100644 --- a/code/datums/weather/weather_types/sand_storm.dm +++ b/code/datums/weather/weather_types/sand_storm.dm @@ -29,6 +29,7 @@ // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/sand_storm/telegraph() + // VOIDCREW EDIT REMOVAL: Preserve independent sand storm sounds across sites (voidcrew/edits/datums/weather/weather_types/sand_storm.dm). for(var/area/impacted_area as anything in impacted_areas) weak_sounds[impacted_area] = /datum/looping_sound/weak_outside_ashstorm strong_sounds[impacted_area] = /datum/looping_sound/active_outside_ashstorm diff --git a/code/datums/weather/weather_types/snow_storm.dm b/code/datums/weather/weather_types/snow_storm.dm index 4c67ce2202a..4bea3e04933 100644 --- a/code/datums/weather/weather_types/snow_storm.dm +++ b/code/datums/weather/weather_types/snow_storm.dm @@ -35,6 +35,7 @@ // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/snow_storm/start() + // VOIDCREW EDIT REMOVAL: Preserve independent snow storm sounds across sites. for(var/area/impacted_area as anything in impacted_areas) active_sounds[impacted_area] = /datum/looping_sound/snowstorm GLOB.snowstorm_sounds += active_sounds @@ -43,6 +44,7 @@ // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/weather/snow_storm/end() + // VOIDCREW EDIT: Preserve independent snow storm sounds across sites. GLOB.snowstorm_sounds -= active_sounds return ..() diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index f02797b0dab..0d39e27346f 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -195,6 +195,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) . = ..() + // VOIDCREW EDIT REMOVAL - overmap lighting: area illumination must not multiply the ambient encounter appearance (voidcrew/edits/lighting.dm) reg_in_areas_in_z() update_base_lighting() diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 1fa24ab4113..eaa29ed1f7f 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -829,15 +829,6 @@ /atom/MouseEntered(location, control, params) SSmouse_entered.hovers[usr.client] = src -/atom/MouseExited(location, control, params) - var/client/hovering_client = usr?.client - if(!hovering_client) - return - // The pointer can leave before the deferred MouseEntered has been processed. - if(SSmouse_entered.hovers[hovering_client] == src) - SSmouse_entered.hovers[hovering_client] = null - hovering_client.mob?.hud_used?.screentip_text?.clear_hover(src) - /// Fired whenever this atom is the most recent to be hovered over in the tick. /// Preferred over MouseEntered if you do not need information such as the position of the mouse. /// Especially because this is deferred over a tick, do not trust that `client` is not null. @@ -855,10 +846,10 @@ if(!active_hud) return - var/hover_version = active_hud.screentip_text.begin_hover(src) + var/hover_version = active_hud.screentip_text.begin_hover(src) // VOIDCREW EDIT: screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) var/screentips_enabled = active_hud.screentips_enabled if(screentips_enabled == SCREENTIP_PREFERENCE_DISABLED || flags_1 & NO_SCREENTIPS_1) - active_hud.screentip_text.set_hover_text("") + active_hud.screentip_text.set_hover_text("") // VOIDCREW EDIT: screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) return var/lmb_rmb_line = "" @@ -939,27 +930,33 @@ if(extra_lines) extra_context = "
[lmb_rmb_line][ctrl_lmb_ctrl_rmb_line][alt_lmb_alt_rmb_line][shift_lmb_ctrl_shift_lmb_line]" + // VOIDCREW EDIT START - screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) if (extra_context == "" && (screentips_enabled == SCREENTIP_PREFERENCE_CONTEXT_ONLY || !length(used_name))) active_hud.screentip_text.set_hover_text("") return //We inline a MAPTEXT() here, because there's no good way to statically add to a string like this var/new_maptext = "[used_name][extra_context]" + // VOIDCREW EDIT END if (length(used_name) * 10 > active_hud.screentip_text.maptext_width) - INVOKE_ASYNC(src, PROC_REF(set_hover_maptext), client, active_hud, new_maptext, hover_version) + INVOKE_ASYNC(src, PROC_REF(set_hover_maptext), client, active_hud, new_maptext, hover_version) // VOIDCREW EDIT: screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) return - active_hud.screentip_text.set_hover_text(new_maptext, 10 - (extra_lines > 0 ? 11 + 9 * (extra_lines - 1): 0)) + active_hud.screentip_text.set_hover_text(new_maptext, 10 - (extra_lines > 0 ? 11 + 9 * (extra_lines - 1): 0)) // VOIDCREW EDIT: screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) +// VOIDCREW EDIT START - screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) /atom/proc/set_hover_maptext(client/client, datum/hud/active_hud, new_maptext, hover_version) var/atom/movable/screen/screentip/screentip = active_hud?.screentip_text if(!client || QDELETED(screentip) || screentip.hover_version != hover_version) return +// VOIDCREW EDIT END var/map_height + // VOIDCREW EDIT START - screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) WXH_TO_HEIGHT(client.MeasureText(new_maptext, null, screentip.maptext_width), map_height) if(!client || QDELETED(screentip) || screentip.hover_version != hover_version) return screentip.set_hover_text(new_maptext, 26 - map_height) + // VOIDCREW EDIT END /** * This proc is used for telling whether something can pass by this atom in a given direction, for use by the pathfinding system. diff --git a/code/game/atom/atom_defense.dm b/code/game/atom/atom_defense.dm index 34bf17f2060..d3f19069100 100644 --- a/code/game/atom/atom_defense.dm +++ b/code/game/atom/atom_defense.dm @@ -70,8 +70,10 @@ return atom_integrity = new_value // VOIDCREW: record supported ship fixtures only when they actually lose integrity. + // VOIDCREW EDIT START - ship_repairs: distinguish damaged fixtures from deliberate dismantling if(new_value < old_value) record_ship_fixture_damage(src) + // VOIDCREW EDIT END on_update_integrity(old_value, new_value) return new_value diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index 7fdf566fb3f..02b718c5cb3 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -102,7 +102,7 @@ */ /obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/checked_apc) - // VOIDCREW EDIT ADDITION: packed-level containment, and a live is_on_station. + // VOIDCREW EDIT ADDITION START: packed-level containment, and a live is_on_station. - overmap: contain observers and effects within their packed encounter // Both branches of the upstream expression are wrong once sites share a z-level: // * is_on_station FALSE -> bare z equality lists and REMOTELY OPERATES every APC on // the packed z, i.e. all three co-tenants' sites plus any hull docked at them; diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index df87a597f09..2017545e881 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -65,7 +65,7 @@ var/list/station_alert_areas = GLOB.the_station_areas + typesof(/area/mine) // Setting up a variable for checking our circuit's station_only var/obj/item/circuitboard/computer/atmos_alert/my_circuit = circuit - // VOIDCREW EDIT ADDITION: packed-level containment, resolved once per process() rather + // VOIDCREW EDIT ADDITION START: packed-level containment, resolved once per process() rather - overmap: contain observers and effects within their packed encounter // than once per alarm. The z branch below prints get_area_name() for every matching // alarm, so on a packed level a local atmos console named the neighbouring crew's rooms. var/datum/console_region = my_circuit.station_only ? null : map_region_for_turf(get_turf(src)) @@ -78,7 +78,7 @@ // Otherwise just check if alarms match the console's z-level else if (air_alarm.z != z) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START - overmap: contain observers and effects within their packed encounter else if (map_region_excludes_turf(console_region, get_turf(air_alarm))) continue // VOIDCREW EDIT END diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 0431f0615cc..bf4cbe465e1 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -112,10 +112,10 @@ if(action == "switch_camera") active_camera?.on_stop_watching(src) var/obj/machinery/camera/selected_camera = locate(params["camera"]) in GLOB.cameranet.cameras - active_camera = can_view_camera(selected_camera) ? selected_camera : null + active_camera = can_view_camera(selected_camera) ? selected_camera : null // VOIDCREW EDIT: ship camera integration: validate camera access and clear stale views (voidcrew/edits/machinery/camera.dm) if(isnull(active_camera)) - update_active_camera_screen() + update_active_camera_screen() // VOIDCREW EDIT: ship camera integration: validate camera access and clear stale views (voidcrew/edits/machinery/camera.dm) return TRUE active_camera.on_start_watching(src) @@ -126,13 +126,15 @@ // VOIDCREW EDIT END /obj/machinery/computer/security/proc/update_active_camera_screen() // VOIDCREW: a stale/forged reference must not bypass the local camera network. + // VOIDCREW EDIT START - ship camera integration: validate camera access and clear stale views (voidcrew/edits/machinery/camera.dm) if(active_camera && !can_view_camera(active_camera)) active_camera.on_stop_watching(src) active_camera = null last_camera_turf = null + // VOIDCREW EDIT END // Show static if can't use the camera if(!active_camera?.can_use()) - last_camera_turf = null + last_camera_turf = null // VOIDCREW EDIT: ship camera integration: validate camera access and clear stale views (voidcrew/edits/machinery/camera.dm) cam_screen.show_camera_static() return diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 15a1e8da3f2..a826f8af717 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -22,7 +22,7 @@ /// Cooldown for important actions, such as messaging CentCom or other sectors COOLDOWN_DECLARE(static/important_action_cooldown) - COOLDOWN_DECLARE(emergency_access_cooldown) + COOLDOWN_DECLARE(emergency_access_cooldown) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship /// Whether syndicate mode is enabled or not. var/syndicate = FALSE @@ -50,7 +50,7 @@ var/send_cross_comms_message_timer /// The last lines used for changing the status display - var/last_status_display + var/last_status_display // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship ///how many uses the console has done of toggling the emergency access var/toggle_uses = 0 @@ -79,6 +79,7 @@ /obj/machinery/computer/communications/syndicate/authenticated_as_silicon_or_captain(mob/user) return FALSE +// VOIDCREW EDIT REMOVAL - comms: syndicate consoles use the same local recipient scope as other ship consoles // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/computer/communications/Initialize(mapload) @@ -204,10 +205,10 @@ if (SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_DELTA) to_chat(user, span_warning("Central Command has placed a lock on the alert level due to a doomsday!")) return - if (get_communications_security_level().number_level == new_sec_level) + if (get_communications_security_level().number_level == new_sec_level) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship return - set_communications_security_level(new_sec_level) + set_communications_security_level(new_sec_level) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship to_chat(user, span_notice("Authorization confirmed. Modifying security level.")) playsound(src, 'sound/machines/terminal/terminal_prompt_confirm.ogg', 50, FALSE) @@ -280,7 +281,7 @@ bank_account.adjust_money(-shuttle.credit_cost) var/purchaser_name = (obj_flags & EMAGGED) ? scramble_message_replace_chars("AUTHENTICATION FAILURE: CVE-2018-17107", 60) : user.real_name - minor_announce("[purchaser_name] has purchased [shuttle.name] for [shuttle.credit_cost] credits.[shuttle.extra_desc ? " [shuttle.extra_desc]" : ""]" , "Shuttle Purchase", players = get_communication_players()) + minor_announce("[purchaser_name] has purchased [shuttle.name] for [shuttle.credit_cost] credits.[shuttle.extra_desc ? " [shuttle.extra_desc]" : ""]" , "Shuttle Purchase", players = get_communication_players()) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship message_admins("[ADMIN_LOOKUPFLW(user)] purchased [shuttle.name].") log_shuttle("[key_name(user)] has purchased [shuttle.name].") @@ -291,6 +292,7 @@ if (!authenticated(user) || HAS_SILICON_ACCESS(user) || syndicate) return SSshuttle.cancelEvac(user) + // VOIDCREW EDIT REMOVAL - comms: ship consoles do not request station nuclear self-destruct codes if ("restoreBackupRoutingData") if (!authenticated_as_non_silicon_captain(user)) return @@ -360,6 +362,7 @@ var/line_one = reject_bad_text(params["upperText"] || "", MAX_STATUS_LINE_LENGTH) var/line_two = reject_bad_text(params["lowerText"] || "", MAX_STATUS_LINE_LENGTH) post_status("message", line_one, line_two) + // VOIDCREW EDIT REMOVAL - comms: keep announcements, alert state and status displays local to the communicating ship if ("setStatusPicture") if (!authenticated(user)) return @@ -370,7 +373,7 @@ post_status(picture) else if(picture == "currentalert") // You cannot set Code Blue display during Code Red and similiar - post_status("alert", get_communications_security_level().status_display_icon_state) + post_status("alert", get_communications_security_level().status_display_icon_state) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship else post_status("alert", picture) @@ -406,13 +409,15 @@ return if (!authenticated_as_silicon_or_captain(user)) return + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship if (get_communications_emergency_access()) revoke_maint_all_access(src) + // VOIDCREW EDIT END user.log_message("disabled emergency maintenance access.", LOG_GAME) message_admins("[ADMIN_LOOKUPFLW(user)] disabled emergency maintenance access.") deadchat_broadcast(" disabled emergency maintenance access at [span_name("[get_area_name(user, TRUE)]")].", span_name("[user.real_name]"), user, message_type = DEADCHAT_ANNOUNCEMENT) else - make_maint_all_access(src) + make_maint_all_access(src) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship user.log_message("enabled emergency maintenance access.", LOG_GAME) message_admins("[ADMIN_LOOKUPFLW(user)] enabled emergency maintenance access.") deadchat_broadcast(" enabled emergency maintenance access at [span_name("[get_area_name(user, TRUE)]")].", span_name("[user.real_name]"), user, message_type = DEADCHAT_ANNOUNCEMENT) @@ -439,7 +444,7 @@ SSjob.safe_code_request_loc = pod_location SSjob.safe_code_requested = TRUE SSjob.safe_code_timer_id = addtimer(CALLBACK(SSjob, TYPE_PROC_REF(/datum/controller/subsystem/job, send_spare_id_safe_code), pod_location), 120 SECONDS, TIMER_UNIQUE | TIMER_STOPPABLE) - minor_announce("Due to staff shortages, your crew has been approved for delivery of access codes to secure the Captain's Spare ID. Delivery via drop pod at [get_area(pod_location)]. ETA 120 seconds.", players = get_communication_players()) + minor_announce("Due to staff shortages, your crew has been approved for delivery of access codes to secure the Captain's Spare ID. Delivery via drop pod at [get_area(pod_location)]. ETA 120 seconds.", players = get_communication_players()) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship // VOIDCREW EDIT END /obj/machinery/computer/communications/proc/emergency_access_cooldown(mob/user) @@ -474,7 +479,7 @@ payload["is_filtered"] = TRUE send2otherserver(html_decode(station_name()), message, "Comms_Console", destination == "all" ? null : list(destination), additional_data = payload) - minor_announce(message, title = "Outgoing message to allied station", players = get_communication_players()) + minor_announce(message, title = "Outgoing message to allied station", players = get_communication_players()) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship user.log_talk(message, LOG_SAY, tag = "message to the other server") message_admins("[ADMIN_LOOKUPFLW(user)] has sent a message to the other server\[s].") deadchat_broadcast(" has sent an outgoing message to the other station(s).", "[user.real_name]", user, message_type = DEADCHAT_ANNOUNCEMENT) @@ -520,6 +525,7 @@ data["canMakeAnnouncement"] = FALSE data["canMessageAssociates"] = FALSE data["canRecallShuttles"] = !HAS_SILICON_ACCESS(user) + // VOIDCREW EDIT REMOVAL - comms: keep announcements, alert state and status displays local to the communicating ship data["canSendToSectors"] = FALSE data["canSetAlertLevel"] = FALSE data["canToggleEmergencyAccess"] = FALSE @@ -527,7 +533,7 @@ data["shuttleCalled"] = FALSE data["shuttleLastCalled"] = FALSE data["aprilFools"] = check_holidays(APRIL_FOOLS) - data["alertLevel"] = get_communications_security_level().name + data["alertLevel"] = get_communications_security_level().name // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship data["authorizeName"] = authorize_name data["canLogOut"] = !HAS_SILICON_ACCESS(user) data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac() @@ -536,6 +542,7 @@ if (authenticated_as_non_silicon_captain(user)) data["canMessageAssociates"] = TRUE +// VOIDCREW EDIT REMOVAL - comms: keep announcements, alert state and status displays local to the communicating ship if (can_send_messages_to_other_sectors(user)) data["canSendToSectors"] = TRUE @@ -552,7 +559,7 @@ if (authenticated_as_silicon_or_captain(user)) data["canToggleEmergencyAccess"] = TRUE - data["emergencyAccess"] = get_communications_emergency_access() + data["emergencyAccess"] = get_communications_emergency_access() // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship data["alertLevelTick"] = alert_level_tick data["canMakeAnnouncement"] = TRUE @@ -607,9 +614,11 @@ data["budget"] = bank_account.account_balance data["shuttles"] = shuttles if (STATE_CHANGING_STATUS) + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship var/list/status_message = get_status_display_message() data["upperText"] = status_message ? status_message[1] : "" data["lowerText"] = status_message ? status_message[2] : "" + // VOIDCREW EDIT END return data @@ -652,10 +661,12 @@ /// Returns whether or not the communications console can communicate with the station /obj/machinery/computer/communications/proc/has_communication() + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship if(voidcrew_communications_ship(src)) return TRUE + // VOIDCREW EDIT END var/turf/current_turf = get_turf(src) - var/z_level = current_turf?.z + var/z_level = current_turf?.z // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship if(syndicate) return TRUE return is_station_level(z_level) || is_centcom_level(z_level) @@ -716,11 +727,13 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/computer/communications/proc/make_announcement(mob/living/user) var/is_ai = HAS_SILICON_ACCESS(user) + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship var/datum/communciations_controller/controller = get_announcement_controller() if(!controller.can_announce(user, is_ai)) + // VOIDCREW EDIT END to_chat(user, span_alert("Intercomms recharging. Please stand by.")) return - var/input = tgui_input_text(user, "Message to announce to the local crew", "Announcement", max_length = MAX_MESSAGE_LEN) + var/input = tgui_input_text(user, "Message to announce to the local crew", "Announcement", max_length = MAX_MESSAGE_LEN) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship if(!input || !user.can_perform_action(src, ALLOW_SILICON_REACH)) return if(user.try_speak(input)) @@ -739,13 +752,15 @@ var/list/players = get_communication_players() // Resolve again after the input prompt in case the console moved to another ship. + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship controller = get_announcement_controller() controller.make_announcement(user, is_ai, input, syndicate || (obj_flags & EMAGGED), players) + // VOIDCREW EDIT END deadchat_broadcast(" made a priority announcement from [span_name("[get_area_name(user, TRUE)]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT) // VOIDCREW EDIT END /obj/machinery/computer/communications/proc/get_communication_players() - return voidcrew_announcement_players(src) + return voidcrew_announcement_players(src) // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship /obj/machinery/computer/communications/proc/post_status(command, data1, data2) @@ -754,16 +769,20 @@ if(!frequency) return + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship var/datum/signal/status_signal = new(list("command" = command, "voidcrew_net" = voidcrew_local_comms_net(src))) if(!status_signal.data["voidcrew_net"]) return + // VOIDCREW EDIT END switch(command) if("message") + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship var/obj/docking_port/mobile/ship = voidcrew_communications_ship(src) if(ship) ship.last_comms_status_display = list(data1, data2) else last_status_display = list(data1, data2) + // VOIDCREW EDIT END status_signal.data["top_text"] = data1 status_signal.data["bottom_text"] = data2 log_game("[key_name(usr)] has changed the station status display message to \"[data1] [data2]\" [loc_name(usr)]") @@ -866,7 +885,7 @@ priority_announce( "Attention crew: sector monitoring reports a jump-trace from an unidentified vessel destined for your system. Prepare for probable contact.", "[command_name()] High-Priority Update", - players = get_communication_players(), + players = get_communication_players(), // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship ) SSdynamic.force_run_midround(/datum/dynamic_ruleset/midround/from_ghosts/fugitives) @@ -874,7 +893,7 @@ priority_announce( "Attention crew, it appears that someone on your station has hijacked your telecommunications and broadcasted an unknown signal.", "[command_name()] High-Priority Update", - players = get_communication_players(), + players = get_communication_players(), // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship ) var/max_number_of_sleepers = clamp(round(length(GLOB.alive_player_list) / 40), 1, 3) if(!SSdynamic.force_run_midround(/datum/dynamic_ruleset/midround/from_living/traitor, forced_max_cap = max_number_of_sleepers)) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 4140e6eec95..ab08ffaa957 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -61,7 +61,7 @@ return var/list/new_table = list() - for(var/list/player_record as anything in GLOB.crewmonitor.update_data(attached_console)) + for(var/list/player_record as anything in GLOB.crewmonitor.update_data(attached_console)) // VOIDCREW EDIT: crew sensor integration: scope and cache readings by the requesting device (voidcrew/edits/machinery/crew_monitor.dm) var/list/entry = list() entry["name"] = player_record["name"] entry["job"] = player_record["assignment"] @@ -178,10 +178,11 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) return host_ref?.resolve() /datum/crewmonitor/ui_data(mob/user) + // VOIDCREW EDIT REMOVAL - crew sensor integration: scope and cache readings by the requesting device (voidcrew/edits/machinery/crew_monitor.dm) // Voidcrew: the scope comes from the device that opened the UI - the console, the // handheld, the silicon - not from a bare z-level. voidcrew/edits/machinery/crew_monitor.dm . = list( - "sensors" = update_data(ui_host(user) || user), + "sensors" = update_data(ui_host(user) || user), // VOIDCREW EDIT: crew sensor integration: scope and cache readings by the requesting device (voidcrew/edits/machinery/crew_monitor.dm) "link_allowed" = HAS_AI_ACCESS(user), ) @@ -200,6 +201,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) if(data_by_scope[cache_key] && last_update[cache_key] && world.time <= last_update[cache_key] + SENSORS_UPDATE_PERIOD) return data_by_scope[cache_key] +// VOIDCREW EDIT END var/list/results = list() for(var/tracked_mob in GLOB.suit_sensors_list) @@ -220,7 +222,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) // Voidcrew: the target has to be aboard our hull, or off-hull in the same place we // are - never just "on a station level", since every ship interior is one. // voidcrew/edits/machinery/crew_monitor.dm - if(!voidcrew_crew_sensor_in_scope(tracked_living_mob, pos, hull, z, source_turf)) + if(!voidcrew_crew_sensor_in_scope(tracked_living_mob, pos, hull, z, source_turf)) // VOIDCREW EDIT: crew sensor integration: scope and cache readings by the requesting device (voidcrew/edits/machinery/crew_monitor.dm) continue var/mob/living/carbon/human/tracked_human = tracked_living_mob @@ -296,12 +298,13 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) results[++results.len] = entry // Cache result + // VOIDCREW EDIT START - crew sensor integration: scope and cache readings by the requesting device (voidcrew/edits/machinery/crew_monitor.dm) data_by_scope[cache_key] = results last_update[cache_key] = world.time + // VOIDCREW EDIT END return results -// VOIDCREW EDIT END /datum/crewmonitor/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 6ddd23dd86d..30a969532b7 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1608,7 +1608,7 @@ if(!disassembled) A?.update_integrity(A.max_integrity * 0.5) // VOIDCREW: this exact wrecked frame belongs to the recorded destruction. - record_ship_repair_wreckage(src, A) + record_ship_repair_wreckage(src, A) // VOIDCREW EDIT: ship_repairs: distinguish damaged fixtures from deliberate dismantling else if(!(obj_flags & EMAGGED)) var/obj/item/electronics/airlock/ae diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 8da95c8180d..2b84ca2978d 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -73,8 +73,10 @@ // this keeps any future one from costing a player their tgui window. Repairing the // var rather than just the payload also keeps do_action()'s `accesses += access` // from turning a null into a bare number. + // VOIDCREW EDIT START - ship access integration: preserve empty electronics access lists for AccessConfig (voidcrew/edits/ship_access.dm) if(isnull(accesses)) accesses = list() + // VOIDCREW EDIT END data["accesses"] = accesses data["oneAccess"] = one_access data["unres_direction"] = unres_sides diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index ec7244174d5..9742cbf1495 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -90,8 +90,10 @@ RegisterSignal(src, COMSIG_MACHINERY_POWER_RESTORED, PROC_REF(on_power_restore)) RegisterSignal(src, COMSIG_MACHINERY_POWER_LOST, PROC_REF(on_power_loss)) // Suppress atmosphere checks during shuttle moves to prevent false activations + // VOIDCREW EDIT START - shuttle: suspend firedoor atmosphere checks until the move settles (voidcrew/edits/machinery/firedoor_shuttle.dm) RegisterSignal(src, COMSIG_ATOM_BEFORE_SHUTTLE_MOVE, PROC_REF(on_shuttle_move_start)) RegisterSignal(src, COMSIG_ATOM_AFTER_SHUTTLE_MOVE, PROC_REF(on_shuttle_move_complete)) + // VOIDCREW EDIT END return INITIALIZE_HINT_LATELOAD /obj/machinery/door/firedoor/post_machine_initialize() @@ -489,28 +491,6 @@ if(is_playing_alarm) soundloop.start() -/// Called right before the shuttle physically moves - suppress atmosphere checks -/obj/machinery/door/firedoor/proc/on_shuttle_move_start(datum/source, turf/new_turf, rotation, move_mode, obj/docking_port/mobile/moving_dock) - SIGNAL_HANDLER - ignore_alarms = TRUE - -/// Called after shuttle move completes - re-enable checks and verify atmosphere -/obj/machinery/door/firedoor/proc/on_shuttle_move_complete(datum/source, turf/old_turf) - SIGNAL_HANDLER - ignore_alarms = FALSE - // Re-check atmosphere after it stabilizes to catch any real hazards - addtimer(CALLBACK(src, PROC_REF(post_shuttle_move_check)), 0.5 SECONDS) - -/// Re-evaluate atmospheric conditions after a shuttle move to catch real hazards -/obj/machinery/door/firedoor/proc/post_shuttle_move_check() - if(QDELETED(src)) - return - for(var/dir in GLOB.cardinals) - var/turf/checked_turf = get_step(get_turf(src), dir) - if(!checked_turf || !isopenturf(checked_turf)) - continue - process_results(checked_turf) - /obj/machinery/door/firedoor/attack_hand(mob/living/user, list/modifiers) . = ..() if(.) diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 036ea5138ff..601c6d4bf8f 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -42,10 +42,13 @@ // VOIDCREW EDIT START - PR #423: Initialize windoor atmos seals with the requested direction. /obj/machinery/door/window/Initialize(mapload, set_dir, unres_sides) // The parent publishes atmos adjacency, which must use the edge we actually seal. + // VOIDCREW EDIT START - ship access and atmos integration: initialize the sealing edge before adjacency and preserve empty access lists (voidcrew/edits/ship_access.dm) if(set_dir) setDir(set_dir) + // VOIDCREW EDIT END . = ..() flags_1 &= ~PREVENT_CLICK_UNDER_1 + // VOIDCREW EDIT REMOVAL - ship access and atmos integration: initialize the sealing edge before adjacency and preserve empty access lists (voidcrew/edits/ship_access.dm) if(LAZYLEN(req_access)) icon_state = "[icon_state]" base_state = icon_state @@ -446,10 +449,10 @@ // no access at all has both lists null, and copying that null onto the // electronics blue-screens tgui when they are opened (AirlockElectronics.tsx // defaults `accesses` for undefined, not for null). - if(length(req_one_access)) + if(length(req_one_access)) // VOIDCREW EDIT: ship access and atmos integration: initialize the sealing edge before adjacency and preserve empty access lists (voidcrew/edits/ship_access.dm) dropped_electronics.one_access = 1 dropped_electronics.accesses = req_one_access - else if(length(req_access)) + else if(length(req_access)) // VOIDCREW EDIT: ship access and atmos integration: initialize the sealing edge before adjacency and preserve empty access lists (voidcrew/edits/ship_access.dm) dropped_electronics.accesses = req_access else dropped_electronics = electronics diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm index c377deb398c..5b5447af32b 100644 --- a/code/game/machinery/embedded_controller/airlock_controller.dm +++ b/code/game/machinery/embedded_controller/airlock_controller.dm @@ -71,7 +71,7 @@ switch(state) if(AIRLOCK_STATE_INOPEN) if(target_state != state) - var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() + var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(interior_airlock)) continue @@ -81,7 +81,7 @@ else interior_airlock.secure_close() else - var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() + var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if(pump?.on) pump.on = FALSE @@ -94,7 +94,7 @@ continue if(sensor_pressure >= ONE_ATMOSPHERE*0.95) - var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() + var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(interior_airlock)) continue @@ -104,7 +104,7 @@ state = AIRLOCK_STATE_INOPEN process_again = TRUE else - var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() + var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(pump)) continue @@ -120,7 +120,7 @@ if(AIRLOCK_STATE_CLOSED) if(target_state == AIRLOCK_STATE_OUTOPEN) - var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() + var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(interior_airlock)) continue @@ -130,7 +130,7 @@ else interior_airlock?.secure_close() else if(target_state == AIRLOCK_STATE_INOPEN) - var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() + var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(exterior_airlock)) continue @@ -140,7 +140,7 @@ else exterior_airlock?.secure_close() else - var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() + var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(pump)) continue @@ -159,7 +159,7 @@ if(sensor_pressure <= target_pressure) if(target_state == AIRLOCK_STATE_OUTOPEN) - var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() + var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(exterior_airlock)) continue @@ -174,7 +174,7 @@ state = AIRLOCK_STATE_CLOSED process_again = TRUE else - var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() + var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(pump)) continue @@ -187,7 +187,7 @@ if(AIRLOCK_STATE_OUTOPEN) //state 2 if(target_state != AIRLOCK_STATE_OUTOPEN) - var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() + var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(exterior_airlock)) continue @@ -201,7 +201,7 @@ else exterior_airlock.secure_close() else - var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() + var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(pump)) continue @@ -224,19 +224,19 @@ var/sensor_pressure = sensor_pressure() data["sensorPressure"] = isnull(sensor_pressure) ? "----" : round(sensor_pressure, 0.1) - var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() + var/obj/machinery/door/airlock/interior_airlock = interior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(interior_airlock)) data["interiorStatus"] = "----" else data["interiorStatus"] = interior_airlock.density ? "closed" : "open" - var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() + var/obj/machinery/door/airlock/exterior_airlock = exterior_door_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (isnull(exterior_airlock)) data["exteriorStatus"] = "----" else data["exteriorStatus"] = exterior_airlock.density ? "closed" : "open" - var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() + var/obj/machinery/atmospherics/components/binary/dp_vent_pump/pump = pump_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) switch (pump?.pump_direction) if (null) data["pumpStatus"] = "----" @@ -275,7 +275,7 @@ /// Returns the pressure over the pump, or null if it is deleted // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/airlock_controller/proc/sensor_pressure() - var/obj/machinery/airlock_sensor/sensor = sensor_ref?.resolve() + var/obj/machinery/airlock_sensor/sensor = sensor_ref?.resolve() // VOIDCREW EDIT: shuttle airlock integration: tolerate missing linked devices while cycling ship airlocks (voidcrew/modules/shuttle) if (!isnull(sensor) && !sensor.on) return last_pressure diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index a24f81a001b..de50628a900 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -422,8 +422,10 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) return PROCESS_KILL /obj/machinery/status_display/evac/receive_signal(datum/signal/signal) + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship if(signal.data["voidcrew_net"] && signal.data["voidcrew_net"] != voidcrew_local_comms_net(src)) return + // VOIDCREW EDIT END switch(signal.data["command"]) if("blank") current_mode = SD_BLANK @@ -466,16 +468,18 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32) /// Changes only when we are in 'alert' mode ([SD_PICTURE] and one of the alert's icon state already set) /obj/machinery/status_display/evac/proc/on_sec_level_change(datum/source, new_level) SIGNAL_HANDLER + // VOIDCREW EDIT START - comms: keep announcements, alert state and status displays local to the communicating ship var/obj/docking_port/mobile/ship = voidcrew_communications_ship(src) if(ship && source != ship) return + // VOIDCREW EDIT END if(current_mode != SD_PICTURE) return if(!(current_picture in SSsecurity_level.alert_level_icons)) return var/datum/security_level/alert_level = SSsecurity_level.available_levels[SSsecurity_level.number_level_to_text(new_level)] - last_picture = alert_level.status_display_icon_state + last_picture = alert_level.status_display_icon_state // VOIDCREW EDIT: comms: keep announcements, alert state and status displays local to the communicating ship set_picture(alert_level.status_display_icon_state) /// Supply display which shows the status of the supply shuttle. diff --git a/code/game/movable_luminosity.dm b/code/game/movable_luminosity.dm index 7a6eaddafd9..8995ea7d7b0 100644 --- a/code/game/movable_luminosity.dm +++ b/code/game/movable_luminosity.dm @@ -10,8 +10,6 @@ luminosity -= affecting_dynamic_lumi affecting_dynamic_lumi = highest luminosity += affecting_dynamic_lumi - - ///Helper to change several lighting overlay settings. /atom/movable/proc/set_light_range_power_color(range, power, color) set_light_range(range) diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index a24e2169f38..c0cdf4cd84e 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -21,7 +21,7 @@ name = e_name if(desc_override) desc = "[desc_override]" - else if(desc == initial(desc)) + else if(desc == initial(desc)) // VOIDCREW EDIT: ship_upgrades: preserve descriptions supplied by mapped decals // Preserve descriptions supplied by maps before initialization. desc = "A [name] vandalizing the station." if(alt_icon) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index afb9674e274..ac6cc0eb7f9 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1198,7 +1198,7 @@ remove_filter(HOVER_OUTLINE_FILTER) //get rid of the hover effect in case the mouse exit isn't called if someone drags and drops an item and somthing goes wrong /obj/item/MouseExited() - . = ..() + . = ..() // VOIDCREW EDIT: screentip hover integration: clear departed hovers and reject stale deferred text (voidcrew/edits/screentip_hover.dm) deltimer(tip_timer) //delete any in-progress timer if the mouse is moved off the item before it finishes closeToolTip(usr) remove_filter(HOVER_OUTLINE_FILTER) diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 66c55d13a52..219d94dadd3 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -96,7 +96,7 @@ // VOIDCREW EDIT: the barometer reads the weather site standing under it, not the // z-level - several places can share a level and each hold its own storm cooldown. var/next_hit = SSweather.next_hit_timeleft_for_turf(T) - var/fixed = isnull(next_hit) ? -1 : next_hit + var/fixed = isnull(next_hit) ? -1 : next_hit // VOIDCREW EDIT: overmap weather: read the barometer cooldown for this encounter if(fixed < 0) to_chat(user, span_warning("[src]'s barometer function was unable to trace any weather patterns.")) else diff --git a/code/game/objects/items/devices/scanners/t_scanner.dm b/code/game/objects/items/devices/scanners/t_scanner.dm index a57884042db..39aa4dcdb58 100644 --- a/code/game/objects/items/devices/scanners/t_scanner.dm +++ b/code/game/objects/items/devices/scanners/t_scanner.dm @@ -60,7 +60,7 @@ if(isnull(centre)) centre = viewer var/list/t_ray_images = list() - for(var/obj/O in orange(distance, centre) ) + for(var/obj/O in orange(distance, centre) ) // VOIDCREW EDIT: shuttle construction: scan around the remote drone while retaining the handheld default if(HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) var/image/I = new(loc = get_turf(O)) var/mutable_appearance/MA = new(O) diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index bab0cfa7270..6a9af8a2424 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -287,7 +287,7 @@ var/obj/effect/constructing_effect/rcd_effect = new(get_turf(target), delay, rcd_results["[RCD_DESIGN_MODE]"], construction_upgrades) //resource & structure placement sanity checks before & after delay along with beam effects - if(!check_rcd_resources(rcd_results, user) || !can_place(target, rcd_results, user)) + if(!check_rcd_resources(rcd_results, user) || !can_place(target, rcd_results, user)) // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) qdel(rcd_effect) return FALSE var/beam @@ -301,15 +301,15 @@ return FALSE if (QDELETED(rcd_effect)) return FALSE - if(!check_rcd_resources(rcd_results, user) || !can_place(target, rcd_results, user)) + if(!check_rcd_resources(rcd_results, user) || !can_place(target, rcd_results, user)) // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) qdel(rcd_effect) return FALSE - if(!use_rcd_resources(rcd_results, user)) + if(!use_rcd_resources(rcd_results, user)) // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) qdel(rcd_effect) return FALSE activate() - if(!apply_rcd_action(target, user, rcd_results)) + if(!apply_rcd_action(target, user, rcd_results)) // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) qdel(rcd_effect) return FALSE playsound(loc, 'sound/machines/click.ogg', 50, TRUE) @@ -339,9 +339,9 @@ for(var/key in electronics_data) data[key] = electronics_data[key] - var/list/design_tree = get_rcd_designs() + var/list/design_tree = get_rcd_designs() // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) data["root_categories"] = list() - for(var/category in design_tree) + for(var/category in design_tree) // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) data["root_categories"] += category data["selected_root"] = root_category @@ -390,7 +390,7 @@ switch(action) if("root_category") var/new_root = params["root_category"] - if(get_rcd_designs()[new_root] != null) //is a valid category + if(get_rcd_designs()[new_root] != null) //is a valid category // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) root_category = new_root update_static_data_for_all_viewers() @@ -398,7 +398,7 @@ //read and validate params from UI var/category_name = params["category"] var/index = params["index"] - var/list/root = get_rcd_designs()[root_category] + var/list/root = get_rcd_designs()[root_category] // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/rcd/RCD.dm) if(root == null) //not a valid root return TRUE var/list/category = root[category_name] diff --git a/code/game/objects/items/rcd/RHD.dm b/code/game/objects/items/rcd/RHD.dm index 67170e51b92..870b5c2af48 100644 --- a/code/game/objects/items/rcd/RHD.dm +++ b/code/game/objects/items/rcd/RHD.dm @@ -70,7 +70,7 @@ ///used for examining the RCD and for its UI // VOIDCREW EDIT START - PR #283: Allow RCD silo access outside ships and across z-levels. /obj/item/construction/proc/get_silo_iron() - if(silo_link && silo_mats.mat_container && silo_mats.check_z_level() && !silo_mats.on_hold()) + if(silo_link && silo_mats.mat_container && silo_mats.check_z_level() && !silo_mats.on_hold()) // VOIDCREW EDIT: ship material silo integration: check the linked silo scope before reading or spending resources (voidcrew/edits/machinery/materials_market.dm) return silo_mats.mat_container.get_material_amount(/datum/material/iron) / SILO_USE_AMOUNT return 0 @@ -196,8 +196,10 @@ if(!silo_mats.mat_container) if(user) balloon_alert(user, "no silo detected!") + // VOIDCREW EDIT START - ship material silo integration: check the linked silo scope before reading or spending resources (voidcrew/edits/machinery/materials_market.dm) return FALSE if(!silo_mats.can_use_resource(user_data = ID_DATA(user))) + // VOIDCREW EDIT END return FALSE if(!silo_mats.mat_container.has_enough_of_material(/datum/material/iron, amount * SILO_USE_AMOUNT)) diff --git a/code/game/objects/items/rcd/RPD.dm b/code/game/objects/items/rcd/RPD.dm index 2736cede5ab..b065c3e4a30 100644 --- a/code/game/objects/items/rcd/RPD.dm +++ b/code/game/objects/items/rcd/RPD.dm @@ -294,7 +294,7 @@ return if(istype(attack_target, /obj/item/rpd_upgrade)) - return install_upgrade(attack_target, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + return install_upgrade(attack_target, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING // VOIDCREW EDIT: construction tools: share disk installation between both item interaction directions (voidcrew/edits/game/objects/items/rcd/RPD.dm) //So that changing the menu settings doesn't affect the pipes already being built. var/queued_pipe_type = recipe.id diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index a75e8ca5ae4..a6f0bdd9656 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -183,8 +183,10 @@ if(!use(1) || !repeating || amount <= 0) var/atom/alert_loc = QDELETED(src) ? user : src alert_loc.balloon_alert(user, repeating ? "all used up!" : "treated [parse_zone(healed_zone)]") + // VOIDCREW EDIT START - Voidcrew medical integration: silent treatments must not pass a null healing sound (voidcrew/edits) if(heal_end_sound) playsound(patient, heal_end_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE) + // VOIDCREW EDIT END return if(heal_continuous_sound && (continuous || !silent)) playsound(patient, heal_continuous_sound, 75, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 7aeba6f7dc8..ce8728e22d9 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -642,8 +642,10 @@ return FALSE if(SEND_SIGNAL(src, COMSIG_STACK_CAN_MERGE, check, inhand) & CANCEL_STACK_MERGE) return FALSE + // VOIDCREW EDIT START - antag_ruins: let trial loan components veto stack merges and follow splits if(SEND_SIGNAL(check, COMSIG_STACK_CAN_RECEIVE_MERGE, src, inhand) & CANCEL_STACK_MERGE) return FALSE + // VOIDCREW EDIT END return TRUE /** @@ -732,7 +734,7 @@ return null var/obj/item/stack/new_stack = new type(null, amount, FALSE, mats_per_unit) new_stack.copy_evidences(src) - SEND_SIGNAL(src, COMSIG_STACK_SPLIT, new_stack) + SEND_SIGNAL(src, COMSIG_STACK_SPLIT, new_stack) // VOIDCREW EDIT: antag_ruins: let trial loan components veto stack merges and follow splits loc.atom_storage?.refresh_views() is_zero_amount(delete_if_zero = TRUE) return new_stack diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index b68245b0a52..01e77484309 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -79,7 +79,7 @@ return // Close open air tank if it got dropped by its current user. if (loc != breathing_mob) - breathing_mob.cutoff_internals("tank dropped by [user], now in [loc] ([loc?.type])") + breathing_mob.cutoff_internals("tank dropped by [user], now in [loc] ([loc?.type])") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) /// Closes the tank if given to another mob while open. // VOIDCREW EDIT END @@ -88,7 +88,7 @@ . = ..() // Close open air tank if it was equipped by a mob other than the current user. if (breathing_mob && (user != breathing_mob)) - breathing_mob.cutoff_internals("tank equipped to slot [slot] by [user || "NULL USER"]") + breathing_mob.cutoff_internals("tank equipped to slot [slot] by [user || "NULL USER"]") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) /// Called by carbons after they connect the tank to their breathing apparatus. // VOIDCREW EDIT END diff --git a/code/game/objects/items/tools/painter/decal_painter.dm b/code/game/objects/items/tools/painter/decal_painter.dm index b7920b37918..508d0b1556f 100644 --- a/code/game/objects/items/tools/painter/decal_painter.dm +++ b/code/game/objects/items/tools/painter/decal_painter.dm @@ -39,7 +39,7 @@ */ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/airlock_painter/decal/proc/paint_floor(turf/open/floor/target) - var/list/decal_data = get_decal_data() + var/list/decal_data = get_decal_data() // VOIDCREW EDIT: shuttle construction: route captured designs and remote building through construction hooks (voidcrew/edits/game/objects/items/tools/painter/decal_painter.dm) target.AddElement( \ /datum/element/decal, \ diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 63566af6115..540a850448e 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -195,7 +195,7 @@ SHOULD_NOT_OVERRIDE(TRUE) // VOIDCREW: capture destruction before the fixture's configuration is discarded. - record_ship_fixture_damage(src, disassembled) + record_ship_fixture_damage(src, disassembled) // VOIDCREW EDIT: ship_repairs: distinguish damaged fixtures from deliberate dismantling //allow objects to deconstruct themselves handle_deconstruct(disassembled) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 077e27e22cc..aaf263f33eb 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -619,7 +619,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) if(length(req_one_access)) electronics.one_access = TRUE electronics.accesses = req_one_access - else if(length(req_access)) + else if(length(req_access)) // VOIDCREW EDIT: ship access integration: preserve empty electronics access lists for AccessConfig (voidcrew/edits/ship_access.dm) electronics.accesses = req_access if(card_reader_installed) new /obj/item/stock_parts/card_reader(drop_location()) @@ -780,7 +780,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) if(length(req_one_access)) airlock_electronics.one_access = TRUE airlock_electronics.accesses = req_one_access - else if(length(req_access)) + else if(length(req_access)) // VOIDCREW EDIT: ship access integration: preserve empty electronics access lists for AccessConfig (voidcrew/edits/ship_access.dm) airlock_electronics.accesses = req_access req_access = list() diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index faacdb8f970..1665f7b8f07 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -114,13 +114,13 @@ //checks if its a valid build direction //not user.dir: a remotely driven RCD builds where its drone is looking, not where //the body credited with the build happens to be pointing (see rcd_build_dir()) - var/build_dir = the_rcd.rcd_build_dir(user) + var/build_dir = the_rcd.rcd_build_dir(user) // VOIDCREW EDIT: shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) if(!initial(window_path.fulltile)) - if(!valid_build_direction(loc, build_dir, is_fulltile = FALSE)) + if(!valid_build_direction(loc, build_dir, is_fulltile = FALSE)) // VOIDCREW EDIT: shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) balloon_alert(user, "window already here!") return FALSE - var/obj/structure/window/WD = new window_path(T, build_dir) + var/obj/structure/window/WD = new window_path(T, build_dir) // VOIDCREW EDIT: shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) WD.set_anchored(TRUE) return TRUE return FALSE diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index 0341b91d7c9..d2482f52a4c 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -143,13 +143,13 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/structure/lattice/catwalk/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data) if(rcd_data["[RCD_DESIGN_MODE]"] == RCD_DECONSTRUCT) +// VOIDCREW EDIT END var/turf/turf = loc for(var/obj/structure/cable/cable_coil in turf) cable_coil.deconstruct() qdel(src) return TRUE -// VOIDCREW EDIT END /obj/structure/lattice/catwalk/mining name = "reinforced catwalk" desc = "A heavily reinforced catwalk used to build bridges in hostile environments. It doesn't look like anything could make this budge." diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index 231155f0c2e..0a51fdfa612 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -410,10 +410,12 @@ // empty if SSore_generation's roundstart round-robin ran out of pool before it got to // this one (it breaks on stallbreaker), so roll a breakdown rather than produce a dud. if(!length(mineral_breakdown) && !unique_vent) + // VOIDCREW EDIT START - overmap: mid-round planet vents need a mineral breakdown before producing boulders generate_mineral_breakdown() generate_description() if(!length(mineral_breakdown)) return + // VOIDCREW EDIT END //produce the boulder var/obj/item/boulder/new_rock diff --git a/code/game/objects/structures/mystery_box.dm b/code/game/objects/structures/mystery_box.dm index 57ccd72960f..b91eb68fae1 100644 --- a/code/game/objects/structures/mystery_box.dm +++ b/code/game/objects/structures/mystery_box.dm @@ -18,14 +18,6 @@ /// How long after the box closes until it can go again #define MBOX_DURATION_STANDBY (2.7 SECONDS) -/// How many spins one crew gets out of a treasure chest before it stops opening for them. -/// Pooled across the crew rather than handed out per person: a full ship would otherwise -/// strip every use out of a chest on its own, while a two-man crew could never spend more -/// than a fraction of them. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -#define TREASURE_CHEST_CREW_SPINS 6 -// VOIDCREW EDIT END - GLOBAL_LIST_INIT(mystery_box_guns, list( /obj/item/gun/energy/recharge/ebow/large, /obj/item/gun/energy/e_gun, @@ -303,32 +295,9 @@ GLOBAL_LIST_INIT(mystery_fishing, list( /obj/structure/mystery_box/fishing/generate_valid_types() valid_types = GLOB.mystery_fishing -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/obj/structure/mystery_box/fishing/examine(mob/user) - . = ..() - var/datum/weakref/pool = get_spin_pool(user) - if(!pool) - return - var/spins_left = max(TREASURE_CHEST_CREW_SPINS - LAZYACCESS(spins_by_crew, pool), 0) - if(!spins_left) - . += span_warning("It has nothing left for your crew.") - return - . += span_notice("It has [spins_left] spin[spins_left == 1 ? "" : "s"] left for your crew.") - -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/obj/structure/mystery_box/fishing/activate(mob/living/user) - var/datum/weakref/pool = get_spin_pool(user) - if(pool && LAZYACCESS(spins_by_crew, pool) >= TREASURE_CHEST_CREW_SPINS) - to_chat(user, span_warning("[src] refuses to open for your crew anymore. Perhaps you should hand it off to another one...")) - return - . = ..() - if(pool) - LAZYINITLIST(spins_by_crew) - spins_by_crew[pool] += 1 +// VOIDCREW EDIT REMOVAL: Crew-pooled activation and examination live in voidcrew/edits/game/objects/structures/mystery_box.dm. /// This represents the item that comes out of the box and is constantly changing before the box finishes deciding. Can probably be just an /atom or /movable. -// VOIDCREW EDIT END /obj/effect/abstract/mystery_box_item name = "???" desc = "Who knows what it'll be??" @@ -412,5 +381,4 @@ GLOBAL_LIST_INIT(mystery_fishing, list( #undef MBOX_DURATION_PRESENTING #undef MBOX_DURATION_EXPIRING #undef MBOX_DURATION_STANDBY -#undef TREASURE_CHEST_CREW_SPINS // VOIDCREW EDIT END diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm index 7a6fd613997..319d02d6712 100644 --- a/code/game/objects/structures/shower.dm +++ b/code/game/objects/structures/shower.dm @@ -10,7 +10,7 @@ #define SHOWER_EXPOSURE_MULTIPLIER 2 // Showers effectively double exposed reagents /// How long we run in TIMED mode #define SHOWER_TIMED_LENGTH (15 SECONDS) -// VOIDCREW EDIT: reserve a dry shower must rebuild before it auto-resumes. +// VOIDCREW EDIT START: reserve a dry shower must rebuild before it auto-resumes. - Voidcrew shower integration: refill to a working reserve before automatic restart (voidcrew/edits) // Without it, a shower left switched on re-fires the moment it recollects one // spray's worth (5u) and dumps it the same tick, so it never visibly recovers. // 50u = 10 seconds of spray. Invented/unplaytested value. @@ -326,7 +326,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/shower, (-16)) // Don't turn back on. if(mode != SHOWER_MODE_FOREVER) intended_on = FALSE - // VOIDCREW EDIT: an off-but-wanted-on shower waits for a working reserve + // VOIDCREW EDIT START: an off-but-wanted-on shower waits for a working reserve - Voidcrew shower integration: refill to a working reserve before automatic restart (voidcrew/edits) // (SHOWER_RESTART_VOLUME) instead of firing one spray per refill cycle. // Deliberate clicks (interact) still start it at one spray's worth. else if(!(intended_on && !actually_on && reagents.total_volume < SHOWER_RESTART_VOLUME)) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 9947723d565..259de76fda8 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -1021,7 +1021,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/structure/table/optable/make_climbable() - AddComponent(/datum/component/climb_walkable) + AddComponent(/datum/component/climb_walkable) // VOIDCREW EDIT: movable fixtures integration: make operating tables climbable (voidcrew/edits/objects/structures/movable_fixtures.dm) AddElement(/datum/element/elevation, pixel_shift = 12) ///Align the mob with the table when buckled. diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index b294a390066..282d4710fb6 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -256,7 +256,7 @@ playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) to_chat(user, span_notice("You successfully disassemble [src].")) // VOIDCREW: this tool path deletes directly, bypassing deconstruct(TRUE). - record_ship_fixture_damage(src, disassembled = TRUE) + record_ship_fixture_damage(src, disassembled = TRUE) // VOIDCREW EDIT: ship_repairs: distinguish damaged fixtures from deliberate dismantling qdel(src) return ITEM_INTERACT_SUCCESS diff --git a/code/game/shuttle_engines.dm b/code/game/shuttle_engines.dm index d5d5a6fe2a4..df3c8d5ba3e 100644 --- a/code/game/shuttle_engines.dm +++ b/code/game/shuttle_engines.dm @@ -6,7 +6,7 @@ /// Reference mass for fuel consumption scaling. Ships at this mass use base fuel amounts. /// Ships heavier than this use proportionally more fuel per burn. -#define REFERENCE_SHIP_MASS 100 +#define REFERENCE_SHIP_MASS 100 // VOIDCREW EDIT: shuttle: retain the reference ship mass used by fuel consumption scaling /obj/machinery/power/shuttle_engine name = "engine" @@ -41,7 +41,7 @@ // 30% armour = 21) needs ~24 swings per engine, where the same axe disables a laser // turret in 5. Bullet/laser stay at 10 so ship guns remain the fast way to kill engines. /datum/armor/power_shuttle_engine - melee = 30 + melee = 30 // VOIDCREW EDIT: shuttle: retain the reference ship mass used by fuel consumption scaling bullet = 10 laser = 10 fire = 50 diff --git a/code/game/sound/sound.dm b/code/game/sound/sound.dm index 167ecb828c0..60452addb21 100644 --- a/code/game/sound/sound.dm +++ b/code/game/sound/sound.dm @@ -69,7 +69,7 @@ if(get_dist(listening_ghost, turf_source) <= audible_distance) listeners += listening_ghost - // VOIDCREW EDIT ADDITION: packed-level containment. + // VOIDCREW EDIT ADDITION START: packed-level containment. - overmap: contain observers and effects within their packed encounter // ignore_walls defaults to TRUE, so the default sound path in the whole game is // get_hearers_in_range() - the one hearer helper with no opacity filter and no LOS // raycast. At vol 100 that reaches 14 tiles, and two tenants of a packed z-level are @@ -149,7 +149,7 @@ //Atmosphere affects sound var/pressure_factor = 1 var/datum/gas_mixture/hearer_env = turf_loc.return_air_readonly() // VOIDCREW EDIT: read only; must not materialize a planetary turf's air - var/datum/gas_mixture/source_env = turf_source.return_air_readonly() + var/datum/gas_mixture/source_env = turf_source.return_air_readonly() // VOIDCREW EDIT: planetary shared air: observations must not materialize planetary gas (voidcrew/edits/planetary_shared_air.dm) if(hearer_env && source_env) var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 72805a85644..79972becf83 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -56,7 +56,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( if(null) return if(/turf/baseturf_bottom) - // VOIDCREW EDIT: kept in lockstep with the copy in voidcrew/edits/turf.dm, which + // VOIDCREW EDIT START: kept in lockstep with the copy in voidcrew/edits/turf.dm, which - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) // is the body that actually runs (it is the outermost link of the duplicate- // definition chain and never calls ..()). The map FOOTPRINT under the turf is // asked before the z-level: a level holds up to four planets of different biomes @@ -166,7 +166,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( if(SSlighting.initialized) // Space tiles should never have lighting objects if(!space_lit) - // VOIDCREW EDIT: kept in lockstep with the copy in voidcrew/edits/turf.dm, which is + // VOIDCREW EDIT START: kept in lockstep with the copy in voidcrew/edits/turf.dm, which is - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) // the body that actually runs (it is the outermost link of the duplicate-definition // chain and never calls ..()). Two rules composed here: // 1. The AREA gate that SSlighting.create_all_lighting_objects() and @@ -234,7 +234,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( for(var/turf/open/space/space_tile in RANGE_TURFS(1, src)) space_tile.enable_starlight() - // VOIDCREW EDIT: ambient bleed, the same three cases the starlight branches above + // VOIDCREW EDIT START: ambient bleed, the same three cases the starlight branches above - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) // handle, generalised from "space turf" to "turf in an area that lights it wholesale". // Our own capability can have flipped (we became or stopped being a cordon or a space // tile), and we can have started or stopped being something for the base-lit ground @@ -279,8 +279,10 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( // VOIDCREW EDIT: a new planetary turf that came up on the very same shared mix we had // already holds this air; anything else takes a private mixture before the write. if(new_turf.air != old_air) + // VOIDCREW EDIT START - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) var/datum/gas_mixture/new_air = new_turf.materialize_planet_air() new_air.copy_from(stashed_air) + // VOIDCREW EDIT END new_turf.excited = stashed_state new_turf.excited_group = stashed_group #ifdef VISUALIZE_ACTIVE_TURFS @@ -316,11 +318,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( // survives - which is how dismantling a wall dumps a full tile of breathable air into // whatever the wall was sealing. Build the adjacency now and throw the invented gas away, // so we take a share of what our neighbours actually have instead. + // VOIDCREW EDIT START - planetary atmos integration: assimilate surrounding gas after opening a closed turf (voidcrew/edits/planetary_shared_air.dm) var/sheered_from_closed = ispath(oldType, /turf/closed) && !blocks_air && !planetary_atmos && !(flags & CHANGETURF_IGNORE_AIR) if(sheered_from_closed) flags |= CHANGETURF_RECALC_ADJACENT ..(flags, oldType) + // VOIDCREW EDIT END RemoveLattice() + // VOIDCREW EDIT START - planetary atmos integration: assimilate surrounding gas after opening a closed turf (voidcrew/edits/planetary_shared_air.dm) if(sheered_from_closed) // Temperature is deliberately left alone. An emptied turf mix still carries // HEAT_CAPACITY_VACUUM into Assimilate_Air's average, and TCMB there would @@ -329,6 +334,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( else if(flags & (CHANGETURF_IGNORE_AIR | CHANGETURF_INHERIT_AIR)) return Assimilate_Air() + // VOIDCREW EDIT END //////Assimilate Air////// // VOIDCREW EDIT END @@ -338,9 +344,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( return //Stolen blatently from self_breakdown - var/list/turf_list = atmos_adjacent_turfs + src + var/list/turf_list = atmos_adjacent_turfs + src // VOIDCREW EDIT: planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) - // VOIDCREW EDIT: turfs still on the shared planetary mix. When every turf here is on the + // VOIDCREW EDIT START: turfs still on the shared planetary mix. When every turf here is on the - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) // SAME shared mix the average is that mix and there is nothing to write; otherwise each // of them needs a private mixture before the copy_from() below. if(has_shared_planet_air()) @@ -357,6 +363,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( var/datum/gas_mixture/total = new//Holders to assimilate air from nearby turfs var/list/total_gases = total.gases + // VOIDCREW EDIT REMOVAL - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) var/turflen = turf_list.len var/energy = 0 var/heat_cap = 0 diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index 6adff51030f..9d198d1983c 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -67,6 +67,7 @@ return var/obj/item/held_item = bumping.get_active_held_item() + // VOIDCREW EDIT START - Voidcrew mining integration: use and monitor a held mining tool without changing the active hand (voidcrew/edits) var/obj/item/mining_tool = held_item // Prefer the selected tool, then a mining tool held in another hand. Do not // switch hands or send a click with the active item, which might be a weapon. @@ -75,7 +76,9 @@ if(mining_tool) attackby(mining_tool, bumping) else if(!held_item) // Preserve empty-hand bump digging for snow and mining arms. + // VOIDCREW EDIT END INVOKE_ASYNC(bumping, TYPE_PROC_REF(/mob, ClickOn), src) +// VOIDCREW EDIT REMOVAL - Voidcrew mining integration: use and monitor a held mining tool without changing the active hand (voidcrew/edits) // VOIDCREW EDIT END /turf/closed/mineral/proc/Spread_Vein() @@ -187,10 +190,12 @@ // do_after already watches the active hand. An off-hand tool needs its own // check so dropping or stowing it also interrupts mining. + // VOIDCREW EDIT START - Voidcrew mining integration: use and monitor a held mining tool without changing the active hand (voidcrew/edits) var/datum/callback/held_tool_check if(I != user.get_active_held_item() && user.is_holding(I)) held_tool_check = CALLBACK(user, TYPE_PROC_REF(/mob, is_holding), I) if(!I.use_tool(src, user, tool_mine_speed, volume=50, extra_checks=held_tool_check)) + // VOIDCREW EDIT END TIMER_COOLDOWN_END(src, REF(user)) //if we fail we can start again immediately return if(ismineralturf(src)) @@ -445,8 +450,10 @@ // VOIDCREW EDIT: mined walls must yield the FROZEN breathable floor, the upstream icemoon // turfs are planetary ICEMOON, and every dug tile on a FROZEN planet churns atmos forever turf_type = /turf/open/misc/asteroid/snow/icemoon/breathable + // VOIDCREW EDIT START - overmap planets: mined snow walls retain the breathable frozen atmosphere baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable initial_gas_mix = FROZEN_ATMOS + // VOIDCREW EDIT END weak_turf = TRUE proximity_based = TRUE @@ -542,8 +549,10 @@ canSmoothWith = SMOOTH_GROUP_CLOSED_TURFS defer_change = TRUE turf_type = /turf/open/misc/asteroid/snow/icemoon/breathable // VOIDCREW EDIT (see random/snow) + // VOIDCREW EDIT START - overmap planets: mined snow walls retain the breathable frozen atmosphere baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable initial_gas_mix = FROZEN_ATMOS + // VOIDCREW EDIT END defer_change = TRUE /turf/closed/mineral/random/labormineral/ice/mineral_chances() @@ -731,14 +740,16 @@ /turf/closed/mineral/snowmountain/icemoon // VOIDCREW EDIT: dig into FROZEN breathable floor, not planetary-ICEMOON (churns vs FROZEN planets) turf_type = /turf/open/misc/asteroid/snow/icemoon/breathable + // VOIDCREW EDIT START - overmap planets: mined snow walls retain the breathable frozen atmosphere baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable initial_gas_mix = FROZEN_ATMOS + // VOIDCREW EDIT END /// This snowy mountain will never be scraped away for any reason what so ever. /turf/closed/mineral/snowmountain/icemoon/unscrapeable turf_flags = IS_SOLID | NO_CLEARING turf_type = /turf/open/misc/asteroid/snow/icemoon/breathable // VOIDCREW EDIT (see parent) - baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable + baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable // VOIDCREW EDIT: overmap planets: mined snow walls retain the breathable frozen atmosphere /turf/closed/mineral/snowmountain/cavern name = "ice cavern rock" @@ -752,8 +763,10 @@ /turf/closed/mineral/snowmountain/cavern/icemoon // VOIDCREW EDIT: snow/ice/icemoon is planetary ICEMOON, dig into FROZEN breathable instead baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable + // VOIDCREW EDIT START - overmap planets: mined snow walls retain the breathable frozen atmosphere turf_type = /turf/open/misc/asteroid/snow/icemoon/breathable initial_gas_mix = FROZEN_ATMOS + // VOIDCREW EDIT END //For when you want genuine, real snowy mountainside in your kitchen's cold room. /turf/closed/mineral/snowmountain/coldroom @@ -912,8 +925,10 @@ /turf/closed/mineral/gibtonite/ice/icemoon // VOIDCREW EDIT: snow/ice/icemoon is planetary ICEMOON, dig into FROZEN breathable instead turf_type = /turf/open/misc/asteroid/snow/icemoon/breathable + // VOIDCREW EDIT START - overmap planets: mined snow walls retain the breathable frozen atmosphere baseturfs = /turf/open/misc/asteroid/snow/icemoon/breathable initial_gas_mix = FROZEN_ATMOS + // VOIDCREW EDIT END /turf/closed/mineral/strong name = "Very strong rock" diff --git a/code/game/turfs/closed/wall/misc_walls.dm b/code/game/turfs/closed/wall/misc_walls.dm index 7446b6166e0..2ff18f09ada 100644 --- a/code/game/turfs/closed/wall/misc_walls.dm +++ b/code/game/turfs/closed/wall/misc_walls.dm @@ -63,7 +63,7 @@ //SDMM supports colors, this is simply for easier mapping //and should be removed on initialize color = MAP_SWITCH(null, COLOR_ORANGE_BROWN) - base_decon_state = "rusty_wall" + base_decon_state = "rusty_wall" // VOIDCREW EDIT: Voidcrew wall integration: use the rusty wall deconstruction icon state (voidcrew/edits) // VOIDCREW EDIT END /turf/closed/wall/r_wall/rust/Initialize(mapload) diff --git a/code/game/turfs/closed/wall/reinf_walls.dm b/code/game/turfs/closed/wall/reinf_walls.dm index 53510067a3c..9295f56eaf0 100644 --- a/code/game/turfs/closed/wall/reinf_walls.dm +++ b/code/game/turfs/closed/wall/reinf_walls.dm @@ -173,7 +173,7 @@ if(!istype(src, /turf/closed/wall/r_wall) || d_state != SHEATH) return TRUE to_chat(user, span_notice("You pry off the outer sheath.")) - dismantle_wall(disassembled = TRUE) + dismantle_wall(disassembled = TRUE) // VOIDCREW EDIT: ship_repairs: distinguish damaged fixtures from deliberate dismantling return TRUE if(W.tool_behaviour == TOOL_WELDER) diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index 8e5ad61bd09..baadba18317 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -38,7 +38,7 @@ . = ..() if(!can_engrave) ADD_TRAIT(src, TRAIT_NOT_ENGRAVABLE, INNATE_TRAIT) - // VOIDCREW EDIT CHANGE: never register ALLOCATOR-DEALT ground - original was + // VOIDCREW EDIT CHANGE START: never register ALLOCATOR-DEALT ground - original was - overmap: contain observers and effects within their packed encounter // `if(is_station_level(z))`. is_station_level() means "any z with a hull on it" in this // fork, so a ruin stamped onto a packed level while a neighbour has a ship docked put // every wall it owns into GLOB.station_turfs; the removal below is skipped because the @@ -76,7 +76,7 @@ dismantle_wall(TRUE, FALSE) /turf/closed/wall/Destroy() - // VOIDCREW EDIT CHANGE: symmetric with the guard in Initialize() - original was + // VOIDCREW EDIT CHANGE START: symmetric with the guard in Initialize() - original was - overmap: contain observers and effects within their packed encounter // `if(is_station_level(z))`, which is a DIFFERENT condition by the time a turf dies // (the level's station flag is refcounted off the hulls standing on it, and teardown // runs after the last one has left), so the entry survived its own turf. @@ -107,6 +107,7 @@ if(repair_controller) repair_controller.forget_repair_record(repair_controller.repair_coordinate_key(src)) repair_controller.repair_applying = TRUE +// VOIDCREW EDIT END if(devastated) devastate_wall() else @@ -124,10 +125,11 @@ else ScrapeAway() QUEUE_SMOOTH_NEIGHBORS(src) + // VOIDCREW EDIT START - ship_repairs: deliberate remodeling supersedes pending repairs if(repair_controller) repair_controller.repair_applying = was_repairing + // VOIDCREW EDIT END -// VOIDCREW EDIT END /turf/closed/wall/proc/break_wall() new sheet_type(src, sheet_amount) if(girder_type) @@ -274,7 +276,7 @@ if(I.use_tool(src, user, slicing_duration, volume=100)) if(iswallturf(src)) to_chat(user, span_notice("You remove the outer plating.")) - dismantle_wall(disassembled = TRUE) + dismantle_wall(disassembled = TRUE) // VOIDCREW EDIT: ship_repairs: deliberate remodeling supersedes pending repairs return TRUE return FALSE diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index f0276ccc5bd..5fa90a341a0 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -339,7 +339,7 @@ /turf/open/TakeTemperature(temp) var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix - our_air.temperature += temp + our_air.temperature += temp // VOIDCREW EDIT: planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) air_update_turf(FALSE, FALSE) /turf/open/proc/freeze_turf() diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index 3c370edb571..1b13a274d9d 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -31,7 +31,7 @@ if(mapload && prob(33)) MakeDirty() - // VOIDCREW EDIT CHANGE: never register ALLOCATOR-DEALT ground - original was + // VOIDCREW EDIT CHANGE START: never register ALLOCATOR-DEALT ground - original was - overmap: contain observers and effects within their packed encounter // `if(is_station_level(z))`. See the matching comment on /turf/closed/wall/Initialize(). if(is_station_level(z) && !map_region_for_turf(src)) GLOB.station_turfs += src @@ -44,7 +44,7 @@ return list() /turf/open/floor/Destroy() - // VOIDCREW EDIT CHANGE: symmetric with the guard in Initialize() - original was + // VOIDCREW EDIT CHANGE START: symmetric with the guard in Initialize() - original was - overmap: contain observers and effects within their packed encounter // `if(is_station_level(z))`. See /turf/closed/wall/Destroy(). if(length(GLOB.station_turfs) && !map_region_for_turf(src)) GLOB.station_turfs -= src @@ -122,7 +122,7 @@ if(!ispath(path, /turf/open/floor)) return ..() var/old_dir = dir - // VOIDCREW EDIT ADDITION: when the map loader is the caller it has already queued the + // VOIDCREW EDIT ADDITION START: when the map loader is the caller it has already queued the - ship_upgrades: retain mapped floor directions when loading modules onto hull plating // mapped vars - dir included - for /atom/New() to apply to the turf ..() creates. // Restoring old_dir below would then stomp that with whatever floor sat here before. // Ship upgrade modules load onto hull plating, every tile of which faces SOUTH, so @@ -172,6 +172,7 @@ // VOIDCREW EDIT START - PR #395: Keep mapped floor dir when a ship module loads over hull plating. /turf/open/floor/proc/remove_tile(mob/user, silent = FALSE, make_tile = TRUE, force_plating) // VOIDCREW: taking up tiles with a tool is deliberate remodeling. + // VOIDCREW EDIT START - ship_repairs: deliberate remodeling supersedes pending repairs var/obj/machinery/computer/camera_advanced/base_construction/ship/repair_controller if(user) repair_controller = SSship_repairs.area_controllers[get_area(src)] @@ -179,6 +180,7 @@ if(repair_controller) repair_controller.forget_repair_record(repair_controller.repair_coordinate_key(src)) repair_controller.repair_applying = TRUE + // VOIDCREW EDIT END if(broken || burnt) broken = FALSE burnt = FALSE @@ -189,9 +191,11 @@ to_chat(user, span_notice("You remove the floor tile.")) if(make_tile) spawn_tile() + // VOIDCREW EDIT START - ship_repairs: deliberate remodeling supersedes pending repairs . = make_plating(force_plating) if(repair_controller) repair_controller.repair_applying = was_repairing + // VOIDCREW EDIT END // VOIDCREW EDIT END /turf/open/floor/proc/has_tile() @@ -313,11 +317,13 @@ if(!initial(window_path.fulltile)) //not user.dir: a remotely driven RCD builds where its drone is looking, not //where the body credited with the build happens to be pointing + // VOIDCREW EDIT START - shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) var/build_dir = the_rcd.rcd_build_dir(user) if(!valid_build_direction(src, build_dir, is_fulltile = FALSE)) + // VOIDCREW EDIT END balloon_alert(user, "window already here!") return FALSE - var/obj/structure/window/WD = new window_path(src, build_dir) + var/obj/structure/window/WD = new window_path(src, build_dir) // VOIDCREW EDIT: shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) WD.set_anchored(TRUE) return TRUE @@ -332,8 +338,10 @@ if(ispath(airlock_type, /obj/machinery/door/window)) //see the window branch above - the drone's facing, not the operator's + // VOIDCREW EDIT START - shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) var/build_dir = the_rcd.rcd_build_dir(user) if(!valid_build_direction(src, build_dir, is_fulltile = FALSE)) + // VOIDCREW EDIT END balloon_alert(user, "there's already a windoor!") return FALSE for(var/obj/machinery/door/door in src) @@ -342,7 +350,7 @@ balloon_alert(user, "there's already a door!") return FALSE //create the assembly and let it finish itself - var/obj/structure/windoor_assembly/assembly = new (src, build_dir) + var/obj/structure/windoor_assembly/assembly = new (src, build_dir) // VOIDCREW EDIT: shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) assembly.secure = ispath(airlock_type, /obj/machinery/door/window/brigdoor) assembly.electronics = the_rcd.airlock_electronics.create_copy(assembly) assembly.finish_door() @@ -386,7 +394,7 @@ ) if(is_path_in_list(locate_type, dir_types)) //see the window branch above - the drone's facing, not the operator's - design.setDir(the_rcd.rcd_build_dir(user)) + design.setDir(the_rcd.rcd_build_dir(user)) // VOIDCREW EDIT: shuttle construction: directional builds follow the remote drone (voidcrew/edits/game/objects/items/rcd/RCD.dm) return TRUE if(RCD_DECONSTRUCT) if(rcd_proof) diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm index 13b45230ca9..72fee097e84 100644 --- a/code/game/turfs/open/floor/fancy_floor.dm +++ b/code/game/turfs/open/floor/fancy_floor.dm @@ -513,7 +513,7 @@ // A FLOAT_LAYER decal would inherit that layer while sitting on the emissive plane, where it would draw above // every emissive blocker in the world and glow straight through mobs, items and walls. // emissive_appearance() remaps floor plane layers into the FLOOR_EMISSIVE band for this exact reason. - AddElement(/datum/element/decal, neon_icon || icon, neon_icon_state || base_icon_state, dir, EMISSIVE_PLANE, FLOOR_EMISSIVE_START_LAYER, emissive_alpha, GLOB.emissive_color, smoothing_junction) + AddElement(/datum/element/decal, neon_icon || icon, neon_icon_state || base_icon_state, dir, EMISSIVE_PLANE, FLOOR_EMISSIVE_START_LAYER, emissive_alpha, GLOB.emissive_color, smoothing_junction) // VOIDCREW EDIT: ship_upgrades lighting: floor emissives stay below blockers (voidcrew/edits/lighting.dm) // VOIDCREW EDIT END /turf/open/floor/carpet/neon/simple diff --git a/code/game/turfs/open/grass.dm b/code/game/turfs/open/grass.dm index 1d4e3fd7393..13ed112bc49 100644 --- a/code/game/turfs/open/grass.dm +++ b/code/game/turfs/open/grass.dm @@ -45,7 +45,7 @@ transform = translation icon = smooth_icon - // VOIDCREW EDIT CHANGE: never register ALLOCATOR-DEALT ground - original was + // VOIDCREW EDIT CHANGE START: never register ALLOCATOR-DEALT ground - original was - overmap: contain observers and effects within their packed encounter // `if(is_station_level(z))`. See the matching comment on /turf/closed/wall/Initialize(). // Grass is the worst offender of the three: it is planet ground, it is dealt out and // recycled on every planet build, and it had no Destroy() removal at all. diff --git a/code/game/turfs/open/river.dm b/code/game/turfs/open/river.dm index d50d7571342..3e4ac281ede 100644 --- a/code/game/turfs/open/river.dm +++ b/code/game/turfs/open/river.dm @@ -33,7 +33,7 @@ // /turf/proc/release_light_for_raw_swap() and voidcrew/mapping/rivers.dm, which fixed // the voidcrew copy of this generator for exactly this reason. if(SSlighting.initialized) - cur_turf.release_light_for_raw_swap() + cur_turf.release_light_for_raw_swap() // VOIDCREW EDIT: overmap river generation: release lighting before mid-round raw turf swaps (voidcrew/mapping/rivers.dm) cur_turf = new turf_type(cur_turf) var/turf/target_turf = get_turf(pick(river_nodes - waypoints)) if(!target_turf) @@ -66,7 +66,7 @@ // Workaround around ChangeTurf that's safe because of when this proc is called // VOIDCREW EDIT: see the identical guard above. if(SSlighting.initialized) - cur_turf.release_light_for_raw_swap() + cur_turf.release_light_for_raw_swap() // VOIDCREW EDIT: overmap river generation: release lighting before mid-round raw turf swaps (voidcrew/mapping/rivers.dm) var/turf/river_turf = new turf_type(cur_turf) river_turf.Spread(25, 11, whitelist_area) diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index 95dba19dce7..40a6aabba10 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -22,7 +22,7 @@ GLOBAL_VAR_INIT(starlight_power, default_starlight_power()) GLOB.base_starlight_color = star_color set_starlight(star_color, range, power) -/proc/set_starlight(star_color = null, range = null, power = null, list/restrict_z = null) +/proc/set_starlight(star_color = null, range = null, power = null, list/restrict_z = null) // VOIDCREW EDIT: overmap lighting: limit per-turf starlight sweeps to selected levels (voidcrew/edits/lighting.dm) if(isnull(star_color)) star_color = GLOB.starlight_color var/old_star_color = GLOB.starlight_color @@ -33,8 +33,10 @@ GLOBAL_VAR_INIT(starlight_power, default_starlight_power()) // overlay objects and the signal below always update, so unswept z-levels // light correctly the next time anything relights them. for(var/turf/open/space/spess as anything in GLOB.starlight) + // VOIDCREW EDIT START - overmap lighting: limit per-turf starlight sweeps to selected levels (voidcrew/edits/lighting.dm) if(restrict_z && !(spess.z in restrict_z)) continue + // VOIDCREW EDIT END spess.set_light(l_range = range, l_power = power, l_color = star_color) if(star_color == old_star_color) @@ -139,6 +141,7 @@ GLOBAL_LIST_EMPTY(starlight) return attack_hand(user, modifiers) /turf/open/space/proc/CanBuildHere() + // VOIDCREW EDIT REMOVAL - shuttle construction: allow building on transition space aboard ships return TRUE /turf/open/space/handle_slip() diff --git a/code/game/turfs/open/space/transit.dm b/code/game/turfs/open/space/transit.dm index 2dbaa65d52b..6bf8da79698 100644 --- a/code/game/turfs/open/space/transit.dm +++ b/code/game/turfs/open/space/transit.dm @@ -37,8 +37,10 @@ SIGNAL_HANDLER // The async initialization callback can outlive the move or turf replacement. + // VOIDCREW EDIT START - hyperspace integration: honor movement exemptions and reject stale asynchronous entries (voidcrew/edits/hyperspace_overboard.dm) if(QDELETED(enterer) || enterer.loc != src || !istype(src, /turf/open/space/transit)) return + // VOIDCREW EDIT END // VOIDCREW EDIT ADDITION START - the hull grace zone. Close in against a ship, hyperspace // does not take hold. The tiles are still vacuum and you still get around by pushing off @@ -70,7 +72,7 @@ var/turf/location = gone.loc // VOIDCREW: crossing into a normal-space breach respects the same exemption as the soft cordon. - if(istype(location, /turf/open/space) && !istype(location, src.type) && !HAS_TRAIT(gone, TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT)) + if(istype(location, /turf/open/space) && !istype(location, src.type) && !HAS_TRAIT(gone, TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT)) // VOIDCREW EDIT: hyperspace integration: honor movement exemptions and reject stale asynchronous entries (voidcrew/edits/hyperspace_overboard.dm) dump_in_space(gone) //launch them into game space, away from transitspace ///Get rid of all our contents, called when our reservation is released (which in our case means the shuttle arrived) diff --git a/code/modules/admin/admin_fax_panel.dm b/code/modules/admin/admin_fax_panel.dm index 49cb1cf2660..fa9f6c8c2a7 100644 --- a/code/modules/admin/admin_fax_panel.dm +++ b/code/modules/admin/admin_fax_panel.dm @@ -117,7 +117,7 @@ ADMIN_VERB(fax_panel, R_ADMIN, "Fax Panel", "View and respond to faxes sent to C stamp_class = needed_stamp[3] break - fax_paper.name = "paper, [default_paper_name]" + fax_paper.name = "paper, [default_paper_name]" // VOIDCREW EDIT: paperwork keeps fax titles compatible with the client font. fax_paper.add_raw_text(params["rawText"], advanced_html = TRUE) if(stamp) diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index ec940fcdeac..db3da1958f4 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -786,6 +786,7 @@ ADMIN_VERB(cmd_admin_pm_panel, R_NONE, "Admin PM", "Show a list of clients to PM var/datum/translated_speech/translation = try_begin_adminhelp_translation(raw_message, sender) var/display_message = translation ? translation.wrapped_adminhelp_text(message) : message // VOIDCREW EDIT ADDITION END + // VOIDCREW EDIT START: autotranslate displays the translated administrator message. to_chat( src, type = MESSAGE_TYPE_ADMINPM, @@ -797,6 +798,7 @@ ADMIN_VERB(cmd_admin_pm_panel, R_NONE, "Admin PM", "Show a list of clients to PM "boxed_message red_box"), confidential = TRUE ) + // VOIDCREW EDIT END // VOIDCREW EDIT ADDITION BEGIN - AUTOTRANSLATE translation?.begin() // VOIDCREW EDIT ADDITION END diff --git a/code/modules/antagonists/abductor/equipment/glands/heal.dm b/code/modules/antagonists/abductor/equipment/glands/heal.dm index 589ded68a35..8d6b89ad77d 100644 --- a/code/modules/antagonists/abductor/equipment/glands/heal.dm +++ b/code/modules/antagonists/abductor/equipment/glands/heal.dm @@ -9,9 +9,8 @@ icon_state = "health" mind_control_uses = 3 mind_control_duration = 3000 - // VOIDCREW ADD: delayed healing belongs to one continuous implantation. -// VOIDCREW ADD START + /obj/item/organ/heart/gland/heal/activate() if(!(owner.mob_biotypes & MOB_ORGANIC)) return @@ -153,9 +152,9 @@ new_stomach.Insert(owner) /obj/item/organ/heart/gland/heal/proc/replace_eyes(obj/item/organ/eyes/eyes) - // VOIDCREW ADD: capture the recipient before organ-removal callbacks can change it. + // VOIDCREW EDIT ADDITION: capture the recipient before organ-removal callbacks can change it. var/mob/living/carbon/recipient = owner - var/generation = healing_generation + var/generation = healing_generation // VOIDCREW EDIT: healing gland integration: pending regrowth belongs to one continuous implantation (voidcrew/edits/modules/antagonists/abductor/equipment/glands/heal.dm) if(eyes) owner.visible_message(span_warning("[owner]'s [eyes.name] fall out of their sockets!"), span_userdanger("Your [eyes.name] fall out of their sockets!")) playsound(owner, 'sound/effects/splat.ogg', 50, TRUE) @@ -167,10 +166,10 @@ addtimer(CALLBACK(src, PROC_REF(finish_replace_eyes), recipient, generation), rand(10 SECONDS, 20 SECONDS)) // VOIDCREW EDIT /obj/item/organ/heart/gland/heal/proc/finish_replace_eyes(mob/living/carbon/recipient, generation) // VOIDCREW EDIT - // VOIDCREW ADD START + // VOIDCREW EDIT ADDITION START if(!can_finish_healing(recipient, generation)) return - // VOIDCREW ADD END + // VOIDCREW EDIT ADDITION END var/eye_type = /obj/item/organ/eyes if(recipient.dna.species && recipient.dna.species.mutanteyes) // VOIDCREW EDIT eye_type = recipient.dna.species.mutanteyes // VOIDCREW EDIT @@ -179,9 +178,9 @@ recipient.visible_message(span_warning("A pair of new eyes suddenly inflates into [recipient]'s eye sockets!"), span_userdanger("A pair of new eyes suddenly inflates into your eye sockets!")) // VOIDCREW EDIT /obj/item/organ/heart/gland/heal/proc/replace_limb(body_zone, obj/item/bodypart/limb) - // VOIDCREW ADD: limb-removal callbacks must not redirect the pending regrowth. + // VOIDCREW EDIT ADDITION: limb-removal callbacks must not redirect the pending regrowth. var/mob/living/carbon/recipient = owner - var/generation = healing_generation + var/generation = healing_generation // VOIDCREW EDIT: healing gland integration: pending regrowth belongs to one continuous implantation (voidcrew/edits/modules/antagonists/abductor/equipment/glands/heal.dm) if(limb) owner.visible_message(span_warning("[owner]'s [limb.plaintext_zone] suddenly detaches from [owner.p_their()] body!"), span_userdanger("Your [limb.plaintext_zone] suddenly detaches from your body!")) playsound(owner, SFX_DESECRATION, 50, TRUE, -1) @@ -192,10 +191,10 @@ addtimer(CALLBACK(src, PROC_REF(finish_replace_limb), body_zone, recipient, generation), rand(15 SECONDS, 30 SECONDS)) // VOIDCREW EDIT /obj/item/organ/heart/gland/heal/proc/finish_replace_limb(body_zone, mob/living/carbon/recipient, generation) // VOIDCREW EDIT - // VOIDCREW ADD START + // VOIDCREW EDIT ADDITION START if(!can_finish_healing(recipient, generation)) return - // VOIDCREW ADD END + // VOIDCREW EDIT ADDITION END recipient.visible_message(span_warning("With a loud snap, [recipient]'s [parse_zone(body_zone)] rapidly grows back from [recipient.p_their()] body!"), // VOIDCREW EDIT span_userdanger("With a loud snap, your [parse_zone(body_zone)] rapidly grows back from your body!"), span_warning("Your hear a loud snap.")) @@ -207,10 +206,10 @@ keep_replacing_blood(owner, healing_generation) // VOIDCREW EDIT /obj/item/organ/heart/gland/heal/proc/keep_replacing_blood(mob/living/carbon/recipient, generation) // VOIDCREW EDIT - // VOIDCREW ADD START + // VOIDCREW EDIT ADDITION START if(!can_finish_healing(recipient, generation)) return - // VOIDCREW ADD END + // VOIDCREW EDIT ADDITION END var/keep_going = FALSE // VOIDCREW EDIT START recipient.vomit(vomit_flags = (MOB_VOMIT_BLOOD | MOB_VOMIT_FORCE), lost_nutrition = 0, distance = 3) diff --git a/code/modules/antagonists/heretic/magic/rust_construction.dm b/code/modules/antagonists/heretic/magic/rust_construction.dm index 26de2087033..b3fe3f30dd8 100644 --- a/code/modules/antagonists/heretic/magic/rust_construction.dm +++ b/code/modules/antagonists/heretic/magic/rust_construction.dm @@ -80,7 +80,7 @@ // but I guess a fading filter will have to do for now as walls have 0 depth (currently) // damn though with 3/4ths walls this'll look sick just imagine it new_wall.add_filter("rust_wall", 2, list("type" = "outline", "color" = "#85be299c", "size" = 2)) - // VOIDCREW EDIT: The constructed wall outlives the action. Capture this cast's + // VOIDCREW EDIT START: The constructed wall outlives the action. Capture this cast's - Voidcrew rust spell integration: expire only the filter owned by this cast (voidcrew/edits/spells) // parameter list, which survives unrelated filter rebuilds but not replacement. var/list/owned_filter = new_wall.filter_data["rust_wall"] addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(fade_rust_wall_filter), new_wall, owned_filter, filter_duration * (9/20)), filter_duration * 0.5) @@ -122,3 +122,5 @@ if(!message_shown) new_wall.visible_message(span_warning("\A [new_wall] [rises_message]!")) + +// VOIDCREW EDIT REMOVAL - rust spell: cosmetic expiry runs independently of the action (voidcrew/edits/modules/antagonists/heretic/magic/rust_construction.dm). diff --git a/code/modules/asset_cache/assets/rcd.dm b/code/modules/asset_cache/assets/rcd.dm index dbb2fc9d8c6..c6735a08c3f 100644 --- a/code/modules/asset_cache/assets/rcd.dm +++ b/code/modules/asset_cache/assets/rcd.dm @@ -1,10 +1,13 @@ /datum/asset/spritesheet_batched/rcd name = "rcd-tgui" -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/asset/spritesheet_batched/rcd/create_spritesheets() //the ship construction console's hull windows are not in GLOB.rcd_designs (they are not //offered by the handheld RCD) but they share this spritesheet, so draw both trees + // VOIDCREW EDIT START: shuttle draws hull-window construction icons. for(var/list/design_tree as anything in list(GLOB.rcd_designs, GLOB.ship_rcd_hull_designs)) draw_design_tree(design_tree) -// VOIDCREW EDIT END + // VOIDCREW EDIT END + +// VOIDCREW EDIT: shuttle draws icons for construction design trees; implementation in voidcrew/edits/modules/asset_cache/assets/rcd.dm. +// VOIDCREW EDIT REMOVAL: shuttle draws the original design loop in voidcrew/edits/modules/asset_cache/assets/rcd.dm. diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm index ddb6d1b8e65..60e9ae81c2a 100644 --- a/code/modules/atmospherics/environmental/LINDA_fire.dm +++ b/code/modules/atmospherics/environmental/LINDA_fire.dm @@ -11,7 +11,6 @@ return null - /turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0) return @@ -191,6 +190,7 @@ // VOIDCREW EDIT: return_air() so a turf still on the shared planetary mix takes a // private one; what we remove here has to be missing when assume_air() puts it back. var/datum/gas_mixture/location_air = location.return_air() + // VOIDCREW EDIT: Materialize private planetary air before fire removes gas (voidcrew/edits/planetary_shared_air.dm). var/datum/gas_mixture/affected = location_air.remove_ratio(volume/location_air.volume) if(affected) //in case volume is 0 reference = affected // Our color and volume will depend on this small sparked gasmix diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm index a562356f5ac..9c16306678d 100644 --- a/code/modules/atmospherics/environmental/LINDA_system.dm +++ b/code/modules/atmospherics/environmental/LINDA_system.dm @@ -76,6 +76,7 @@ // through to the else below is what REMOVES a pairing an earlier raw turf swap left standing, // and a continue would leave exactly the stale entry we are here to clear. var/turf/open/open_src = src + // VOIDCREW EDIT: Avoid null-air adjacency and materialize shared planetary air before writes (voidcrew/edits/planetary_shared_air.dm). var/we_hold_air = !isopenturf(src) || open_src.air // I am essentially inlineing two get_dir_multizs here, because they're way too slow on their own. I'm sorry brother var/list/z_traits = SSmapping.multiz_levels[z] @@ -105,6 +106,7 @@ // (direction & (UP | DOWN)) is just "is this vertical" by the by // VOIDCREW EDIT: `we_hold_air`/`open_neighbour.air` - see the note above the loop. var/turf/open/open_neighbour = current_turf + // VOIDCREW EDIT: Avoid null-air adjacency and materialize shared planetary air before writes (voidcrew/edits/planetary_shared_air.dm). if(canpass && we_hold_air && open_neighbour.air && CANATMOSPASS(current_turf, src, (direction & (UP|DOWN))) && !(blocks_air || current_turf.blocks_air)) LAZYINITLIST(current_turf.atmos_adjacent_turfs) atmos_adjacent_turfs[current_turf] = TRUE @@ -133,6 +135,7 @@ // pairing (the else below strips it from BOTH sides), so a `continue` here would be a no-op // against the entry that is actually causing the runtime. var/turf/open/open_src = src + // VOIDCREW EDIT: Avoid null-air adjacency and materialize shared planetary air before writes (voidcrew/edits/planetary_shared_air.dm). var/we_hold_air = !isopenturf(src) || open_src.air for(var/direction in GLOB.cardinals_multiz) var/turf/current_turf = get_step_multiz(src, direction) @@ -141,8 +144,10 @@ //Can you and me form a deeper relationship, or is this just a passing wind // (direction & (UP | DOWN)) is just "is this vertical" by the by + // VOIDCREW EDIT START: Avoid null-air adjacency and materialize shared planetary air before writes (voidcrew/edits/planetary_shared_air.dm). var/turf/open/open_neighbour = current_turf if(canpass && we_hold_air && open_neighbour.air && CANATMOSPASS(current_turf, src, (direction & (UP|DOWN))) && !(blocks_air || current_turf.blocks_air)) + // VOIDCREW EDIT END LAZYINITLIST(current_turf.atmos_adjacent_turfs) atmos_adjacent_turfs[current_turf] = TRUE current_turf.atmos_adjacent_turfs[src] = TRUE @@ -240,6 +245,7 @@ var/datum/gas_mixture/turf_mixture = SSair.parse_gas_string(text, /datum/gas_mixture/turf) var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix + // VOIDCREW EDIT: Avoid null-air adjacency and materialize shared planetary air before writes (voidcrew/edits/planetary_shared_air.dm). our_air.merge(turf_mixture) archive() SSair.add_to_active(src) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 7e5456ab196..d75457cd8e7 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -57,14 +57,17 @@ #endif /turf/open/Initialize(mapload) + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). prepare_planet_atmosphere() // VOIDCREW: authored atmosphere precedes air creation. if(!blocks_air) // VOIDCREW EDIT: a planetary turf starts on the shared mix for its gas string and only // takes a private mixture on its first write. See voidcrew/edits/planetary_shared_air.dm. if(planetary_atmos) + // VOIDCREW EDIT START: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). air = planetary_shared_air() if(!air) air = create_gas_mixture() + // VOIDCREW EDIT END if(planetary_atmos) if(!SSair.planetary[initial_gas_mix]) var/datum/gas_mixture/immutable/planetary/mix = new @@ -98,6 +101,7 @@ if(!giver) return FALSE var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). our_air.merge(giver) update_visuals() air_update_turf(FALSE, FALSE) @@ -113,11 +117,13 @@ /turf/open/proc/copy_air_with_tile(turf/open/target_turf) if(istype(target_turf)) var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). our_air.copy_from(target_turf.air) /turf/open/proc/copy_air(datum/gas_mixture/copy) if(copy) var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). our_air.copy_from(copy) /turf/return_air() @@ -131,6 +137,7 @@ // so a turf still on the shared planetary mix takes its private copy now. Readers that // must not trigger that use return_air_readonly(). if(planetary_atmos) + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). return materialize_planet_air() return air @@ -335,9 +342,11 @@ // VOIDCREW EDIT: share() writes both mixes. Either turf may still be on the shared // planetary mix; give it a private one first (no-op otherwise). if(planetary_atmos) + // VOIDCREW EDIT START: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). our_air = materialize_planet_air() if(enemy_tile.planetary_atmos) enemy_air = enemy_tile.materialize_planet_air() + // VOIDCREW EDIT END var/difference = our_air.share(enemy_air, our_share_coeff, 1 / (LAZYLEN(enemy_tile.atmos_adjacent_turfs) + 1)) if(difference) if(difference > 0) @@ -369,6 +378,7 @@ // VOIDCREW EDIT: a 100% share into space writes us; leave the shared planetary mix first. if(planetary_atmos && share_end) + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). our_air = materialize_planet_air() for(var/turf/open/enemy_tile as anything in share_end) var/datum/gas_mixture/enemy_mix = enemy_tile.air @@ -645,6 +655,7 @@ Then we space some of our heat, and think about if we should stop conducting. var/turf/open/open_other = other // VOIDCREW EDIT: temperature_share() writes both mixes; neither may stay on the shared planetary mix. var/datum/gas_mixture/other_air = open_other.materialize_planet_air() + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). other_air.temperature_share(materialize_planet_air(), WINDOW_HEAT_TRANSFER_COEFFICIENT) else //Open but neighbor is solid temperature_share_open_to_solid(other) @@ -684,6 +695,7 @@ Then we space some of our heat, and think about if we should stop conducting. //Conduct with air on my tile if I have it if(..((blocks_air ? temperature : air.temperature)) != FALSE && !blocks_air) var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). temperature = our_air.temperature_share(null, thermal_conductivity, temperature, heat_capacity) ///Should we attempt to superconduct? @@ -721,6 +733,7 @@ Then we space some of our heat, and think about if we should stop conducting. /turf/open/proc/temperature_share_open_to_solid(turf/sharer) var/datum/gas_mixture/our_air = materialize_planet_air() // VOIDCREW EDIT: shared planetary mix + // VOIDCREW EDIT: Prepare planetary atmospheres and materialize private gas before every mutation (voidcrew/edits/planetary_shared_air.dm). sharer.temperature = our_air.temperature_share(null, sharer.thermal_conductivity, sharer.temperature, sharer.heat_capacity) /turf/proc/share_temperature_mutual_solid(turf/sharer, conduction_coefficient) //This is all just heat sharing, don't get freaked out diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 44a0e7bb4aa..71347d1edcb 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -200,8 +200,10 @@ // braces with the guards in SSair.add_to_rebuild_queue()/process_rebuilds(): this one // also covers any caller that reaches rebuild_pipes() without going through the queue. if(QDELETED(src)) + // VOIDCREW EDIT START: Avoid new pipelines for dying atmos machines and tolerate asymmetric node teardown. rebuilding = FALSE return + // VOIDCREW EDIT END var/list/targets = get_rebuild_targets() rebuilding = FALSE for(var/datum/pipeline/build_off as anything in targets) @@ -419,8 +421,10 @@ // VOIDCREW EDIT: Find() returns 0 on an asymmetric link, and nodes[0] runtimes - // aborting the caller's Destroy() chain before any of its cleanup runs var/node_index = nodes.Find(reference) + // VOIDCREW EDIT START: Avoid new pipelines for dying atmos machines and tolerate asymmetric node teardown. if(node_index) nodes[node_index] = null + // VOIDCREW EDIT END update_appearance() /obj/machinery/atmospherics/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index e94e2b331b1..c8daf297d85 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -179,6 +179,7 @@ // expected teardown path, not an error - the old CRASH here fired once per // pipeline with components on every hull/zone teardown if(QDESTROYING(reference)) + // VOIDCREW EDIT: Maintain both sides of component pipeline links during live rebuilds and merges. return qdel(reference) @@ -197,6 +198,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/atmospherics/components/set_pipenet(datum/pipeline/reference, obj/machinery/atmospherics/target_component) + // VOIDCREW EDIT START: Maintain both sides of component pipeline links during live rebuilds and merges. var/port_index = nodes.Find(target_component) var/datum/pipeline/previous_parent = parents[port_index] if(previous_parent == reference) @@ -212,6 +214,7 @@ previous_parent.other_atmos_machines -= src if(custom_reconcilation) previous_parent.require_custom_reconcilation -= src + // VOIDCREW EDIT END // VOIDCREW EDIT END /obj/machinery/atmospherics/components/return_pipenet(obj/machinery/atmospherics/target_component = nodes[1]) //returns parents[1] if called without argument @@ -219,6 +222,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/atmospherics/components/replace_pipenet(datum/pipeline/Old, datum/pipeline/New) + // VOIDCREW EDIT START: Maintain both sides of component pipeline links during live rebuilds and merges. var/first_port = parents.Find(Old) if(!first_port) CRASH("[type] at [COORD(src)] was asked to replace a pipeline it does not belong to.") @@ -226,6 +230,7 @@ for(var/port_index in first_port to length(parents)) if(parents[port_index] == Old) parents[port_index] = New + // VOIDCREW EDIT END // Helpers diff --git a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm index 4375683dc37..66658d277e7 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/machine_connector.dm @@ -120,8 +120,10 @@ // The internal connector can be deleted first during map cleanup. Its own // destruction disconnects the pipes, and connector_deleted has cleared this reference. + // VOIDCREW EDIT START: Tolerate an internal connector already removed during site teardown. if(gas_connector) disconnect_connector() + // VOIDCREW EDIT END SSair.stop_processing_machine(connected_machine) unregister_from_machine() qdel(src) diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index ece9ed94169..d5f1440b09b 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -41,6 +41,7 @@ // removes the component from other_atmos_machines) - a for-in over the live list // skips every other entry when the current one is removed. Detach the lists first. var/list/dying_members = members + // VOIDCREW EDIT START: Detach pipeline ownership safely and remove stale members during site churn (voidcrew/edits/modules/atmospherics/machinery/datum_pipeline.dm). members = list() for(var/obj/machinery/atmospherics/pipe/considered_pipe in dying_members) // Only sever pipes that are still ours: a pipe already rebuilt into a LIVE @@ -49,9 +50,11 @@ // leaving the live pipeline holding a pipe that no longer pointed back. if(considered_pipe.parent == src) considered_pipe.replace_pipenet(src, null) + // VOIDCREW EDIT END if(QDELETED(considered_pipe)) continue SSair.add_to_rebuild_queue(considered_pipe) + // VOIDCREW EDIT START: Detach pipeline ownership safely and remove stale members during site churn (voidcrew/edits/modules/atmospherics/machinery/datum_pipeline.dm). var/list/dying_machines = other_atmos_machines other_atmos_machines = list() for(var/obj/machinery/atmospherics/components/considered_component in dying_machines) @@ -62,6 +65,7 @@ // animate() color filter; qdel'ing them also detaches them from any pipe // vis_contents still showing them QDEL_LIST_ASSOC_VAL(gas_visuals) + // VOIDCREW EDIT END return ..() /datum/pipeline/process() @@ -131,8 +135,10 @@ if(item.parent) var/static/pipenetwarnings = 10 if(pipenetwarnings > 0) + // VOIDCREW EDIT START: Include the area type when diagnosing stacked hull pipes during live site loading. var/area/our_area = get_area(borderline) log_mapping("build_pipeline(): [item.type] added to a pipenet while still having one. (pipes leading to the same spot stacking in one turf) around [AREACOORD(item)] in [our_area.type].") + // VOIDCREW EDIT END pipenetwarnings-- if(pipenetwarnings == 0) log_mapping("build_pipeline(): further messages about pipenets will be suppressed") @@ -189,7 +195,6 @@ members += reference_pipe air.volume += reference_pipe.volume -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/pipeline/proc/merge(datum/pipeline/parent_pipeline) if(parent_pipeline == src) return @@ -200,9 +205,11 @@ // in both pipelines at once, and concatenating duplicated the shared pipes into // the survivor's members (each duplicate = one permanent GC-blocking ref). var/list/merged_members = parent_pipeline.members + // VOIDCREW EDIT START: Detach pipeline ownership safely and remove stale members during site churn (voidcrew/edits/modules/atmospherics/machinery/datum_pipeline.dm). parent_pipeline.members = list() members |= merged_members for(var/obj/machinery/atmospherics/pipe/reference_pipe in merged_members) + // VOIDCREW EDIT END reference_pipe.replace_pipenet(reference_pipe.parent, src) air.merge(parent_pipeline.air) for(var/obj/machinery/atmospherics/components/reference_component in parent_pipeline.other_atmos_machines) @@ -211,12 +218,12 @@ require_custom_reconcilation |= reference_component other_atmos_machines |= parent_pipeline.other_atmos_machines other_airs |= parent_pipeline.other_airs + // VOIDCREW EDIT REMOVAL: Detach pipeline ownership safely and remove stale members during site churn (voidcrew/edits/modules/atmospherics/machinery/datum_pipeline.dm). parent_pipeline.other_atmos_machines.Cut() parent_pipeline.require_custom_reconcilation.Cut() update = TRUE qdel(parent_pipeline) -// VOIDCREW EDIT END /obj/machinery/atmospherics/proc/add_member(obj/machinery/atmospherics/considered_device) return @@ -266,7 +273,6 @@ stack_trace("[src] has one or more null gas mixtures, which may cause bugs. Null mixtures will not be considered in reconcile_air().") /// Called when the pipenet needs to update and mix together all the air mixes -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/pipeline/proc/reconcile_air() var/list/datum/gas_mixture/gas_mixture_list = list() var/list/datum/pipeline/pipeline_list = list() @@ -284,6 +290,7 @@ // A network or port being rebuilt can have no mixture yet. As in return_air(), // leave absent volumes out while still reconciling the surviving connections. + // VOIDCREW EDIT: Ignore not-yet-created gas mixtures while reconciling rebuilt pipeline ports. list_clear_nulls(gas_mixture_list) var/total_thermal_energy = 0 @@ -341,7 +348,6 @@ * Used to create and/or get the gas visual overlay created using the given icon file. * The color is automatically kept up to date and expected to be used as a vis_contents object. */ -// VOIDCREW EDIT END /datum/pipeline/proc/GetGasVisual(icon/icon_file) if(gas_visuals[icon_file]) return gas_visuals[icon_file] diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 46c3228907c..7f18a09a350 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -115,6 +115,7 @@ // but SSair.networks points at them), so each stale entry was a permanent // GC-blocking ref: round 4 spent ~275 s hard-deleting pipes pinned this way. if(old_pipenet && old_pipenet != new_pipenet) + // VOIDCREW EDIT: Remove pipes from their previous network when rebuilding live site pipelines. old_pipenet.members -= src parent = new_pipenet diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm index 6493aab9f1f..6f017701eb9 100644 --- a/code/modules/atmospherics/machinery/portable/scrubber.dm +++ b/code/modules/atmospherics/machinery/portable/scrubber.dm @@ -198,6 +198,7 @@ name = "huge air scrubber" icon_state = "hugescrubber" anchored = TRUE + // VOIDCREW EDIT: Return portable scrubbers to idle power use after scrubbing stops. use_power = IDLE_POWER_USE active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.5 diff --git a/code/modules/awaymissions/signpost.dm b/code/modules/awaymissions/signpost.dm index 54b4a2a8d36..671ddf0e1da 100644 --- a/code/modules/awaymissions/signpost.dm +++ b/code/modules/awaymissions/signpost.dm @@ -7,21 +7,18 @@ var/question = "Travel back?" var/list/zlevels -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/structure/signpost/Initialize(mapload) . = ..() set_light(2) +// VOIDCREW EDIT REMOVAL: mining resolves signpost destinations through the crew ship. -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/structure/signpost/interact(mob/user) . = ..() if(.) return if(tgui_alert(usr,question,name,list("Yes","No")) == "Yes" && Adjacent(user)) - var/turf/T = get_destination_turf(user) - - // VOIDCREW EDIT ADDITION START: no way home across an overmap zone boundary (voidcrew/modules/overmap, zone_teleport.dm) + var/turf/T = get_destination_turf(user) // VOIDCREW EDIT: mining resolves signpost destinations through the crew ship. + // VOIDCREW EDIT ADDITION START: signposts respect zone boundaries. if(T && teleport_crosses_zone(user, T)) to_chat(user, span_warning("Nothing happens. The way home is past the zone boundary.")) return @@ -38,7 +35,8 @@ else to_chat(user, "Nothing happens. You feel that this is a bad sign.") -// VOIDCREW EDIT END +// VOIDCREW EDIT: mining returns explorers to their own crew ship; implementation in voidcrew/edits/modules/awaymissions/signpost.dm. + /obj/structure/signpost/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) return interact(user) @@ -77,3 +75,5 @@ zlevels -= SSmapping.levels_by_trait(ZTRAIT_CENTCOM) // no easy victory, even with meme signposts // also, could you think of the horror if they ended up in a holodeck // template or something + +// VOIDCREW EDIT: mining preserves the exit signpost random destination; implementation in voidcrew/edits/modules/awaymissions/signpost.dm. diff --git a/code/modules/bitrunning/areas.dm b/code/modules/bitrunning/areas.dm index 9716a224c61..af60b28d65c 100644 --- a/code/modules/bitrunning/areas.dm +++ b/code/modules/bitrunning/areas.dm @@ -25,7 +25,7 @@ area_flags = UNIQUE_AREA | LOCAL_TELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING default_gravity = STANDARD_GRAVITY requires_power = FALSE - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. // VOIDCREW EDIT END /area/virtual_domain/fullbright @@ -41,7 +41,7 @@ icon_state = "bit_safe" requires_power = FALSE sound_environment = SOUND_ENVIRONMENT_ROOM - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. /// Custom subtypes @@ -51,7 +51,7 @@ name = "Virtual Domain Lava Ruins" icon_state = "bit_ruin" area_flags = UNIQUE_AREA | LOCAL_TELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. @@ -59,7 +59,7 @@ name = "Virtual Domain Ice Ruins" icon_state = "bit_ice" area_flags = UNIQUE_AREA | LOCAL_TELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. @@ -68,7 +68,7 @@ icon = 'icons/area/areas_station.dmi' icon_state = "bit_ruin" area_flags = UNIQUE_AREA | LOCAL_TELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. @@ -77,7 +77,7 @@ icon = 'icons/area/areas_station.dmi' icon_state = "bit_space" area_flags = UNIQUE_AREA | LOCAL_TELEPORT | EVENT_PROTECTED | HIDDEN_AREA | UNLIMITED_FISHING - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. ///Areas that virtual entities should not be in @@ -87,7 +87,7 @@ name = "Virtual Domain Safe Zone" area_flags = UNIQUE_AREA | LOCAL_TELEPORT | EVENT_PROTECTED | VIRTUAL_SAFE_AREA | UNLIMITED_FISHING icon_state = "bit_safe" - allow_shuttle_docking = FALSE + allow_shuttle_docking = FALSE // VOIDCREW EDIT: research forbids shuttle entry into virtual domains. // VOIDCREW EDIT END /area/virtual_domain/protected_space/fullbright diff --git a/code/modules/bitrunning/server/map_handling.dm b/code/modules/bitrunning/server/map_handling.dm index de189a310fd..42f91b56c36 100644 --- a/code/modules/bitrunning/server/map_handling.dm +++ b/code/modules/bitrunning/server/map_handling.dm @@ -84,19 +84,20 @@ /// Initializes a new domain if the given key is valid and the user has enough points // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/quantum_server/proc/load_domain(map_key) - var/datum/lazy_template/virtual_domain/target_domain + var/datum/lazy_template/virtual_domain/target_domain // VOIDCREW EDIT: research locks each virtual domain to one server. for(var/datum/lazy_template/virtual_domain/available in SSbitrunning.all_domains) if(map_key == available.key && points >= available.cost) - target_domain = available + target_domain = available // VOIDCREW EDIT: research locks each virtual domain to one server. break - if(!target_domain) + if(!target_domain) // VOIDCREW EDIT: research locks each virtual domain to one server. return FALSE // Domain datums are one instance for the whole fleet, and their reservation // list and loot counters go with them. A second server booting the same key // would read the first one's reservation, match no landmarks at all and take // itself offline for the round, so one holder per domain at a time. + // VOIDCREW EDIT START: research locks each virtual domain to one server. if(!SSbitrunning.claim_domain(map_key, src)) balloon_alert_to_viewers("domain in use!") say("[target_domain.name] is already running on another server. Pick a different domain.") @@ -104,6 +105,7 @@ return FALSE generated_domain = target_domain + // VOIDCREW EDIT END if(generated_domain.mission_min_candidates && (!COOLDOWN_FINISHED(src, polling_cooldown))) say("Advanced NPC algorithms resetting, please wait [DisplayTimeText(polling_cooldown)] or load a different domain.") @@ -146,11 +148,13 @@ // GLOB.landmarks_list is global, but a fleet can have a server on every // ship. Two of them cold booting at once would consume each other's // landmarks, so only claim the ones inside our own reservation. - var/datum/turf_reservation/our_reservation = LAZYACCESS(generated_domain.reservations, 1) + var/datum/turf_reservation/our_reservation = LAZYACCESS(generated_domain.reservations, 1) // VOIDCREW EDIT: research claims landmarks from the server reservation and tolerates missing exits. for(var/obj/effect/landmark/bitrunning/thing in GLOB.landmarks_list) + // VOIDCREW EDIT START: research claims landmarks from the server reservation and tolerates missing exits. if(our_reservation && !our_reservation.contains_turf(get_turf(thing))) continue + // VOIDCREW EDIT END if(istype(thing, /obj/effect/landmark/bitrunning/hololadder_spawn)) exit_turfs += get_turf(thing) @@ -195,11 +199,15 @@ // Logged rather than thrown: an unwound cold_boot_map never restores is_ready, // which leaves the server dark for the rest of the round. if(!length(exit_turfs)) + // VOIDCREW EDIT START: research claims landmarks from the server reservation and tolerates missing exits. stack_trace("Failed to find exit turfs on generated domain.") return FALSE + // VOIDCREW EDIT END if(!length(goal_turfs)) + // VOIDCREW EDIT START: research claims landmarks from the server reservation and tolerates missing exits. stack_trace("Failed to find send turfs on generated domain.") return FALSE + // VOIDCREW EDIT END if(!attempt_spawn_cache(cache_turfs)) return FALSE @@ -244,6 +252,7 @@ // A boot that failed before a domain was picked still lands here, so nothing // below may assume there is one. + // VOIDCREW EDIT START: research clears spent reservations before releasing virtual-domain ownership. if(generated_domain) // Drop the reservation from the domain before releasing it. lazy_load() appends to // this list and nothing else ever removes from it, so leaving spent entries behind @@ -258,6 +267,7 @@ generated_domain.secondary_loot_generated = 0 SSbitrunning.release_domain(generated_domain.key, src) + // VOIDCREW EDIT END var/list/creatures = spawned_threat_refs + mutation_candidate_refs for(var/datum/weakref/creature_ref as anything in creatures) @@ -267,6 +277,7 @@ qdel(creature) + // VOIDCREW EDIT REMOVAL: research clears spent reservations before releasing virtual-domain ownership. avatar_connection_refs.Cut() exit_turfs = list() generated_domain = null diff --git a/code/modules/bitrunning/server/obj_generation.dm b/code/modules/bitrunning/server/obj_generation.dm index b0129d544af..3db509acb1f 100644 --- a/code/modules/bitrunning/server/obj_generation.dm +++ b/code/modules/bitrunning/server/obj_generation.dm @@ -107,11 +107,13 @@ // Same reason load_map_items() scopes its sweep: GLOB.landmarks_list is global // and a fleet can have a server on every ship, so only claim the landmarks // standing inside our own reservation. - var/datum/turf_reservation/our_reservation = LAZYACCESS(generated_domain.reservations, 1) + var/datum/turf_reservation/our_reservation = LAZYACCESS(generated_domain.reservations, 1) // VOIDCREW EDIT: research claims mob landmarks only from the server reservation. for(var/obj/effect/landmark/bitrunning/mob_segment/landmark in GLOB.landmarks_list) + // VOIDCREW EDIT START: research claims mob landmarks only from the server reservation. if(our_reservation && !our_reservation.contains_turf(get_turf(landmark))) continue + // VOIDCREW EDIT END if(current_index > length(generated_domain.mob_modules)) stack_trace("vdom: mobs segments are set to unique, but there are more landmarks than available segments") diff --git a/code/modules/bitrunning/server/signal_handlers.dm b/code/modules/bitrunning/server/signal_handlers.dm index ded80f5fc19..60f556671c3 100644 --- a/code/modules/bitrunning/server/signal_handlers.dm +++ b/code/modules/bitrunning/server/signal_handlers.dm @@ -75,11 +75,13 @@ // ismegafauna() also covers /mob/living/basic/boss, which has no // make_virtual_megafauna() - calling it on one is a runtime. if(ismegafauna(creature)) + // VOIDCREW EDIT START: research limits virtual megafauna conversion to supported mobs. if(istype(creature, /mob/living/simple_animal/hostile/megafauna)) var/mob/living/simple_animal/hostile/megafauna/boss = creature boss.make_virtual_megafauna() else stack_trace("bitrunning: [creature.type] has no virtual megafauna nerf, it keeps full loot inside the domain") + // VOIDCREW EDIT END continue mutation_candidate_refs.Add(WEAKREF(creature)) diff --git a/code/modules/bitrunning/server/util.dm b/code/modules/bitrunning/server/util.dm index 7f13696e78b..91e7047e150 100644 --- a/code/modules/bitrunning/server/util.dm +++ b/code/modules/bitrunning/server/util.dm @@ -86,8 +86,10 @@ // A ship can map or build a server without a forge in range. Callers already // handle a null forge; pick() on an empty list would runtime before they got it. + // VOIDCREW EDIT START: research tolerates ship servers without a nearby forge. if(!length(nearby_forges)) return null + // VOIDCREW EDIT END return pick(nearby_forges) diff --git a/code/modules/bitrunning/util/virtual_megafauna.dm b/code/modules/bitrunning/util/virtual_megafauna.dm index adad2f730c9..2cc4c91e804 100644 --- a/code/modules/bitrunning/util/virtual_megafauna.dm +++ b/code/modules/bitrunning/util/virtual_megafauna.dm @@ -11,9 +11,11 @@ // well after it, so the component is already attached by the time we get here. Left // alone, every megafauna domain broadcasts a lavaland signal out of the turf // reservation to anyone holding a GPS. + // VOIDCREW EDIT START: research removes real-world GPS signals from virtual bosses. var/datum/component/gps/beacon = GetComponent(/datum/component/gps) if(beacon) qdel(beacon) + // VOIDCREW EDIT END loot.Cut() loot += /obj/structure/closet/crate/secure/bitrunning/encrypted diff --git a/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm b/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm index 27ad6b04ded..a42addb4179 100644 --- a/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm +++ b/code/modules/bitrunning/virtual_domain/domains/ash_drake.dm @@ -1,15 +1,17 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lazy_template/virtual_domain/ash_drake name = "Ashen Inferno" - cost = BITRUNNER_COST_BOSS + cost = BITRUNNER_COST_BOSS // VOIDCREW EDIT: research prices virtual boss domains and supplies their domain briefing. desc = "Home of the ash drake, a powerful dragon that scours the surface of Lavaland." difficulty = BITRUNNER_DIFFICULTY_MEDIUM forced_outfit = /datum/outfit/job/miner + // VOIDCREW EDIT START: research prices virtual boss domains and supplies their domain briefing. help_text = "There is no crate waiting for you out there. The drake is carrying it. \ Kill it, take the cache off the body, and haul it back to the safehouse goal tile. \ It breathes fire in a cone, calls down meteors, throws out rings of fireballs, and swoops \ into the air to land somewhere else. Below half health it walls the fight into a ring of \ lava, and leaving that ring only makes it angrier. Take the armoury with you." + // VOIDCREW EDIT END key = "ash_drake" map_name = "ash_drake" reward_points = BITRUNNER_REWARD_MEDIUM diff --git a/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm b/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm index d6f01792bb4..11f0b5f0455 100644 --- a/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm +++ b/code/modules/bitrunning/virtual_domain/domains/blood_drunk_miner.dm @@ -1,15 +1,17 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lazy_template/virtual_domain/blood_drunk_miner name = "Sanguine Excavation" - cost = BITRUNNER_COST_BOSS + cost = BITRUNNER_COST_BOSS // VOIDCREW EDIT: research prices virtual boss domains and supplies their domain briefing. desc = "Few escape the surface of Lavaland without a few scars. Some remain, maddened by the hunt." difficulty = BITRUNNER_DIFFICULTY_MEDIUM forced_outfit = /datum/outfit/job/miner + // VOIDCREW EDIT START: research prices virtual boss domains and supplies their domain briefing. help_text = "The miner is carrying the cache. Kill it, pick the cache up off the body, and \ bring it back to the safehouse goal tile. It dashes to close distance and hits hard with \ its saw, so it will not let you kite it for long. It also eats the dead to heal, which \ means a downed teammate left on the floor hands it most of its health back. \ Everything in the safehouse armoury is yours." + // VOIDCREW EDIT END key = "blood_drunk_miner" map_name = "blood_drunk_miner" reward_points = BITRUNNER_REWARD_MEDIUM diff --git a/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm b/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm index fede99577da..ef5c2cd8b0b 100644 --- a/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm +++ b/code/modules/bitrunning/virtual_domain/domains/bubblegum.dm @@ -1,15 +1,17 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lazy_template/virtual_domain/bubblegum name = "Blood-Soaked Lair" - cost = BITRUNNER_COST_APEX_BOSS + cost = BITRUNNER_COST_APEX_BOSS // VOIDCREW EDIT: research prices virtual boss domains and supplies their domain briefing. desc = "King of the slaughter demons. Bubblegum is a massive, hulking beast with a penchant for violence." difficulty = BITRUNNER_DIFFICULTY_HIGH completion_loot = list(/obj/item/toy/plush/bubbleplush = 1) forced_outfit = /datum/outfit/job/miner + // VOIDCREW EDIT START: research prices virtual boss domains and supplies their domain briefing. help_text = "Bubblegum is carrying the cache. Kill it, take the cache off the body, and haul \ it to the safehouse goal tile. It moves through blood, so every pool on the floor is \ somewhere it can appear from, including the blood you are leaving behind. It charges in a \ straight line and calls in copies of itself. Fighting it on clean ground is much easier." + // VOIDCREW EDIT END key = "bubblegum" map_name = "bubblegum" reward_points = BITRUNNER_REWARD_HIGH diff --git a/code/modules/bitrunning/virtual_domain/domains/colossus.dm b/code/modules/bitrunning/virtual_domain/domains/colossus.dm index 5bd5c35b83b..c25764268be 100644 --- a/code/modules/bitrunning/virtual_domain/domains/colossus.dm +++ b/code/modules/bitrunning/virtual_domain/domains/colossus.dm @@ -1,14 +1,16 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lazy_template/virtual_domain/colossus name = "Celestial Trial" - cost = BITRUNNER_COST_APEX_BOSS + cost = BITRUNNER_COST_APEX_BOSS // VOIDCREW EDIT: research prices virtual boss domains and supplies their domain briefing. desc = "A massive, ancient beast named the Colossus. Judgment comes." difficulty = BITRUNNER_DIFFICULTY_HIGH forced_outfit = /datum/outfit/job/miner + // VOIDCREW EDIT START: research prices virtual boss domains and supplies their domain briefing. help_text = "The Colossus is holding the cache. Kill it, take the cache, and carry it back to \ the safehouse goal tile. It barely moves. Everything it does is projectiles, and every \ pattern has a gap in it, so the fight is about reading the spread and standing in the gap. \ It gets faster as its health drops. Take the whole armoury with you." + // VOIDCREW EDIT END key = "colossus" map_name = "colossus" reward_points = BITRUNNER_REWARD_HIGH diff --git a/code/modules/bitrunning/virtual_domain/domains/hierophant.dm b/code/modules/bitrunning/virtual_domain/domains/hierophant.dm index 509fa1147dc..b9e0249ea88 100644 --- a/code/modules/bitrunning/virtual_domain/domains/hierophant.dm +++ b/code/modules/bitrunning/virtual_domain/domains/hierophant.dm @@ -1,15 +1,17 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lazy_template/virtual_domain/hierophant name = "Zealot Arena" - cost = BITRUNNER_COST_APEX_BOSS + cost = BITRUNNER_COST_APEX_BOSS // VOIDCREW EDIT: research prices virtual boss domains and supplies their domain briefing. desc = "Dance, puppets, dance!" difficulty = BITRUNNER_DIFFICULTY_HIGH forced_outfit = /datum/outfit/job/miner + // VOIDCREW EDIT START: research prices virtual boss domains and supplies their domain briefing. help_text = "The hierophant is carrying the cache. Kill it, take the cache, and get it to the \ safehouse goal tile. It teleports directly onto whoever it is chasing and leaves damaging \ squares on the floor, so putting a wall between you and it buys less time than you think. \ Watch the ground: everything it does is telegraphed a moment before it lands. \ Everything in the safehouse armoury is yours." + // VOIDCREW EDIT END key = "hierophant" map_name = "hierophant" reward_points = BITRUNNER_REWARD_HIGH diff --git a/code/modules/bitrunning/virtual_domain/domains/psyker_zombies.dm b/code/modules/bitrunning/virtual_domain/domains/psyker_zombies.dm index 383d7d1c9bd..f4ac1f15ec2 100644 --- a/code/modules/bitrunning/virtual_domain/domains/psyker_zombies.dm +++ b/code/modules/bitrunning/virtual_domain/domains/psyker_zombies.dm @@ -4,7 +4,7 @@ // Was COST_MEDIUM, which made this the only domain in the roster paying net +3 // while also being BEPIS-eligible - strictly better than the megafauna arenas it // is supposed to fund. Priced back onto the flat +2 ladder everything else uses. - cost = BITRUNNER_COST_HIGH + cost = BITRUNNER_COST_HIGH // VOIDCREW EDIT: research keeps the psyker domain on the shared bitrunning reward ladder. desc = "Another neglected corner of the virtual world. This one had to be abandoned due to zombie virus. \ Warning -- Virtual domain does not support visual display. This mission must be completed using echolocation." difficulty = BITRUNNER_DIFFICULTY_MEDIUM diff --git a/code/modules/bitrunning/virtual_domain/domains/wendigo.dm b/code/modules/bitrunning/virtual_domain/domains/wendigo.dm index 4ae0ee449a4..f5815392647 100644 --- a/code/modules/bitrunning/virtual_domain/domains/wendigo.dm +++ b/code/modules/bitrunning/virtual_domain/domains/wendigo.dm @@ -1,15 +1,17 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lazy_template/virtual_domain/wendigo name = "Glacial Devourer" - cost = BITRUNNER_COST_APEX_BOSS + cost = BITRUNNER_COST_APEX_BOSS // VOIDCREW EDIT: research prices virtual boss domains and supplies their domain briefing. desc = "Legends speak of the ravenous Wendigo hidden deep within the caves of Icemoon." difficulty = BITRUNNER_DIFFICULTY_HIGH forced_outfit = /datum/outfit/job/miner + // VOIDCREW EDIT START: research prices virtual boss domains and supplies their domain briefing. help_text = "The wendigo has the cache. Kill it, take the cache, and bring it back to the \ safehouse goal tile. It slams the ground to throw you across the arena and fires shockwaves \ in spirals and expanding walls, so distance on its own will not keep you safe. Below half \ health it teleports back to where the fight started and opens up with heavier shockwave \ patterns. The bodies out there are the last crew that tried this." + // VOIDCREW EDIT END key = "wendigo" map_name = "wendigo" reward_points = BITRUNNER_REWARD_HIGH diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index 90cff8e20e4..f1d625a81b9 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -1,6 +1,5 @@ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/export/large/crate - cost = CARGO_CRATE_VALUE * 0.25 + cost = CARGO_CRATE_VALUE * 0.25 // VOIDCREW EDIT: cargo tunes salvage refunds to ship shipment prices. k_elasticity = 0 unit_name = "crate" export_types = list(/obj/structure/closet/crate) @@ -11,12 +10,13 @@ /obj/structure/closet/crate/wooden, ) -// VOIDCREW EDIT END /datum/export/large/crate/total_printout(datum/export_report/ex, notes = TRUE) // That's why a goddamn metal crate costs that much. . = ..() if(. && notes) . += " Thanks for participating in Nanotrasen Crates Recycling Program." +// VOIDCREW EDIT: cargo caps crate resale against the settled shipment; implementation in voidcrew/edits/modules/cargo/exports/large_objects.dm. + /datum/export/large/crate/wooden cost = CARGO_CRATE_VALUE/5 unit_name = "large wooden crate" @@ -47,20 +47,16 @@ return ..() + round(contents_cost * ratio) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/export/large/reagent_dispenser/water unit_name = "watertank" export_types = list(/obj/structure/reagent_dispensers/watertank) - contents_cost = CARGO_CRATE_VALUE * 0.25 + contents_cost = CARGO_CRATE_VALUE * 0.25 // VOIDCREW EDIT: cargo tunes salvage refunds to ship shipment prices. -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/export/large/reagent_dispenser/fuel unit_name = "fueltank" export_types = list(/obj/structure/reagent_dispensers/fueltank) - contents_cost = CARGO_CRATE_VALUE * 0.55 + contents_cost = CARGO_CRATE_VALUE * 0.55 // VOIDCREW EDIT: cargo tunes salvage refunds to ship shipment prices. -// VOIDCREW EDIT END /datum/export/large/reagent_dispenser/beer unit_name = "beer keg" contents_cost = CARGO_CRATE_VALUE * 3.5 diff --git a/code/modules/cargo/exports/manifest.dm b/code/modules/cargo/exports/manifest.dm index 4074fdacda3..56a0b06306c 100644 --- a/code/modules/cargo/exports/manifest.dm +++ b/code/modules/cargo/exports/manifest.dm @@ -2,15 +2,15 @@ // Approved manifest. // At most20 credits or10% of payment: cheap goodies and flash coupons cannot subsidize themselves. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/export/manifest_correct - cost = CARGO_CRATE_VALUE * 0.1 + cost = CARGO_CRATE_VALUE * 0.1 // VOIDCREW EDIT: cargo caps manifest resale against shipment payment. k_elasticity = 0 unit_name = "approved manifest" export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest) scannable = FALSE -// VOIDCREW EDIT END +// VOIDCREW EDIT: cargo caps manifest refunds against the paid order; implementation in voidcrew/edits/modules/cargo/exports/manifest.dm. + /datum/export/manifest_correct/applies_to(obj/O) if(!..()) return FALSE diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm index ffbff8594f8..af8b729a817 100644 --- a/code/modules/cargo/exports/materials.dm +++ b/code/modules/cargo/exports/materials.dm @@ -33,14 +33,16 @@ // Materials. Static materials exist as parent types, while materials subject to the stock market have a fluid cost as determined by material/market types // If you're adding a new material to the stock market, make sure its export type is added here. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. +// VOIDCREW EDIT: cargo shares the plasma resale ceiling with stock blocks; implementation in voidcrew/edits/modules/cargo/exports/materials.dm. + /datum/export/material/plasma - cost = 10 + cost = 10 // VOIDCREW EDIT: cargo caps plasma resale across loose and market exports. k_elasticity = 0 material_id = /datum/material/plasma message = "cm3 of plasma" -// VOIDCREW EDIT END +// VOIDCREW EDIT: cargo applies the plasma resale ceiling to loose material; implementation in voidcrew/edits/modules/cargo/exports/materials.dm. + /datum/export/material/bananium cost = CARGO_CRATE_VALUE * 2 material_id = /datum/material/bananium @@ -172,9 +174,6 @@ /obj/item/stock_block, ) //For whatever reason, bluespace crystals are not a mineral -// VOIDCREW EDIT: plasma trades on the materials market here (see basemats.dm). -// Direct plasma is matched by the earlier datum. Blocks must obey its same -// ceiling, including a fixed quote captured before prices or balance changed. /datum/export/material/market/iron message = "cm3 of iron" material_id = /datum/material/iron diff --git a/code/modules/cargo/exports/sheets.dm b/code/modules/cargo/exports/sheets.dm index 5ca1df5f6c6..2e1eeea6f73 100644 --- a/code/modules/cargo/exports/sheets.dm +++ b/code/modules/cargo/exports/sheets.dm @@ -66,7 +66,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/export/stack/plasteel - cost = CARGO_CRATE_VALUE * 0.1 + cost = CARGO_CRATE_VALUE * 0.1 // VOIDCREW EDIT: cargo keeps plasteel salvage below its shipment price. message = "of plasteel" export_types = list(/obj/item/stack/sheet/plasteel) diff --git a/code/modules/cargo/materials_market.dm b/code/modules/cargo/materials_market.dm index bcbf871cd0d..d341c53f7de 100644 --- a/code/modules/cargo/materials_market.dm +++ b/code/modules/cargo/materials_market.dm @@ -100,14 +100,7 @@ else set_light(initial(light_range), initial(light_power)) -/** - * VOIDCREW EDIT ADDITION: four seams so a market that is not bolted to a station's cargo - * department can still work. Nothing in this fork ever ships SSshuttle.shopping_list - - * deliveries run off the per-ship cargo console's own cart (voidcrew/modules/cargo/shipping) - * - and there is no ACCOUNT_CAR budget and no crew member holding ACCESS_CARGO, so an order - * placed here used to be quoted against the wrong account and then filed into a list nothing - * reads. Overridden in voidcrew/edits/materials_market.dm. - */ +// VOIDCREW EDIT: cargo supplies market account and cart hooks; implementation in voidcrew/edits/machinery/materials_market.dm. /** * Find the order purchased either privately or by cargo budget @@ -115,9 +108,8 @@ * * [user][mob] - the user who placed this order * * is_ordering_private - is the player ordering privatly. If FALSE it means they are using cargo budget */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/materials_market/proc/find_order(mob/user, is_ordering_private) - for(var/datum/supply_order/order in get_order_list()) + for(var/datum/supply_order/order in get_order_list()) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. // Must be a Galactic Materials Market order and payed by the null account(if ordered via cargo budget) or by correct user for private purchase if(order.orderer_rank == GALATIC_MATERIAL_ORDER && ( \ (!is_ordering_private && isnull(order.paying_account)) || \ @@ -126,7 +118,6 @@ return order return null -// VOIDCREW EDIT END /obj/machinery/materials_market/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!anchored) @@ -139,19 +130,19 @@ . = list() .["CARGO_CRATE_VALUE"] = CARGO_CRATE_VALUE -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/materials_market/ui_data(mob/user) . = list() //can this player use cargo budget + // VOIDCREW EDIT REMOVAL: cargo routes material orders through ship accounts and validates the pooled cart. var/obj/item/card/id/used_id_card if(isliving(user)) var/mob/living/living_user = user used_id_card = living_user.get_idcard(TRUE) - var/can_buy_via_budget = can_order_on_budget(used_id_card) + var/can_buy_via_budget = can_order_on_budget(used_id_card) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. //if no cargo access then force private purchase - var/is_ordering_private = ordering_privately(used_id_card) + var/is_ordering_private = ordering_privately(used_id_card) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. //find current order based on ordering mode & player var/datum/supply_order/current_order = find_order(user, is_ordering_private) @@ -222,7 +213,7 @@ // this proc uses `is_ordering_private`, so a buyer with no cargo access was quoted against // the budget's balance and then charged their own. Ask the seam that ui_act() bills. var/datum/bank_account/quoted_account = market_account(used_id_card, is_ordering_private) - var/balance = quoted_account?.account_balance || 0 + var/balance = quoted_account?.account_balance || 0 // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. //is market crashing var/market_crashing = FALSE @@ -243,8 +234,6 @@ .["canOrderCargo"] = can_buy_via_budget .["updateTime"] = SSstock_market.next_fire - world.time -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/materials_market/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) @@ -256,18 +245,20 @@ if(isnull(used_id_card)) say("No ID Found") return - var/can_buy_via_budget = can_order_on_budget(used_id_card) + var/can_buy_via_budget = can_order_on_budget(used_id_card) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. //if multiple users open the UI some of them may not have the required access so we recheck - var/is_ordering_private = ordering_privately(used_id_card) + var/is_ordering_private = ordering_privately(used_id_card) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. switch(action) if("buy") var/material_str = params["material"] + // VOIDCREW EDIT START: cargo routes material orders through ship accounts and validates the pooled cart. var/quantity = isnum(params["quantity"]) ? params["quantity"] : text2num(params["quantity"]) if(!valid_cargo_order_quantity(quantity, MAX_STACK_SIZE * MAX_STACK_LIMIT)) say("Order a whole number of sheets, from 1 to [MAX_STACK_SIZE * MAX_STACK_LIMIT].") return FALSE + // VOIDCREW EDIT END //find material from its name var/datum/material/material_bought @@ -277,13 +268,13 @@ material_bought = mat break if(!material_bought) - return FALSE + return FALSE // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. sheet_to_buy = initial(material_bought.sheet_type) if(!sheet_to_buy) CRASH("Material with no sheet type being sold on materials market!") //get available bank account for purchasing - var/datum/bank_account/account_payable = market_account(used_id_card, is_ordering_private) + var/datum/bank_account/account_payable = market_account(used_id_card, is_ordering_private) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. if(!account_payable) say("No bank account detected!") return @@ -302,16 +293,19 @@ // We want to count how many stacks of all sheets we're ordering to make sure they don't exceed the limit of 10 // If we already have a custom order on SSshuttle, we should add the things to order to that order var/datum/supply_order/current_order = find_order(living_user, is_ordering_private) + // VOIDCREW EDIT START: cargo routes material orders through ship accounts and validates the pooled cart. var/list/proposed_contents = current_order ? current_order.pack.contains.Copy() : list() proposed_contents[sheet_to_buy] += quantity if(!valid_material_order_contents(proposed_contents)) say("One material order can contain at most [MAX_STACK_LIMIT] stacks across all materials.") return FALSE + // VOIDCREW EDIT END if(!isnull(current_order)) // Check if this order exceeded the market limit var/prior_sheets = current_order.pack.contains[sheet_to_buy] if(prior_sheets + quantity > SSstock_market.materials_quantity[material_bought] ) say("There aren't enough sheets on the market! Please wait for more sheets to be traded before adding more.") + // VOIDCREW EDIT REMOVAL: cargo routes material orders through ship accounts and validates the pooled cart. playsound(usr, 'sound/machines/synth/synth_no.ogg', 35, FALSE) return @@ -352,11 +346,13 @@ // VOIDCREW EDIT CHANGE - original: `SSshuttle.shopping_list += new_order`. The seam // says no by returning null, and has already told the buyer why. var/list/order_list = get_order_list(announce_refusal = TRUE) + // VOIDCREW EDIT START: cargo routes material orders through ship accounts and validates the pooled cart. if(isnull(order_list)) qdel(new_order) return + // VOIDCREW EDIT END say("Thank you for your purchase! It will arrive on the next cargo shuttle!") - order_list += new_order + order_list += new_order // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. return TRUE if("toggle_budget") @@ -369,13 +365,14 @@ var/datum/supply_order/current_order = find_order(living_user, is_ordering_private) if(!isnull(current_order)) var/list/order_list = get_order_list() // VOIDCREW EDIT CHANGE - original: `SSshuttle.shopping_list` + // VOIDCREW EDIT START: cargo routes material orders through ship accounts and validates the pooled cart. if(isnull(order_list)) return order_list -= current_order + // VOIDCREW EDIT END qdel(current_order) return TRUE -// VOIDCREW EDIT END /obj/item/stock_block name = "stock block" desc = "A block of stock. It's worth a certain amount of money, based on a sale on the materials market. Ship it on the cargo shuttle to claim your money." @@ -408,11 +405,10 @@ icon_state = "stock_block_fluid" update_appearance(UPDATE_ICON_STATE) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/stock_block/proc/update_value() if(!SSstock_market.materials_prices[export_mat]) return - export_value = quantity * (export_mat == /datum/material/plasma ? plasma_export_bid() : SSstock_market.materials_prices[export_mat]) + export_value = quantity * (export_mat == /datum/material/plasma ? plasma_export_bid() : SSstock_market.materials_prices[export_mat]) // VOIDCREW EDIT: cargo routes material orders through ship accounts and validates the pooled cart. icon_state = "stock_block_liquid" update_appearance(UPDATE_ICON_STATE) visible_message(span_warning("\The [src] becomes liquid!")) @@ -420,4 +416,3 @@ #undef MAX_STACK_LIMIT #undef GALATIC_MATERIAL_ORDER -// VOIDCREW EDIT END diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm index 967debd2b20..b4851affd17 100644 --- a/code/modules/cargo/order.dm +++ b/code/modules/cargo/order.dm @@ -41,7 +41,6 @@ /obj/item/paper/fluff/jobs/cargo/manifest/proc/is_denied() return LAZYLEN(stamp_cache) && ("stamp-deny" in stamp_cache) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/supply_order var/id var/cost_type @@ -62,7 +61,6 @@ ///Boolean on whether the manifest can be cancelled through cargo consoles. var/can_be_cancelled = TRUE -// VOIDCREW EDIT END /datum/supply_order/New( datum/supply_pack/pack, orderer, @@ -104,6 +102,8 @@ cost *= 1.1 return round(cost) +// VOIDCREW EDIT: cargo settles ship orders before goods are generated; implementation in voidcrew/edits/modules/cargo/order.dm. + /datum/supply_order/proc/generateRequisition(turf/T) var/obj/item/paper/requisition/requisition_paper = new(T) @@ -184,7 +184,6 @@ return manifest_paper -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/supply_order/proc/generate(atom/A) var/account_holder if(paying_account) @@ -197,11 +196,12 @@ ADD_TRAIT(item_within, TRAIT_CONTRABAND, INNATE_TRAIT) if(department_destination) crate.AddElement(/datum/element/deliver_first, department_destination, pack.cost) + // VOIDCREW EDIT START: cargo tracks the settled ship payment on crates and manifests. crate.cargo_paid_cost = ship_paid_cost generateManifest(crate, account_holder, pack, isnull(ship_paid_cost) ? pack.cost : ship_paid_cost) + // VOIDCREW EDIT END return crate -// VOIDCREW EDIT END /datum/supply_order/proc/generateCombo(miscbox, misc_own, misc_contents, misc_cost) for (var/I in misc_contents) new I(miscbox) @@ -223,14 +223,12 @@ return ..() /// Custom material order to append cargo crate value to the final order cost -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/supply_order/disposable/materials/get_final_cost() // The material quote is captured when ordered. It is not an ordinary pack // price, and must not receive a station-trait modifier or a coupon a second time. - return round(pack.cost) + CARGO_CRATE_VALUE + return round(pack.cost) + CARGO_CRATE_VALUE // VOIDCREW EDIT: cargo tracks the settled ship payment on crates and manifests. #undef MANIFEST_ERROR_CHANCE #undef MANIFEST_ERROR_NAME #undef MANIFEST_ERROR_CONTENTS #undef MANIFEST_ERROR_ITEM -// VOIDCREW EDIT END diff --git a/code/modules/cargo/packs/_packs.dm b/code/modules/cargo/packs/_packs.dm index 71f8ed26c7a..967eba21bd7 100644 --- a/code/modules/cargo/packs/_packs.dm +++ b/code/modules/cargo/packs/_packs.dm @@ -149,6 +149,8 @@ src.cost = cost src.contains = contains +// VOIDCREW EDIT: cargo validates and commits pooled material orders; implementation in voidcrew/edits/modules/cargo/packs/_packs.dm. + ///Alters material amrkey & adjust order quantities if they exceed whats on the market /datum/supply_pack/custom/minerals/proc/adjust_market() . = list() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 1b2906f674a..fadba8723cd 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -97,7 +97,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) /datum/preferences/New(client/parent) src.parent = parent // Voidcrew has no antagonist preferences page, so offer all roles by default. - be_special = assoc_to_keys(get_all_antag_flags()) + be_special = assoc_to_keys(get_all_antag_flags()) // VOIDCREW EDIT: preferences enables available antagonist roles without an antagonist preference page. for (var/middleware_type in subtypesof(/datum/preference_middleware)) middleware += new middleware_type(src) @@ -132,7 +132,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) save_preferences() save_character() //let's save this new random character so it doesn't keep generating new ones. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/preferences/ui_interact(mob/user, datum/tgui/ui) // There used to be code here that readded the preview view if you "rejoined" // I'm making the assumption that ui close will be called whenever a user logs out, or loses a window @@ -147,16 +146,17 @@ GLOBAL_LIST_EMPTY(preferences_datums) // If the preview could not survive being built, the menu was closed again while // we were building it. Opening on a dead preview produces a permanently blank // window (see create_character_preview_view); doing nothing costs one click. + // VOIDCREW EDIT START: preferences recovers character previews lost while the UI sleeps. if(isnull(create_character_preview_view(user))) return + // VOIDCREW EDIT END ui = new(user, src, "PreferencesMenu") ui.set_autoupdate(FALSE) ui.open() // open() sends the preference spritesheets, which sleeps too, so the same race // can still land here. - character_preview_view?.display_to(user, ui.window) + character_preview_view?.display_to(user, ui.window) // VOIDCREW EDIT: preferences recovers character previews lost while the UI sleeps. -// VOIDCREW EDIT END /datum/preferences/ui_state(mob/user) return GLOB.always_state @@ -181,7 +181,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) return data -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/preferences/ui_static_data(mob/user) var/list/data = list() @@ -190,7 +189,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) // Rebuild rather than deref: a runtime here silently drops the entire static half of // the payload, and data["window"] two lines down is what PreferencesMenu routes on - // without it the interface throws and the player is left with a blank dark window. - data["character_preview_view"] = get_character_preview_view(user)?.assigned_map + data["character_preview_view"] = get_character_preview_view(user)?.assigned_map // VOIDCREW EDIT: preferences recovers character previews lost while the UI sleeps. data["overflow_role"] = SSjob.get_job_type(SSjob.overflow_role).title data["window"] = current_window @@ -201,7 +200,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) return data -// VOIDCREW EDIT END /datum/preferences/ui_assets(mob/user) var/list/assets = list( get_asset_datum(/datum/asset/spritesheet_batched/preferences), @@ -304,12 +302,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) ui_interact(usr) return TRUE -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/preferences/proc/create_character_preview_view(mob/user) + // VOIDCREW EDIT START: preferences recovers character previews lost while the UI sleeps. var/atom/movable/screen/map_view/char_preview/preview = new(null, src) character_preview_view = preview preview.generate_view("character_preview_[REF(preview)]") preview.update_body() + // VOIDCREW EDIT END // update_body() sleeps. Anything that runs ui_close() while it does - closing an // already open preferences window is enough - hits QDEL_NULL(character_preview_view) @@ -324,6 +323,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) // // Report the loss honestly instead, so the caller can back out rather than open a // menu that can never render. + // VOIDCREW EDIT START: preferences recovers character previews lost while the UI sleeps. if(QDELETED(preview)) return null @@ -335,8 +335,10 @@ GLOBAL_LIST_EMPTY(preferences_datums) character_preview_view = preview return preview + // VOIDCREW EDIT END + +// VOIDCREW EDIT: preferences rebuilds character previews lost during UI opening; implementation in voidcrew/edits/modules/client/preferences.dm. -// VOIDCREW EDIT END /datum/preferences/proc/compile_character_preferences(mob/user) var/list/preferences = list() diff --git a/code/modules/client/preferences/screentips.dm b/code/modules/client/preferences/screentips.dm index 52f982e2e04..ab651ecdc8e 100644 --- a/code/modules/client/preferences/screentips.dm +++ b/code/modules/client/preferences/screentips.dm @@ -11,7 +11,7 @@ /datum/preference/choiced/enable_screentips/apply_to_client(client/client, value) client.mob?.hud_used?.screentips_enabled = value - client.mob?.hud_used?.screentip_text?.refresh_hover() + client.mob?.hud_used?.screentip_text?.refresh_hover() // VOIDCREW EDIT: preferences refreshes the live screentip after a setting change. /datum/preference/choiced/enable_screentips/deserialize(input, datum/preferences/preferences) // Migrate old always disabled screentips to context only. diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 48069f1f508..477fb842636 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -13,9 +13,7 @@ /// You do not need to raise this if you are adding new values that have sane defaults. /// Only raise this value when changing the meaning/format/name/layout of an existing value /// where you would want the updater procs below to run -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -#define SAVEFILE_VERSION_MAX 50 -// VOIDCREW EDIT END +#define SAVEFILE_VERSION_MAX 50 // VOIDCREW EDIT: preferences migrates existing accounts to the available ship-role defaults. #define IS_DATA_OBSOLETE(version) (version == SAVE_DATA_OBSOLETE) #define SHOULD_UPDATE_DATA(version) (version >= SAVE_DATA_NO_ERROR && version < SAVEFILE_VERSION_MAX) @@ -109,9 +107,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if (current_version < 44) update_tts_blip_prefs() + // VOIDCREW EDIT START: preferences migrates existing accounts to the available ship-role defaults. if(current_version < 50) // Apply Voidcrew's all-role default to existing accounts as well. be_special = assoc_to_keys(get_all_antag_flags()) + // VOIDCREW EDIT END /datum/preferences/proc/update_character(current_version, list/save_data) if (current_version < 41) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index cb72bcc108a..2a8fef737a7 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -109,20 +109,20 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") if(!holder.fakekey || receiver.holder) if(check_rights_for(src, R_ADMIN)) var/ooc_color = prefs.read_preference(/datum/preference/color/ooc_color) - to_chat(receiver, span_adminooc("[CONFIG_GET(flag/allow_admin_ooccolor) && ooc_color ? "" :"" ][span_prefix("OOC:")] [keyname][holder.fakekey ? "/([holder.fakekey])" : ""]: [receiver_msg]"), avoid_highlighting = avoid_highlight) + to_chat(receiver, span_adminooc("[CONFIG_GET(flag/allow_admin_ooccolor) && ooc_color ? "" :"" ][span_prefix("OOC:")] [keyname][holder.fakekey ? "/([holder.fakekey])" : ""]: [receiver_msg]"), avoid_highlighting = avoid_highlight) // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. else - to_chat(receiver, span_adminobserverooc(span_prefix("OOC: [keyname][holder.fakekey ? "/([holder.fakekey])" : ""]: [receiver_msg]")), avoid_highlighting = avoid_highlight) + to_chat(receiver, span_adminobserverooc(span_prefix("OOC: [keyname][holder.fakekey ? "/([holder.fakekey])" : ""]: [receiver_msg]")), avoid_highlighting = avoid_highlight) // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. else if(GLOB.OOC_COLOR) - to_chat(receiver, "[span_prefix("OOC:")] [holder.fakekey ? holder.fakekey : key]: [receiver_msg]", avoid_highlighting = avoid_highlight) + to_chat(receiver, "[span_prefix("OOC:")] [holder.fakekey ? holder.fakekey : key]: [receiver_msg]", avoid_highlighting = avoid_highlight) // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. else - to_chat(receiver, span_ooc(span_prefix("OOC: [holder.fakekey ? holder.fakekey : key]: [receiver_msg]")), avoid_highlighting = avoid_highlight) + to_chat(receiver, span_ooc(span_prefix("OOC: [holder.fakekey ? holder.fakekey : key]: [receiver_msg]")), avoid_highlighting = avoid_highlight) // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. - else + else // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. if(GLOB.OOC_COLOR) - to_chat(receiver, "[span_prefix("OOC:")] [keyname]: [receiver_msg]", avoid_highlighting = avoid_highlight) + to_chat(receiver, "[span_prefix("OOC:")] [keyname]: [receiver_msg]", avoid_highlighting = avoid_highlight) // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. else - to_chat(receiver, span_ooc(span_prefix("OOC: [keyname]: [receiver_msg]")), avoid_highlighting = avoid_highlight) + to_chat(receiver, span_ooc(span_prefix("OOC: [keyname]: [receiver_msg]")), avoid_highlighting = avoid_highlight) // VOIDCREW EDIT: autotranslate delivers each recipient their translated OOC message. // VOIDCREW EDIT ADDITION BEGIN - AUTOTRANSLATE // Cache hits can finish immediately, so queue the original line first. translation?.begin() diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index bfa3e4c8ee4..0a213b46c00 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -563,7 +563,7 @@ BLIND // can't see anything if(visor_vars_to_toggle & VISOR_TINT) carbon_user.update_tint() if((visor_flags & (MASKINTERNALS|HEADINTERNALS)) && carbon_user.invalid_internals()) - carbon_user.cutoff_internals("visor adjusted on [type], up=[up]") + carbon_user.cutoff_internals("visor adjusted on [type], up=[up]") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) return TRUE // VOIDCREW EDIT END diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index 7a7a14a1dc5..487537dabd8 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -169,7 +169,6 @@ modes = list(MODE_NONE = MODE_ATMOS_THERMAL, MODE_ATMOS_THERMAL = MODE_NONE) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/glasses/meson/engine/atmos_imaging/update_icon_state() icon_state = inhand_icon_state = "trayson-[mode]" return ..() @@ -183,14 +182,14 @@ * case. A remote operator - the ship construction console's drone pilot - has to pass the * camera, or the readout appears around them at the console rather than around the drone. */ -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/proc/atmos_thermal(mob/viewer, range = 5, duration = 10, atom/centre) +/proc/atmos_thermal(mob/viewer, range = 5, duration = 10, atom/centre) // VOIDCREW EDIT: shuttle construction: scan around the remote drone while retaining the handheld default if(!ismob(viewer) || !viewer.client) return + // VOIDCREW EDIT START - shuttle construction: scan around the remote drone while retaining the handheld default if(isnull(centre)) centre = viewer for(var/turf/open in view(range, centre)) + // VOIDCREW EDIT END if(open.blocks_air) continue var/datum/gas_mixture/environment = open.return_air() @@ -227,4 +226,3 @@ #undef TEMP_SHADE_GREEN #undef TEMP_SHADE_YELLOW #undef TEMP_SHADE_RED -// VOIDCREW EDIT END diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index d86d9e08717..0eb0e028a78 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -6,9 +6,11 @@ name = "hard hat" desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight." icon_state = "hardhat0_yellow" + // VOIDCREW EDIT START - Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing inhand_icon_state = "hardhat_yellow" lefthand_file = 'voidcrew/icons/mob/inhands/clothing/hardhat_lefthand.dmi' righthand_file = 'voidcrew/icons/mob/inhands/clothing/hardhat_righthand.dmi' + // VOIDCREW EDIT END armor_type = /datum/armor/utility_hardhat flags_inv = 0 hair_mask = /datum/hair_mask/standard_hat_middle @@ -54,11 +56,13 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/update_icon_state() + // VOIDCREW EDIT START - Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing icon_state = "hardhat[on]_[hat_type]" if(hat_type == "cakehat" || hat_type == "energycake") inhand_icon_state = icon_state else inhand_icon_state = "hardhat_[hat_type]" + // VOIDCREW EDIT END return ..() // VOIDCREW EDIT END @@ -80,7 +84,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/orange icon_state = "hardhat0_orange" - inhand_icon_state = "hardhat_orange" + inhand_icon_state = "hardhat_orange" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "orange" dog_fashion = null @@ -88,7 +92,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/red icon_state = "hardhat0_red" - inhand_icon_state = "hardhat_red" + inhand_icon_state = "hardhat_red" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "red" dog_fashion = null name = "firefighter helmet" @@ -104,7 +108,7 @@ name = "workplace-ready firefighter helmet" desc = "By applying state of the art lighting technology to a fire helmet, and using photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards." icon_state = "hardhat0_purple" - inhand_icon_state = "hardhat_purple" + inhand_icon_state = "hardhat_purple" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing light_range = 5 resistance_flags = FIRE_PROOF | ACID_PROOF custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT*2, /datum/material/glass =HALF_SHEET_MATERIAL_AMOUNT, /datum/material/plastic = SHEET_MATERIAL_AMOUNT*1.5, /datum/material/silver = SMALL_MATERIAL_AMOUNT*5) @@ -114,7 +118,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/white icon_state = "hardhat0_white" - inhand_icon_state = "hardhat_white" + inhand_icon_state = "hardhat_white" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "white" clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT heat_protection = HEAD @@ -127,7 +131,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/dblue icon_state = "hardhat0_dblue" - inhand_icon_state = "hardhat_dblue" + inhand_icon_state = "hardhat_dblue" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "dblue" dog_fashion = null @@ -187,7 +191,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/welding/orange icon_state = "hardhat0_orange" - inhand_icon_state = "hardhat_orange" + inhand_icon_state = "hardhat_orange" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "orange" // VOIDCREW EDIT END @@ -195,7 +199,7 @@ /obj/item/clothing/head/utility/hardhat/welding/white desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight AND welding shield!" //This bulb is not smaller icon_state = "hardhat0_white" - inhand_icon_state = "hardhat_white" + inhand_icon_state = "hardhat_white" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing light_range = 4 //Boss always takes the best stuff hat_type = "white" clothing_flags = STOPSPRESSUREDAMAGE | STACKABLE_HELMET_EXEMPT @@ -217,14 +221,14 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/welding/dblue icon_state = "hardhat0_dblue" - inhand_icon_state = "hardhat_dblue" + inhand_icon_state = "hardhat_dblue" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "dblue" // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/clothing/head/utility/hardhat/welding/atmos icon_state = "hardhat0_atmos" - inhand_icon_state = "hardhat_atmos" + inhand_icon_state = "hardhat_atmos" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "atmos" dog_fashion = null name = "atmospheric firefighter helmet" @@ -255,7 +259,7 @@ icon = 'icons/obj/clothing/head/costume.dmi' worn_icon = 'icons/mob/clothing/head/costume.dmi' icon_state = "hardhat0_pumpkin" - inhand_icon_state = "hardhat_pumpkin" + inhand_icon_state = "hardhat_pumpkin" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "pumpkin" clothing_flags = SNUG_FIT | STACKABLE_HELMET_EXEMPT flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT @@ -307,7 +311,7 @@ name = "carved blumpkin" desc = "A very blue jack o' lantern! Believed to ward off vengeful chemists." icon_state = "hardhat0_blumpkin" - inhand_icon_state = "hardhat_blumpkin" + inhand_icon_state = "hardhat_blumpkin" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "blumpkin" light_color = "#76ff8e" dog_fashion = /datum/dog_fashion/head/blumpkin/unlit @@ -328,7 +332,7 @@ icon = 'icons/obj/clothing/head/costume.dmi' worn_icon = 'icons/mob/clothing/head/costume.dmi' icon_state = "hardhat0_reindeer" - inhand_icon_state = "hardhat_reindeer" + inhand_icon_state = "hardhat_reindeer" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing hat_type = "reindeer" flags_inv = 0 hair_mask = "" diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index 54ca5ef17c0..ed051b940b8 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -325,9 +325,11 @@ name = "ushanka" desc = "Perfect for winter in Siberia, da?" icon_state = "ushankadown" + // VOIDCREW EDIT START - Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing inhand_icon_state = "ushanka" lefthand_file = 'voidcrew/icons/mob/inhands/clothing/ushanka_lefthand.dmi' righthand_file = 'voidcrew/icons/mob/inhands/clothing/ushanka_righthand.dmi' + // VOIDCREW EDIT END flags_inv = HIDEEARS|HIDEHAIR cold_protection = HEAD min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT @@ -342,9 +344,11 @@ /obj/item/clothing/head/costume/ushanka/attack_self(mob/user) if(earflaps) icon_state = upsprite + // VOIDCREW EDIT REMOVAL - Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing to_chat(user, span_notice("You raise the ear flaps on the ushanka.")) else icon_state = downsprite + // VOIDCREW EDIT REMOVAL - Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing to_chat(user, span_notice("You lower the ear flaps on the ushanka.")) earflaps = !earflaps @@ -354,7 +358,7 @@ name = "bear hunter's ushanka" desc = "Handcrafted in Siberia from real polar bears." icon_state = "ushankadown_polar" - inhand_icon_state = "ushanka_polar" + inhand_icon_state = "ushanka_polar" // VOIDCREW EDIT: Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing upsprite = "ushankaup_polar" downsprite = "ushankadown_polar" diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 943d583962d..5b31b862a35 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -175,9 +175,11 @@ /obj/item/clothing/head/utility/radiation name = "radiation hood" icon_state = "rad" + // VOIDCREW EDIT START - Voidcrew clothing sprites: use dedicated inhand states from voidcrew/icons/mob/inhands/clothing inhand_icon_state = "rad" lefthand_file = 'voidcrew/icons/mob/inhands/clothing/radiation_hood_lefthand.dmi' righthand_file = 'voidcrew/icons/mob/inhands/clothing/radiation_hood_righthand.dmi' + // VOIDCREW EDIT END desc = "A hood with radiation protective properties. The label reads, 'Made with lead. Please do not consume insulation.'" clothing_flags = THICKMATERIAL | SNUG_FIT flags_inv = HIDEMASK|HIDEEARS|HIDEFACE|HIDEEYES|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index af104abc216..da1baf0b539 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -1,33 +1,11 @@ GLOBAL_VAR_INIT(total_runtimes, GLOB.total_runtimes || 0) GLOBAL_VAR_INIT(total_runtimes_skipped, 0) -/* - * VOIDCREW ADDITION - runtime flood breaker state. - * - * Plain numbers on purpose. The failure these guard against (round-7, 2026-08-16) is one - * where EVERY list operation in the world starts throwing "bad list" - a boot-time, - * never-mutated list like the config subsystem's entries_by_type failed a plain read, - * as did client keybinding caches, SSgarbage's queues and this handler's own static - * error_last_seen. Anything here that touched a list or a config entry would throw on the - * way to the breaker and hand control back to BYOND's built-in handler, which is what - * actually wrote 337 MB of dd.log in 46 seconds. GLOB var reads are a global slot lookup - * and kept working throughout (GLOB.total_runtimes counted the whole flood), so the - * breaker is built out of those and nothing else. - */ -/// world.time-derived index of the flood window we are currently counting in. -GLOBAL_VAR_INIT(error_flood_window, 0) -/// Runtimes handled so far in this window. -GLOBAL_VAR_INIT(error_flood_count, 0) -/// Runtimes dropped by the breaker in this window. -GLOBAL_VAR_INIT(error_flood_suppressed, 0) -/// While world.time is below this, world/Error emits one flat line per runtime and does -/// nothing else - set when the handler itself threw. See the catch in world/Error. -GLOBAL_VAR_INIT(error_handler_degraded_until, 0) - #ifdef USE_CUSTOM_ERROR_HANDLER #define ERROR_USEFUL_LEN 2 /// Length of a flood-breaker window, in deciseconds. +// VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. #define ERROR_FLOOD_WINDOW 10 /// Runtimes fully handled per ERROR_FLOOD_WINDOW before the breaker starts dropping them. /// Normal play sits under one runtime a second; round-7's flood ran at 81,000 log lines a @@ -39,6 +17,7 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) /// How long world/Error stays on its flat one-line path after throwing while handling a /// runtime. Short, because a single unlucky exception should not blind the log for long. #define ERROR_HANDLER_DEGRADE_TIME 50 +// VOIDCREW EDIT END /world/Error(exception/E, datum/e_src) GLOB.total_runtimes++ @@ -101,6 +80,7 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) // // Off under UNIT_TESTS: a dropped runtime never reaches GLOB.current_test.Fail(), and // a test suite that silently stops failing is worse than a slow one. +// VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. #ifndef UNIT_TESTS var/flood_window = round(world.time / ERROR_FLOOD_WINDOW) if(flood_window != GLOB.error_flood_window) @@ -115,6 +95,7 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) GLOB.error_flood_suppressed++ return #endif +// VOIDCREW EDIT END var/static/regex/stack_workaround if(isnull(stack_workaround)) @@ -128,11 +109,13 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) // VOIDCREW ADDITION: the handler threw recently, so don't try the rich path again yet - // just get the runtime on the record in one line. See the catch below. +// VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. #ifndef UNIT_TESTS if(world.time < GLOB.error_handler_degraded_until) SEND_TEXT(world.log, "\[[time2text(world.timeofday, "hh:mm:ss")]\] Runtime in [E.file],[E.line]: [E] (handler degraded)") return #endif +// VOIDCREW EDIT END // VOIDCREW ADDITION: everything from here down touches lists, the config subsystem, the // error cache and the structured logger, and every one of those threw in round-7. A @@ -140,6 +123,7 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) // handler, which prints the full call stack of the ORIGINAL error once per unwound // frame - roughly a twenty-line block per runtime with no rate limit of any kind // attached to it. Catch it here and fall back to a flat line instead. + // VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. try if(stack_workaround.Find(E.name)) if(length(stack_workaround.group) > 0) @@ -179,9 +163,11 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) configured_error_limit = initial(CE.default) CE = /datum/config_entry/number/error_silence_time configured_error_silence_time = initial(CE.default) + // VOIDCREW EDIT END //Each occurence of a unique error adds to its cooldown time... + // VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. cooldown = max(0, cooldown - (world.time - last_seen)) + configured_error_cooldown // ... which is used to silence an error if it occurs too often, too fast if(cooldown > configured_error_cooldown * configured_error_limit) @@ -245,17 +231,23 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) SEND_TEXT(world.log, main_line) for(var/line in desclines) SEND_TEXT(world.log, line) + // VOIDCREW EDIT END #ifdef UNIT_TESTS + // VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. if(GLOB.current_test) //good day, sir GLOB.current_test.Fail("[main_line]\n[desclines.Join("\n")]", file = E.file, line = E.line) + // VOIDCREW EDIT END #endif + // VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. if(Debugger?.enabled) to_chat(world, span_alertwarning("[main_line]"), type = MESSAGE_TYPE_DEBUG) + // VOIDCREW EDIT END // This writes the regular format (unwrapping newlines and inserting timestamps as needed). + // VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. log_runtime("runtime error: [E.name]\n[E.desc]") catch(var/exception/handler_failure) // Two flat lines and a short degrade window. Nothing in here indexes a list, calls @@ -265,12 +257,15 @@ GLOBAL_VAR_INIT(error_handler_degraded_until, 0) GLOB.error_handler_degraded_until = world.time + ERROR_HANDLER_DEGRADE_TIME SEND_TEXT(world.log, "\[[time2text(world.timeofday, "hh:mm:ss")]\] Runtime in [E.file],[E.line]: [E]") SEND_TEXT(world.log, " RUNTIME HANDLER FAILED reporting the above ([handler_failure]) - flat logging for [ERROR_HANDLER_DEGRADE_TIME / 10] seconds.") + // VOIDCREW EDIT END #endif #undef ERROR_USEFUL_LEN +// VOIDCREW EDIT START: Bound runtime flood handling and keep flat logging available if the rich handler fails. #undef ERROR_FLOOD_WINDOW #undef ERROR_FLOOD_LIMIT #undef ERROR_HANDLER_DEGRADE_TIME +// VOIDCREW EDIT END /// Exists to trigger infinite recursion runtimes in testing /proc/recurse(times) diff --git a/code/modules/error_handler/error_viewer.dm b/code/modules/error_handler/error_viewer.dm index cc0e957f964..3a1c9798c51 100644 --- a/code/modules/error_handler/error_viewer.dm +++ b/code/modules/error_handler/error_viewer.dm @@ -33,9 +33,11 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) * and both numbers are shown in the viewer. */ /// Full copies retained per error signature (file + line). +// VOIDCREW EDIT START: Bound retained runtime entries while keeping source totals (voidcrew/edits/modules/error_handler/error_viewer.dm). #define ERROR_CACHE_MAX_PER_SOURCE 50 /// Ceiling on the flat all-errors list, across every source. #define ERROR_CACHE_MAX_ENTRIES 5000 +// VOIDCREW EDIT END // Common vars and procs are kept at the error_viewer level /datum/error_viewer @@ -121,6 +123,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) if (!error_source) error_source = new(e) error_sources[erroruid] = error_source + // VOIDCREW EDIT: Bound retained runtime entries while keeping source totals (voidcrew/edits/modules/error_handler/error_viewer.dm). error_source.total_errors++ // VOIDCREW EDIT: retain a bounded number of full copies per signature. Skip-count @@ -128,6 +131,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) // window, they are what tells you how big a flood actually was, and dropping them // would leave the viewer claiming a source went quiet when it did the opposite. if(length(error_source.errors) >= ERROR_CACHE_MAX_PER_SOURCE && !skip_count) + // VOIDCREW EDIT START: Bound retained runtime entries while keeping source totals (voidcrew/edits/modules/error_handler/error_viewer.dm). error_source.dropped_errors++ else var/datum/error_viewer/error_entry/error_entry = new(e, desclines, skip_count) @@ -135,6 +139,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) errors += error_entry error_source.errors += error_entry trim_to_cap() + // VOIDCREW EDIT END if (skip_count) return // Skip notifying admins about skipped errors. @@ -159,6 +164,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) * keeps the entry - and the /exception and description text hanging off it - alive, which * is the entire thing this is here to stop. */ +// VOIDCREW EDIT START: Bound retained runtime entries while keeping source totals (voidcrew/edits/modules/error_handler/error_viewer.dm). /datum/error_viewer/error_cache/proc/trim_to_cap() var/overflow = length(errors) - ERROR_CACHE_MAX_ENTRIES if(overflow <= 0) @@ -169,6 +175,7 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) if(source) source.errors -= oldest errors.Cut(1, overflow + 1) +// VOIDCREW EDIT END /datum/error_viewer/error_source var/list/errors = list() @@ -187,8 +194,10 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) var/html = build_header(back_to) // VOIDCREW ADDITION: say so when the list below is a sample rather than the whole story. + // VOIDCREW EDIT START: Bound retained runtime entries while keeping source totals (voidcrew/edits/modules/error_handler/error_viewer.dm). if(dropped_errors) html += "[total_errors] runtimes from this source; [dropped_errors] were counted but not retained (cap is [ERROR_CACHE_MAX_PER_SOURCE] per source).

" + // VOIDCREW EDIT END for (var/datum/error_viewer/error_entry/error_entry in errors) html += "[error_entry.make_link(null, src)]
" @@ -239,10 +248,10 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache) browse_to(user, html) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/error_viewer/error_entry/make_link(linktext, datum/error_viewer/back_to, linear) return is_skip_count ? name : ..() +// VOIDCREW EDIT START: Bound retained runtime entries while keeping source totals (voidcrew/edits/modules/error_handler/error_viewer.dm). #undef ERROR_CACHE_MAX_PER_SOURCE #undef ERROR_CACHE_MAX_ENTRIES // VOIDCREW EDIT END diff --git a/code/modules/events/wormholes.dm b/code/modules/events/wormholes.dm index 84aab707e30..6423525fe2f 100644 --- a/code/modules/events/wormholes.dm +++ b/code/modules/events/wormholes.dm @@ -26,7 +26,7 @@ GLOBAL_LIST_EMPTY(all_wormholes) // So we can pick wormholes to teleport to /datum/round_event/wormholes/start() for(var/turf/open/floor/valid in GLOB.station_turfs) - // VOIDCREW EDIT ADDITION: 400 portals are seeded out of this list and + // VOIDCREW EDIT ADDITION START: overmap - 400 portals are seeded out of this list and // /obj/effect/portal/wormhole/teleport() picks its destination from the GLOBAL // wormhole list with no z or site filter, so a portal on recycled encounter ground // walks a crewmember straight through the five-turf cordon into an unrelated @@ -38,7 +38,7 @@ GLOBAL_LIST_EMPTY(all_wormholes) // So we can pick wormholes to teleport to // VOIDCREW EDIT END pick_turfs += valid - // VOIDCREW EDIT ADDITION: pick() on an empty list runtimes, and the filter above can + // VOIDCREW EDIT ADDITION START: overmap - pick() on an empty list runtimes, and the filter above can // legitimately empty it (a fleet with no permanent station ground). if(!length(pick_turfs)) return diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm index 1deb6bb944d..5c5cd833375 100644 --- a/code/modules/experisci/experiment/handlers/experiment_handler.dm +++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm @@ -195,7 +195,7 @@ // (see CONNECT_TO_RND_SERVER_ROUNDSTART), so linked_web can legitimately be null; the ALWAYS_ACTIVE // branch below reads linked_web.available_experiments and would runtime on it. if (isnull(linked_web)) - return FALSE + return FALSE // VOIDCREW EDIT: research allows experiment handlers without a linked ship techweb. // Check if an experiment is selected if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) return FALSE diff --git a/code/modules/experisci/experiment/physical_experiments.dm b/code/modules/experisci/experiment/physical_experiments.dm index 945815c9822..dd8cccc83f4 100644 --- a/code/modules/experisci/experiment/physical_experiments.dm +++ b/code/modules/experisci/experiment/physical_experiments.dm @@ -29,8 +29,10 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/experiment/physical/meat_wall_explosion/finish_experiment(datum/component/experiment_handler/experiment_handler) . = ..() + // VOIDCREW EDIT START: research stops failed experiment completion before downstream effects. if(!.) return FALSE + // VOIDCREW EDIT END new /obj/effect/gibspawner/generic(currently_scanned_atom) var/turf/meat_wall = currently_scanned_atom var/turf/new_turf = meat_wall.ScrapeAway() diff --git a/code/modules/experisci/experiment/types/scanning.dm b/code/modules/experisci/experiment/types/scanning.dm index 68d371c3e6d..ead403700d9 100644 --- a/code/modules/experisci/experiment/types/scanning.dm +++ b/code/modules/experisci/experiment/types/scanning.dm @@ -43,15 +43,17 @@ for (var/req_atom in required_atoms) var/list/seen = scanned[req_atom] ///typecache experiments work all the same whether it's destructive or not + // VOIDCREW EDIT START: research accepts shared progress beyond the goal and tracks typecache entries by type. if(typecache) //Some experiments share their scanned list with others (see fish), so the tally can overshoot //this experiment's own requirement. An exact match would leave it uncompletable forever. if(length(seen) < required_atoms[req_atom]) return FALSE + // VOIDCREW EDIT END continue - if (destructive && (!(req_atom in scanned) || scanned[req_atom] < required_atoms[req_atom])) + if (destructive && (!(req_atom in scanned) || scanned[req_atom] < required_atoms[req_atom])) // VOIDCREW EDIT: research accepts shared progress beyond the goal and tracks typecache entries by type. return FALSE - if (!destructive && (!seen || seen.len < required_atoms[req_atom])) + if (!destructive && (!seen || seen.len < required_atoms[req_atom])) // VOIDCREW EDIT: research accepts shared progress beyond the goal and tracks typecache entries by type. return FALSE /** @@ -114,7 +116,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/experiment/scanning/proc/experiment_requirements(datum/component/experiment_handler/experiment_handler, atom/target) var/destructive = (traits & EXPERIMENT_TRAIT_DESTRUCTIVE) - var/typecache = (traits & EXPERIMENT_TRAIT_TYPECACHE) + var/typecache = (traits & EXPERIMENT_TRAIT_TYPECACHE) // VOIDCREW EDIT: research accepts shared progress beyond the goal and tracks typecache entries by type. for (var/req_atom in required_atoms) if (!istype(target, req_atom)) continue @@ -122,11 +124,13 @@ var/selected var/list/seen = scanned[req_atom] //A typecache's entries are keyed by typepath, not by weakref, so a type already scanned must not be offered again. - if (typecache && length(seen) < required_atoms[req_atom] && !(target.type in seen)) + if (typecache && length(seen) < required_atoms[req_atom] && !(target.type in seen)) // VOIDCREW EDIT: research accepts shared progress beyond the goal and tracks typecache entries by type. selected = req_atom + // VOIDCREW EDIT START: research accepts shared progress beyond the goal and tracks typecache entries by type. else if (!typecache && destructive && (req_atom in scanned) && scanned[req_atom] < required_atoms[req_atom]) selected = req_atom else if (!typecache && !destructive && seen.len < required_atoms[req_atom] && !(WEAKREF(target) in seen)) + // VOIDCREW EDIT END selected = req_atom // Run any additonal checks if necessary if (selected && final_contributing_index_checks(experiment_handler, target, selected)) diff --git a/code/modules/experisci/experiment/types/scanning_fish.dm b/code/modules/experisci/experiment/types/scanning_fish.dm index 96832cd8672..b6bb63f01e8 100644 --- a/code/modules/experisci/experiment/types/scanning_fish.dm +++ b/code/modules/experisci/experiment/types/scanning_fish.dm @@ -62,6 +62,8 @@ GLOBAL_LIST_EMPTY(scanned_fish_by_techweb) message += "
" examine_list += message +// VOIDCREW EDIT: research clamps shared fish progress to the experiment requirement; implementation in voidcrew/edits/modules/experisci/experiment/types/scanning_fish.dm. + ///Only scannable fish will contribute towards the experiment. /datum/experiment/scanning/fish/final_contributing_index_checks(datum/component/experiment_handler/experiment_handler, obj/item/fish/target, typepath) return target.fish_flags & FISH_FLAG_EXPERIMENT_SCANNABLE diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm index 3c6b22e1da0..7508d96b1bd 100644 --- a/code/modules/fishing/sources/_fish_source.dm +++ b/code/modules/fishing/sources/_fish_source.dm @@ -526,30 +526,38 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons()) return // VOIDCREW EDIT: water gets one low-chance roll per tile, independent of other blasts. var/is_water = iswaterturf(location) + // VOIDCREW EDIT START: mining limits explosive water catches and preserves shared rare fish. var/reward_attempts = severity + 2 var/reward_chance = 100 + 100 * severity + // VOIDCREW EDIT END var/multiplier = 1 + // VOIDCREW EDIT START: mining limits explosive water catches and preserves shared rare fish. if(is_water) reward_attempts = 1 reward_chance = 2 * severity // 2% light, 4% heavy, 6% devastation. else if(fish_source_flags & FISH_SOURCE_FLAG_EXPLOSIVE_MALUS) + // VOIDCREW EDIT END if(explosive_fishing_score <= 0) explosive_fishing_score = 1 START_PROCESSING(SSprocessing, src) else explosive_fishing_score++ multiplier = explosive_fishing_score**-EXPLOSIVE_FISHING_MALUS_EXPONENT + // VOIDCREW EDIT START: mining limits explosive water catches and preserves shared rare fish. for(var/i in 1 to reward_attempts) if(!prob(reward_chance / i * multiplier)) + // VOIDCREW EDIT END continue + // VOIDCREW EDIT START: mining limits explosive water catches and preserves shared rare fish. var/list/reward_table = get_fish_table(location, from_explosion = TRUE) - // VOIDCREW ADDITION START: water blasts must not deplete shared rare catches for other players. + // VOIDCREW EDIT ADDITION START: water blasts must not deplete shared rare catches for other players. if(is_water) reward_table -= fish_counts if(!length(reward_table)) return - // VOIDCREW ADDITION END + // VOIDCREW EDIT ADDITION END var/reward_loot = pick_weight(reward_table) + // VOIDCREW EDIT END var/atom/spawn_location = isturf(location) ? location : location.drop_location() var/atom/movable/reward = simple_dispense_reward(reward_loot, spawn_location, location) if(isnull(reward)) diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index c50d4da52fd..bfea94a0d79 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -1,7 +1,6 @@ // ------------------------- // SmartFridge. Much todo // ------------------------- -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/smartfridge name = "smartfridge" desc = "Keeps cold things cold and hot things cold." @@ -35,7 +34,6 @@ var/vend_sound = 'sound/machines/machine_vend.ogg' layout_prefs_used = /datum/preference/choiced/tgui_layout/smartfridge -// VOIDCREW EDIT END /obj/machinery/smartfridge/Initialize(mapload) . = ..() create_reagents(100, NO_REACT) @@ -231,7 +229,6 @@ /obj/machinery/smartfridge/proc/visible_items() return contents.len - 1 // Exclude circuitboard -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/smartfridge/update_overlays() . = ..() @@ -247,13 +244,14 @@ content_level += "-3" . += mutable_appearance(icon, content_level) + // VOIDCREW EDIT START: research disk storage omits the separate glass overlay. if(has_glass_overlay) . += mutable_appearance(icon, "[base_icon_state]-glass[(machine_stat & BROKEN) ? "-broken" : ""]") + // VOIDCREW EDIT END if(has_emissive && powered() && !(machine_stat & BROKEN)) . += mutable_appearance(icon, "[base_icon_state]-powered") . += emissive_appearance(icon, "[base_icon_state]-light-mask", src, alpha = src.alpha) -// VOIDCREW EDIT END /obj/machinery/smartfridge/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) if(BRUTE) @@ -798,7 +796,6 @@ // ---------------------------- // Disk """fridge""" // ---------------------------- -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/smartfridge/disks name = "disk compartmentalizer" desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)." @@ -808,10 +805,9 @@ pass_flags = PASSTABLE can_atmos_pass = ATMOS_PASS_YES visible_contents = FALSE - has_glass_overlay = FALSE + has_glass_overlay = FALSE // VOIDCREW EDIT: research disk storage omits the separate glass overlay. has_emissive = FALSE base_build_path = /obj/machinery/smartfridge/disks -// VOIDCREW EDIT END /obj/machinery/smartfridge/disks/accept_check(obj/item/weapon) return istype(weapon, /obj/item/disk) diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 115176bbfcf..27421005d07 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -511,7 +511,7 @@ // This is unfortunately necessary because of snowflake AI init code. To be refactored. spawn_instance = new spawn_type(get_turf(spawn_point), null, player_client.mob) else - spawn_instance = new spawn_type(ship_role == "cyborg" ? get_turf(spawn_point) : player_client.mob.loc) + spawn_instance = new spawn_type(ship_role == "cyborg" ? get_turf(spawn_point) : player_client.mob.loc) // VOIDCREW EDIT: cryo spawns ship cyborg roles at the reserved hull spawn point. spawn_point.JoinPlayerHere(spawn_instance, TRUE) spawn_instance.apply_prefs_job(player_client, src) if(!player_client) diff --git a/code/modules/jobs/job_types/ai.dm b/code/modules/jobs/job_types/ai.dm index 116586ad934..3ace5c811d2 100644 --- a/code/modules/jobs/job_types/ai.dm +++ b/code/modules/jobs/job_types/ai.dm @@ -27,7 +27,7 @@ /datum/job/ai/after_spawn(mob/living/spawned, client/player_client) . = ..() //we may have been created after our borg - if(SSticker.current_state == GAME_STATE_SETTING_UP && ship_role != "ai") + if(SSticker.current_state == GAME_STATE_SETTING_UP && ship_role != "ai") // VOIDCREW EDIT: cryo preserves ship-selected AI spawn placement. for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs) if(!R.connected_ai) R.TryConnectToAI() diff --git a/code/modules/jobs/job_types/prisoner.dm b/code/modules/jobs/job_types/prisoner.dm index eafa97f1d7a..5a5e5e8767e 100644 --- a/code/modules/jobs/job_types/prisoner.dm +++ b/code/modules/jobs/job_types/prisoner.dm @@ -32,15 +32,19 @@ /datum/job/prisoner/proc/handle_prisoner_joining(datum/source, mob/living/crewmember, rank) SIGNAL_HANDLER // Ships can have separate prisoner jobs with the same title. + // VOIDCREW EDIT START: cryo resolves ship prisoner roles by job identity and available records. if(crewmember.mind?.assigned_role != src) return + // VOIDCREW EDIT END + // VOIDCREW EDIT START: cryo resolves ship prisoner roles by job identity and available records. var/datum/record/crew/target_record = find_record(crewmember.real_name) if(!target_record) return var/datum/client_interface/player_client = GET_CLIENT(crewmember) var/crime_name = player_client?.prefs?.read_preference(/datum/preference/choiced/prisoner_crime) + // VOIDCREW EDIT END if(!crime_name) stack_trace("[crewmember] joined as a Prisoner without having a prisoner crime set.") crime_name = pick(assoc_to_keys(GLOB.prisoner_crimes)) @@ -49,6 +53,7 @@ var/datum/prisoner_crime/crime = GLOB.prisoner_crimes[crime_name] var/datum/crime/past_crime = new(crime.name, crime.desc, "Central Command", "Indefinite.") + // VOIDCREW EDIT REMOVAL: cryo resolves ship prisoner roles by job identity and available records. target_record.crimes += past_crime target_record.recreate_manifest_photos(add_height_chart = TRUE) to_chat(crewmember, span_warning("You are imprisoned for \"[crime_name]\".")) diff --git a/code/modules/library/bibles.dm b/code/modules/library/bibles.dm index 83aaa05e9c8..8740916f997 100644 --- a/code/modules/library/bibles.dm +++ b/code/modules/library/bibles.dm @@ -42,7 +42,7 @@ GLOBAL_LIST_INIT(biblestates, list( "gurugranthsahib", "kojiki", )) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. +// VOIDCREW EDIT START: clothing uses existing bible inhand states. GLOBAL_LIST_INIT(bibleitemstates, list( "bible", "koran", @@ -64,8 +64,8 @@ GLOBAL_LIST_INIT(bibleitemstates, list( "bible", "kojiki", )) - // VOIDCREW EDIT END + /obj/item/book/bible name = "bible" desc = "Apply to head repeatedly." diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index 64ec6bb43e0..fefce819478 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -35,7 +35,7 @@ GLOBAL_LIST_EMPTY(default_lighting_underlays_by_z) for(var/turf/open/space/space_tile in RANGE_TURFS(1, affected_turf)) space_tile.enable_starlight() - // VOIDCREW EDIT: ambient bleed, the same wake-up the loop above does for starlight, + // VOIDCREW EDIT START: ambient bleed, the same wake-up the loop above does for starlight, // generalised to any area that paints its light on the area instead of on its turfs // (ambient_lighting - planet surfaces). Those turfs carry no lighting objects and emit // nothing, so this brand new statically lit tile would render as a hard black edge @@ -125,7 +125,7 @@ GLOBAL_LIST_EMPTY(default_lighting_underlays_by_z) // Of note. Most of the cost in this proc is here, I think because color matrix'd underlays DO NOT cache well, which is what adding to underlays does // We use underlays because objects on each tile would fuck with maptick. if that ever changes, use an object for this instead affected_turf.underlays += current_underlay - // VOIDCREW EDIT: an area with active base lighting is lit by a BLEND_ADD overlay on + // VOIDCREW EDIT START: an area with active base lighting is lit by a BLEND_ADD overlay on // the area, not by light sources on its turfs, so every corner here reads dark and // set_luminosity comes out 0. BYOND culls the contents of a luminosity 0 tile out of // clients' view, which on a base-lit planet surface would leave the ground looking diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index cd96ae0a449..375b400c513 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -97,28 +97,30 @@ ///Transfer the lighting of one area to another /turf/proc/transfer_area_lighting(area/old_area, area/new_area) if(SSlighting.initialized && !space_lit) + // VOIDCREW EDIT START: Update ambient bleed on area transfers and tolerate live z-level growth (voidcrew/edits/lighting.dm). var/static_lighting_changed = (new_area.static_lighting != old_area.static_lighting) - // VOIDCREW EDIT: remembered so the ambient bleed block below can tell whether this + // VOIDCREW EDIT START: remembered so the ambient bleed block below can tell whether this // transfer actually took our lighting object away. See voidcrew/edits/lighting.dm. var/had_lighting_object = !!lighting_object // END VOIDCREW EDIT if (static_lighting_changed) + // VOIDCREW EDIT END if (new_area.static_lighting) lighting_build_overlay() - // VOIDCREW EDIT: a turf that lights itself inside an ambient-lit area - fallout + // VOIDCREW EDIT START: a turf that lights itself inside an ambient-lit area - fallout // ground, a lava river - keeps its object, or its own light has nothing to render // on. Everything else on the dynamic side loses it exactly as upstream. else if(!new_area.ambient_lighting || skips_lighting_object()) lighting_clear_overlay() // END VOIDCREW EDIT (was: else lighting_clear_overlay()) - // VOIDCREW EDIT: moving into ambient-lit ground from another DYNAMIC area does not + // VOIDCREW EDIT START: moving into ambient-lit ground from another DYNAMIC area does not // trip static_lighting_changed, but the object still has to go - that ground carries // none at all. else if(lighting_object && skips_lighting_object()) lighting_clear_overlay() // END VOIDCREW EDIT - // VOIDCREW EDIT: ambient bleed. Changing area without changing type - a ship + // VOIDCREW EDIT START: ambient bleed. Changing area without changing type - a ship // landing or taking off, a room being repainted, cave generation claiming a tile - // changes both whether we bleed light ourselves and whether we are something worth // bleeding onto, and nothing else on this path notices. See @@ -134,12 +136,15 @@ // We will only run this logic on turfs off the prime z layer // Since on the prime z layer, we use an overlay on the area instead, to save time + // VOIDCREW EDIT: Update ambient bleed on area transfers and tolerate live z-level growth (voidcrew/edits/lighting.dm). if(z <= length(SSmapping.z_level_to_plane_offset) && SSmapping.z_level_to_plane_offset[z]) var/index = SSmapping.z_level_to_plane_offset[z] + 1 //Inherit overlay of new area + // VOIDCREW EDIT START: Update ambient bleed on area transfers and tolerate live z-level growth (voidcrew/edits/lighting.dm). if(old_area.lighting_effects && index <= length(old_area.lighting_effects)) cut_overlay(old_area.lighting_effects[index]) if(new_area.lighting_effects && index <= length(new_area.lighting_effects)) + // VOIDCREW EDIT END add_overlay(new_area.lighting_effects[index]) // Manage removing/adding starlight overlays, we'll inherit from the area so we can drop it if the area has it already diff --git a/code/modules/loadout/loadout_menu.dm b/code/modules/loadout/loadout_menu.dm index 09ce648c4f1..b1c2fed02a6 100644 --- a/code/modules/loadout/loadout_menu.dm +++ b/code/modules/loadout/loadout_menu.dm @@ -100,14 +100,14 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/preference_middleware/loadout/get_ui_data(mob/user) var/list/data = list() - data["job_clothes"] = preferences.get_character_preview_view(user)?.show_job_clothes + data["job_clothes"] = preferences.get_character_preview_view(user)?.show_job_clothes // VOIDCREW EDIT: preferences recovers missing loadout preview views. return data // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/preference_middleware/loadout/get_ui_static_data(mob/user) var/list/data = list() - data["loadout_preview_view"] = preferences.get_character_preview_view(user)?.assigned_map + data["loadout_preview_view"] = preferences.get_character_preview_view(user)?.assigned_map // VOIDCREW EDIT: preferences recovers missing loadout preview views. return data // VOIDCREW EDIT END diff --git a/code/modules/logging/log_holder.dm b/code/modules/logging/log_holder.dm index 1edbb2b8c41..65875c8a7c3 100644 --- a/code/modules/logging/log_holder.dm +++ b/code/modules/logging/log_holder.dm @@ -1,8 +1,6 @@ GLOBAL_REAL(logger, /datum/log_holder) -/// VOIDCREW ADDITION: how long the structured log path stays parked after it throws. -/// Short - one unlucky file write should not blind the round's logs for long. -#define LOG_HOLDER_FAILURE_BACKOFF (5 SECONDS) +// VOIDCREW EDIT: metrics sets a backoff for failed structured logging; implementation in voidcrew/modules/metrics/structured_logging_fallback.dm. /** * Main datum to manage logging actions @@ -307,10 +305,10 @@ ADMIN_VERB(log_viewer_new, R_ADMIN|R_DEBUG, "View Round Logs", "View the rounds waiting_log_calls += list(list(category, message, data)) return - // VOIDCREW ADDITION: the logger recently threw, so don't go back through the structured + // VOIDCREW EDIT ADDITION: the logger recently threw, so don't go back through the structured // path yet - get the line out flat instead of losing it. See logging_failed(). if(world.time < structured_logging_broken_until) - SEND_TEXT(world.log, "\[LOG FALLBACK]\[[category]] [message]") + SEND_TEXT(world.log, "\[LOG FALLBACK]\[[category]] [message]") // VOIDCREW EDIT: metrics falls back to world logging when structured writes fail. return // VOIDCREW EDIT: the category lookups are two plain assoc-list reads, and in round-7 @@ -324,6 +322,7 @@ ADMIN_VERB(log_viewer_new, R_ADMIN|R_DEBUG, "View Round Logs", "View the rounds // Narrow on purpose: recursive_jsonify() below stays outside, because it raises // stack_trace()s as part of normal operation and swallowing those would hide real bugs. var/category_disabled = FALSE + // VOIDCREW EDIT START: metrics falls back to world logging when structured writes fail. var/datum/log_category/log_category try if(disabled_categories[category]) @@ -336,6 +335,7 @@ ADMIN_VERB(log_viewer_new, R_ADMIN|R_DEBUG, "View Round Logs", "View the rounds if(category_disabled) return + // VOIDCREW EDIT END if(!log_category) Log(LOG_CATEGORY_INTERNAL_CATEGORY_NOT_FOUND, message, data) @@ -346,30 +346,17 @@ ADMIN_VERB(log_viewer_new, R_ADMIN|R_DEBUG, "View Round Logs", "View the rounds semver_store = list() data = recursive_jsonify(data, semver_store) + // VOIDCREW EDIT START: metrics falls back to world logging when structured writes fail. try log_category.create_entry(message, data, semver_store) catch(var/exception/write_failure) logging_failed(category, message, write_failure) -/** - * VOIDCREW ADDITION: last resort for when the structured logger itself throws. - * - * Writes the line flat to world.log and parks the structured path for a few seconds, so a - * world whose list allocator is failing produces one line per log call instead of a - * BYOND-default stack dump per log call. Touches no lists and calls nothing that logs - - * this proc has to work in the state where nothing else does. - * - * The message body does go to world.log here, secret categories included. That is a - * deliberate trade: world.log is host-side only, and the alternative is losing the record - * of whatever was happening at the moment the server stopped being able to write records. - */ -/datum/log_holder/proc/logging_failed(category, message, failure) - structured_logging_broken_until = world.time + LOG_HOLDER_FAILURE_BACKOFF - SEND_TEXT(world.log, "\[LOG FALLBACK]\[[category]] [message]") - SEND_TEXT(world.log, " STRUCTURED LOGGING FAILED ([failure]) - flat world.log lines for the next [LOG_HOLDER_FAILURE_BACKOFF / 10] seconds.") + // VOIDCREW EDIT END + +// VOIDCREW EDIT: metrics writes a flat fallback when structured logging fails; implementation in voidcrew/modules/metrics/structured_logging_fallback.dm. /// Recursively converts an associative list of datums into their jsonified(list) form -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/log_holder/proc/recursive_jsonify(list/data_list, list/semvers) if(isnull(data_list)) return null @@ -409,5 +396,4 @@ ADMIN_VERB(log_viewer_new, R_ADMIN|R_DEBUG, "View Round Logs", "View the rounds return jsonified_list -#undef LOG_HOLDER_FAILURE_BACKOFF -// VOIDCREW EDIT END +// VOIDCREW EDIT: metrics scopes the structured logging backoff define; implementation in voidcrew/modules/metrics/structured_logging_fallback.dm. diff --git a/code/modules/lootpanel/_lootpanel.dm b/code/modules/lootpanel/_lootpanel.dm index aafe5900a82..89439864d56 100644 --- a/code/modules/lootpanel/_lootpanel.dm +++ b/code/modules/lootpanel/_lootpanel.dm @@ -28,7 +28,7 @@ // nothing removed it - a client who alt-clicked a cluttered tile and disconnected // before the backlog drained left their panel pinned there SSlooting.backlog -= src - SSlooting.processing -= src + SSlooting.processing -= src // VOIDCREW EDIT: storage removes deleted loot panels from subsystem queues. owner = null source_turf = null diff --git a/code/modules/lootpanel/contents.dm b/code/modules/lootpanel/contents.dm index 5786f81ae3b..330069310ba 100644 --- a/code/modules/lootpanel/contents.dm +++ b/code/modules/lootpanel/contents.dm @@ -42,11 +42,11 @@ /// For: Resetting to empty. Ignores the searchable qdel event -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/lootpanel/proc/reset_contents() // VOIDCREW EDIT: removing mid-walk skipped every other index, leaving half the // search objects registered and listed across populate_contents() calls for(var/datum/search_object/index as anything in contents) + // VOIDCREW EDIT REMOVAL: storage clears lootpanel contents after their handlers are detached. to_image -= index if(QDELETED(index)) @@ -54,5 +54,4 @@ UnregisterSignal(index, COMSIG_QDELETING) qdel(index) - contents.Cut() -// VOIDCREW EDIT END + contents.Cut() // VOIDCREW EDIT: storage clears lootpanel contents after their handlers are detached. diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm index efed0f54641..2b8d897208c 100644 --- a/code/modules/mapping/map_template.dm +++ b/code/modules/mapping/map_template.dm @@ -96,7 +96,7 @@ continue var/area/loc_area = unlit.loc if(!loc_area.static_lighting) - // VOIDCREW EDIT: ambient-lit ground (a planet surface) carries no lighting objects + // VOIDCREW EDIT START: ambient-lit ground (a planet surface) carries no lighting objects // at all, with one exception - a turf that lights itself, e.g. a ruin dropping a // /lit tile straight onto surface ground rather than into its own area. Its light // needs somewhere to render. See /turf/proc/skips_lighting_object(). @@ -158,6 +158,7 @@ if((T.y+height) - 1 > world.maxy) return + // VOIDCREW EDIT: Retain self-lit planetary tiles and instrument live template loading (voidcrew/modules/worldgen_logging/worldgen.dm). var/datum/worldgen_probe/probe = worldgen_begin("template", "[name] [width]x[height] @ [T.x],[T.y],[T.z]") // Cache for sonic speed @@ -188,11 +189,13 @@ no_changeturf = (SSatoms.initialized == INITIALIZATION_INSSATOMS), place_on_top = should_place_on_top, )) + // VOIDCREW EDIT: Retain self-lit planetary tiles and instrument live template loading (voidcrew/modules/worldgen_logging/worldgen.dm). worldgen_end(probe, "parse-failed") return var/list/bounds = parsed.bounds if(!bounds) + // VOIDCREW EDIT: Retain self-lit planetary tiles and instrument live template loading (voidcrew/modules/worldgen_logging/worldgen.dm). worldgen_end(probe, "no-bounds") return @@ -206,6 +209,7 @@ generate_ceiling(affected_turfs) log_game("[name] loaded at [T.x],[T.y],[T.z]") + // VOIDCREW EDIT: Retain self-lit planetary tiles and instrument live template loading (voidcrew/modules/worldgen_logging/worldgen.dm). worldgen_end(probe) return bounds diff --git a/code/modules/mapping/mapping_helpers.dm b/code/modules/mapping/mapping_helpers.dm index c00b323e556..b068c64ea80 100644 --- a/code/modules/mapping/mapping_helpers.dm +++ b/code/modules/mapping/mapping_helpers.dm @@ -1,7 +1,6 @@ //Landmarks and other helpers which speed up the mapping process and reduce the number of unique instances/subtypes of items/turf/ect - /obj/effect/baseturf_helper //Set the baseturfs of every turf in the /area/ it is placed. name = "baseturf editor" icon = 'icons/effects/mapping_helpers.dmi' @@ -1147,7 +1146,7 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_atoms_ontop) var/datum/space_level/level = SSmapping.z_list[z] if(!level || !length(traits_to_add)) return - // VOIDCREW EDIT ADDITION: a template loaded onto the slot lattice must not rewrite the + // VOIDCREW EDIT ADDITION START: a template loaded onto the slot lattice must not rewrite the // LEVEL's traits - all four tenants inherit them, and one of them is ZTRAIT_BASETURF, // the fallback every flat tenant resolves a scraped floor through. The level's own // weather site would be rebuilt rect-less for everybody too. diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm index 9af158ea18a..d623874dc4d 100644 --- a/code/modules/mapping/reader.dm +++ b/code/modules/mapping/reader.dm @@ -778,9 +778,11 @@ GLOBAL_LIST_EMPTY(map_model_default) if(!ispath(atom_def, /atom)) // Skip the item if the path does not exist. Fix your crap, mappers! // Attributes were appended before resolving this path. Remove their slot too, // or every later atom receives the preceding atom's mapped variables. + // VOIDCREW EDIT START: Keep map attribute slots aligned and instantiate repeated planetary ruin areas separately (voidcrew/modules/overmap). members_attributes.len-- if(bad_paths) LAZYOR(bad_paths[path_to_init], model_key) + // VOIDCREW EDIT END continue // Index is already incremented either way, just gotta set the path and all members += atom_def @@ -935,9 +937,11 @@ GLOBAL_LIST_EMPTY(map_model_default) if(instance_ruin_area) area_instance = new_planet_ruin_area(area_type) // VOIDCREW EDIT ADDITION END + // VOIDCREW EDIT START: Keep map attribute slots aligned and instantiate repeated planetary ruin areas separately (voidcrew/modules/overmap). else // If this parsed map doesn't have that area already, we check the global cache area_instance = GLOB.areas_by_type[area_type] + // VOIDCREW EDIT END // If the global list DOESN'T have this area it's either not a unique area, or it just hasn't been created yet if (!area_instance) area_instance = new area_type(null) diff --git a/code/modules/mapping/ruins.dm b/code/modules/mapping/ruins.dm index 05c99362be9..ef26b624866 100644 --- a/code/modules/mapping/ruins.dm +++ b/code/modules/mapping/ruins.dm @@ -1,3 +1,4 @@ + /** * Tries to drop this ruin somewhere on z. * @@ -40,12 +41,14 @@ var/height_border = TRANSITIONEDGE + SPACERUIN_MAP_EDGE_PAD + round(height / 2) // VOIDCREW EDIT: sample from the placement rect when one was given, from the whole z otherwise var/turf/central_turf + // VOIDCREW EDIT START: Sample ruins inside the tenant bounds and whitelist owned area instances (voidcrew/edits/modules/mapping/ruins.dm). if(forced_turf) central_turf = forced_turf else if(sample_bounds) central_turf = locate(rand(sample_bounds[1], sample_bounds[3]), rand(sample_bounds[2], sample_bounds[4]), z) else central_turf = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z) + // VOIDCREW EDIT END var/valid = TRUE var/list/affected_turfs = get_affected_turfs(central_turf,1) var/list/affected_areas = list() @@ -60,6 +63,7 @@ // This is faster yes. Only BARELY but it is faster if(length(allowed_area_instances)) // VOIDCREW EDIT: instance whitelist wins over the type one + // VOIDCREW EDIT START: Sample ruins inside the tenant bounds and whitelist owned area instances (voidcrew/edits/modules/mapping/ruins.dm). for(var/area/affct_area as anything in affected_areas) if(!allowed_area_instances[affct_area]) valid = FALSE @@ -69,6 +73,7 @@ if(!allowed_areas_typecache[affct_area.type]) valid = FALSE break + // VOIDCREW EDIT END if(!valid) continue @@ -133,10 +138,12 @@ var/list/whitelist_typecache = typecacheof(whitelist) // VOIDCREW EDIT: built once here rather than per placement sample var/list/whitelist_instances + // VOIDCREW EDIT START: Sample ruins inside the tenant bounds and whitelist owned area instances (voidcrew/edits/modules/mapping/ruins.dm). if(length(area_whitelist_instances)) whitelist_instances = list() for(var/area/whitelisted_area as anything in area_whitelist_instances) whitelist_instances[whitelisted_area] = TRUE + // VOIDCREW EDIT END for(var/zl in z_levels) var/turf/T = locate(1, 1, zl) @@ -192,7 +199,7 @@ break else //Otherwise just pick random one current_pick = pick_weight(ruins_available) - // VOIDCREW EDIT: pick_weight() returns null when every remaining candidate has + // VOIDCREW EDIT START: pick_weight() returns null when every remaining candidate has // weight 0, and ruins_available is only ever pruned by placement or by going // over budget - a zero-weight entry sits in it forever and keeps the `.len` // test in the while() above true. Unguarded, the next line reads diff --git a/code/modules/mapping/space_management/space_reservation.dm b/code/modules/mapping/space_management/space_reservation.dm index ad0f06e8cac..fdfbd2816f4 100644 --- a/code/modules/mapping/space_management/space_reservation.dm +++ b/code/modules/mapping/space_management/space_reservation.dm @@ -4,9 +4,8 @@ /// Above this many turfs, reservation teardown in Release() spreads itself over /// multiple ticks instead of running atomically. Small reservations keep the /// historical no-sleep behavior, so qdel() from tick-sensitive contexts stays safe. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. +// VOIDCREW EDIT: Bound long site releases while preserving atomic teardown for small reservations. #define RESERVATION_RELEASE_YIELD_THRESHOLD 2500 -// VOIDCREW EDIT END /datum/turf_reservation /// All turfs that we've reserved @@ -46,7 +45,7 @@ turf_type = /turf/open/space/transit pre_cordon_distance = 7 -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. + /datum/turf_reservation/proc/Release() // VOIDCREW EDIT: the release set is rebuilt from the corners we recorded at claim time // instead of trusting `reserved_turfs` to still list everything _reserve_area() took. @@ -72,6 +71,7 @@ // alone and cannot be reached by anyone else, so block() over them stays the // authoritative answer to "what did we take" no matter who mutates our lists. var/list/released = list() + // VOIDCREW EDIT START: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). for(var/z_idx in 1 to min(length(bottom_left_turfs), length(top_right_turfs))) var/turf/bottom_left = bottom_left_turfs[z_idx] var/turf/top_right = top_right_turfs[z_idx] @@ -87,12 +87,16 @@ for(var/turf/cordon_turf as anything in cordon_turfs) if(!isnull(cordon_turf)) released[cordon_turf] = TRUE + // VOIDCREW EDIT END bottom_left_turfs.Cut() top_right_turfs.Cut() + // VOIDCREW EDIT REMOVAL: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). reserved_turfs = list() + // VOIDCREW EDIT REMOVAL: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). cordon_turfs = list() + // VOIDCREW EDIT START: Bound long site releases while preserving atomic teardown for small reservations. if(!length(released)) return @@ -113,6 +117,7 @@ // from qdel(): our turf lists were already emptied above, so a reentrant Release() // during a yield has nothing left to double-process. var/can_yield = length(release_turfs) > RESERVATION_RELEASE_YIELD_THRESHOLD + // VOIDCREW EDIT END for(var/turf/reserved_turf as anything in release_turfs) SEND_SIGNAL(reserved_turf, COMSIG_TURF_RESERVATION_RELEASED, src) @@ -120,14 +125,15 @@ // immediately disconnect from atmos reserved_turf.blocks_air = TRUE CALCULATE_ADJACENT_TURFS(reserved_turf, KILL_EXCITED) + // VOIDCREW EDIT START: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). if(can_yield) CHECK_TICK + // VOIDCREW EDIT END // Makes the linter happy, even tho we don't await this INVOKE_ASYNC(SSmapping, TYPE_PROC_REF(/datum/controller/subsystem/mapping, reserve_turfs), release_turfs) /// Attempts to calaculate and store a list of turfs around the reservation for cordoning. Returns whether a valid cordon was calculated -// VOIDCREW EDIT END /datum/turf_reservation/proc/calculate_cordon_turfs(turf/bottom_left, turf/top_right) if(bottom_left.x < 2 || bottom_left.y < 2 || top_right.x > (world.maxx - 2) || top_right.y > (world.maxy - 2)) return FALSE // no space for a cordon here @@ -149,7 +155,6 @@ return TRUE /// Actually generates the cordon around the reservation, and marking the cordon turfs as reserved -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/turf_reservation/proc/generate_cordon() for(var/turf/cordon_turf as anything in cordon_turfs) var/area/misc/cordon/cordon_area = GLOB.areas_by_type[/area/misc/cordon] || new @@ -166,8 +171,10 @@ // per-turf removal is not; see _reserve_area()) cordon_turf.turf_flags &= ~UNUSED_RESERVATION_TURF cordon_turf.empty(/turf/cordon, /turf/cordon) + // VOIDCREW EDIT REMOVAL: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). // still gets linked to us though SSmapping.used_turfs[cordon_turf] = src + // VOIDCREW EDIT: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). CHECK_TICK //swap the area with the pre-cordoning area @@ -175,7 +182,6 @@ make_repel(pre_cordon_turf) ///Register signals in the cordon "danger zone" to do something with whoever trespasses -// VOIDCREW EDIT END /datum/turf_reservation/proc/make_repel(turf/pre_cordon_turf) SHOULD_CALL_PARENT(TRUE) //Okay so hear me out. If we place a special turf IN the reserved area, it will be overwritten, so we can't do that @@ -218,7 +224,6 @@ turf_type_is_baseturf = FALSE /// Internal proc which handles reserving the area for the reservation. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/turf_reservation/proc/_reserve_area(width, height, zlevel) src.width = width src.height = height @@ -242,6 +247,7 @@ // the first origin that can ever pass calculate_cordon_turfs() is one in from the // band edge - anchoring there keeps the outermost usable column/row on the grid. if((BL.x - SHUTTLE_TRANSIT_BORDER - 1) % RESERVATION_ORIGIN_STRIDE || (BL.y - SHUTTLE_TRANSIT_BORDER - 1) % RESERVATION_ORIGIN_STRIDE) + // VOIDCREW EDIT: Align reservation origins so fleet transit holes can be reused without fragmentation. continue if(BL.x + width > world.maxx || BL.y + height > world.maxy) continue @@ -274,13 +280,17 @@ // of hard freeze for big reservations). The reserve scan above already skips // anything without UNUSED_RESERVATION_TURF, and the unused_turfs lists are assoc // keyed by turf, so handing a turf back later just updates its existing key. + // VOIDCREW EDIT START: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). reserved_turfs += final for(var/turf/T as anything in final) + // VOIDCREW EDIT END SSmapping.used_turfs[T] = src T.turf_flags = (T.turf_flags | RESERVATION_TURF) & ~UNUSED_RESERVATION_TURF + // VOIDCREW EDIT START: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). for(var/turf/cordon_turf as anything in cordon_turfs) cordon_turf.turf_flags &= ~UNUSED_RESERVATION_TURF SSmapping.used_turfs[cordon_turf] = src + // VOIDCREW EDIT END // Record the corners as part of claiming, not after the conversion below. The // turfs are already flagged RESERVATION_TURF and pointed at us in used_turfs, so @@ -292,13 +302,14 @@ // The actual turf conversion is by far the expensive part (a full ChangeTurf per // turf) - now that everything is claimed it can safely spread over multiple ticks + // VOIDCREW EDIT START: Keep reservation claims atomic and release large site footprints across ticks (voidcrew/edits/modules/mapping/space_management/space_reservation.dm). for(var/turf/T as anything in final) T.empty(turf_type, turf_type_is_baseturf ? turf_type : null) CHECK_TICK + // VOIDCREW EDIT END return TRUE -// VOIDCREW EDIT END /datum/turf_reservation/proc/reserve(width, height, z_size, z_reservation) src.z_size = z_size var/failed_reservation = FALSE @@ -315,10 +326,10 @@ return TRUE /// Calculates the effective bounds information for the given turf. Returns a list of the information, or null if not applicable. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/turf_reservation/proc/calculate_turf_bounds_information(turf/target) // Bounded by the corner lists rather than z_size, same as contains_turf(): a // half-built or already-released reservation still has its z_size set. + // VOIDCREW EDIT: Bound corner walks by the actual reservation state, including partial builds and released datums. for(var/z_idx in 1 to length(bottom_left_turfs)) var/turf/bottom_left = bottom_left_turfs[z_idx] var/turf/top_right = top_right_turfs[z_idx] @@ -347,8 +358,6 @@ return null /// Gets the turf below the given target. Returns null if there is no turf below the target -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/turf_reservation/proc/get_turf_below(turf/target) var/list/bounds_info = calculate_turf_bounds_information(target) if(isnull(bounds_info)) @@ -356,6 +365,7 @@ var/z_idx = bounds_info["z_idx"] // check what z level, if its the max, then there is no turf below + // VOIDCREW EDIT: Bound corner walks by the actual reservation state, including partial builds and released datums. if(z_idx >= length(bottom_left_turfs)) return null @@ -365,8 +375,6 @@ return locate(bottom_left.x + offset_x, bottom_left.y + offset_y, bottom_left.z) /// Gets the turf above the given target. Returns null if there is no turf above the target -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/turf_reservation/proc/get_turf_above(turf/target) var/list/bounds_info = calculate_turf_bounds_information(target) if(isnull(bounds_info)) @@ -382,9 +390,9 @@ var/turf/bottom_left = bottom_left_turfs[z_idx - 1] return locate(bottom_left.x + offset_x, bottom_left.y + offset_y, bottom_left.z) +// VOIDCREW EDIT: Bound long site releases while preserving atomic teardown for small reservations. #undef RESERVATION_RELEASE_YIELD_THRESHOLD -// VOIDCREW EDIT END /datum/turf_reservation/New() LAZYADD(SSmapping.turf_reservations, src) diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm index aca39fec93e..8f02fe48c7c 100644 --- a/code/modules/mining/aux_base.dm +++ b/code/modules/mining/aux_base.dm @@ -164,7 +164,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/auxiliary_base, 32) var/list/all_mining_turfs = list() for(var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING)) all_mining_turfs += Z_TURFS(z_level) - // VOIDCREW EDIT ADDITION: every lattice encounter level and every planet level + // VOIDCREW EDIT ADDITION START: overmap - every lattice encounter level and every planet level // publishes ZTRAIT_MINING in this fork, so a blind drop picked uniformly over // the gutter, unclaimed slots and LIVE co-tenant sites - dropping a shuttle into // another crew's ruin. Allocator-dealt ground is not a blind-drop target. diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index 5f138241e6e..729ceaa540d 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -80,7 +80,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) if(area != target_area && ((area.area_flags & LOCAL_TELEPORT) || (target_area.area_flags & LOCAL_TELEPORT))) balloon_alert(user, "unable to activate!") return - // VOIDCREW EDIT ADDITION: fultons don't go through do_teleport(), so they need the + // VOIDCREW EDIT ADDITION START: mining - fultons don't go through do_teleport(), so they need the // bitrunning boundary check of their own. The LOCAL_TELEPORT test above misses a // domain's reservation floor, which is plain /area/space. if(SSbitrunning.is_domain_turf(get_turf(thing)) != SSbitrunning.is_domain_turf(get_turf(beacon))) diff --git a/code/modules/mining/lavaland/mining_loot/megafauna/legion.dm b/code/modules/mining/lavaland/mining_loot/megafauna/legion.dm index af29220fb67..b906ed24d1e 100644 --- a/code/modules/mining/lavaland/mining_loot/megafauna/legion.dm +++ b/code/modules/mining/lavaland/mining_loot/megafauna/legion.dm @@ -38,7 +38,7 @@ return var/datum/weather/affected_weather for(var/datum/weather/weather as anything in SSweather.processing) - // VOIDCREW EDIT ADDITION: storms are per-SITE, not per-level. Every voidcrew planet + // VOIDCREW EDIT ADDITION START: overmap - storms are per-SITE, not per-level. Every voidcrew planet // storm uses area_type = /area/overmap_encounter/planetoid, so on a packed planet // level this matched a CO-TENANT's storm and wind_down() cancelled it outright for a // crew standing on a different planet. A storm with no site keeps the z-wide match. @@ -96,7 +96,7 @@ for(var/datum/weather/weather as anything in SSweather.processing) if(weather.stage != MAIN_STAGE) continue - // VOIDCREW EDIT ADDITION: same site scoping as attack_self() above - the damage + // VOIDCREW EDIT ADDITION START: overmap - same site scoping as attack_self() above - the damage // boost leaked off a co-tenant planet's storm exactly the same way. if(weather.weather_site && !weather.weather_site.contains_turf(target_turf)) continue diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 5733553a656..cd902b071c3 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -187,9 +187,11 @@ if(istype(target, /obj/structure/ore_box)) var/obj/structure/ore_box/box = target for(var/obj/item/stack/ore/ore_item in box.contents) + // VOIDCREW EDIT START: mining unloads ore satchels through the ore intake. ore_list += ore_item else if(istype(target, /obj/item/storage/bag/ore)) // VOIDCREW EDIT ADDITION - a mining satchel dropped on the input side empties like an ore box instead of sitting there for(var/obj/item/stack/ore/ore_item in target.contents) + // VOIDCREW EDIT END ore_list += ore_item else if(istype(target, /obj/item/stack/ore)) ore_list += target diff --git a/code/modules/mining/machine_silo.dm b/code/modules/mining/machine_silo.dm index 4fbd00e018f..991d8e59cd1 100644 --- a/code/modules/mining/machine_silo.dm +++ b/code/modules/mining/machine_silo.dm @@ -245,7 +245,7 @@ data["materials"] = materials.ui_data() data["machines"] = list() - // VOIDCREW EDIT: a connection whose machine died (or hard-deleted to a null entry) + // VOIDCREW EDIT START: research - a connection whose machine died (or hard-deleted to a null entry) // must not crash the whole window. Pruned from the real list, not skipped in the // data, because ui_act's hold/remove actions index into ore_connected_machines - // a display list that skips entries would point those buttons at the wrong machine. @@ -279,7 +279,7 @@ ) ) data["banned_users"] = banned_users - data["id_required"] = ID_required + data["id_required"] = ID_required // VOIDCREW EDIT: research prunes dead silo links and matches the UI data contract. return data @@ -346,7 +346,7 @@ if("toggle_restrict") attempt_toggle_restrict(usr) - return TRUE + return TRUE // VOIDCREW EDIT: research prunes dead silo links and matches the UI data contract. /** * Called from the ore silo's UI, when someone attempts to (un)ban a user from using the ore silo. * The person doing the banning should have at least QM access. Unless this is emagged. Not modifiable by silicons unless emagged. diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 77b47827396..7138bb5739f 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -49,7 +49,7 @@ if(!refined_type) return TRUE - if(I.use_tool(src, user, 0, volume=50, amount=1)) //one fuel per chunk, otherwise a self-refuelling welder smelts for free + if(I.use_tool(src, user, 0, volume=50, amount=1)) //one fuel per chunk, otherwise a self-refuelling welder smelts for free // VOIDCREW EDIT: mining consumes welder fuel and identifies the plasma smelting machine. new refined_type(drop_location()) use(1) @@ -161,7 +161,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/stack/ore/plasma/welder_act(mob/living/user, obj/item/I) - to_chat(user, span_warning("You can't hit a high enough temperature to smelt [src] properly! It needs an ore redemption machine.")) + to_chat(user, span_warning("You can't hit a high enough temperature to smelt [src] properly! It needs an ore redemption machine.")) // VOIDCREW EDIT: mining consumes welder fuel and identifies the plasma smelting machine. return TRUE // VOIDCREW EDIT END diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 85b56fa1df8..512a64f410d 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -65,7 +65,6 @@ vote_on_poll_handler(poll, href_list) //When you cop out of the round (NB: this HAS A SLEEP FOR PLAYER INPUT IN IT) -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /mob/dead/new_player/proc/make_me_an_observer() if(QDELETED(src) || !src.client) ready = PLAYER_NOT_READY @@ -75,7 +74,7 @@ if(SSlag_switch.measures[DISABLE_DEAD_KEYLOOP]) less_input_message = " - Notice: Observer freelook is currently disabled." // Don't convert this to tgui please, it's way too important - var/this_is_like_playing_right = alert(usr, "Are you sure you wish to observe? [get_respawn_notice()][less_input_message]", "Observe", "Yes", "No") + var/this_is_like_playing_right = alert(usr, "Are you sure you wish to observe? [get_respawn_notice()][less_input_message]", "Observe", "Yes", "No") // VOIDCREW EDIT: ghost respawn integration: display the applicable respawn notice (voidcrew/edits/mobs/ghost_respawn.dm) if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes") ready = PLAYER_NOT_READY return FALSE @@ -108,7 +107,6 @@ qdel(src) return TRUE -// VOIDCREW EDIT END /proc/get_job_unavailable_error_message(retval, jobtitle) switch(retval) if(JOB_AVAILABLE) @@ -152,7 +150,6 @@ return JOB_UNAVAILABLE_GENERIC return JOB_AVAILABLE -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /mob/dead/new_player/proc/AttemptLateSpawn(rank) // Check that they're picking someone new for new character respawning if(CONFIG_GET(flag/allow_respawn) == RESPAWN_FLAG_NEW_CHARACTER) @@ -248,9 +245,8 @@ if(humanc && arrivals && !arrivals.power_environ) //arrivals depowered humanc.put_in_hands(new /obj/item/crowbar/large/emergency(get_turf(humanc))) //if hands full then just drops on the floor log_manifest(character.mind.key, character.mind, character, latejoin = TRUE) - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CREWMEMBER_JOINED, character, character.mind.assigned_role.title) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CREWMEMBER_JOINED, character, character.mind.assigned_role.title) // VOIDCREW EDIT: ship crew spawning: validate arrival and announce only after equipment and manifest setup (voidcrew/edits/mobs/new_player.dm) -// VOIDCREW EDIT END /mob/dead/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee) //TODO: figure out a way to exclude wizards/nukeops/demons from this. for(var/C in GLOB.employmentCabinets) @@ -259,15 +255,16 @@ employmentCabinet.addFile(employee) /// Creates, assigns and returns the new_character to spawn as. Assumes a valid mind.assigned_role exists. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/mob/dead/new_player/proc/create_character(atom/destination, datum/callback/validate_arrival) +/mob/dead/new_player/proc/create_character(atom/destination, datum/callback/validate_arrival) // VOIDCREW EDIT: ship crew spawning: validate arrival and announce only after equipment and manifest setup (voidcrew/edits/mobs/new_player.dm) spawning = TRUE mind.active = FALSE //we wish to transfer the key manually var/mob/living/spawning_mob = mind.assigned_role.get_spawn_mob(client, destination) + // VOIDCREW EDIT START - ship crew spawning: validate arrival and announce only after equipment and manifest setup (voidcrew/edits/mobs/new_player.dm) if(QDELETED(src) || !HAS_CONNECTED_PLAYER(src) || (validate_arrival && !validate_arrival.Invoke(spawning_mob))) qdel(spawning_mob) return // Disconnected or destination refused after appearance checks. + // VOIDCREW EDIT END if(!isAI(spawning_mob)) // Unfortunately there's still snowflake AI code out there. // transfer_to sets mind to null @@ -282,8 +279,6 @@ new_character = . -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /mob/dead/new_player/proc/transfer_character() . = new_character if(!.) @@ -293,11 +288,11 @@ var/area/joined_area = get_area(new_character.loc) if(joined_area) joined_area.on_joining_game(new_character) + // VOIDCREW EDIT REMOVAL - ship crew spawning: validate arrival and announce only after equipment and manifest setup (voidcrew/edits/mobs/new_player.dm) // The spawn caller announces the arrival after equipment and manifest setup. new_character = null qdel(src) -// VOIDCREW EDIT END /mob/dead/new_player/proc/ViewManifest() if(!client) return diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 5ead24cba07..4ffac79cba6 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -316,7 +316,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!HAS_TRAIT(src, TRAIT_CORPSELOCKED)) //corpse-locked have to confirm with the alert below ghostize(TRUE) return TRUE - var/response = tgui_alert(usr, "Are you sure you want to ghost? You won't be able to re-enter your body! [get_respawn_notice()]", "Confirm Ghost Observe", list("Ghost", "Stay in Body")) + var/response = tgui_alert(usr, "Are you sure you want to ghost? You won't be able to re-enter your body! [get_respawn_notice()]", "Confirm Ghost Observe", list("Ghost", "Stay in Body")) // VOIDCREW EDIT: ghost respawn and interaction integration (voidcrew/edits/mobs/ghost_respawn.dm): preserve respawn notices and validate clicked loot tiles if(response != "Ghost") return FALSE//didn't want to ghost after-all ghostize(FALSE) // FALSE parameter is so we can never re-enter our body. U ded. @@ -937,11 +937,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp // things buried under other atoms instead of only whatever is on top. // Deliberately skips COMSIG_CLICK_ALT and click_alt() - ghosts look, they don't act. if(SEND_SIGNAL(src, COMSIG_MOB_ALTCLICKON, target) & COMSIG_MOB_CANCEL_CLICKON) + // VOIDCREW EDIT START - ghost respawn and interaction integration (voidcrew/edits/mobs/ghost_respawn.dm): preserve respawn notices and validate clicked loot tiles return var/turf/tile = get_turf(target) if(isnull(tile) || isnull(client)) return client.loot_panel.open(tile) + // VOIDCREW EDIT END /mob/dead/observer/AltClickSecondaryOn(atom/target) if(client && check_rights_for(client, R_DEBUG)) diff --git a/code/modules/mob/living/basic/lavaland/legion/legion.dm b/code/modules/mob/living/basic/lavaland/legion/legion.dm index dc2248ebcb0..011ee9d3a1f 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion.dm @@ -60,7 +60,7 @@ return UnregisterSignal(stored_mob, COMSIG_LIVING_REVIVE) // Direct deletion destroys our controller before deleting the contained corpse. - ai_controller?.clear_blackboard_key(BB_LEGION_CORPSE) + ai_controller?.clear_blackboard_key(BB_LEGION_CORPSE) // VOIDCREW EDIT: Voidcrew legion lifecycle integration: tolerate the controller being deleted before its stored corpse stored_mob.remove_status_effect(/datum/status_effect/grouped/stasis, STASIS_LEGION_EATEN) stored_mob.add_mood_event("legion_core", /datum/mood_event/healsbadman/long_term) // This will still probably mostly be gone before you are alive stored_mob = null diff --git a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm index e92d85c4d5c..b1732eb752f 100644 --- a/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm +++ b/code/modules/mob/living/basic/lavaland/legion/spawn_legions.dm @@ -26,7 +26,6 @@ return FALSE return TRUE -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/action/cooldown/mob_cooldown/skull_launcher/Activate(atom/target) var/turf/target_turf = get_turf(target) @@ -36,18 +35,20 @@ // The skull is thrown, so it has to be able to physically get there. Targeting only // needs line of sight, and glass is transparent but solid - without this a legion // stood outside a window drops brood on the far side of the hull. + // VOIDCREW EDIT START - Voidcrew legion reach integration: skulls must stop at solid hull obstacles (voidcrew/edits/modules/mob/living/basic/lavaland/legion/spawn_legions.dm) target_turf = clamp_to_reachable_turf(target_turf) if (isnull(target_turf)) owner.balloon_alert(owner, "no room!") StartCooldown(0.5 SECONDS) return + // VOIDCREW EDIT END // Only a dense mob can be in the way now - clamp_to_reachable_turf() already rejected // anything solid. Shuffle off it if there's a free neighbour we can also reach. if (target_turf.is_blocked_turf()) var/list/near_turfs = RANGE_TURFS(1, target_turf) - target_turf for (var/turf/check_turf as anything in near_turfs) - if (check_turf.is_blocked_turf() || clamp_to_reachable_turf(check_turf) != check_turf) + if (check_turf.is_blocked_turf() || clamp_to_reachable_turf(check_turf) != check_turf) // VOIDCREW EDIT: Voidcrew legion reach integration: skulls must stop at solid hull obstacles (voidcrew/edits/modules/mob/living/basic/lavaland/legion/spawn_legions.dm) near_turfs -= check_turf if (length(near_turfs)) target_turf = pick(near_turfs) @@ -72,7 +73,6 @@ StartCooldown() /// Actually create a mob -// VOIDCREW EDIT END /datum/action/cooldown/mob_cooldown/skull_launcher/proc/spawn_skull(turf/spawn_location, target) var/mob/living/basic/legion_brood/brood = new spawn_type(spawn_location) if (istype(brood)) diff --git a/code/modules/mob/living/basic/tree.dm b/code/modules/mob/living/basic/tree.dm index 6027f941dc8..7dd85e78509 100644 --- a/code/modules/mob/living/basic/tree.dm +++ b/code/modules/mob/living/basic/tree.dm @@ -74,7 +74,7 @@ if(co2 > 0 && SPT_PROB(13, seconds_per_tick)) var/amt = min(co2, 9) var/datum/gas_mixture/turf_air = our_turf.return_air() // VOIDCREW EDIT: written to; leaves the shared planetary mix - turf_air.gases[/datum/gas/carbon_dioxide][MOLES] -= amt + turf_air.gases[/datum/gas/carbon_dioxide][MOLES] -= amt // VOIDCREW EDIT: planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) our_turf.atmos_spawn_air("[GAS_O2]=[amt]") /mob/living/basic/tree/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE) diff --git a/code/modules/mob/living/basic/trooper/pirate.dm b/code/modules/mob/living/basic/trooper/pirate.dm index d3c180d152e..229104cc577 100644 --- a/code/modules/mob/living/basic/trooper/pirate.dm +++ b/code/modules/mob/living/basic/trooper/pirate.dm @@ -32,6 +32,7 @@ light_range = 2 light_power = 2.5 light_color = COLOR_SOFT_RED + // VOIDCREW EDIT REMOVAL - overmap ruin loot: retain the pirate corpse drop without a guaranteed duplicate energy sword mob_spawner = /obj/effect/mob_spawn/corpse/human/pirate/melee corpse = /obj/effect/mob_spawn/corpse/human/pirate/melee r_hand = /obj/item/melee/energy/sword/pirate diff --git a/code/modules/mob/living/basic/trooper/trooper.dm b/code/modules/mob/living/basic/trooper/trooper.dm index af5c58db6b9..32829923d23 100644 --- a/code/modules/mob/living/basic/trooper/trooper.dm +++ b/code/modules/mob/living/basic/trooper/trooper.dm @@ -29,10 +29,11 @@ /// Path of the left hand held item we give to the mob's visuals. var/l_hand + /mob/living/basic/trooper/Initialize(mapload) . = ..() if(use_dynamic_appearance) // VOIDCREW EDIT - apply_dynamic_human_appearance(src, mob_spawn_path = mob_spawner, r_hand = r_hand, l_hand = l_hand) + apply_dynamic_human_appearance(src, mob_spawn_path = mob_spawner, r_hand = r_hand, l_hand = l_hand) // VOIDCREW EDIT: trooper appearance integration: respect static fork sprites (voidcrew/edits/modules/mob/living/basic/trooper/trooper.dm) if(LAZYLEN(loot) || corpse) LAZYOR(loot, corpse) loot = string_list(loot) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 190b73137ae..dd3ca505f60 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -16,7 +16,7 @@ TRAIT_NO_UNDERWEAR, TRAIT_PIERCEIMMUNE, TRAIT_RADIMMUNE, - // VOIDCREW EDIT ADDITION: upstream hangs the mineral-buff trait solely on + // VOIDCREW EDIT ADDITION START: upstream hangs the mineral-buff trait solely on - self_surgery: retain mineral metabolism when a golem receives another brain // /obj/item/organ/brain/golem, so a golem body carrying anyone else's brain eats // minerals (TRAIT_ROCK_EATER, from the golem stomach) and gets nothing back. This // fork ships self-surgery, so brain-swapping into a golem shell is routine, and the diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index b6caf6bd911..1d0a87ea67b 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -215,7 +215,6 @@ /mob/living/carbon/get_equipped_speed_mod_items() return ..() + get_equipped_items() -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /mob/living/carbon/doUnEquip(obj/item/item_dropping, force, newloc, no_move, invdrop = TRUE, silent = FALSE) . = ..() //Sets the default return value to what the parent returns. if(!. || !item_dropping) //We don't want to set anything to null if the parent returned 0. @@ -253,7 +252,7 @@ // Not an else-if because we're probably equipped in another slot if(item_dropping == internal && (QDELETED(src) || QDELETED(item_dropping) || item_dropping.loc != src)) - cutoff_internals("tank unequipped from slot, newloc=[item_dropping.loc]") + cutoff_internals("tank unequipped from slot, newloc=[item_dropping.loc]") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) if(!QDELETED(src)) update_mob_action_buttons(UPDATE_BUTTON_STATUS) @@ -265,7 +264,6 @@ hud_used?.update_locked_slots() /// Returns the helmet if an air tank compatible helmet is equipped. -// VOIDCREW EDIT END /mob/living/carbon/proc/can_breathe_helmet() if (isclothing(head) && (head.clothing_flags & HEADINTERNALS)) return head @@ -379,7 +377,6 @@ * Arguments: * * is_external - A boolean which indicates if the air tank must be equipped, or stored elsewhere. */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /mob/living/carbon/proc/toggle_close_internals(is_external = FALSE) if (!internal && !external) return @@ -388,12 +385,10 @@ /// Prepares emergency disconnect from open air tanks and notifies in chat. Usually called after mob suddenly unequips breathing apparatus. /// reason names the call site so intermittent cutoffs can be traced - see log_internals_cutoff(). -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/mob/living/carbon/proc/cutoff_internals(reason = "unspecified") +/mob/living/carbon/proc/cutoff_internals(reason = "unspecified") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) if (!external && !internal) return - log_internals_cutoff(reason) + log_internals_cutoff(reason) // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) to_chat(src, span_notice("Your internals disconnect from [external || internal] and the valve closes.")) close_all_airtanks() @@ -404,7 +399,6 @@ * Arguments: * * tank - The given tank to toggle open and start breathing from internally. */ -// VOIDCREW EDIT END /mob/living/carbon/proc/toggle_internals(obj/item/tank) // Carbons can't open their own internals tanks. return FALSE diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 96d41e05ae6..5f2e25d5bc8 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -444,7 +444,7 @@ /mob/living/carbon/proc/get_breath_from_internal(volume_needed) if(invalid_internals()) // Unexpectely lost breathing apparatus and ability to breathe from the internal air tank. - cutoff_internals("invalid internals on breath") + cutoff_internals("invalid internals on breath") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) return if (external) . = external.remove_air_volume(volume_needed) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 76aca672fb1..9bb4e2da159 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1336,7 +1336,7 @@ if(!istype(target)) CRASH("Missing target arg for can_perform_action") - if(stat != CONSCIOUS && !(stat == SOFT_CRIT && (action_bitflags & ALLOW_SOFT_CRIT))) + if(stat != CONSCIOUS && !(stat == SOFT_CRIT && (action_bitflags & ALLOW_SOFT_CRIT))) // VOIDCREW EDIT: soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) to_chat(src, span_warning("You are not conscious enough for this action!")) return FALSE @@ -1344,11 +1344,13 @@ var/ignore_flags = NONE if(interaction_flags_atom & INTERACT_ATOM_IGNORE_RESTRAINED) ignore_flags |= INCAPABLE_RESTRAINTS - if(!(interaction_flags_atom & INTERACT_ATOM_CHECK_GRAB) && stat != SOFT_CRIT) + if(!(interaction_flags_atom & INTERACT_ATOM_CHECK_GRAB) && stat != SOFT_CRIT) // VOIDCREW EDIT: soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) ignore_flags |= INCAPABLE_GRAB + // VOIDCREW EDIT START - soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) var/is_incapacitated = (action_bitflags & ALLOW_SOFT_CRIT) ? incapacitated_except_softcrit(ignore_flags) : INCAPACITATED_IGNORING(src, ignore_flags) if(is_incapacitated) + // VOIDCREW EDIT END to_chat(src, span_warning("You are incapacitated at the moment!")) return FALSE @@ -2376,7 +2378,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) if(SOFT_CRIT) if(stat >= UNCONSCIOUS) ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) //adding trait sources should come before removing to avoid unnecessary updates - ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) + ADD_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) // VOIDCREW EDIT: soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) if(pulledby) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, PULLED_WHILE_SOFTCRIT_TRAIT) if(UNCONSCIOUS) @@ -2401,7 +2403,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT) ADD_TRAIT(src, TRAIT_CRITICAL_CONDITION, STAT_TRAIT) log_combat(src, src, "entered soft crit") - REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) + REMOVE_TRAIT(src, TRAIT_HANDS_BLOCKED, STAT_TRAIT) // VOIDCREW EDIT: soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) if(UNCONSCIOUS) if(. != HARD_CRIT) become_blind(UNCONSCIOUS_TRAIT) diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index cccf350f4e1..bae8c944391 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -6,7 +6,7 @@ //Mind updates sync_mind() // VOIDCREW: retain physical boarding history across reconnects. - LoadComponent(/datum/component/ship_zone_logging) + LoadComponent(/datum/component/ship_zone_logging) // VOIDCREW EDIT: overmap logging: retain ship boarding history on reconnect update_damage_hud() update_health_hud() diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 292a2ec5ba4..6b3b4c8e371 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -24,7 +24,7 @@ create_eye() - if((target_ai.mind && target_ai.mind.active) || SSticker.current_state == GAME_STATE_SETTING_UP || target_ai.mind?.assigned_role?.ship_role == "ai") + if((target_ai.mind && target_ai.mind.active) || SSticker.current_state == GAME_STATE_SETTING_UP || target_ai.mind?.assigned_role?.ship_role == "ai") // VOIDCREW EDIT: ship silicon crew: retain the assigned crew AI relationship (voidcrew/edits/machinery/silicon_ship_systems.dm) target_ai.mind.transfer_to(src) if(is_antag()) to_chat(src, span_userdanger("You have been installed as an AI! ")) @@ -288,7 +288,7 @@ if (!is_valid_z_level(ai_turf, target_turf)) return FALSE - // VOIDCREW EDIT ADDITION: packed-level containment. can_see() in + // VOIDCREW EDIT ADDITION START: packed-level containment. can_see() in - overmap: contain observers and effects within their packed encounter // voidcrew/edits/machinery/silicon_ship_systems.dm scopes an AI that is aboard a HULL; // an AI with no hull scope (an outpost core, a ruin, an admin spawn) falls through to // cameranet.checkTurfVis(), and a co-tenant ruin with its own mapped cameras is lit for @@ -571,7 +571,7 @@ var/mob/living/silicon/ai/U = usr - // VOIDCREW EDIT ADDITION: packed-level containment, resolved once outside the loop. + // VOIDCREW EDIT ADDITION START: packed-level containment, resolved once outside the loop. - overmap: contain observers and effects within their packed encounter // Lattice encounter levels and planet levels both publish ZTRAIT_MINING, and in this // fork is_station_level() means "any z with a hull on it", so both clauses below admit a // co-tenant's cameras. The eye is already refused entry by silicon_ship_systems.dm, but @@ -585,7 +585,7 @@ var/list/tempnetwork = C.network if(!camera_turf || !(is_station_level(camera_turf.z) || is_mining_level(camera_turf.z) || (CAMERANET_NETWORK_SS13 in tempnetwork))) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START - overmap: contain observers and effects within their packed encounter if(map_region_excludes_turf(ai_region, camera_turf)) continue // VOIDCREW EDIT END diff --git a/code/modules/mob/living/silicon/ai/ai_say.dm b/code/modules/mob/living/silicon/ai/ai_say.dm index 402002507d1..01ecbbd3a34 100644 --- a/code/modules/mob/living/silicon/ai/ai_say.dm +++ b/code/modules/mob/living/silicon/ai/ai_say.dm @@ -149,14 +149,14 @@ var/list/players = list() var/turf/ai_turf = get_turf(src) - // VOIDCREW EDIT ADDITION: is_valid_z_level() is bare z equality, and a packed z-level + // VOIDCREW EDIT ADDITION START: is_valid_z_level() is bare z equality, and a packed z-level - overmap: contain observers and effects within their packed encounter // carries up to four unrelated crews. A ship AI announcing while docked at an encounter // was heard in full, text and VOX, by every co-tenant. Resolved once, outside the loop. var/datum/ai_region = map_region_for_turf(ai_turf) // VOIDCREW EDIT END for(var/mob/player_mob as anything in GLOB.player_list) var/turf/player_turf = get_turf(player_mob) - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START - overmap: contain observers and effects within their packed encounter if(map_region_excludes_turf(ai_region, player_turf)) continue // VOIDCREW EDIT END @@ -178,7 +178,7 @@ // If there is no single listener, broadcast to everyone in the same z level if(!only_listener) - // VOIDCREW EDIT ADDITION: same packed-level containment as the announcement + // VOIDCREW EDIT ADDITION START: same packed-level containment as the announcement - overmap: contain observers and effects within their packed encounter // text above - see /mob/living/silicon/ai/proc/announcement(). var/datum/ai_region = map_region_for_turf(ai_turf) // VOIDCREW EDIT END @@ -191,7 +191,7 @@ var/turf/player_turf = get_turf(player_mob) if(!is_valid_z_level(ai_turf, player_turf)) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START - overmap: contain observers and effects within their packed encounter if(map_region_excludes_turf(ai_region, player_turf)) continue // VOIDCREW EDIT END diff --git a/code/modules/mob/living/silicon/ai/robot_control.dm b/code/modules/mob/living/silicon/ai/robot_control.dm index 9b3ed32b9f3..355129c2f5e 100644 --- a/code/modules/mob/living/silicon/ai/robot_control.dm +++ b/code/modules/mob/living/silicon/ai/robot_control.dm @@ -35,14 +35,14 @@ var/turf/ai_current_turf = get_turf(owner) data["robots"] = list() - // VOIDCREW EDIT ADDITION: packed-level containment - is_valid_z_level() is bare z + // VOIDCREW EDIT ADDITION START: packed-level containment - is_valid_z_level() is bare z - overmap: contain observers and effects within their packed encounter // equality, so a co-tenant's bots were listed and remotely commandable. var/datum/ai_region = map_region_for_turf(ai_current_turf) // VOIDCREW EDIT END for(var/mob/living/our_bot as anything in GLOB.bots_list) if(!isbot(our_bot) || !is_valid_z_level(ai_current_turf, get_turf(our_bot))) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START - overmap: contain observers and effects within their packed encounter if(map_region_excludes_turf(ai_region, get_turf(our_bot))) continue // VOIDCREW EDIT END diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index f8368ea4602..9ab4b141135 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -984,10 +984,12 @@ unbuckle_mob(unbuckle_me_now, FALSE) /mob/living/silicon/robot/proc/TryConnectToAI() + // VOIDCREW EDIT START - ship silicon crew: retain the assigned crew AI relationship (voidcrew/edits/machinery/silicon_ship_systems.dm) if(mind?.assigned_role?.ship_role == "cyborg" || istype(get_area(src), /area/shuttle/voidcrew)) set_connected_ai(crew_ai()) else set_connected_ai(select_active_ai_with_fewest_borgs(z)) + // VOIDCREW EDIT END if(connected_ai) lawsync() lawupdate = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 19ab82c2aea..3f2b819cd5b 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -620,7 +620,7 @@ /mob/living/simple_animal/hostile/proc/ListTargetsLazy(_Z)//Step 1, find out what we can see var/static/hostile_machines = typecacheof(list(/obj/machinery/porta_turret, /obj/vehicle/sealed/mecha)) . = list() - // VOIDCREW EDIT ADDITION: packed-level containment. vision_range is 9 by default and two + // VOIDCREW EDIT ADDITION START: packed-level containment. vision_range is 9 by default and two - overmap: contain observers and effects within their packed encounter // tenants' nearest live turfs are 6 apart, so a mob at the edge of its slot acquired a // player in the NEXT slot - one it can never reach, because /turf/cordon is never // Adjacent(), so it paths at them for the rest of its life. Resolved once per call. @@ -628,7 +628,7 @@ // VOIDCREW EDIT END for (var/I in SSmobs.clients_by_zlevel[_Z]) var/mob/M = I - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START - overmap: contain observers and effects within their packed encounter if(map_region_excludes_turf(own_region, get_turf(M))) continue // VOIDCREW EDIT END diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm index c5625b8429a..ace7f2d257e 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm @@ -82,48 +82,6 @@ return ..() return ..() -// VOIDCREW: record targeting decisions, including aggro before any attack lands. -/mob/living/simple_animal/hostile/megafauna/add_target(new_target) - var/atom/previous_target = target - . = ..() - if(previous_target != target) - log_aggro_change(previous_target, target) - -/mob/living/simple_animal/hostile/megafauna/handle_target_del(datum/source) - SIGNAL_HANDLER - // The parent clears target before calling LoseTarget(), so capture it now. - if(target == source) - log_aggro_change(target, null) - return ..() - -/mob/living/simple_animal/hostile/megafauna/proc/aggro_target_description(atom/subject) - if(!subject) - return "none" - var/description = "[key_name_and_tag(subject)] [REF(subject)] at [loc_name(subject)]; [overmap_zone_log_context(subject)]" - if(ismecha(subject)) - var/obj/vehicle/sealed/mecha/mech = subject - var/list/pilots = list() - for(var/mob/pilot as anything in mech.occupants) - pilots += key_name_and_tag(pilot) - description += "; occupants: [length(pilots) ? jointext(pilots, ", ") : "none"]" - return description - -/mob/living/simple_animal/hostile/megafauna/proc/log_aggro_change(atom/previous_target, atom/new_target) - var/action = new_target ? (previous_target ? "switched target" : "acquired target") : "lost target" - var/message = "\[MEGAFAUNA AGGRO\] [action]; from: [aggro_target_description(previous_target)]; to: [aggro_target_description(new_target)]" - log_message(message, LOG_ATTACK, color = "blue") - // Keep the same event in the involved players' individual logs, too. - var/list/mob/observers = list() - for(var/atom/subject as anything in list(previous_target, new_target)) - if(ismob(subject)) - observers |= subject - else if(ismecha(subject)) - var/obj/vehicle/sealed/mecha/mech = subject - for(var/mob/pilot as anything in mech.occupants) - observers |= pilot - for(var/mob/observer as anything in observers) - observer.log_message("[key_name_and_tag(src)] at [loc_name(src)]; [overmap_zone_log_context(src)]: [message]", LOG_ATTACK, color = "blue", log_globally = FALSE) - /mob/living/simple_animal/hostile/megafauna/death(gibbed, list/force_grant) if(gibbed) // in case they've been force dusted return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index b94431db55e..052a45b120a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -3,7 +3,7 @@ vision_range = 2 atmos_requirements = null faction = list(FACTION_MINING) - // VOIDCREW EDIT: TRAIT_SNOWSTORM_IMMUNE added. /mob/living/basic/mining - the newer + // VOIDCREW EDIT START: TRAIT_SNOWSTORM_IMMUNE added. /mob/living/basic/mining - the newer - overmap planets: legacy mining wildlife shares plasma-river immunity with basic mining mobs // base every other icemoon mob already sits on - grants all THREE of these // (see its Initialize), and this one being two-thirds of that list is an oversight // upstream never felt because on icemoon the plasma rivers are mapped, not carved. diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 3c18c37662c..4b2b27d45df 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -220,7 +220,7 @@ QDEL_NULL(access_card) GLOB.simple_animals[AIStatus] -= src SSnpcpool.currentrun -= src - SSidlenpcpool.currentrun -= src // voidcrew: same deal, an in-flight idle scan would hold us past Destroy + SSidlenpcpool.currentrun -= src // voidcrew: same deal, an in-flight idle scan would hold us past Destroy // VOIDCREW EDIT: overmap NPC lifecycle: remove dying mobs from the in-flight idle scan return ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 0b35ba36687..eca260d66a5 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -757,9 +757,11 @@ if(ismecha(loc)) return + // VOIDCREW EDIT START - soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) if(incapacitated_except_softcrit() || HAS_TRAIT(src, TRAIT_HANDS_BLOCKED)) return if(stat == SOFT_CRIT && next_move > world.time) + // VOIDCREW EDIT END return var/obj/item/I = get_active_held_item() @@ -806,6 +808,7 @@ return usr.log_message("used the respawn button.", LOG_GAME) +// VOIDCREW EDIT REMOVAL - Voidcrew mob interaction: omit the generic roleplay admonition (voidcrew/edits/mobs) if(!client) usr.log_message("respawn failed due to disconnect.", LOG_GAME) diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index 4b7a9c04fad..09ca02a4289 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -274,7 +274,7 @@ wearer.update_clothing(part.slot_flags | slot_flags) wearer.update_obscured_slots(part.visor_flags_inv) if((part.clothing_flags & (MASKINTERNALS|HEADINTERNALS)) && wearer.invalid_internals()) - wearer.cutoff_internals("MOD part [part.type] [is_sealed ? "sealed" : "unsealed"]") + wearer.cutoff_internals("MOD part [part.type] [is_sealed ? "sealed" : "unsealed"]") // VOIDCREW EDIT: shuttle internals diagnostics: identify the disconnect call site (voidcrew/edits/modules/mob/living/carbon/inventory.dm) SEND_SIGNAL(src, COMSIG_MOD_PART_SEALED, part_datum) if(is_sealed) if (!active) diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index c89c79df5d7..86e5bcb7ce6 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -181,22 +181,24 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/mod_theme/civilian name = "civilian" + // VOIDCREW EDIT START - Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) desc = "A light-weight civilian suit that offers unmatched ease of movement without giving up a vacuum seal." extended_desc = "An experimental design by Nakamura Engineering, intended to be marketed towards civilian customers. \ This model sacrifices the protection from biological and chemical threats in exchange for \ vastly improved mobility, though the seals were kept intact for vacuum work. Due to the slimmed-down profile, \ it also has less capacity for modifications compared to mainline models." + // VOIDCREW EDIT END default_skin = "civilian" armor_type = /datum/armor/mod_theme_civilian max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT - min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) complexity_max = DEFAULT_MAX_COMPLEXITY - 3 slowdown_deployed = 0 variants = list( "civilian" = list( /obj/item/clothing/head/mod = list( UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) UNSEALED_MESSAGE = HELMET_UNSEAL_MESSAGE, SEALED_MESSAGE = HELMET_SEAL_MESSAGE, UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEEYES|HIDEHAIR|HIDESNOUT, @@ -204,21 +206,21 @@ ), /obj/item/clothing/suit/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) SEALED_INVISIBILITY = HIDEJUMPSUIT, UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE, SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE, ), /obj/item/clothing/gloves/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE, SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE, ), /obj/item/clothing/shoes/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE, SEALED_MESSAGE = BOOT_SEAL_MESSAGE, @@ -467,7 +469,7 @@ armor_type = /datum/armor/mod_theme_mining resistance_flags = FIRE_PROOF|LAVA_PROOF max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT - min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) complexity_max = DEFAULT_MAX_COMPLEXITY - 2 charge_drain = DEFAULT_CHARGE_DRAIN * 2 inbuilt_modules = list(/obj/item/mod/module/ash_accretion, /obj/item/mod/module/sphere_transform) @@ -557,6 +559,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/mod_theme/loader name = "loader" + // VOIDCREW EDIT START - Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) desc = "An experimental motorized harness manufactured by Scarborough Arms for quick and efficient munition supplies." extended_desc = "This powered suit is an experimental spinoff of standard Engineering suits. \ This fully articulated titanium exoskeleton is Scarborough Arms' suit of choice for their munition delivery men, \ @@ -567,10 +570,11 @@ suit capable of lifting 250 tons. Even the legs in the suit have been tuned to incredible capacity, \ the user being able to run at greater speeds for much longer distances and times than an unsuited equivalent. \ A lot of people would say loading cargo is a dull job. You could not disagree more." + // VOIDCREW EDIT END default_skin = "loader" armor_type = /datum/armor/mod_theme_loader max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT - min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) siemens_coefficient = 0.25 complexity_max = DEFAULT_MAX_COMPLEXITY - 5 slowdown_deployed = 0 @@ -585,7 +589,7 @@ "loader" = list( /obj/item/clothing/head/mod = list( UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR, SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT, SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, @@ -594,18 +598,18 @@ ), /obj/item/clothing/suit/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE, SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE, ), /obj/item/clothing/gloves/mod = list( - SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE, SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE, ), /obj/item/clothing/shoes/mod = list( - SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE, SEALED_MESSAGE = BOOT_SEAL_MESSAGE, @@ -1368,7 +1372,7 @@ "infiltrator" = list( /obj/item/clothing/head/mod = list( UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR, SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT|HIDEANTENNAE, SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, @@ -1378,20 +1382,20 @@ ), /obj/item/clothing/suit/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) SEALED_INVISIBILITY = HIDEJUMPSUIT|HIDEMUTWINGS, CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE, SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE, ), /obj/item/clothing/gloves/mod = list( - SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE, SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE, ), /obj/item/clothing/shoes/mod = list( - SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, // VOIDCREW EDIT: Voidcrew MOD integration: civilian, loader and ninja suits retain vacuum seals (voidcrew/modules/clothing) CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE, SEALED_MESSAGE = BOOT_SEAL_MESSAGE, diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm index b136683b8a2..c55d8acea22 100644 --- a/code/modules/mod/modules/modules_supply.dm +++ b/code/modules/mod/modules/modules_supply.dm @@ -87,7 +87,7 @@ // inside the deactivated module (and pinned by this list if later deleted) for(var/atom/movable/crate in stored_crates) crate.forceMove(drop_location()) - stored_crates.Cut() + stored_crates.Cut() // VOIDCREW EDIT: Voidcrew MOD storage lifecycle: keep crate and ore lists coherent while contents leave (voidcrew/edits/modules/mod/modules/modules_supply.dm) /obj/item/mod/module/clamp/proc/check_crate_pickup(atom/movable/target) if(length(stored_crates) >= max_crates) @@ -208,7 +208,7 @@ // the dead stack pinned it in this round-long list forever - one hard delete per // pickup once the bag held a full stack of that ore (round 4: ~380 of them, 170 s). if(QDELETED(ore)) - return + return // VOIDCREW EDIT: Voidcrew MOD storage lifecycle: keep crate and ore lists coherent while contents leave (voidcrew/edits/modules/mod/modules/modules_supply.dm) ores += ore /obj/item/mod/module/orebag/on_use() @@ -216,6 +216,7 @@ // and the old explicit `ores -= ore` mid-walk skipped every other stack anyway for(var/obj/item/ore in ores.Copy()) ore.forceMove(drop_location()) + // VOIDCREW EDIT REMOVAL - Voidcrew MOD storage lifecycle: keep crate and ore lists coherent while contents leave (voidcrew/edits/modules/mod/modules/modules_supply.dm) drain_power(use_energy_cost) /obj/item/mod/module/hydraulic diff --git a/code/modules/mod/modules/modules_visor.dm b/code/modules/mod/modules/modules_visor.dm index bd378fab8ae..f3bbc4afa2d 100644 --- a/code/modules/mod/modules/modules_visor.dm +++ b/code/modules/mod/modules/modules_visor.dm @@ -93,12 +93,12 @@ // VOIDCREW EDIT START - PR #415: Restore built-in MOD night vision. /obj/item/mod/module/night/on_activation() - ADD_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src)) + ADD_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src)) // VOIDCREW EDIT: Voidcrew MOD integration: add and remove the single night-vision trait through its scalar API (voidcrew/modules/clothing) mod.wearer.update_sight() // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #415: Restore built-in MOD night vision. /obj/item/mod/module/night/on_deactivation(display_message = TRUE, deleting = FALSE) - REMOVE_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src)) + REMOVE_TRAIT(mod.wearer, TRAIT_TRUE_NIGHT_VISION, REF(src)) // VOIDCREW EDIT: Voidcrew MOD integration: add and remove the single night-vision trait through its scalar API (voidcrew/modules/clothing) mod.wearer.update_sight() // VOIDCREW EDIT END diff --git a/code/modules/modular_computers/file_system/programs/budgetordering.dm b/code/modules/modular_computers/file_system/programs/budgetordering.dm index 955227cdb03..df654fda537 100644 --- a/code/modules/modular_computers/file_system/programs/budgetordering.dm +++ b/code/modules/modular_computers/file_system/programs/budgetordering.dm @@ -58,13 +58,16 @@ return FALSE -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. +// VOIDCREW EDIT: cargo refuses station supply apps without a supply shuttle; implementation in voidcrew/edits/modules/modular_computers/file_system/programs/budgetordering.dm. + /datum/computer_file/program/budgetorders/ui_data(mob/user) var/list/data = list() // can_run() should stop us ever opening without a supply shuttle, but a half filled // in app is still a far better failure than the blue screen a runtime here causes. + // VOIDCREW EDIT START: cargo handles the absent station supply shuttle in the budget app. var/obj/docking_port/mobile/supply/supply_shuttle = SSshuttle.supply data["location"] = supply_shuttle ? supply_shuttle.getStatusText() : "OFFLINE" + // VOIDCREW EDIT END data["department"] = "Cargo" var/datum/bank_account/buyer = SSeconomy.get_dep_account(cargo_account) var/obj/item/card/id/id_card = computer.computer_id_slot?.GetID() @@ -114,9 +117,9 @@ //Data regarding the User's capability to buy things. data["has_id"] = id_card - data["away"] = supply_shuttle ? (supply_shuttle.getDockedId() == docking_away) : FALSE + data["away"] = supply_shuttle ? (supply_shuttle.getDockedId() == docking_away) : FALSE // VOIDCREW EDIT: cargo handles the absent station supply shuttle in the budget app. data["self_paid"] = self_paid - data["docked"] = supply_shuttle ? (supply_shuttle.mode == SHUTTLE_IDLE) : FALSE + data["docked"] = supply_shuttle ? (supply_shuttle.mode == SHUTTLE_IDLE) : FALSE // VOIDCREW EDIT: cargo handles the absent station supply shuttle in the budget app. data["loan"] = !!SSshuttle.shuttle_loan data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched data["can_send"] = FALSE //There is no situation where I want the app to be able to send the shuttle AWAY from the station, but conversely is fine. @@ -171,19 +174,19 @@ return data -// VOIDCREW EDIT END /datum/computer_file/program/budgetorders/ui_static_data(mob/user) var/list/data = list() data["max_order"] = CARGO_MAX_ORDER return data -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/computer_file/program/budgetorders/ui_act(action, params, datum/tgui/ui, datum/ui_state/state) . = ..() // Same reasoning as ui_data(): every branch below assumes a station supply shuttle, // and there isn't one here. Nothing this app does is meaningful without it. + // VOIDCREW EDIT START: cargo handles the absent station supply shuttle in the budget app. if(isnull(SSshuttle.supply)) return + // VOIDCREW EDIT END switch(action) if("send") if(!SSshuttle.supply.canMove()) @@ -323,7 +326,6 @@ if(.) post_signal(cargo_shuttle) -// VOIDCREW EDIT END /datum/computer_file/program/budgetorders/proc/post_signal(command) var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm index 43fa74e9e57..c3a689e2c60 100644 --- a/code/modules/modular_computers/file_system/programs/radar.dm +++ b/code/modules/modular_computers/file_system/programs/radar.dm @@ -151,7 +151,7 @@ var/turf/there = get_turf(signal) if(isnull(here) || isnull(there) || !is_valid_z_level(here, there)) return RADAR_NOT_TRACKABLE - // VOIDCREW EDIT ADDITION: packed-level containment. is_valid_z_level() is bare z + // VOIDCREW EDIT ADDITION START: overmap - packed-level containment. is_valid_z_level() is bare z // equality, so a Lifeline (or Fission360, or the custodial locator) in one slot tracked // any suit-sensor crewmember in the neighbouring slot and track() handed the client a // true bearing and pixel offset off raw coordinate arithmetic. Refuses only a diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index d011b563058..02bb1143de4 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -147,11 +147,11 @@ playsound(computer, SFX_TERMINAL_TYPE, 25, FALSE) var/obj/machinery/camera/selected_camera = locate(params["camera"]) in GLOB.cameranet.cameras - if(can_view_camera(selected_camera)) + if(can_view_camera(selected_camera)) // VOIDCREW EDIT: comms revokes cameras outside the tablet ship network. camera_ref = WEAKREF(selected_camera) else camera_ref = null - update_active_camera_screen() + update_active_camera_screen() // VOIDCREW EDIT: comms revokes cameras outside the tablet ship network. return TRUE if(!spying) selected_camera.on_start_watching(src) @@ -163,7 +163,7 @@ if("start_tracking") if(!internal_tracker) - internal_tracker = new /datum/trackable/secureye(src) + internal_tracker = new /datum/trackable/secureye(src) // VOIDCREW EDIT: comms revokes cameras outside the tablet ship network. RegisterSignal(internal_tracker, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target)) internal_tracker.track_input(usr) return TRUE @@ -176,8 +176,10 @@ if(!target_camerachunk) CRASH("[src] was able to track [target] through /datum/trackable, but was not on a visible turf to cameras.") for(var/obj/machinery/camera/cameras as anything in target_camerachunk.cameras["[target.z]"]) + // VOIDCREW EDIT START: comms revokes cameras outside the tablet ship network. if(!can_view_camera(cameras)) continue + // VOIDCREW EDIT END var/found_target = locate(target) in cameras.can_see() if(!found_target) continue @@ -213,15 +215,17 @@ /datum/computer_file/program/secureye/proc/update_active_camera_screen() var/obj/machinery/camera/active_camera = camera_ref?.resolve() // VOIDCREW: moving the tablet or changing networks revokes an old camera view. + // VOIDCREW EDIT START: comms revokes cameras outside the tablet ship network. if(active_camera && !can_view_camera(active_camera)) if(!spying) active_camera.on_stop_watching(src) camera_ref = null active_camera = null last_camera_turf = null + // VOIDCREW EDIT END // Show static if can't use the camera if(!active_camera?.can_use()) - last_camera_turf = null + last_camera_turf = null // VOIDCREW EDIT: comms revokes cameras outside the tablet ship network. cam_screen.show_camera_static() return diff --git a/code/modules/modular_computers/file_system/programs/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/sm_monitor.dm index 37e9f5c9647..26fd04103a3 100644 --- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm @@ -34,7 +34,7 @@ var/turf/user_turf = get_turf(computer.ui_host()) if(!user_turf) return - // VOIDCREW EDIT ADDITION: packed-level containment. Two of the three clauses below fire + // VOIDCREW EDIT ADDITION START: overmap - packed-level containment. Two of the three clauses below fire // on a lattice encounter level (ZTRAIT_MINING is published by every one of them, and // is_station_level() means "any z with a hull on it" here), so a co-tenant's supermatter // appeared on the CIMS. Resolved once, outside the loop. @@ -44,7 +44,7 @@ //Exclude Syndicate owned, Delaminating, not within coverage, not on a tile. if (!sm.include_in_cims || !isturf(sm.loc) || !(is_station_level(sm.z) || is_mining_level(sm.z) || sm.z == user_turf.z)) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START: overmap scopes this effect to its encounter site. if(map_region_excludes_turf(console_region, get_turf(sm))) continue // VOIDCREW EDIT END diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index b941b6e6df1..dfa041a5b6d 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -385,7 +385,6 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list( propagate_network(O, newPN)//... and propagates it to the other side of the cable //Makes a new network for the cable and propgates it. If we already have one, just die -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/structure/cable/proc/propagate_if_no_network() if(powernet) return @@ -397,9 +396,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list( // neighbours. Only for callers about to cut EVERY cable on the net (a shuttle move): // the timers would rebuild nets over cables mid-transplant, and propagate_if_no_network() // then trusts those half-built nets after landing, leaving the grid permanently split. -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/obj/structure/cable/proc/cut_cable_from_powernet(remove = TRUE, rebuild_neighbor_networks = TRUE) +/obj/structure/cable/proc/cut_cable_from_powernet(remove = TRUE, rebuild_neighbor_networks = TRUE) // VOIDCREW EDIT: shuttle power integration: defer neighbor network rebuilding until every cable has moved (voidcrew/edits/machinery/power.dm) if(!powernet) return @@ -412,11 +409,13 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list( P.disconnect_from_network() var/list/P_list = list() + // VOIDCREW EDIT START - shuttle power integration: defer neighbor network rebuilding until every cable has moved (voidcrew/edits/machinery/power.dm) if(rebuild_neighbor_networks) for(var/dir_check in GLOB.cardinals) if(linked_dirs & dir_check) T1 = get_step(loc, dir_check) P_list += locate(/obj/structure/cable) in T1 + // VOIDCREW EDIT END // remove the cut cable from its turf and powernet, so that it doesn't get count in propagate_network worklist if(remove) @@ -438,7 +437,6 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list( // Definitions //////////////////////////////// -// VOIDCREW EDIT END #define CABLE_RESTRAINTS_COST 15 /obj/item/stack/cable_coil diff --git a/code/modules/power/singularity/dark_matter_singularity.dm b/code/modules/power/singularity/dark_matter_singularity.dm index a8a7b2de170..d70cdb74fc7 100644 --- a/code/modules/power/singularity/dark_matter_singularity.dm +++ b/code/modules/power/singularity/dark_matter_singularity.dm @@ -20,8 +20,10 @@ /obj/singularity/dark_matter/Initialize(mapload, starting_energy) . = ..() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(. == INITIALIZE_HINT_QDEL) // VOIDCREW return + // VOIDCREW EDIT END COOLDOWN_START(src, initial_explosion_immunity, 5 SECONDS) var/datum/component/singularity/resolved_singularity = singularity_component.resolve() resolved_singularity.chance_to_move_to_target = 100 diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index ba7e2913162..b28d883c737 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -192,11 +192,11 @@ var/power_usage = active_power_usage * seconds_per_tick if(machine_stat & (BROKEN)) return - if(!welded) + if(!welded) // VOIDCREW EDIT: shuttle power integration: preserve enabled emitters while a hull powernet reconnects (voidcrew/edits/machinery/power.dm) active = FALSE update_appearance() return - if(!powernet && power_usage) + if(!powernet && power_usage) // VOIDCREW EDIT: shuttle power integration: preserve enabled emitters while a hull powernet reconnects (voidcrew/edits/machinery/power.dm) // VOIDCREW EDIT CHANGE - original: `if(!welded || (!powernet && power_usage))` above. // A ship jump severs the hull cables of any net that reaches past the hull in // cable/beforeShuttleMove() (self-contained nets now travel intact, see @@ -207,12 +207,14 @@ // merely being rebuilt: reconnect or wait. Only an actually missing cable turns the // emitter off. var/turf/here = loc + // VOIDCREW EDIT START - shuttle power integration: preserve enabled emitters while a hull powernet reconnects (voidcrew/edits/machinery/power.dm) if(!connect_to_network() && isturf(here) && here.get_cable_node(cable_layer)) return if(!powernet) active = FALSE update_appearance() return + // VOIDCREW EDIT END if(!active) return if(power_usage && surplus() < power_usage) diff --git a/code/modules/power/singularity/reality_tear.dm b/code/modules/power/singularity/reality_tear.dm index 9f744cc45da..c164a1a43bb 100644 --- a/code/modules/power/singularity/reality_tear.dm +++ b/code/modules/power/singularity/reality_tear.dm @@ -26,8 +26,10 @@ var/collapse_spawn_time = 9 SECONDS /obj/reality_tear/proc/start_disaster() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(neutralize_trader_outpost_hazard(src)) // VOIDCREW return + // VOIDCREW EDIT END apply_wibbly_filters(src) playsound(loc, 'sound/effects/clockcult_gateway_disrupted.ogg', vary = 200, extrarange = 3, falloff_exponent = 1, frequency = 0.33, pressure_affected = FALSE, ignore_walls = TRUE, falloff_distance = 7) AddComponent( @@ -43,13 +45,17 @@ animate(time = 0.5 SECONDS, alpha = 0) /obj/reality_tear/proc/reality_collapse() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(neutralize_trader_outpost_hazard(src)) // VOIDCREW: it may have moved since creation. return + // VOIDCREW EDIT END playsound(loc, 'sound/effects/supermatter.ogg', 200, vary = TRUE, extrarange = 3, falloff_exponent = 1, frequency = 0.5, pressure_affected = FALSE, ignore_walls = TRUE, falloff_distance = 7) var/obj/singularity/bagulo = new(loc) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(!QDELETED(bagulo)) bagulo.expand(STAGE_TWO) bagulo.energy = 400 + // VOIDCREW EDIT END qdel(src) /obj/reality_tear/attack_tk(mob/user) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 5a8f0caf01f..913b46a361d 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -57,9 +57,11 @@ /obj/singularity/Initialize(mapload, starting_energy) . = ..() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(is_trader_outpost_protected(src)) // VOIDCREW log_game("OUTPOST PROTECTION: Prevented [name] from forming at [AREACOORD(src)].") return INITIALIZE_HINT_QDEL + // VOIDCREW EDIT END energy = starting_energy || energy @@ -163,8 +165,10 @@ return TRUE /obj/singularity/process(seconds_per_tick) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(neutralize_trader_outpost_hazard(src)) // VOIDCREW return PROCESS_KILL + // VOIDCREW EDIT END time_since_act += seconds_per_tick if(time_since_act < 2) return @@ -187,8 +191,10 @@ time_since_last_dissipiation -= dissipate_delay /obj/singularity/proc/expand(force_size) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(QDELETED(src)) // VOIDCREW: creation may have been suppressed. return FALSE + // VOIDCREW EDIT END var/temp_allowed_size = allowed_size if(force_size) @@ -319,8 +325,10 @@ return TRUE /obj/singularity/proc/consume(atom/thing) - if(QDELETED(src) || is_trader_outpost_protected(src) || is_trader_outpost_protected(thing) || singularity_spares(thing)) // VOIDCREW EDIT + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects + if(QDELETED(src) || is_trader_outpost_protected(src) || is_trader_outpost_protected(thing) || singularity_spares(thing)) // VOIDCREW return + // VOIDCREW EDIT END if(istype(thing, /obj/item/storage/backpack/holding) && !consumed_supermatter && !collapsing) consume_boh(thing) return @@ -442,8 +450,10 @@ /obj/singularity/proc/combust_mobs() for(var/mob/living/carbon/burned_mob in urange(20, src, 1)) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(is_trader_outpost_protected(burned_mob)) // VOIDCREW continue + // VOIDCREW EDIT END burned_mob.visible_message( span_warning("[burned_mob]'s skin bursts into flame!"), span_userdanger("You feel an inner fire as your skin bursts into flames!") @@ -454,8 +464,10 @@ /obj/singularity/proc/mezzer() for(var/mob/living/carbon/stunned_mob in oviewers(8, src)) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(is_trader_outpost_protected(stunned_mob)) // VOIDCREW continue + // VOIDCREW EDIT END if(stunned_mob.stat == DEAD || stunned_mob.is_blind()) continue @@ -508,8 +520,10 @@ /obj/singularity/deadchat_controlled/Initialize(mapload, starting_energy) . = ..() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(. == INITIALIZE_HINT_QDEL) // VOIDCREW return + // VOIDCREW EDIT END deadchat_plays(mode = DEMOCRACY_MODE) /// Special singularity spawned by being sucked into a black hole during emagged orion trail. @@ -518,14 +532,18 @@ /obj/singularity/orion/Initialize(mapload) . = ..() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(. == INITIALIZE_HINT_QDEL) // VOIDCREW return + // VOIDCREW EDIT END var/datum/component/singularity/singularity = singularity_component.resolve() singularity?.grav_pull = 1 /obj/singularity/orion/process(seconds_per_tick) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(neutralize_trader_outpost_hazard(src)) // VOIDCREW return PROCESS_KILL + // VOIDCREW EDIT END if(SPT_PROB(0.5, seconds_per_tick)) mezzer() diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 80eaa2ba523..8d47b21d3dc 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -71,11 +71,13 @@ update_appearance(UPDATE_OVERLAYS) // Connect to powernet if there's a cable under us + // VOIDCREW EDIT START - shuttle power integration: bind mapped SMES to the cable beneath it (voidcrew/edits/machinery/power.dm) if(!powernet) var/obj/structure/cable/C = locate() in loc if(!QDELETED(C)) cable_layer = C.cable_layer connect_to_network() + // VOIDCREW EDIT END /obj/machinery/power/smes/on_construction(mob/user) var/obj/structure/cable/C = locate() in loc diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index 430aa94c238..55dc9398b48 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -40,9 +40,11 @@ /obj/energy_ball/Initialize(mapload, starting_energy = 50, is_miniball = FALSE) . = ..() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(is_trader_outpost_protected(src)) // VOIDCREW log_game("OUTPOST PROTECTION: Prevented [name] from forming at [AREACOORD(src)].") return INITIALIZE_HINT_QDEL + // VOIDCREW EDIT END energy = starting_energy miniball = is_miniball @@ -66,8 +68,10 @@ return ..() /obj/energy_ball/process() + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(neutralize_trader_outpost_hazard(src)) // VOIDCREW return PROCESS_KILL + // VOIDCREW EDIT END if(orbiting) energy = 0 // ensure we dont have miniballs of miniballs else @@ -117,8 +121,10 @@ /obj/energy_ball/proc/can_move(turf/to_move) if (!to_move) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects return FALSE if(is_trader_outpost_protected(to_move)) // VOIDCREW + // VOIDCREW EDIT END return FALSE for (var/_thing in to_move) @@ -193,8 +199,10 @@ /obj/energy_ball/proc/dust_mobs(atom/A) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(is_trader_outpost_protected(src) || is_trader_outpost_protected(A)) // VOIDCREW return + // VOIDCREW EDIT END if(isliving(A)) var/mob/living/living = A if(living.incorporeal_move || HAS_TRAIT(living, TRAIT_GODMODE)) @@ -210,8 +218,10 @@ /proc/tesla_zap(atom/source, zap_range = 3, power, cutoff = 4e5, zap_flags = ZAP_DEFAULT_FLAGS, list/shocked_targets = list()) if(QDELETED(source)) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects return if(is_trader_outpost_protected(source)) // VOIDCREW + // VOIDCREW EDIT END return if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) LAZYSET(shocked_targets, source, TRUE) //I don't want no null refs in my list yeah? @@ -256,8 +266,10 @@ //Darkness fucks oview up hard. I've tried dview() but it doesn't seem to work //I hate existence for(var/atom/A as anything in typecache_filter_list(oview(zap_range+2, source), things_to_shock)) + // VOIDCREW EDIT START - trade outpost protection: stop suppressed or protected hazards before further effects if(is_trader_outpost_protected(A)) // VOIDCREW continue + // VOIDCREW EDIT END if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(shocked_targets, A)) continue // NOTE: these type checks are safe because CURRENTLY the range family of procs returns turfs in least to greatest distance order diff --git a/code/modules/power/turbine/turbine.dm b/code/modules/power/turbine/turbine.dm index cf034ab7e38..3b48e3533f4 100644 --- a/code/modules/power/turbine/turbine.dm +++ b/code/modules/power/turbine/turbine.dm @@ -19,6 +19,7 @@ ///The gas mixture this turbine part is storing var/datum/gas_mixture/machine_gasmix + /obj/machinery/power/turbine/Initialize(mapload, gas_theoretical_volume) . = ..() @@ -237,7 +238,7 @@ /obj/machinery/power/turbine/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) . = ..() if(shuttle_moving) // VOIDCREW EDIT ADDITION - a shuttle move carries the whole assembly together; see onShuttleMove below - return + return // VOIDCREW EDIT: shuttle turbine integration: preserve the assembly throughout movement (voidcrew/edits/modules/power/turbine/turbine.dm) set_panel_open(TRUE) update_appearance(UPDATE_OVERLAYS) deactivate_parts() diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 1a810f51c7a..5d65e684704 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -482,9 +482,11 @@ var/base_bonus_spread = 0 if(user) // MonkeStation's poor-aim penalty for firing while in soft crit. + // VOIDCREW EDIT START: mob adds the soft-critical aim penalty. if(user.stat == SOFT_CRIT) base_bonus_spread += 10 bonus_spread += 35 + // VOIDCREW EDIT END var/list/bonus_spread_values = list(base_bonus_spread, bonus_spread) SEND_SIGNAL(user, COMSIG_MOB_FIRED_GUN, src, target, params, zone_override, bonus_spread_values) base_bonus_spread = bonus_spread_values[MIN_BONUS_SPREAD_INDEX] diff --git a/code/modules/reagents/chemistry/equilibrium.dm b/code/modules/reagents/chemistry/equilibrium.dm index 14452c6010c..3c5be803f60 100644 --- a/code/modules/reagents/chemistry/equilibrium.dm +++ b/code/modules/reagents/chemistry/equilibrium.dm @@ -105,7 +105,7 @@ return FALSE //To prevent reactions outside of the pH window from starting. - //VOIDCREW EDIT: only recipes that opt in with REACTION_USES_PURITY are gated on pH. + //VOIDCREW EDIT START: only recipes that opt in with REACTION_USES_PURITY are gated on pH. - Voidcrew chemistry: apply pH gating only to recipes opting into purity (voidcrew/modules/chemistry) if((reaction.reaction_flags & REACTION_USES_PURITY) && (holder.ph < (reaction.optimal_ph_min - reaction.determin_ph_range) || holder.ph > (reaction.optimal_ph_max + reaction.determin_ph_range))) return FALSE //VOIDCREW EDIT END @@ -271,7 +271,7 @@ //Begin checks //Calculate DeltapH (Deviation of pH from optimal) - //VOIDCREW EDIT: pH only drives purity for recipes that opt in with REACTION_USES_PURITY. + //VOIDCREW EDIT START: pH only drives purity for recipes that opt in with REACTION_USES_PURITY. - Voidcrew chemistry: apply pH gating only to recipes opting into purity (voidcrew/modules/chemistry) //Everything else reacts at full purity whatever the mixture's pH happens to be, so a //recipe's optimal band doesn't have to contain neutral for the recipe to be usable. if(!(reaction.reaction_flags & REACTION_USES_PURITY)) @@ -350,13 +350,14 @@ //Calculate how much product to make and how much reactant to remove factors.. var/required_amount + // VOIDCREW EDIT REMOVAL - Voidcrew chemistry: reset pH adjustment within each reagent loop (voidcrew/modules/chemistry) for(var/datum/reagent/requirement as anything in reaction.required_reagents) required_amount = reaction.required_reagents[requirement] if(!holder.remove_reagent(requirement, delta_chem_factor * required_amount)) to_delete = TRUE return //Apply pH changes - var/pH_adjust + var/pH_adjust // VOIDCREW EDIT: Voidcrew chemistry: reset pH adjustment within each reagent loop (voidcrew/modules/chemistry) if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT) pH_adjust = ((delta_chem_factor * required_amount) / target_vol) * (reaction.H_ion_release * h_ion_mod) else //Default adds pH independant of volume @@ -373,7 +374,7 @@ return //Apply pH changes - var/pH_adjust + var/pH_adjust // VOIDCREW EDIT: Voidcrew chemistry: reset pH adjustment within each reagent loop (voidcrew/modules/chemistry) if(reaction.reaction_flags & REACTION_PH_VOL_CONSTANT) pH_adjust = (step_add / target_vol) * (reaction.H_ion_release * h_ion_mod) else diff --git a/code/modules/reagents/chemistry/holder/holder.dm b/code/modules/reagents/chemistry/holder/holder.dm index 2c33234e830..c74c15217ad 100644 --- a/code/modules/reagents/chemistry/holder/holder.dm +++ b/code/modules/reagents/chemistry/holder/holder.dm @@ -204,7 +204,7 @@ /datum/reagents/proc/add_reagent_list(list/list_reagents, list/data = null, added_purity = null, temperature = DEFAULT_REAGENT_TEMPERATURE) for(var/r_id in list_reagents) var/amt = list_reagents[r_id] - add_reagent(r_id, amt, data, reagtemp = temperature, added_purity = added_purity) + add_reagent(r_id, amt, data, reagtemp = temperature, added_purity = added_purity) // VOIDCREW EDIT: circuits chemistry integration: preserve supplied reagent temperature (voidcrew/modules/circuits) /** * Removes a specific reagent. can supress reactions if needed @@ -586,8 +586,9 @@ var/list/deleted_reagents = list() var/chem_index = 1 var/num_reagents = length(cached_reagents) - var/reagent_volume = 0 + var/reagent_volume = 0 // VOIDCREW EDIT: circuits chemistry integration: preserve supplied reagent temperature (voidcrew/modules/circuits) var/total_ph = 0 + // VOIDCREW EDIT REMOVAL - circuits chemistry integration: preserve supplied reagent temperature (voidcrew/modules/circuits) . = 0 //responsible for removing reagents and computing total ph & volume diff --git a/code/modules/reagents/chemistry/holder/reactions.dm b/code/modules/reagents/chemistry/holder/reactions.dm index ee0f9906fa4..739f71f8a84 100644 --- a/code/modules/reagents/chemistry/holder/reactions.dm +++ b/code/modules/reagents/chemistry/holder/reactions.dm @@ -72,7 +72,7 @@ if(isliving(cached_my_atom) && !reaction.mob_react) //Makes it so certain chemical reactions don't occur in mobs continue - //VOIDCREW EDIT ADDITION: keeps mob-spawning mixtures out of plant chemistry + //VOIDCREW EDIT ADDITION START: keeps mob-spawning mixtures out of plant chemistry - Voidcrew chemistry: apply pH gating only to recipes opting into purity (voidcrew/modules/chemistry) if((reaction.reaction_flags & REACTION_NOT_IN_PLANTS) && istype(cached_my_atom, /obj/item/food/grown)) continue //VOIDCREW EDIT END @@ -91,7 +91,7 @@ LAZYADD(failed_but_capable_reactions, reaction) continue - //VOIDCREW EDIT: only recipes that opt in with REACTION_USES_PURITY are gated on pH. + //VOIDCREW EDIT START: only recipes that opt in with REACTION_USES_PURITY are gated on pH. - Voidcrew chemistry: apply pH gating only to recipes opting into purity (voidcrew/modules/chemistry) if((reaction.reaction_flags & REACTION_USES_PURITY) && (ph < reaction.optimal_ph_min - reaction.determin_ph_range && ph > reaction.optimal_ph_max + reaction.determin_ph_range)) LAZYADD(failed_but_capable_reactions, reaction) continue @@ -150,7 +150,7 @@ else if(reaction.required_temp < chem_temp) return TRUE - //VOIDCREW EDIT: a reaction that doesn't opt into pH mechanics is never held back by pH, + //VOIDCREW EDIT START: a reaction that doesn't opt into pH mechanics is never held back by pH, - Voidcrew chemistry: apply pH gating only to recipes opting into purity (voidcrew/modules/chemistry) //so it's always eligible to restart once its other conditions are met. if(reaction.reaction_flags & REACTION_USES_PURITY) if(((ph >= (reaction.optimal_ph_min - reaction.determin_ph_range)) && (ph <= (reaction.optimal_ph_max + reaction.determin_ph_range)))) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 04da45a7af0..32da0432859 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -255,7 +255,7 @@ if(reagent.purity < equilibrium.reaction.purity_min) purity_alert = ENABLE_FLASHING//Because 0 is seen as null danger = TRUE - //VOIDCREW EDIT: only alarm on pH for recipes that actually care about it. Without + //VOIDCREW EDIT START: only alarm on pH for recipes that actually care about it. Without - Voidcrew chemistry: apply pH gating only to recipes opting into purity (voidcrew/modules/chemistry) //REACTION_USES_PURITY the mixture's pH has no effect on the reaction, so flashing the //meter at the chemist would be warning them about nothing. if(flashing != ENABLE_FLASHING && (equilibrium.reaction.reaction_flags & REACTION_USES_PURITY))//So that the pH meter flashes for ANY reactions out of optimal diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 2cfd64ad481..acc837451a2 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -413,9 +413,11 @@ var/turf/open/exposed_open_turf = exposed_turf exposed_open_turf.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure. var/datum/gas_mixture/turf_air = exposed_open_turf.return_air() // VOIDCREW EDIT: written to below; leaves the shared planetary mix + // VOIDCREW EDIT START - planetary shared air: materialize a private mixture before writes (voidcrew/edits/planetary_shared_air.dm) var/temperature = turf_air.temperature var/heat_capacity = turf_air.heat_capacity() turf_air.temperature = max(turf_air.temperature - ((temperature - TCMB) * (heat_capacity * reac_volume * specific_heat) / (heat_capacity + reac_volume * specific_heat)) / heat_capacity, TCMB) // Exchanges environment temperature with reagent. Reagent is at 2.7K with a heat capacity of 40J per unit. + // VOIDCREW EDIT END if(reac_volume < 5) return for(var/mob/living/basic/slime/exposed_slime in exposed_turf) diff --git a/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm b/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm index 44abc20c561..a8374d87c53 100644 --- a/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/reaction_agents_reagents.dm @@ -19,7 +19,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/reagent/reaction_agent/acidic_buffer name = "Strong Acidic Buffer" - description = "An industrial acidic buffer, used to lower the pH of a solution." + description = "An industrial acidic buffer, used to lower the pH of a solution." // VOIDCREW EDIT: Voidcrew chemistry: describe industrial buffers without self-consumption instructions (voidcrew/modules/chemistry) color = "#fbc314" ph = 0 inverse_chem = null @@ -53,7 +53,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/reagent/reaction_agent/basic_buffer name = "Strong Basic Buffer" - description = "An industrial alkaline buffer, used to raise the pH of a solution." + description = "An industrial alkaline buffer, used to raise the pH of a solution." // VOIDCREW EDIT: Voidcrew chemistry: describe industrial buffers without self-consumption instructions (voidcrew/modules/chemistry) color = "#3853a4" ph = 14 inverse_chem = null diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 57297f6dd8c..f88183f2ed1 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -270,7 +270,7 @@ /obj/item/reagent_containers/proc/on_reagent_change(datum/reagents/holder, ...) SIGNAL_HANDLER update_appearance() - //VOIDCREW EDIT ADDITION: lets reagents react to their own container changing (Australium) + //VOIDCREW EDIT ADDITION START: lets reagents react to their own container changing (Australium) - Voidcrew reagents: reprocess container-sensitive reagents after a container change (voidcrew/modules/chemistry) reagent_processing() //VOIDCREW EDIT END diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index c731d076617..3c2b7bb7d34 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -65,7 +65,7 @@ trans = round(reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user), CHEMICAL_VOLUME_ROUNDING) to_chat(user, span_notice("You transfer [trans] unit\s of the solution.")) - if(trans) + if(trans) // VOIDCREW EDIT: Voidcrew reagent audio: run after-pour feedback only after a successful transfer (voidcrew/modules/chemistry) after_pour(trans, target, user) //VOIDCREW EDIT ADDITION: dropper sounds update_appearance() target.update_appearance() diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 65f2e07ba68..f521868b9a9 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -143,7 +143,7 @@ // VOIDCREW EDIT START - PR #284: Port MonkeStation soft-crit item use. /obj/item/reagent_containers/hypospray/medipen/attack_self(mob/user) - if(user.can_perform_action(src, FORBID_TELEKINESIS_REACH|ALLOW_RESTING|ALLOW_SOFT_CRIT)) + if(user.can_perform_action(src, FORBID_TELEKINESIS_REACH|ALLOW_RESTING|ALLOW_SOFT_CRIT)) // VOIDCREW EDIT: soft crit interaction: permit selected actions while retaining other incapacitation checks (voidcrew/edits/modules/mob/mob.dm) inject(user, user) // VOIDCREW EDIT END diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index b8c37864e6d..91403c6e2f7 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -124,12 +124,13 @@ other types of metals and chemistry for reagents). ///The bepis node we have the design id's of var/datum/techweb_node/bepis_node -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/disk/design_disk/bepis/Initialize(mapload) . = ..() + // VOIDCREW EDIT START: research cycles the finite experimental technology deck. refill_experimental_technology_deck() if(!length(SSresearch.techweb_nodes_experimental)) return INITIALIZE_HINT_QDEL + // VOIDCREW EDIT END var/bepis_id = pick(SSresearch.techweb_nodes_experimental) bepis_node = (SSresearch.techweb_node_by_id(bepis_id)) @@ -138,7 +139,6 @@ other types of metals and chemistry for reagents). blueprints += new_entry ///Unhide and research our node so we show up in the R&D console. -// VOIDCREW EDIT END /obj/item/disk/design_disk/bepis/on_upload(datum/techweb/stored_research, atom/research_source) stored_research.hidden_nodes -= bepis_node.id stored_research.research_node(bepis_node, force = TRUE, auto_adjust_cost = FALSE, research_source = research_source) @@ -152,14 +152,18 @@ other types of metals and chemistry for reagents). name = "Reformatted technology disk" desc = "A disk containing a new, completed tech from the B.E.P.I.S. Upload the disk to an R&D Console to redeem the tech." -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/disk/design_disk/bepis/remove_tech/Initialize(mapload) . = ..() + // VOIDCREW EDIT START: research cycles the finite experimental technology deck. if(. == INITIALIZE_HINT_QDEL) return + // VOIDCREW EDIT END SSresearch.techweb_nodes_experimental -= bepis_node.id + // VOIDCREW EDIT START: research cycles the finite experimental technology deck. log_research("[bepis_node.display_name] drawn from the experimental technology deck.") // Bitrunning checks this pool BEFORE making a disk. Refill at exhaustion, // rather than waiting for an Initialize() that the caller would never reach. refill_experimental_technology_deck() -// VOIDCREW EDIT END + // VOIDCREW EDIT END + +// VOIDCREW EDIT: research refills the experimental technology deck at exhaustion; implementation in voidcrew/edits/modules/research/designs.dm. diff --git a/code/modules/research/designs/autolathe/security_designs.dm b/code/modules/research/designs/autolathe/security_designs.dm index ef1e59fb0ea..9d86811839e 100644 --- a/code/modules/research/designs/autolathe/security_designs.dm +++ b/code/modules/research/designs/autolathe/security_designs.dm @@ -203,7 +203,7 @@ name = "Ammo Box (10mm) (Lethal)" id = "c10mm" build_type = AUTOLATHE - materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6) + materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6) // VOIDCREW EDIT: weapons_bench charges ammunition materials consistent with recycling. build_path = /obj/item/ammo_box/c10mm category = list( RND_CATEGORY_HACKED, @@ -217,7 +217,7 @@ name = "Ammo Box (.45) (Lethal)" id = "c45" build_type = AUTOLATHE - materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6) + materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6) // VOIDCREW EDIT: weapons_bench charges ammunition materials consistent with recycling. build_path = /obj/item/ammo_box/c45 category = list( RND_CATEGORY_HACKED, @@ -231,7 +231,7 @@ name = "Ammo Box (9mm) (Lethal)" id = "c9mm" build_type = AUTOLATHE - materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6) + materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 6) // VOIDCREW EDIT: weapons_bench charges ammunition materials consistent with recycling. build_path = /obj/item/ammo_box/c9mm category = list( RND_CATEGORY_HACKED, diff --git a/code/modules/research/designs/comp_board_designs.dm b/code/modules/research/designs/comp_board_designs.dm index 078e3aabcc0..d5df75ba52c 100644 --- a/code/modules/research/designs/comp_board_designs.dm +++ b/code/modules/research/designs/comp_board_designs.dm @@ -421,3 +421,5 @@ RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO ) departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING + +// VOIDCREW EDIT: research exposes ship-buildable bitrunning boards; implementation in voidcrew/edits/modules/research/designs/comp_board_designs.dm. diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index 086b4ca947b..18fc0cec7c8 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -1396,6 +1396,8 @@ ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING +// VOIDCREW EDIT: research exposes ship-buildable bitrunning boards; implementation in voidcrew/edits/modules/research/designs/machine_designs.dm. + /datum/design/board/netpod name = "Netpod Board" desc = "The circuit board for a netpod." diff --git a/code/modules/research/destructive_analyzer.dm b/code/modules/research/destructive_analyzer.dm index 0cd10f50383..babb93affc4 100644 --- a/code/modules/research/destructive_analyzer.dm +++ b/code/modules/research/destructive_analyzer.dm @@ -199,7 +199,7 @@ */ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/rnd/destructive_analyzer/proc/user_try_decon_id(id) - if(QDELETED(loaded_item) || QDELETED(stored_research) || busy || !is_operational || panel_open || disabled) + if(QDELETED(loaded_item) || QDELETED(stored_research) || busy || !is_operational || panel_open || disabled) // VOIDCREW EDIT: research validates item-authorized discoveries and analyzer state. return FALSE if(isnull(id)) return FALSE @@ -212,10 +212,12 @@ // The UI's buttons are suggestions, not authority: a forged id must never // let an ordinary item reveal an unrelated field or consume the item. + // VOIDCREW EDIT START: research validates item-authorized discoveries and analyzer state. var/list/unlockable_nodes = techweb_item_unlock_check(loaded_item) if(!(id in unlockable_nodes) || !stored_research.hidden_nodes[id]) return FALSE var/datum/techweb_node/node_to_discover = SSresearch.techweb_nodes[id] + // VOIDCREW EDIT END if(!istype(node_to_discover)) return FALSE if(!destroy_item()) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index 79190d5dd25..bd4285fc5c1 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -224,7 +224,7 @@ // Stack outputs retain their per-unit materials instead of receiving the // nonstack salvage adjustment in do_make_item(). Discounting them creates // material when cable, ducts or rods are fed back into a material container. - if(ispath(path, /obj/item/stack)) + if(ispath(path, /obj/item/stack)) // VOIDCREW EDIT: research preserves stack material costs to prevent recycling gain. return 1 else return efficiency_coeff diff --git a/code/modules/research/part_replacer.dm b/code/modules/research/part_replacer.dm index dd26ebc6923..a118acf9775 100644 --- a/code/modules/research/part_replacer.dm +++ b/code/modules/research/part_replacer.dm @@ -55,6 +55,7 @@ // VOIDCREW EDIT: inherit the compact storage sprite; the obsolete storage_wide.dmi override was removed. name = "bluespace rapid part exchange device" desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts." + // VOIDCREW EDIT REMOVAL: research uses the inherited part-replacer icon. icon_state = "BS_RPED" inhand_icon_state = "BS_RPED" w_class = WEIGHT_CLASS_NORMAL diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index 3ee96180b6e..89384723787 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -68,8 +68,10 @@ /datum/techweb_node/Destroy() // Temporary instances (for example design-source validation) may share an // id with the canonical node. They do not own that registry entry. + // VOIDCREW EDIT START: research only unregisters the canonical techweb node. if(SSresearch.techweb_nodes[id] == src) SSresearch.techweb_nodes -= id + // VOIDCREW EDIT END return ..() // VOIDCREW EDIT END diff --git a/code/modules/research/techweb/nodes/medbay_nodes.dm b/code/modules/research/techweb/nodes/medbay_nodes.dm index 920d660e942..6e5fc00dee4 100644 --- a/code/modules/research/techweb/nodes/medbay_nodes.dm +++ b/code/modules/research/techweb/nodes/medbay_nodes.dm @@ -70,7 +70,7 @@ /datum/techweb_node/medbay_equip_adv id = TECHWEB_NODE_MEDBAY_EQUIP_ADV display_name = "Advanced Medbay Equipment" - description = "State-of-the-art medical gear for keeping the crew in one piece, mostly." + description = "State-of-the-art medical gear for keeping the crew in one piece, mostly." // VOIDCREW EDIT: research keeps node descriptions compatible with the client font. prereq_ids = list(TECHWEB_NODE_CHEM_SYNTHESIS) design_ids = list( "smoke_machine", diff --git a/code/modules/research/techweb/nodes/mining_nodes.dm b/code/modules/research/techweb/nodes/mining_nodes.dm index b189ee812ef..3d39445e913 100644 --- a/code/modules/research/techweb/nodes/mining_nodes.dm +++ b/code/modules/research/techweb/nodes/mining_nodes.dm @@ -90,7 +90,7 @@ "byteforge", "quantum_console", "netpod", - "quantum_server", + "quantum_server", // VOIDCREW EDIT: research unlocks ship-buildable bitrunning machinery. "bitrunning_order_console", // VOIDCREW EDIT: spends the points the loop pays out; upstream hand-places it ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) diff --git a/code/modules/research/techweb/nodes/service_nodes.dm b/code/modules/research/techweb/nodes/service_nodes.dm index 2059956ab22..d438e170260 100644 --- a/code/modules/research/techweb/nodes/service_nodes.dm +++ b/code/modules/research/techweb/nodes/service_nodes.dm @@ -3,7 +3,7 @@ id = TECHWEB_NODE_OFFICE_EQUIP starting_node = TRUE display_name = "Office Equipment" - description = "Nanotrasen's finest in ergonomic office tech, ensuring station admin stays productive and compliant with corporate policies, because even in space, paperwork never stops." + description = "Nanotrasen's finest in ergonomic office tech, ensuring station admin stays productive and compliant with corporate policies, because even in space, paperwork never stops." // VOIDCREW EDIT: research keeps node descriptions compatible with the client font. design_ids = list( "fax", "sec_pen", diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index f4a12f4735a..65dc14fe534 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -167,11 +167,13 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/keycard_auth/wall_mounted, 26) find_and_hang_on_wall() GLOBAL_VAR_INIT(emergency_access, FALSE) +// VOIDCREW EDIT START: comms scopes emergency maintenance access to the source ship. /proc/make_maint_all_access(atom/source) var/obj/docking_port/mobile/ship = voidcrew_communications_ship(source) if(ship) ship.set_communications_emergency_access(TRUE) return +// VOIDCREW EDIT END for(var/area/station/maintenance/area in GLOB.areas) for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) for(var/turf/area_turf as anything in zlevel_turfs) @@ -183,11 +185,13 @@ GLOBAL_VAR_INIT(emergency_access, FALSE) GLOB.emergency_access = TRUE SSblackbox.record_feedback("nested tally", "keycard_auths", 1, list("emergency maintenance access", "enabled")) +// VOIDCREW EDIT START: comms scopes emergency maintenance access to the source ship. /proc/revoke_maint_all_access(atom/source) var/obj/docking_port/mobile/ship = voidcrew_communications_ship(source) if(ship) ship.set_communications_emergency_access(FALSE) return +// VOIDCREW EDIT END for(var/area/station/maintenance/area in GLOB.areas) for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) for(var/turf/area_turf as anything in zlevel_turfs) diff --git a/code/modules/shuttle/mobile_port/mobile_port.dm b/code/modules/shuttle/mobile_port/mobile_port.dm index e1b2bf69e34..531cd119805 100644 --- a/code/modules/shuttle/mobile_port/mobile_port.dm +++ b/code/modules/shuttle/mobile_port/mobile_port.dm @@ -95,7 +95,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/docking_port/mobile/Destroy(force) unregister() - QDEL_NULL(announcement_controller) + QDEL_NULL(announcement_controller) // VOIDCREW EDIT: shuttle measures only its own hull ground and cleans departure resources. destination = null previous = null if(!QDELETED(assigned_transit)) @@ -149,6 +149,7 @@ // hull out onto - is kept, so this can never shrink a rectangle around real hull. // A hull with no region of its own still discards turfs sitting inside somebody // else's, which is the stranded-at-a-ruin case seen from deep space. + // VOIDCREW EDIT START: shuttle measures only its own hull ground and cleans departure resources. var/turf/own_ground = get_turf(src) var/datum/own_region = own_ground ? map_region_for_turf(own_ground) : null var/region_filtered = !isnull(own_ground) @@ -168,11 +169,13 @@ var/datum/turf_region = map_region_for_turf(turf) if(turf_region && turf_region != own_region) continue + // VOIDCREW EDIT END min_x = min(turf.x, min_x) max_x = max(turf.x, max_x) min_y = min(turf.y, min_y) max_y = max(turf.y, max_y) CHECK_TICK + // VOIDCREW EDIT START: shuttle measures only its own hull ground and cleans departure resources. if(max_x != -1 || !region_filtered) break // Containment threw away every turf we have. That means our own tile is not @@ -184,6 +187,7 @@ min_y = WORLDMAXY_CUTOFF max_x = -1 max_y = -1 + // VOIDCREW EDIT END if(min_x == WORLDMAXX_CUTOFF || max_x == -1) CRASH("Failed to locate shuttle boundaries when iterating through shuttle areas, somehow.") @@ -445,7 +449,7 @@ // deleted hull's rect on open space otherwise stays initialized and starlit for // the rest of the round. See /turf/proc/return_to_uninitialized_space(). if(isspaceturf(oldT) && !istype(oldT, /turf/open/space/basic) && isnull(map_region_for_turf(oldT))) - oldT.return_to_uninitialized_space() + oldT.return_to_uninitialized_space() // VOIDCREW EDIT: shuttle measures only its own hull ground and cleans departure resources. qdel(src, force=TRUE) @@ -759,7 +763,7 @@ if(!distant_source) return - // VOIDCREW EDIT ADDITION: packed-level containment. long_range is range * 2.5 where + // VOIDCREW EDIT ADDITION START: shuttle - packed-level containment. long_range is range * 2.5 where // range is engine_coeff * max(width, height), so a ~40-wide hull reaches ~100 tiles // against the 6 that separate two tenants of a packed level - a co-tenant crew hears a // full hyperspace departure from a ship they cannot see. Resolved once, outside the @@ -767,7 +771,7 @@ var/datum/source_region = map_region_for_turf(get_turf(distant_source)) // VOIDCREW EDIT END for(var/mob/zlevel_mobs as anything in SSmobs.clients_by_zlevel[z]) - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START: shuttle scopes this effect to its encounter site. if(map_region_excludes_turf(source_region, get_turf(zlevel_mobs))) continue // VOIDCREW EDIT END diff --git a/code/modules/shuttle/mobile_port/shuttle_move.dm b/code/modules/shuttle/mobile_port/shuttle_move.dm index 7f1c7414b74..934771e5841 100644 --- a/code/modules/shuttle/mobile_port/shuttle_move.dm +++ b/code/modules/shuttle/mobile_port/shuttle_move.dm @@ -1,6 +1,5 @@ /// This is the main proc. Despite what the name suggests, /// it instantly moves our mobile port to stationary port `new_dock`. -// VOIDCREW EDIT START - PR #378: Keep plumbing connected when a ship docks or rotates. /obj/docking_port/mobile/proc/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE) // Crashing this ship with NO SURVIVORS @@ -8,8 +7,10 @@ // ship in open flight - and a null dock used to runtime on the line below, killing // the whole SSshuttle fire mid-loop (round 811: Scarab/Kilo/Delta and the // shuttle-purchase flow all hit it). Hand check() the error code it already handles. + // VOIDCREW EDIT START: shuttle validates docking and maintains hull networks through the move. if(isnull(new_dock)) return DOCKING_NULL_DESTINATION + // VOIDCREW EDIT END // VOIDCREW EDIT ADDITION START: also enforce bay ownership on forced template loads. if(!new_dock.allows_ship_bay_docking(src)) @@ -66,11 +67,11 @@ var/list/areas_to_move = list() //unique assoc list of areas on turfs being moved var/list/underlying_areas = list() //unique assoc list of areas beneath turfs being moved - move_powernet_verdicts = list() // Voidcrew: see powernet_leaves_hull() + move_powernet_verdicts = list() // Voidcrew: see powernet_leaves_hull() // VOIDCREW EDIT: shuttle validates docking and maintains hull networks through the move. . = preflight_check(old_turfs, new_turfs, areas_to_move, underlying_areas, rotation) - move_powernet_verdicts = null + move_powernet_verdicts = null // VOIDCREW EDIT: shuttle validates docking and maintains hull networks through the move. if(.) - repair_networks_after_aborted_move(old_turfs) + repair_networks_after_aborted_move(old_turfs) // VOIDCREW EDIT: shuttle validates docking and maintains hull networks through the move. remove_ripples() return @@ -89,11 +90,11 @@ if(!force) if(!check_dock(new_dock)) - repair_networks_after_aborted_move(old_turfs) + repair_networks_after_aborted_move(old_turfs) // VOIDCREW EDIT: shuttle validates docking and maintains hull networks through the move. remove_ripples() return DOCKING_BLOCKED if(!canMove()) - repair_networks_after_aborted_move(old_turfs) + repair_networks_after_aborted_move(old_turfs) // VOIDCREW EDIT: shuttle validates docking and maintains hull networks through the move. remove_ripples() return DOCKING_IMMOBILIZED @@ -128,9 +129,8 @@ remove_ripples() return DOCKING_SUCCESS -/// Voidcrew: powernet -> TRUE/FALSE verdicts from powernet_leaves_hull(), valid for one -/// preflight_check() pass only. Null outside a move. -// VOIDCREW EDIT END +// VOIDCREW EDIT: shuttle preserves whole hull powernets and repairs aborted moves; implementation in voidcrew/edits/modules/shuttle/mobile_port/shuttle_move.dm. + /obj/docking_port/mobile/proc/preflight_check(list/old_turfs, list/new_turfs, list/areas_to_move, list/underlying_areas, rotation) for(var/i in 1 to length(old_turfs)) CHECK_TICK @@ -165,12 +165,14 @@ // tile carrying one of our engines: round 811's Pill lost its thruster off // a space turf in an orphaned same-name area, which the registered-area // filter and the space-turf filter both silently waved through. + // VOIDCREW EDIT START: shuttle validates docking and maintains hull networks through the move. if(!(move_mode & MOVE_TURF)) var/obj/machinery/power/shuttle_engine/mounted = locate() in oldT if(mounted && !(mounted in engine_list)) mounted = null if(mounted || (!isspaceturf(oldT) && shuttle_areas[old_area])) log_shuttle("[name]: preflight will leave hull turf [oldT] ([oldT.type]) at [AREACOORD(oldT)] behind[mounted ? " WITH ENGINE [mounted]" : ""] - move_mode=[move_mode], area=[old_area.type] [REF(old_area)] (registered=[shuttle_areas[old_area] ? "yes" : "NO"]), baseturfs=[islist(oldT.baseturfs) ? jointext(oldT.baseturfs, " > ") : "[oldT.baseturfs]"]") + // VOIDCREW EDIT END old_turfs[oldT] = move_mode @@ -195,162 +197,7 @@ moving_atom.onShuttleMove(newT, oldT, movement_force, movement_direction, old_dock, src) //atoms moved_atoms[moving_atom] = oldT -/// How far past the hull's edge evict_landing_stowaways() will look for somewhere to put a stowaway. -#define STOWAWAY_EXIT_DEPTH 5 - -/** - * VOIDCREW ADDITION. Evict anything that was standing on the landing site and survived - * into the hull's interior. - * - * /turf/toShuttleMove() is supposed to clear the destination before the deck is laid over - * it - living things are gibbed, anchored objects deleted, loose objects shoved aside - - * but "shoved aside" is a single step(thing, shuttle.dir), and that has never been enough - * for this fork: - * - * - One tile does not clear a footprint. Ships land in a 56x40 planet berth - * (RESERVE_DOCK_MAX_SIZE_*) with the hull centred in it, so a tank in the middle of the - * deck is still under the deck after its step. - * - The step direction is the port's OLD facing (setDir() to the berth's dir happens at - * the very end of initiate_docking()), while preflight_check() walks the destination in - * return_ordered_turfs() order - x ascending, y ascending within each column. Whenever - * those disagree (ship facing SOUTH or WEST relative to that scan) everything loose is - * pushed into tiles the crush has already finished with, and stays there. - * - step() also simply fails when the next tile is blocked, which on a planet surface it - * frequently is. - * - preflight_check() is full of CHECK_TICKs, so the crush is spread over several ticks - * and planet fauna walks onto cleared tiles in the gap. Anything riding inside a shoved - * object (a mob in a closet) is never looked at in the first place. - * - * Upstream gets away with all of that because a station shuttle's destination is empty - * space. Ours is a planet surface covered in loot and wildlife, so the leftovers end up on - * the deck: the reported fuel tanks, shards and RTGs, and the mobs that came with them. - * - * moved_atoms is the exact set of movables this move carried, so anything else standing on - * a turf we just laid down was already there. Crew, cargo, and anything the crew left - * lying on their own floor are all in moved_atoms and are never touched by this. - */ -/obj/docking_port/mobile/proc/evict_landing_stowaways(list/old_turfs, list/new_turfs, list/moved_atoms) - var/min_x = INFINITY - var/min_y = INFINITY - var/max_x = 0 - var/max_y = 0 - var/footprint_z = 0 - var/list/stowaways = list() - for(var/i in 1 to length(old_turfs)) - var/turf/landed = new_turfs[i] - if(!landed) - continue - // The rectangle is taken from the WHOLE footprint, not just the tiles that moved, - // so a stowaway is pushed clear of the ship rather than into the ground squares a - // non-rectangular hull leaves inside its own bounding box. - min_x = min(min_x, landed.x) - max_x = max(max_x, landed.x) - min_y = min(min_y, landed.y) - max_y = max(max_y, landed.y) - footprint_z = landed.z - var/turf/old_turf = old_turfs[i] - if(!old_turf) - continue - // Both flags, not either: MOVE_CONTENTS is what put this tile's legitimate - // occupants into moved_atoms, and without it the exemption below cannot be - // trusted. MOVE_AREA alone is a breached tile - the site's own ground adopted into - // one of our areas - and what is lying on that is still the site's business. - var/move_mode = old_turfs[old_turf] - if((move_mode & (MOVE_TURF|MOVE_CONTENTS)) != (MOVE_TURF|MOVE_CONTENTS)) - continue - for(var/atom/movable/stowaway as anything in landed.contents) - if(moved_atoms[stowaway]) // came with the ship - continue - if(stowaway.loc != landed) // multi-tile objects - continue - if(stowaway.resistance_flags & SHUTTLE_CRUSH_PROOF) - continue - // The berth's own stationary port sits inside the rectangle by definition, and - // non-living mobs are left alone by every other crush branch in this module. - if(istype(stowaway, /obj/docking_port)) - continue - if(ismob(stowaway) && !isliving(stowaway)) - continue - stowaways += stowaway - - if(!length(stowaways)) - return - - var/evicted = 0 - var/destroyed = 0 - for(var/atom/movable/stowaway as anything in stowaways) - if(QDELETED(stowaway)) - continue - var/turf/exit_turf = find_stowaway_exit(stowaway, min_x, min_y, max_x, max_y, footprint_z) - stowaway.pulledby?.stop_pulling() - stowaway.stop_pulling() - if(isliving(stowaway)) - var/mob/living/living_stowaway = stowaway - living_stowaway.buckled?.unbuckle_mob(living_stowaway, force = TRUE) - if(!exit_turf) - // Nowhere on the map to put it, and the hull is already on top of it, so - // this is the crush arriving late rather than a new outcome. - log_shuttle("[name]: [key_name(living_stowaway)] survived the landing crush at [AREACOORD(living_stowaway)] with nowhere outside the footprint to go - gibbed.") - living_stowaway.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS) - living_stowaway.gib(DROP_ALL_REMAINS) - destroyed++ - continue - log_shuttle("[name]: [key_name(living_stowaway)] survived the landing crush at [AREACOORD(living_stowaway)] - moved clear to [AREACOORD(exit_turf)].") - living_stowaway.forceMove(exit_turf) - evicted++ - continue - if(!exit_turf) - qdel(stowaway) // what the crush already does to anything it cannot shove - destroyed++ - continue - stowaway.forceMove(exit_turf) - evicted++ - - log_shuttle("[name]: landing footprint ([min_x],[min_y],[footprint_z])-([max_x],[max_y],[footprint_z]) held [length(stowaways)] site movable(s) the crush missed - [evicted] moved clear, [destroyed] destroyed.") - -/** - * Nearest turf outside the rectangle the hull just occupied, for a stowaway standing in it. - * - * Walks straight out along whichever of the four axes is closest and takes the first tile - * past the edge that will actually hold the thing, going up to STOWAWAY_EXIT_DEPTH further - * out if the tiles at the edge are walls or rubble. Falls back to the first tile outside - * the rectangle it found at all, blocked or not - overlapping something on the surface is - * a far smaller problem than riding around inside somebody's hull - and the caller only - * destroys the thing when even that does not exist. - */ -/obj/docking_port/mobile/proc/find_stowaway_exit(atom/movable/stowaway, min_x, min_y, max_x, max_y, footprint_z) - var/stow_x = stowaway.x - var/stow_y = stowaway.y - if(!stow_x || !stow_y) - return null - // start_x, start_y, step_x, step_y, tiles from the stowaway to that starting tile - var/list/exit_lanes = list( - list(min_x - 1, stow_y, -1, 0, stow_x - (min_x - 1)), - list(max_x + 1, stow_y, 1, 0, (max_x + 1) - stow_x), - list(stow_x, min_y - 1, 0, -1, stow_y - (min_y - 1)), - list(stow_x, max_y + 1, 0, 1, (max_y + 1) - stow_y), - ) - var/turf/fallback - var/best_cost = INFINITY - var/turf/best - for(var/list/lane as anything in exit_lanes) - var/lane_cost = lane[5] - for(var/depth in 0 to STOWAWAY_EXIT_DEPTH - 1) - if((lane_cost + depth) >= best_cost) - break - var/turf/candidate = locate(lane[1] + (lane[3] * depth), lane[2] + (lane[4] * depth), footprint_z) - if(!candidate) - break // ran off the edge of the map on this axis - if(!fallback) - fallback = candidate - if(candidate.is_blocked_turf(exclude_mobs = TRUE, source_atom = stowaway)) - continue - best_cost = lane_cost + depth - best = candidate - break - return best || fallback - -#undef STOWAWAY_EXIT_DEPTH +// VOIDCREW EDIT: shuttle clears landing-site occupants after placing the hull; implementation in voidcrew/modules/shuttle/shuttle_move_helpers.dm. /obj/docking_port/mobile/proc/cleanup_runway(obj/docking_port/stationary/new_dock, list/old_turfs, list/new_turfs, list/areas_to_move, list/underlying_areas, list/moved_atoms, rotation, movement_direction, area/fallback_area) fallback_area.afterShuttleMove(0) diff --git a/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm b/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm index 49769f3a81e..5658f5b2c89 100644 --- a/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm +++ b/code/modules/shuttle/mobile_port/shuttle_move_callbacks.dm @@ -30,8 +30,10 @@ All ShuttleMove procs go here // standing behind the one we just shoved: it is skipped here, the hull is copied on // top of it in takeoff(), and it ends up sitting on the deck. Iterate a snapshot. for(var/atom/movable/thing as anything in contents.Copy()) + // VOIDCREW EDIT START: shuttle snapshots landing occupants before deleting or moving them. if(QDELETED(thing) || thing.loc != src) continue + // VOIDCREW EDIT END if(thing.resistance_flags & SHUTTLE_CRUSH_PROOF) continue if(isliving(thing)) @@ -90,7 +92,7 @@ All ShuttleMove procs go here // guard: a berth inside a site footprint or a transit/turf reservation is that // owner's ground and gets swept by ITS teardown; see return_to_uninitialized_space(). if(isspaceturf(oldT) && !istype(oldT, /turf/open/space/basic) && isnull(map_region_for_turf(oldT))) - oldT.return_to_uninitialized_space() + oldT.return_to_uninitialized_space() // VOIDCREW EDIT: shuttle returns unclaimed departure space to an uninitialized turf. if(rotation) shuttleRotate(rotation) //see shuttle_rotate.dm @@ -145,7 +147,7 @@ All ShuttleMove procs go here return TRUE /atom/movable/proc/lateShuttleMove(turf/oldT, list/movement_force, move_dir) - // VOIDCREW ADDITION: sent before the anchored early-return so bolted machinery hears it. + // VOIDCREW EDIT ADDITION: sent before the anchored early-return so bolted machinery hears it. SEND_SIGNAL(src, COMSIG_ATOM_LATE_SHUTTLE_MOVE, oldT, movement_force, move_dir) if(!movement_force || anchored) return @@ -389,6 +391,7 @@ All ShuttleMove procs go here // needs MOVE_CONTENTS. Any foreign cable that ends up inside the move rectangle (a // co-tenant's grid on a packed z-level, ground the hull is merely parked on) is // therefore killed silently and permanently by a ship taking off next to it. + // VOIDCREW EDIT START: shuttle preserves hull powernets and clears the landing footprint safely. if(!(. & MOVE_AREA)) return // Voidcrew: a powernet is only a set of cables and machines - nothing in it is @@ -405,10 +408,16 @@ All ShuttleMove procs go here // pinning half-built powernets onto cables that afterShuttleMove() then trusts. cut_cable_from_powernet(FALSE, FALSE) + // VOIDCREW EDIT END + +// VOIDCREW EDIT: shuttle rotates cable direction bits with the hull; implementation in voidcrew/edits/modules/shuttle/mobile_port/shuttle_move_callbacks.dm. + /obj/structure/cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation) . = ..() Connect_cable(TRUE) +// VOIDCREW EDIT: shuttle rebuilds power after every cable has landed; implementation in voidcrew/edits/modules/shuttle/mobile_port/shuttle_move_callbacks.dm. + /obj/machinery/power/shuttle_engine/hypotheticalShuttleMove(move_mode) . = ..() if(. & MOVE_AREA) diff --git a/code/modules/shuttle/mobile_port/variants/custom/custom_consoles.dm b/code/modules/shuttle/mobile_port/variants/custom/custom_consoles.dm index 5302ef32b97..12bfe4e94d0 100644 --- a/code/modules/shuttle/mobile_port/variants/custom/custom_consoles.dm +++ b/code/modules/shuttle/mobile_port/variants/custom/custom_consoles.dm @@ -45,6 +45,7 @@ jump_to_ports = list("whiteship_home" = 1) designate_time = 100 circuit = /obj/item/circuitboard/computer/shuttle/docker + // VOIDCREW EDIT REMOVAL: shuttle disables unsupported linked-z camera range. //zlink_range = 1 // TODO: Fix zlink_range var/static/list/connections = list(COMSIG_TURF_ADDED_TO_SHUTTLE = PROC_REF(on_loc_added_to_shuttle)) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 7444853c0d1..8255c5530c7 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -172,7 +172,8 @@ return P.shuttle_id // Say that A in the absolute (rectangular) bounds of this shuttle or no. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/docking_port/proc/is_in_shuttle_bounds(atom/A) + // VOIDCREW EDIT: shuttle separates geometric hull bounds from area membership. return is_in_shuttle_bounds_geometric(A) -// VOIDCREW EDIT END + +// VOIDCREW EDIT: shuttle exposes geometric hull bounds for engine membership; implementation in voidcrew/edits/modules/shuttle/shuttle.dm. diff --git a/code/modules/shuttle/shuttle_consoles/navigation_computer.dm b/code/modules/shuttle/shuttle_consoles/navigation_computer.dm index e8763f915e9..48057589d5c 100644 --- a/code/modules/shuttle/shuttle_consoles/navigation_computer.dm +++ b/code/modules/shuttle/shuttle_consoles/navigation_computer.dm @@ -3,6 +3,7 @@ desc = "Used to designate a precise transit location for a spacecraft." jump_action = null should_supress_view_changes = FALSE +// VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. // Docking cameras should only interact with their current z-level. move_up_action = null @@ -24,16 +25,18 @@ var/x_offset = 0 ///y offset for where the camera eye will spawn. Starts from the shuttle's docking port var/y_offset = 0 - var/list/whitelist_turfs = list(/turf/open/space, /turf/open/floor/plating, /turf/open/lava, /turf/open/openspace) + var/list/whitelist_turfs = list(/turf/open/space, /turf/open/floor/plating, /turf/open/lava, /turf/open/openspace) // VOIDCREW EDIT: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. var/see_hidden = FALSE var/designate_time = 0 var/turf/designating_target_loc var/jammed = FALSE +// VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. /obj/machinery/computer/camera_advanced/shuttle_docker/Initialize(mapload) . = ..() actions += new /datum/action/innate/shuttledocker_rotate(src) actions += new /datum/action/innate/shuttledocker_place(src) +// VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. set_init_ports() @@ -58,6 +61,7 @@ my_port = null else QDEL_NULL(my_port) +// VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. /// "Initializes" any default port ids we have, done so add_jumpable_port can be a proper setter /obj/machinery/computer/camera_advanced/shuttle_docker/proc/set_init_ports() @@ -110,34 +114,7 @@ SET_PLANE(I, ABOVE_GAME_PLANE, shuttle_turf) I.mouse_opacity = MOUSE_OPACITY_TRANSPARENT the_eye.placement_images[I] = list(x_off, y_off) - -// Commenting out do to overwriting this in 'voidcrew\modules\shuttle\survey\survey_computer.dm' - -// /obj/machinery/computer/camera_advanced/shuttle_docker/give_eye_control(mob/user) -// ..() -// if(!QDELETED(user) && user.client) -// var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj -// var/list/to_add = list() -// to_add += the_eye.placement_images -// to_add += the_eye.placed_images -// if(!see_hidden) -// to_add += SSshuttle.hidden_shuttle_turf_images - -// user.client.images += to_add -// user.client.view_size.setTo(view_range) - -// /obj/machinery/computer/camera_advanced/shuttle_docker/remove_eye_control(mob/living/user) -// ..() -// if(!QDELETED(user) && user.client) -// var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj -// var/list/to_remove = list() -// to_remove += the_eye.placement_images -// to_remove += the_eye.placed_images -// if(!see_hidden) -// to_remove += SSshuttle.hidden_shuttle_turf_images - -// user.client.images -= to_remove -// user.client.view_size.resetToDefault() +// VOIDCREW EDIT REMOVAL: shuttle survey owns eye-control images in voidcrew/modules/shuttle/survey/survey_computer.dm. /obj/machinery/computer/camera_advanced/shuttle_docker/proc/placeLandingSpot() if(designating_target_loc || !current_user) @@ -212,7 +189,7 @@ /obj/machinery/computer/camera_advanced/shuttle_docker/proc/rotateLandingSpot() var/mob/eye/camera/remote/shuttle_docker/the_eye = eyeobj - var/list/image_cache = the_eye.placement_images + var/list/image_cache = the_eye.placement_images // VOIDCREW EDIT: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. the_eye.setDir(turn(the_eye.dir, -90)) for(var/i in 1 to image_cache.len) var/image/pic = image_cache[i] @@ -221,6 +198,7 @@ coords[1] = coords[2] coords[2] = -Tmp pic.loc = locate(the_eye.x + coords[1], the_eye.y + coords[2], the_eye.z) + // VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. var/Tmp = x_offset x_offset = y_offset y_offset = -Tmp @@ -253,12 +231,13 @@ else I.icon_state = "red" . = SHUTTLE_DOCKER_BLOCKED +// VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. /obj/machinery/computer/camera_advanced/shuttle_docker/proc/checkLandingTurf(turf/T, list/overlappers) // Too close to the map edge is never allowed if(!T || T.x <= 10 || T.y <= 10 || T.x >= world.maxx - 10 || T.y >= world.maxy - 10) return SHUTTLE_DOCKER_BLOCKED - // VOIDCREW EDIT ADDITION: no designating a pad inside a live bitrunning domain. The + // VOIDCREW EDIT ADDITION START: shuttle - no designating a pad inside a live bitrunning domain. The // reservation floor is plain /area/space, so the allow_shuttle_docking check further // down happily clears it, and a shuttle is a door into VR that runs both ways. if(SSbitrunning.is_domain_turf(T)) @@ -314,8 +293,10 @@ use_visibility = FALSE var/list/image/placement_images = list() var/list/image/placed_images = list() +// VOIDCREW EDIT REMOVAL: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. /mob/eye/camera/remote/shuttle_docker/setLoc(turf/destination, force_update = FALSE) + // VOIDCREW EDIT START: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. var/obj/machinery/origin = origin_ref?.resolve() var/obj/machinery/computer/camera_advanced/shuttle_docker/console = null if(istype(origin, /obj/machinery/computer/camera_advanced/shuttle_docker)) @@ -326,8 +307,11 @@ // the survey console's override for the one that bounds itself. if(console && !console.eye_may_enter(destination)) return + // VOIDCREW EDIT END . = ..() - console?.checkLandingSpot() + console?.checkLandingSpot() // VOIDCREW EDIT: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. + +// VOIDCREW EDIT: shuttle provides a survey camera containment hook; implementation in voidcrew/edits/modules/shuttle/shuttle_consoles/navigation_computer.dm. /mob/eye/camera/remote/shuttle_docker/update_remote_sight(mob/living/user) user.set_sight(BLIND|SEE_TURFS) @@ -345,7 +329,7 @@ if(QDELETED(owner) || !isliving(owner)) return var/mob/eye/camera/remote/remote_eye = owner.remote_control - var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin_ref?.resolve() + var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin_ref?.resolve() // VOIDCREW EDIT: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. origin.rotateLandingSpot() /datum/action/innate/shuttledocker_place @@ -357,7 +341,7 @@ if(QDELETED(owner) || !isliving(owner)) return var/mob/eye/camera/remote/remote_eye = owner.remote_control - var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin_ref?.resolve() + var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin_ref?.resolve() // VOIDCREW EDIT: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. origin.placeLandingSpot(owner) /datum/action/innate/camera_jump/shuttle_docker @@ -368,11 +352,11 @@ if(QDELETED(owner) || !isliving(owner)) return var/mob/eye/camera/remote/remote_eye = owner.remote_control - var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin_ref?.resolve() + var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin_ref?.resolve() // VOIDCREW EDIT: shuttle uses survey-owned navigation images and enforces encounter camera boundaries. playsound(console, 'sound/machines/terminal/terminal_prompt_deny.ogg', 25, FALSE) - // VOIDCREW EDIT ADDITION: packed-level containment for the destination list. + // VOIDCREW EDIT ADDITION START: shuttle - packed-level containment for the destination list. // locked_traits is (ZTRAIT_RESERVED, ZTRAIT_CENTCOM, ZTRAIT_AWAY) and a lattice encounter // level carries none of them, so a berth or a nav beacon sitting inside a CO-TENANT's // slot became a "Jump to Location" destination. Deliberately narrowed to the SAME-Z case: @@ -388,7 +372,7 @@ var/obj/docking_port/stationary/S = V if(console.z_lock.len && !(S.z in console.z_lock)) continue - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START: shuttle scopes this effect to its encounter site. var/turf/port_turf = get_turf(S) if(port_turf && console_turf && port_turf.z == console_turf.z && map_region_excludes_turf(console_region, port_turf)) continue @@ -403,7 +387,7 @@ var/obj/machinery/spaceship_navigation_beacon/nav_beacon = V if(!nav_beacon.z || SSmapping.level_has_any_trait(nav_beacon.z, console.locked_traits)) break - // VOIDCREW EDIT ADDITION + // VOIDCREW EDIT ADDITION START: shuttle scopes this effect to its encounter site. var/turf/beacon_turf = get_turf(nav_beacon) if(beacon_turf && console_turf && beacon_turf.z == console_turf.z && map_region_excludes_turf(console_region, beacon_turf)) continue diff --git a/code/modules/shuttle/stationary_port/port_types.dm b/code/modules/shuttle/stationary_port/port_types.dm index 98fc15d1561..eb9644b08cc 100644 --- a/code/modules/shuttle/stationary_port/port_types.dm +++ b/code/modules/shuttle/stationary_port/port_types.dm @@ -74,8 +74,10 @@ // SSmapping.fire()'s reservation drain already guards a dead area explicitly // (the isnull(old_area.turfs_to_uncontain_by_zlevel) branch). if(!QDELETED(assigned_area)) + // VOIDCREW EDIT START: shuttle releases transit areas after reservation cleanup. qdel(assigned_area) assigned_area = null + // VOIDCREW EDIT END return ..() /obj/docking_port/stationary/picked @@ -111,4 +113,3 @@ "whiteship_obelisk", "whiteship_birdshot", ) - diff --git a/code/modules/shuttle/stationary_port/stationary_port.dm b/code/modules/shuttle/stationary_port/stationary_port.dm index 11d12541d64..fbe67c2a174 100644 --- a/code/modules/shuttle/stationary_port/stationary_port.dm +++ b/code/modules/shuttle/stationary_port/stationary_port.dm @@ -34,7 +34,7 @@ /obj/docking_port/stationary/LateInitialize() // Ports late-initialize independently. The subsystem skips ports without a template // and action_load() serializes every real load across its yielding operations. - INVOKE_ASYNC(SSshuttle, TYPE_PROC_REF(/datum/controller/subsystem/shuttle, setup_shuttle_late), src) + INVOKE_ASYNC(SSshuttle, TYPE_PROC_REF(/datum/controller/subsystem/shuttle, setup_shuttle_late), src) // VOIDCREW EDIT: shuttle serializes independent late port template loads. #ifdef TESTING highlight("#f00") diff --git a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm index 2d87b1e8c1b..a2cdd44f883 100644 --- a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm +++ b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm @@ -53,7 +53,7 @@ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/action/cooldown/spell/jaunt/bloodcrawl/proc/find_nearby_blood(turf/origin) for(var/obj/effect/decal/cleanable/blood_nearby in range(blood_radius, origin)) - if(is_valid_blood_destination(origin, blood_nearby)) + if(is_valid_blood_destination(origin, blood_nearby)) // VOIDCREW EDIT: jaunt destination integration: validate teleport permission before and after the wind-up (voidcrew/edits/modules/spells/spell_types/jaunt/bloodcrawl.dm) return blood_nearby return null @@ -78,8 +78,10 @@ */ // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/action/cooldown/spell/jaunt/bloodcrawl/proc/try_enter_jaunt(obj/effect/decal/cleanable/blood, mob/living/jaunter, forced = FALSE) + // VOIDCREW EDIT START - jaunt destination integration: validate teleport permission before and after the wind-up (voidcrew/edits/modules/spells/spell_types/jaunt/bloodcrawl.dm) if(!is_valid_blood_destination(jaunter, blood)) return FALSE + // VOIDCREW EDIT END if(!forced) if(enter_blood_time > 0 SECONDS) blood.visible_message(span_warning("[jaunter] starts to sink into [blood]!")) @@ -87,8 +89,10 @@ return FALSE // The pool or its teleport permissions may have changed during the wind-up. + // VOIDCREW EDIT START - jaunt destination integration: validate teleport permission before and after the wind-up (voidcrew/edits/modules/spells/spell_types/jaunt/bloodcrawl.dm) if(!is_valid_blood_destination(jaunter, blood)) return FALSE + // VOIDCREW EDIT END // The actual turf we enter var/turf/jaunt_turf = get_turf(blood) @@ -125,8 +129,10 @@ // VOIDCREW EDIT END // VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/action/cooldown/spell/jaunt/bloodcrawl/proc/try_exit_jaunt(obj/effect/decal/cleanable/blood, mob/living/jaunter, forced = FALSE) + // VOIDCREW EDIT START - jaunt destination integration: validate teleport permission before and after the wind-up (voidcrew/edits/modules/spells/spell_types/jaunt/bloodcrawl.dm) if(!is_valid_blood_destination(jaunter, blood)) return FALSE + // VOIDCREW EDIT END if(!forced) if(HAS_TRAIT(jaunter, TRAIT_NO_TRANSFORM)) to_chat(jaunter, span_warning("You cannot exit yet!!")) @@ -138,8 +144,10 @@ return FALSE // Moving into a NOTELEPORT area makes eject_jaunter scatter us across the z-level. + // VOIDCREW EDIT START - jaunt destination integration: validate teleport permission before and after the wind-up (voidcrew/edits/modules/spells/spell_types/jaunt/bloodcrawl.dm) if(!is_valid_blood_destination(jaunter, blood)) return FALSE + // VOIDCREW EDIT END if(!exit_jaunt(jaunter, get_turf(blood))) return FALSE diff --git a/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm b/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm index 4a369637623..5a38a5642e4 100644 --- a/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm +++ b/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm @@ -21,7 +21,6 @@ /// VOIDCREW EDIT: physical exit references travel with the deck during shuttle movement. var/list/exit_point_list -/// An invisible location reference, carried by ordinary shuttle movement and rotation. /datum/action/cooldown/spell/jaunt/ethereal_jaunt/enter_jaunt(mob/living/jaunter, turf/loc_override) . = ..() if(!.) @@ -54,10 +53,10 @@ // VOIDCREW EDIT: keep the starting floor attached to its moving ship. clear_exit_points() - start_point_anchor = new(get_turf(holder)) + start_point_anchor = new(get_turf(holder)) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) LAZYINITLIST(exit_point_list) RegisterSignal(holder, COMSIG_MOVABLE_MOVED, PROC_REF(update_exit_point), target) - addtimer(CALLBACK(src, PROC_REF(stop_jaunt), cast_on, holder, start_point_anchor), jaunt_duration) + addtimer(CALLBACK(src, PROC_REF(stop_jaunt), cast_on, holder, start_point_anchor), jaunt_duration) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) /** * The stopping of the jaunt. @@ -68,8 +67,7 @@ * - immediately, if jaunt_in_time >= 2.5 seconds * - 2.5 seconds - jaunt_in_time seconds otherwise */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/action/cooldown/spell/jaunt/ethereal_jaunt/proc/stop_jaunt(mob/living/cast_on, obj/effect/dummy/phased_mob/spell_jaunt/holder, atom/start_point) +/datum/action/cooldown/spell/jaunt/ethereal_jaunt/proc/stop_jaunt(mob/living/cast_on, obj/effect/dummy/phased_mob/spell_jaunt/holder, atom/start_point) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) if(QDELETED(cast_on) || QDELETED(holder) || QDELETED(src)) return @@ -83,26 +81,30 @@ var/turf/found_exit // VOIDCREW EDIT: resolve each exit where its original deck tile is now. for(var/obj/effect/abstract/jaunt_exit/exit_anchor as anything in exit_point_list) + // VOIDCREW EDIT START - jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) var/turf/possible_exit = get_turf(exit_anchor) if(!possible_exit || possible_exit.is_blocked_turf_ignore_climbable()) + // VOIDCREW EDIT END continue found_exit = possible_exit break // No valid exit was found if(!found_exit) - var/turf/start_turf = get_turf(start_point) || get_turf(holder) + var/turf/start_turf = get_turf(start_point) || get_turf(holder) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) // It's possible no exit was found, because we literally didn't even move - if(get_turf(cast_on) != start_turf) + if(get_turf(cast_on) != start_turf) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) to_chat(cast_on, span_danger("Unable to find an unobstructed space, you find yourself ripped back to where you started.")) // Either way, default to where we started - found_exit = start_turf + found_exit = start_turf // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) - clear_exit_points() + clear_exit_points() // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) holder.forceMove(found_exit) // Movement callbacks may eject, transform, or remove the caster's action. + // VOIDCREW EDIT START - jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) if(QDELETED(src) || QDELETED(cast_on) || QDELETED(holder) || cast_on.loc != holder || holder.jaunter != cast_on) return + // VOIDCREW EDIT END // VOIDCREW EDIT: synchronous movement callbacks can relocate the entire deck. found_exit = get_turf(holder) do_steam_effects(found_exit) @@ -123,13 +125,14 @@ * * Calls end_jaunt. */ -// VOIDCREW EDIT END /datum/action/cooldown/spell/jaunt/ethereal_jaunt/proc/do_jaunt_in(mob/living/cast_on, obj/effect/dummy/phased_mob/spell_jaunt/holder, turf/final_point) if(QDELETED(cast_on) || QDELETED(holder) || QDELETED(src)) return + // VOIDCREW EDIT START - jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) if(cast_on.loc != holder || holder.jaunter != cast_on) qdel(holder) return + // VOIDCREW EDIT END // VOIDCREW EDIT: the return animation follows its holder through ship transit. final_point = get_turf(holder) @@ -149,13 +152,14 @@ * If the final_point is dense for some reason, * tries to put the caster in an adjacent turf. */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/action/cooldown/spell/jaunt/ethereal_jaunt/proc/end_jaunt(mob/living/cast_on, obj/effect/dummy/phased_mob/spell_jaunt/holder, turf/final_point) if(QDELETED(cast_on) || QDELETED(holder) || QDELETED(src)) return + // VOIDCREW EDIT START - jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) if(cast_on.loc != holder || holder.jaunter != cast_on) qdel(holder) return + // VOIDCREW EDIT END ADD_TRAIT(cast_on, TRAIT_NO_TRANSFORM, REF(src)) exit_jaunt(cast_on) @@ -165,7 +169,7 @@ // VOIDCREW EDIT: check the floor we actually emerged on, never the old deck. final_point = get_turf(cast_on) - if(final_point?.density) + if(final_point?.density) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) var/list/aside_turfs = get_adjacent_open_turfs(final_point) if(length(aside_turfs)) cast_on.forceMove(pick(aside_turfs)) @@ -178,7 +182,6 @@ * spots are kept in the list, in case the last few changed since we passed * by (doors closing, engineers building walls, etc) */ -// VOIDCREW EDIT END /datum/action/cooldown/spell/jaunt/ethereal_jaunt/proc/update_exit_point(mob/living/source) SIGNAL_HANDLER @@ -187,9 +190,9 @@ return // VOIDCREW EDIT: retain the same bounded history using movable references. var/obj/effect/abstract/jaunt_exit/exit_anchor = new(location) - exit_point_list.Insert(1, exit_anchor) + exit_point_list.Insert(1, exit_anchor) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) if(length(exit_point_list) >= 5) - qdel(exit_point_list[5]) + qdel(exit_point_list[5]) // VOIDCREW EDIT: jaunt destination integration: carry return anchors with moving decks and stop interrupted returns (voidcrew/edits/modules/spells/spell_types/jaunt/ethereal_jaunt.dm) exit_point_list.Cut(5) /// Does some steam effects from the jaunt at passed loc. diff --git a/code/modules/spells/spell_types/tower_of_babel.dm b/code/modules/spells/spell_types/tower_of_babel.dm index 5a27623baf6..12c0f63c7ab 100644 --- a/code/modules/spells/spell_types/tower_of_babel.dm +++ b/code/modules/spells/spell_types/tower_of_babel.dm @@ -37,7 +37,7 @@ GLOBAL_DATUM(tower_of_babel, /datum/tower_of_babel) // carbon_list, not player_list: player_list only holds mobs with a client attached, and a // dead player who ghosted leaves their cursed body clientless. Miss the body here and they // revive still babbling, with the cure already destroyed. - for(var/mob/living/carbon/target in GLOB.carbon_list) + for(var/mob/living/carbon/target in GLOB.carbon_list) // VOIDCREW EDIT: Voidcrew spell cleanup: cure clientless and mindless cursed bodies (voidcrew/edits/spells) cure_curse_of_babel(target) // VOIDCREW EDIT END @@ -68,8 +68,9 @@ GLOBAL_DATUM(tower_of_babel, /datum/tower_of_babel) // A body whose mind left mid-curse (respawn, borging, mind swap) has no mind to carry // the babel trait but still holds the permanent status effect. Cure it unconditionally; // the minded early-out below only protects people who were never cursed by this source. - if(to_cure.mind && !HAS_TRAIT_FROM(to_cure.mind, TRAIT_TOWER_OF_BABEL, TRAUMA_TRAIT)) + if(to_cure.mind && !HAS_TRAIT_FROM(to_cure.mind, TRAIT_TOWER_OF_BABEL, TRAUMA_TRAIT)) // VOIDCREW EDIT: Voidcrew spell cleanup: cure clientless and mindless cursed bodies (voidcrew/edits/spells) return + // VOIDCREW EDIT REMOVAL - Voidcrew spell cleanup: cure clientless and mindless cursed bodies (voidcrew/edits/spells) to_cure.remove_status_effect(/datum/status_effect/tower_of_babel/magical) // VOIDCREW EDIT END diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm index 3d4ed163adf..bae07749421 100644 --- a/code/modules/surgery/experimental_dissection.dm +++ b/code/modules/surgery/experimental_dissection.dm @@ -1,7 +1,5 @@ ///How many research points you gain from dissecting a Human. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -#define BASE_HUMAN_REWARD 100 -// VOIDCREW EDIT END +#define BASE_HUMAN_REWARD 100 // VOIDCREW EDIT: surgery values fauna dissections and consumes failed corpses once. /datum/surgery/advanced/experimental_dissection name = "Experimental Dissection" @@ -42,7 +40,7 @@ time = 12 SECONDS silicons_obey_prob = TRUE ///Research points a baseline human corpse is worth. Upgraded dissection tiers raise this. - var/base_value = BASE_HUMAN_REWARD + var/base_value = BASE_HUMAN_REWARD // VOIDCREW EDIT: surgery values fauna dissections and consumes failed corpses once. /datum/surgery_step/experimental_dissection/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery) user.visible_message(span_notice("[user] starts dissecting [target]."), span_notice("You start dissecting [target].")) @@ -76,22 +74,23 @@ span_notice("You dissect [target], but do not find anything particularly interesting."), ) + // VOIDCREW EDIT START: surgery values fauna dissections and consumes failed corpses once. if(points_earned > 0) var/obj/item/research_notes/the_dossier = new /obj/item/research_notes(user.loc, points_earned, "biology") if(!user.put_in_hands(the_dossier) && istype(user.get_inactive_held_item(), /obj/item/research_notes)) var/obj/item/research_notes/hand_dossier = user.get_inactive_held_item() hand_dossier.merge(the_dossier) + // VOIDCREW EDIT END target.apply_damage(80, BRUTE, BODY_ZONE_CHEST) // A botched dissection still consumes the corpse. Without this the surgery can be cancelled and // re-run indefinitely on the same body, which was farmable for free notes. - ADD_TRAIT(target, TRAIT_DISSECTED, EXPERIMENTAL_SURGERY_TRAIT) + ADD_TRAIT(target, TRAIT_DISSECTED, EXPERIMENTAL_SURGERY_TRAIT) // VOIDCREW EDIT: surgery values fauna dissections and consumes failed corpses once. return TRUE ///Calculates how many research points dissecting 'target' is worth. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /datum/surgery_step/experimental_dissection/proc/check_value(mob/living/target) - var/cost = base_value + var/cost = base_value // VOIDCREW EDIT: surgery values fauna dissections and consumes failed corpses once. if(ishuman(target)) var/mob/living/carbon/human/human_target = target @@ -110,20 +109,21 @@ cost *= 5 // Fauna is graded by how dangerous it is, so the corpse is worth roughly what it cost to make. // melee_damage_upper lives on /mob/living, so this reads correctly on both basic and simple mobs. + // VOIDCREW EDIT START: surgery values fauna dissections and consumes failed corpses once. else if(ismegafauna(target)) cost *= 10 else if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite)) cost *= 3 else if(target.melee_damage_upper > 0) cost /= 3 + // VOIDCREW EDIT END else cost /= 6 - return max(round(cost), 1) + return max(round(cost), 1) // VOIDCREW EDIT: surgery values fauna dissections and consumes failed corpses once. #undef BASE_HUMAN_REWARD -// VOIDCREW EDIT END /obj/item/research_notes name = "research notes" desc = "Valuable scientific data. Use it in an ancient research server to turn it in." @@ -137,17 +137,15 @@ ///if it ws merged with different origins to apply a bonus var/mixed = FALSE -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/research_notes/Initialize(mapload, value, origin_type) . = ..() // Explicitly check for null, not truthiness: a passed-in 0 must mean "worthless", not "use the default". - if(!isnull(value)) + if(!isnull(value)) // VOIDCREW EDIT: surgery values fauna dissections and consumes failed corpses once. src.value = value if(origin_type) src.origin_type = origin_type change_vol() -// VOIDCREW EDIT END /obj/item/research_notes/examine(mob/user) . = ..() . += span_notice("It is worth [value] research points.") diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm index 9ee3414dba8..d5e14deadd8 100644 --- a/code/modules/surgery/healing.dm +++ b/code/modules/surgery/healing.dm @@ -95,6 +95,7 @@ brute_healed += round((target.getBruteLoss() * brute_multiplier),0.1) burn_healed += round((target.getFireLoss() * burn_multiplier),0.1) dead_patient = FALSE + // VOIDCREW EDIT REMOVAL: surgery permits treatment through clothing. target.heal_bodypart_damage(brute_healed,burn_healed) user_msg += get_progress(user, target, brute_healed, burn_healed) diff --git a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm index fbbd0472ca2..911e506d4c6 100644 --- a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm +++ b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm @@ -89,7 +89,7 @@ /obj/item/organ/heart/cybernetic/anomalock/proc/add_lightning_overlay(time_to_last = 10 SECONDS) if(!owner) // VOIDCREW EDIT - BAL-4: nothing to draw the arc on, and arming the timer anyway is what used to runtime later - return + return // VOIDCREW EDIT: cyberware skips lightning overlays without an organ owner. if(lightning_overlay) lightning_timer = addtimer(CALLBACK(src, PROC_REF(clear_lightning_overlay)), time_to_last, (TIMER_UNIQUE|TIMER_OVERRIDE)) return diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index fac5def2b41..3ed6b33e956 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -134,7 +134,7 @@ var/step_handled = surgery_step.try_op(user, target, user.zone_selected, tool, src, try_to_fail) qdel(surgery_step) // VOIDCREW EDIT END - if(step_handled) + if(step_handled) // VOIDCREW EDIT: surgery owns each sleeping step invocation until completion. return TRUE if(!tool) return FALSE diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 145871780e8..6efcf344b51 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -76,7 +76,7 @@ var/next_step_handled = next_step.try_op(user, target, user.zone_selected, user.get_active_held_item(), surgery) qdel(next_step) // VOIDCREW EDIT END - if(next_step_handled) + if(next_step_handled) // VOIDCREW EDIT: surgery reclaims the fallback step after its channel ends. return TRUE else surgery.status-- diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 83a3ddc81ec..608226130ed 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -85,7 +85,6 @@ #define TRAIT_SOURCE_UNIT_TESTS "unit_tests" /// Helper to allocate a new object with the implied type (the type of the variable it's assigned to) in the corner of the test room #define EASY_ALLOCATE(arguments...) allocate(__IMPLIED_TYPE__, run_loc_floor_bottom_left, ##arguments) -// VOIDCREW EDIT START - PR #425: Support cyborg and AI ship crew. // BEGIN_INCLUDE #include "abductor_baton_spell.dm" @@ -246,7 +245,6 @@ #include "plantgrowth_tests.dm" #include "preference_species.dm" #include "preferences.dm" -#include "prisoner_photos.dm" #include "projectiles.dm" #include "quirks.dm" #include "range_return.dm" @@ -336,4 +334,3 @@ #undef TEST_ASSERT_NOTEQUAL //#undef TEST_FOCUS - This define is used by vscode unit test extension to pick specific unit tests to run and appended later so needs to be used out of scope here #endif -// VOIDCREW EDIT END diff --git a/code/modules/unit_tests/designs.dm b/code/modules/unit_tests/designs.dm index fbf44850e71..dc1e3754a26 100644 --- a/code/modules/unit_tests/designs.dm +++ b/code/modules/unit_tests/designs.dm @@ -43,6 +43,7 @@ // these are pulled out of their upstream nodes in // voidcrew/modules/research/techweb_nodes.dm. The designs stay behind for the // consoles that are already mapped in; nothing researches them. + // VOIDCREW EDIT START: unit_tests permits deliberately unresearchable research and depot designs. /datum/design/board/cargorequest, /datum/design/board/accounting_console, /datum/design/cargo_express, @@ -67,6 +68,7 @@ /datum/design/nanites/nerve_decay, /datum/design/nanites/brain_decay, /datum/design/nanites/heart_stop, + // VOIDCREW EDIT END ) for (var/datum/design/design as anything in subtypesof(/datum/design)) diff --git a/code/modules/unit_tests/missing_icons.dm b/code/modules/unit_tests/missing_icons.dm index d431cb7956a..0758aa0fdc0 100644 --- a/code/modules/unit_tests/missing_icons.dm +++ b/code/modules/unit_tests/missing_icons.dm @@ -11,11 +11,14 @@ if(!directory_path) directory_path = "icons/obj/" for(var/file_path in flist(directory_path)) + // VOIDCREW EDIT START: unit_tests recurses only into icon directories. if(copytext(file_path, -1) == "/") // only directories end in "/"; anything else is a loose file (.png smoothing sources etc.) we must not descend into generate_possible_icon_states_list("[directory_path][file_path]") else if(copytext(file_path, -4) == ".dmi") + // VOIDCREW EDIT END for(var/sprite_icon in icon_states("[directory_path][file_path]", 1)) //2nd arg = 1 enables 64x64+ icon support, otherwise you'll end up with "sword0_1" instead of "sword" possible_icon_states[sprite_icon] += list("[directory_path][file_path]") +// VOIDCREW EDIT REMOVAL: unit_tests recurses only into icon directories. // VOIDCREW EDIT END /datum/unit_test/missing_icons/Run() diff --git a/code/modules/unit_tests/operating_table.dm b/code/modules/unit_tests/operating_table.dm index 1ea00c87d96..f512cd89217 100644 --- a/code/modules/unit_tests/operating_table.dm +++ b/code/modules/unit_tests/operating_table.dm @@ -31,46 +31,4 @@ human.forceMove(get_step(get_turf(table), NORTH)) TEST_ASSERT_EQUAL(table.patient, replacement_human, "Operating table failed to find a replacement patient.") -/// Occupants can move between adjacent tables, while floor entry and buckling keep their normal restrictions. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/unit_test/operating_table_movement - -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/unit_test/operating_table_movement/Run() - var/turf/first_site = get_step(run_loc_floor_bottom_left, EAST) - var/turf/second_site = get_step(first_site, EAST) - var/turf/floor_exit = get_step(first_site, NORTH) - var/obj/structure/table/optable/first_table = allocate(__IMPLIED_TYPE__, first_site) - var/obj/structure/table/optable/second_table = allocate(__IMPLIED_TYPE__, second_site) - var/mob/living/carbon/human/consistent/human = allocate(__IMPLIED_TYPE__) - - TEST_ASSERT(!human.Move(first_site, EAST), "Walking from the floor must not bypass getting onto an operating table.") - TEST_ASSERT(!HAS_TRAIT(human, TRAIT_ON_CLIMBABLE), "A failed attempt to enter must not grant table-walking permission.") - human.forceMove(first_site) // Simulate having already climbed or been placed onto the table. - TEST_ASSERT(human.Move(second_site, EAST), "An occupant must be able to walk onto an adjacent operating table.") - TEST_ASSERT_EQUAL(human.loc, second_site, "Walking between tables must move the occupant physically.") - TEST_ASSERT_NULL(first_table.patient, "Walking upright must not leave a patient on the first table.") - TEST_ASSERT_NULL(second_table.patient, "Walking upright must not create a patient on the second table.") - - TEST_ASSERT(second_table.buckle_mob(human, force = TRUE), "The occupied operating table must still support buckling.") - TEST_ASSERT(!human.Move(first_site, WEST), "A buckled patient must not walk off the table.") - TEST_ASSERT_EQUAL(human.buckled, second_table, "Attempted movement must not unbuckle the patient.") - second_table.unbuckle_mob(human, force = TRUE) - human.set_resting(new_resting = TRUE, instant = TRUE) - TEST_ASSERT_EQUAL(second_table.patient, human, "The resting occupant must be registered as the current patient.") - TEST_ASSERT(human.Move(first_site, WEST), "An unbuckled resting occupant must be able to move between tables.") - TEST_ASSERT_NULL(second_table.patient, "Moving away must clear the previous table's patient.") - TEST_ASSERT_EQUAL(first_table.patient, human, "The destination table must recognize the resting patient.") - - TEST_ASSERT(human.Move(floor_exit, NORTH), "The occupant must be able to leave the table for the floor.") - TEST_ASSERT_NULL(first_table.patient, "Leaving the table must clear its patient.") - TEST_ASSERT(!HAS_TRAIT(human, TRAIT_ON_CLIMBABLE), "Table-walking permission must end when the occupant leaves.") - human.set_resting(new_resting = FALSE, instant = TRUE) - TEST_ASSERT(!human.Move(first_site, SOUTH), "An occupant on the floor must get onto the table again before crossing it.") - - human.forceMove(first_site) - qdel(first_table) - TEST_ASSERT(!HAS_TRAIT(human, TRAIT_ON_CLIMBABLE), "Removing the occupied table must remove its table-walking permission.") - TEST_ASSERT(!human.Move(second_site, EAST), "A removed table must not allow walking onto a remaining adjacent table.") -// VOIDCREW EDIT END +// VOIDCREW EDIT: unit_tests covers operating table movement restrictions; implementation in voidcrew/modules/unit_tests/operating_table_movement.dm. diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 7de76fb716a..daefc29f871 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -32,6 +32,7 @@ // Voidcrew: mining and wasteland fauna carried over from the fork's original // mob set, grandfathered here so the freeze still catches genuinely new // simple animals. They are queued for the basic mob refactor like the rest. + // VOIDCREW EDIT START: unit_tests retains the existing mining fauna during basic-mob migration. /mob/living/simple_animal/hostile/asteroid/hermit, /mob/living/simple_animal/hostile/asteroid/hermit/ranged, /mob/living/simple_animal/hostile/asteroid/hermit/ranged/gunslinger, @@ -39,10 +40,13 @@ /mob/living/simple_animal/hostile/asteroid/hermit/survivor, /mob/living/simple_animal/hostile/asteroid/hermit/survivor/random, /mob/living/simple_animal/hostile/asteroid/old_demon, + // VOIDCREW EDIT END /mob/living/simple_animal/hostile/asteroid/polarbear, /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, + // VOIDCREW EDIT START: unit_tests retains the existing mining fauna during basic-mob migration. /mob/living/simple_animal/hostile/asteroid/polarbear/random, /mob/living/simple_animal/hostile/asteroid/polarbear/warrior, + // VOIDCREW EDIT END /mob/living/simple_animal/hostile/illusion, /mob/living/simple_animal/hostile/illusion/escape, /mob/living/simple_animal/hostile/illusion/mirage, diff --git a/code/modules/unit_tests/spell_jaunt.dm b/code/modules/unit_tests/spell_jaunt.dm index 82430d39010..c68c93100ab 100644 --- a/code/modules/unit_tests/spell_jaunt.dm +++ b/code/modules/unit_tests/spell_jaunt.dm @@ -20,76 +20,4 @@ TEST_ASSERT_EQUAL(jaunter.loc, jaunt_turf, "Jaunter failed to exit jaunt on exiting [walk].") -/// A nearby pool across a ruin boundary must not invoke the random jaunt ejection fallback. -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/unit_test/blood_jaunt_destinations - var/turf/pool_turf - var/area/original_area - var/area/overmap_encounter/planet_ruin/ruin_area - var/original_turf_flags - -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/unit_test/blood_jaunt_destinations/Destroy() - if(pool_turf) - pool_turf.turf_flags = original_turf_flags - pool_turf.change_area(ruin_area, original_area) - QDEL_NULL(ruin_area) - return ..() - -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/unit_test/blood_jaunt_destinations/Run() - var/mob/living/carbon/human/jaunter = allocate(/mob/living/carbon/human/consistent) - var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = allocate(/datum/action/cooldown/spell/jaunt/bloodcrawl) - crawl.Grant(jaunter) - crawl.equip_blood_hands = FALSE - var/obj/effect/decal/cleanable/blood/entry_pool = allocate(/obj/effect/decal/cleanable/blood) - pool_turf = get_step(run_loc_floor_bottom_left, EAST) - original_area = get_area(pool_turf) - original_turf_flags = pool_turf.turf_flags - ruin_area = new - pool_turf.change_area(original_area, ruin_area) - var/obj/effect/decal/cleanable/blood/exit_pool = allocate(/obj/effect/decal/cleanable/blood, pool_turf) - - TEST_ASSERT(!crawl.try_enter_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl entered a pool inside a NOTELEPORT ruin") - TEST_ASSERT_EQUAL(get_turf(jaunter), run_loc_floor_bottom_left, "Refused blood entry moved the caster") - TEST_ASSERT(crawl.try_enter_jaunt(entry_pool, jaunter, forced = TRUE), "Blood Crawl could not enter an ordinary pool") - var/obj/effect/dummy/phased_mob/holder = jaunter.loc - qdel(entry_pool) - - TEST_ASSERT(isnull(crawl.find_nearby_blood(get_turf(jaunter))), "Blood Crawl offered a pool across a NOTELEPORT boundary") - var/datum/action/cooldown/spell/jaunt/bloodcrawl/vestige_trapdoor/trapdoor = allocate(/datum/action/cooldown/spell/jaunt/bloodcrawl/vestige_trapdoor) - TEST_ASSERT(isnull(trapdoor.find_wet_door(get_turf(jaunter))), "The trapdoor pact offered a pool across a NOTELEPORT boundary") - TEST_ASSERT(!crawl.try_exit_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl exited into a NOTELEPORT ruin") - TEST_ASSERT_EQUAL(jaunter.loc, holder, "A refused blood exit ejected or scattered the caster") - TEST_ASSERT_EQUAL(get_turf(holder), run_loc_floor_bottom_left, "A refused blood exit moved the holder") - - // Turf-level wards must also apply to pool selection and direct entry/exit. - ruin_area.area_flags &= ~NOTELEPORT - pool_turf.turf_flags |= NOJAUNT - TEST_ASSERT(isnull(crawl.find_nearby_blood(get_turf(jaunter))), "Blood Crawl offered a pool on a NOJAUNT turf") - TEST_ASSERT(!crawl.try_exit_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl exited onto a NOJAUNT turf") - pool_turf.turf_flags = original_turf_flags - - TEST_ASSERT_EQUAL(crawl.find_nearby_blood(get_turf(jaunter)), exit_pool, "Blood Crawl did not offer the now-unprotected pool") - TEST_ASSERT_EQUAL(trapdoor.find_wet_door(get_turf(jaunter)), exit_pool, "The trapdoor pact did not offer the now-unprotected pool") - - // The destination can become protected after selection, during the bubbling delay. - crawl.exit_blood_time = 1 SECONDS - addtimer(CALLBACK(src, PROC_REF(ward_destination)), 0.5 SECONDS) - TEST_ASSERT(!crawl.try_exit_jaunt(exit_pool, jaunter), "Blood Crawl ignored a ward applied during its exit delay") - TEST_ASSERT(ruin_area.area_flags & NOTELEPORT, "The destination was never warded during the exit delay") - TEST_ASSERT_EQUAL(jaunter.loc, holder, "A ward applied during the exit delay scattered the caster") - TEST_ASSERT_EQUAL(get_turf(holder), run_loc_floor_bottom_left, "A ward applied during the exit delay moved the holder") - - ruin_area.area_flags &= ~NOTELEPORT - TEST_ASSERT(crawl.try_exit_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl could not exit through an unprotected pool") - TEST_ASSERT_EQUAL(jaunter.loc, pool_turf, "Blood Crawl did not surface at the chosen pool") - TEST_ASSERT(!HAS_TRAIT(jaunter, TRAIT_MAGICALLY_PHASED), "Blood Crawl left the caster phased after a successful exit") - -// VOIDCREW EDIT END -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. -/datum/unit_test/blood_jaunt_destinations/proc/ward_destination() - ruin_area.area_flags |= NOTELEPORT -// VOIDCREW EDIT END +// VOIDCREW EDIT: unit_tests covers protected blood-jaunt destinations; implementation in voidcrew/modules/unit_tests/blood_jaunt_destinations.dm. diff --git a/code/modules/unit_tests/spell_shapeshift.dm b/code/modules/unit_tests/spell_shapeshift.dm index 6b11f9a9e4a..bf503c1db6c 100644 --- a/code/modules/unit_tests/spell_shapeshift.dm +++ b/code/modules/unit_tests/spell_shapeshift.dm @@ -30,6 +30,7 @@ var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent, run_loc_floor_bottom_left) dummy.mind_initialize() + // VOIDCREW EDIT START: antag_ruins excludes identity-copying disguises from bare-trigger tests. var/list/spell_types = subtypesof(/datum/action/cooldown/spell/shapeshift) // VOIDCREW EDIT: the vestige mimic disguises are identity-copying // shapeshifts - the shape is built from an appearance borrowed through the @@ -37,6 +38,7 @@ // borrowed correctly refuses to transform and this harness can't drive them. spell_types -= typesof(/datum/action/cooldown/spell/shapeshift/vestige_mimic) for(var/spell_type in spell_types) + // VOIDCREW EDIT END // Test all shapeshifts as if they were on the mob's body var/datum/action/cooldown/spell/shapeshift/bodybound_shift = new spell_type(dummy) bodybound_shift.Grant(dummy) @@ -117,11 +119,13 @@ /datum/unit_test/shapeshift_health /datum/unit_test/shapeshift_health/Run() + // VOIDCREW EDIT START: antag_ruins excludes identity-copying disguises from bare-trigger tests. var/list/spell_types = subtypesof(/datum/action/cooldown/spell/shapeshift) // VOIDCREW EDIT: see shapeshift_spell - identity-copying vestige disguises // can't be driven by a bare Trigger(). spell_types -= typesof(/datum/action/cooldown/spell/shapeshift/vestige_mimic) for(var/spell_type in spell_types) + // VOIDCREW EDIT END var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent, run_loc_floor_bottom_left) var/datum/action/cooldown/spell/shapeshift/shift_spell = new spell_type(dummy) shift_spell.Grant(dummy) diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm index ce80ebb3640..0c97bc3ed9a 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -1,4 +1,3 @@ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/mecha_part_fabricator icon = 'icons/obj/machines/robotics.dmi' icon_state = "fab-idle" @@ -60,7 +59,6 @@ /// Direction the produced items will drop (0 means on top of us) var/drop_direction = SOUTH -// VOIDCREW EDIT END /obj/machinery/mecha_part_fabricator/Initialize(mapload) print_sound = new(src, FALSE) rmat = AddComponent(/datum/component/remote_materials, mapload && link_on_init) @@ -250,7 +248,6 @@ * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. * * user_data - ID_DATA(user), see the proc on SSid_access */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE, alist/user_data) if(!D || length(D.reagents_list)) return FALSE @@ -267,6 +264,7 @@ say("Not enough resources. Processing stopped.") return FALSE + // VOIDCREW EDIT START: research retains paid fabrication materials and permits local designs without a disk. var/list/materials_before = materials.materials.Copy() if(!rmat.use_materials(D.materials, component_coeff, 1, "built", "[D.name]", user_data)) return FALSE @@ -275,6 +273,7 @@ var/consumed = materials_before[material] - materials.materials[material] if(consumed > 0) being_built_materials[material] = consumed + // VOIDCREW EDIT END being_built = D build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time)) build_start = world.time @@ -282,7 +281,6 @@ return TRUE -// VOIDCREW EDIT END /obj/machinery/mecha_part_fabricator/process() // If there's a stored part to dispense due to an obstruction, try to dispense it. if(stored_part) @@ -318,11 +316,12 @@ * Return TRUE if the part was successfully dispensed. * * dispensed_design - Design datum to attempt to dispense. */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/dispensed_design) var/obj/item/built_part = new dispensed_design.build_path(src) + // VOIDCREW EDIT START: research retains paid fabrication materials and permits local designs without a disk. apply_fabrication_materials(built_part, being_built_materials) being_built_materials = null + // VOIDCREW EDIT END SSblackbox.record_feedback("nested tally", "lathe_printed_items", 1, list("[type]", "[built_part.type]")) being_built = null @@ -341,6 +340,8 @@ return TRUE +// VOIDCREW EDIT: research allocates only the paid fabrication materials; implementation in voidcrew/edits/modules/vehicles/mecha/mech_fabricator.dm. + /** * Adds a datum design to the build queue. * @@ -348,7 +349,6 @@ * * D - Datum design to add to the queue. * user_data - user data in the form rendered by ID_DATA(user), see the proc on SSidaccess */ -// VOIDCREW EDIT END /obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D, alist/user_data) if(!istype(queue)) queue = list() @@ -473,10 +473,11 @@ if(!istext(design_id)) continue - var/datum/design/design = SSresearch.techweb_design_by_id(design_id) + var/datum/design/design = SSresearch.techweb_design_by_id(design_id) // VOIDCREW EDIT: research retains paid fabrication materials and permits local designs without a disk. // VOIDCREW EDIT: independent local designs still work with the server disk removed. if(!((stored_research && stored_research.researched_designs.Find(design_id)) || (design in illegal_local_designs))) continue +// VOIDCREW EDIT REMOVAL: research retains paid fabrication materials and permits local designs without a disk. if(!(design.build_type & MECHFAB) || design.id != design_id) continue diff --git a/code/modules/wiremod/components/ntnet/ntnet_receive.dm b/code/modules/wiremod/components/ntnet/ntnet_receive.dm index 8b73f2e3958..7d1cca6a819 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_receive.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_receive.dm @@ -39,15 +39,19 @@ // Voidcrew: ships are their own NTNet node, and the broadcast is scoped to one of them. // The global signal reaches every receiver in the world, so without this a crew could // read - and jam - the circuit traffic of a ship they have never met. + // VOIDCREW EDIT START: circuits restricts NTNet reception to the sender ship network. var/turf/our_turf = get_circuit_turf(parent) if(!ntnet_reachable_from(our_turf)) + // VOIDCREW EDIT END return if(data["enc_key"] != enc_key.value) + // VOIDCREW EDIT START: circuits restricts NTNet reception to the sender ship network. return var/datum/weakref/sender_ref = data["sender"] var/obj/item/circuit_component/sender = sender_ref?.resolve() if(isnull(sender) || !on_same_ship_network(get_circuit_turf(sender.parent), our_turf)) + // VOIDCREW EDIT END return var/datum/weakref/ref = data["port"] diff --git a/code/modules/wiremod/components/ntnet/ntnet_send.dm b/code/modules/wiremod/components/ntnet/ntnet_send.dm index 4ea2f66a336..729f5edcea8 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_send.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_send.dm @@ -34,7 +34,7 @@ /// If the server is down, don't use power or attempt to send data // Voidcrew: this fork loads no station and maps no relays, so a bare // find_functional_ntnet_relay() is always FALSE. Ships are their own NTNet node. - return ntnet_reachable_from(get_circuit_turf(parent)) + return ntnet_reachable_from(get_circuit_turf(parent)) // VOIDCREW EDIT: circuits uses the ship-local NTNet node. /obj/item/circuit_component/ntnet_send/pre_input_received(datum/port/input/port) if(port == list_options) diff --git a/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm b/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm index c565a1ec467..e8e3fed433a 100644 --- a/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm +++ b/code/modules/wiremod/components/ntnet/ntnet_send_literal.dm @@ -24,7 +24,7 @@ return FALSE /// If the server is down, don't use power or attempt to send data // Voidcrew: see ntnet_send.dm - ships are their own NTNet node. - return ntnet_reachable_from(get_circuit_turf(parent)) + return ntnet_reachable_from(get_circuit_turf(parent)) // VOIDCREW EDIT: circuits uses the ship-local NTNet node. /obj/item/circuit_component/list_literal/ntnet_send/input_received(datum/port/input/port) . = ..() diff --git a/code/modules/wiremod/components/utility/nfc_receive.dm b/code/modules/wiremod/components/utility/nfc_receive.dm index 3d347a26b02..2fe0c4b2012 100644 --- a/code/modules/wiremod/components/utility/nfc_receive.dm +++ b/code/modules/wiremod/components/utility/nfc_receive.dm @@ -66,12 +66,14 @@ // free ship-to-ship or orbit-to-surface link. Locating through get_circuit_turf() also fixes // circuits in unremovable shells (bots, drones), which sit in nullspace and were previously // unreachable by NFC at any distance. + // VOIDCREW EDIT START: circuits permits hull-wide NFC while retaining off-ship range limits. var/turf/our_turf = get_circuit_turf(parent) var/turf/sender_turf = get_circuit_turf(sender) if(isnull(our_turf) || isnull(sender_turf)) return if(!on_same_ship_network(sender_turf, our_turf) && get_dist(sender_turf, our_turf) >= 10) + // VOIDCREW EDIT END return if(data["enc_key"] != enc_key.value) diff --git a/code/modules/wiremod/components/utility/nfc_send_literal.dm b/code/modules/wiremod/components/utility/nfc_send_literal.dm index db923420bbc..b6195c1a48f 100644 --- a/code/modules/wiremod/components/utility/nfc_send_literal.dm +++ b/code/modules/wiremod/components/utility/nfc_send_literal.dm @@ -22,6 +22,7 @@ enc_key = add_input_port("Encryption Key", PORT_TYPE_STRING) target = add_input_port("Target", PORT_TYPE_ATOM) +// VOIDCREW EDIT REMOVAL: circuits sends NFC directly with the sending circuit in the signal payload. // Voidcrew: this used to gate on find_functional_ntnet_relay(). NFC is a direct point to point // link that never touched NTNet, and the fork has no relays at all, so the gate did nothing but // keep the component permanently dead. The plain component check is the whole requirement. @@ -33,4 +34,4 @@ // Voidcrew: the sending circuit was missing from this signal, so nfc_receive() read the // payload list as its `sender` argument and the real payload as null - the list literal // variant could never deliver anything. nfc_send.dm has always passed it. - SEND_SIGNAL(target_enty, COMSIG_CIRCUIT_NFC_DATA_SENT, parent, list("data" = list_output.value, "enc_key" = enc_key.value, "port" = WEAKREF(list_output))) + SEND_SIGNAL(target_enty, COMSIG_CIRCUIT_NFC_DATA_SENT, parent, list("data" = list_output.value, "enc_key" = enc_key.value, "port" = WEAKREF(list_output))) // VOIDCREW EDIT: circuits sends NFC directly with the sending circuit in the signal payload. diff --git a/code/modules/wiremod/core/component.dm b/code/modules/wiremod/core/component.dm index 5df67e38b3e..8453ae2a119 100644 --- a/code/modules/wiremod/core/component.dm +++ b/code/modules/wiremod/core/component.dm @@ -221,7 +221,6 @@ * Arguments: * * output_port - The output port to remove. */ -// VOIDCREW EDIT START - PR #123: ship systems and overmap integration. /obj/item/circuit_component/proc/remove_output_port(datum/port/output/output_port) output_ports -= output_port qdel(output_port) @@ -229,6 +228,8 @@ SStgui.update_uis(parent) return null //explicitly set the port to null if used like this: `port = remove_output_port(port)` +// VOIDCREW EDIT: circuits provides chemistry trigger cleanup and power hooks; implementation in voidcrew/edits/modules/wiremod/core/component.dm. + /** * Called whenever an input is received from one of the ports. * @@ -237,7 +238,6 @@ * * port - Can be null. The port that sent the input * * return_values - Only defined if the component is receiving an input due to instant execution. Contains the values to be returned once execution has stopped. */ -// VOIDCREW EDIT END /obj/item/circuit_component/proc/trigger_component(datum/port/input/port, list/return_values) SHOULD_NOT_SLEEP(TRUE) pre_input_received(port) @@ -442,4 +442,4 @@ /obj/item/circuit_component/proc/send_ntnet_data(datum/port/input/port, key, signal_type = COMSIG_GLOB_CIRCUIT_NTNET_DATA_SENT) // Voidcrew: the sender rides along so receivers can scope the broadcast to one ship. // See on_same_ship_network() in voidcrew/modules/circuits/ntnet_ship_scope.dm. - SEND_GLOBAL_SIGNAL(signal_type, list("data" = port.value, "enc_key" = key, "port" = WEAKREF(port), "sender" = WEAKREF(src))) + SEND_GLOBAL_SIGNAL(signal_type, list("data" = port.value, "enc_key" = key, "port" = WEAKREF(port), "sender" = WEAKREF(src))) // VOIDCREW EDIT: circuits includes the sender in ship-scoped NTNet broadcasts. diff --git a/code/modules/wiremod/core/integrated_circuit.dm b/code/modules/wiremod/core/integrated_circuit.dm index 0245b3f762e..6817971b502 100644 --- a/code/modules/wiremod/core/integrated_circuit.dm +++ b/code/modules/wiremod/core/integrated_circuit.dm @@ -290,10 +290,8 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit) to_add.register_shell(shell) return TRUE -//VOIDCREW EDIT ADDITION: hard per-board component restrictions. -//Overridden rather than driven by a list var so a module can express "no subtype of X" -//without core having to know the module's type paths. Default is "everything allowed", -//which is the historic behaviour for every stock board. +// VOIDCREW EDIT: circuits provides per-board component restrictions; implementation in voidcrew/edits/modules/wiremod/core/integrated_circuit.dm. + /** * Adds a component to the circuitboard through a manual action. */ diff --git a/code/modules/wiremod/core/port.dm b/code/modules/wiremod/core/port.dm index 79b54aee775..0bc83b73124 100644 --- a/code/modules/wiremod/core/port.dm +++ b/code/modules/wiremod/core/port.dm @@ -123,14 +123,6 @@ * Sends a signal whenever the output value is changed */ /datum/port/output - //VOIDCREW EDIT ADDITION: singular outputs, for the chemistry circuits. - //VOIDCREW EDIT END - -//VOIDCREW EDIT ADDITION: an output only one input may connect to. -//The chemistry components move a *quantity* of reagent down a wire rather than a -//readable value, so fanning one output into two inputs would silently duplicate the -//payload. Capping the fan-out at one makes that impossible to wire up in the first place. -//VOIDCREW EDIT END /** * Disconnects a port from all other ports. @@ -195,7 +187,7 @@ /datum/port/input/proc/connect(datum/port/output/output) if(output in connected_ports) return - //VOIDCREW EDIT ADDITION: refuse the connection if the output is already at its fan-out cap. + //VOIDCREW EDIT ADDITION START: circuits - refuse the connection if the output is already at its fan-out cap. if(output.connected_inputs >= output.max_inputs) return output.connected_inputs++ diff --git a/code/modules/wiremod/dcs_components/component_add_port.dm b/code/modules/wiremod/dcs_components/component_add_port.dm index d6503215963..5db67ae5026 100644 --- a/code/modules/wiremod/dcs_components/component_add_port.dm +++ b/code/modules/wiremod/dcs_components/component_add_port.dm @@ -12,7 +12,7 @@ var/port_type = PORT_TYPE_ANY /// Whether we are adding output ports or not var/is_output = FALSE - //VOIDCREW EDIT ADDITION: whether the output ports we add are /datum/port/output/singular. + //VOIDCREW EDIT ADDITION START: circuits - whether the output ports we add are /datum/port/output/singular. //Only meaningful alongside is_output. See /datum/port/output/singular for why. //VOIDCREW EDIT END /// The prefix of the new ports diff --git a/tgstation.dme b/tgstation.dme index fdfeed6725e..22c33b7caa9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -32,7 +32,8 @@ #include "code\__DEFINES\_helpers.dm" #include "code\__DEFINES\_protect.dm" #include "code\__DEFINES\_tick.dm" -#include "voidcrew\_DEFINES\modular_hooks.dm" +#include "voidcrew\_DEFINES\core_integration.dm" // VOIDCREW EDIT: shared hooks must precede upstream macro use. +#include "voidcrew\_DEFINES\modular_hooks.dm" // VOIDCREW EDIT: shared hooks must precede upstream macro use. #include "code\__DEFINES\access.dm" #include "code\__DEFINES\achievements.dm" #include "code\__DEFINES\acid.dm" @@ -525,7 +526,6 @@ #include "code\__HELPERS\logging\transport.dm" #include "code\__HELPERS\logging\ui.dm" #include "code\__HELPERS\logging\virus.dm" -#include "voidcrew\modules\worldgen_logging\worldgen.dm" #include "code\__HELPERS\paths\jps.dm" #include "code\__HELPERS\paths\path.dm" #include "code\__HELPERS\paths\sssp.dm" @@ -6099,9 +6099,6 @@ #include "code\modules\research\xenobiology\vatgrowing\samples\viruses\_virus.dm" #include "code\modules\security_levels\keycard_authentication.dm" #include "code\modules\security_levels\security_level_datums.dm" -#include "voidcrew\modules\ship_upgrades\ship_catalog_ui.dm" -#include "code\modules\ship_purchase\ship_economy_database.dm" -#include "code\modules\ship_purchase\transaction_helpers.dm" #include "code\modules\shuttle\shuttle.dm" #include "code\modules\shuttle\misc\manipulator.dm" #include "code\modules\shuttle\misc\medisim.dm" @@ -6670,8 +6667,8 @@ #include "code\modules\zombie\organs.dm" #include "interface\interface.dm" #include "interface\menu.dm" -#include "interface\stylesheet.dm" #include "interface\skin.dmf" +#include "interface\stylesheet.dm" #include "interface\fonts\fonts_datum.dm" #include "interface\fonts\grand_9k.dm" #include "interface\fonts\pixellari.dm" @@ -6758,6 +6755,7 @@ #include "voidcrew\area\lich.dm" #include "voidcrew\area\megafauna_ban.dm" #include "voidcrew\area\ship_areas.dm" +#include "voidcrew\controllers\configuration\new_round_alert.dm" #include "voidcrew\controllers\subsystem\idle_npc_wakeup.dm" #include "voidcrew\controllers\subsystem\instance_census.dm" #include "voidcrew\controllers\subsystem\planet_mobs.dm" @@ -6770,9 +6768,9 @@ #include "voidcrew\datums\mapgen\BeachGenerator.dm" #include "voidcrew\datums\mapgen\LavaGenerator.dm" #include "voidcrew\datums\mapgen\planet_anomalies.dm" -#include "voidcrew\datums\mapgen\PlanetGenerator.dm" #include "voidcrew\datums\mapgen\planet_rivers.dm" #include "voidcrew\datums\mapgen\planet_settings.dm" +#include "voidcrew\datums\mapgen\PlanetGenerator.dm" #include "voidcrew\datums\mapgen\SnowGenerator.dm" #include "voidcrew\datums\mapgen\biomes\_biome.dm" #include "voidcrew\datums\mapgen\biomes\beach_biomes.dm" @@ -6805,30 +6803,36 @@ #include "voidcrew\datums\ruins\space.dm" #include "voidcrew\datums\ruins\wasteland.dm" #include "voidcrew\datums\votes\transfer_vote.dm" -#include "voidcrew\edits\modules\research\designs\machine_designs.dm" -#include "voidcrew\edits\modules\research\designs\comp_board_designs.dm" -#include "voidcrew\edits\modules\wiremod\dcs_components\component_add_port.dm" -#include "voidcrew\edits\modules\wiremod\core\port.dm" -#include "voidcrew\edits\modules\mob\mob_defines.dm" -#include "voidcrew\edits\modules\mob\living\basic\trooper\trooper.dm" -#include "voidcrew\edits\modules\logging\log_holder.dm" -#include "voidcrew\edits\modules\food_and_drinks\machinery\smartfridge.dm" -#include "voidcrew\edits\modules\error_handler\error_viewer.dm" -#include "voidcrew\edits\modules\client\client_defines.dm" -#include "voidcrew\edits\game\objects\structures\crates_lockers\crates.dm" -#include "voidcrew\edits\game\machinery\computer\crew.dm" -#include "voidcrew\edits\datums\weather\weather_types\snow_storm.dm" -#include "voidcrew\edits\datums\weather\weather_types\rain_storm.dm" -#include "voidcrew\edits\datums\alarm.dm" -#include "voidcrew\edits\controllers\subsystem\mapping.dm" -#include "voidcrew\edits\_onclick\hud\parallax\parallax.dm" +#include "voidcrew\edits\config.dm" +#include "voidcrew\edits\gps.dm" +#include "voidcrew\edits\hyperspace_overboard.dm" +#include "voidcrew\edits\id_card.dm" +#include "voidcrew\edits\jobs.dm" +#include "voidcrew\edits\keybindings.dm" +#include "voidcrew\edits\lighting.dm" +#include "voidcrew\edits\map_config.dm" +#include "voidcrew\edits\outpost_door_access.dm" +#include "voidcrew\edits\planetary_shared_air.dm" +#include "voidcrew\edits\preferences.dm" +#include "voidcrew\edits\screentip_hover.dm" +#include "voidcrew\edits\ship_access.dm" +#include "voidcrew\edits\ship_silicon.dm" +#include "voidcrew\edits\turf.dm" #include "voidcrew\edits\__HELPERS\_lists.dm" +#include "voidcrew\edits\_onclick\ranged_hand.dm" +#include "voidcrew\edits\_onclick\hud\hud.dm" +#include "voidcrew\edits\_onclick\hud\screen_extensions.dm" #include "voidcrew\edits\_onclick\hud\screen_objects.dm" +#include "voidcrew\edits\_onclick\hud\parallax\parallax.dm" +#include "voidcrew\edits\code\modules\cargo\supplypod_containment.dm" +#include "voidcrew\edits\components\tether_pulling.dm" #include "voidcrew\edits\controllers\subsystem\air.dm" -#include "voidcrew\edits\controllers\subsystem\networks\bitrunning.dm" +#include "voidcrew\edits\controllers\subsystem\mapping.dm" #include "voidcrew\edits\controllers\subsystem\shuttle.dm" #include "voidcrew\edits\controllers\subsystem\time_track.dm" #include "voidcrew\edits\controllers\subsystem\weather.dm" +#include "voidcrew\edits\controllers\subsystem\networks\bitrunning.dm" +#include "voidcrew\edits\datums\alarm.dm" #include "voidcrew\edits\datums\actions\mobs\charge.dm" #include "voidcrew\edits\datums\components\gps.dm" #include "voidcrew\edits\datums\components\overlay_lighting.dm" @@ -6837,46 +6841,77 @@ #include "voidcrew\edits\datums\elements\decals\_decal.dm" #include "voidcrew\edits\datums\mapgen\CaveGenerator.dm" #include "voidcrew\edits\datums\weather\weather.dm" +#include "voidcrew\edits\datums\weather\weather_types\rain_storm.dm" #include "voidcrew\edits\datums\weather\weather_types\sand_storm.dm" -#include "voidcrew\edits\game\area\areas.dm" +#include "voidcrew\edits\datums\weather\weather_types\snow_storm.dm" +#include "voidcrew\edits\error_handler\runtime_state.dm" #include "voidcrew\edits\game\movable_luminosity.dm" +#include "voidcrew\edits\game\area\areas.dm" +#include "voidcrew\edits\game\machinery\computer\crew.dm" #include "voidcrew\edits\game\objects\items\rcd\RCD.dm" #include "voidcrew\edits\game\objects\items\rcd\RPD.dm" #include "voidcrew\edits\game\objects\items\storage\bags.dm" #include "voidcrew\edits\game\objects\items\tools\painter\decal_painter.dm" #include "voidcrew\edits\game\objects\structures\mystery_box.dm" +#include "voidcrew\edits\game\objects\structures\crates_lockers\crates.dm" #include "voidcrew\edits\game\turfs\open\chasm.dm" #include "voidcrew\edits\game\turfs\open\grass.dm" #include "voidcrew\edits\game\turfs\open\water.dm" +#include "voidcrew\edits\machinery\camera.dm" +#include "voidcrew\edits\machinery\crew_monitor.dm" +#include "voidcrew\edits\machinery\firedoor_shuttle.dm" +#include "voidcrew\edits\machinery\light_switch.dm" +#include "voidcrew\edits\machinery\materials_market.dm" +#include "voidcrew\edits\machinery\nebula_shielding.dm" +#include "voidcrew\edits\machinery\plumbing_shuttle_move.dm" +#include "voidcrew\edits\machinery\power.dm" +#include "voidcrew\edits\machinery\pressure_tank.dm" +#include "voidcrew\edits\machinery\silicon_ship_systems.dm" +#include "voidcrew\edits\mobs\ghost_respawn.dm" +#include "voidcrew\edits\mobs\green_zone_respawn.dm" +#include "voidcrew\edits\mobs\megafauna_logging.dm" +#include "voidcrew\edits\mobs\new_player.dm" +#include "voidcrew\edits\mobs\plasmaman.dm" +#include "voidcrew\edits\mobs\respawn_timer.dm" +#include "voidcrew\edits\mobs\ruin_icons.dm" +#include "voidcrew\edits\mobs\ship_join_menu.dm" #include "voidcrew\edits\modules\antagonists\abductor\equipment\glands\heal.dm" #include "voidcrew\edits\modules\antagonists\heretic\magic\rust_construction.dm" #include "voidcrew\edits\modules\asset_cache\assets\rcd.dm" #include "voidcrew\edits\modules\atmospherics\machinery\datum_pipeline.dm" #include "voidcrew\edits\modules\awaymissions\signpost.dm" +#include "voidcrew\edits\modules\cargo\materials_market.dm" +#include "voidcrew\edits\modules\cargo\order.dm" #include "voidcrew\edits\modules\cargo\exports\large_objects.dm" #include "voidcrew\edits\modules\cargo\exports\manifest.dm" #include "voidcrew\edits\modules\cargo\exports\materials.dm" -#include "voidcrew\edits\modules\cargo\materials_market.dm" -#include "voidcrew\edits\modules\cargo\order.dm" #include "voidcrew\edits\modules\cargo\packs\_packs.dm" +#include "voidcrew\edits\modules\client\client_defines.dm" #include "voidcrew\edits\modules\client\preferences.dm" +#include "voidcrew\edits\modules\error_handler\error_viewer.dm" #include "voidcrew\edits\modules\experisci\experiment\types\scanning_fish.dm" #include "voidcrew\edits\modules\fishing\fishing_equipment.dm" #include "voidcrew\edits\modules\fishing\fishing_rod.dm" +#include "voidcrew\edits\modules\food_and_drinks\machinery\smartfridge.dm" +#include "voidcrew\edits\modules\logging\log_holder.dm" #include "voidcrew\edits\modules\mapping\ruins.dm" #include "voidcrew\edits\modules\mapping\space_management\space_reservation.dm" #include "voidcrew\edits\modules\mining\machine_redemption.dm" +#include "voidcrew\edits\modules\mob\mob.dm" +#include "voidcrew\edits\modules\mob\mob_defines.dm" #include "voidcrew\edits\modules\mob\living\basic\lavaland\legion\spawn_legions.dm" +#include "voidcrew\edits\modules\mob\living\basic\trooper\trooper.dm" #include "voidcrew\edits\modules\mob\living\carbon\inventory.dm" -#include "voidcrew\edits\modules\mob\mob.dm" #include "voidcrew\edits\modules\mod\modules\modules_supply.dm" #include "voidcrew\edits\modules\modular_computers\file_system\programs\budgetordering.dm" #include "voidcrew\edits\modules\power\turbine\turbine.dm" #include "voidcrew\edits\modules\projectiles\boxes_magazines\_box_magazine.dm" #include "voidcrew\edits\modules\research\designs.dm" +#include "voidcrew\edits\modules\research\designs\comp_board_designs.dm" +#include "voidcrew\edits\modules\research\designs\machine_designs.dm" +#include "voidcrew\edits\modules\shuttle\shuttle.dm" #include "voidcrew\edits\modules\shuttle\mobile_port\shuttle_move.dm" #include "voidcrew\edits\modules\shuttle\mobile_port\shuttle_move_callbacks.dm" -#include "voidcrew\edits\modules\shuttle\shuttle.dm" #include "voidcrew\edits\modules\shuttle\shuttle_consoles\navigation_computer.dm" #include "voidcrew\edits\modules\spells\spell_types\jaunt\bloodcrawl.dm" #include "voidcrew\edits\modules\spells\spell_types\jaunt\ethereal_jaunt.dm" @@ -6884,40 +6919,8 @@ #include "voidcrew\edits\modules\vehicles\mecha\mech_fabricator.dm" #include "voidcrew\edits\modules\wiremod\core\component.dm" #include "voidcrew\edits\modules\wiremod\core\integrated_circuit.dm" -#include "voidcrew\edits\config.dm" -#include "voidcrew\edits\gps.dm" -#include "voidcrew\edits\hyperspace_overboard.dm" -#include "voidcrew\edits\id_card.dm" -#include "voidcrew\edits\jobs.dm" -#include "voidcrew\edits\machinery\light_switch.dm" -#include "voidcrew\edits\ship_silicon.dm" -#include "voidcrew\edits\keybindings.dm" -#include "voidcrew\edits\lighting.dm" -#include "voidcrew\edits\map_config.dm" -#include "voidcrew\edits\outpost_door_access.dm" -#include "voidcrew\edits\planetary_shared_air.dm" -#include "voidcrew\edits\preferences.dm" -#include "voidcrew\edits\ship_access.dm" -#include "voidcrew\edits\turf.dm" -#include "voidcrew\edits\_onclick\ranged_hand.dm" -#include "voidcrew\edits\_onclick\hud\hud.dm" -#include "voidcrew\edits\code\modules\cargo\supplypod_containment.dm" -#include "voidcrew\edits\machinery\camera.dm" -#include "voidcrew\edits\machinery\crew_monitor.dm" -#include "voidcrew\edits\machinery\light_switch.dm" -#include "voidcrew\edits\machinery\materials_market.dm" -#include "voidcrew\edits\machinery\nebula_shielding.dm" -#include "voidcrew\edits\machinery\plumbing_shuttle_move.dm" -#include "voidcrew\edits\machinery\power.dm" -#include "voidcrew\edits\machinery\pressure_tank.dm" -#include "voidcrew\edits\machinery\silicon_ship_systems.dm" -#include "voidcrew\edits\mobs\ghost_respawn.dm" -#include "voidcrew\edits\mobs\green_zone_respawn.dm" -#include "voidcrew\edits\mobs\new_player.dm" -#include "voidcrew\edits\mobs\plasmaman.dm" -#include "voidcrew\edits\mobs\respawn_timer.dm" -#include "voidcrew\edits\mobs\ruin_icons.dm" -#include "voidcrew\edits\mobs\ship_join_menu.dm" +#include "voidcrew\edits\modules\wiremod\core\port.dm" +#include "voidcrew\edits\modules\wiremod\dcs_components\component_add_port.dm" #include "voidcrew\edits\objects\items\extinguisher.dm" #include "voidcrew\edits\objects\items\kinetic_accelerator_modkits.dm" #include "voidcrew\edits\objects\items\posibrain.dm" @@ -6945,10 +6948,8 @@ #include "voidcrew\mapping\rivers.dm" #include "voidcrew\mapping\rotated_template_load.dm" #include "voidcrew\mapping\docking_port\_docking_port.dm" -#include "voidcrew\mapping\rotated_template_load.dm" #include "voidcrew\mapping\ship_areas\hiryu_class_carrier.dm" #include "voidcrew\mapping\ship_areas\nanobead.dm" -#include "voidcrew\mapping\ship_crew\nanobead.dm" #include "voidcrew\mapping\ship_areas\squab.dm" #include "voidcrew\mapping\ship_crew\bogatyr.dm" #include "voidcrew\mapping\ship_crew\hiryu_class_carrier.dm" @@ -7001,16 +7002,6 @@ #include "voidcrew\mapping\shuttles\syndicate\geneva.dm" #include "voidcrew\mapping\shuttles\syndicate\hyena.dm" #include "voidcrew\mapping\spawners\nanites.dm" -#include "voidcrew\modules\player_outposts\outpost_cargo_dock.dm" -#include "voidcrew\modules\player_outposts\outpost_upgrades.dm" -#include "voidcrew\modules\metrics\combat_metrics.dm" -#include "voidcrew\modules\metrics\economy_metrics.dm" -#include "voidcrew\modules\metrics\metrics_helpers.dm" -#include "voidcrew\modules\metrics\metrics_subsystem.dm" -#include "voidcrew\modules\metrics\mission_metrics.dm" -#include "voidcrew\modules\metrics\research_metrics.dm" -#include "voidcrew\modules\metrics\ship_metrics.dm" -#include "voidcrew\modules\throwing\diagnostics.dm" #include "voidcrew\modules\admin\feature_testing.dm" #include "voidcrew\modules\admin\overmap_management.dm" #include "voidcrew\modules\admin\shuttle_deletion.dm" @@ -7117,8 +7108,8 @@ #include "voidcrew\modules\chemistry\recipes.dm" #include "voidcrew\modules\circuits\ntnet_ship_scope.dm" #include "voidcrew\modules\circuits\usb_cable_shuttle_move.dm" -#include "voidcrew\modules\cloning\cloning_vat.dm" #include "voidcrew\modules\cloning\clone_wake.dm" +#include "voidcrew\modules\cloning\cloning_vat.dm" #include "voidcrew\modules\clothing\glasses\sunglasses.dm" #include "voidcrew\modules\clothing\gloves\insulated.dm" #include "voidcrew\modules\clothing\head\helmet.dm" @@ -7247,6 +7238,15 @@ #include "voidcrew\modules\loot\uniques\research.dm" #include "voidcrew\modules\loot\uniques\syndicate.dm" #include "voidcrew\modules\loot\uniques\wardrobe.dm" +#include "voidcrew\modules\metrics\combat_metrics.dm" +#include "voidcrew\modules\metrics\economy_metrics.dm" +#include "voidcrew\modules\metrics\metrics_helpers.dm" +#include "voidcrew\modules\metrics\metrics_subsystem.dm" +#include "voidcrew\modules\metrics\mission_metrics.dm" +#include "voidcrew\modules\metrics\research_metrics.dm" +#include "voidcrew\modules\metrics\ship_metrics.dm" +#include "voidcrew\modules\metrics\structured_logging_fallback.dm" +#include "voidcrew\modules\mining\ore_redemption.dm" #include "voidcrew\modules\mining\edits\fulton.dm" #include "voidcrew\modules\mining\edits\order_consumables.dm" #include "voidcrew\modules\mining\equipment\explorer_gear.dm" @@ -7254,7 +7254,6 @@ #include "voidcrew\modules\mining\lavaland\edits\machine_redemption.dm" #include "voidcrew\modules\mining\lavaland\edits\mining_order.dm" #include "voidcrew\modules\mining\lavaland\edits\necropolis_chests.dm" -#include "voidcrew\modules\mining\ore_redemption.dm" #include "voidcrew\modules\missions\_missions.dm" #include "voidcrew\modules\missions\design.dm" #include "voidcrew\modules\missions\gps_link.dm" @@ -7419,20 +7418,38 @@ #include "voidcrew\modules\overmap\code\modules\overmap\zones\zone_teleport.dm" #include "voidcrew\modules\overmap\code\modules\overmap\zones\zone_weather.dm" #include "voidcrew\modules\paperwork\faxes.dm" -#include "voidcrew\modules\player_outposts\outpost_adverts.dm" #include "voidcrew\modules\player_outposts\outpost_admin.dm" #include "voidcrew\modules\player_outposts\outpost_admin_bays.dm" #include "voidcrew\modules\player_outposts\outpost_admin_checkpoints.dm" #include "voidcrew\modules\player_outposts\outpost_admin_prison.dm" +#include "voidcrew\modules\player_outposts\outpost_adverts.dm" #include "voidcrew\modules\player_outposts\outpost_ambient_work.dm" +#include "voidcrew\modules\player_outposts\outpost_autosurgeon.dm" #include "voidcrew\modules\player_outposts\outpost_cargo_dock.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_build_effects.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_construction.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_loading.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_machinery.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_rebuild.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_snapshot.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoint_yard_audio.dm" +#include "voidcrew\modules\player_outposts\outpost_checkpoints.dm" +#include "voidcrew\modules\player_outposts\outpost_cloning_bay.dm" #include "voidcrew\modules\player_outposts\outpost_construction.dm" #include "voidcrew\modules\player_outposts\outpost_deed.dm" +#include "voidcrew\modules\player_outposts\outpost_dock_fees.dm" #include "voidcrew\modules\player_outposts\outpost_door_access.dm" #include "voidcrew\modules\player_outposts\outpost_elevator_placement.dm" +#include "voidcrew\modules\player_outposts\outpost_freight.dm" +#include "voidcrew\modules\player_outposts\outpost_home_management.dm" #include "voidcrew\modules\player_outposts\outpost_level_layout.dm" #include "voidcrew\modules\player_outposts\outpost_management.dm" #include "voidcrew\modules\player_outposts\outpost_management_ui.dm" +#include "voidcrew\modules\player_outposts\outpost_market.dm" +#include "voidcrew\modules\player_outposts\outpost_medical_lab.dm" +#include "voidcrew\modules\player_outposts\outpost_medical_lab_machines.dm" +#include "voidcrew\modules\player_outposts\outpost_network.dm" +#include "voidcrew\modules\player_outposts\outpost_network_ui.dm" #include "voidcrew\modules\player_outposts\outpost_npc_looks.dm" #include "voidcrew\modules\player_outposts\outpost_prison.dm" #include "voidcrew\modules\player_outposts\outpost_prison_ambience.dm" @@ -7474,44 +7491,26 @@ #include "voidcrew\modules\player_outposts\outpost_prison_warden.dm" #include "voidcrew\modules\player_outposts\outpost_prison_warden_tools.dm" #include "voidcrew\modules\player_outposts\outpost_prison_wing_events.dm" -#include "voidcrew\modules\player_outposts\outpost_shells.dm" -#include "voidcrew\modules\player_outposts\outpost_ship_bay.dm" -#include "voidcrew\modules\player_outposts\outpost_upgrades.dm" -#include "voidcrew\modules\player_outposts\outpost_yard_droids.dm" -#include "voidcrew\modules\player_outposts\player_outpost.dm" -#include "voidcrew\modules\player_outposts\outpost_services.dm" -#include "voidcrew\modules\player_outposts\outpost_home_management.dm" -#include "voidcrew\modules\player_outposts\outpost_freight.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoints.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_machinery.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_rebuild.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_snapshot.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_yard_audio.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_loading.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_build_effects.dm" -#include "voidcrew\modules\player_outposts\outpost_checkpoint_construction.dm" -#include "voidcrew\modules\player_outposts\outpost_ship_orders.dm" -#include "voidcrew\modules\player_outposts\outpost_research.dm" #include "voidcrew\modules\player_outposts\outpost_relay.dm" +#include "voidcrew\modules\player_outposts\outpost_research.dm" #include "voidcrew\modules\player_outposts\outpost_residents.dm" #include "voidcrew\modules\player_outposts\outpost_room_contracts.dm" #include "voidcrew\modules\player_outposts\outpost_room_power.dm" -#include "voidcrew\modules\player_outposts\outpost_autosurgeon.dm" -#include "voidcrew\modules\player_outposts\outpost_cloning_bay.dm" -#include "voidcrew\modules\player_outposts\outpost_dock_fees.dm" -#include "voidcrew\modules\player_outposts\outpost_market.dm" -#include "voidcrew\modules\player_outposts\outpost_medical_lab.dm" -#include "voidcrew\modules\player_outposts\outpost_medical_lab_machines.dm" -#include "voidcrew\modules\player_outposts\outpost_network.dm" -#include "voidcrew\modules\player_outposts\outpost_network_ui.dm" #include "voidcrew\modules\player_outposts\outpost_service_doors.dm" #include "voidcrew\modules\player_outposts\outpost_service_rooms.dm" +#include "voidcrew\modules\player_outposts\outpost_services.dm" +#include "voidcrew\modules\player_outposts\outpost_shells.dm" +#include "voidcrew\modules\player_outposts\outpost_ship_bay.dm" +#include "voidcrew\modules\player_outposts\outpost_ship_orders.dm" #include "voidcrew\modules\player_outposts\outpost_shop.dm" #include "voidcrew\modules\player_outposts\outpost_shop_stock.dm" #include "voidcrew\modules\player_outposts\outpost_storage.dm" #include "voidcrew\modules\player_outposts\outpost_style_turfs.dm" #include "voidcrew\modules\player_outposts\outpost_styles.dm" #include "voidcrew\modules\player_outposts\outpost_teleporter.dm" +#include "voidcrew\modules\player_outposts\outpost_upgrades.dm" +#include "voidcrew\modules\player_outposts\outpost_yard_droids.dm" +#include "voidcrew\modules\player_outposts\player_outpost.dm" #include "voidcrew\modules\power\port_gen.dm" #include "voidcrew\modules\preferences\ship_categories_middleware.dm" #include "voidcrew\modules\reagents\chemistry\reagents\medicine_reagents.dm" @@ -7519,7 +7518,6 @@ #include "voidcrew\modules\research\research_boards.dm" #include "voidcrew\modules\research\research_notes.dm" #include "voidcrew\modules\research\server.dm" -#include "voidcrew\modules\research\edits\_relay_consumers.dm" #include "voidcrew\modules\research\survey_scanner.dm" #include "voidcrew\modules\research\techweb_nodes.dm" #include "voidcrew\modules\research\designs\ammo_catalogue.dm" @@ -7532,6 +7530,7 @@ #include "voidcrew\modules\research\edits\_experiments.dm" #include "voidcrew\modules\research\edits\_production.dm" #include "voidcrew\modules\research\edits\_rd_consoles.dm" +#include "voidcrew\modules\research\edits\_relay_consumers.dm" #include "voidcrew\modules\research\edits\_techweb.dm" #include "voidcrew\modules\research\edits\_techweb_node.dm" #include "voidcrew\modules\research\edits\component_printer.dm" @@ -7578,11 +7577,15 @@ #include "voidcrew\modules\ship_combat\electronic_warfare\ew_payloads_heavy.dm" #include "voidcrew\modules\ship_combat\electronic_warfare\ew_payloads_utility.dm" #include "voidcrew\modules\ship_combat\electronic_warfare\ew_suite.dm" +#include "voidcrew\modules\ship_purchase\ship_economy_database.dm" +#include "voidcrew\modules\ship_purchase\transaction_helpers.dm" #include "voidcrew\modules\ship_upgrades\_ship_upgrades.dm" #include "voidcrew\modules\ship_upgrades\admin_verbs.dm" #include "voidcrew\modules\ship_upgrades\modular_map_root_ship.dm" +#include "voidcrew\modules\ship_upgrades\ship_catalog_ui.dm" #include "voidcrew\modules\ship_upgrades\ship_preview_assets.dm" #include "voidcrew\modules\ship_upgrades\ship_upgrade_selector.dm" +#include "voidcrew\modules\ship_upgrades\shuttle_manipulator.dm" #include "voidcrew\modules\ship_upgrades\ships\delta.dm" #include "voidcrew\modules\ship_upgrades\ships\goon.dm" #include "voidcrew\modules\ship_upgrades\ships\hiryu_class_carrier.dm" @@ -7597,17 +7600,18 @@ #include "voidcrew\modules\shuttle\boards.dm" #include "voidcrew\modules\shuttle\design.dm" #include "voidcrew\modules\shuttle\emergency.dm" +#include "voidcrew\modules\shuttle\shuttle_move_helpers.dm" #include "voidcrew\modules\shuttle\construction\construction_actions.dm" -#include "voidcrew\modules\shuttle\construction\construction_console.dm" #include "voidcrew\modules\shuttle\construction\construction_areas.dm" +#include "voidcrew\modules\shuttle\construction\construction_console.dm" #include "voidcrew\modules\shuttle\construction\construction_decoration.dm" #include "voidcrew\modules\shuttle\construction\construction_drone.dm" #include "voidcrew\modules\shuttle\construction\construction_queue.dm" +#include "voidcrew\modules\shuttle\construction\construction_upgrades.dm" +#include "voidcrew\modules\shuttle\construction\hull_survey.dm" #include "voidcrew\modules\shuttle\construction\repair_damage.dm" #include "voidcrew\modules\shuttle\construction\repair_drone_parts.dm" #include "voidcrew\modules\shuttle\construction\repair_drones.dm" -#include "voidcrew\modules\shuttle\construction\construction_upgrades.dm" -#include "voidcrew\modules\shuttle\construction\hull_survey.dm" #include "voidcrew\modules\shuttle\engine\electric.dm" #include "voidcrew\modules\shuttle\engine\fuel.dm" #include "voidcrew\modules\shuttle\engine\gas_harvest.dm" @@ -7631,6 +7635,8 @@ #include "voidcrew\modules\storage\wall_locker.dm" #include "voidcrew\modules\surgery\experimental_dissection.dm" #include "voidcrew\modules\teams\_team.dm" +#include "voidcrew\modules\throwing\diagnostics.dm" +#include "voidcrew\modules\trade\bag_rift_protection.dm" #include "voidcrew\modules\trade\blueprint_imprinter.dm" #include "voidcrew\modules\trade\modsuit_bench.dm" #include "voidcrew\modules\trade\outpost.dm" @@ -7687,6 +7693,7 @@ #include "voidcrew\modules\weapons_bench\guns\laser_carbine.dm" #include "voidcrew\modules\weapons_bench\guns\sniper.dm" #include "voidcrew\modules\weapons_bench\guns\wt550.dm" +#include "voidcrew\modules\worldgen_logging\worldgen.dm" #include "voidcrew\objects\items\blueprints.dm" #include "voidcrew\objects\items\cards_ids.dm" #include "voidcrew\objects\items\trash.dm" diff --git a/tgui/packages/tgui/drag.ts b/tgui/packages/tgui/drag.ts index b7a5602b0d0..ac3ccd9e753 100644 --- a/tgui/packages/tgui/drag.ts +++ b/tgui/packages/tgui/drag.ts @@ -16,6 +16,7 @@ const pixelRatio = window.devicePixelRatio ?? 1; let windowKey = Byond.windowId; let dragging = false; let resizing = false; +// VOIDCREW EDIT: preferences resynchronizes native window coordinates before dragging. let screenOffsetSynced = false; let screenOffset: [number, number] = [0, 0]; let screenOffsetPromise: Promise<[number, number]>; @@ -222,25 +223,31 @@ const constraintPosition = ( export const dragStartHandler = (event) => { logger.log('drag start'); dragging = true; + // VOIDCREW EDIT START: preferences resynchronizes native window coordinates before dragging. screenOffsetSynced = false; const windowPosition = getWindowPosition(); + // VOIDCREW EDIT END dragPointOffset = vecSubtract( [event.screenX * pixelRatio, event.screenY * pixelRatio], + // VOIDCREW EDIT: preferences resynchronizes native window coordinates before dragging. windowPosition, ) as [number, number]; // screenOffset is measured once at startup and goes stale when the // window's monitor or DPI context changes; applying a stale offset on // the first winset flings the window to a screen edge. Re-measure it // on every grab, and hold the drag until the fresh value arrives. + // VOIDCREW EDIT START: preferences resynchronizes native window coordinates before dragging. Byond.winget(Byond.windowId, 'pos').then((pos) => { screenOffset = [pos.x - windowPosition[0], pos.y - windowPosition[1]]; screenOffsetSynced = true; dragMoveHandler(event); }); + // VOIDCREW EDIT END // Focus click target (event.target as HTMLElement)?.focus(); document.addEventListener('mousemove', dragMoveHandler); document.addEventListener('mouseup', dragEndHandler); +// VOIDCREW EDIT REMOVAL: preferences resynchronizes native window coordinates before dragging. }; // End dragging the window @@ -255,6 +262,7 @@ const dragEndHandler = (event) => { // Move the window while dragging const dragMoveHandler = (event: MouseEvent) => { + // VOIDCREW EDIT: preferences resynchronizes native window coordinates before dragging. if (!dragging || !screenOffsetSynced) { return; } diff --git a/tgui/packages/tgui/interfaces/BankMachine.tsx b/tgui/packages/tgui/interfaces/BankMachine.tsx index 5fd8b6fd553..3acc62615a6 100644 --- a/tgui/packages/tgui/interfaces/BankMachine.tsx +++ b/tgui/packages/tgui/interfaces/BankMachine.tsx @@ -1,10 +1,12 @@ -// VOIDCREW EDIT START - Outpost treasury transfers and transaction history. +// VOIDCREW EDIT: player_outposts supports claim treasury deposits and withdrawals. import { useState } from 'react'; import { AnimatedNumber, + // VOIDCREW EDIT: player_outposts supports claim treasury deposits and withdrawals. Box, Button, + // VOIDCREW EDIT: player_outposts supports claim treasury deposits and withdrawals. Input, LabeledList, NoticeBox, @@ -20,29 +22,38 @@ type Data = { current_balance: number; siphoning: BooleanLike; station_name: string; + // VOIDCREW EDIT START: player_outposts supports claim treasury deposits and withdrawals. is_outpost?: BooleanLike; user_account?: string | null; can_withdraw?: BooleanLike; history?: { adjusted_money: number; reason: string }[]; + // VOIDCREW EDIT END }; export const BankMachine = (props) => { const { act, data } = useBackend(); const { current_balance, siphoning, station_name } = data; + // VOIDCREW EDIT START: player_outposts supports claim treasury deposits and withdrawals. const [amount, setAmount] = useState(''); const isOutpost = !!data.is_outpost; + // VOIDCREW EDIT END return ( + // VOIDCREW EDIT: player_outposts supports claim treasury deposits and withdrawals. + {/* VOIDCREW EDIT: player_outposts supports claim treasury deposits and withdrawals. */} + {/* VOIDCREW EDIT START: player_outposts supports claim treasury deposits and withdrawals. */} {isOutpost ? 'Claim treasury' : 'Authorized personnel only'} + {/* VOIDCREW EDIT END */}
{ onClick={() => act(siphoning ? 'halt' : 'siphon')} /> ) + // VOIDCREW EDIT END } > {
+ {/* VOIDCREW EDIT START: player_outposts supports claim treasury deposits and withdrawals. */} {!!isOutpost && (
@@ -96,8 +109,8 @@ export const BankMachine = (props) => { ))}
)} + {/* VOIDCREW EDIT END */}
); }; -// VOIDCREW EDIT END diff --git a/tgui/packages/tgui/interfaces/CameraConsole.tsx b/tgui/packages/tgui/interfaces/CameraConsole.tsx index 388c7f54228..4f5a64915eb 100644 --- a/tgui/packages/tgui/interfaces/CameraConsole.tsx +++ b/tgui/packages/tgui/interfaces/CameraConsole.tsx @@ -110,6 +110,7 @@ export const CameraContent = (props) => { const CameraSelector = (props) => { const { act, data } = useBackend(); const { searchText, setSearchText } = props; + // VOIDCREW EDIT: comms displays the active ship camera networks. const { activeCamera, networkNames = [] } = data; const cameras = selectCameras(data.cameras, searchText); diff --git a/tgui/packages/tgui/interfaces/ChemHeater.tsx b/tgui/packages/tgui/interfaces/ChemHeater.tsx index db6568bb542..4f74e127bdb 100644 --- a/tgui/packages/tgui/interfaces/ChemHeater.tsx +++ b/tgui/packages/tgui/interfaces/ChemHeater.tsx @@ -308,6 +308,7 @@ export const ChemHeater = (props) => { format={(value) => `${toFixed(value)} K`} /> )) || + // VOIDCREW EDIT: chemistry uses a client-compatible fallback glyph. '-'} diff --git a/tgui/packages/tgui/interfaces/CommunicationsConsole/Main.tsx b/tgui/packages/tgui/interfaces/CommunicationsConsole/Main.tsx index a5bfb2da15d..1cf295de8d3 100644 --- a/tgui/packages/tgui/interfaces/CommunicationsConsole/Main.tsx +++ b/tgui/packages/tgui/interfaces/CommunicationsConsole/Main.tsx @@ -17,6 +17,7 @@ export function PageMain(props) { canMakeAnnouncement, canMessageAssociates, canRecallShuttles, + // VOIDCREW EDIT REMOVAL: comms omits station self-destruct requests and coerces UI flags. canSendToSectors, canSetAlertLevel, canToggleEmergencyAccess, @@ -35,6 +36,7 @@ export function PageMain(props) { const [callingShuttle, setCallingShuttle] = useState(false); const [messagingAssociates, setMessagingAssociates] = useState(false); const [messagingSector, setMessagingSector] = useState(''); +// VOIDCREW EDIT REMOVAL: comms omits station self-destruct requests and coerces UI flags. const [newAlertLevel, setNewAlertLevel] = useState(''); const showAlertLevelConfirm = newAlertLevel && newAlertLevel !== alertLevel; @@ -177,6 +179,7 @@ export function PageMain(props) { )} + {/* VOIDCREW EDIT REMOVAL: comms omits station self-destruct requests and coerces UI flags. */} {!!emagged && !syndicate && ( - - - - - ); - })} - - - )} - - {/* Upgrade Slots */} - {slots && slots.length > 0 && ( -
- Select modules for each slot - - } - > - - {slots.map((slot) => ( - - - - ))} - -
- )} - - {(!slots || slots.length === 0) && (!has_themes || themes.length === 0) && ( - - No configuration options available for this ship. - - )} - - ); -}; - -/** - * Upgrade Slot Section component - * Shows available modules for a single upgrade slot - */ -const UpgradeSlotSection = ({ slot, selectedModuleId }) => { - const { act } = useBackend(); - - return ( -
- - {slot.modules.map((module) => { - const isSelected = selectedModuleId === module.id; - - return ( - - - - - - - - {module.name} - {module.is_default && ( - - (Default) - - )} - - - - - {module.desc} - - - - - - - - - - - - ); - })} - {slot.modules.length === 0 && ( - - - No modules available for this slot. - - - )} - -
- ); -}; +// VOIDCREW EDIT: ship_upgrades renders configuration from voidcrew_tgui/components/ModularShipConfig. diff --git a/tgui/packages/tgui/interfaces/StripMenu.tsx b/tgui/packages/tgui/interfaces/StripMenu.tsx index 66b13be8b81..d950f2a9fdb 100644 --- a/tgui/packages/tgui/interfaces/StripMenu.tsx +++ b/tgui/packages/tgui/interfaces/StripMenu.tsx @@ -260,6 +260,7 @@ type StripMenuData = { export const StripMenu = (props) => { const { act, data } = useBackend(); + // VOIDCREW EDIT: clothing types strip-menu positions as the flexible grid keys. const gridSpots = new Map(); for (const key of Object.keys(data.items)) { gridSpots.set(SLOTS[key].gridSpot, key); diff --git a/tgui/packages/tgui/interfaces/Techweb/nodes/TechNode.tsx b/tgui/packages/tgui/interfaces/Techweb/nodes/TechNode.tsx index c47565a7872..c221c44f264 100644 --- a/tgui/packages/tgui/interfaces/Techweb/nodes/TechNode.tsx +++ b/tgui/packages/tgui/interfaces/Techweb/nodes/TechNode.tsx @@ -207,6 +207,7 @@ export function TechNode(props: Props) { if (thisExp === null || thisExp === undefined) { return ; } + // VOIDCREW EDIT: research keys experiment rows by their stable node identifier. return ; })} @@ -222,6 +223,7 @@ export function TechNode(props: Props) { return ; } return ( + // VOIDCREW EDIT: research keys experiment rows by their stable node identifier. Provides a discount of {discount_experiments[k]} points to all diff --git a/tgui/packages/tgui/layouts/Window.tsx b/tgui/packages/tgui/layouts/Window.tsx index 8fccf51d038..45e3cfaa864 100644 --- a/tgui/packages/tgui/layouts/Window.tsx +++ b/tgui/packages/tgui/layouts/Window.tsx @@ -103,6 +103,7 @@ export const Window = (props: Props) => { logger.log('unmounting'); }; } + // VOIDCREW EDIT: preferences refreshes reopened native windows and coerces boolean UI flags. }, [isReadyToRender, width, height, scale, suspended, config.window.key]); const dispatch = globalStore.dispatch; @@ -132,8 +133,10 @@ export const Window = (props: Props) => {
{!suspended && children} + {/* VOIDCREW EDIT: preferences refreshes reopened native windows and coerces boolean UI flags. */} {!!showDimmer &&
}
+ {/* VOIDCREW EDIT: preferences refreshes reopened native windows and coerces boolean UI flags. */} {!!fancy && ( <>
{ + const { act } = useBackend(); + const { themes, has_themes, slots, selected_theme, selected_upgrades } = + modularData; + + return ( +
act('clear_ship_selections')} + /> + } + > + {/* Theme Selection */} + {has_themes && themes && themes.length > 0 && ( +
+ Choose ship variant + + } + > + + {themes.map((theme) => { + const isSelected = selected_theme === theme.id; + + return ( + + + + + + + + {theme.name} + {theme.is_default && ( + + (Default) + + )} + + + + + {theme.desc} + + + {theme.jobs && theme.jobs.length > 0 && ( + + + + {theme.jobs.map((job, idx) => ( + + {job.officer && ( + + )} + {job.slots}x {job.name} + + ))} + + + + )} + + + + + + + + + + ); + })} + +
+ )} + + {/* Upgrade Slots */} + {slots && slots.length > 0 && ( +
+ Select modules for each slot + + } + > + + {slots.map((slot) => ( + + + + ))} + +
+ )} + + {(!slots || slots.length === 0) && (!has_themes || themes.length === 0) && ( + + No configuration options available for this ship. + + )} +
+ ); +}; + +/** + * Upgrade Slot Section component + * Shows available modules for a single upgrade slot + */ +const UpgradeSlotSection = ({ slot, selectedModuleId }) => { + const { act } = useBackend(); + + return ( +
+ + {slot.modules.map((module) => { + const isSelected = selectedModuleId === module.id; + + return ( + + + + + + + + {module.name} + {module.is_default && ( + + (Default) + + )} + + + + + {module.desc} + + + + + + + + + + + + ); + })} + {slot.modules.length === 0 && ( + + + No modules available for this slot. + + + )} + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/ShipCategoriesPage.tsx b/tgui/packages/voidcrew_tgui/interfaces/PreferencesMenu/CharacterPreferences/ShipCategoriesPage.tsx similarity index 96% rename from tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/ShipCategoriesPage.tsx rename to tgui/packages/voidcrew_tgui/interfaces/PreferencesMenu/CharacterPreferences/ShipCategoriesPage.tsx index 7a2e5bf3d4b..1c3fac338a3 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/ShipCategoriesPage.tsx +++ b/tgui/packages/voidcrew_tgui/interfaces/PreferencesMenu/CharacterPreferences/ShipCategoriesPage.tsx @@ -1,8 +1,8 @@ import { useBackend } from 'tgui/backend'; import { Box, Button, Section, Stack } from 'tgui-core/components'; -import { JobPriority, type PreferencesMenuData } from '../types'; -import { useServerPrefs } from '../useServerPrefs'; +import { JobPriority, type PreferencesMenuData } from '../../../../tgui/interfaces/PreferencesMenu/types'; +import { useServerPrefs } from '../../../../tgui/interfaces/PreferencesMenu/useServerPrefs'; const PRIORITY_BUTTON_SIZE = '18px'; diff --git a/tgui/packages/tgui/src/interfaces/ShipSiphon.tsx b/tgui/packages/voidcrew_tgui/interfaces/ShipSiphon.tsx similarity index 94% rename from tgui/packages/tgui/src/interfaces/ShipSiphon.tsx rename to tgui/packages/voidcrew_tgui/interfaces/ShipSiphon.tsx index 4822e87469a..bb46e13c9b0 100644 --- a/tgui/packages/tgui/src/interfaces/ShipSiphon.tsx +++ b/tgui/packages/voidcrew_tgui/interfaces/ShipSiphon.tsx @@ -1,7 +1,13 @@ -// VOIDCREW EDIT START - Voidcrew ship credit siphon controls. -import { useBackend } from '../backend'; -import { Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components'; -import { Window } from '../layouts'; +import { + Button, + LabeledList, + NoticeBox, + ProgressBar, + Section, +} from 'tgui-core/components'; + +import { useBackend } from '../../tgui/backend'; +import { Window } from '../../tgui/layouts'; type SiphonData = { active: boolean; @@ -79,7 +85,7 @@ export const ShipSiphon = (props) => { )} - {active && siphon_goal > 0 && ( + {!!active && siphon_goal > 0 && ( { ); }; -// VOIDCREW EDIT END diff --git a/tgui/packages/tgui/layouts/Window.test.tsx b/tgui/packages/voidcrew_tgui/layouts/Window.test.tsx similarity index 86% rename from tgui/packages/tgui/layouts/Window.test.tsx rename to tgui/packages/voidcrew_tgui/layouts/Window.test.tsx index d31cd45a737..33f397f8c27 100644 --- a/tgui/packages/tgui/layouts/Window.test.tsx +++ b/tgui/packages/voidcrew_tgui/layouts/Window.test.tsx @@ -15,25 +15,25 @@ Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true, Byond: { windowId: 'tgui-window-2', winset }, }); -mock.module('../backend', () => ({ +mock.module('../../tgui/backend', () => ({ useBackend: () => backend, globalStore: { dispatch: () => {} }, backendSuspendStart: () => ({}), })); -mock.module('../debug', () => ({ useDebug: () => ({}) })); -mock.module('../logging', () => ({ createLogger: () => ({ log: () => {} }) })); -mock.module('../drag', () => ({ +mock.module('../../tgui/debug', () => ({ useDebug: () => ({}) })); +mock.module('../../tgui/logging', () => ({ createLogger: () => ({ log: () => {} }) })); +mock.module('../../tgui/drag', () => ({ dragStartHandler: () => {}, resizeStartHandler: () => {}, recallWindowGeometry: recallGeometry, setWindowKey, })); -mock.module('./Layout', () => ({ +mock.module('../../tgui/layouts/Layout', () => ({ Layout: ({ children }: PropsWithChildren) =>
{children}
, })); -mock.module('./TitleBar', () => ({ TitleBar: () => null })); +mock.module('../../tgui/layouts/TitleBar', () => ({ TitleBar: () => null })); -const { Window } = await import('./Window'); +const { Window } = await import('../../tgui/layouts/Window'); let root: Root; let container: HTMLDivElement; diff --git a/voidcrew/_DEFINES/core_integration.dm b/voidcrew/_DEFINES/core_integration.dm new file mode 100644 index 00000000000..1948eadfd51 --- /dev/null +++ b/voidcrew/_DEFINES/core_integration.dm @@ -0,0 +1,4 @@ +#define R_ECONOMY (1<<15) + +/// Voidcrew. From base of /atom/movable/lateShuttleMove, once every moved atom has landed and rotated: (turf/oldT, list/movement_force, move_dir) +#define COMSIG_ATOM_LATE_SHUTTLE_MOVE "movable_late_shuttle_move" diff --git a/voidcrew/controllers/configuration/new_round_alert.dm b/voidcrew/controllers/configuration/new_round_alert.dm new file mode 100644 index 00000000000..80748b58b01 --- /dev/null +++ b/voidcrew/controllers/configuration/new_round_alert.dm @@ -0,0 +1,2 @@ +/// Discord role ID pinged in the new-round announcement sent to CHANNEL_ANNOUNCE_NEW_GAME channels +/datum/config_entry/string/new_round_alert_role_id diff --git a/voidcrew/edits/_onclick/hud/screen_extensions.dm b/voidcrew/edits/_onclick/hud/screen_extensions.dm new file mode 100644 index 00000000000..511dcafca72 --- /dev/null +++ b/voidcrew/edits/_onclick/hud/screen_extensions.dm @@ -0,0 +1,66 @@ +/atom/movable/screen/screentip + /// Weak reference so hovering cannot keep a deleted target alive. + var/datum/weakref/hovered_atom_ref + /// Invalidates text measurements that finish after the pointer has moved on. + var/hover_version = 0 + var/showing_hover = FALSE + /// Refreshed separately from mouse events, including while our ship is moving. + var/fallback_maptext = "" + +/// Reapply a changed preference even when the pointer stays still. +/atom/movable/screen/screentip/proc/refresh_hover() + update_fallback() + var/atom/target = hovered_atom_ref?.resolve() + if(target && hud?.mymob?.client) + target.on_mouse_enter(hud.mymob.client) + else + clear_hover() + +/// Reused HUDs must not retain a hover from the previous connection. +/atom/movable/screen/screentip/proc/on_connection_changed(datum/source) + SIGNAL_HANDLER + update_fallback() + clear_hover() + +/atom/movable/screen/screentip/proc/update_fallback() + fallback_maptext = hud?.screentips_enabled == SCREENTIP_PREFERENCE_DISABLED ? "" : get_fallback_maptext() + if(!showing_hover) + show_fallback() + +/atom/movable/screen/screentip/proc/show_fallback() + maptext = hud?.screentips_enabled == SCREENTIP_PREFERENCE_DISABLED ? "" : fallback_maptext + maptext_y = 10 + +/// Empty or suppressed hover text gives the fallback its turn. +/atom/movable/screen/screentip/proc/set_hover_text(new_maptext, text_y = 10) + showing_hover = length(new_maptext) > 0 + if(showing_hover) + maptext = new_maptext + maptext_y = text_y + else + show_fallback() + +/// An exit from an older target must not clear a more recent hover. +/atom/movable/screen/screentip/proc/clear_hover(atom/target) + if(target && !IS_WEAKREF_OF(target, hovered_atom_ref)) + return + hovered_atom_ref = null + hover_version++ + set_hover_text("") + +/// Starts a hover and returns the version to use for asynchronous text measurement. +/atom/movable/screen/screentip/proc/begin_hover(atom/target) + hovered_atom_ref = WEAKREF(target) + return ++hover_version + +/atom/movable/screen/screentip/process(seconds_per_tick) + if(!hud?.mymob?.client) + return + if(hovered_atom_ref && !hovered_atom_ref.resolve()) + clear_hover() + update_fallback() + +/atom/movable/screen/screentip/Destroy() + STOP_PROCESSING(SSprocessing, src) + hovered_atom_ref = null + return ..() diff --git a/voidcrew/edits/components/tether_pulling.dm b/voidcrew/edits/components/tether_pulling.dm new file mode 100644 index 00000000000..d216ee15d3b --- /dev/null +++ b/voidcrew/edits/components/tether_pulling.dm @@ -0,0 +1,3 @@ +/datum/component/tether + /// Prevents infinite recursion when pulling the anchor + var/currently_pulling = FALSE diff --git a/voidcrew/edits/controllers/subsystem/mapping.dm b/voidcrew/edits/controllers/subsystem/mapping.dm index 5eec5a91aaa..91ffc4ea8a5 100644 --- a/voidcrew/edits/controllers/subsystem/mapping.dm +++ b/voidcrew/edits/controllers/subsystem/mapping.dm @@ -3,8 +3,108 @@ /datum/controller/subsystem/mapping /// Whether we have already reported a reservation turf found sitting in a destroyed area. var/warned_about_dead_reservation_area = FALSE - /// off and which still have to be taken out of GLOB.starlight. Assoc turf -> TRUE so the + /// Released reservation turfs whose starlight is off and which still have to be taken out of GLOB.starlight. Assoc turf -> TRUE so the /// compaction below is a membership test rather than a search. See release_reservation_starlight(). var/list/starlight_release_queue /// Rate limit for reconcile_used_turfs(), which walks all of used_turfs. var/next_used_turf_reconcile = 0 + +/** + * Voidcrew: takes the turfs darkened by the reservation drain out of + * GLOB.starlight, in one linear pass over the list rather than one linear scan per turf. + * + * `GLOB.starlight -= turf` inside the drain loop is the obvious spelling and it is + * quadratic: the loop runs once per released turf and the list can hold as many entries + * again, which on a large release is a multi-second world freeze. Rebuilding the list once + * against an assoc membership set is O(len(GLOB.starlight)) no matter how many turfs were + * released, and the drain only pays it once per REBUILD_STARLIGHT_AFTER turfs plus once at + * the end of each fire. + * + * Leaving the entries in place instead is not an option: enable_starlight() only appends + * when `!light_on`, so a member whose light we switched off would be appended a SECOND + * time the next time that ground is lit, and BYOND's Remove() only ever drops one of them. + * That trades a bounded datum leak for an unbounded list leak. + * + * A turf that was re-lit between being queued and being flushed is kept: the queue is a + * request to drop the entry, `light_on` is the ground truth about whether it still belongs. + */ +/// Turfs the reservation drain may darken before the GLOB.starlight compaction is worth a pass. +#define REBUILD_STARLIGHT_AFTER 1000 + +/datum/controller/subsystem/mapping/proc/release_reservation_starlight(force = FALSE) + var/list/released = starlight_release_queue + if(!length(released)) + return + if(!force && length(released) < REBUILD_STARLIGHT_AFTER) + return + starlight_release_queue = null + + var/list/kept = list() + for(var/turf/open/space/lit as anything in GLOB.starlight) + // `as anything`, so this also drops the nulls a hard delete leaves in place and + // anything a raw turf swap retargeted into something that is no longer space. + if(isnull(lit)) + continue + if(released[lit] && !lit.light_on) + continue + kept += lit + GLOB.starlight = kept + +#undef REBUILD_STARLIGHT_AFTER + +// Voidcrew: how often the used_turfs orphan sweep below may run. +#define USED_TURF_RECONCILE_INTERVAL (2 MINUTES) +// Voidcrew: how many orphans one sweep may hand back, so a pathological +// backlog is drained over several passes instead of in one unbounded release. +#define USED_TURF_RECONCILE_MAX_RECLAIM 5000 + +/** + * Voidcrew: self-healing sweep for SSmapping.used_turfs. + * + * used_turfs maps turf -> the /datum/turf_reservation that claimed it, and the only thing + * that ever removes an entry is that reservation's Release(). An entry whose reservation + * is gone is therefore ground that is claimed forever: it keeps RESERVATION_TURF, never + * goes back into unused_turfs, and _reserve_area() will never hand it out again. Enough of + * those and request_turf_block_reservation() cannot fit a block on any existing reservation + * z-level and mints a permanent new 255x255 one (~65k turfs, ~48 MB) per shortfall. + * + * Release() is the fix for the known way that happened (see the note there); this is the + * net for any path that is still missed, and it also cleans up entries stranded before this + * code existed. It is deliberately narrow: an entry is only dropped when nothing live owns + * it - a null value (the reservation hard deleted, which nulls the ref in place) or a + * QDELETED one. A reservation that still exists is never touched, so this cannot race a + * live claim, and turfs claimed but not yet published are impossible because _reserve_area() + * writes used_turfs[T] and the datum ref in the same unyielding pass. + * + * O(length(used_turfs)) with no sleeps, capped and rate limited. + */ +/datum/controller/subsystem/mapping/proc/reconcile_used_turfs() + if(!initialized || clearing_reserved_turfs) + return + if(world.time < next_used_turf_reconcile) + return + next_used_turf_reconcile = world.time + USED_TURF_RECONCILE_INTERVAL + + var/list/orphans = list() + // `as anything` - a hard delete can null a key in place, and those are skipped rather + // than reclaimed: there is no turf left to hand back. + for(var/turf/claimed as anything in used_turfs) + if(isnull(claimed)) + continue + var/datum/turf_reservation/holder = used_turfs[claimed] + if(!QDELETED(holder)) + continue + orphans += claimed + if(length(orphans) >= USED_TURF_RECONCILE_MAX_RECLAIM) + break + + if(!length(orphans)) + return + + used_turfs -= orphans + log_mapping("SSmapping: reconciled [length(orphans)] used_turfs entr[length(orphans) == 1 ? "y" : "ies"] whose \ + reservation no longer exists - the ground was claimed with nothing left to release it. Handing it back.") + reserve_turfs(orphans) + +#undef USED_TURF_RECONCILE_INTERVAL +#undef USED_TURF_RECONCILE_MAX_RECLAIM diff --git a/voidcrew/edits/error_handler/runtime_state.dm b/voidcrew/edits/error_handler/runtime_state.dm new file mode 100644 index 00000000000..fcd8946ced2 --- /dev/null +++ b/voidcrew/edits/error_handler/runtime_state.dm @@ -0,0 +1,22 @@ +/* + * Voidcrew - runtime flood breaker state. + * + * Plain numbers on purpose. The failure these guard against (round-7, 2026-08-16) is one + * where EVERY list operation in the world starts throwing "bad list" - a boot-time, + * never-mutated list like the config subsystem's entries_by_type failed a plain read, + * as did client keybinding caches, SSgarbage's queues and this handler's own static + * error_last_seen. Anything here that touched a list or a config entry would throw on the + * way to the breaker and hand control back to BYOND's built-in handler, which is what + * actually wrote 337 MB of dd.log in 46 seconds. GLOB var reads are a global slot lookup + * and kept working throughout (GLOB.total_runtimes counted the whole flood), so the + * breaker is built out of those and nothing else. + */ +/// world.time-derived index of the flood window we are currently counting in. +GLOBAL_VAR_INIT(error_flood_window, 0) +/// Runtimes handled so far in this window. +GLOBAL_VAR_INIT(error_flood_count, 0) +/// Runtimes dropped by the breaker in this window. +GLOBAL_VAR_INIT(error_flood_suppressed, 0) +/// While world.time is below this, world/Error emits one flat line per runtime and does +/// nothing else - set when the handler itself threw. See the catch in world/Error. +GLOBAL_VAR_INIT(error_handler_degraded_until, 0) diff --git a/voidcrew/edits/game/objects/structures/mystery_box.dm b/voidcrew/edits/game/objects/structures/mystery_box.dm index f083da4cb40..e646409f943 100644 --- a/voidcrew/edits/game/objects/structures/mystery_box.dm +++ b/voidcrew/edits/game/objects/structures/mystery_box.dm @@ -14,3 +14,32 @@ /obj/structure/mystery_box/fishing /// Weakref of a crew - their ship, or the opener's own mind when they crew for none - to the spins that crew has already taken out of this chest. var/list/spins_by_crew + +/// How many spins one crew gets out of a treasure chest before it stops opening for them. +/// Pooled across the crew rather than handed out per person: a full ship would otherwise +/// strip every use out of a chest on its own, while a two-man crew could never spend more +/// than a fraction of them. +#define TREASURE_CHEST_CREW_SPINS 6 + +/obj/structure/mystery_box/fishing/examine(mob/user) + . = ..() + var/datum/weakref/pool = get_spin_pool(user) + if(!pool) + return + var/spins_left = max(TREASURE_CHEST_CREW_SPINS - LAZYACCESS(spins_by_crew, pool), 0) + if(!spins_left) + . += span_warning("It has nothing left for your crew.") + return + . += span_notice("It has [spins_left] spin[spins_left == 1 ? "" : "s"] left for your crew.") + +/obj/structure/mystery_box/fishing/activate(mob/living/user) + var/datum/weakref/pool = get_spin_pool(user) + if(pool && LAZYACCESS(spins_by_crew, pool) >= TREASURE_CHEST_CREW_SPINS) + to_chat(user, span_warning("[src] refuses to open for your crew anymore. Perhaps you should hand it off to another one...")) + return + . = ..() + if(pool) + LAZYINITLIST(spins_by_crew) + spins_by_crew[pool] += 1 + +#undef TREASURE_CHEST_CREW_SPINS diff --git a/voidcrew/edits/machinery/firedoor_shuttle.dm b/voidcrew/edits/machinery/firedoor_shuttle.dm new file mode 100644 index 00000000000..ed5cbbb3289 --- /dev/null +++ b/voidcrew/edits/machinery/firedoor_shuttle.dm @@ -0,0 +1,21 @@ +/// Called right before the shuttle physically moves - suppress atmosphere checks +/obj/machinery/door/firedoor/proc/on_shuttle_move_start(datum/source, turf/new_turf, rotation, move_mode, obj/docking_port/mobile/moving_dock) + SIGNAL_HANDLER + ignore_alarms = TRUE + +/// Called after shuttle move completes - re-enable checks and verify atmosphere +/obj/machinery/door/firedoor/proc/on_shuttle_move_complete(datum/source, turf/old_turf) + SIGNAL_HANDLER + ignore_alarms = FALSE + // Re-check atmosphere after it stabilizes to catch any real hazards + addtimer(CALLBACK(src, PROC_REF(post_shuttle_move_check)), 0.5 SECONDS) + +/// Re-evaluate atmospheric conditions after a shuttle move to catch real hazards +/obj/machinery/door/firedoor/proc/post_shuttle_move_check() + if(QDELETED(src)) + return + for(var/dir in GLOB.cardinals) + var/turf/checked_turf = get_step(get_turf(src), dir) + if(!checked_turf || !isopenturf(checked_turf)) + continue + process_results(checked_turf) diff --git a/voidcrew/edits/machinery/materials_market.dm b/voidcrew/edits/machinery/materials_market.dm index a0d384b3bc5..7c5650dad75 100644 --- a/voidcrew/edits/machinery/materials_market.dm +++ b/voidcrew/edits/machinery/materials_market.dm @@ -1,5 +1,5 @@ /** - * VOIDCREW EDIT: the Galactic Materials Market, aboard a ship. + * Voidcrew: the Galactic Materials Market, aboard a ship. * * The stock machine is a fixture of a station cargo department: it quotes against * ACCOUNT_CAR or the buyer's own ID, gates the budget on ACCESS_CARGO, and files its diff --git a/voidcrew/edits/mobs/megafauna_logging.dm b/voidcrew/edits/mobs/megafauna_logging.dm new file mode 100644 index 00000000000..fde200d88dc --- /dev/null +++ b/voidcrew/edits/mobs/megafauna_logging.dm @@ -0,0 +1,41 @@ +// VOIDCREW: record targeting decisions, including aggro before any attack lands. +/mob/living/simple_animal/hostile/megafauna/add_target(new_target) + var/atom/previous_target = target + . = ..() + if(previous_target != target) + log_aggro_change(previous_target, target) + +/mob/living/simple_animal/hostile/megafauna/handle_target_del(datum/source) + SIGNAL_HANDLER + // The parent clears target before calling LoseTarget(), so capture it now. + if(target == source) + log_aggro_change(target, null) + return ..() + +/mob/living/simple_animal/hostile/megafauna/proc/aggro_target_description(atom/subject) + if(!subject) + return "none" + var/description = "[key_name_and_tag(subject)] [REF(subject)] at [loc_name(subject)]; [overmap_zone_log_context(subject)]" + if(ismecha(subject)) + var/obj/vehicle/sealed/mecha/mech = subject + var/list/pilots = list() + for(var/mob/pilot as anything in mech.occupants) + pilots += key_name_and_tag(pilot) + description += "; occupants: [length(pilots) ? jointext(pilots, ", ") : "none"]" + return description + +/mob/living/simple_animal/hostile/megafauna/proc/log_aggro_change(atom/previous_target, atom/new_target) + var/action = new_target ? (previous_target ? "switched target" : "acquired target") : "lost target" + var/message = "\[MEGAFAUNA AGGRO\] [action]; from: [aggro_target_description(previous_target)]; to: [aggro_target_description(new_target)]" + log_message(message, LOG_ATTACK, color = "blue") + // Keep the same event in the involved players' individual logs, too. + var/list/mob/observers = list() + for(var/atom/subject as anything in list(previous_target, new_target)) + if(ismob(subject)) + observers |= subject + else if(ismecha(subject)) + var/obj/vehicle/sealed/mecha/mech = subject + for(var/mob/pilot as anything in mech.occupants) + observers |= pilot + for(var/mob/observer as anything in observers) + observer.log_message("[key_name_and_tag(src)] at [loc_name(src)]; [overmap_zone_log_context(src)]: [message]", LOG_ATTACK, color = "blue", log_globally = FALSE) diff --git a/voidcrew/edits/modules/antagonists/abductor/equipment/glands/heal.dm b/voidcrew/edits/modules/antagonists/abductor/equipment/glands/heal.dm index e9b665306d9..0f49ebe6136 100644 --- a/voidcrew/edits/modules/antagonists/abductor/equipment/glands/heal.dm +++ b/voidcrew/edits/modules/antagonists/abductor/equipment/glands/heal.dm @@ -7,7 +7,6 @@ /// Removal invalidates pending work even if this gland returns to the same body. /obj/item/organ/heart/gland/heal/proc/can_finish_healing(mob/living/carbon/recipient, generation) return !QDELETED(src) && !QDELETED(recipient) && owner == recipient && active && generation == healing_generation && ownerCheck() -// VOIDCREW ADD END /obj/item/organ/heart/gland/heal var/healing_generation = 0 diff --git a/voidcrew/edits/modules/antagonists/heretic/magic/rust_construction.dm b/voidcrew/edits/modules/antagonists/heretic/magic/rust_construction.dm index 1860170b70d..621231af49d 100644 --- a/voidcrew/edits/modules/antagonists/heretic/magic/rust_construction.dm +++ b/voidcrew/edits/modules/antagonists/heretic/magic/rust_construction.dm @@ -16,4 +16,3 @@ return wall.remove_filter("rust_wall") -// END VOIDCREW EDIT diff --git a/voidcrew/edits/screentip_hover.dm b/voidcrew/edits/screentip_hover.dm new file mode 100644 index 00000000000..6f199071bf1 --- /dev/null +++ b/voidcrew/edits/screentip_hover.dm @@ -0,0 +1,8 @@ +/atom/MouseExited(location, control, params) + var/client/hovering_client = usr?.client + if(!hovering_client) + return + // The pointer can leave before the deferred MouseEntered has been processed. + if(SSmouse_entered.hovers[hovering_client] == src) + SSmouse_entered.hovers[hovering_client] = null + hovering_client.mob?.hud_used?.screentip_text?.clear_hover(src) diff --git a/voidcrew/mapping/_mapping.dm b/voidcrew/mapping/_mapping.dm index d8903c5870d..1c3e5ac5307 100644 --- a/voidcrew/mapping/_mapping.dm +++ b/voidcrew/mapping/_mapping.dm @@ -335,7 +335,7 @@ if(registration.ruin_type) lower_traits[registration.ruin_type] = TRUE upper_traits[registration.ruin_type] = TRUE - LoadGroup(FailedZs, "Planet [planet_name] [i]", "map_files/voidcrew", "[planet_name].dmm", list(lower_traits, upper_traits)) + LoadGroup(FailedZs, "Planet [planet_name] [i]", "voidcrew/planets", "[planet_name].dmm", list(lower_traits, upper_traits)) z_count += 2 planets["[planet_name] [i]"] = list("type" = overmap_type, "z" = z_count, "zone_band" = next_planet_zone_band()) qdel(environment) diff --git a/code/modules/admin/verbs/shuttlepanel.dm b/voidcrew/modules/admin/legacy/shuttlepanel.dm similarity index 100% rename from code/modules/admin/verbs/shuttlepanel.dm rename to voidcrew/modules/admin/legacy/shuttlepanel.dm diff --git a/voidcrew/modules/metrics/structured_logging_fallback.dm b/voidcrew/modules/metrics/structured_logging_fallback.dm new file mode 100644 index 00000000000..a86acd2450f --- /dev/null +++ b/voidcrew/modules/metrics/structured_logging_fallback.dm @@ -0,0 +1,22 @@ +/// Voidcrew: how long the structured log path stays parked after it throws. +/// Short - one unlucky file write should not blind the round's logs for long. +#define LOG_HOLDER_FAILURE_BACKOFF (5 SECONDS) + +/** + * Voidcrew: last resort for when the structured logger itself throws. + * + * Writes the line flat to world.log and parks the structured path for a few seconds, so a + * world whose list allocator is failing produces one line per log call instead of a + * BYOND-default stack dump per log call. Touches no lists and calls nothing that logs - + * this proc has to work in the state where nothing else does. + * + * The message body does go to world.log here, secret categories included. That is a + * deliberate trade: world.log is host-side only, and the alternative is losing the record + * of whatever was happening at the moment the server stopped being able to write records. + */ +/datum/log_holder/proc/logging_failed(category, message, failure) + structured_logging_broken_until = world.time + LOG_HOLDER_FAILURE_BACKOFF + SEND_TEXT(world.log, "\[LOG FALLBACK]\[[category]] [message]") + SEND_TEXT(world.log, " STRUCTURED LOGGING FAILED ([failure]) - flat world.log lines for the next [LOG_HOLDER_FAILURE_BACKOFF / 10] seconds.") + +#undef LOG_HOLDER_FAILURE_BACKOFF // Voidcrew: metrics falls back to world logging when structured writes fail. diff --git a/code/modules/ship_purchase/admin/economy_verbs.dm b/voidcrew/modules/ship_purchase/admin/economy_verbs.dm similarity index 100% rename from code/modules/ship_purchase/admin/economy_verbs.dm rename to voidcrew/modules/ship_purchase/admin/economy_verbs.dm diff --git a/code/modules/ship_purchase/ship_economy_database.dm b/voidcrew/modules/ship_purchase/ship_economy_database.dm similarity index 100% rename from code/modules/ship_purchase/ship_economy_database.dm rename to voidcrew/modules/ship_purchase/ship_economy_database.dm diff --git a/code/modules/ship_purchase/transaction_helpers.dm b/voidcrew/modules/ship_purchase/transaction_helpers.dm similarity index 100% rename from code/modules/ship_purchase/transaction_helpers.dm rename to voidcrew/modules/ship_purchase/transaction_helpers.dm diff --git a/voidcrew/modules/ship_upgrades/shuttle_manipulator.dm b/voidcrew/modules/ship_upgrades/shuttle_manipulator.dm new file mode 100644 index 00000000000..814a2cb6c21 --- /dev/null +++ b/voidcrew/modules/ship_upgrades/shuttle_manipulator.dm @@ -0,0 +1,102 @@ +/datum/controller/subsystem/shuttle + + //VOID EDIT - Modular ship configuration for shuttle manipulator + /// Pending upgrade module selections (slot_key -> module_id) for shuttle manipulator + var/list/pending_upgrade_selections = list() + /// Pending theme selection (theme_id) for shuttle manipulator + var/pending_theme_id + //END VOID EDIT + +/** + * Build UI data for modular ship configuration in shuttle manipulator + * + * Returns a list with: + * - themes: list of available themes with id, name, desc, is_default, jobs + * - has_themes: boolean if there are themes to choose from + * - slots: list of upgrade slots with their available modules + * - selected_theme: currently selected theme id (from pending_theme_id) + * - selected_upgrades: currently selected modules (from pending_upgrade_selections) + */ +/datum/controller/subsystem/shuttle/proc/build_modular_ui_data(datum/map_template/shuttle/voidcrew/template) + ensure_ship_upgrades_initialized() + + var/list/data = list() + + // Get themes for this ship + var/list/ship_themes = get_themes_for_ship(template.type) + var/list/themes_data = list() + + for(var/theme_id in ship_themes) + var/datum/ship_theme/theme = ship_themes[theme_id] + var/list/theme_info = list() + theme_info["id"] = theme.id + theme_info["name"] = theme.name + theme_info["desc"] = theme.desc + theme_info["is_default"] = theme.is_default + + // Include job slots for preview + if(theme.job_slots) + var/list/jobs = list() + for(var/list/job_data in theme.job_slots) + jobs += list(list( + "name" = job_data["name"], + "slots" = job_data["slots"], + "officer" = job_data["officer"] + )) + theme_info["jobs"] = jobs + + themes_data += list(theme_info) + + data["themes"] = themes_data + data["has_themes"] = length(themes_data) > 0 + + // Determine selected theme - use pending selection or find default + var/effective_theme_id = pending_theme_id + if(!effective_theme_id && length(themes_data)) + var/datum/ship_theme/default_theme = get_default_theme_for_ship(template.type) + if(default_theme) + effective_theme_id = default_theme.id + + data["selected_theme"] = effective_theme_id + + // Get upgrade slots - from theme if selected, otherwise from template + var/list/upgrade_slot_ids = template.upgrade_slot_ids + if(effective_theme_id) + var/datum/ship_theme/selected_theme = ship_themes[effective_theme_id] + if(selected_theme?.upgrade_slot_ids) + upgrade_slot_ids = selected_theme.upgrade_slot_ids + + // Get modules filtered by theme + var/list/all_modules = get_modules_for_ship_theme(template.type, effective_theme_id) + + // Organize modules by slot + var/list/slots_data = list() + for(var/slot_key in upgrade_slot_ids) + var/list/slot_info = list() + slot_info["key"] = slot_key + // Generate display name from slot key (capitalize, replace underscores) + slot_info["display_name"] = capitalize(replacetext(slot_key, "_", " ")) + + var/list/slot_modules = list() + for(var/module_id in all_modules) + var/datum/ship_upgrade_module/module = all_modules[module_id] + if(module.slot != slot_key) + continue + + var/list/module_info = list() + module_info["id"] = module.id + module_info["name"] = module.name + module_info["desc"] = module.desc + module_info["is_default"] = module.is_default + + slot_modules += list(module_info) + + slot_info["modules"] = slot_modules + slots_data += list(slot_info) + + data["slots"] = slots_data + + // Include current pending selections + data["selected_upgrades"] = pending_upgrade_selections.Copy() + + return data diff --git a/voidcrew/modules/shuttle/shuttle_move_helpers.dm b/voidcrew/modules/shuttle/shuttle_move_helpers.dm new file mode 100644 index 00000000000..25bbcb13164 --- /dev/null +++ b/voidcrew/modules/shuttle/shuttle_move_helpers.dm @@ -0,0 +1,156 @@ +/// How far past the hull's edge evict_landing_stowaways() will look for somewhere to put a stowaway. +#define STOWAWAY_EXIT_DEPTH 5 + +/** + * VOIDCREW ADDITION. Evict anything that was standing on the landing site and survived + * into the hull's interior. + * + * /turf/toShuttleMove() is supposed to clear the destination before the deck is laid over + * it - living things are gibbed, anchored objects deleted, loose objects shoved aside - + * but "shoved aside" is a single step(thing, shuttle.dir), and that has never been enough + * for this fork: + * + * - One tile does not clear a footprint. Ships land in a 56x40 planet berth + * (RESERVE_DOCK_MAX_SIZE_*) with the hull centred in it, so a tank in the middle of the + * deck is still under the deck after its step. + * - The step direction is the port's OLD facing (setDir() to the berth's dir happens at + * the very end of initiate_docking()), while preflight_check() walks the destination in + * return_ordered_turfs() order - x ascending, y ascending within each column. Whenever + * those disagree (ship facing SOUTH or WEST relative to that scan) everything loose is + * pushed into tiles the crush has already finished with, and stays there. + * - step() also simply fails when the next tile is blocked, which on a planet surface it + * frequently is. + * - preflight_check() is full of CHECK_TICKs, so the crush is spread over several ticks + * and planet fauna walks onto cleared tiles in the gap. Anything riding inside a shoved + * object (a mob in a closet) is never looked at in the first place. + * + * Upstream gets away with all of that because a station shuttle's destination is empty + * space. Ours is a planet surface covered in loot and wildlife, so the leftovers end up on + * the deck: the reported fuel tanks, shards and RTGs, and the mobs that came with them. + * + * moved_atoms is the exact set of movables this move carried, so anything else standing on + * a turf we just laid down was already there. Crew, cargo, and anything the crew left + * lying on their own floor are all in moved_atoms and are never touched by this. + */ +/obj/docking_port/mobile/proc/evict_landing_stowaways(list/old_turfs, list/new_turfs, list/moved_atoms) + var/min_x = INFINITY + var/min_y = INFINITY + var/max_x = 0 + var/max_y = 0 + var/footprint_z = 0 + var/list/stowaways = list() + for(var/i in 1 to length(old_turfs)) + var/turf/landed = new_turfs[i] + if(!landed) + continue + // The rectangle is taken from the WHOLE footprint, not just the tiles that moved, + // so a stowaway is pushed clear of the ship rather than into the ground squares a + // non-rectangular hull leaves inside its own bounding box. + min_x = min(min_x, landed.x) + max_x = max(max_x, landed.x) + min_y = min(min_y, landed.y) + max_y = max(max_y, landed.y) + footprint_z = landed.z + var/turf/old_turf = old_turfs[i] + if(!old_turf) + continue + // Both flags, not either: MOVE_CONTENTS is what put this tile's legitimate + // occupants into moved_atoms, and without it the exemption below cannot be + // trusted. MOVE_AREA alone is a breached tile - the site's own ground adopted into + // one of our areas - and what is lying on that is still the site's business. + var/move_mode = old_turfs[old_turf] + if((move_mode & (MOVE_TURF|MOVE_CONTENTS)) != (MOVE_TURF|MOVE_CONTENTS)) + continue + for(var/atom/movable/stowaway as anything in landed.contents) + if(moved_atoms[stowaway]) // came with the ship + continue + if(stowaway.loc != landed) // multi-tile objects + continue + if(stowaway.resistance_flags & SHUTTLE_CRUSH_PROOF) + continue + // The berth's own stationary port sits inside the rectangle by definition, and + // non-living mobs are left alone by every other crush branch in this module. + if(istype(stowaway, /obj/docking_port)) + continue + if(ismob(stowaway) && !isliving(stowaway)) + continue + stowaways += stowaway + + if(!length(stowaways)) + return + + var/evicted = 0 + var/destroyed = 0 + for(var/atom/movable/stowaway as anything in stowaways) + if(QDELETED(stowaway)) + continue + var/turf/exit_turf = find_stowaway_exit(stowaway, min_x, min_y, max_x, max_y, footprint_z) + stowaway.pulledby?.stop_pulling() + stowaway.stop_pulling() + if(isliving(stowaway)) + var/mob/living/living_stowaway = stowaway + living_stowaway.buckled?.unbuckle_mob(living_stowaway, force = TRUE) + if(!exit_turf) + // Nowhere on the map to put it, and the hull is already on top of it, so + // this is the crush arriving late rather than a new outcome. + log_shuttle("[name]: [key_name(living_stowaway)] survived the landing crush at [AREACOORD(living_stowaway)] with nowhere outside the footprint to go - gibbed.") + living_stowaway.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS) + living_stowaway.gib(DROP_ALL_REMAINS) + destroyed++ + continue + log_shuttle("[name]: [key_name(living_stowaway)] survived the landing crush at [AREACOORD(living_stowaway)] - moved clear to [AREACOORD(exit_turf)].") + living_stowaway.forceMove(exit_turf) + evicted++ + continue + if(!exit_turf) + qdel(stowaway) // what the crush already does to anything it cannot shove + destroyed++ + continue + stowaway.forceMove(exit_turf) + evicted++ + + log_shuttle("[name]: landing footprint ([min_x],[min_y],[footprint_z])-([max_x],[max_y],[footprint_z]) held [length(stowaways)] site movable(s) the crush missed - [evicted] moved clear, [destroyed] destroyed.") + +/** + * Nearest turf outside the rectangle the hull just occupied, for a stowaway standing in it. + * + * Walks straight out along whichever of the four axes is closest and takes the first tile + * past the edge that will actually hold the thing, going up to STOWAWAY_EXIT_DEPTH further + * out if the tiles at the edge are walls or rubble. Falls back to the first tile outside + * the rectangle it found at all, blocked or not - overlapping something on the surface is + * a far smaller problem than riding around inside somebody's hull - and the caller only + * destroys the thing when even that does not exist. + */ +/obj/docking_port/mobile/proc/find_stowaway_exit(atom/movable/stowaway, min_x, min_y, max_x, max_y, footprint_z) + var/stow_x = stowaway.x + var/stow_y = stowaway.y + if(!stow_x || !stow_y) + return null + // start_x, start_y, step_x, step_y, tiles from the stowaway to that starting tile + var/list/exit_lanes = list( + list(min_x - 1, stow_y, -1, 0, stow_x - (min_x - 1)), + list(max_x + 1, stow_y, 1, 0, (max_x + 1) - stow_x), + list(stow_x, min_y - 1, 0, -1, stow_y - (min_y - 1)), + list(stow_x, max_y + 1, 0, 1, (max_y + 1) - stow_y), + ) + var/turf/fallback + var/best_cost = INFINITY + var/turf/best + for(var/list/lane as anything in exit_lanes) + var/lane_cost = lane[5] + for(var/depth in 0 to STOWAWAY_EXIT_DEPTH - 1) + if((lane_cost + depth) >= best_cost) + break + var/turf/candidate = locate(lane[1] + (lane[3] * depth), lane[2] + (lane[4] * depth), footprint_z) + if(!candidate) + break // ran off the edge of the map on this axis + if(!fallback) + fallback = candidate + if(candidate.is_blocked_turf(exclude_mobs = TRUE, source_atom = stowaway)) + continue + best_cost = lane_cost + depth + best = candidate + break + return best || fallback + +#undef STOWAWAY_EXIT_DEPTH diff --git a/voidcrew/modules/trade/bag_rift_protection.dm b/voidcrew/modules/trade/bag_rift_protection.dm new file mode 100644 index 00000000000..7e8c98647c3 --- /dev/null +++ b/voidcrew/modules/trade/bag_rift_protection.dm @@ -0,0 +1,8 @@ +/// The receiving bag can be on the other side of an area boundary from its user. +/datum/storage/bag_of_holding/proc/can_create_rift(mob/user) + var/area/bag_area = get_area(parent) + if(!bag_area || (bag_area.area_flags & NO_BOH) || is_trader_outpost_protected(parent)) + if(user) + to_chat(user, span_warning("Bluespace interference prevents the bags from nesting here.")) + return FALSE + return TRUE diff --git a/voidcrew/modules/unit_tests/_unit_tests.dm b/voidcrew/modules/unit_tests/_unit_tests.dm index 3a829f945d8..c06795ee683 100644 --- a/voidcrew/modules/unit_tests/_unit_tests.dm +++ b/voidcrew/modules/unit_tests/_unit_tests.dm @@ -3,6 +3,7 @@ #include "_voidcrew_test_selection.dm" #include "armor_partial_modifiers.dm" #include "atmos_component_pipeline.dm" +#include "blood_jaunt_destinations.dm" #include "drift_vectors.dm" #include "gas_connector_lifecycle.dm" #include "glass_floor_baseturfs.dm" @@ -10,8 +11,10 @@ #include "late_initialization_reentry.dm" #include "map_parser_attributes.dm" #include "mod_night_vision.dm" +#include "operating_table_movement.dm" #include "overmap_spawn_density.dm" #include "pipeline_reconciliation.dm" +#include "prisoner_photos.dm" #include "reagent_holder_teardown.dm" #include "shuttle_cling_lifecycle.dm" #include "shuttle_cling_rethrow.dm" diff --git a/voidcrew/modules/unit_tests/blood_jaunt_destinations.dm b/voidcrew/modules/unit_tests/blood_jaunt_destinations.dm new file mode 100644 index 00000000000..8d4f0df5e45 --- /dev/null +++ b/voidcrew/modules/unit_tests/blood_jaunt_destinations.dm @@ -0,0 +1,65 @@ +/// A nearby pool across a ruin boundary must not invoke the random jaunt ejection fallback. +/datum/unit_test/blood_jaunt_destinations + var/turf/pool_turf + var/area/original_area + var/area/overmap_encounter/planet_ruin/ruin_area + var/original_turf_flags + +/datum/unit_test/blood_jaunt_destinations/Destroy() + if(pool_turf) + pool_turf.turf_flags = original_turf_flags + pool_turf.change_area(ruin_area, original_area) + QDEL_NULL(ruin_area) + return ..() + +/datum/unit_test/blood_jaunt_destinations/Run() + var/mob/living/carbon/human/jaunter = allocate(/mob/living/carbon/human/consistent) + var/datum/action/cooldown/spell/jaunt/bloodcrawl/crawl = allocate(/datum/action/cooldown/spell/jaunt/bloodcrawl) + crawl.Grant(jaunter) + crawl.equip_blood_hands = FALSE + var/obj/effect/decal/cleanable/blood/entry_pool = allocate(/obj/effect/decal/cleanable/blood) + pool_turf = get_step(run_loc_floor_bottom_left, EAST) + original_area = get_area(pool_turf) + original_turf_flags = pool_turf.turf_flags + ruin_area = new + pool_turf.change_area(original_area, ruin_area) + var/obj/effect/decal/cleanable/blood/exit_pool = allocate(/obj/effect/decal/cleanable/blood, pool_turf) + + TEST_ASSERT(!crawl.try_enter_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl entered a pool inside a NOTELEPORT ruin") + TEST_ASSERT_EQUAL(get_turf(jaunter), run_loc_floor_bottom_left, "Refused blood entry moved the caster") + TEST_ASSERT(crawl.try_enter_jaunt(entry_pool, jaunter, forced = TRUE), "Blood Crawl could not enter an ordinary pool") + var/obj/effect/dummy/phased_mob/holder = jaunter.loc + qdel(entry_pool) + + TEST_ASSERT(isnull(crawl.find_nearby_blood(get_turf(jaunter))), "Blood Crawl offered a pool across a NOTELEPORT boundary") + var/datum/action/cooldown/spell/jaunt/bloodcrawl/vestige_trapdoor/trapdoor = allocate(/datum/action/cooldown/spell/jaunt/bloodcrawl/vestige_trapdoor) + TEST_ASSERT(isnull(trapdoor.find_wet_door(get_turf(jaunter))), "The trapdoor pact offered a pool across a NOTELEPORT boundary") + TEST_ASSERT(!crawl.try_exit_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl exited into a NOTELEPORT ruin") + TEST_ASSERT_EQUAL(jaunter.loc, holder, "A refused blood exit ejected or scattered the caster") + TEST_ASSERT_EQUAL(get_turf(holder), run_loc_floor_bottom_left, "A refused blood exit moved the holder") + + // Turf-level wards must also apply to pool selection and direct entry/exit. + ruin_area.area_flags &= ~NOTELEPORT + pool_turf.turf_flags |= NOJAUNT + TEST_ASSERT(isnull(crawl.find_nearby_blood(get_turf(jaunter))), "Blood Crawl offered a pool on a NOJAUNT turf") + TEST_ASSERT(!crawl.try_exit_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl exited onto a NOJAUNT turf") + pool_turf.turf_flags = original_turf_flags + + TEST_ASSERT_EQUAL(crawl.find_nearby_blood(get_turf(jaunter)), exit_pool, "Blood Crawl did not offer the now-unprotected pool") + TEST_ASSERT_EQUAL(trapdoor.find_wet_door(get_turf(jaunter)), exit_pool, "The trapdoor pact did not offer the now-unprotected pool") + + // The destination can become protected after selection, during the bubbling delay. + crawl.exit_blood_time = 1 SECONDS + addtimer(CALLBACK(src, PROC_REF(ward_destination)), 0.5 SECONDS) + TEST_ASSERT(!crawl.try_exit_jaunt(exit_pool, jaunter), "Blood Crawl ignored a ward applied during its exit delay") + TEST_ASSERT(ruin_area.area_flags & NOTELEPORT, "The destination was never warded during the exit delay") + TEST_ASSERT_EQUAL(jaunter.loc, holder, "A ward applied during the exit delay scattered the caster") + TEST_ASSERT_EQUAL(get_turf(holder), run_loc_floor_bottom_left, "A ward applied during the exit delay moved the holder") + + ruin_area.area_flags &= ~NOTELEPORT + TEST_ASSERT(crawl.try_exit_jaunt(exit_pool, jaunter, forced = TRUE), "Blood Crawl could not exit through an unprotected pool") + TEST_ASSERT_EQUAL(jaunter.loc, pool_turf, "Blood Crawl did not surface at the chosen pool") + TEST_ASSERT(!HAS_TRAIT(jaunter, TRAIT_MAGICALLY_PHASED), "Blood Crawl left the caster phased after a successful exit") + +/datum/unit_test/blood_jaunt_destinations/proc/ward_destination() + ruin_area.area_flags |= NOTELEPORT diff --git a/voidcrew/modules/unit_tests/operating_table_movement.dm b/voidcrew/modules/unit_tests/operating_table_movement.dm new file mode 100644 index 00000000000..4f7ca6ab283 --- /dev/null +++ b/voidcrew/modules/unit_tests/operating_table_movement.dm @@ -0,0 +1,39 @@ +/// Occupants can move between adjacent tables, while floor entry and buckling keep their normal restrictions. +/datum/unit_test/operating_table_movement + +/datum/unit_test/operating_table_movement/Run() + var/turf/first_site = get_step(run_loc_floor_bottom_left, EAST) + var/turf/second_site = get_step(first_site, EAST) + var/turf/floor_exit = get_step(first_site, NORTH) + var/obj/structure/table/optable/first_table = allocate(__IMPLIED_TYPE__, first_site) + var/obj/structure/table/optable/second_table = allocate(__IMPLIED_TYPE__, second_site) + var/mob/living/carbon/human/consistent/human = allocate(__IMPLIED_TYPE__) + + TEST_ASSERT(!human.Move(first_site, EAST), "Walking from the floor must not bypass getting onto an operating table.") + TEST_ASSERT(!HAS_TRAIT(human, TRAIT_ON_CLIMBABLE), "A failed attempt to enter must not grant table-walking permission.") + human.forceMove(first_site) // Simulate having already climbed or been placed onto the table. + TEST_ASSERT(human.Move(second_site, EAST), "An occupant must be able to walk onto an adjacent operating table.") + TEST_ASSERT_EQUAL(human.loc, second_site, "Walking between tables must move the occupant physically.") + TEST_ASSERT_NULL(first_table.patient, "Walking upright must not leave a patient on the first table.") + TEST_ASSERT_NULL(second_table.patient, "Walking upright must not create a patient on the second table.") + + TEST_ASSERT(second_table.buckle_mob(human, force = TRUE), "The occupied operating table must still support buckling.") + TEST_ASSERT(!human.Move(first_site, WEST), "A buckled patient must not walk off the table.") + TEST_ASSERT_EQUAL(human.buckled, second_table, "Attempted movement must not unbuckle the patient.") + second_table.unbuckle_mob(human, force = TRUE) + human.set_resting(new_resting = TRUE, instant = TRUE) + TEST_ASSERT_EQUAL(second_table.patient, human, "The resting occupant must be registered as the current patient.") + TEST_ASSERT(human.Move(first_site, WEST), "An unbuckled resting occupant must be able to move between tables.") + TEST_ASSERT_NULL(second_table.patient, "Moving away must clear the previous table's patient.") + TEST_ASSERT_EQUAL(first_table.patient, human, "The destination table must recognize the resting patient.") + + TEST_ASSERT(human.Move(floor_exit, NORTH), "The occupant must be able to leave the table for the floor.") + TEST_ASSERT_NULL(first_table.patient, "Leaving the table must clear its patient.") + TEST_ASSERT(!HAS_TRAIT(human, TRAIT_ON_CLIMBABLE), "Table-walking permission must end when the occupant leaves.") + human.set_resting(new_resting = FALSE, instant = TRUE) + TEST_ASSERT(!human.Move(first_site, SOUTH), "An occupant on the floor must get onto the table again before crossing it.") + + human.forceMove(first_site) + qdel(first_table) + TEST_ASSERT(!HAS_TRAIT(human, TRAIT_ON_CLIMBABLE), "Removing the occupied table must remove its table-walking permission.") + TEST_ASSERT(!human.Move(second_site, EAST), "A removed table must not allow walking onto a remaining adjacent table.") diff --git a/code/modules/unit_tests/prisoner_photos.dm b/voidcrew/modules/unit_tests/prisoner_photos.dm similarity index 100% rename from code/modules/unit_tests/prisoner_photos.dm rename to voidcrew/modules/unit_tests/prisoner_photos.dm