Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c1c4c4f
Porting quadbikes from Polaris.
MistakeNot4892 Dec 26, 2025
88d07f3
Porting cliffs and mines from Polaris.
MistakeNot4892 Dec 28, 2025
8ecf0f0
Fixes copypasted loadout path for hooded cloaks.
MistakeNot4892 Jan 1, 2026
4c80fd1
Porting various projectile impact effects and sounds from Polaris.
MistakeNot4892 Jan 1, 2026
3b93cd8
Adjust actual_range in recalc_corner to respect dirlights
out-of-phaze Jan 2, 2026
2bca5f4
Fix lighting corners not being lit from space
out-of-phaze Jan 2, 2026
cb19fad
Lightly optimize update_corners
out-of-phaze Jan 2, 2026
8d02381
Porting some minor vox outfit reworking from Polaris.
MistakeNot4892 Jan 2, 2026
ff5ea45
Changing /decl/material/gas out for a filterable material proc.
MistakeNot4892 Dec 31, 2025
53123a3
Merge pull request #5242 from MistakeNot4892/fix/loadout
out-of-phaze Jan 3, 2026
21561a5
Adding many missing signs from Polaris Cynosure branch and tidying si…
MistakeNot4892 Nov 26, 2025
93cbd7c
Make random subset supplypacks use expected price instead of raw sum
out-of-phaze Jan 6, 2026
fcc1de1
Merge branch 'stable' of github.com:NebulaSS13/Nebula into dev
MistakeNot4892 Jan 8, 2026
e268313
Merge pull request #5266 from MistakeNot4892/dev
MistakeNot4892 Jan 8, 2026
9f3f012
Make corner generation checks clearer
out-of-phaze Jan 9, 2026
3195df9
Enlarges the stamina bar and moves it centrally above the hand select…
MistakeNot4892 Jan 9, 2026
89e439b
Merge pull request #5239 from MistakeNot4892/tweak/gas
out-of-phaze Jan 9, 2026
2c79d31
Merge pull request #5246 from MistakeNot4892/port/impacteffects
out-of-phaze Jan 9, 2026
987b409
Merge pull request #5219 from MistakeNot4892/port/hazards
out-of-phaze Jan 9, 2026
aca7b93
Porting new hivebot icons and subtypes from Polaris.
MistakeNot4892 Jan 9, 2026
359222f
Porting map effects from Polaris.
MistakeNot4892 Jan 8, 2026
54e4829
Merge pull request #5264 from out-of-phaze/fix/supplypack-avgprice
MistakeNot4892 Jan 9, 2026
2f6130a
Automatic changelog generation for PR #5264 [ci skip]
NebulaSS13Bot Jan 9, 2026
5b16cf8
Ported/reimplemented salvageable machines and devices from Polaris.
MistakeNot4892 Jan 8, 2026
e718a6f
Clarified cable coil/network cable coil singular/plural names.
MistakeNot4892 Jan 9, 2026
94363b0
Automatic changelog generation [ci skip]
NebulaSS13Bot Jan 10, 2026
5d0f48b
Merge pull request #5250 from out-of-phaze/fix/lighting-correctness
MistakeNot4892 Jan 11, 2026
92a30b8
Porting and modpacking exploration and xenofauna content from Polaris.
MistakeNot4892 Dec 31, 2025
4a2bcd9
Merge pull request #5204 from MistakeNot4892/feature/moresigns
out-of-phaze Jan 11, 2026
918d080
Merge pull request #5268 from MistakeNot4892/port/map_effects
out-of-phaze Jan 11, 2026
e067271
Merge pull request #5251 from MistakeNot4892/port/voxclothes
out-of-phaze Jan 11, 2026
93e272a
Merge pull request #5216 from MistakeNot4892/port/quads
out-of-phaze Jan 11, 2026
6c72356
Merge pull request #5269 from MistakeNot4892/port/hivebots
out-of-phaze Jan 12, 2026
89b35e5
Merge pull request #5208 from MistakeNot4892/port/xenofauna
out-of-phaze Jan 12, 2026
6d27eec
Merge pull request #5265 from MistakeNot4892/feature/salvage
out-of-phaze Jan 12, 2026
97dc984
Merge pull request #5270 from MistakeNot4892/tweak/stamina
out-of-phaze Jan 13, 2026
0f3bc11
Port recursion limit error handling from TG
out-of-phaze Jan 12, 2026
0360920
Merge pull request #5273 from out-of-phaze/fix/recurse-error
MistakeNot4892 Jan 14, 2026
e888113
Merge branch 'dev' of github.com:NebulaSS13/Nebula into polaris-rebase
MistakeNot4892 Jan 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/__defines/armor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#define ARMOR_RAD_MINOR 10
#define ARMOR_RAD_SMALL 25
#define ARMOR_RAD_RESISTANT 40
#define ARMOR_RAD_LARGE 60
#define ARMOR_RAD_SHIELDED 100

