diff --git a/_maps/map_files/templates/shelter_1.dmm b/_maps/map_files/templates/shelter_1.dmm new file mode 100644 index 00000000000..19071ada955 --- /dev/null +++ b/_maps/map_files/templates/shelter_1.dmm @@ -0,0 +1,23 @@ +"a" = (/turf/simulated/wall/survival,/area/survivalpod) +"b" = (/obj/structure/sign/mining/survival{tag = "icon-survival (NORTH)"; icon_state = "survival"; dir = 1},/turf/simulated/wall/survival,/area/survivalpod) +"c" = (/obj/structure/fans,/turf/simulated/floor/pod,/area/survivalpod) +"d" = (/obj/machinery/smartfridge/survival_pod/loaded,/turf/simulated/floor/pod,/area/survivalpod) +"e" = (/obj/item/device/gps/computer,/turf/simulated/floor/pod,/area/survivalpod) +"f" = (/obj/structure/sign/mining/survival{dir = 8},/turf/simulated/wall/survival,/area/survivalpod) +"g" = (/obj/machinery/sleeper/survival_pod,/turf/simulated/floor/pod,/area/survivalpod) +"h" = (/turf/simulated/floor/pod,/area/survivalpod) +"i" = (/obj/structure/stool/bed/pod,/obj/item/weapon/bedsheet/brown,/turf/simulated/floor/pod,/area/survivalpod) +"j" = (/obj/structure/sign/mining/survival{tag = "icon-survival (EAST)"; icon_state = "survival"; dir = 4},/turf/simulated/wall/survival,/area/survivalpod) +"k" = (/obj/structure/table/survival_pod,/turf/simulated/floor/pod,/area/survivalpod) +"l" = (/obj/structure/tubes,/obj/structure/stool/bed/chair/comfy/black{dir = 8},/turf/simulated/floor/pod,/area/survivalpod) +"m" = (/obj/structure/sign/mining/survival,/turf/simulated/wall/survival,/area/survivalpod) +"n" = (/obj/structure/fans/tiny,/obj/machinery/door/airlock/survival_pod,/turf/simulated/floor/pod,/area/survivalpod) +"o" = (/obj/structure/sign/mining,/turf/simulated/wall/survival,/area/survivalpod) + +(1,1,1) = {" +aabaa +acdea +fghij +akhla +amnoa +"} diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index ab1357a5833..85221f5cf3c 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -1,5 +1,3 @@ -#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level - //Object specific defines #define CANDLE_LUM 3 //For how bright candles are @@ -281,4 +279,11 @@ // Sound #define SOUND_MINIMUM_PRESSURE 10 -#define FALLOFF_SOUNDS 0.5 \ No newline at end of file +#define FALLOFF_SOUNDS 0.5 + + +// Bluespace shelter deploy checks +#define SHELTER_DEPLOY_ALLOWED "allowed" +#define SHELTER_DEPLOY_BAD_TURFS "bad turfs" +#define SHELTER_DEPLOY_BAD_AREA "bad area" +#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects" diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index 3042ff6d302..b623ce72158 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -6,4 +6,7 @@ #define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste. #define QDEL_HINT_PUTINPOOL 5 //qdel will put this object in the atom pool. #define QDEL_HINT_FINDREFERENCE 6 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm. - //if TESTING is enabled, qdel will call this object's find_references() verb. \ No newline at end of file + //if TESTING is enabled, qdel will call this object's find_references() verb. + +// A convenient wrapper around checking for qdeletion/non-existence +#define exists(A) (A && !qdeleted(A)) diff --git a/code/__DEFINES/zlevel.dm b/code/__DEFINES/zlevel.dm index e69de29bb2d..274fbb75f07 100644 --- a/code/__DEFINES/zlevel.dm +++ b/code/__DEFINES/zlevel.dm @@ -0,0 +1,12 @@ +#define Z_LEVEL_NORTH "1" +#define Z_LEVEL_SOUTH "2" +#define Z_LEVEL_EAST "4" +#define Z_LEVEL_WEST "8" + +#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level + +// Defining these here so everything is consistent +#define TRANSITION_BORDER_NORTH (world.maxy - TRANSITIONEDGE - 1) +#define TRANSITION_BORDER_SOUTH TRANSITIONEDGE +#define TRANSITION_BORDER_EAST (world.maxx - TRANSITIONEDGE - 1) +#define TRANSITION_BORDER_WEST TRANSITIONEDGE diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm index abc81f9d52a..44b678a8f67 100644 --- a/code/_globalvars/mapping.dm +++ b/code/_globalvars/mapping.dm @@ -52,3 +52,4 @@ var/list/datum/map_template/map_templates = list() var/list/datum/map_template/ruins_templates = list() var/list/datum/map_template/space_ruins_templates = list() //var/list/datum/map_template/lava_ruins_templates = list() +var/list/datum/map_template/shelter_templates = list() \ No newline at end of file diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 8b61be7d12b..0d52cdc9463 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -116,7 +116,7 @@ if(!config.disable_space_ruins) // so we don't unnecessarily clutter start-up preloadRuinTemplates() - //preloadShuttleTemplates() + preloadShelterTemplates() /proc/preloadRuinTemplates() // Still supporting bans by filename @@ -147,15 +147,12 @@ if(istype(R, /datum/map_template/ruin/space)) space_ruins_templates[R.name] = R -/* -/proc/preloadShuttleTemplates() - for(var/item in subtypesof(/datum/map_template/shuttle)) - var/datum/map_template/shuttle/shuttle_type = item - if(!(initial(shuttle_type.suffix))) +/proc/preloadShelterTemplates() + for(var/item in subtypesof(/datum/map_template/shelter)) + var/datum/map_template/shelter/shelter_type = item + if(!(initial(shelter_type.mappath))) continue + var/datum/map_template/shelter/S = new shelter_type() - var/datum/map_template/shuttle/S = new shuttle_type() - - shuttle_templates[S.shuttle_id] = S - map_templates[S.shuttle_id] = S -*/ + shelter_templates[S.shelter_id] = S + map_templates[S.shelter_id] = S \ No newline at end of file diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index b2185b15d33..843e4e1258b 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -340,7 +340,8 @@ var/round_start_time = 0 if(player.ready && player.mind) if(player.mind.assigned_role == "AI") player.close_spawn_windows() - player.AIize() + var/mob/living/silicon/ai/ai_character = player.AIize() + ai_character.moveToAILandmark() else if(!player.mind.assigned_role) continue else diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index a0b3f147b46..60e650691e5 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -577,4 +577,17 @@ light_color = LIGHT_COLOR_DARKRED +/obj/machinery/sleeper/syndie/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/sleeper/syndicate(null) + var/obj/item/weapon/stock_parts/matter_bin/B = new(null) + B.rating = initial_bin_rating + component_parts += B + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/stack/cable_coil(null, 1) + RefreshParts() + #undef ADDICTION_SPEEDUP_TIME \ No newline at end of file diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index f06771cc288..29e315ec001 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -264,9 +264,9 @@ atom/proc/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/A if(interaction == AI_TRANS_FROM_CARD) AI.control_disabled = 0 AI.aiRadio.disabledAi = 0 - AI.loc = loc//To replace the terminal. + AI.forceMove(loc)//To replace the terminal. to_chat(AI, "You have been uploaded to a stationary terminal. Remote device connection restored.") - to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.") + to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.") qdel(src) else //If for some reason you use an empty card on an empty AI terminal. to_chat(user, "There is no AI loaded on this terminal!") diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 2defdbf4623..2c6740ffbb3 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -744,6 +744,15 @@ obj/item/weapon/circuitboard/rdserver /obj/item/stack/cable_coil = 1, /obj/item/weapon/stock_parts/console_screen = 2) +/obj/item/weapon/circuitboard/sleeper/syndicate + name = "circuit board (Sleeper Syndicate)" + build_path = /obj/machinery/sleeper/syndie + +/obj/item/weapon/circuitboard/sleeper/survival + name = "circuit board (Sleeper Survival Pod)" + build_path = /obj/machinery/sleeper/survival_pod + + /obj/item/weapon/circuitboard/bodyscanner name = "circuit board (Body Scanner)" build_path = /obj/machinery/bodyscanner diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 518304fda5f..b003d9ef1d6 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -386,6 +386,8 @@ Class Procs: I.crit_fail = 1 I.forceMove(loc) qdel(src) + return 1 + return 0 /obj/machinery/proc/default_deconstruction_screwdriver(var/mob/user, var/icon_state_open, var/icon_state_closed, var/obj/item/weapon/screwdriver/S) if(istype(S)) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 4cdc3494927..4a9d8c439ae 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -113,7 +113,9 @@ var/const/SAFETY_COOLDOWN = 100 for(var/i in to_eat) var/atom/movable/AM = i - if(isliving(AM)) + if(!exists(AM)) + continue + else if(isliving(AM)) if(emagged) crush_living(AM) else @@ -123,7 +125,7 @@ var/const/SAFETY_COOLDOWN = 100 items_recycled++ else playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) - AM.loc = loc + AM.forceMove(loc) if(items_recycled && sound) playsound(loc, item_recycle_sound, 100, 0) diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index bfbd0a4ccb6..f5b3650c5bb 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -129,3 +129,11 @@ turf_type = /turf/simulated/floor/silent mineralType = "tranquillite" materials = list(MAT_TRANQUILLITE=500) + +//Pod floor +/obj/item/stack/tile/pod + name = "pod floor tile" + singular_name = "pod floor tile" + desc = "A grooved floor tile." + icon_state = "tile_pod" + turf_type = /turf/simulated/floor/pod \ No newline at end of file diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index 0b090581595..6399a11c291 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -1,16 +1,49 @@ -/obj/item/weapon/dice - name = "d6" +/obj/item/weapon/storage/pill_bottle/dice + name = "bag of dice" + desc = "Contains all the luck you'll ever need." + icon = 'icons/obj/dice.dmi' + icon_state = "dicebag" + +/obj/item/weapon/storage/pill_bottle/dice/New() + ..() + var/special_die = pick("1","2","fudge","00","100") + if(special_die == "1") + new /obj/item/weapon/dice/d1(src) + if(special_die == "2") + new /obj/item/weapon/dice/d2(src) + new /obj/item/weapon/dice/d4(src) + new /obj/item/weapon/dice/d6(src) + if(special_die == "fudge") + new /obj/item/weapon/dice/fudge(src) + new /obj/item/weapon/dice/d8(src) + new /obj/item/weapon/dice/d10(src) + if(special_die == "00") + new /obj/item/weapon/dice/d00(src) + new /obj/item/weapon/dice/d12(src) + new /obj/item/weapon/dice/d20(src) + if(special_die == "100") + new /obj/item/weapon/dice/d100(src) + +/obj/item/weapon/dice //depreciated d6, use /obj/item/weapon/dice/d6 if you actually want a d6 + name = "die" desc = "A die with six sides. Basic and servicable." icon = 'icons/obj/dice.dmi' icon_state = "d6" w_class = 1 var/sides = 6 var/result = null + var/list/special_faces = list() //entries should match up to sides var if used /obj/item/weapon/dice/New() result = rand(1, sides) update_icon() +/obj/item/weapon/dice/d1 + name = "d1" + desc = "A die with one side. Deterministic!" + icon_state = "d1" + sides = 1 + /obj/item/weapon/dice/d2 name = "d2" desc = "A die with two sides. Coins are undignified!" @@ -23,6 +56,16 @@ icon_state = "d4" sides = 4 +/obj/item/weapon/dice/d6 + name = "d6" + +/obj/item/weapon/dice/fudge + name = "fudge die" + desc = "A die with six sides but only three results. Is this a plus or a minus? Your mind is drawing a blank..." + sides = 3 //shhh + icon_state = "fudge" + special_faces = list("minus","blank","plus") + /obj/item/weapon/dice/d8 name = "d8" desc = "A die with eight sides. It feels... lucky." @@ -53,6 +96,15 @@ icon_state = "d20" sides = 20 +/obj/item/weapon/dice/d100 + name = "d100" + desc = "A die with one hundred sides! Probably not fairly weighted..." + icon_state = "d100" + sides = 100 + +/obj/item/weapon/dice/d100/update_icon() + return + /obj/item/weapon/dice/d20/e20 var/triggered = 0 @@ -64,8 +116,9 @@ return diceroll(user) -/obj/item/weapon/dice/proc/diceroll(mob/user as mob) +/obj/item/weapon/dice/proc/diceroll(mob/user) result = rand(1, sides) + var/fake_result = rand(1, sides)//Daredevil isn't as good as he used to be var/comment = "" if(sides == 20 && result == 20) comment = "Nat 20!" @@ -74,20 +127,14 @@ update_icon() if(initial(icon_state) == "d00") result = (result - 1)*10 + if(special_faces.len == sides) + result = special_faces[result] if(user != null) //Dice was rolled in someone's hand user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \ "You throw [src]. It lands on [result]. [comment]", \ - "You hear [src] landing on [result]. [comment]") + "You hear [src] rolling, it sounds like a [fake_result].") else if(src.throwing == 0) //Dice was thrown and is coming to rest visible_message("[src] rolls to a stop, landing on [result]. [comment]") -/* -/obj/item/weapon/dice/d4/Crossed(var/mob/living/carbon/human/H) - if(istype(H) && !H.shoes) - to_chat(H, "You step on the D4!") - H.apply_damage(4,BRUTE,(pick("l_leg", "r_leg"))) - H.Weaken(3) -*///ew. - /obj/item/weapon/dice/d20/e20/diceroll(mob/user as mob, thrown) if(triggered) @@ -112,6 +159,7 @@ /obj/item/weapon/dice/update_icon() overlays.Cut() overlays += "[src.icon_state][src.result]" + /obj/item/weapon/storage/box/dice name = "Box of dice" desc = "ANOTHER ONE!? FUCK!" diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 03ba6bed54b..67d44c53b2d 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -276,16 +276,6 @@ new /obj/item/weapon/reagent_containers/food/pill/charcoal( src ) new /obj/item/weapon/reagent_containers/food/pill/charcoal( src ) -/obj/item/weapon/storage/pill_bottle/dice - name = "pack of dice" - desc = "It's a small container with dice inside." - - New() - ..() - new /obj/item/weapon/dice( src ) - new /obj/item/weapon/dice/d20( src ) - - /obj/item/weapon/storage/pill_bottle/painkillers name = "Pill Bottle (Salicylic Acid)" desc = "Contains various pills for minor pain relief." diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 4ec1b1587c8..d498109b2dd 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -83,7 +83,7 @@ icon = loc if(!in_range(src, user)) if(icon == src) - to_chat(user, "\blue It's \a [bicon(icon)][src]! If you want any more information you'll need to get closer.") + to_chat(user, "It's \a [bicon(icon)][src]! If you want any more information you'll need to get closer.") return var/celsius_temperature = air_contents.temperature-T0C diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 1831b983f2c..ed0092cf60d 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -65,7 +65,10 @@ /obj/structure/closet/proc/moveMob(var/mob/M, var/atom/destination) loc.Exited(M) M.loc = destination - loc.Entered(M, ignoreRest = 1) + if(isturf(loc)) + loc.Entered(M, src, ignoreRest = 1) + else + loc.Entered(M, src) for(var/atom/movable/AM in loc) if(istype(AM, /obj/item)) continue diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index c1b6d7d2122..a247e35a86f 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -116,6 +116,8 @@ if(!..()) return 0 + if(!istype(M)) // To avoid non-humans from causing runtimes whena dding blood to the floor + return 0 var/obj/effect/decal/cleanable/blood/B = locate() in contents //check for existing blood splatter if(!B) blood_splatter(src,M.get_blood(M.vessel),1) diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index fb10d23ae9c..c8c454383ea 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -213,21 +213,21 @@ /turf/space/proc/set_transition_north(dest_z) destination_x = x - destination_y = TRANSITIONEDGE + 2 + destination_y = TRANSITION_BORDER_SOUTH + 1 destination_z = dest_z /turf/space/proc/set_transition_south(dest_z) destination_x = x - destination_y = world.maxy - TRANSITIONEDGE - 2 + destination_y = TRANSITION_BORDER_NORTH - 1 destination_z = dest_z /turf/space/proc/set_transition_east(dest_z) - destination_x = TRANSITIONEDGE + 2 + destination_x = TRANSITION_BORDER_WEST + 1 destination_y = y destination_z = dest_z /turf/space/proc/set_transition_west(dest_z) - destination_x = world.maxx - TRANSITIONEDGE - 2 + destination_x = TRANSITION_BORDER_EAST - 1 destination_y = y destination_z = dest_z diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 9548e189695..a457a843ffb 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1416,7 +1416,8 @@ message_admins("\red Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!", 1) log_admin("[key_name(usr)] AIized [key_name(H)]") - H.AIize() + var/mob/living/silicon/ai/ai_character = H.AIize() + ai_character.moveToAILandmark() else if(href_list["makealien"]) if(!check_rights(R_SPAWN)) return diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 577d16233d8..b776eb9a649 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -416,6 +416,8 @@ Traitors and the like can also be revived with the previous role mostly intact. call(/datum/game_mode/proc/add_law_zero)(new_character) if("AI") new_character = new_character.AIize() + var/mob/living/silicon/ai/ai_character = new_character + ai_character.moveToAILandmark() if(new_character.mind.special_role=="traitor") call(/datum/game_mode/proc/add_law_zero)(new_character) //Add aliens. diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index ed4e648e6d0..b70c2741e83 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -295,7 +295,8 @@ prefs.last_id = computer_id //these are gonna be used for banning . = ..() //calls mob.Login() - chatOutput.start() + spawn() // Goonchat does some non-instant checks in start() + chatOutput.start() if(custom_event_msg && custom_event_msg != "") to_chat(src, "

