Skip to content

Commit

Permalink
Merge Upstream 16.01.2025 (#1750)
Browse files Browse the repository at this point in the history
This pull request merges upstream/master. Resolve possible conflicts
manually and make sure all the changes are applied correctly.

> [!NOTE]
> Requires Wiki Update:
> www.github.com/ParadiseSS13/Paradise/pull/27894
> www.github.com/ParadiseSS13/Paradise/pull/27911

## Changelog
:cl: ParadiseSS13
fix: Исправлена ошибка, из-за которой медицинские сканеры всегда
показывали случайное время смерти. <!-- Fixed an oversight with health
scanners always showing random death times.
(www.github.com/ParadiseSS13/Paradise/pull/27983) -->
add: Добавлены крупные и блюспейс-версии переносного воздушного насоса.
Их нельзя найти на станции. <!-- Large and bluespace versions of the
portable air pump. They are not available on station.
(www.github.com/ParadiseSS13/Paradise/pull/27894) -->
tweak: Теперь воздушные насосы могут достигать давления до 45 атмосфер
(раньше было 10), что соответствует давлению в баллоне. <!-- Air pumps
can now reach up to 45 atm, up from 10 and matching a canister.
(www.github.com/ParadiseSS13/Paradise/pull/27894) -->
tweak: Воздушные насосы теперь изначально полностью заполнены воздухом.
<!-- Air pumps now start filled to capacity with air.
(www.github.com/ParadiseSS13/Paradise/pull/27894) -->
tweak: Хранилище инженерного отряда быстрого реагирования (ERT) было
расширено, оснащено стеллажами с ресурсами и содержит различное
оборудование. <!-- Engineering ERT storage area has been expanded, uses
shelving, and has several bluespace portable air pumps for all your
refilling needs. (www.github.com/ParadiseSS13/Paradise/pull/27894) -->
imageadd: Химические пожары получили обновлённые спрайты. Некоторые из
них теперь имеют новые цвета. <!-- chemical fires have been resprited!
Some have new colors! (www.github.com/ParadiseSS13/Paradise/pull/27911)
-->
tweak: Алгоритм покрытия метеорного щита был изменён: теперь он
использует симуляцию метеоритов, падающих на станцию. Это означает, что
100% покрытия теперь обеспечивают (почти) полную защиту станции. <!--
The meteor shield coverage algorithm has been changed to throw simulated
meteors at the station. This means that 100% coverage is now (close to)
complete protection of the station.
(www.github.com/ParadiseSS13/Paradise/pull/27937) -->
tweak: Компьютер управления спутника щита был полностью переработан и
теперь отображает симуляцию покрытия в реальном времени. <!-- The shield
satellite control computer has been given a complete overhaul, and will
now display the coverage simulation in real time.
(www.github.com/ParadiseSS13/Paradise/pull/27937) -->
tweak: Цель по покрытию метеорного щита теперь считается выполненной при
достижении 75% покрытия. Для расчёта покрытия необходимо выполнить
симуляцию с использованием компьютера управления. <!-- The meteor shield
goal is now considered complete at 75% coverage. You must perform a
simulation with the control computer to calculate your coverage.
(www.github.com/ParadiseSS13/Paradise/pull/27937) -->
tweak: Контейнеры со щитами для спутника стали дешевле (с 250 до 100) и
теперь содержат больше щитов (с 3 до 4), чтобы компенсировать
увеличившуюся сложность защиты. <!-- Shield sat crates are now cheaper
(250 -> 100) and contain more shields (3 -> 4) to account for the
increased difficulty of coverage.
(www.github.com/ParadiseSS13/Paradise/pull/27937) -->
/:cl:

## Summary by Sourcery

Update the health scanner to display the correct time of death. Add
large and bluespace versions of the portable air pump, which are not
available on the station. Increase the maximum pressure of air pumps to
45 atm and pre-fill them with air. Expand the engineering ERT storage
area with shelving and bluespace portable air pumps. Resprite chemical
fires with new colors. Change the meteor shield coverage algorithm to
simulate meteor impacts, requiring 75% coverage for completion. Redesign
the shield satellite control computer to display real-time coverage
simulation. Reduce the cost of shield sat crates from 250 to 100 and
increase the number of shields from 3 to 4.

New Features:
- Add large and bluespace portable air pumps.
- Add real-time meteor shield coverage simulation to the shield
satellite control computer.

Bug Fixes:
- Fix an issue where health scanners always displayed a random time of
death.

Tests:
- Prevent fake meteors from triggering meteor alerts.
  • Loading branch information
AyIong authored Jan 16, 2025
2 parents 08786ee + 7718a44 commit 5915804
Show file tree
Hide file tree
Showing 17 changed files with 1,644 additions and 1,064 deletions.
553 changes: 268 additions & 285 deletions _maps/map_files/generic/centcomm.dmm

Large diffs are not rendered by default.

1,512 changes: 890 additions & 622 deletions _maps/map_files220/generic/centcomm.dmm

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions code/_onclick/hud/follow_alert.dm
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@
/atom/movable/screen/alert/augury/meteor/process()
var/overridden = FALSE
for(var/obj/effect/meteor/M in GLOB.meteor_list)
if(istype(M, /obj/effect/meteor/fake))
continue // Meteor? What meteor?
if(!is_station_level(M.z))
continue // don't worry about endlessly looping
if(istype(M, /obj/effect/meteor/tunguska) && !overridden)
Expand Down
46 changes: 46 additions & 0 deletions code/game/objects/effects/meteors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,52 @@ GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/meaty = 5, /obj/effect/me
//Meteor types
///////////////////////

//Fake
/obj/effect/meteor/fake
name = "simulated meteor"
desc = "A simulated meteor for testing shield satellites. How did you see this, anyway?"
invisibility = INVISIBILITY_MAXIMUM
density = FALSE
pass_flags = NONE
/// The station goal that is simulating this meteor.
var/datum/station_goal/station_shield/goal
/// Did we crash into something? Used to avoid falsely reporting success when qdeleted.
var/failed = FALSE

/obj/effect/meteor/fake/Initialize(mapload)
. = ..()
for(var/datum/station_goal/station_shield/found_goal in SSticker.mode.station_goals)
goal = found_goal
return

/obj/effect/meteor/fake/Destroy()
if(!failed)
succeed()
goal = null
return ..()

/obj/effect/meteor/fake/ram_turf(turf/T)
if(!isspaceturf(T))
fail()
return
for(var/thing in T)
if(isobj(thing) && !iseffect(thing))
fail()
return

/obj/effect/meteor/fake/get_hit()
return

/obj/effect/meteor/fake/proc/succeed()
if(istype(goal))
goal.update_coverage(TRUE, get_turf(src))

/obj/effect/meteor/fake/proc/fail()
if(istype(goal))
goal.update_coverage(FALSE, get_turf(src))
failed = TRUE
qdel(src)

//Dust
/obj/effect/meteor/dust
name = "space dust"
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/devices/scanners.dm
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ SLIME SCANNER
msgs += "Damage Specifics: <span class='healthscan_oxy'>[OX]</span> - <font color='green'>[TX]</font> - <font color='#FFA500'>[BU]</font> - <font color='red'>[BR]</font>"

if(H.timeofdeath && (H.stat == DEAD || (HAS_TRAIT(H, TRAIT_FAKEDEATH)) || probably_dead))
var/tod = probably_dead || (HAS_TRAIT(user, TRAIT_MED_MACHINE_HALLUCINATING) && prob(10)) ? world.time - rand(10, 5000) : H.timeofdeath // Sure let's blow it out
var/tod = probably_dead && (HAS_TRAIT(user, TRAIT_MED_MACHINE_HALLUCINATING) && prob(10)) ? world.time - rand(10, 5000) : H.timeofdeath // Sure let's blow it out
msgs += "<span class='notice'>Time of Death: [station_time_timestamp("hh:mm:ss", tod)]</span>"
var/tdelta = round(world.time - tod)
if(H.is_revivable() && !DNR)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
var/canister_burn_duration = 10 SECONDS
/// How many firestacks will our reagent apply
var/canister_fire_applications = 1
/// Does our chemical have any special color?
var/canister_fire_color
/// How much ammo do we use per tile?
var/ammo_usage = 1
/// Is this a syndicate flamethrower
Expand Down Expand Up @@ -90,23 +92,28 @@
canister_burn_temp = null
canister_burn_duration = null
canister_fire_applications = null
canister_fire_color = null
return

var/burn_temp
var/burn_duration
var/fire_applications
var/how_many_canisters = length(canisters)
var/list/colors = list()

for(var/obj/item/chemical_canister/canister as anything in canisters)
if(!canister.ammo)
continue
burn_temp += canister.chem_burn_temp
burn_duration += canister.chem_burn_duration
fire_applications += canister.fire_applications
colors += canister.chem_color

canister_burn_temp = round(burn_temp / how_many_canisters, 1)
canister_burn_duration = round(burn_duration / how_many_canisters, 1)
canister_fire_applications = round(fire_applications / how_many_canisters, 1)
if(length(colors))
canister_fire_color = pick(colors)
update_icon(UPDATE_OVERLAYS)

/obj/item/chemical_flamethrower/afterattack__legacy__attackchain(atom/target, mob/user, flag)
Expand Down Expand Up @@ -159,7 +166,8 @@
previousturf = T

/obj/item/chemical_flamethrower/proc/make_flame(turf/spawn_turf)
new /obj/effect/fire(spawn_turf, canister_burn_temp, (canister_burn_duration + rand(1, 3) SECONDS), canister_fire_applications) // For that spicy randomness (and to save your ears from all fires extinguishing at the same time)
// For that spicy randomness (and to save your ears from all fires extinguishing at the same time)
new /obj/effect/fire(spawn_turf, canister_burn_temp, (canister_burn_duration + rand(1, 3) SECONDS), canister_fire_applications, canister_fire_color)

/*
* Uses `amount` ammo from the flamethrower.
Expand Down Expand Up @@ -232,6 +240,8 @@
var/first_time_silent = FALSE // The reason for this is so we can have canisters that spawn with reagents but don't announce it on `Initialize()`
/// What chemical do we have? This will be the chemical ID, so a string
var/stored_chemical
/// What color will our fire burn
var/chem_color

/obj/item/chemical_canister/Initialize(mapload)
. = ..()
Expand Down Expand Up @@ -273,6 +283,8 @@
chem_burn_duration = reagent_to_burn.burn_duration
chem_burn_temp = reagent_to_burn.burn_temperature
fire_applications = reagent_to_burn.fire_stack_applications
if(reagent_to_burn.burn_color)
chem_color = reagent_to_burn.burn_color
ammo = initial(ammo)
has_filled_reagent = TRUE
reagents.clear_reagents()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ GLOBAL_LIST_EMPTY(flame_effects)
name = "fire"
desc = "You don't think you should touch this."
icon = 'icons/effects/chemical_fire.dmi'
icon_state = "fire1"

icon_state = "red_small"
base_icon_state = "red"
/// How hot is our fire?
var/temperature
/// How long will our fire last
var/duration = 10 SECONDS
/// How many firestacks does the fire give to mobs
var/application_stacks = 1

/obj/effect/fire/Initialize(mapload, reagent_temperature, reagent_duration, fire_applications)
/obj/effect/fire/Initialize(mapload, reagent_temperature, reagent_duration, fire_applications, color)
. = ..()

if(reagent_duration < 0 || reagent_temperature <= 0) // There is no reason for this thing to exist
Expand All @@ -24,6 +24,9 @@ GLOBAL_LIST_EMPTY(flame_effects)
duration = reagent_duration
temperature = reagent_temperature
application_stacks = max(application_stacks, fire_applications)
if(color)
base_icon_state = color
update_icon()

for(var/obj/effect/fire/flame in get_turf(src))
if(!istype(flame) || flame == src)
Expand All @@ -48,6 +51,7 @@ GLOBAL_LIST_EMPTY(flame_effects)
fizzle()
return
duration -= 2 SECONDS
update_icon(UPDATE_ICON_STATE)

for(var/atom/movable/thing_to_burn in get_turf(src))
if(isliving(thing_to_burn))
Expand All @@ -68,6 +72,14 @@ GLOBAL_LIST_EMPTY(flame_effects)
var/datum/milla_safe/fire_heat_air/milla = new()
milla.invoke_async(src, location)

/obj/effect/fire/update_icon_state()
var/suffix = "small"
if(duration >= 30 SECONDS)
suffix = "big"
else if(duration >= 10 SECONDS)
suffix = "medium"
icon_state = "[base_icon_state]_[suffix]"

/datum/milla_safe/fire_heat_air

/datum/milla_safe/fire_heat_air/on_run(obj/effect/fire/fire, turf/T)
Expand All @@ -79,6 +91,7 @@ GLOBAL_LIST_EMPTY(flame_effects)
duration -= 10 SECONDS
if(duration <= 0)
fizzle()
update_icon(UPDATE_ICON_STATE)

/obj/effect/fire/proc/on_atom_entered(datum/source, atom/movable/entered, old_loc)
SIGNAL_HANDLER // COMSIG_ATOM_ENTERED
Expand Down
49 changes: 43 additions & 6 deletions code/modules/atmospherics/machinery/portable/portable_pump.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/// The maximum `target_pressure` you can set on the pump. Equates to about 1013.25 kPa.
#define MAX_TARGET_PRESSURE 10 * ONE_ATMOSPHERE
/// The maximum `target_pressure` you can set on the pump.
#define MAX_TARGET_PRESSURE 45 * ONE_ATMOSPHERE
/// The pump will be siphoning gas.
#define DIRECTION_IN 0
/// The pump will be pumping gas out.
Expand All @@ -9,7 +9,9 @@
/obj/machinery/atmospherics/portable/pump
name = "portable air pump"
icon = 'icons/obj/atmos.dmi'
icon_state = "psiphon:0"
icon_state = "ppump:0"
base_icon_state = "ppump"
var/base_attachment_icon_state = "ppump"
density = TRUE
volume = 1000
/// The direction the pump is operating in. This should be either `DIRECTION_IN` or `DIRECTION_OUT`.
Expand All @@ -18,6 +20,12 @@
target_pressure = 101.325
resistance_flags = NONE

/obj/machinery/atmospherics/portable/pump/Initialize(mapload)
. = ..()
// Fill with normal air.
air_contents.set_oxygen(MAX_TARGET_PRESSURE * O2STANDARD * volume / (T20C * R_IDEAL_GAS_EQUATION))
air_contents.set_nitrogen(MAX_TARGET_PRESSURE * N2STANDARD * volume / (T20C * R_IDEAL_GAS_EQUATION))

/obj/machinery/atmospherics/portable/pump/examine(mob/user)
. = ..()
. += "<span class='notice'>Invaluable for filling air in a room rapidly after a breach repair. The internal gas container can be filled by \
Expand All @@ -26,14 +34,14 @@
A tank of gas can also be attached to the air pump, allowing you to fill or empty the tank, via the internal one.</span>"

/obj/machinery/atmospherics/portable/pump/update_icon_state()
icon_state = "psiphon:[on]"
icon_state = "[base_icon_state]:[on]"

/obj/machinery/atmospherics/portable/pump/update_overlays()
. = ..()
if(holding_tank)
. += "siphon-open"
. += "[base_attachment_icon_state]-open"
if(connected_port)
. += "siphon-connector"
. += "[base_attachment_icon_state]-connector"

/obj/machinery/atmospherics/portable/pump/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
Expand Down Expand Up @@ -166,6 +174,7 @@
direction = DIRECTION_OUT
if(on && holding_tank)
investigate_log("[key_name(usr)] started a transfer into [holding_tank].<br>", "atmos")
update_icon()
return TRUE

if("remove_tank")
Expand All @@ -179,6 +188,34 @@

add_fingerprint(usr)

/obj/machinery/atmospherics/portable/pump/big
name = "large portable air pump"
icon_state = "ppump_big:0"
base_icon_state = "ppump_big"
base_attachment_icon_state = "ppump_big"
volume = 5000

/obj/machinery/atmospherics/portable/pump/big/examine(mob/user)
. = ..()
. += "<br><span class='notice'>This one is quite large, enabling it to hold more air.</span>"

/obj/machinery/atmospherics/portable/pump/bluespace
name = "bluespace portable air pump"
icon_state = "ppump_bs:0"
base_icon_state = "ppump_bs"
base_attachment_icon_state = "ppump_big"
volume = 25000

/obj/machinery/atmospherics/portable/pump/bluespace/examine(mob/user)
. = ..()
. += "<br><span class='notice'>This one is not only large, but made of exotic materials, and uses bluespace technology to hold even more air.</span>"

/obj/machinery/atmospherics/portable/pump/bluespace/update_icon_state()
if(on && direction == DIRECTION_IN)
icon_state = "[base_icon_state]:[on]-r"
else
icon_state = "[base_icon_state]:[on]"

#undef MAX_TARGET_PRESSURE
#undef DIRECTION_IN
#undef DIRECTION_OUT
4 changes: 2 additions & 2 deletions code/modules/atmospherics/machinery/portable/scrubber.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
/obj/machinery/atmospherics/portable/scrubber/update_overlays()
. = ..()
if(holding_tank)
. += "scrubber-open"
. += "pscrubber-open"
if(connected_port)
. += "scrubber-connector"
. += "pscrubber-connector"

/obj/machinery/atmospherics/portable/scrubber/process_atmos()
..()
Expand Down
4 changes: 4 additions & 0 deletions code/modules/reagents/chemistry/reagents/pyrotechnic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
taste_description = "burning"
burn_temperature = T0C + 500
burn_duration = 20 SECONDS
burn_color = "white"
var/temp_fire = 4000
var/temp_deviance = 1000
var/size_divisor = 40
Expand Down Expand Up @@ -46,6 +47,7 @@
size_divisor = 80
mob_burning = 3 // 15
burn_temperature = T0C + 700
burn_color = "white"

/datum/reagent/napalm
name = "Napalm"
Expand Down Expand Up @@ -198,6 +200,7 @@
taste_description = "rust"
burn_temperature = T0C + 1500 // hahahahHAHAHAHAH LET IT BURN
burn_duration = 5 SECONDS // Not for long though
burn_color = "blue" // too hot!

/datum/reagent/thermite/reaction_mob(mob/living/M, method= REAGENT_TOUCH, volume)
if(method == REAGENT_TOUCH)
Expand Down Expand Up @@ -253,6 +256,7 @@
burn_temperature = T0C + 700
burn_duration = 15 SECONDS
fire_stack_applications = 3
burn_color = "green"

/datum/reagent/clf3/on_mob_life(mob/living/M)
if(M.on_fire)
Expand Down
2 changes: 2 additions & 0 deletions code/modules/reagents/chemistry/reagents_datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
var/burn_duration = 30 SECONDS
/// How many firestacks will the reagent apply when it is burning? Currently only used for chemical flamethrowers
var/fire_stack_applications = 1
/// If we burn in a fire, what color do we have?
var/burn_color

/datum/reagent/Destroy()
. = ..()
Expand Down
Loading

0 comments on commit 5915804

Please sign in to comment.