#define ARMOR_BOMB_MINOR 10
Expand Down
1 change: 1 addition & 0 deletions code/_global_vars/lists/flavor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ GLOBAL_GETTER(cable_colors, /list, SetupCableColors())
. = list()

var/list/valid_cable_coils = typesof(/obj/item/stack/cable_coil) - typesof(
/obj/item/stack/cable_coil/five,
/obj/item/stack/cable_coil/single,
/obj/item/stack/cable_coil/cut,
/obj/item/stack/cable_coil/cyborg,
Expand Down
9 changes: 8 additions & 1 deletion code/_global_vars/sound.dm
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,11 @@ var/global/list/sweeping_sound = list(
'sound/foley/sweeping5.ogg',
'sound/foley/sweeping6.ogg',
'sound/foley/sweeping7.ogg',
)
)

var/global/list/ricochet_sound = list(
'sound/weapons/guns/ricochet1.ogg',
'sound/weapons/guns/ricochet2.ogg',
'sound/weapons/guns/ricochet3.ogg',
'sound/weapons/guns/ricochet4.ogg'
)
11 changes: 9 additions & 2 deletions code/_helpers/type2type.dm
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
/*
* Holds procs designed to change one type of value, into another.
* Contains:
* text2list & list2text
* alist2list
* file2list
* angle2dir
* angle2text
* worldtime2text
*/

// This proc does not support converting numerically indexed alists to assoc lists.
/proc/alist2list(alist/input)
. = list()
for(var/k,v in input)
if(isnum(k))
CRASH("Numeric index passed to alist2list()!")
.[k] = v

// Splits the text of a file at seperator and returns them in a list.
/proc/file2list(filename, seperator = "\n")
return splittext(safe_file2text(filename), seperator)
Expand Down
1 change: 0 additions & 1 deletion code/_onclick/hud/_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
#define ui_movi "RIGHT-2:24,BOTTOM:5"
#define ui_attack_selector "RIGHT-2:27,BOTTOM+2:9"
#define ui_zonesel "RIGHT-1:28,BOTTOM:5"
#define ui_stamina "RIGHT-2:24,BOTTOM:8"

#define ui_borg_module "RIGHT-1:28,BOTTOM+1:7"

Expand Down
9 changes: 6 additions & 3 deletions code/_onclick/hud/hud_types/_hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
var/action_buttons_hidden = FALSE
var/obj/screen/action_button/hide_toggle/hide_actions_toggle

var/const/HAND_UI_PER_ROW = 4
var/const/HAND_UI_INITIAL_Y_OFFSET = 21

// TODO: declify these.
VAR_PROTECTED/gun_mode_toggle_type
VAR_PRIVATE/obj/screen/gun/mode/gun_mode_toggle
Expand Down Expand Up @@ -351,11 +354,10 @@
qdel(inv_box)

// Rebuild offsets for the hand elements.
var/const/elems_per_row = 4
var/hand_y_offset = 21
var/hand_y_offset = HAND_UI_INITIAL_Y_OFFSET
var/list/elements = hud_elements_hands?.Copy()
while(length(elements))
var/copy_index = min(length(elements), elems_per_row)+1
var/copy_index = min(length(elements), HAND_UI_PER_ROW)+1
var/list/sublist = elements.Copy(1, copy_index)
elements.Cut(1, copy_index)
var/hand_x_offset = (world.icon_size/2) * (1 - length(sublist))
Expand Down Expand Up @@ -389,6 +391,7 @@
if(mymob.client)
mymob.client.screen |= swap_elem

refresh_element(HUD_STAMINA)
update_hand_elements()

