diff --git a/_maps/shuttles/ert_bounty.dmm b/_maps/shuttles/ert_bounty.dmm new file mode 100644 index 00000000000..92b3628f97f --- /dev/null +++ b/_maps/shuttles/ert_bounty.dmm @@ -0,0 +1,486 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"d" = ( +/obj/structure/sign/warning/vacuum/external, +/turf/closed/wall/mineral/plastitanium, +/area/shuttle/hunter) +"f" = ( +/obj/structure/table, +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"h" = ( +/obj/effect/spawner/structure/window/reinforced/plasma/plastitanium, +/turf/open/floor/plating, +/area/shuttle/hunter) +"j" = ( +/obj/structure/curtain/bounty, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"l" = ( +/obj/machinery/power/shuttle_engine/propulsion{ + dir = 8 + }, +/turf/open/floor/plating/airless, +/area/shuttle/hunter) +"n" = ( +/turf/closed/wall/mineral/plastitanium, +/area/shuttle/hunter) +"p" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plating, +/area/shuttle/hunter) +"r" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/obj/effect/landmark/ert_shuttle_spawn, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"s" = ( +/obj/machinery/computer/shuttle/hunter{ + dir = 8 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"t" = ( +/obj/machinery/suit_storage_unit/standard_unit{ + storage_type = /obj/item/tank/internals/oxygen/yellow + }, +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"u" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"v" = ( +/obj/machinery/power/shuttle_engine/heater{ + dir = 8 + }, +/obj/structure/window/reinforced{ + dir = 4 + }, +/turf/open/floor/plating/airless, +/area/shuttle/hunter) +"w" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external/ruin, +/turf/open/floor/plating, +/area/shuttle/hunter) +"x" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/obj/effect/landmark/ert_shuttle_spawn, +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"y" = ( +/obj/structure/chair/office{ + dir = 4 + }, +/obj/effect/landmark/ert_shuttle_spawn, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"z" = ( +/obj/structure/sign/poster/contraband/bountyhunters, +/turf/closed/wall/mineral/plastitanium, +/area/shuttle/hunter) +"A" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"C" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"D" = ( +/obj/machinery/power/smes, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"E" = ( +/obj/structure/table, +/obj/item/phone, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"F" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/airlock/external/ruin, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/shuttle/hunter) +"G" = ( +/turf/open/floor/plating, +/area/shuttle/hunter) +"H" = ( +/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/hunter{ + dir = 8 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"I" = ( +/obj/structure/chair/comfy/shuttle{ + dir = 4 + }, +/obj/effect/landmark/ert_shuttle_brief_spawn, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"K" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/obj/effect/landmark/ert_shuttle_spawn, +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"L" = ( +/obj/effect/landmark/ert_shuttle_spawn, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"O" = ( +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"P" = ( +/obj/structure/table, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"Q" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/airlock/external/ruin, +/turf/open/floor/plating, +/area/shuttle/hunter) +"R" = ( +/obj/structure/table, +/obj/item/binoculars, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"S" = ( +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"T" = ( +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/shuttle/hunter) +"U" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external/ruin, +/obj/docking_port/stationary{ + dwidth = 11; + height = 16; + name = "Deep Space"; + shuttle_id = "pirate_home"; + width = 17 + }, +/obj/docking_port/mobile{ + dheight = 3; + dwidth = 3; + height = 13; + movement_force = list("KNOCKDOWN" = 0, "THROW" = 0); + name = "hunter shuttle"; + rechargeTime = 1800; + shuttle_id = "huntership"; + width = 15 + }, +/obj/structure/fans/tiny, +/turf/open/floor/plating, +/area/shuttle/hunter) +"V" = ( +/obj/machinery/computer/camera_advanced{ + dir = 8 + }, +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"W" = ( +/obj/structure/table, +/obj/item/storage/toolbox/mechanical, +/turf/open/floor/pod/light, +/area/shuttle/hunter) +"X" = ( +/obj/structure/rack, +/obj/item/grenade/c4{ + pixel_x = -1; + pixel_y = 1 + }, +/obj/item/grenade/c4{ + pixel_x = -6; + pixel_y = 7 + }, +/obj/item/grenade/c4{ + pixel_x = 7; + pixel_y = -5 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) +"Z" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/turf/open/floor/pod/dark, +/area/shuttle/hunter) + +(1,1,1) = {" +a +a +a +n +a +a +a +a +a +n +a +a +a +"} +(2,1,1) = {" +a +a +a +n +a +a +a +a +a +n +a +a +a +"} +(3,1,1) = {" +n +a +a +n +a +l +a +l +a +n +a +a +n +"} +(4,1,1) = {" +n +a +l +n +n +v +h +v +n +n +l +a +n +"} +(5,1,1) = {" +n +n +v +n +n +O +X +D +n +n +v +n +n +"} +(6,1,1) = {" +n +n +d +n +n +O +O +O +n +n +d +n +n +"} +(7,1,1) = {" +F +p +G +T +w +A +C +Z +Q +p +G +T +U +"} +(8,1,1) = {" +n +n +h +n +n +j +j +j +n +n +h +n +n +"} +(9,1,1) = {" +a +n +h +n +x +y +L +O +t +n +h +n +a +"} +(10,1,1) = {" +a +a +h +z +f +E +P +O +t +n +h +a +a +"} +(11,1,1) = {" +a +a +a +n +W +P +R +O +t +n +a +a +a +"} +(12,1,1) = {" +a +a +a +n +K +r +L +O +t +n +a +a +a +"} +(13,1,1) = {" +a +a +a +h +n +j +j +j +n +h +a +a +a +"} +(14,1,1) = {" +a +a +a +h +S +O +O +O +S +h +a +a +a +"} +(15,1,1) = {" +a +a +a +h +S +u +I +u +S +h +a +a +a +"} +(16,1,1) = {" +a +a +a +n +h +s +V +H +h +n +a +a +a +"} +(17,1,1) = {" +a +a +a +a +h +h +h +h +h +a +a +a +a +"} diff --git a/code/datums/ert.dm b/code/datums/ert.dm index 99d80935022..6299e7de727 100644 --- a/code/datums/ert.dm +++ b/code/datums/ert.dm @@ -18,6 +18,10 @@ var/leader_experience = TRUE ///SKYRAT EDIT: Do we want to notify the players of this ERT? var/notify_players = TRUE + /// A custom map template to spawn the ERT at. If this is null or use_custom_shuttle is FALSE, the ERT will spawn at Centcom. + var/datum/map_template/ert_template + /// If we should actually _use_ the ert_template custom shuttle + var/use_custom_shuttle = TRUE /datum/ert/New() if (!polldesc) @@ -113,3 +117,4 @@ mission = "Assist the station in catching perps, dead or alive." polldesc = "a Centcom-hired bounty hunting gang" random_names = FALSE + ert_template = /datum/map_template/shuttle/ert/bounty diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index 654bd1bee64..45a4b455685 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -165,6 +165,10 @@ port_id = "snowdin" who_can_purchase = null +/datum/map_template/shuttle/ert + port_id = "ert" + who_can_purchase = null + // Shuttles start here: /datum/map_template/shuttle/emergency/backup @@ -760,4 +764,9 @@ suffix = "excavation" name = "Snowdin Excavation Elevator" +// Custom ERT shuttles +/datum/map_template/shuttle/ert/bounty + suffix = "bounty" + name = "Bounty Hunter ERT Shuttle" + #undef EMAG_LOCKED_SHUTTLE_COST diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index f77338df7af..8460364cac0 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -367,6 +367,14 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player) GLOB.emergencyresponseteamspawn += loc return INITIALIZE_HINT_QDEL +/obj/effect/landmark/ert_shuttle_spawn + name = "ertshuttlespawn" + icon_state = "ert_spawn" + +/obj/effect/landmark/ert_shuttle_brief_spawn + name = "ertshuttlebriefspawn" + icon_state = "ert_brief_spawn" + //ninja energy nets teleport victims here /obj/effect/landmark/holding_facility name = "Holding Facility" diff --git a/code/modules/admin/verbs/ert.dm b/code/modules/admin/verbs/ert.dm index dd51113f92e..387f54ef806 100644 --- a/code/modules/admin/verbs/ert.dm +++ b/code/modules/admin/verbs/ert.dm @@ -21,6 +21,7 @@ .["mainsettings"]["leader_experience"]["value"] = newtemplate.leader_experience ? "Yes" : "No" .["mainsettings"]["random_names"]["value"] = newtemplate.random_names ? "Yes" : "No" .["mainsettings"]["spawn_admin"]["value"] = newtemplate.spawn_admin ? "Yes" : "No" + .["mainsettings"]["use_custom_shuttle"]["value"] = newtemplate.use_custom_shuttle ? "Yes" : "No" /datum/admins/proc/equipAntagOnDummy(mob/living/carbon/human/dummy/mannequin, datum/antagonist/antag) @@ -88,11 +89,12 @@ "leader_experience" = list("desc" = "Pick an experienced leader", "type" = "boolean", "value" = "[(ertemplate.leader_experience ? "Yes" : "No")]"), "random_names" = list("desc" = "Randomize names", "type" = "boolean", "value" = "[(ertemplate.random_names ? "Yes" : "No")]"), "spawn_admin" = list("desc" = "Spawn yourself as briefing officer", "type" = "boolean", "value" = "[(ertemplate.spawn_admin ? "Yes" : "No")]"), - "notify_players" = list("desc" = "Notify players that you have sent an ERT", "type" = "boolean", "value" = "[(ertemplate.notify_players ? "Yes" : "No")]") //SKYRAT EDIT ADDITION + "notify_players" = list("desc" = "Notify players that you have sent an ERT", "type" = "boolean", "value" = "[(ertemplate.notify_players ? "Yes" : "No")]"), //SKYRAT EDIT ADDITION + "use_custom_shuttle" = list("desc" = "Use the ERT's custom shuttle (if it has one)", "type" = "boolean", "value" = "[(ertemplate.use_custom_shuttle ? "Yes" : "No")]"), ) ) - var/list/prefreturn = presentpreflikepicker(usr,"Customize ERT", "Customize ERT", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings) + var/list/prefreturn = presentpreflikepicker(usr, "Customize ERT", "Customize ERT", Button1="Ok", width = 600, StealFocus = 1,Timeout = 0, settings=settings) if (isnull(prefreturn)) return FALSE @@ -110,37 +112,76 @@ ertemplate.teamsize = prefs["teamsize"]["value"] ertemplate.mission = prefs["mission"]["value"] ertemplate.polldesc = prefs["polldesc"]["value"] - ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" // these next 5 are effectively toggles + ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" // these next 6 are effectively toggles ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes" ertemplate.leader_experience = prefs["leader_experience"]["value"] == "Yes" ertemplate.random_names = prefs["random_names"]["value"] == "Yes" ertemplate.spawn_admin = prefs["spawn_admin"]["value"] == "Yes" ertemplate.notify_players = prefs["notify_players"]["value"] == "Yes" //SKYRAT EDIT ADDITION + ertemplate.use_custom_shuttle = prefs["use_custom_shuttle"]["value"] == "Yes" var/list/spawnpoints = GLOB.emergencyresponseteamspawn var/index = 0 + var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you wish to be considered for [ertemplate.polldesc]?", "deathsquad") + var/teamSpawned = FALSE + + // This list will take priority over spawnpoints if not empty + var/list/spawn_turfs = list() + + // Takes precedence over spawnpoints[1] if not null + var/turf/brief_spawn + + if(!length(candidates)) + return FALSE + + if(ertemplate.use_custom_shuttle && ertemplate.ert_template) + to_chat(usr, span_boldnotice("Attempting to spawn ERT custom shuttle, this may take a few seconds...")) + var/datum/map_template/shuttle/ship = new ertemplate.ert_template + var/x = rand(TRANSITIONEDGE, world.maxx - TRANSITIONEDGE - ship.width) + var/y = rand(TRANSITIONEDGE, world.maxy - TRANSITIONEDGE - ship.height) + var/z = SSmapping.empty_space.z_value + var/turf/located_turf = locate(x, y, z) + if(!located_turf) + CRASH("ERT shuttle found no place to load in") + + if(!ship.load(located_turf)) + CRASH("Loading ERT shuttle failed!") + + var/list/shuttle_turfs = ship.get_affected_turfs(located_turf) + + for(var/turf/affected_turf as anything in shuttle_turfs) + for(var/obj/effect/landmark/ert_shuttle_spawn/spawner in affected_turf) + spawn_turfs += get_turf(spawner) + + if(!brief_spawn) + brief_spawn = locate(/obj/effect/landmark/ert_shuttle_brief_spawn) in affected_turf + + if(!length(spawn_turfs)) + stack_trace("ERT shuttle loaded but found no spawnpoints, placing the ERT at wherever inside the shuttle instead.") + + for(var/turf/open/floor/open_turf in shuttle_turfs) + if(!is_safe_turf(open_turf)) + continue + spawn_turfs += open_turf + + if(ertemplate.spawn_admin) if(isobserver(usr)) - var/mob/living/carbon/human/admin_officer = new (spawnpoints[1]) + var/mob/living/carbon/human/admin_officer = new (brief_spawn || spawnpoints[1]) var/chosen_outfit = usr.client?.prefs?.read_preference(/datum/preference/choiced/brief_outfit) usr.client.prefs.safe_transfer_prefs_to(admin_officer, is_antag = TRUE) admin_officer.equipOutfit(chosen_outfit) admin_officer.key = usr.key + else to_chat(usr, span_warning("Could not spawn you in as briefing officer as you are not a ghost!")) - var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you wish to be considered for [ertemplate.polldesc]?", "deathsquad") - var/teamSpawned = FALSE - - if(candidates.len == 0) - return FALSE - //Pick the (un)lucky players - var/numagents = min(ertemplate.teamsize,candidates.len) + var/numagents = min(ertemplate.teamsize, length(candidates)) //Create team - var/datum/team/ert/ert_team = new ertemplate.team () + var/datum/team/ert/ert_team = new ertemplate.team() if(ertemplate.rename_team) ert_team.name = ertemplate.rename_team @@ -169,9 +210,14 @@ earmarked_leader = pick(candidates) while(numagents && candidates.len) - var/spawnloc = spawnpoints[index+1] - //loop through spawnpoints one at a time - index = (index + 1) % spawnpoints.len + var/turf/spawnloc + if(length(spawn_turfs)) + spawnloc = pick(spawn_turfs) + else + spawnloc = spawnpoints[index+1] + //loop through spawnpoints one at a time + index = (index + 1) % spawnpoints.len + var/mob/dead/observer/chosen_candidate = earmarked_leader || pick(candidates) // this way we make sure that our leader gets chosen candidates -= chosen_candidate if(!chosen_candidate?.key) diff --git a/icons/effects/landmarks_static.dmi b/icons/effects/landmarks_static.dmi index d6a26b050d5..5537b58448f 100644 Binary files a/icons/effects/landmarks_static.dmi and b/icons/effects/landmarks_static.dmi differ