Merge remote-tracking branch 'upstream/master'

This commit is contained in:
DeltaFire
2021-01-08 23:30:29 +01:00
94 changed files with 1238 additions and 351 deletions
+1 -1
View File
@@ -2372,7 +2372,7 @@
},
/area/awaymission/BMPship/Midship)
"hh" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plating/airless,
/area/awaymission/BMPship/Midship)
"hi" = (
+1 -1
View File
@@ -2710,7 +2710,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/effect/turf_decal/tile/green,
/obj/effect/turf_decal/tile/green{
dir = 4
@@ -312,7 +312,7 @@
/obj/structure/janitorialcart,
/obj/item/mop,
/obj/item/reagent_containers/glass/bucket,
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
/area/awaymission/cabin)
+1 -1
View File
@@ -45265,7 +45265,7 @@
/area/maintenance/aft)
"cfq" = (
/obj/structure/mopbucket,
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plating,
/area/maintenance/aft)
"cfr" = (
+14 -14
View File
@@ -3643,7 +3643,7 @@
lootcount = 2;
name = "2maintenance loot spawner"
},
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plating,
/area/construction)
"ajb" = (
@@ -4579,7 +4579,7 @@
/turf/open/floor/plasteel,
/area/security/processing)
"alk" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plating,
/area/construction/secondary)
"all" = (
@@ -23340,19 +23340,19 @@
/obj/effect/turf_decal/stripes/line{
dir = 8
},
/obj/item/caution{
/obj/item/clothing/suit/caution{
pixel_x = 6;
pixel_y = 3
},
/obj/item/caution{
/obj/item/clothing/suit/caution{
pixel_x = 6;
pixel_y = 3
},
/obj/item/caution{
/obj/item/clothing/suit/caution{
pixel_x = 6;
pixel_y = 3
},
/obj/item/caution{
/obj/item/clothing/suit/caution{
pixel_x = 6;
pixel_y = 3
},
@@ -26810,7 +26810,7 @@
/area/quartermaster/sorting)
"bgP" = (
/obj/item/analyzer,
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plating,
/area/maintenance/disposal)
"bgQ" = (
@@ -33797,7 +33797,7 @@
/turf/open/floor/plasteel/dark,
/area/chapel/office)
"bvU" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/effect/decal/cleanable/dirt,
/obj/structure/sign/warning/biohazard{
pixel_x = -32
@@ -38795,7 +38795,7 @@
/turf/open/floor/plasteel/freezer,
/area/crew_quarters/toilet/restrooms)
"bGv" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plasteel,
/area/science/server/compcore)
"bGw" = (
@@ -40999,7 +40999,7 @@
dir = 1;
pixel_y = -26
},
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/item/shovel,
/obj/item/stack/tile/plasteel{
pixel_x = 10;
@@ -51446,8 +51446,8 @@
/area/quartermaster/warehouse)
"cgt" = (
/obj/structure/rack,
/obj/item/caution,
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/item/clothing/suit/caution,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/quartermaster/warehouse)
@@ -61826,7 +61826,7 @@
/obj/effect/turf_decal/tile/green{
dir = 8
},
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
dir = 4
},
@@ -62925,7 +62925,7 @@
/obj/effect/turf_decal/tile/green{
dir = 4
},
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/machinery/atmospherics/pipe/manifold4w/orange/hidden,
/obj/structure/cable{
icon_state = "4-8"
+2 -2
View File
@@ -10679,7 +10679,7 @@
light_color = "#e8eaff"
},
/obj/machinery/vending/wardrobe/jani_wardrobe{
products = list(/obj/item/clothing/under/rank/civilian/janitor = 2, /obj/item/cartridge/janitor = 2, /obj/item/clothing/gloves/color/black = 2, /obj/item/clothing/head/soft/purple = 2, /obj/item/paint/paint_remover = 2, /obj/item/melee/flyswatter = 2, /obj/item/flashlight = 2, /obj/item/caution = 10, /obj/item/holosign_creator = 2, /obj/item/lightreplacer = 2, /obj/item/soap/nanotrasen = 2, /obj/item/storage/bag/trash = 2, /obj/item/clothing/shoes/galoshes = 2, /obj/item/watertank/janitor = 2, /obj/item/storage/belt/janitor = 2)
products = list(/obj/item/clothing/under/rank/civilian/janitor = 2, /obj/item/cartridge/janitor = 2, /obj/item/clothing/gloves/color/black = 2, /obj/item/clothing/head/soft/purple = 2, /obj/item/paint/paint_remover = 2, /obj/item/melee/flyswatter = 2, /obj/item/flashlight = 2, /obj/item/clothing/suit/caution = 10, /obj/item/holosign_creator = 2, /obj/item/lightreplacer = 2, /obj/item/soap/nanotrasen = 2, /obj/item/storage/bag/trash = 2, /obj/item/clothing/shoes/galoshes = 2, /obj/item/watertank/janitor = 2, /obj/item/storage/belt/janitor = 2)
},
/turf/open/floor/plating,
/area/janitor)
@@ -13637,7 +13637,7 @@
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"IX" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{
+1 -7
View File
@@ -12681,7 +12681,7 @@
/turf/open/floor/wood,
/area/crew_quarters/dorms)
"axL" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/effect/turf_decal/stripes/line{
dir = 1
},
@@ -39921,9 +39921,6 @@
/turf/open/floor/plasteel/dark,
/area/bridge)
"bzU" = (
/obj/structure/chair/comfy/teal{
dir = 4
},
/obj/structure/chair/comfy/black{
dir = 4
},
@@ -65296,9 +65293,6 @@
/turf/open/floor/plasteel,
/area/medical/genetics)
"czd" = (
/obj/machinery/light_switch{
pixel_x = 23
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
@@ -24603,7 +24603,7 @@
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"beS" = (
/obj/item/caution,
/obj/item/clothing/suit/caution,
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"beU" = (
+5 -2
View File
@@ -238,8 +238,11 @@
CHECK_TICK
SSdbcore.SetRoundEnd()
//Collects persistence features
if(mode.allow_persistence_save)
SSpersistence.CollectData()
if(mode.station_was_nuked)
SSpersistence.station_was_destroyed = TRUE
if(!mode.allow_persistence_save)
SSpersistence.station_persistence_save_disabled = TRUE
SSpersistence.CollectData()
//stop collecting feedback during grifftime
SSblackbox.Seal()
+1 -1
View File
@@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt"))
//LANGUAGE CHARACTER CUSTOMIZATION
GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles"))
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc))
GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc, "xeno tongue" = /obj/item/organ/tongue/alien))
//SPECIES BODYPART LISTS
//locked parts are those that your picked species requires to have
@@ -566,3 +566,20 @@
config_entry_value = 0.333
min_val = 0
integer = FALSE
/// Amount of dirtyness tiles need to spawn dirt.
/datum/config_entry/number/turf_dirt_threshold
config_entry_value = 100
min_val = 1
integer = TRUE
/// Alpha dirt starts at
/datum/config_entry/number/dirt_alpha_starting
config_entry_value = 127
max_val = 255
min_val = 0
integer = TRUE
/// Dirtyness multiplier for making turfs dirty
/datum/config_entry/number/turf_dirty_multiplier
config_entry_value = 1
@@ -0,0 +1,20 @@
/// Whether or not to use the persistence system for cleanable objects
/datum/config_entry/flag/persistent_debris
config_entry_value = FALSE
/// Whether or not to nuke all roundstart debris that isn't due to persistence if the above is true
/datum/config_entry/flag/persistent_debris_only
config_entry_value = TRUE
/// Max amount of objects to store, total
/datum/config_entry/number/persistent_debris_global_max
config_entry_value = 10000
integer = TRUE
/// Max amount of objects to store per type
/datum/config_entry/number/persistent_debris_type_max
config_entry_value = 2000
integer = TRUE
/// Wipe dirty stuff on nuke
/datum/config_entry/flag/persistent_debris_wipe_on_nuke
+8 -7
View File
@@ -115,18 +115,22 @@ SUBSYSTEM_DEF(garbage)
lastlevel = level
for (var/refID in queue)
if (!refID)
//We do this rather then for(var/refID in queue) because that sort of for loop copies the whole list.
//Normally this isn't expensive, but the gc queue can grow to 40k items, and that gets costly/causes overrun.
for (var/i in 1 to length(queue))
var/list/L = queue[i]
if (length(L) < 2)
count++
if (MC_TICK_CHECK)
return
continue
var/GCd_at_time = queue[refID]
var/GCd_at_time = L[1]
if(GCd_at_time > cut_off_time)
break // Everything else is newer, skip them
count++
var/refID = L[2]
var/datum/D
D = locate(refID)
@@ -202,10 +206,7 @@ SUBSYSTEM_DEF(garbage)
D.gc_destroyed = gctime
var/list/queue = queues[level]
if (queue[refid])
queue -= refid // Removing any previous references that were GC'd so that the current object will be at the end of the list.
queue[refid] = gctime
queue[++queue.len] = list(gctime, refid) // not += for byond reasons
#ifdef LEGACY_REFERENCE_TRACKING
/datum/controller/subsystem/garbage/proc/add_type_to_findref(type)
+14
View File
@@ -41,6 +41,8 @@ SUBSYSTEM_DEF(mapping)
var/datum/space_level/transit
var/datum/space_level/empty_space
var/num_of_res_levels = 1
/// Lookup for zlevel to station z. text = num.
var/list/z_to_station_z_index
var/stat_map_name = "Loading..."
@@ -259,6 +261,16 @@ SUBSYSTEM_DEF(mapping)
INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
return parsed_maps
/datum/controller/subsystem/mapping/proc/setup_station_z_index()
z_to_station_z_index = list()
var/sz = 1
var/cz = station_start
if(islist(config.map_file))
for(var/map in config.map_file)
z_to_station_z_index["[cz++]"] = sz++
else
z_to_station_z_index["[station_start]"] = 1
/datum/controller/subsystem/mapping/proc/loadWorld()
//if any of these fail, something has gone horribly, HORRIBLY, wrong
var/list/FailedZs = list()
@@ -271,6 +283,8 @@ SUBSYSTEM_DEF(mapping)
INIT_ANNOUNCE("Loading [config.map_name]...")
LoadGroup(FailedZs, "Station", config.map_path, config.map_file, config.traits, ZTRAITS_STATION, FALSE, config.orientation)
setup_station_z_index()
if(SSdbcore.Connect())
var/datum/DBQuery/query_round_map_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET map_name = '[config.map_name]' WHERE id = [GLOB.round_id]")
query_round_map_name.Execute()
@@ -5,18 +5,14 @@ SUBSYSTEM_DEF(persistence)
name = "Persistence"
init_order = INIT_ORDER_PERSISTENCE
flags = SS_NO_FIRE
var/list/satchel_blacklist = list() //this is a typecache
var/list/new_secret_satchels = list() //these are objects
var/list/old_secret_satchels = list()
/// Marks if the station got horribly destroyed
var/station_was_destroyed = FALSE
/// Marks if persistence save should be disabled
var/station_persistence_save_disabled = FALSE
var/list/obj/structure/chisel_message/chisel_messages = list()
var/list/saved_messages = list()
var/list/saved_modes = list(1,2,3)
var/list/saved_dynamic_rules = list(list(),list(),list())
var/list/saved_storytellers = list("foo","bar","baz")
var/list/average_dynamic_threat = 50
var/list/saved_maps
var/list/saved_trophies = list()
var/list/spawned_objects = list()
var/list/antag_rep = list()
var/list/antag_rep_change = list()
@@ -28,62 +24,81 @@ SUBSYSTEM_DEF(persistence)
var/list/paintings = list()
/datum/controller/subsystem/persistence/Initialize()
LoadSatchels()
LoadPoly()
LoadChiselMessages()
LoadTrophies()
LoadRecentModes()
LoadRecentStorytellers()
LoadRecentRulesets()
LoadRecentMaps()
LoadPhotoPersistence()
LoadServerPersistence()
LoadGamePersistence()
var/map_persistence_path = get_map_persistence_path()
if(map_persistence_path)
LoadMapPersistence()
return ..()
/**
* Gets the persistence path of the current map.
*/
/datum/controller/subsystem/persistence/proc/get_map_persistence_path()
ASSERT(SSmapping.config)
if(!SSmapping.config.persistence_key || (SSmapping.config.persistence_key == "NO_PERSIST"))
return null
return "data/persistence/[ckey(SSmapping.config.persistence_key)]"
/datum/controller/subsystem/persistence/proc/CollectData()
SaveServerPersistence()
if(station_persistence_save_disabled)
return
SaveGamePersistence()
var/map_persistence_path = get_map_persistence_path()
if(map_persistence_path)
SaveMapPersistence()
/**
* Loads persistent data relevant to the server: Configurations, past gamemodes, votes, antag rep, etc
*/
/datum/controller/subsystem/persistence/proc/LoadServerPersistence()
for(var/client/C in GLOB.clients)
LoadSavedVote(C.ckey)
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
LoadRandomizedRecipes()
LoadPanicBunker()
return ..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
var/placed_satchel = 0
var/path
/**
* Saves persistent data relevant to the server: Configurations, past gamemodes, votes, antag rep, etc
*/
/datum/controller/subsystem/persistence/proc/SaveServerPersistence()
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
SaveRandomizedRecipes()
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/json = list()
if(fexists(json_file))
json = json_decode(file2text(json_file))
/**
* Loads persistent data relevant to the game in general: Photos, etc
*
* Legacy map persistence systems also use this.
*/
/datum/controller/subsystem/persistence/proc/LoadGamePersistence()
LoadChiselMessages()
LoadPhotoPersistence()
LoadPaintings()
old_secret_satchels = json["data"]
var/obj/item/storage/backpack/satchel/flat/F
if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear.
var/pos = rand(1, old_secret_satchels.len)
F = new()
old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len)
F.x = old_secret_satchels[pos]["x"]
F.y = old_secret_satchels[pos]["y"]
F.z = SSmapping.station_start
path = text2path(old_secret_satchels[pos]["saved_obj"])
/**
* Saves persistent data relevant to the game in general: Photos, etc
*
* Legacy map persistence systems also use this.
*/
/datum/controller/subsystem/persistence/proc/SaveGamePersistence()
CollectChiselMessages()
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
SavePaintings()
SaveScars()
if(F)
if(isfloorturf(F.loc) && !isplatingturf(F.loc))
F.hide(1)
if(ispath(path))
var/spawned_item = new path(F)
spawned_objects[spawned_item] = TRUE
placed_satchel++
var/free_satchels = 0
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only
if(isfloorturf(T) && !isplatingturf(T))
new /obj/item/storage/backpack/satchel/flat/secret(T)
free_satchels++
if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves
break
/**
* Loads persistent data relevant to the current map: Objects, etc.
*/
/datum/controller/subsystem/persistence/proc/LoadMapPersistence()
return
/datum/controller/subsystem/persistence/proc/LoadPoly()
for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!
/**
* Saves persistent data relevant to the current map: Objects, etc.
*/
/datum/controller/subsystem/persistence/proc/SaveMapPersistence()
return
/datum/controller/subsystem/persistence/proc/LoadChiselMessages()
var/list/saved_messages = list()
@@ -130,63 +145,6 @@ SUBSYSTEM_DEF(persistence)
log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]")
/datum/controller/subsystem/persistence/proc/LoadTrophies()
if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav")
var/saved_json
S >> saved_json
if(!saved_json)
return
saved_trophies = json_decode(saved_json)
fdel("data/npc_saves/TrophyItems.sav")
else
var/json_file = file("data/npc_saves/TrophyItems.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_trophies = json["data"]
SetUpTrophies(saved_trophies.Copy())
/datum/controller/subsystem/persistence/proc/LoadRecentModes()
var/json_file = file("data/RecentModes.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_modes = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
var/json_file = file("data/RecentRulesets.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_dynamic_rules = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers()
var/json_file = file("data/RecentStorytellers.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_storytellers = json["data"]
if(saved_storytellers.len > 3)
average_dynamic_threat = saved_storytellers[4]
saved_storytellers.len = 3
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
var/json_file = file("data/RecentMaps.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_maps = json["maps"]
/datum/controller/subsystem/persistence/proc/LoadAntagReputation()
var/json = file2text(FILE_ANTAG_REP)
@@ -207,59 +165,6 @@ SUBSYSTEM_DEF(persistence)
return
saved_votes[ckey] = json["data"]
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
for(var/A in GLOB.trophy_cases)
var/obj/structure/displaycase/trophy/T = A
if (T.showpiece)
continue
T.added_roundstart = TRUE
var/trophy_data = pick_n_take(trophy_items)
if(!islist(trophy_data))
continue
var/list/chosen_trophy = trophy_data
if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
continue
var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
if(!path)
continue
T.showpiece = new /obj/item/showpiece_dummy(T, path)
T.trophy_message = chosen_trophy["message"]
T.placer_key = chosen_trophy["placer_key"]
T.update_icon()
/datum/controller/subsystem/persistence/proc/CollectData()
CollectChiselMessages()
CollectSecretSatchels()
CollectTrophies()
CollectRoundtype()
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
CollectStoryteller(mode)
CollectRulesets(mode)
RecordMaps()
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
SaveRandomizedRecipes()
SavePanicBunker()
SavePaintings()
SaveScars()
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
var/bunker_path = file("data/bunker_passthrough.json")
if(fexists(bunker_path))
var/list/json = json_decode(file2text(bunker_path))
GLOB.bunker_passthrough = json["data"]
for(var/ckey in GLOB.bunker_passthrough)
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
GLOB.bunker_passthrough -= ckey
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
var/album_path = file("data/photo_albums.json")
if(fexists(album_path))
@@ -329,35 +234,6 @@ SUBSYSTEM_DEF(persistence)
WRITE_FILE(frame_path, frame_json)
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar))
var/list/satchels_to_add = list()
for(var/A in new_secret_satchels)
var/obj/item/storage/backpack/satchel/flat/F = A
if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM)
continue
var/list/savable_obj = list()
for(var/obj/O in F)
if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1))
continue
if(O.persistence_replacement)
savable_obj += O.persistence_replacement
else
savable_obj += O.type
if(isemptylist(savable_obj))
continue
var/list/data = list()
data["x"] = F.x
data["y"] = F.y
data["saved_obj"] = pick(savable_obj)
satchels_to_add += list(data)
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/file_data = list()
fdel(json_file)
file_data["data"] = old_secret_satchels + satchels_to_add
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectChiselMessages()
var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json")
@@ -373,84 +249,6 @@ SUBSYSTEM_DEF(persistence)
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
saved_messages += list(M.pack()) // dm eats one list
/datum/controller/subsystem/persistence/proc/CollectTrophies()
var/json_file = file("data/npc_saves/TrophyItems.json")
var/list/file_data = list()
file_data["data"] = remove_duplicate_trophies(saved_trophies)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/SavePanicBunker()
var/json_file = file("data/bunker_passthrough.json")
var/list/file_data = list()
file_data["data"] = GLOB.bunker_passthrough
fdel(json_file)
WRITE_FILE(json_file,json_encode(file_data))
/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies)
var/list/ukeys = list()
. = list()
for(var/trophy in trophies)
var/tkey = "[trophy["path"]]-[trophy["message"]]"
if(ukeys[tkey])
continue
else
. += list(trophy)
ukeys[tkey] = TRUE
/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
if(!T.added_roundstart && T.showpiece)
var/list/data = list()
data["path"] = T.showpiece.type
data["message"] = T.trophy_message
data["placer_key"] = T.placer_key
saved_trophies += list(data)
/datum/controller/subsystem/persistence/proc/CollectRoundtype()
saved_modes[3] = saved_modes[2]
saved_modes[2] = saved_modes[1]
saved_modes[1] = SSticker.mode.config_tag
var/json_file = file("data/RecentModes.json")
var/list/file_data = list()
file_data["data"] = saved_modes
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode)
saved_storytellers.len = 3
saved_storytellers[3] = saved_storytellers[2]
saved_storytellers[2] = saved_storytellers[1]
saved_storytellers[1] = mode.storyteller.name
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
var/json_file = file("data/RecentStorytellers.json")
var/list/file_data = list()
file_data["data"] = saved_storytellers + average_dynamic_threat
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode)
saved_dynamic_rules[3] = saved_dynamic_rules[2]
saved_dynamic_rules[2] = saved_dynamic_rules[1]
saved_dynamic_rules[1] = list()
for(var/r in mode.executed_rules)
var/datum/dynamic_ruleset/rule = r
saved_dynamic_rules[1] += rule.config_tag
var/json_file = file("data/RecentRulesets.json")
var/list/file_data = list()
file_data["data"] = saved_dynamic_rules
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/RecordMaps()
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
var/json_file = file("data/RecentMaps.json")
var/list/file_data = list()
file_data["maps"] = saved_maps
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectAntagReputation()
var/ANTAG_REP_MAXIMUM = CONFIG_GET(number/antag_rep_maximum)
@@ -0,0 +1,177 @@
/**
* Persistence for cleanable debris.
*/
/datum/controller/subsystem/persistence
/// tracks if we already loaded debris. Unlike everything else, this can actually be a major problem if some badmin procs it twice.
var/loaded_debris = FALSE
/datum/controller/subsystem/persistence/LoadMapPersistence()
. = ..()
if(CONFIG_GET(flag/persistent_debris))
LoadMapDebris()
/datum/controller/subsystem/persistence/SaveMapPersistence()
. = ..()
if(CONFIG_GET(flag/persistent_debris))
SaveMapDebris()
/datum/controller/subsystem/persistence/proc/LoadMapDebris()
if(CONFIG_GET(flag/persistent_debris_only))
wipe_existing_debris()
if(!fexists("[get_map_persistence_path()]/debris.json"))
return
if(loaded_debris)
return
loaded_debris = TRUE
var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space)
var/list/allowed_z_cache = list()
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
allowed_z_cache[num2text(z)] = TRUE
var/list/data = json_decode(file2text("[get_map_persistence_path()]/debris.json"))
var/list/z_lookup = list()
var/loaded = 0
var/list/loaded_by_type = list()
var/nopath = 0
var/badloc = 0
var/noturf = 0
/// reverse it
for(var/z in SSmapping.z_to_station_z_index)
var/sz = SSmapping.z_to_station_z_index[z]
z_lookup[num2text(sz)] = text2num(z)
for(var/z in data)
var/actual_z = z_lookup[z]
var/list/L1 = data[z]
for(var/x in L1)
var/list/L2 = data[z][x]
for(var/y in L2)
var/turf/tile = locate(text2num(x), text2num(y), actual_z)
if(!tile)
noturf++
continue
var/list/objects = data[z][x][y]
for(var/_L in objects)
var/list/objdata
var/path
if(islist(_L))
objdata = _L
path = text2path(objdata["__PATH__"])
else
path = text2path(_L)
objdata = objects[_L]
if(!path)
nopath++
continue
if(!IsValidDebrisLocation(tile, allowed_turf_typecache, allowed_z_cache, path, TRUE))
badloc++
continue
var/obj/effect/decal/cleanable/instantiated = new path(tile)
loaded_by_type[path] += 1
loaded++
if(objdata)
instantiated.PersistenceLoad(objdata)
var/list/bytype = list()
for(var/path in loaded_by_type)
bytype += "[path] - [loaded_by_type[path]]"
subsystem_log(
{"Debris loading completed:
Errors:
No path: [nopath]
Invalid location: [badloc]
No turf on map: [noturf]
Total loaded: [loaded]
By type:
[bytype.Join("\n")]"}
)
/datum/controller/subsystem/persistence/proc/SaveMapDebris()
if(fexists("[get_map_persistence_path()]/debris.json"))
fdel("[get_map_persistence_path()]/debris.json")
if(CONFIG_GET(flag/persistent_debris_wipe_on_nuke) && station_was_destroyed)
return // local janitor cheers on nukeop team to save some work
var/list/data = list()
var/list/z_lookup = SSmapping.z_to_station_z_index
var/list/debris = RelevantPersistentDebris()
var/obj/effect/decal/cleanable/saving
var/global_max = CONFIG_GET(number/persistent_debris_global_max)
var/type_max = CONFIG_GET(number/persistent_debris_type_max)
var/stored = 0
var/list/stored_by_type = list()
for(var/i in debris)
saving = i
var/list/serializing = list()
var/path = saving.PersistenceSave(serializing)
if(!path)
continue
if(stored_by_type[path] > type_max)
continue
var/text_z = num2text(z_lookup[num2text(saving.z)])
var/text_y = num2text(saving.y)
var/text_x = num2text(saving.x)
LAZYINITLIST(data[text_z])
LAZYINITLIST(data[text_z][text_x])
LAZYINITLIST(data[text_z][text_x][text_y])
if(saving.persistence_allow_stacking)
serializing["__PATH__"] = path
data[text_z][text_x][text_y] += list(serializing)
else
data[text_z][text_x][text_y][path] = serializing
stored++
if(stored > global_max)
var/w = "Persistent debris saving globally aborted due to global max >= [global_max]. Either janitors never do their jobs or something is wrong."
message_admins(w)
subsystem_log(w)
return
stored_by_type[path] = stored_by_type[path]? stored_by_type[path] + 1 : 1
if(stored_by_type[path] > type_max)
var/w = "Persistent debris saving aborted for type [path] due to type max >= [global_max]. Either janitors never do their jobs or something is wrong."
message_admins(w)
subsystem_log(w)
var/list/bytype = list()
for(var/path in stored_by_type)
bytype += "[path] - [stored_by_type[path]]"
subsystem_log(
{"Debris saving completed:
Total: [stored]
By type:
[bytype.Join("\n")]"}
)
WRITE_FILE(file("[get_map_persistence_path()]/debris.json"), json_encode(data))
/datum/controller/subsystem/persistence/proc/IsValidDebrisLocation(turf/tile, list/allowed_typecache, list/allowed_zcache, obj/effect/decal/cleanable/type, loading = FALSE)
if(!allowed_typecache[tile.type])
return FALSE
var/area/A = tile.loc
if(!A.persistent_debris_allowed)
return FALSE
if(!allowed_zcache[num2text(tile.z)])
return FALSE
if(loading)
if(!initial(type.persistence_allow_stacking))
var/obj/effect/decal/cleanable/C = locate(type) in tile
if(!QDELETED(C))
return FALSE
// Saving verifies allow stacking in the save proc.
for(var/obj/structure/window/W in tile)
if(W.fulltile)
return FALSE
return TRUE
/datum/controller/subsystem/persistence/proc/wipe_existing_debris()
var/list/existing = RelevantPersistentDebris()
QDEL_LIST(existing)
/datum/controller/subsystem/persistence/proc/RelevantPersistentDebris()
var/list/allowed_turf_typecache = typecacheof(/turf/open) - typecacheof(/turf/open/space)
var/list/allowed_z_cache = list()
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
allowed_z_cache[num2text(z)] = TRUE
. = list()
for(var/obj/effect/decal/cleanable/C in world)
if(!C.loc || QDELETED(C))
continue
if(!C.persistent)
continue
if(!IsValidDebrisLocation(C.loc, allowed_turf_typecache, allowed_z_cache, C.type, FALSE))
continue
. += C
@@ -0,0 +1,26 @@
/**
* Persists panic bunker whitelisting for a configured period of time
*/
/datum/controller/subsystem/persistence/LoadServerPersistence()
. = ..()
LoadPanicBunker()
/datum/controller/subsystem/persistence/SaveServerPersistence()
. = ..()
SavePanicBunker()
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
var/bunker_path = file("data/bunker_passthrough.json")
if(fexists(bunker_path))
var/list/json = json_decode(file2text(bunker_path))
GLOB.bunker_passthrough = json["data"]
for(var/ckey in GLOB.bunker_passthrough)
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
GLOB.bunker_passthrough -= ckey
/datum/controller/subsystem/persistence/proc/SavePanicBunker()
var/json_file = file("data/bunker_passthrough.json")
var/list/file_data = list()
file_data["data"] = GLOB.bunker_passthrough
fdel(json_file)
WRITE_FILE(json_file,json_encode(file_data))
@@ -0,0 +1,11 @@
/**
* Persists poly messages across rounds
*/
/datum/controller/subsystem/persistence/LoadGamePersistence()
. = ..()
LoadPoly()
/datum/controller/subsystem/persistence/proc/LoadPoly()
for(var/mob/living/simple_animal/parrot/Poly/P in GLOB.alive_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!
@@ -0,0 +1,107 @@
/**
* Stores recently played gamemodes, maps, etc.
*/
/datum/controller/subsystem/persistence
var/list/saved_modes = list(1,2,3)
var/list/saved_dynamic_rules = list(list(),list(),list())
var/list/saved_storytellers = list("foo","bar","baz")
var/list/average_dynamic_threat = 50
var/list/saved_maps
/datum/controller/subsystem/persistence/SaveServerPersistence()
. = ..()
CollectRoundtype()
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
CollectStoryteller(mode)
CollectRulesets(mode)
RecordMaps()
/datum/controller/subsystem/persistence/LoadServerPersistence()
. = ..()
LoadRecentModes()
LoadRecentStorytellers()
LoadRecentRulesets()
LoadRecentMaps()
/datum/controller/subsystem/persistence/proc/CollectRoundtype()
saved_modes[3] = saved_modes[2]
saved_modes[2] = saved_modes[1]
saved_modes[1] = SSticker.mode.config_tag
var/json_file = file("data/RecentModes.json")
var/list/file_data = list()
file_data["data"] = saved_modes
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectStoryteller(var/datum/game_mode/dynamic/mode)
saved_storytellers.len = 3
saved_storytellers[3] = saved_storytellers[2]
saved_storytellers[2] = saved_storytellers[1]
saved_storytellers[1] = mode.storyteller.name
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
var/json_file = file("data/RecentStorytellers.json")
var/list/file_data = list()
file_data["data"] = saved_storytellers + average_dynamic_threat
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/CollectRulesets(var/datum/game_mode/dynamic/mode)
saved_dynamic_rules[3] = saved_dynamic_rules[2]
saved_dynamic_rules[2] = saved_dynamic_rules[1]
saved_dynamic_rules[1] = list()
for(var/r in mode.executed_rules)
var/datum/dynamic_ruleset/rule = r
saved_dynamic_rules[1] += rule.config_tag
var/json_file = file("data/RecentRulesets.json")
var/list/file_data = list()
file_data["data"] = saved_dynamic_rules
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/RecordMaps()
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
var/json_file = file("data/RecentMaps.json")
var/list/file_data = list()
file_data["maps"] = saved_maps
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/LoadRecentModes()
var/json_file = file("data/RecentModes.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_modes = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
var/json_file = file("data/RecentRulesets.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_dynamic_rules = json["data"]
/datum/controller/subsystem/persistence/proc/LoadRecentStorytellers()
var/json_file = file("data/RecentStorytellers.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_storytellers = json["data"]
if(saved_storytellers.len > 3)
average_dynamic_threat = saved_storytellers[4]
saved_storytellers.len = 3
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
var/json_file = file("data/RecentMaps.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_maps = json["maps"]
@@ -0,0 +1,79 @@
/**
* Secret satchel persistence - allows storing of items in underfloor satchels that's loaded later.
*/
/datum/controller/subsystem/persistence
var/list/satchel_blacklist = list() //this is a typecache
var/list/new_secret_satchels = list() //these are objects
var/list/old_secret_satchels = list()
/datum/controller/subsystem/persistence/LoadGamePersistence()
. = ..()
LoadSatchels()
/datum/controller/subsystem/persistence/SaveGamePersistence()
. = ..()
CollectSecretSatchels()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
var/placed_satchel = 0
var/path
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/json = list()
if(fexists(json_file))
json = json_decode(file2text(json_file))
old_secret_satchels = json["data"]
var/obj/item/storage/backpack/satchel/flat/F
if(old_secret_satchels && old_secret_satchels.len >= 10) //guards against low drop pools assuring that one player cannot reliably find his own gear.
var/pos = rand(1, old_secret_satchels.len)
F = new()
old_secret_satchels.Cut(pos, pos+1 % old_secret_satchels.len)
F.x = old_secret_satchels[pos]["x"]
F.y = old_secret_satchels[pos]["y"]
F.z = SSmapping.station_start
path = text2path(old_secret_satchels[pos]["saved_obj"])
if(F)
if(isfloorturf(F.loc) && !isplatingturf(F.loc))
F.hide(1)
if(ispath(path))
var/spawned_item = new path(F)
spawned_objects[spawned_item] = TRUE
placed_satchel++
var/free_satchels = 0
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,SSmapping.station_start), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,SSmapping.station_start)))) //Nontrivially expensive but it's roundstart only
if(isfloorturf(T) && !isplatingturf(T))
new /obj/item/storage/backpack/satchel/flat/secret(T)
free_satchels++
if((free_satchels + placed_satchel) == 10) //ten tiles, more than enough to kill anything that moves
break
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/crowbar))
var/list/satchels_to_add = list()
for(var/A in new_secret_satchels)
var/obj/item/storage/backpack/satchel/flat/F = A
if(QDELETED(F) || F.z != SSmapping.station_start || F.invisibility != INVISIBILITY_MAXIMUM)
continue
var/list/savable_obj = list()
for(var/obj/O in F)
if(is_type_in_typecache(O, satchel_blacklist) || (O.flags_1 & ADMIN_SPAWNED_1))
continue
if(O.persistence_replacement)
savable_obj += O.persistence_replacement
else
savable_obj += O.type
if(isemptylist(savable_obj))
continue
var/list/data = list()
data["x"] = F.x
data["y"] = F.y
data["saved_obj"] = pick(savable_obj)
satchels_to_add += list(data)
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
var/list/file_data = list()
fdel(json_file)
file_data["data"] = old_secret_satchels + satchels_to_add
WRITE_FILE(json_file, json_encode(file_data))
@@ -0,0 +1,84 @@
/**
* Stores trophies in curator display cases
*/
/datum/controller/subsystem/persistence
var/list/saved_trophies = list()
/datum/controller/subsystem/persistence/LoadGamePersistence()
. = ..()
LoadTrophies()
/datum/controller/subsystem/persistence/SaveGamePersistence()
. = ..()
CollectTrophies()
/datum/controller/subsystem/persistence/proc/LoadTrophies()
if(fexists("data/npc_saves/TrophyItems.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/TrophyItems.sav")
var/saved_json
S >> saved_json
if(!saved_json)
return
saved_trophies = json_decode(saved_json)
fdel("data/npc_saves/TrophyItems.sav")
else
var/json_file = file("data/npc_saves/TrophyItems.json")
if(!fexists(json_file))
return
var/list/json = json_decode(file2text(json_file))
if(!json)
return
saved_trophies = json["data"]
SetUpTrophies(saved_trophies.Copy())
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
for(var/A in GLOB.trophy_cases)
var/obj/structure/displaycase/trophy/T = A
if (T.showpiece)
continue
T.added_roundstart = TRUE
var/trophy_data = pick_n_take(trophy_items)
if(!islist(trophy_data))
continue
var/list/chosen_trophy = trophy_data
if(!chosen_trophy || isemptylist(chosen_trophy)) //Malformed
continue
var/path = text2path(chosen_trophy["path"]) //If the item no longer exist, this returns null
if(!path)
continue
T.showpiece = new /obj/item/showpiece_dummy(T, path)
T.trophy_message = chosen_trophy["message"]
T.placer_key = chosen_trophy["placer_key"]
T.update_icon()
/datum/controller/subsystem/persistence/proc/CollectTrophies()
var/json_file = file("data/npc_saves/TrophyItems.json")
var/list/file_data = list()
file_data["data"] = remove_duplicate_trophies(saved_trophies)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies)
var/list/ukeys = list()
. = list()
for(var/trophy in trophies)
var/tkey = "[trophy["path"]]-[trophy["message"]]"
if(ukeys[tkey])
continue
else
. += list(trophy)
ukeys[tkey] = TRUE
/datum/controller/subsystem/persistence/proc/SaveTrophy(obj/structure/displaycase/trophy/T)
if(!T.added_roundstart && T.showpiece)
var/list/data = list()
data["path"] = T.showpiece.type
data["message"] = T.trophy_message
data["placer_key"] = T.placer_key
saved_trophies += list(data)
+9
View File
@@ -85,6 +85,15 @@
var/mob/M = teleatom
M.cancel_camera()
var/static/list/bread_cache = typecacheof(/obj/item/reagent_containers/food/snacks/store/bread)
var/list/breadlist = typecache_filter_list(teleatom.GetAllContents(), bread_cache)
if(breadlist.len && (channel == TELEPORT_CHANNEL_BLUESPACE || channel == TELEPORT_CHANNEL_QUANTUM))
for(var/obj/item/reagent_containers/food/snacks/store/bread/bread in breadlist)
bread.bread_teleport()
else if(istype(teleatom, /obj/item/reagent_containers/food/snacks/store/bread))
var/obj/item/reagent_containers/food/snacks/store/bread/bread = teleatom
bread.bread_teleport()
return TRUE
/proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound)
+1
View File
@@ -41,6 +41,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
power_environ = FALSE
valid_territory = FALSE
outdoors = TRUE
persistent_debris_allowed = FALSE
ambientsounds = SPACE
blob_allowed = FALSE //Eating up space doesn't count for victory as a blob.
considered_hull_exterior = TRUE
+4
View File
@@ -24,6 +24,10 @@
var/clockwork_warp_allowed = TRUE
/// Message to display when the clockwork warp fails
var/clockwork_warp_fail = "The structure there is too dense for warping to pierce. (This is normal in high-security areas.)"
/// Persistent debris alowed
var/persistent_debris_allowed = TRUE
/// Dirty flooring allowed
var/dirt_buildup_allowed = TRUE
/// If mining tunnel generation is allowed in this area
var/tunnel_allowed = FALSE
@@ -6,6 +6,7 @@
name = "gas sensor"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "gsensor1"
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 0)
var/on = TRUE
@@ -774,6 +774,9 @@
stun_projectile_sound = 'sound/weapons/gunshot_smg.ogg'
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 80, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
/obj/machinery/porta_turret/syndicate/pod/toolbox
max_integrity = 100
/obj/machinery/porta_turret/syndicate/shuttle/target(atom/movable/target)
if(target)
setDir(get_dir(base, target))//even if you can't shoot, follow the target
+21 -2
View File
@@ -1,6 +1,13 @@
/obj/effect/decal/cleanable
gender = PLURAL
layer = ABOVE_NORMAL_TURF_LAYER
/// Is this kind of cleanable decal persistent
var/persistent = FALSE
/// Can we stack multiple in one tile?
var/persistence_allow_stacking = FALSE
/// Are we deleted by turf changes?
var/wiped_by_floor_change = FALSE
var/list/random_icon_states = null
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
@@ -29,9 +36,21 @@
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0)
/**
* A data list is passed into this.
* This should return null to skip saving, or the type of data to save. Type must be /cleanable.
*/
/obj/effect/decal/cleanable/proc/PersistenceSave(list/data)
return type
/**
* Loads from a data list.
*/
/obj/effect/decal/cleanable/proc/PersistenceLoad(list/data)
return
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
if(mergeable_decal)
qdel(C)
return mergeable_decal
/obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
@@ -6,6 +6,7 @@
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
mergeable_decal = FALSE
bloodiness = 0 //This isn't supposed to be bloody.
persistent = TRUE
var/body_colors = "#e3ba84" //a default color just in case.
var/gibs_reagent_id = /datum/reagent/liquidgibs
var/gibs_bloodtype = "A+"
@@ -31,6 +32,10 @@
flesh.color = body_colors
add_overlay(flesh)
/obj/effect/decal/cleanable/blood/gibs/PersistenceSave(list/data)
. = ..()
return /obj/effect/decal/cleanable/blood/gibs/old
/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
return
@@ -159,6 +164,10 @@
. = ..()
update_icon()
/obj/effect/decal/cleanable/blood/gibs/slime/PersistenceSave(list/data)
. = ..()
return type
/obj/effect/decal/cleanable/blood/gibs/slime/update_icon()
add_atom_colour(body_colors, FIXED_COLOUR_PRIORITY)
cut_overlays()
@@ -198,6 +207,10 @@
. = ..()
update_icon()
/obj/effect/decal/cleanable/blood/gibs/synth/PersistenceSave(list/data)
. = ..()
return type
//IPCs
/obj/effect/decal/cleanable/blood/gibs/ipc
desc = "They look sharp yet oozing."
@@ -209,6 +222,10 @@
. = ..()
update_icon()
/obj/effect/decal/cleanable/blood/gibs/ipc/PersistenceSave(list/data)
. = ..()
return type
/obj/effect/decal/cleanable/blood/gibs/ipc/update_icon()
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
cut_overlays()
@@ -8,12 +8,18 @@
bloodiness = BLOOD_AMOUNT_PER_DECAL
color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere.
beauty = -100
persistent = TRUE
var/fixed_color = FALSE
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
if(C.fixed_color)
qdel(C)
return FALSE
if (C.blood_DNA)
blood_DNA |= C.blood_DNA
qdel(C)
update_icon()
..()
return FALSE
/obj/effect/decal/cleanable/blood/transfer_blood_dna()
..()
@@ -24,7 +30,22 @@
update_icon()
/obj/effect/decal/cleanable/blood/update_icon()
color = blood_DNA_to_color()
. = ..()
if(!fixed_color)
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
/obj/effect/decal/cleanable/blood/PersistenceSave(list/data)
. = ..()
data["color"] = color
/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data)
. = ..()
if(data["color"])
fixed_color = TRUE
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
name = "dried blood"
desc = "Looks like it's been here a while. Eew"
bloodiness = 0
/obj/effect/decal/cleanable/blood/old
name = "dried blood"
@@ -38,6 +59,7 @@
/obj/effect/decal/cleanable/blood/splats
random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
persistence_allow_stacking = TRUE
/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("splatter1", "splatter2", "splatter3", "splatter4", "splatter5")
@@ -48,16 +70,43 @@
random_icon_states = null
beauty = -50
/obj/effect/decal/cleanable/blood/tracks/PersistenceSave(list/data)
. = ..()
data["dir"] = dir
/obj/effect/decal/cleanable/blood/tracks/PersistenceLoad(list/data)
. = ..()
if(data["dir"])
setDir(text2num(data["dir"]))
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
random_icon_states = null
beauty = -50
persistent = TRUE
persistence_allow_stacking = TRUE
var/list/existing_dirs = list()
var/fixed_color = FALSE
/obj/effect/decal/cleanable/trail_holder/PersistenceSave(list/data)
. = ..()
data["dir"] = dir
data["color"] = color
/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data)
. = ..()
if(data["dir"])
setDir(text2num(data["dir"]))
if(data["color"])
fixed_color = TRUE
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
/obj/effect/decal/cleanable/trail_holder/update_icon()
color = blood_DNA_to_color()
. = ..()
if(!fixed_color)
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
/obj/effect/cleanable/trail_holder/Initialize()
. = ..()
@@ -84,8 +133,19 @@
var/entered_dirs = 0
var/exited_dirs = 0
blood_state = BLOOD_STATE_BLOOD //the icon state to load images from
persistent = TRUE
persistence_allow_stacking = TRUE
var/list/shoe_types = list()
/obj/effect/decal/cleanable/blood/footprints/PersistenceSave(list/data)
. = ..()
data["dir"] = dir
/obj/effect/decal/cleanable/blood/footprints/PersistenceLoad(list/data)
. = ..()
if(data["dir"])
setDir(text2num(data["dir"]))
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
if(ishuman(O))
var/mob/living/carbon/human/H = O
@@ -143,7 +203,7 @@
return
if(color != C.color)
return
..()
return ..()
/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
@@ -12,6 +12,8 @@
icon_state = "ash"
mergeable_decal = FALSE
beauty = -50
persistent = TRUE
persistence_allow_stacking = TRUE
/obj/effect/decal/cleanable/ash/Initialize()
. = ..()
@@ -38,6 +40,8 @@
icon = 'icons/obj/shards.dmi'
icon_state = "tiny"
beauty = -100
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/glass/Initialize()
. = ..()
@@ -53,10 +57,33 @@
name = "dirt"
desc = "Someone should clean that up."
icon_state = "dirt"
alpha = 127
canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall)
smooth = SMOOTH_FALSE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
beauty = -75
mergeable_decal = TRUE
persistent = TRUE
wiped_by_floor_change = TRUE
/obj/effect/decal/cleanable/dirt/Initialize(mapload)
. = ..()
alpha = CONFIG_GET(number/dirt_alpha_starting)
/obj/effect/decal/cleanable/dirt/proc/dirty(strength = 1)
if(alpha < 255)
alpha += strength
if(alpha > 255)
alpha = 255
/obj/effect/decal/cleanable/dirt/PersistenceSave(list/data)
. = ..()
data["alpha"] = alpha
/obj/effect/decal/cleanable/dirt/PersistenceLoad(list/data)
. = ..()
if(data["alpha"])
alpha = text2num(data["alpha"])
/obj/effect/decal/cleanable/dirt/Initialize()
. = ..()
@@ -94,6 +121,8 @@
light_color = LIGHT_COLOR_GREEN
icon_state = "greenglow"
beauty = -300
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/greenglow/Initialize(mapload)
. = ..()
@@ -122,6 +151,8 @@
icon_state = "molten"
mergeable_decal = FALSE
beauty = -150
persistent = TRUE
persistence_allow_stacking = TRUE
/obj/effect/decal/cleanable/molten_object/large
name = "big gooey grey mass"
@@ -136,6 +167,7 @@
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
beauty = -150
persistent = TRUE
/obj/effect/decal/cleanable/vomit/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(ishuman(user))
@@ -151,6 +183,10 @@
reagents.trans_to(H, reagents.total_volume)
qdel(src)
/obj/effect/decal/cleanable/vomit/PersistenceSave(list/data)
. = ..()
return /obj/effect/decal/cleanable/vomit/old
/obj/effect/decal/cleanable/vomit/old
name = "crusty dried vomit"
desc = "You try not to look at the chunks, and fail."
@@ -166,12 +202,16 @@
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
beauty = -100
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/plant_smudge
name = "plant smudge"
gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_plant")
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/egg_smudge
name = "smashed egg"
@@ -179,6 +219,8 @@
gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/pie_smudge //honk
name = "smashed pie"
@@ -186,6 +228,8 @@
gender = NEUTER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_pie")
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/chem_pile
name = "chemical pile"
@@ -193,6 +237,8 @@
gender = NEUTER
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/shreds
name = "shreds"
@@ -200,6 +246,8 @@
icon_state = "shreds"
gender = PLURAL
mergeable_decal = FALSE
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/shreds/ex_act(severity, target)
if(severity == 1) //so shreds created during an explosion aren't deleted by the explosion.
@@ -222,6 +270,8 @@
desc = "The herpes of arts and crafts."
icon = 'icons/effects/atmospherics.dmi'
gender = NEUTER
mergeable_decal = TRUE
persistent = TRUE
/obj/effect/decal/cleanable/glitter/pink
name = "pink glitter"
@@ -247,3 +297,5 @@
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
mergeable_decal = TRUE
persistent = TRUE
@@ -11,6 +11,7 @@
bloodiness = BLOOD_AMOUNT_PER_DECAL
mergeable_decal = FALSE
beauty = -50
persistent = TRUE
/obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases)
. = ..()
@@ -52,6 +53,7 @@
blood_state = BLOOD_STATE_OIL
bloodiness = BLOOD_AMOUNT_PER_DECAL
beauty = -100
persistent = TRUE
/obj/effect/decal/cleanable/oil/Initialize()
. = ..()
@@ -61,8 +63,10 @@
/obj/effect/decal/cleanable/oil/streak
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
beauty = -50
persistent = TRUE
/obj/effect/decal/cleanable/oil/slippery
persistent = FALSE
/obj/effect/decal/cleanable/oil/slippery/Initialize()
AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE))
@@ -5,6 +5,8 @@
icon_state = "rune1"
plane = ABOVE_WALL_PLANE //makes the graffiti visible over a wall.
gender = NEUTER
persistent = TRUE
persistence_allow_stacking = TRUE
mergeable_decal = FALSE
var/do_icon_rotate = TRUE
var/rotation = 0
@@ -29,3 +31,35 @@
if(main)
paint_colour = main
add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY)
/obj/effect/decal/cleanable/crayon/PersistenceSave(list/data)
. = ..()
if(icon != initial(icon)) // no support for alticons yet, awful system anyways
return null
data["icon_state"] = icon_state
data["paint_color"] = paint_colour
if(do_icon_rotate)
data["rotation"] = rotation
data["name"] = name
if(pixel_x != initial(pixel_x))
data["pixel_x"] = pixel_x
if(pixel_y != initial(pixel_y))
data["pixel_y"] = pixel_y
/obj/effect/decal/cleanable/crayon/PersistenceLoad(list/data)
. = ..()
if(data["name"])
name = data["name"]
if(do_icon_rotate && data["rotation"])
var/matrix/M = matrix()
M.Turn(text2num(data["rotation"]))
transform = M
if(data["paint_color"])
paint_colour = data["paint_color"]
add_atom_colour(paint_colour, FIXED_COLOUR_PRIORITY)
if(data["icon_state"])
icon_state = data["icon_state"]
if(data["pixel_x"])
pixel_x = data["pixel_x"]
if(data["pixel_y"])
pixel_y = data["pixel_y"]
@@ -264,6 +264,30 @@ effective or pretty fucking useless.
GLOB.active_jammers -= src
update_icon()
/*portable turret*/
/obj/item/storage/toolbox/emergency/turret
desc = "You feel a strange urge to hit this with a wrench."
/obj/item/storage/toolbox/emergency/turret/PopulateContents()
new /obj/item/screwdriver(src)
new /obj/item/wrench(src)
new /obj/item/weldingtool(src)
new /obj/item/crowbar(src)
new /obj/item/analyzer(src)
new /obj/item/wirecutters(src)
/obj/item/storage/toolbox/emergency/turret/attackby(obj/item/I, mob/living/user, params)
if(I.tool_behaviour == TOOL_WRENCH && user.a_intent == INTENT_HARM)
user.visible_message("<span class='danger'>[user] bashes [src] with [I]!</span>", \
"<span class='danger'>You bash [src] with [I]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(src, "sound/items/drill_use.ogg", 80, TRUE, -1)
var/obj/machinery/porta_turret/syndicate/pod/toolbox/turret = new(get_turf(loc))
turret.faction = list("[REF(user)]")
qdel(src)
return
..()
/obj/item/headsetupgrader
name = "headset upgrader"
desc = "A tool that can be used to upgrade a normal headset to be able to protect from flashbangs."
+2 -1
View File
@@ -19,6 +19,7 @@
var/boom_sizes = list(0, 0, 3)
var/can_attach_mob = FALSE
var/full_damage_on_mobs = FALSE
var/can_gib_mobs = FALSE
/obj/item/grenade/plastic/Initialize()
. = ..()
@@ -72,7 +73,7 @@
explosion(get_step(T, aim_dir), boom_sizes[1], boom_sizes[2], boom_sizes[3])
else
explosion(location, boom_sizes[1], boom_sizes[2], boom_sizes[3])
if(ismob(target))
if(ismob(target) && can_gib_mobs)
var/mob/M = target
M.gib()
qdel(src)
-14
View File
@@ -1,17 +1,3 @@
/obj/item/caution
desc = "Caution! Wet Floor!"
name = "wet floor sign"
icon = 'icons/obj/janitor.dmi'
icon_state = "caution"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
force = 1
throwforce = 3
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("warned", "cautioned", "smashed")
/obj/item/choice_beacon
name = "choice beacon"
desc = "Hey, why are you viewing this?!! Please let Centcom know about this odd occurance."
@@ -392,6 +392,7 @@
created_name = new_name
else
created_name = ""
log_game("[key_name(usr)] renamed [src] ([REF(src)]) to [created_name].")
else if(href_list["Master"])
forced_ai = select_active_ai(usr)
@@ -793,7 +793,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \
new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \
new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \
new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2)))
new /datum/stack_recipe("wet floor sign", /obj/item/clothing/suit/caution, 2)))
/obj/item/stack/sheet/plastic
name = "plastic"
@@ -103,6 +103,39 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/mechanical/old/heirloom/PopulateContents()
return
/obj/item/storage/toolbox/mechanical/old/clean // the assistant traitor toolbox, damage scales with TC inside
name = "toolbox"
desc = "An old, blue toolbox. It menaces with a sickening miasma of robust energies. You sure about this, Brain?"
icon_state = "toolbox_blue_clean"
force = 19
throwforce = 22
wound_bonus = 0
bare_wound_bonus = 10
/obj/item/storage/toolbox/mechanical/old/clean/proc/calc_damage()
var/power = 0
for (var/obj/item/stack/telecrystal/TC in GetAllContents())
power += TC.amount
force = 19 + power
throwforce = 22 + power
/obj/item/storage/toolbox/mechanical/old/clean/attack(mob/target, mob/living/user)
calc_damage() // one damage for one telecrystal equals about thirty seven(?) damage if you pour ALL your tc
..()
/obj/item/storage/toolbox/mechanical/old/clean/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
calc_damage()
..()
/obj/item/storage/toolbox/mechanical/old/clean/PopulateContents()
new /obj/item/screwdriver(src)
new /obj/item/wrench(src)
new /obj/item/weldingtool(src)
new /obj/item/crowbar(src)
new /obj/item/wirecutters(src)
new /obj/item/multitool(src)
new /obj/item/clothing/gloves/color/yellow(src)
/obj/item/storage/toolbox/electrical
name = "electrical toolbox"
icon_state = "yellow"
@@ -70,7 +70,7 @@
new /obj/item/melee/flyswatter(src)
new /obj/item/flashlight(src)
for(var/i in 1 to 3)
new /obj/item/caution(src)
new /obj/item/clothing/suit/caution(src)
new /obj/item/holosign_creator(src)
new /obj/item/lightreplacer(src)
new /obj/item/soap(src)
+2 -2
View File
@@ -73,7 +73,7 @@
l.janicart_insert(user,src)
else
to_chat(user, fail_msg)
else if(istype(I, /obj/item/caution))
else if(istype(I, /obj/item/clothing/suit/caution))
if(signs < max_signs)
put_in_cart(I, user)
signs++
@@ -104,7 +104,7 @@
items += list("Spray bottle" = image(icon = myspray.icon, icon_state = myspray.icon_state))
if(myreplacer)
items += list("Light replacer" = image(icon = myreplacer.icon, icon_state = myreplacer.icon_state))
var/obj/item/caution/sign = locate() in src
var/obj/item/clothing/suit/caution/sign = locate() in src
if(sign)
items += list("Sign" = image(icon = sign.icon, icon_state = sign.icon_state))
+7
View File
@@ -1,5 +1,12 @@
/turf/open
plane = FLOOR_PLANE
/// Does dirt buildup happen on us?
var/dirt_buildup_allowed = FALSE
/// Dirt level.
var/dirtyness = 0
/// Dirt level to spawn dirt. Null to use config.
var/dirt_spawn_threshold
/// Slowdown applied to mobs on us.
var/slowdown = 0 //negative for faster, positive for slower
var/postdig_icon_change = FALSE
+1
View File
@@ -9,6 +9,7 @@
canSmoothWith = list(/turf/open/floor/fakepit, /turf/open/chasm)
density = TRUE //This will prevent hostile mobs from pathing into chasms, while the canpass override will still let it function like an open turf
bullet_bounce_sound = null //abandon all hope ye who enter
dirt_buildup_allowed = FALSE
/turf/open/chasm/Initialize()
. = ..()
+4 -1
View File
@@ -8,6 +8,9 @@
//Making the station dirty, one tile at a time. Called by master controller's setup_objects
/turf/open/floor/proc/MakeDirty()
if(CONFIG_GET(flag/persistent_debris_only))
return
if(prob(66)) //fastest possible exit 2/3 of the time
return
@@ -38,7 +41,7 @@
return
//Construction zones. Blood, sweat, and oil. Oh, and dirt.
var/static/list/engine_dirt_areas = typecacheof(list(/area/engine,
var/static/list/engine_dirt_areas = typecacheof(list(/area/engine,
/area/crew_quarters/heads/chief,
/area/ruin/space/derelict/assembly_line,
/area/science/robotics,
+4
View File
@@ -5,6 +5,7 @@
name = "floor"
icon = 'icons/turf/floors.dmi'
baseturfs = /turf/open/floor/plating
dirt_buildup_allowed = TRUE
footstep = FOOTSTEP_FLOOR
barefootstep = FOOTSTEP_HARD_BAREFOOT
@@ -137,6 +138,9 @@
burnt = 1
/turf/open/floor/proc/make_plating()
for(var/obj/effect/decal/cleanable/C in src)
if(C.wiped_by_floor_change)
qdel(C)
return ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
/turf/open/floor/ChangeTurf(path, new_baseturf, flags)
@@ -61,6 +61,9 @@
to_chat(user, "<span class='notice'>You begin reinforcing the floor...</span>")
if(do_after(user, 30, target = src))
if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine))
for(var/obj/effect/decal/cleanable/decal in src)
if(decal.wiped_by_floor_change)
qdel(decal)
PlaceOnTop(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR)
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
R.use(2)
@@ -78,6 +81,9 @@
to_chat(user, "<span class='notice'>You begin adding glass to the floor...</span>")
if(do_after(user, 5, target = src))
if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass))
for(var/obj/effect/decal/cleanable/decal in src)
if(decal.wiped_by_floor_change)
qdel(decal)
PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR)
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
G.use(2)
@@ -95,6 +101,9 @@
to_chat(user, "<span class='notice'>You begin adding reinforced glass to the floor...</span>")
if(do_after(user, 10, target = src))
if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced))
for(var/obj/effect/decal/cleanable/decal in src)
if(decal.wiped_by_floor_change)
qdel(decal)
PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR)
playsound(src, 'sound/items/deconstruct.ogg', 80, 1)
RG.use(2)
@@ -110,6 +119,9 @@
var/obj/item/stack/tile/W = C
if(!W.use(1))
return
for(var/obj/effect/decal/cleanable/decal in src)
if(decal.wiped_by_floor_change)
qdel(decal)
if(istype(W, /obj/item/stack/tile/material))
var/turf/newturf = PlaceOnTop(/turf/open/floor/material, flags = CHANGETURF_INHERIT_AIR)
newturf.set_custom_materials(W.custom_materials)
@@ -43,6 +43,9 @@
return TRUE
if(floor_tile)
new floor_tile(src, 2)
for(var/obj/effect/decal/cleanable/C in src)
if(C.wiped_by_floor_change)
qdel(C)
ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
return TRUE
+1
View File
@@ -6,6 +6,7 @@
gender = PLURAL //"That's some lava."
baseturfs = /turf/open/lava //lava all the way down
slowdown = 2
dirt_buildup_allowed = FALSE
light_range = 2
light_power = 0.75
+1
View File
@@ -6,6 +6,7 @@
planetary_atmos = TRUE
bullet_bounce_sound = null //forever falling
tiled_dirt = FALSE
dirt_buildup_allowed = FALSE
/turf/open/indestructible/reebe_void/Initialize(mapload)
. = ..()
+1
View File
@@ -3,6 +3,7 @@
icon_state = "0"
name = "\proper space"
intact = 0
dirt_buildup_allowed = FALSE
temperature = TCMB
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
@@ -26,7 +26,7 @@
return
flick("blob_resource_glow", src)
if(overmind)
overmind.add_points(1)
overmind.add_points(2)
resource_delay = world.time + 40 + overmind.resource_blobs.len * 2.5 //4 seconds plus a quarter second for each resource blob the overmind has
else
resource_delay = world.time + 40
+2 -1
View File
@@ -147,7 +147,7 @@
set category = "Blob"
set name = "Create Factory Blob (60)"
set desc = "Create a spore tower that will spawn spores to harass your enemies."
createSpecial(60, /obj/structure/blob/factory, 7, 1)
createSpecial(60, /obj/structure/blob/factory, 5, 1)
/mob/camera/blob/verb/create_blobbernaut()
set category = "Blob"
@@ -195,6 +195,7 @@
to_chat(blobber, "The <b><font color=\"[blobstrain.color]\">[blobstrain.name]</b></font> reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]")
else
to_chat(src, "<span class='warning'>You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later.</span>")
B.naut = FALSE
add_points(40)
/mob/camera/blob/verb/relocate_core()
@@ -30,6 +30,7 @@
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [get_area_name(src)] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0)
SSpersistence.station_was_destroyed = TRUE
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
GLOB.ratvar_awakens--
+3 -1
View File
@@ -42,7 +42,9 @@
/obj/screen,
/obj/singularity,
/mob/living/simple_animal/hostile/morph,
/obj/effect))
/obj/effect,
/mob/camera
))
var/playstyle_string = "<span class='big bold'>You are a morph,</span></b> an abomination of science created primarily with changeling cells. \
You may take the form of anything nearby by shift-clicking it. This process will alert any nearby \
+4
View File
@@ -179,6 +179,10 @@
if((pack.hidden && !(obj_flags & EMAGGED)) || (pack.contraband && !contraband) || pack.DropPodOnly)
return
if(self_paid && !pack.can_private_buy)
say("This cannot be bought privately.")
return
var/name = "*None Provided*"
var/rank = "*None Provided*"
var/ckey = usr.ckey
+3 -3
View File
@@ -261,9 +261,9 @@
/obj/item/reagent_containers/glass/bucket,
/obj/item/reagent_containers/glass/bucket,
/obj/item/mop,
/obj/item/caution,
/obj/item/caution,
/obj/item/caution,
/obj/item/clothing/suit/caution,
/obj/item/clothing/suit/caution,
/obj/item/clothing/suit/caution,
/obj/item/storage/bag/trash,
/obj/item/reagent_containers/spray/cleaner,
/obj/item/reagent_containers/rag,
@@ -541,6 +541,21 @@
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
allowed = list(/obj/item/clothing/mask/facehugger/toy)
/obj/item/clothing/suit/caution
name = "wet floor sign"
desc = "Caution! Wet Floor!"
icon_state = "caution"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
force = 1
throwforce = 3
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN
attack_verb = list("warned", "cautioned", "smashed")
armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
// WINTER COATS
/obj/item/clothing/suit/hooded/wintercoat
@@ -7,6 +7,12 @@
foodtype = GRAIN
dunkable = TRUE
/obj/item/reagent_containers/food/snacks/store/bread/proc/bread_teleport()
// you did WHAT?
new /mob/living/simple_animal/hostile/bread(get_turf(src))
visible_message("<span class='warning'>[src] begins to deform and grow grotesque tumors!</span>")
qdel(src)
/obj/item/reagent_containers/food/snacks/breadslice
icon = 'icons/obj/food/burgerbread.dmi'
bitesize = 2
@@ -228,3 +234,25 @@
/obj/item/reagent_containers/food/snacks/butterdog/ComponentInitialize()
. = ..()
AddComponent(/datum/component/slippery, 80)
/obj/item/reagent_containers/food/snacks/store/bread/tumor_bread
name = "dead tumor bread"
desc = "It's still within its expiration date, right?."
icon_state = "tumorbread"
slice_path = /obj/item/reagent_containers/food/snacks/breadslice/tumor_bread
list_reagents = list(/datum/reagent/consumable/nutriment = 10, /datum/reagent/toxin = 10)
foodtype = GROSS | GRAIN
tastes = list("wheat and tumors" = 10)
//teleporting tumor bread kills it
/obj/item/reagent_containers/food/snacks/store/bread/tumor_bread/bread_teleport()
visible_message(src, "<span class='warning'>[src] explodes in a horrible mess of tumor and flour!</span>")
qdel(src)
/obj/item/reagent_containers/food/snacks/breadslice/tumor_bread
name = "tumor bread slice"
desc = "A slice of bread filled with tumors!"
icon_state = "tumorbreadslice"
filling_color = "#B2D72C"
list_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/toxin = 2)
foodtype = GROSS | GRAIN
+12
View File
@@ -18,6 +18,8 @@
var/map_name = "Box Station"
var/map_path = "map_files/BoxStation"
var/map_file = "BoxStation.dmm"
/// Persistence key: Defaults to ckey(map_name). If set to "NO_PERSIST", this map will have NO persistence.
var/persistence_key
var/traits = null
var/space_ruin_levels = 4
@@ -99,6 +101,16 @@
map_path = json["map_path"]
map_file = json["map_file"]
persistence_key = ckey(map_name)
var/json_persistence_key = json["persistence_key"]
if(json_persistence_key)
if(json_persistence_key == "NO_PERSIST")
persistence_key = null
else
persistence_key = json_persistence_key
// "map_file": "BoxStation.dmm"
if (istext(map_file))
if (!fexists("_maps/[map_path]/[map_file]"))
@@ -138,6 +138,18 @@
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/deco_wings/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/deco_wings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
/datum/sprite_accessory/deco_wings/jungle
name = "Jungle"
icon_state = "jungle"
//INSECT WINGS
/datum/sprite_accessory/insect_wings
@@ -15,6 +15,7 @@
block_parry_data = /datum/block_parry_data/unarmed/human
default_block_parry_data = /datum/block_parry_data/unarmed/human
causes_dirt_buildup_on_floor = TRUE
//Hair colour and style
var/hair_color = "000"
@@ -100,3 +100,8 @@
if(dna.species.space_move(src))
return TRUE
return ..()
/mob/living/carbon/human/dirt_buildup(strength)
if(!shoes || !(shoes.body_parts_covered & FEET))
return // barefoot advantage
return ..()
@@ -5,7 +5,7 @@
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade")
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade","deco_wings"= "None")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -63,6 +63,8 @@
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas
//and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt
/// Do we make floors dirty as we move?
var/causes_dirt_buildup_on_floor = FALSE
var/list/roundstart_quirks = list()
@@ -101,7 +101,30 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
if(causes_dirt_buildup_on_floor && (movement_type & GROUND))
dirt_buildup()
/**
* Attempts to make the floor dirty.
*/
/mob/living/proc/dirt_buildup(strength = 1)
var/turf/open/T = loc
if(!istype(T) || !T.dirt_buildup_allowed)
return
var/area/A = T.loc
if(!A.dirt_buildup_allowed)
return
var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
strength *= multiplier
var/obj/effect/decal/cleanable/dirt/D = locate() in T
if(D)
D.dirty(strength)
else
T.dirtyness += strength
if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
D = new /obj/effect/decal/cleanable/dirt(T)
D.dirty(T.dirt_spawn_threshold - T.dirtyness)
T.dirtyness = 0 // reset.
/mob/living/Move_Pulled(atom/A)
. = ..()
@@ -0,0 +1,69 @@
//funny reference to the video 'Expiration Date'
/mob/living/simple_animal/hostile/bread
name = "tumor bread"
desc = "I have done nothing but teleport bread for three days."
icon_state = "tumorbread"
health = 1
maxHealth = 1
turns_per_move = 5 //this isn't player speed =|
speed = 2 //this is player speed
melee_damage_lower = 1
melee_damage_upper = 2
obj_damage = 0
loot = list(/obj/item/reagent_containers/food/snacks/store/bread/tumor_bread)
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 270
maxbodytemp = INFINITY
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
response_help_continuous = "pokes"
response_help_simple = "poke"
response_disarm_continuous = "shoos"
response_disarm_simple = "shoo"
response_harm_continuous = "punches"
response_harm_simple = "punch"
speak_emote = list("growls")
mouse_opacity = 2
density = TRUE
ventcrawler = VENTCRAWLER_ALWAYS
verb_say = "growls"
verb_ask = "growls inquisitively"
verb_exclaim = "growls loudly"
verb_yell = "growls loudly"
del_on_death = TRUE
/mob/living/simple_animal/bread/hostile/Initialize()
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A tumor bread has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
/mob/living/simple_animal/hostile/bread/attack_ghost(mob/user)
if(key) //please stop using src. without a good reason.
return
if(CONFIG_GET(flag/use_age_restriction_for_jobs))
if(!isnum(user.client.player_age))
return
if(isobserver(user))
var/mob/dead/observer/O = user
if(!O.can_reenter_round())
return
if(!SSticker.mode)
to_chat(user, "Can't become a tumor bread before the game has started.")
return
var/be_bread = alert("Become a tumor bread? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_bread == "No" || QDELETED(src) || !isobserver(user))
return
if(key)
to_chat(user, "<span class='notice'>Someone else already took this tumor bread.</span>")
return
sentience_act()
user.transfer_ckey(src, FALSE)
density = TRUE
/mob/living/simple_animal/hostile/bread/ex_act()
return
/mob/living/simple_animal/hostile/bread/start_pulling()
return FALSE
@@ -354,7 +354,7 @@
/mob/living/simple_animal/proc/drop_loot()
if(loot.len)
for(var/i in loot)
new i(loc)
new i(loc, dir = src.dir)
/mob/living/simple_animal/death(gibbed)
movement_type &= ~FLYING
+2 -1
View File
@@ -182,8 +182,9 @@
if(..())
if(reagents.total_volume)
if(M.reagents)
log_combat(user, M, "injected with sleepypen", src, reagents.log_list())
reagents.reaction(M, INJECT)
reagents.trans_to(M, reagents.total_volume)
reagents.trans_to(M, reagents.total_volume, log = "sleepypen inject")
/obj/item/pen/sleepy/Initialize()
+1
View File
@@ -78,6 +78,7 @@
set_security_level("delta")
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
SSpersistence.station_was_destroyed = TRUE
sleep(600)
if(resolved == FALSE)
resolved = TRUE
@@ -142,6 +142,14 @@
cost = 4 // Has syndie tools + gloves + a robust weapon
restricted_roles = list("Assistant", "Curator") //Curator due to this being made of gold - It fits the theme
/datum/uplink_item/role_restricted/oldtoolboxclean // this is the fourth item relating to toolboxes to be placed into this godforsaken bloated uplink
name = "Ancient Toolbox"
desc = "An iconic toolbox design notorious with Assistants everywhere, this design was especially made to become more robust the more telecrystals it has inside it! Tools and insulated gloves included."
item = /obj/item/storage/toolbox/mechanical/old/clean
cost = 2 // with eighteen telecrystals you are still weaker than a desword and without any of its defenses -- the scary part comes from collaborating with allies for a fifty eight force toolbox oh fuck
restricted_roles = list("Assistant")
surplus = 0
/datum/uplink_item/role_restricted/mimery
name = "Guide to Advanced Mimery Series"
desc = "The classical two part series on how to further hone your mime skills. Upon studying the series, the user should be able to make 3x1 invisible walls, and shoot bullets out of their fingers. \
@@ -242,3 +250,11 @@
cost = 2
item = /obj/item/clothing/shoes/magboots/crushing
restricted_roles = list("Chief Engineer", "Station Engineer", "Atmospheric Technician")
/datum/uplink_item/role_restricted/turretbox
name = "Disposable Sentry Gun"
desc = "A disposable sentry gun deployment system cleverly disguised as a toolbox, apply wrench for functionality."
item = /obj/item/storage/toolbox/emergency/turret
cost = 11
restricted_roles = list("Station Engineer")
+1 -1
View File
@@ -375,7 +375,7 @@
/obj/item/paint/paint_remover = 2,
/obj/item/melee/flyswatter = 2,
/obj/item/flashlight = 2,
/obj/item/caution = 8,
/obj/item/clothing/suit/caution = 8,
/obj/item/holosign_creator = 2,
/obj/item/lightreplacer = 2,
/obj/item/soap = 2,
+1
View File
@@ -11,6 +11,7 @@ $include dynamic_config.txt
$include plushies/defines.txt
$include job_threats.txt
$include policy.txt
$include persistence.txt
$include respawns.txt
# You can use the @ character at the beginning of a config option to lock it from being edited in-game
+7 -1
View File
@@ -668,4 +668,10 @@ ALLOW_CUSTOM_SKINTONES
## Enables the FoV component, which hides objects and mobs behind the parent from their sight, unless they turn around, duh.
## Camera mobs, AIs, ghosts and some other are of course exempt from this. This also doesn't influence simplemob AI, for the best.
#USE_FIELD_OF_VISION
#USE_FIELD_OF_VISION
## Default turf threshold to get dirt
TURF_DIRT_THRESHOLD 100
## Default alpha of dirt on spawn
DIRT_ALPHA_STARTING 127
+14
View File
@@ -0,0 +1,14 @@
### Whether or not cleanable object persistence is on
PERSISTENT_DEBRIS
### Whether or not ONLY persistent cleanable objects should be spawned, for supported objects
PERSISTENT_DEBRIS_ONLY
### Max objects to store, total
PERSISTENT_DEBRIS_GLOBAL_MAX 10000
### Max objects to store per type, total
PERSISTENT_DEBRIS_TYPE_MAX 2000
### Wipe objects on nuke for the above
PERSISTENT_DEBRIS_WIPE_ON_NUKE
@@ -0,0 +1,4 @@
author: "zeroisthebiggay"
delete-after: True
changes:
- rscadd: "Traitor assistants can now purchase the patented POGBox! Put TC into it for even higher damage!"
@@ -0,0 +1,5 @@
author: "NT Cleaning Crews On Break"
delete-after: True
changes:
- rscadd: "Most kinds of dirt, grime, and debris are now persistent. Get to work, jannies."
- rscadd: "Dirt can now be removed by tile replacements. Other cleanable decals can't, though."
@@ -0,0 +1,4 @@
author: "shellspeed1"
delete-after: True
changes:
- rscadd: "Adds the disposable sentry gun from tg for 11tc each."
@@ -0,0 +1,6 @@
author: "keronshb"
delete-after: True
changes:
- balance: "Blob Resource Tower to 2 points per instead of 1 point per."
- balance: "Blob Factory Towers can be placed 5 tiles apart instead of 7."
- bugfix: "Fixes Blobbernaut Factories consuming Factories if no naut is chosen."
@@ -0,0 +1,4 @@
author: "timothyteakettle"
delete-after: True
changes:
- rscadd: "you can teleport bread"
@@ -0,0 +1,4 @@
author: "silicons"
delete-after: True
changes:
- balance: "c4 can no longer gib mobs"
@@ -0,0 +1,4 @@
author: "MrJWhit"
delete-after: True
changes:
- rscadd: "Makes gas sensors fireproof."
@@ -0,0 +1,6 @@
author: "shellspeed1"
delete-after: True
changes:
- rscadd: "Xenomorph hybrids can now select wings
~~add: Xenomorph hybrids can now speak xenomorph~~"
- rscadd: "Xenomorph tongues are available for customization."
@@ -0,0 +1,4 @@
author: "DeltaFire15"
delete-after: True
changes:
- bugfix: "Cargo packs marked as 'no private buying' now actually register as such."
@@ -0,0 +1,4 @@
author: "MrJWhit"
delete-after: True
changes:
- tweak: "Bugfix of a morph becoming an AI eye"
@@ -0,0 +1,4 @@
author: "MrJWhit"
delete-after: True
changes:
- tweak: "Porting garbage collection tweak from /tg/"
@@ -0,0 +1,4 @@
author: "MrJWhit"
delete-after: True
changes:
- tweak: "Fixes two chairs on one table"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 KiB

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

+9 -1
View File
@@ -292,6 +292,7 @@
#include "code\controllers\configuration\entries\fail2topic.dm"
#include "code\controllers\configuration\entries\game_options.dm"
#include "code\controllers\configuration\entries\general.dm"
#include "code\controllers\configuration\entries\persistence.dm"
#include "code\controllers\configuration\entries\plushies.dm"
#include "code\controllers\configuration\entries\policy.dm"
#include "code\controllers\configuration\entries\resources.dm"
@@ -340,7 +341,6 @@
#include "code\controllers\subsystem\pai.dm"
#include "code\controllers\subsystem\parallax.dm"
#include "code\controllers\subsystem\pathfinder.dm"
#include "code\controllers\subsystem\persistence.dm"
#include "code\controllers\subsystem\profiler.dm"
#include "code\controllers\subsystem\radiation.dm"
#include "code\controllers\subsystem\radio.dm"
@@ -363,6 +363,13 @@
#include "code\controllers\subsystem\vis_overlays.dm"
#include "code\controllers\subsystem\vore.dm"
#include "code\controllers\subsystem\vote.dm"
#include "code\controllers\subsystem\persistence\_persistence.dm"
#include "code\controllers\subsystem\persistence\cleanable_debris.dm"
#include "code\controllers\subsystem\persistence\panic_bunker.dm"
#include "code\controllers\subsystem\persistence\poly_parrot.dm"
#include "code\controllers\subsystem\persistence\recent_votes_etc.dm"
#include "code\controllers\subsystem\persistence\secret_satchels.dm"
#include "code\controllers\subsystem\persistence\trophies.dm"
#include "code\controllers\subsystem\processing\chemistry.dm"
#include "code\controllers\subsystem\processing\circuit.dm"
#include "code\controllers\subsystem\processing\fastprocess.dm"
@@ -2716,6 +2723,7 @@
#include "code\modules\mob\living\simple_animal\hostile\banana_spider.dm"
#include "code\modules\mob\living\simple_animal\hostile\bear.dm"
#include "code\modules\mob\living\simple_animal\hostile\bees.dm"
#include "code\modules\mob\living\simple_animal\hostile\bread.dm"
#include "code\modules\mob\living\simple_animal\hostile\carp.dm"
#include "code\modules\mob\living\simple_animal\hostile\cat_butcher.dm"
#include "code\modules\mob\living\simple_animal\hostile\dark_wizard.dm"
+1 -1
View File
@@ -3,7 +3,7 @@
"name": "tgui-dev-server",
"version": "4.2.0",
"dependencies": {
"axios": "^0.19.2",
"axios": "^0.21.1",
"common": "workspace:*",
"esm": "^3.2.25",
"glob": "^7.1.4",
@@ -57,7 +57,6 @@ const Toner = (props, context) => {
title="Toner"
buttons={
<Button
disabled={!current_toner}
onClick={() => act('remove_toner')}
icon="eject">
Eject
File diff suppressed because one or more lines are too long