return TRUE
Expand Down
35 changes: 26 additions & 9 deletions code/_onclick/hud/screen/screen_stamina.dm
Original file line number Diff line number Diff line change
@@ -1,24 +1,41 @@
/obj/screen/stamina
name = "stamina"
icon = 'icons/effects/progressbar.dmi'
icon_state = "prog_bar_100"
icon = 'icons/effects/staminabar.dmi'
icon_state = "bar"
invisibility = INVISIBILITY_MAXIMUM
screen_loc = ui_stamina
use_supplied_ui_color = FALSE
use_supplied_ui_alpha = FALSE
use_supplied_ui_icon = FALSE
requires_ui_style = FALSE
layer = HUD_BASE_LAYER + 0.1 // needs to layer over the movement intent element
var/const/STAMINA_STATE_PERIOD = 5

/obj/screen/stamina/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat)
. = ..()
update_icon()

/obj/screen/stamina/on_update_icon()
. = ..()
var/mob/living/owner = owner_ref?.resolve()
if(!istype(owner))
set_invisibility(INVISIBILITY_MAXIMUM)
return

var/hand_row_offset = /datum/hud::HAND_UI_INITIAL_Y_OFFSET + (ceil(length(owner.get_held_item_slots()) / /datum/hud::HAND_UI_PER_ROW) * world.icon_size) + 16
screen_loc = "CENTER:-32,BOTTOM:[hand_row_offset]"

var/stamina = owner.get_stamina()
cut_overlays()
if(stamina < 100)
set_invisibility(INVISIBILITY_NONE)
var/stamina_amt = floor(stamina/STAMINA_STATE_PERIOD)*STAMINA_STATE_PERIOD
var/bar_overlay_state = "bar_[stamina_amt]"
if(stamina_amt > 0 && stamina <= 25)
bar_overlay_state = "[bar_overlay_state]_fail"
var/image/bar_overlay = image(icon = icon, icon_state = bar_overlay_state)
bar_overlay.appearance_flags |= RESET_COLOR
bar_overlay.color = COLOR_WHITE
add_overlay(bar_overlay)
else
var/stamina = owner.get_stamina()
if(stamina < 100)
set_invisibility(INVISIBILITY_NONE)
icon_state = "prog_bar_[floor(stamina/5)*5][(stamina >= 5) && (stamina <= 25) ? "_fail" : null]"
else
set_invisibility(INVISIBILITY_MAXIMUM)
set_invisibility(INVISIBILITY_MAXIMUM)
compile_overlays()
16 changes: 12 additions & 4 deletions code/controllers/subsystems/initialization/persistence.dm
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,19 @@ SUBSYSTEM_DEF(persistence)

var/turf/T = get_turf(value)
if(!T)
return
return FALSE

var/area/A = get_area(T)
if(!A || (A.area_flags & AREA_FLAG_IS_NOT_PERSISTENT))
return
var/decl/persistence_handler/handler = RESOLVE_TO_DECL(track_type)
if(!istype(handler))
return FALSE

if(handler.station_restricted && (!T || !(T.z in SSmapping.station_levels) ))
return FALSE

if(handler.area_restricted)
var/area/A = get_area(T)
if(!A || (A.area_flags & AREA_FLAG_IS_NOT_PERSISTENT))
return FALSE

var/datum/level_data/level = SSmapping.levels_by_z[T.z]
if(!istype(level) || !level.permit_persistence)
Expand Down
7 changes: 7 additions & 0 deletions code/datums/composite_sounds/vehicle_engine.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/datum/composite_sound/vehicle_engine
start_sound = 'sound/machines/vehicle/engine_start.ogg'
start_length = 2
mid_sounds = list('sound/machines/vehicle/engine_mid.ogg'=1)
mid_length = 6
end_sound = 'sound/machines/vehicle/engine_end.ogg'
play_volume = 20
26 changes: 18 additions & 8 deletions code/datums/repositories/atom_info.dm
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
var/global/repository/atom_info/atom_info_repository = new()

/repository/atom_info
var/list/matter_cache = list()
var/list/matter_cache = list()
var/list/combined_worth_cache = list()
var/list/single_worth_cache = list()
var/list/name_cache = list()
var/list/description_cache = list()
var/list/matter_mult_cache = list()
var/list/origin_tech_cache = list()
var/list/single_worth_cache = list()
var/list/name_cache = list()
var/list/description_cache = list()
var/list/matter_mult_cache = list()
var/list/origin_tech_cache = list()
var/list/appearance_cache = list()

