Merge remote-tracking branch 'tgstation/master' into upstream-2025-11-29

# Conflicts:
#	_maps/RandomRuins/SpaceRuins/derelict_sulaco.dmm
#	_maps/RandomRuins/SpaceRuins/garbagetruck2.dmm
#	_maps/map_files/CatwalkStation/CatwalkStation_2023.dmm
#	_maps/map_files/tramstation/tramstation.dmm
#	code/_onclick/hud/new_player.dm
#	code/datums/components/squashable.dm
#	code/datums/diseases/advance/symptoms/heal.dm
#	code/datums/diseases/chronic_illness.dm
#	code/datums/status_effects/buffs.dm
#	code/datums/status_effects/debuffs/drunk.dm
#	code/datums/status_effects/debuffs/stamcrit.dm
#	code/game/machinery/computer/crew.dm
#	code/game/objects/items/devices/scanners/health_analyzer.dm
#	code/game/objects/items/wall_mounted.dm
#	code/game/turfs/closed/indestructible.dm
#	code/modules/admin/view_variables/filterrific.dm
#	code/modules/antagonists/heretic/influences.dm
#	code/modules/cargo/orderconsole.dm
#	code/modules/client/preferences.dm
#	code/modules/events/space_vines/vine_mutations.dm
#	code/modules/mob/dead/new_player/new_player.dm
#	code/modules/mob/living/carbon/human/death.dm
#	code/modules/mob/living/carbon/human/species_types/jellypeople.dm
#	code/modules/mob/living/damage_procs.dm
#	code/modules/mob/living/living.dm
#	code/modules/mob_spawn/ghost_roles/mining_roles.dm
#	code/modules/mob_spawn/mob_spawn.dm
#	code/modules/projectiles/ammunition/energy/laser.dm
#	code/modules/projectiles/guns/ballistic/launchers.dm
#	code/modules/projectiles/guns/energy/laser.dm
#	code/modules/reagents/chemistry/machinery/chem_dispenser.dm
#	code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm
#	code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm
#	code/modules/reagents/chemistry/reagents/medicine_reagents.dm
#	code/modules/surgery/healing.dm
#	code/modules/unit_tests/designs.dm
#	icons/mob/inhands/items_lefthand.dmi
#	icons/mob/inhands/items_righthand.dmi
#	tgui/packages/tgui/interfaces/ChemDispenser.tsx
This commit is contained in:
nevimer
2025-11-29 22:49:21 -05:00
1185 changed files with 39068 additions and 32028 deletions
@@ -739,11 +739,10 @@
. += bloodstep_overlay
if(emissive_alpha && emissive_alpha < alpha && !dried)
var/enter_emissive_state = "[enter_state]_emissive-[emissive_alpha]"
var/mutable_appearance/emissive_overlay = bloody_footprints_cache[enter_emissive_state]
var/enter_emissive_state = "[enter_state]_emissive-[Ddir]-[emissive_alpha]"
var/image/emissive_overlay = bloody_footprints_cache[enter_emissive_state]
if(!emissive_overlay)
emissive_overlay = blood_emissive(icon, "[icon_state_to_use]1")
emissive_overlay.dir = Ddir
emissive_overlay = image(blood_emissive(icon, "[icon_state_to_use]1"), dir = Ddir)
bloody_footprints_cache[enter_emissive_state] = emissive_overlay
. += emissive_overlay
@@ -756,11 +755,10 @@
. += bloodstep_overlay
if(emissive_alpha && emissive_alpha < alpha && !dried)
var/exit_emissive_state = "[exit_state]_emissive-[emissive_alpha]"
var/mutable_appearance/emissive_overlay = bloody_footprints_cache[exit_emissive_state]
var/exit_emissive_state = "[exit_state]_emissive-[Ddir]-[emissive_alpha]"
var/image/emissive_overlay = bloody_footprints_cache[exit_emissive_state]
if(!emissive_overlay)
emissive_overlay = blood_emissive(icon, "[icon_state_to_use]2")
emissive_overlay.dir = Ddir
emissive_overlay = image(blood_emissive(icon, "[icon_state_to_use]2"), dir = Ddir)
bloody_footprints_cache[exit_emissive_state] = emissive_overlay
. += emissive_overlay
@@ -78,8 +78,9 @@
/obj/effect/decal/cleanable/fuel_pool/bullet_act(obj/projectile/hit_proj)
. = ..()
ignite()
log_combat(hit_proj.firer, src, "used [hit_proj] to ignite")
if(hit_proj.damage > 0)
ignite()
log_combat(hit_proj.firer, src, "used [hit_proj] to ignite")
/obj/effect/decal/cleanable/fuel_pool/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers)
if(item.ignition_effect(src, user))
@@ -187,8 +187,7 @@
//Bottom
/obj/effect/turf_decal/syndicateemblem/bottom/left/obj/effect/turf_decal/raven/nine
icon_state = "RAVEN9"
/obj/effect/turf_decal/syndicateemblem/bottom/left
icon_state = "synd1,1"
/obj/effect/turf_decal/syndicateemblem/bottom/middle
@@ -207,7 +207,7 @@
return
smoker.drop_all_held_items()
smoker.adjustOxyLoss(1)
smoker.adjust_oxy_loss(1)
smoker.emote("cough")
/**
+60 -77
View File
@@ -18,13 +18,9 @@
force = 0
resistance_flags = FLAMMABLE
w_class = WEIGHT_CLASS_SMALL
var/poster_type
var/obj/structure/sign/poster/poster_type
var/obj/structure/sign/poster/poster_structure
/obj/item/poster/examine(mob/user)
. = ..()
. += span_notice("You can booby-trap the poster by using a glass shard on it before you put it up.")
/obj/item/poster/Initialize(mapload, obj/structure/sign/poster/new_poster_structure)
. = ..()
@@ -36,22 +32,21 @@
AddElement(/datum/element/contextual_screentip_item_typechecks, hovering_item_typechecks)
if(new_poster_structure && (new_poster_structure.loc != src))
new_poster_structure.forceMove(src) //The poster structure *must* be in the item's contents for the exited() proc to properly clean up when placing the poster
qdel(new_poster_structure.GetComponent(/datum/component/atom_mounted))
new_poster_structure.forceMove(src)
poster_structure = new_poster_structure
if(!new_poster_structure && poster_type)
poster_structure = new poster_type(src)
if(poster_type)
name = "[poster_type::poster_item_name] - [poster_type::original_name]"
desc = poster_type::poster_item_desc
icon_state = poster_type::poster_item_icon_state
// posters store what name and description they would like their
// rolled up form to take.
if(poster_structure)
if(QDELETED(poster_structure))
stack_trace("A poster was initialized with a qdeleted poster_structure, something's gone wrong")
return INITIALIZE_HINT_QDEL
name = poster_structure.poster_item_name
desc = poster_structure.poster_item_desc
icon_state = poster_structure.poster_item_icon_state
/obj/item/poster/Destroy(force)
QDEL_NULL(poster_structure)
return ..()
name = "[name] - [poster_structure.original_name]"
/obj/item/poster/examine(mob/user)
. = ..()
. += span_notice("You can booby-trap the poster by using a glass shard on it before you put it up.")
/obj/item/poster/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers)
if(!istype(I, /obj/item/shard))
@@ -67,22 +62,49 @@
poster_structure.trap = WEAKREF(I)
to_chat(user, span_notice("You conceal \the [I] inside the rolled up poster."))
/obj/item/poster/Exited(atom/movable/gone, direction)
. = ..()
if(gone == poster_structure)
poster_structure = null
if(!QDELING(src))
qdel(src) //we're now a poster, huzzah!
/obj/item/poster/interact_with_atom(turf/closed/wall_structure, mob/living/user, list/modifiers)
if(!isclosedturf(wall_structure))
return NONE
/obj/item/poster/Destroy(force)
QDEL_NULL(poster_structure)
return ..()
// Deny placing posters on currently-diagonal walls, although the wall may change in the future.
if (wall_structure.smoothing_flags & SMOOTH_DIAGONAL_CORNERS)
for(var/overlay in wall_structure.overlays)
var/image/new_image = overlay
if(copytext(new_image.icon_state, 1, 3) == "d-") //3 == length("d-") + 1
to_chat(user, span_warning("Cannot place on diagonal wall!"))
return ITEM_INTERACT_FAILURE
// The poster sign/structure
var/stuff_on_wall = 0
for(var/obj/contained_object in wall_structure.contents) //Let's see if it already has a poster on it or too much stuff
if(istype(contained_object, /obj/structure/sign/poster))
balloon_alert(user, "no room!")
return ITEM_INTERACT_FAILURE
stuff_on_wall++
if(stuff_on_wall == 3)
balloon_alert(user, "no room!")
return ITEM_INTERACT_FAILURE
balloon_alert(user, "hanging poster...")
var/obj/structure/sign/poster/placed_poster = poster_structure || new poster_type(src)
placed_poster.poster_item_type = type
placed_poster.forceMove(wall_structure)
poster_structure = null
flick("poster_being_set", placed_poster)
playsound(src, 'sound/items/poster/poster_being_created.ogg', 100, TRUE)
qdel(src)
var/turf/user_drop_location = get_turf(user)
if(!do_after(user, PLACE_SPEED, placed_poster, extra_checks = CALLBACK(placed_poster, TYPE_PROC_REF(/obj/structure/sign/poster, snowflake_closed_turf_check), wall_structure)))
placed_poster.roll_and_drop(user_drop_location, user)
return ITEM_INTERACT_FAILURE
placed_poster.setDir(get_dir(user_drop_location, wall_structure))
placed_poster.find_and_hang_on_atom()
placed_poster.on_placed_poster(user)
return ITEM_INTERACT_SUCCESS
/**
* The structure form of a poster.
*
* These are what get placed on maps as posters. They are also what gets created when a player places a poster on a wall.
* For the item form that can be spawned for players, see [/obj/item/poster]
*/
@@ -172,15 +194,15 @@
desc = holi_data.poster_desc
icon_state = holi_data.poster_icon
/obj/structure/sign/poster/attackby(obj/item/tool, mob/user, list/modifiers, list/attack_modifiers)
if(tool.tool_behaviour == TOOL_WIRECUTTER)
tool.play_tool_sound(src, 100)
if(ruined)
to_chat(user, span_notice("You remove the remnants of the poster."))
qdel(src)
else
to_chat(user, span_notice("You carefully remove the poster from the wall."))
roll_and_drop(Adjacent(user) ? get_turf(user) : loc, user)
/obj/structure/sign/poster/wirecutter_act(mob/living/user, obj/item/tool)
tool.play_tool_sound(src, 100)
if(ruined)
to_chat(user, span_notice("You remove the remnants of the poster."))
qdel(src)
else
to_chat(user, span_notice("You carefully remove the poster from the wall."))
roll_and_drop(Adjacent(user) ? get_turf(user) : loc, user)
return ITEM_INTERACT_SUCCESS
/obj/structure/sign/poster/attack_hand(mob/user, list/modifiers)
. = ..()
@@ -224,45 +246,6 @@
/obj/structure/sign/poster/proc/return_to_poster_item(atom/location)
return new poster_item_type(location, src)
//separated to reduce code duplication. Moved here for ease of reference and to unclutter r_wall/attackby()
/turf/closed/proc/place_poster(obj/item/poster/rolled_poster, mob/user)
if(!rolled_poster.poster_structure)
to_chat(user, span_warning("[rolled_poster] has no poster... inside it? Inform a coder!"))
return
// Deny placing posters on currently-diagonal walls, although the wall may change in the future.
if (smoothing_flags & SMOOTH_DIAGONAL_CORNERS)
for (var/overlay in overlays)
var/image/new_image = overlay
if(copytext(new_image.icon_state, 1, 3) == "d-") //3 == length("d-") + 1
return
var/stuff_on_wall = 0
for(var/obj/contained_object in contents) //Let's see if it already has a poster on it or too much stuff
if(istype(contained_object, /obj/structure/sign/poster))
balloon_alert(user, "no room!")
return
stuff_on_wall++
if(stuff_on_wall == 3)
balloon_alert(user, "no room!")
return
balloon_alert(user, "hanging poster...")
var/obj/structure/sign/poster/placed_poster = rolled_poster.poster_structure
flick("poster_being_set", placed_poster)
placed_poster.forceMove(src) //deletion of the poster is handled in poster/Exited(), so don't have to worry about P anymore.
placed_poster.find_and_hang_on_wall()
playsound(src, 'sound/items/poster/poster_being_created.ogg', 100, TRUE)
var/turf/user_drop_location = get_turf(user) //cache this so it just falls to the ground if they move. also no tk memes allowed.
if(!do_after(user, PLACE_SPEED, placed_poster, extra_checks = CALLBACK(placed_poster, TYPE_PROC_REF(/obj/structure/sign/poster, snowflake_closed_turf_check), src)))
placed_poster.roll_and_drop(user_drop_location, user)
return
placed_poster.on_placed_poster(user)
return TRUE
/obj/structure/sign/poster/proc/snowflake_closed_turf_check(atom/hopefully_still_a_closed_turf) //since turfs never get deleted but instead change type, make sure we're still being placed on a wall.
return isclosedturf(hopefully_still_a_closed_turf)
@@ -30,7 +30,7 @@
/obj/effect/spawner/costume/madscientist
name = "mad scientist costume spawner"
items = list(
/obj/item/clothing/under/rank/captain/suit,
/obj/item/clothing/under/costume/captain,
/obj/item/clothing/head/flatcap,
/obj/item/clothing/suit/toggle/labcoat/mad,
)
@@ -38,7 +38,7 @@
/obj/effect/spawner/costume/elpresidente
name = "el presidente costume spawner"
items = list(
/obj/item/clothing/under/rank/captain/suit,
/obj/item/clothing/under/costume/captain,
/obj/item/clothing/head/flatcap,
/obj/item/cigarette/cigar/havana,
/obj/item/clothing/shoes/jackboots,
@@ -62,6 +62,33 @@
icon_state = "laser_gun"
loot = list(/obj/item/gun/energy/laser)
/obj/effect/spawner/random/armory/laser_pistol
name = "laser pistol spawner"
icon_state = "laser_gun"
spawn_loot_count = 6
loot = list(/obj/item/gun/energy/laser/pistol)
/obj/effect/spawner/random/armory/laser_carbine
name = "laser_carbine spawner"
icon_state = "laser_gun"
loot = list(/obj/item/gun/energy/laser/carbine)
/obj/effect/spawner/random/armory/assault_laser
name = "assault laser gun spawner"
icon_state = "laser_gun"
spawn_loot_count = 1
loot = list(/obj/item/gun/energy/laser/assault)
/obj/effect/spawner/random/armory/pick_laser_loadout
name = "laser gun type randomizer"
icon_state = "laser_gun"
spawn_loot_count = 1
loot = list(
/obj/effect/spawner/random/armory/laser_gun = 30,
/obj/effect/spawner/random/armory/laser_carbine = 30,
/obj/effect/spawner/random/armory/laser_pistol = 10,
)
/obj/effect/spawner/random/armory/e_gun
name = "energy gun spawner"
icon_state = "e_gun"