Add ashtray persistence & fixes (#21925)

# Summary

This PR adds persistency to ash trays. This in turn fixes cigarettes
butts spawning a round later in locations where non-empty ash trays were
found.

## Changes

- Add persistence to ash trays and prevent (fixes) cigarette butt
persistence if in an ash tray.
- Fixed cigarette butts not being persistent if the cigarette was put
out on purpose and landing on the floor.
- Fixed loss of registered persistence track on item pickup.
- Fixed persistent tracks when item is held by player.
- Removed all ash trays on the Horizon as their existence is now
persistent. One-time job for operations after merge.
- Fixed matter configuration on `/obj/item/material` not being set
during `set_material()`.
- Fixed persistent trash on space turfs.
- Minor adjustments in SQL/Readme.md.

---------

Signed-off-by: FabianK3 <21039694+FabianK3@users.noreply.github.com>
Co-authored-by: VMSolidus <evilexecutive@gmail.com>
This commit is contained in:
FabianK3
2026-03-17 14:12:57 +01:00
committed by GitHub
parent b56522f6e5
commit 6c4e9254b2
12 changed files with 74 additions and 88 deletions
+6 -3
View File
@@ -172,17 +172,20 @@ and changes are stored in volumes.
services:
flyway:
image: flyway/flyway
command: -url=jdbc:mysql://db -user=root -password=P@ssw0rd -workingDirectory="project" migrate
command: -url=jdbc:mysql://db -user=root -password=my-password -defaultSchema=aurora migrate
volumes:
- ./SQL/migrate-VERSION:/flyway/project # Pathing!
- ./SQL/migrate-VERSION:/flyway/sql # Pathing!
depends_on:
- db
db:
image: mariadb
environment:
MARIADB_ROOT_PASSWORD: Pssw0rd
MARIADB_ROOT_PASSWORD: my-password
volumes:
- aurora:/var/lib/mysql:Z
ports:
- 3306:3306
volumes:
aurora:
```
+6
View File
@@ -90,6 +90,12 @@
* The item will be added to the late_loaders list, this is iterated over after
* initalization of subsystems is complete and calls LateInitalize on the atom
* see [this file for the LateIntialize proc](atom.html#proc/LateInitialize)
*
* It's worth noting that LateInitialize will allow the persistence subsystem to apply content,
* which might be needed during the objects init process supplied via Init arguments,
* as the init by the persistence subsystems doesn't provide init arguments.
* Persistence subsystem instanciates object -> LateInit is returned
* -> Persistence subsystem applies content -> LateInit is called to finish the whole init process.
*/
#define INITIALIZE_HINT_LATELOAD 1
+15 -2
View File
@@ -37,6 +37,10 @@ SUBSYSTEM_DEF(persistence)
var/typepath = text2path(data["type"])
if (!ispath(typepath)) // Type checking
continue
// Note that the object here is instantiated without init args.
// Objects that require init args should fall back to INITALIZE_HINT_LATELOAD during Init,
// as this will give the subsystem the chance to apply the content and
// the object to continue with init logic after the subsystem is done in LateInitialize.
var/obj/instance = new typepath()
instance.persistence_track_id = data["id"]
track_apply_content(instance, data["content"], data["x"], data["y"], data["z"])
@@ -61,6 +65,15 @@ SUBSYSTEM_DEF(persistence)
// Update tracked objects that have an ID (already existing from previous rounds)
// Delete persistent records that no longer exist in the registry (removed during the round)
// Run checks on each track that might prevent further persistence
for (var/obj/track in GLOB.persistence_register)
CHECK_TICK
var/turf/T = get_turf(track)
if(!T || !is_station_level(T.z)) // The persistence system only supports objects from the main map levels for multiple reasons, e.g. Z level value, mapping support
deregister_track(track)
if(astype(track, /obj/item)?.in_inventory) // Objects that are held by players won't become persistent
deregister_track(track)
var/created = 0
var/updated = 0
var/expired = 0
@@ -205,7 +218,7 @@ SUBSYSTEM_DEF(persistence)
log_subsystem_persistence("SQL ERROR during persistence database_add_entry. Failed to connect.")
else
var/turf/T = get_turf(track)
if(!T || !is_station_level(T.z)) // The persistence system only supports objects from the main map levels for multiple reasons, e.g. Z level value, mapping support
if(!T)
return
var/datum/db_query/insert_query = SSdbcore.NewQuery(
@@ -235,7 +248,7 @@ SUBSYSTEM_DEF(persistence)
log_subsystem_persistence("SQL ERROR during persistence database_update_entry. Failed to connect.")
else
var/turf/T = get_turf(track)
if(!T || !is_station_level(T.z)) // The persistence system only supports objects from the main map levels for multiple reasons, e.g. Z level value, mapping support
if(!T)
return
var/datum/db_query/update_query = SSdbcore.NewQuery(
-3
View File
@@ -629,9 +629,6 @@
user.update_equipment_speed_mods()
if(persistency_considered_trash || persistence_track_active) // The moment trash like items get picked up they are no longer persistent
SSpersistence.deregister_track(src)
/obj/item/proc/check_equipped(var/mob/user, var/slot, var/assisted_equip = FALSE)
return TRUE
@@ -246,6 +246,7 @@ ABSTRACT_TYPE(/obj/item/clothing/mask/smokable)
to_chat(M, SPAN_NOTICE("Your [name] goes out."))
if(intentionally)
butt.loc = T
butt.try_make_persistent_trash()
else if(M.wear_mask == src)
M.remove_from_mob(src) //un-equip it so the overlays can update
M.update_inv_wear_mask(0)
@@ -11,11 +11,32 @@
/obj/item/material/ashtray/Initialize(newloc, material_key)
. = ..()
if(!material)
return INITIALIZE_HINT_QDEL
persistance_expiration_time_days = rand(7, 180) // Imagine they get stolen, lost or break...
max_butts = round(material.hardness/10) //This is arbitrary but whatever.
randpixel_xy()
update_icon()
SSpersistence.register_track(src, null)
/obj/item/material/ashtray/persistence_get_content()
var/list/content = list()
content["fill_count"] = length(contents)
content["material"] = material.name
return content
/obj/item/material/ashtray/persistence_apply_content(content, x, y, z)
src.x = x
src.y = y
src.z = z
if(content["material"])
set_material(content["material"])
max_butts = round(material.hardness/10)
var/fill_count = content["fill_count"]
if(fill_count)
if(fill_count > max_butts)
fill_count = max_butts
for(var/i = 1; i <= fill_count; i++)
var/obj/item/trash/cigbutt/cigarbutt/cigbutt = new /obj/item/trash/cigbutt(src)
cigbutt.forceMove(src)
/obj/item/material/ashtray/shatter()
..()
@@ -67,6 +88,9 @@
user.remove_from_mob(attacking_item)
attacking_item.forceMove(src)
if(istype(attacking_item, /obj/item/trash/cigbutt))
SSpersistence.deregister_track(attacking_item) // Ashtray will handle the persistent contents in it itself
if (istype(attacking_item,/obj/item/clothing/mask/smokable/cigarette))
var/obj/item/clothing/mask/smokable/cigarette/cig = attacking_item
if (cig.lit == TRUE)
@@ -36,12 +36,6 @@
qdel(src)
return
matter = material.get_matter()
if(matter.len)
for(var/material_type in matter)
if(!isnull(matter[material_type]))
matter[material_type] *= force_divisor // May require a new var instead.
/obj/item/material/should_equip()
return TRUE
@@ -85,6 +79,11 @@
START_PROCESSING(SSprocessing, src)
update_force()
matter = material.get_matter()
for(var/material_type in matter)
if(!isnull(matter[material_type]))
matter[material_type] *= force_divisor // May require a new var instead.
/obj/item/material/Destroy()
STOP_PROCESSING(SSprocessing, src)
return ..()
@@ -9,4 +9,3 @@
/area/space
static_lighting = FALSE
base_lighting_alpha = 255
@@ -0,0 +1,13 @@
author: FabianK3
delete-after: True
changes:
- rscadd: "Added persistent ashtrays. Ashtrays will now keep their contents and are generally persistent."
- rscdel: "Removed all occurances of ashtrays on the horizon as they are now persistent. Requisition a new one for you in operations."
- bugfix: "Fixed cigarette butts not being made persistent when intentionally put out and fixed them spawning in previous ashtray locations."
- bugfix: "Fixed persistent track loss when picking up items."
- bugfix: "Fixed objects becoming persistent on round end when held by a player."
- bugfix: "Fixed matter configuration logic on material initialization."
- bugfix: "Fixed persistent objects floating in space. Why is there a cigarette butt in space in front of the captains office?"
- refactor: "Updated SQL readme."
+1 -1
View File
@@ -37,7 +37,7 @@ Generally you don't want to put your areas in here; if the area is only used in
no_light_control = 1
base_turf = /turf/space
is_outside = OUTSIDE_YES
area_flags = AREA_FLAG_IS_BACKGROUND | AREA_FLAG_HIDE_FROM_HOLOMAP
area_flags = AREA_FLAG_IS_BACKGROUND | AREA_FLAG_HIDE_FROM_HOLOMAP | AREA_FLAG_PREVENT_PERSISTENT_TRASH
nevergravity = TRUE //There's no gravity in space
/area/space/atmosalert()
+1 -66
View File
@@ -14640,19 +14640,6 @@
/obj/structure/girder,
/turf/simulated/floor/plating,
/area/horizon/maintenance/deck_2/wing/port/far)
"bTy" = (
/obj/structure/table/stone/marble,
/obj/machinery/door/firedoor,
/obj/item/material/ashtray/bronze{
pixel_x = 8;
pixel_y = -8
},
/obj/machinery/door/blast/shutters{
id = "shutters_deck2_kitchendesk";
name = "Galley Desk Shutter"
},
/turf/simulated/floor/tiled/full,
/area/horizon/service/kitchen)
"bTz" = (
/obj/effect/floor_decal/industrial/warning{
dir = 4
@@ -31592,7 +31579,6 @@
id = "bar_shutter";
name = "Bar Shutter"
},
/obj/item/material/ashtray/bronze,
/obj/machinery/door/firedoor{
req_one_access = list(24,11,67,73);
dir = 4
@@ -39375,10 +39361,6 @@
/obj/item/reagent_containers/food/snacks/chips{
pixel_x = -9
},
/obj/item/material/ashtray/glass{
pixel_y = -3;
pixel_x = 7
},
/obj/machinery/recharger{
pixel_x = 5;
pixel_y = 10
@@ -43652,9 +43634,6 @@
/area/horizon/service/hydroponics)
"fOn" = (
/obj/structure/table/wood,
/obj/item/material/ashtray/bronze{
pixel_y = -4
},
/obj/machinery/power/outlet{
pixel_y = -3
},
@@ -44504,10 +44483,6 @@
/obj/effect/floor_decal/spline/fancy/wood{
dir = 4
},
/obj/item/material/ashtray/bronze{
pixel_x = 6;
pixel_y = 2
},
/turf/simulated/floor/wood,
/area/horizon/hallway/primary/deck_3/port)
"fTU" = (
@@ -51072,10 +51047,6 @@
pixel_x = -12
},
/obj/item/radio/intercom/south,
/obj/item/material/ashtray/glass{
pixel_x = -8;
pixel_y = 9
},
/obj/structure/table/reinforced/steel,
/obj/item/paper_bin{
pixel_x = 5;
@@ -53961,9 +53932,6 @@
name = "Cafe Desk Shutter"
},
/obj/structure/table/stone/marble,
/obj/item/material/ashtray/bronze{
pixel_y = -5
},
/obj/machinery/door/firedoor{
req_one_access = list(24,11,67,73);
dir = 4
@@ -56329,10 +56297,6 @@
},
/area/centcom/shared_dream)
"hwr" = (
/obj/item/material/ashtray/bronze{
pixel_x = -5;
pixel_y = 2
},
/obj/effect/floor_decal/corner/dark_green{
dir = 9
},
@@ -75975,10 +75939,6 @@
pixel_x = 5;
pixel_y = 13
},
/obj/item/material/ashtray/bronze{
pixel_x = -4;
pixel_y = -3
},
/obj/random/pottedplant_small{
pixel_x = 9
},
@@ -93193,7 +93153,6 @@
id = "bar_shutter";
name = "Bar Shutter"
},
/obj/item/material/ashtray/bronze,
/turf/simulated/floor/lino,
/area/horizon/service/bar)
"moW" = (
@@ -103436,10 +103395,6 @@
/turf/simulated/floor/tiled/white,
/area/horizon/medical/gen_treatment)
"nKc" = (
/obj/item/material/ashtray/bronze{
pixel_x = -8;
pixel_y = -5
},
/obj/machinery/button/remote/blast_door{
dir = 1;
id = "shutters_deck3_engibreakwindows";
@@ -117968,10 +117923,6 @@
pixel_x = 5;
pixel_y = 14
},
/obj/item/material/ashtray/bronze{
pixel_x = -4;
pixel_y = -4
},
/obj/random/pottedplant_small{
pixel_x = 10;
pixel_y = 1
@@ -125321,10 +125272,6 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/floor_decal/industrial/warning,
/obj/structure/table/standard,
/obj/item/material/ashtray/bronze{
pixel_x = 2;
pixel_y = 1
},
/obj/item/material/stool/chair/folding{
pixel_y = 19
},
@@ -125586,10 +125533,6 @@
"qJX" = (
/obj/structure/table/wood,
/obj/machinery/power/outlet,
/obj/item/material/ashtray/bronze{
pixel_x = 6;
pixel_y = 8
},
/obj/random/pottedplant_small{
pixel_x = -3;
pixel_y = 12
@@ -125989,7 +125932,6 @@
/area/horizon/maintenance/deck_2/wing/port/nacelle)
"qMe" = (
/obj/structure/table/standard,
/obj/item/material/ashtray/glass,
/obj/effect/floor_decal/corner/dark_green/diagonal,
/turf/simulated/floor/tiled,
/area/horizon/hallway/primary/deck_3/starboard)
@@ -155490,7 +155432,6 @@
/area/horizon/shuttle/intrepid/main_compartment)
"uFD" = (
/obj/structure/table/wood/gamblingtable,
/obj/item/material/ashtray,
/obj/effect/floor_decal/spline/plain/black{
dir = 1
},
@@ -158244,10 +158185,6 @@
dir = 9
},
/obj/structure/table/rack/folding_table,
/obj/item/material/ashtray/bronze{
pixel_y = 7;
pixel_x = -7
},
/obj/item/deck/cards,
/turf/simulated/floor/tiled,
/area/horizon/hangar/operations)
@@ -169233,7 +169170,6 @@
/obj/machinery/light{
dir = 4
},
/obj/item/material/ashtray/glass,
/obj/structure/disposalpipe/trunk,
/turf/simulated/floor/wood/walnut,
/area/horizon/medical/smoking)
@@ -182134,7 +182070,6 @@
/area/antag/burglar)
"ygU" = (
/obj/structure/table/wood/gamblingtable,
/obj/item/material/ashtray/bronze,
/obj/machinery/power/outlet{
pixel_y = 8;
pixel_x = 8
@@ -282181,7 +282116,7 @@ vnx
wBI
qRI
gaV
bTy
bdr
qvX
qpE
wxI
@@ -219,10 +219,6 @@
/area/template_noop)
"eB" = (
/obj/structure/table/wood/gamblingtable,
/obj/item/material/ashtray/glass{
pixel_y = 6;
pixel_x = -5
},
/obj/random/smokable{
pixel_y = -8;
pixel_x = 4