/repository/atom_info/proc/create_key_for(var/_path, var/_mat, var/_amount)
. = "[_path]"
Expand All @@ -24,7 +25,7 @@ var/global/repository/atom_info/atom_info_repository = new()
else
. = new _path

/repository/atom_info/proc/update_cached_info_for(var/_path, var/_mat, var/_amount, var/key)
/repository/atom_info/proc/update_cached_info_for(var/_path, var/_mat, var/_amount, var/key, var/cache_appearance = FALSE)
var/atom/instance
if(!matter_cache[key])
instance = get_instance_of(_path, _mat, _amount)
Expand All @@ -41,6 +42,9 @@ var/global/repository/atom_info/atom_info_repository = new()
if(!description_cache[key])
instance = instance || get_instance_of(_path, _mat, _amount)
description_cache[key] = instance.desc
if(cache_appearance && !appearance_cache[key])
instance = instance || get_instance_of(_path, _mat, _amount)
appearance_cache[key] = instance.appearance
if(!matter_mult_cache[key] && ispath(_path, /obj))
var/obj/obj_instance = instance || get_instance_of(_path, _mat, _amount)
matter_mult_cache[key] = obj_instance.get_matter_amount_modifier()
Expand Down Expand Up @@ -84,4 +88,10 @@ var/global/repository/atom_info/atom_info_repository = new()
/repository/atom_info/proc/get_origin_tech_for(var/_path, var/_mat, var/_amount)
var/key = create_key_for(_path, _mat, _amount)
update_cached_info_for(_path, _mat, _amount, key)
. = origin_tech_cache[key]
. = origin_tech_cache[key]

// Bespoke proc; only cache appearance if and when this proc is called, not more generally.
/repository/atom_info/proc/get_appearance_of(var/_path, var/_mat, var/_amount)
var/key = create_key_for(_path, _mat, _amount)
update_cached_info_for(_path, _mat, _amount, key, cache_appearance = TRUE)
. = appearance_cache[key]
4 changes: 2 additions & 2 deletions code/datums/supplypacks/operations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

/decl/hierarchy/supply_pack/operations/cargotrain
name = "Equipment - Cargo Train Tug"
contains = list(/obj/vehicle/train/cargo/engine)
contains = list(/obj/vehicle/train/engine)
containertype = /obj/structure/largecrate
containername = "cargo train tug crate"

/decl/hierarchy/supply_pack/operations/cargotrailer
name = "Equipment - Cargo Train Trolley"
contains = list(/obj/vehicle/train/cargo/trolley)
contains = list(/obj/vehicle/train/trolley)
containertype = /obj/structure/largecrate
containername = "cargo train trolley crate"

Expand Down
9 changes: 0 additions & 9 deletions code/datums/supplypacks/science.dm
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,3 @@
name = "Gear - Illumination grenades"
contains = list(/obj/item/grenade/light = 8)
containername = "illumination grenade crate"

/decl/hierarchy/supply_pack/science/stasis_cages
name = "Stasis Cage"
contains = list(
/obj/structure/stasis_cage = 1
)
containertype = /obj/structure/closet/crate/large
containername = "stasis cage crate"
access = access_xenofauna
7 changes: 5 additions & 2 deletions code/datums/supplypacks/supplypack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ var/global/list/cargoprices = list()
. = ..() // make sure children are set up
if(is_category())
return // don't do any of this for categories
var/total_contained = 0
for(var/entry in contains)
total_contained += max(1, contains[entry])
if(!num_contained)
for(var/entry in contains)
num_contained += max(1, contains[entry])
num_contained = total_contained
if(isnull(cost))
cost = 0
for(var/entry in contains)
cost += atom_info_repository.get_combined_worth_for(entry) * max(1, contains[entry])
cost *= num_contained / total_contained // if you get a random selection, it costs the expected value rather than the total worth. gambling!
cost += containertype ? atom_info_repository.get_single_worth_for(containertype) : 0
cost = max(1, NONUNIT_CEILING((cost * WORTH_TO_SUPPLY_POINTS_CONSTANT * SSsupply.price_markup), WORTH_TO_SUPPLY_POINTS_ROUND_CONSTANT))
global.cargoprices[name] = cost
Expand Down
23 changes: 20 additions & 3 deletions code/game/atoms.dm
Original file line number Diff line number Diff line change
Expand Up @@ -742,17 +742,19 @@
- `post_climb_check?`: If we should check if the user can continue climbing
- Return: `TRUE` if they can climb, otherwise `FALSE`
*/
/atom/proc/can_climb(var/mob/living/user, post_climb_check=0)
/atom/proc/can_climb(mob/living/user, post_climb_check = FALSE, silent = FALSE)
if (!(atom_flags & ATOM_FLAG_CLIMBABLE) || !user.can_touch(src) || (!post_climb_check && climbers && (user in climbers)))
return FALSE

