diff --git a/code/game/objects/structures/droppod.dm b/code/game/objects/structures/droppod.dm new file mode 100644 index 0000000000..3afef81584 --- /dev/null +++ b/code/game/objects/structures/droppod.dm @@ -0,0 +1,133 @@ +/obj/structure/drop_pod + name = "drop pod" + desc = "Standard Commonwealth drop pod. There are file marks where the serial number should be, however." + icon = 'icons/obj/structures/droppod.dmi' + icon_state = "pod" + density = TRUE + anchored = TRUE + + var/polite = FALSE // polite ones don't violently murder everything + var/finished = FALSE + var/datum/gas_mixture/pod_air/air + +/obj/structure/drop_pod/polite + polite = TRUE + +/obj/structure/drop_pod/New(newloc, atom/movable/A, auto_open = FALSE) + ..() + if(A) + A.forceMove(src) // helo + podfall(auto_open) + air = new(1000) + +/obj/structure/drop_pod/proc/podfall(auto_open) + set waitfor = FALSE // sleeping in new otherwise + + var/turf/T = get_turf(src) + if(!T) + warning("Drop pod wasn't spawned on a turf") + return + + moveToNullspace() + icon_state = "[initial(icon_state)]_falling" + + // Show warning on 3x3 area centred on our drop spot + var/list/turfs_nearby = block(get_step(T, SOUTHWEST), get_step(T, NORTHEAST)) + for(var/turf/TN in turfs_nearby) + new /obj/effect/temporary_effect/shuttle_landing(TN) + + // Wait a minute + sleep(4 SECONDS) + + // Wheeeeeee + pixel_z = 300 + alpha = 0 + forceMove(T) + playsound(T, 'sound/effects/droppod.ogg', 50, 1) + animate(src, pixel_z = 0, time = 3 SECONDS, easing = SINE_EASING|EASE_OUT) + animate(src, alpha = 255, time = 1 SECOND, flags = ANIMATION_PARALLEL) + filters += filter(type="drop_shadow", x=-64, y=100, size=10) + animate(filters[filters.len], x=0, y=0, size=0, time=3 SECONDS, flags=ANIMATION_PARALLEL, easing=SINE_EASING|EASE_OUT) + sleep(2 SECONDS) + new /obj/effect/effect/smoke(T) + sleep(1 SECOND) + filters = null + + // CRONCH + playsound(src, 'sound/effects/meteorimpact.ogg', 50, 1) + if(!polite) + for(var/atom/A in view(1, T)) + if(A == src) + continue + A.ex_act(2) + else + for(var/turf/simulated/floor/F in view(1, T)) + F.burn_tile(900) + + for(var/obj/O in T) + if(O == src) + continue + qdel(O) + for(var/mob/living/L in T) + L.gib() + + // Landed! Simmer + icon_state = "[initial(icon_state)]" + + if(auto_open) + sleep(2 SECONDS) + open_pod() + visible_message("\The [src] pops open!") + else + for(var/mob/M in src) + to_chat(M, "You've landed! Open the hatch if you think it's safe! \The [src] has enough air to last for a while...") + +/obj/structure/drop_pod/proc/open_pod() + if(finished) + return + icon_state = "[initial(icon_state)]_open" + playsound(src, 'sound/effects/magnetclamp.ogg', 100, 1) + for(var/atom/movable/AM in src) + AM.forceMove(loc) + AM.set_dir(SOUTH) // cus + qdel_null(air) + finished = TRUE + +/obj/structure/drop_pod/attack_hand(mob/living/user) + if(istype(user) && (Adjacent(user) || (user in src)) && !user.incapacitated()) + if(finished) + to_chat(user, "Nothing left to do with it now. Maybe you can break it down into materials.") + else + open_pod() + user.visible_message("[user] opens \the [src]!","You open \the [src]!") + +/obj/structure/drop_pod/attackby(obj/item/O, mob/user) + if(O.is_wrench()) + if(finished) + to_chat(user, "You start breaking down \the [src].") + if(do_after(user, 10 SECONDS, src, exclusive = TASK_ALL_EXCLUSIVE)) + var/obj/item/stack/S = new /obj/item/stack/material/plasteel(loc) + S.amount = 10 + qdel(src) + playsound(src, O.usesound, 50, 1) + else + to_chat(user, "\The [src] hasn't been opened yet. Do that first.") + return ..() + +/obj/structure/drop_pod/return_air() + return return_air_for_internal_lifeform() + +/obj/structure/drop_pod/return_air_for_internal_lifeform() + return air + +// This is about 0.896m^3 of atmosphere, which is enough to last for quite a while. +/datum/gas_mixture/pod_air + volume = 2500 + temperature = 293.150 + total_moles = 104 + +/datum/gas_mixture/pod_air/New() + . = ..() + gas = list( + "oxygen" = 21, + "nitrogen" = 79) diff --git a/code/modules/admin/admin_verb_lists.dm b/code/modules/admin/admin_verb_lists.dm index aa37774d35..9fbabaafd5 100644 --- a/code/modules/admin/admin_verb_lists.dm +++ b/code/modules/admin/admin_verb_lists.dm @@ -141,6 +141,7 @@ var/list/admin_verbs_fun = list( /datum/admins/proc/call_drop_pod, /client/proc/smite, /client/proc/admin_lightning_strike, + /client/proc/cmd_admin_droppod_deploy ) var/list/admin_verbs_spawn = list( @@ -149,6 +150,7 @@ var/list/admin_verbs_spawn = list( /datum/admins/proc/check_custom_items, /datum/admins/proc/spawn_plant, /datum/admins/proc/spawn_atom, //allows us to spawn instances, + /client/proc/cmd_admin_droppod_spawn, /client/proc/respawn_character, /client/proc/virus2_editor, /client/proc/spawn_chemdisp_cartridge, diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index 597c229478..0cc95ff8c6 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -155,7 +155,8 @@ var/list/admin_verbs_fun = list( /client/proc/smite, /client/proc/smite_vr, //VOREStation Add, /client/proc/admin_lightning_strike, - /client/proc/resize //VOREStation Add, + /client/proc/resize, //VOREStation Add, + /client/proc/cmd_admin_droppod_deploy ) var/list/admin_verbs_spawn = list( @@ -164,6 +165,7 @@ var/list/admin_verbs_spawn = list( /datum/admins/proc/check_custom_items, /datum/admins/proc/spawn_plant, /datum/admins/proc/spawn_atom, //allows us to spawn instances, + /client/proc/cmd_admin_droppod_spawn, /client/proc/respawn_character, /client/proc/spawn_character_mob, //VOREStation Add, /client/proc/virus2_editor, diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index a581d3fb82..c41116686c 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -390,7 +390,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if(location == "Cancel" || !location) return - var/announce = tgui_alert(src,"Announce as if they had just arrived?", "Announce", list("Yes", "No", "Cancel")) + var/announce = tgui_alert(src,"Announce as if they had just arrived?", "Announce", list("No", "Yes", "Cancel")) if(announce == "Cancel") return else if(announce == "Yes") //Too bad buttons can't just have 1/0 values and different display strings @@ -420,7 +420,7 @@ Traitors and the like can also be revived with the previous role mostly intact. else if(samejob == USELESS_JOB) //VOREStation Edit - Visitor not Assistant charjob = USELESS_JOB //VOREStation Edit - Visitor not Assistant else - records = tgui_alert(src,"No data core entry detected. Would you like add them to the manifest, and sec/med/HR records?","Records",list("Yes","No","Cancel")) + records = tgui_alert(src,"No data core entry detected. Would you like add them to the manifest, and sec/med/HR records?","Records",list("No", "Yes", "Cancel")) if(records == "Cancel") return if(records == "Yes") @@ -457,17 +457,19 @@ Traitors and the like can also be revived with the previous role mostly intact. var/mob/living/carbon/human/new_character var/spawnloc - var/sparks + var/showy //Where did you want to spawn them? switch(location) if("Right Here") //Spawn them on your turf spawnloc = get_turf(src.mob) - sparks = tgui_alert(src,"Sparks like they teleported in?", "Showy", list("Yes", "No", "Cancel")) - if(sparks == "Cancel") + showy = tgui_alert(src,"Showy entrance?", "Showy", list("No", "Telesparks", "Drop Pod", "Cancel")) + if(showy == "Cancel") return - if(sparks == "No") - sparks = FALSE + if(showy == "Drop Pod") + showy = tgui_alert(src,"Destructive drop pods cause damage in a 3x3 and may break turfs. Polite drop pods lightly damage the turfs but won't break through.", "Drop Pod", list("Polite", "Destructive", "Cancel")) // reusing var + if(showy == "Cancel") + return if("Arrivals") //Spawn them at a latejoin spawnpoint spawnloc = pick(latejoin) @@ -483,7 +485,7 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character = new(spawnloc) - if(sparks) + if(showy == "Telesparks") anim(spawnloc,new_character,'icons/mob/mob.dmi',,"phasein",,new_character.dir) playsound(spawnloc, "sparks", 50, 1) var/datum/effect/effect/system/spark_spread/spk = new(new_character) @@ -546,9 +548,21 @@ Traitors and the like can also be revived with the previous role mostly intact. log_admin("[admin] has spawned [player_key]'s character [new_character.real_name].") message_admins("[admin] has spawned [player_key]'s character [new_character.real_name].", 1) - to_chat(new_character, "You have been fully spawned. Enjoy the game.") + feedback_add_details("admin_verb","RSPCH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + + // Drop pods + if(showy == "Polite") + var/turf/T = get_turf(new_character) + new /obj/structure/drop_pod/polite(T, new_character) + to_chat(new_character, "Please wait for your arrival.") + else if(showy == "Destructive") + var/turf/T = get_turf(new_character) + new /obj/structure/drop_pod(T, new_character) + to_chat(new_character, "Please wait for your arrival.") + else + to_chat(new_character, "You have been fully spawned. Enjoy the game.") return new_character @@ -1057,3 +1071,73 @@ Traitors and the like can also be revived with the previous role mostly intact. else if(isliving(M)) M.ghostize() qdel(M) //Bye + +/client/proc/cmd_admin_droppod_spawn(var/object as text) + set name = "Drop Pod Spawn" + set desc = "Spawn a new atom/movable in a drop pod where you are." + set category = "Fun" + + if(!check_rights(R_SPAWN)) + return + + var/list/types = typesof(/atom/movable) + var/list/matches = new() + + for(var/path in types) + if(findtext("[path]", object)) + matches += path + + if(!matches.len) + return + + var/chosen + if(matches.len==1) + chosen = matches[1] + else + chosen = tgui_input_list(usr, "Select an atom type", "Spawn Atom", matches) + if(!chosen) + return + + var/podtype = tgui_alert(src,"Destructive drop pods cause damage in a 3x3 and may break turfs. Polite drop pods lightly damage the turfs but won't break through.", "Drop Pod", list("Polite", "Destructive", "Cancel")) + if(podtype == "Cancel") + return + var/autoopen = tgui_alert(src,"Should the pod open automatically?", "Drop Pod", list("Yes", "No", "Cancel")) + if(autoopen == "Cancel") + return + switch(podtype) + if("Destructive") + var/atom/movable/AM = new chosen(usr.loc) + new /obj/structure/drop_pod(get_turf(usr), AM, autoopen == "Yes" ? TRUE : FALSE) + if("Polite") + var/atom/movable/AM = new chosen(usr.loc) + new /obj/structure/drop_pod/polite(get_turf(usr), AM, autoopen == "Yes" ? TRUE : FALSE) + + feedback_add_details("admin_verb","DPS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/cmd_admin_droppod_deploy() + set name = "Drop Pod Deploy" + set desc = "Drop an existing mob where you are in a drop pod." + set category = "Fun" + + if(!check_rights(R_SPAWN)) + return + + var/mob/living/L = tgui_input_list(usr, "Select the mob to drop:", "Drop!", living_mob_list) + if(!L) + return + + var/podtype = tgui_alert(src,"Destructive drop pods cause damage in a 3x3 and may break turfs. Polite drop pods lightly damage the turfs but won't break through.", "Drop Pod", list("Polite", "Destructive", "Cancel")) + if(podtype == "Cancel") + return + var/autoopen = tgui_alert(src,"Should the pod open automatically?", "Drop Pod", list("Yes", "No", "Cancel")) + if(autoopen == "Cancel") + return + if(!L || QDELETED(L)) + return + switch(podtype) + if("Destructive") + new /obj/structure/drop_pod(get_turf(usr), L, autoopen == "Yes" ? TRUE : FALSE) + if("Polite") + new /obj/structure/drop_pod/polite(get_turf(usr), L, autoopen == "Yes" ? TRUE : FALSE) + + feedback_add_details("admin_verb","DPD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! \ No newline at end of file diff --git a/icons/obj/structures/droppod.dmi b/icons/obj/structures/droppod.dmi new file mode 100644 index 0000000000..9254c59eeb Binary files /dev/null and b/icons/obj/structures/droppod.dmi differ diff --git a/sound/effects/droppod.ogg b/sound/effects/droppod.ogg new file mode 100644 index 0000000000..161216ff2b Binary files /dev/null and b/sound/effects/droppod.ogg differ diff --git a/vorestation.dme b/vorestation.dme index ea3fdd0832..f1e7b2d321 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1440,6 +1440,7 @@ #include "code\game\objects\structures\displaycase.dm" #include "code\game\objects\structures\dogbed.dm" #include "code\game\objects\structures\door_assembly.dm" +#include "code\game\objects\structures\droppod.dm" #include "code\game\objects\structures\electricchair.dm" #include "code\game\objects\structures\extinguisher.dm" #include "code\game\objects\structures\fence.dm"