Custom Event

") diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index a012afa74f9..d403b4aae4b 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -779,6 +779,17 @@ Post_Consume(mob/living/M) M.reagents.add_reagent("omnizine", 15) +/obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket_weak + name = "Lightly Warm Donk-pocket" + desc = "The food of choice for the seasoned traitor. This one is lukewarm." + icon_state = "donkpocket" + filling_color = "#DEDEAB" + +/obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket_weak/New() + ..() + reagents.add_reagent("nutriment", 4) + reagents.add_reagent("weak_omnizine", 3) + /obj/item/weapon/reagent_containers/food/snacks/syndidonkpocket name = "Donk-pocket" desc = "This donk-pocket is emitting a small amount of heat." diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 9a670e42d7a..c6f7e54a003 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -49,6 +49,8 @@ /obj/machinery/smartfridge/Destroy() qdel(wires) wires = null + for(var/atom/movable/A in contents) + A.forceMove(loc) return ..() /obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj) @@ -207,7 +209,8 @@ power_change() return - default_deconstruction_crowbar(O) + if(default_deconstruction_crowbar(O)) + return if(istype(O, /obj/item/device/multitool)||istype(O, /obj/item/weapon/wirecutters)) if(panel_open) diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index 994f141d373..22fb9156004 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -250,11 +250,11 @@ var/no_los var/turf/last_turf = origin_turf for(var/turf/target_turf in getline(origin_turf,neighbor)) - if(!last_turf.Enter(target_turf) || target_turf.density) + if(!last_turf.Enter(thrown,target_turf) || target_turf.density) no_los = 1 break last_turf = target_turf - if(!no_los && !origin_turf.Enter(neighbor)) + if(!no_los && !origin_turf.Enter(thrown, neighbor)) no_los = 1 if(no_los) closed_turfs |= neighbor @@ -406,8 +406,10 @@ /datum/seed/proc/randomize() roundstart = 0 - seed_name = "strange plant" // TODO: name generator. + // TODO: Better name generator + seed_name = "cultivar #[uid]" display_name = "strange plants" // TODO: name generator. + base_name = seed_name mysterious = 1 seed_noun = pick("spores","nodes","cuttings","seeds") modular_icon = 1 diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm index aaa30c3275f..7e56c57a45f 100644 --- a/code/modules/hydroponics/seed_controller.dm +++ b/code/modules/hydroponics/seed_controller.dm @@ -96,9 +96,9 @@ var/global/datum/controller/plants/plant_controller // Set in New(). // Proc for creating a random seed type. /datum/controller/plants/proc/create_random_seed(var/survive_on_station) var/datum/seed/seed = new() - seed.randomize() seed.uid = plant_controller.seeds.len + 1 seed.name = "[seed.uid]" + seed.randomize() seeds[seed.name] = seed if(survive_on_station) @@ -106,8 +106,7 @@ var/global/datum/controller/plants/plant_controller // Set in New(). seed.consume_gasses["plasma"] = null seed.consume_gasses["carbon_dioxide"] = null if(seed.chems && !isnull(seed.chems["pacid"])) - seed.chems["pacid"] = null // Eating through the hull will make these plants completely inviable, albeit very dangerous. - seed.chems -= null // Setting to null does not actually remove the entry, which is weird. + seed.chems -= "pacid" // Eating through the hull will make these plants completely inviable, albeit very dangerous. seed.set_trait(TRAIT_IDEAL_HEAT,293) seed.set_trait(TRAIT_HEAT_TOLERANCE,20) seed.set_trait(TRAIT_IDEAL_LIGHT,8) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index e774ef23924..1b1e4755e9b 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -263,6 +263,198 @@ icon_state = "mobcap[colorindex]" update_icon() +/*****************************Survival Pod********************************/ + + +/area/survivalpod + name = "\improper Emergency Shelter" + icon_state = "away" + requires_power = 0 + has_gravity = 1 + +/obj/item/weapon/survivalcapsule + name = "bluespace shelter capsule" + desc = "An emergency shelter stored within a pocket of bluespace." + icon_state = "capsule" + icon = 'icons/obj/mining.dmi' + w_class = 1 + origin_tech = "engineering=3;bluespace=3" + var/template_id = "shelter_alpha" + var/datum/map_template/shelter/template + var/used = FALSE + +/obj/item/weapon/survivalcapsule/proc/get_template() + if(template) + return + template = shelter_templates[template_id] + if(!template) + log_runtime("Shelter template ([template_id]) not found!", src) + qdel(src) + +/obj/item/weapon/survivalcapsule/examine(mob/user) + . = ..() + get_template() + to_chat(user, "This capsule has the [template.name] stored.") + to_chat(user, template.description) + +/obj/item/weapon/survivalcapsule/attack_self() + // Can't grab when capsule is New() because templates aren't loaded then + get_template() + if(used == FALSE) + loc.visible_message("[src] begins to shake. Stand back!") + used = TRUE + sleep(50) + var/turf/deploy_location = get_turf(src) + var/status = template.check_deploy(deploy_location) + switch(status) + if(SHELTER_DEPLOY_BAD_AREA) + loc.visible_message("[src] will not function in this area.") + if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS) + var/width = template.width + var/height = template.height + loc.visible_message("[src] doesn't have room to deploy! You need to clear a [width]x[height] area!") + + if(status != SHELTER_DEPLOY_ALLOWED) + used = FALSE + return + + playsound(get_turf(src), 'sound/effects/phasein.ogg', 100, 1) + + var/turf/T = deploy_location + if(!is_mining_level(T.z))//only report capsules away from the mining/lavaland level + message_admins("[key_name_admin(usr)] (?) (FLW) activated a bluespace capsule away from the mining level! (JMP)") + log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [T.x], [T.y], [T.z]") + template.load(deploy_location, centered = TRUE) + new /obj/effect/effect/harmless_smoke(get_turf(src)) + qdel(src) + +//Pod turfs and objects + + +//Floors +/turf/simulated/floor/pod + name = "pod floor" + icon_state = "podfloor" + icon_regular_floor = "podfloor" + floor_tile = /obj/item/stack/tile/pod + +//Walls +/turf/simulated/wall/survival + name = "pod wall" + desc = "An easily-compressable wall used for temporary shelter." + icon = 'icons/turf/walls/survival_pod_walls.dmi' + icon_state = "smooth" + walltype = "shuttle" + smooth = SMOOTH_MORE // To Do: Add in Diagnaol Smooth Support + canSmoothWith = list(/turf/simulated/wall/survival, /obj/machinery/door/airlock/survival_pod) + +//Door +/obj/machinery/door/airlock/survival_pod + name = "Airlock" + icon = 'icons/obj/doors/survival.dmi' + assembly_type = /obj/structure/door_assembly/door_assembly_pod + opacity = 0 + glass = 1 + +/obj/structure/door_assembly/door_assembly_pod + base_icon_state = "survival_pod" + glass_type = "/survival_pod" + +//Table +/obj/structure/table/survival_pod + icon = 'icons/obj/lavaland/survival_pod.dmi' + icon_state = "table" + smooth = SMOOTH_FALSE + +//Sleeper +/obj/machinery/sleeper/survival_pod + icon = 'icons/obj/lavaland/survival_pod.dmi' + icon_state = "sleeper-open" + density = 0 + +/obj/machinery/sleeper/survival_pod/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/sleeper/survival(null) + var/obj/item/weapon/stock_parts/matter_bin/B = new(null) + B.rating = initial_bin_rating + component_parts += B + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) + component_parts += new /obj/item/stack/cable_coil(null, 1) + RefreshParts() + +//Computer +/obj/item/device/gps/computer + name = "pod computer" + icon_state = "pod_computer" + icon = 'icons/obj/lavaland/pod_computer.dmi' + anchored = 1 + density = 1 + pixel_y = -32 + +/obj/item/device/gps/computer/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + user.visible_message("[user] disassembles the gps.", \ + "You start to disassemble the gps...", "You hear clanking and banging noises.") + if(do_after(user, 20, target = src)) + new /obj/item/device/gps(loc) + qdel(src) + return ..() + +/obj/item/device/gps/computer/attack_hand(mob/user) + attack_self(user) + +//Bed +/obj/structure/stool/bed/pod + icon = 'icons/obj/lavaland/survival_pod.dmi' + icon_state = "bed" + +//Survival Storage Unit +/obj/machinery/smartfridge/survival_pod + name = "survival pod storage" + desc = "A heated storage unit." + icon_state = "donkvendor" + icon = 'icons/obj/lavaland/donkvendor.dmi' + icon_on = "donkvendor" + icon_off = "donkvendor" + light_range = 8 + max_n_of_items = 10 + pixel_y = -4 + +/obj/item/weapon/circuitboard/smartfridge/survival + name = "circuit board (Smartfridge Survival)" + build_path = /obj/machinery/smartfridge/survival_pod + +/obj/item/weapon/circuitboard/smartfridge/attackby(obj/item/I, mob/user, params) + return + +/obj/machinery/smartfridge/survival_pod/accept_check(obj/item/O) + if(istype(O, /obj/item)) + return 1 + return 0 + +/obj/machinery/smartfridge/survival_pod/New() + ..() + component_parts = list() + component_parts += new /obj/item/weapon/circuitboard/smartfridge/survival(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + RefreshParts() + +/obj/machinery/smartfridge/survival_pod/loaded/New() + ..() + for(var/i in 1 to 5) + var/obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket_weak/W = new(src) + load(W) + if(prob(50)) + var/obj/item/weapon/storage/pill_bottle/dice/D = new(src) + load(D) + else + var/obj/item/device/guitar/G = new(src) + load(G) + //Fans /obj/structure/fans icon = 'icons/obj/lavaland/survival_pod.dmi' @@ -307,4 +499,36 @@ return ..() /obj/structure/fans/CanAtmosPass(turf/T) - return !arbitraryatmosblockingvar \ No newline at end of file + return !arbitraryatmosblockingvar + +//Signs +/obj/structure/sign/mining + name = "nanotrasen mining corps sign" + desc = "A sign of relief for weary miners, and a warning for would-be competitors to Nanotrasen's mining claims." + icon = 'icons/turf/walls/survival_pod_walls.dmi' + icon_state = "ntpod" + +/obj/structure/sign/mining/survival + name = "shelter sign" + desc = "A high visibility sign designating a safe shelter." + icon = 'icons/turf/walls/survival_pod_walls.dmi' + icon_state = "survival" + +//Fluff +/obj/structure/tubes + icon_state = "tubes" + icon = 'icons/obj/lavaland/survival_pod.dmi' + name = "tubes" + anchored = 1 + layer = MOB_LAYER - 0.2 + density = 0 + +/obj/structure/tubes/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + user.visible_message("[user] disassembles [src].", \ + "You start to disassemble [src]...", "You hear clanking and banging noises.") + if(do_after(user, 20, target = src)) + new /obj/item/stack/rods(loc) + qdel(src) + return ..() \ No newline at end of file diff --git a/code/modules/mining/shelters.dm b/code/modules/mining/shelters.dm new file mode 100644 index 00000000000..38750b12d19 --- /dev/null +++ b/code/modules/mining/shelters.dm @@ -0,0 +1,42 @@ +/datum/map_template/shelter + var/shelter_id + var/description + var/blacklisted_turfs + var/whitelisted_turfs + var/banned_areas + +/datum/map_template/shelter/New() + . = ..() + blacklisted_turfs = typecacheof(list(/turf/simulated/wall, /turf/simulated/mineral, /turf/simulated/shuttle/wall)) + whitelisted_turfs = list() + banned_areas = typecacheof(/area/shuttle) + +/datum/map_template/shelter/proc/check_deploy(turf/deploy_location) + var/affected = get_affected_turfs(deploy_location, centered=TRUE) + for(var/turf/T in affected) + var/area/A = get_area(T) + if(is_type_in_typecache(A, banned_areas)) + return SHELTER_DEPLOY_BAD_AREA + + var/banned = is_type_in_typecache(T, blacklisted_turfs) + var/permitted = is_type_in_typecache(T, whitelisted_turfs) + if(banned && !permitted) + return SHELTER_DEPLOY_BAD_TURFS + + for(var/obj/O in T) + if(O.density && O.anchored) + return SHELTER_DEPLOY_ANCHORED_OBJECTS + return SHELTER_DEPLOY_ALLOWED + +/datum/map_template/shelter/alpha + name = "Shelter Alpha" + shelter_id = "shelter_alpha" + description = "A cosy self-contained pressurized shelter, with \ + built-in navigation, entertainment, medical facilities and a \ + sleeping area! Order now, and we'll throw in a TINY FAN, \ + absolutely free!" + mappath = "_maps/map_files/templates/shelter_1.dmm" + +/datum/map_template/shelter/alpha/New() + . = ..() + whitelisted_turfs = typecacheof(/turf/simulated/mineral) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 857ff6b2de2..981dad22bf5 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -12,6 +12,7 @@ var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call. /mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna = 0) + if(!dna) dna = new /datum/dna(null) // Species name is handled by set_species() @@ -22,6 +23,8 @@ else set_species(delay_icon_update = 1) + ..() + if(species) real_name = species.get_random_name(gender) name = real_name @@ -32,8 +35,6 @@ reagents = R R.my_atom = src - ..() - prev_gender = gender // Debug for plural genders make_blood() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 0aa2daa0f4f..3f7a76c0470 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -201,7 +201,8 @@ update_hair(redraw_mob) //rebuild hair update_fhair(redraw_mob) update_head_accessory(redraw_mob) - sec_hud_set_ID() + if(hud_list.len) + sec_hud_set_ID() update_inv_wear_mask(redraw_mob) if(slot_handcuffed) handcuffed = W @@ -220,7 +221,8 @@ update_inv_belt(redraw_mob) if(slot_wear_id) wear_id = W - sec_hud_set_ID() + if(!hud_list.len) + sec_hud_set_ID() update_inv_wear_id(redraw_mob) if(slot_wear_pda) wear_pda = W diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index 024172abe8b..1e255ea50cc 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -99,4 +99,4 @@ desc = "strong adamantine hands" icon_state = "golem" item_state = null - flags = ABSTRACT | NODROP \ No newline at end of file + flags = ABSTRACT | NODROP diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm index d869b72eff3..56cee4f651f 100644 --- a/code/modules/mob/living/silicon/ai/latejoin.dm +++ b/code/modules/mob/living/silicon/ai/latejoin.dm @@ -37,4 +37,42 @@ var/global/list/empty_playable_ai_cores = list() var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode current_mode.possible_traitors.Remove(src) - qdel(src) \ No newline at end of file + qdel(src) + +// TODO: Move away from the insane name-based landmark system +/mob/living/silicon/ai/proc/moveToAILandmark() + var/obj/loc_landmark + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if(sloc.name != "AI") + continue + if(locate(/mob/living) in sloc.loc) + continue + loc_landmark = sloc + if(!loc_landmark) + for(var/obj/effect/landmark/tripai in landmarks_list) + if(tripai.name == "tripai") + if(locate(/mob/living) in tripai.loc) + continue + loc_landmark = tripai + if(!loc_landmark) + to_chat(src, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.") + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if(sloc.name == "AI") + loc_landmark = sloc + + forceMove(loc_landmark.loc) + +// Before calling this, make sure an empty core exists, or this will no-op +/mob/living/silicon/ai/proc/moveToEmptyCore() + if(!empty_playable_ai_cores.len) + log_debug("moveToEmptyCore called without any available cores") + return + + // IsJobAvailable for AI checks that there is an empty core available in this list + var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1] + empty_playable_ai_cores -= C + + forceMove(C.loc) + + + qdel(C) diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index adc0e54e661..dfa79a0d0d1 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -56,7 +56,7 @@ while(!istype(M, /mob/living)) if(!M || !M.loc || count > 6) //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) - to_chat(src, "You are not being carried by anyone!") + to_chat(P, "You are not being carried by anyone!") return 0 M = M.loc count++ @@ -705,7 +705,7 @@ while(!isliving(held)) if(!held || !held.loc || count > 6) //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) - to_chat(src, "You are not being carried by anyone!") + to_chat(user, "You are not being carried by anyone!") return 0 held = held.loc count++ diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 682abdb383d..d820f984ec1 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -296,18 +296,13 @@ // AIs don't need a spawnpoint, they must spawn at an empty core if(character.mind.assigned_role == "AI") - character = character.AIize(move=0) // AIize the character, but don't move them yet + var/mob/living/silicon/ai/ai_character = character.AIize() // AIize the character, but don't move them yet // IsJobAvailable for AI checks that there is an empty core available in this list - var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1] - empty_playable_ai_cores -= C + ai_character.moveToEmptyCore() + AnnounceCyborg(ai_character, rank, "has been downloaded to the empty core in \the [get_area(ai_character)]") - character.loc = C.loc - - AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [get_area(character)]") - ticker.mode.latespawn(character) - - qdel(C) + ticker.mode.latespawn(ai_character) qdel(src) return diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index ea710335c77..43970987724 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -7,14 +7,6 @@ spawning = 1 return ..() -/mob/living/carbon/human/AIize(move=1) // 'move' argument needs defining here too because BYOND is dumb - if(notransform) - return - for(var/t in organs) - qdel(t) - - return ..(move) - /mob/living/carbon/AIize() if(notransform) return @@ -40,34 +32,12 @@ else O.key = key - var/obj/loc_landmark - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if(sloc.name != "AI") - continue - if(locate(/mob/living) in sloc.loc) - continue - loc_landmark = sloc - if(!loc_landmark) - for(var/obj/effect/landmark/tripai in landmarks_list) - if(tripai.name == "tripai") - if(locate(/mob/living) in tripai.loc) - continue - loc_landmark = tripai - if(!loc_landmark) - to_chat(O, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.") - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if(sloc.name == "AI") - loc_landmark = sloc - - O.loc = loc_landmark.loc - O.on_mob_init() O.add_ai_verbs() O.rename_self("AI",1) - spawn - qdel(src) + qdel(src) return O diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm index e5e7af93b66..c9cb554b64f 100644 --- a/code/modules/reagents/newchem/medicine.dm +++ b/code/modules/reagents/newchem/medicine.dm @@ -1007,4 +1007,55 @@ M.adjustToxLoss(-5*REM) M.adjustBrainLoss(-15*REM) M.adjustCloneLoss(-3*REM) - ..() \ No newline at end of file + ..() + + +/datum/reagent/omnizine_diluted + name = "Diluted Omnizine" + id = "weak_omnizine" + description = "Slowly heals all damage types. A far weaker substitute than actual omnizine." + reagent_state = LIQUID + color = "#DCDCDC" + overdose_threshold = 30 + metabolization_rate = 0.1 + +/datum/reagent/omnizine_diluted/on_mob_life(mob/living/M) + M.adjustToxLoss(-0.5*REM) + M.adjustOxyLoss(-0.5*REM) + M.adjustBruteLoss(-0.5*REM) + M.adjustFireLoss(-0.5*REM) + ..() + +/datum/reagent/omnizine_diluted/overdose_process(mob/living/M, severity) + var/effect = ..() + if(severity == 1) //lesser + M.stuttering += 1 + if(effect <= 1) + M.visible_message("[M] suddenly cluches their gut!") + M.emote("scream") + M.Stun(4) + M.Weaken(4) + else if(effect <= 3) + M.visible_message("[M] completely spaces out for a moment.") + M.confused += 15 + else if(effect <= 5) + M.visible_message("[M] stumbles and staggers.") + M.Dizzy(5) + M.Weaken(3) + else if(effect <= 7) + M.visible_message("[M] shakes uncontrollably.") + M.Jitter(30) + else if(severity == 2) // greater + if(effect <= 2) + M.visible_message("[M] suddenly cluches their gut!") + M.emote("scream") + M.Stun(7) + M.Weaken(7) + else if(effect <= 5) + M.visible_message("[M] jerks bolt upright, then collapses!") + M.Paralyse(5) + M.Weaken(4) + else if(effect <= 8) + M.visible_message("[M] stumbles and staggers.") + M.Dizzy(5) + M.Weaken(3) \ No newline at end of file diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 39945505aed..85657dd2b5b 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -27,12 +27,10 @@ idle_power_usage = 100 // create a new disposal -// find the attached trunk (if present) and init gas resvr. +// find the attached trunk (if present) /obj/machinery/disposal/New() ..() trunk_check() - - air_contents = new/datum/gas_mixture() //gas.volume = 1.05 * CELLSTANDARD update() @@ -59,6 +57,7 @@ var/datum/gas_mixture/env = new env.copy_from(L.return_air()) var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1) + air_contents = new air_contents.merge(removed) trunk_check() diff --git a/code/modules/space_management/level_traits.dm b/code/modules/space_management/level_traits.dm index 83309c3764f..ae5d6447aae 100644 --- a/code/modules/space_management/level_traits.dm +++ b/code/modules/space_management/level_traits.dm @@ -38,7 +38,7 @@ var/list/default_map_traits = MAP_TRANSITION_CONFIG /proc/check_level_trait(z, trait) - if(z == 0) + if(!z) return 0 // If you're nowhere, you have no traits var/list/trait_list if(space_manager.initialized) diff --git a/code/modules/space_management/space_level.dm b/code/modules/space_management/space_level.dm index 02c16552c12..dc598ccab42 100644 --- a/code/modules/space_management/space_level.dm +++ b/code/modules/space_management/space_level.dm @@ -39,57 +39,57 @@ /datum/space_level/proc/build_space_destination_arrays() // We skip `add_to_transit` here because we want to skip the checks in order to save time // Bottom border - for(var/turf/space/S in block(locate(1,1,zpos),locate(world.maxx,TRANSITIONEDGE+1,zpos))) + for(var/turf/space/S in block(locate(1,1,zpos),locate(world.maxx,TRANSITION_BORDER_SOUTH,zpos))) transit_south |= S // Top border - for(var/turf/space/S in block(locate(1,world.maxy,zpos),locate(world.maxx,world.maxy - TRANSITIONEDGE - 1,zpos))) + for(var/turf/space/S in block(locate(1,world.maxy,zpos),locate(world.maxx,TRANSITION_BORDER_NORTH,zpos))) transit_north |= S // Left border - for(var/turf/space/S in block(locate(1,TRANSITIONEDGE+1,zpos),locate(TRANSITIONEDGE+1,world.maxy - TRANSITIONEDGE - 2,zpos))) + for(var/turf/space/S in block(locate(1,TRANSITION_BORDER_SOUTH + 1,zpos),locate(TRANSITION_BORDER_WEST,TRANSITION_BORDER_NORTH - 1,zpos))) transit_west |= S // Right border - for(var/turf/space/S in block(locate(world.maxx - TRANSITIONEDGE - 1,TRANSITIONEDGE+1,zpos),locate(world.maxx,world.maxy - TRANSITIONEDGE - 2,zpos))) + for(var/turf/space/S in block(locate(TRANSITION_BORDER_EAST,TRANSITION_BORDER_SOUTH + 1,zpos),locate(world.maxx,TRANSITION_BORDER_NORTH - 1,zpos))) transit_east |= S /datum/space_level/proc/add_to_transit(turf/space/S) - if(S.y <= TRANSITIONEDGE) + if(S.y <= TRANSITION_BORDER_SOUTH) transit_south |= S return // Top border - if(S.y >= (world.maxy - TRANSITIONEDGE - 1)) + if(S.y >= TRANSITION_BORDER_NORTH) transit_north |= S return // Left border - if(S.x <= TRANSITIONEDGE) + if(S.x <= TRANSITION_BORDER_WEST) transit_west |= S return // Right border - if(S.x >= (world.maxx - TRANSITIONEDGE - 1)) + if(S.x >= TRANSITION_BORDER_EAST) transit_east |= S /datum/space_level/proc/remove_from_transit(turf/space/S) - if(S.y <= TRANSITIONEDGE) + if(S.y <= TRANSITION_BORDER_SOUTH) transit_south -= S return // Top border - if(S.y >= (world.maxy - TRANSITIONEDGE - 1)) + if(S.y >= TRANSITION_BORDER_NORTH) transit_north -= S return // Left border - if(S.x <= TRANSITIONEDGE) + if(S.x <= TRANSITION_BORDER_WEST) transit_west -= S return // Right border - if(S.x >= (world.maxx - TRANSITIONEDGE - 1)) + if(S.x >= TRANSITION_BORDER_EAST) transit_east -= S /datum/space_level/proc/apply_transition(turf/space/S) @@ -101,16 +101,16 @@ if(SELFLOOPING,CROSSLINKED) var/datum/space_level/E = get_connection() if(S in transit_north) - E = get_connection("[NORTH]") + E = get_connection(Z_LEVEL_NORTH) S.set_transition_north(E.zpos) if(S in transit_south) - E = get_connection("[SOUTH]") + E = get_connection(Z_LEVEL_SOUTH) S.set_transition_south(E.zpos) if(S in transit_east) - E = get_connection("[EAST]") + E = get_connection(Z_LEVEL_EAST) S.set_transition_east(E.zpos) if(S in transit_west) - E = get_connection("[WEST]") + E = get_connection(Z_LEVEL_WEST) S.set_transition_west(E.zpos) diff --git a/code/modules/space_management/space_transition.dm b/code/modules/space_management/space_transition.dm index b7691ce6601..f432d9733a5 100644 --- a/code/modules/space_management/space_transition.dm +++ b/code/modules/space_management/space_transition.dm @@ -1,9 +1,5 @@ //This is realisation of the working torus-looping randomized-per-round space map, this kills the cube -#define Z_LEVEL_NORTH "1" -#define Z_LEVEL_SOUTH "2" -#define Z_LEVEL_EAST "4" -#define Z_LEVEL_WEST "8" /proc/get_opposite_direction(direction) switch(direction) @@ -430,9 +426,3 @@ else our_spot = our_spot.ChangeTurf(/turf/simulated/floor/fakespace) our_spot.desc = grid_desc - - -#undef Z_LEVEL_NORTH -#undef Z_LEVEL_SOUTH -#undef Z_LEVEL_EAST -#undef Z_LEVEL_WEST diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index e2702b36afe..699b9ed1ee3 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -69,13 +69,14 @@ if(parent && parent.children) parent.children -= src - if(owner) - owner.organs_by_name[limb_name] = null - if(internal_organs) for(var/obj/item/organ/internal/O in internal_organs) internal_organs -= O O.remove(owner,special = 1) + qdel(O) + + if(owner) + owner.organs_by_name[limb_name] = null if(children) for(var/obj/item/organ/external/C in children) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index a902dc55afa..2d9ddf78e80 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -39,7 +39,7 @@ var/mob/living/carbon/human/H = M parent = H.get_organ(check_zone(parent_organ)) if(!istype(parent)) - log_to_dd("[src] attempted to insert into a [parent], but [parent] wasn't an organ! Area: [get_area(M)]") + log_debug("[src] attempted to insert into a [parent_organ], but [parent_organ] wasn't an organ! [atom_loc_line(M)]") else parent.internal_organs |= src //M.internal_organs_by_name[src] |= src(H,1) @@ -52,6 +52,8 @@ // Returns the removed object, which is usually just itself // However, you MUST set the object's positiion yourself when you call this! /obj/item/organ/internal/remove(mob/living/carbon/M, special = 0) + if(!owner) + log_debug("\'remove\' called on [src] without an owner! Mob: [M], [atom_loc_line(M)]") owner = null if(M) M.internal_organs -= src @@ -63,7 +65,7 @@ var/mob/living/carbon/human/H = M var/obj/item/organ/external/parent = H.get_organ(check_zone(parent_organ)) if(!istype(parent)) - log_to_dd("[src] attempted to remove from a [parent], but [parent] didn't exist! Area: [get_area(M)], Mob: [M]") + log_debug("[src] attempted to remove from a [parent_organ], but [parent_organ] didn't exist! [atom_loc_line(M)]") else parent.internal_organs -= src diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm index e8af8c93430..bc5392e2251 100644 --- a/goon/code/datums/browserOutput.dm +++ b/goon/code/datums/browserOutput.dm @@ -37,6 +37,9 @@ var/list/chatResources = list( broken = TRUE return 0 + if(!owner) // In case the client vanishes before winexists returns + return 0 + if(winget(owner, "browseroutput", "is-disabled") == "false") doneLoading() diff --git a/html/changelogs/AutoChangeLog-pr-5509.yml b/html/changelogs/AutoChangeLog-pr-5509.yml new file mode 100644 index 00000000000..f20d11714c9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5509.yml @@ -0,0 +1,5 @@ +author: Fox McCloud and KorPhaeron +delete-after: True +changes: + - rscadd: "Adds in mining shelters" + - rscadd: "Adds in a few more dice types and ensure dice are packed in bags and not pill bottles" diff --git a/icons/obj/dice.dmi b/icons/obj/dice.dmi index d1a2dde4550..9ec030df05e 100644 Binary files a/icons/obj/dice.dmi and b/icons/obj/dice.dmi differ diff --git a/icons/obj/doors/door_assembly.dmi b/icons/obj/doors/door_assembly.dmi index 2c927cb8047..232a54da317 100644 Binary files a/icons/obj/doors/door_assembly.dmi and b/icons/obj/doors/door_assembly.dmi differ diff --git a/icons/obj/doors/survival.dmi b/icons/obj/doors/survival.dmi new file mode 100644 index 00000000000..fcc10adaa17 Binary files /dev/null and b/icons/obj/doors/survival.dmi differ diff --git a/icons/obj/lavaland/donkvendor.dmi b/icons/obj/lavaland/donkvendor.dmi new file mode 100644 index 00000000000..0b78a5168e4 Binary files /dev/null and b/icons/obj/lavaland/donkvendor.dmi differ diff --git a/icons/obj/lavaland/pod_computer.dmi b/icons/obj/lavaland/pod_computer.dmi new file mode 100644 index 00000000000..8417cfb8802 Binary files /dev/null and b/icons/obj/lavaland/pod_computer.dmi differ diff --git a/icons/obj/lavaland/survival_pod.dmi b/icons/obj/lavaland/survival_pod.dmi index 62aad7854d2..fae242d524f 100644 Binary files a/icons/obj/lavaland/survival_pod.dmi and b/icons/obj/lavaland/survival_pod.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index c39dbef36a8..ef7ea2ddac7 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/turf/walls/survival_pod_walls.dmi b/icons/turf/walls/survival_pod_walls.dmi new file mode 100644 index 00000000000..12dc44e9ea2 Binary files /dev/null and b/icons/turf/walls/survival_pod_walls.dmi differ diff --git a/paradise.dme b/paradise.dme index 26679b0288d..a2f58dff96d 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1416,6 +1416,7 @@ #include "code\modules\mining\money_bag.dm" #include "code\modules\mining\ore.dm" #include "code\modules\mining\satchel_ore_boxdm.dm" +#include "code\modules\mining\shelters.dm" #include "code\modules\mining\laborcamp\laborminerals.dm" #include "code\modules\mining\laborcamp\laborshuttle.dm" #include "code\modules\mining\laborcamp\laborstacker.dm"