if (!user.Adjacent(src))
to_chat(user, "<span class='danger'>You can't climb there, the way is blocked.</span>")
if(!silent)
to_chat(user, SPAN_WARNING("You can't climb there, the way is blocked."))
return FALSE

var/obj/occupied = turf_is_crowded(user)
if(occupied)
to_chat(user, "<span class='danger'>There's \a [occupied] in the way.</span>")
if(!silent)
to_chat(user, SPAN_WARNING("There's \a [occupied] in the way."))
return FALSE
return TRUE

Expand Down Expand Up @@ -1065,3 +1067,18 @@
if(blood_color)
return FONT_COLORED(blood_color, "stained")
return null

// Used to mark a turf as containing objects that are dangerous to step onto.
/atom/proc/register_dangerous_to_step()
var/turf/T = get_turf(src)
if(T)
T.register_dangerous_object(src)

/atom/proc/unregister_dangerous_to_step()
var/turf/T = get_turf(src)
if(T)
T.unregister_dangerous_object(src)

// Test for if stepping on a tile containing this obj is safe to do, used for things like landmines and cliffs.
/atom/proc/is_safe_to_step(mob/living/stepper)
return TRUE
4 changes: 4 additions & 0 deletions code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -628,3 +628,7 @@

/atom/movable/proc/is_valid_merchant_pad_target()
return simulated

// TODO reimplement this properly.
/atom/movable/proc/is_incorporeal()
return !simulated
12 changes: 0 additions & 12 deletions code/game/jobs/access_datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,6 @@ var/global/const/access_research = "ACCESS_RESEARCH" //47
desc = "Science"
region = ACCESS_REGION_RESEARCH

var/global/const/access_explorer = "ACCESS_EXPLORER"
/datum/access/explorer
id = access_explorer
desc = "Explorer"
region = ACCESS_REGION_GENERAL

var/global/const/access_mining = "ACCESS_MINING" //48
/datum/access/mining
id = access_mining
Expand Down Expand Up @@ -310,12 +304,6 @@ var/global/const/access_xenobiology = "ACCESS_XENOBIO" //55
desc = "Xenobiology Lab"
region = ACCESS_REGION_RESEARCH

var/global/const/access_xenofauna = "ACCESS_XENOFAUNA"
/datum/access/xenofauna
id = access_xenofauna
desc = "Xenfauna Lab"
region = ACCESS_REGION_RESEARCH

var/global/const/access_ce = "ACCESS_CHIEF_ENGINEER" //56
/datum/access/ce
id = access_ce
Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/alarm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
TLV["temperature"] = list(T0C-26, T0C, T0C+40, T0C+66) // K

var/decl/environment_data/env_info = GET_DECL(environment_type)
for(var/g in decls_repository.get_decl_paths_of_subtype(/decl/material/gas))
for(var/g in get_filterable_material_types())
if(!env_info.important_gasses[g])
trace_gas += g
// not everything in these lists is a subtype of /decl/material/gas, so:
Expand Down
2 changes: 1 addition & 1 deletion code/game/machinery/atmoalter/scrubber.dm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
. = ..()
if(!scrubbing_gas)
scrubbing_gas = list()
for(var/g in decls_repository.get_decl_paths_of_subtype(/decl/material/gas))
for(var/g in get_filterable_material_types())
if(g != /decl/material/gas/oxygen && g != /decl/material/gas/nitrogen)
scrubbing_gas += g

Expand Down
1 change: 0 additions & 1 deletion code/game/objects/__objs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -493,4 +493,3 @@
if(anchored)
return FALSE
return ..()

Loading
Loading